From 8af5a32f1d3f3376cb229b85a3d742b51bec0ef3 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 29 May 2020 16:37:46 +0200 Subject: [PATCH 001/101] new store accessor classes implementation of local pool and pool manager extracted into tpp file. store_address_t definition extracted in separate file to avoid circular includes by using forward declarations --- storagemanager/LocalPool.h | 389 ++++++----------------------- storagemanager/LocalPool.tpp | 300 ++++++++++++++++++++++ storagemanager/PoolManager.h | 96 ++----- storagemanager/PoolManager.tpp | 47 ++++ storagemanager/StorageAccessor.cpp | 155 ++++++++++++ storagemanager/StorageAccessor.h | 151 +++++++++++ storagemanager/StorageManagerIF.h | 118 ++++----- storagemanager/storeAddress.h | 54 ++++ 8 files changed, 868 insertions(+), 442 deletions(-) create mode 100644 storagemanager/LocalPool.tpp create mode 100644 storagemanager/PoolManager.tpp create mode 100644 storagemanager/StorageAccessor.cpp create mode 100644 storagemanager/StorageAccessor.h create mode 100644 storagemanager/storeAddress.h diff --git a/storagemanager/LocalPool.h b/storagemanager/LocalPool.h index 5104be2e..c155f918 100644 --- a/storagemanager/LocalPool.h +++ b/storagemanager/LocalPool.h @@ -1,26 +1,18 @@ #ifndef FRAMEWORK_STORAGEMANAGER_LOCALPOOL_H_ #define FRAMEWORK_STORAGEMANAGER_LOCALPOOL_H_ -/** - * @file LocalPool - * - * @date 02.02.2012 - * @author Bastian Baetz - * - * @brief This file contains the definition of the LocalPool class. - */ - #include #include #include #include #include -#include +#include +#include /** * @brief The LocalPool class provides an intermediate data storage with * a fixed pool size policy. - * \details The class implements the StorageManagerIF interface. While the + * @details The class implements the StorageManagerIF interface. While the * total number of pools is fixed, the element sizes in one pool and * the number of pool elements per pool are set on construction. * The full amount of memory is allocated on construction. @@ -39,7 +31,71 @@ public: * @brief This definition generally sets the number of different sized pools. * @details This must be less than the maximum number of pools (currently 0xff). */ -// static const uint32_t NUMBER_OF_POOLS; + // static const uint32_t NUMBER_OF_POOLS; + /** + * @brief This is the default constructor for a pool manager instance. + * @details By passing two arrays of size NUMBER_OF_POOLS, the constructor + * allocates memory (with \c new) for store and size_list. These + * regions are all set to zero on start up. + * @param setObjectId The object identifier to be set. This allows for + * multiple instances of LocalPool in the system. + * @param element_sizes An array of size NUMBER_OF_POOLS in which the size + * of a single element in each pool is determined. + * The sizes must be provided in ascending order. + * + * @param n_elements An array of size NUMBER_OF_POOLS in which the + * number of elements for each pool is determined. + * The position of these values correspond to those in + * element_sizes. + * @param registered Register the pool in object manager or not. Default is false (local pool). + * @param spillsToHigherPools + * A variable to determine whether higher n pools are used if the store is full. + */ + LocalPool(object_id_t setObjectId, + const uint16_t element_sizes[NUMBER_OF_POOLS], + const uint16_t n_elements[NUMBER_OF_POOLS], + bool registered = false, + bool spillsToHigherPools = false); + /** + * @brief In the LocalPool's destructor all allocated memory is freed. + */ + virtual ~LocalPool(void); + + /** + * Documentation: See StorageManagerIF.h + */ + ReturnValue_t addData(store_address_t* storageId, const uint8_t * data, + size_t size, bool ignoreFault = false) override; + ReturnValue_t getFreeElement(store_address_t* storageId,const size_t size, + uint8_t** p_data, bool ignoreFault = false) override; + + ConstAccessorPair getData(store_address_t packet_id) override; + ReturnValue_t getData(store_address_t packet_id, ConstStorageAccessor&) override; + ReturnValue_t getData(store_address_t packet_id, const uint8_t** packet_ptr, + size_t * size) override; + + AccessorPair modifyData(store_address_t packet_id) override; + ReturnValue_t modifyData(store_address_t packet_id, StorageAccessor&) override; + ReturnValue_t modifyData(store_address_t packet_id, uint8_t** packet_ptr, + size_t * size) override; + + virtual ReturnValue_t deleteData(store_address_t) override; + virtual ReturnValue_t deleteData(uint8_t* ptr, size_t size, + store_address_t* storeId = NULL) override; + void clearStore() override; + ReturnValue_t initialize() override; +protected: + /** + * With this helper method, a free element of \c size is reserved. + * @param size The minimum packet size that shall be reserved. + * @param[out] address Storage ID of the reserved data. + * @return - #RETURN_OK on success, + * - the return codes of #getPoolIndex or #findEmpty otherwise. + */ + virtual ReturnValue_t reserveSpace(const uint32_t size, + store_address_t* address, bool ignoreFault); + + InternalErrorReporterIF *internalErrorReporter; private: /** * Indicates that this element is free. @@ -78,7 +134,7 @@ private: * @param data The data to be stored. * @param size The size of the data to be stored. */ - void write(store_address_t packet_id, const uint8_t* data, uint32_t size); + void write(store_address_t packet_id, const uint8_t* data, size_t size); /** * @brief A helper method to read the element size of a certain pool. * @param pool_index The pool in which to look. @@ -101,7 +157,8 @@ private: * @return - #RETURN_OK on success, * - #DATA_TOO_LARGE otherwise. */ - ReturnValue_t getPoolIndex(uint32_t packet_size, uint16_t* poolIndex, uint16_t startAtIndex = 0); + ReturnValue_t getPoolIndex(size_t packet_size, uint16_t* poolIndex, + uint16_t startAtIndex = 0); /** * @brief This helper method calculates the true array position in store * of a given packet id. @@ -121,310 +178,8 @@ private: * - #DATA_STORAGE_FULL if the store is full */ ReturnValue_t findEmpty(uint16_t pool_index, uint16_t* element); -protected: - /** - * With this helper method, a free element of \c size is reserved. - * @param size The minimum packet size that shall be reserved. - * @param[out] address Storage ID of the reserved data. - * @return - #RETURN_OK on success, - * - the return codes of #getPoolIndex or #findEmpty otherwise. - */ - virtual ReturnValue_t reserveSpace(const uint32_t size, store_address_t* address, bool ignoreFault); - - InternalErrorReporterIF *internalErrorReporter; -public: - /** - * @brief This is the default constructor for a pool manager instance. - * @details By passing two arrays of size NUMBER_OF_POOLS, the constructor - * allocates memory (with \c new) for store and size_list. These - * regions are all set to zero on start up. - * @param setObjectId The object identifier to be set. This allows for - * multiple instances of LocalPool in the system. - * @param element_sizes An array of size NUMBER_OF_POOLS in which the size - * of a single element in each pool is determined. - * The sizes must be provided in ascending order. - * - * @param n_elements An array of size NUMBER_OF_POOLS in which the - * number of elements for each pool is determined. - * The position of these values correspond to those in - * element_sizes. - * @param registered Register the pool in object manager or not. Default is false (local pool). - */ - LocalPool(object_id_t setObjectId, - const uint16_t element_sizes[NUMBER_OF_POOLS], - const uint16_t n_elements[NUMBER_OF_POOLS], - bool registered = false, - bool spillsToHigherPools = false); - /** - * @brief In the LocalPool's destructor all allocated memory is freed. - */ - virtual ~LocalPool(void); - ReturnValue_t addData(store_address_t* storageId, const uint8_t * data, - uint32_t size, bool ignoreFault = false); - - /** - * With this helper method, a free element of \c size is reserved. - * - * @param size The minimum packet size that shall be reserved. - * @return Returns the storage identifier within the storage or - * StorageManagerIF::INVALID_ADDRESS (in raw). - */ - ReturnValue_t getFreeElement(store_address_t* storageId, - const uint32_t size, uint8_t** p_data, bool ignoreFault = false); - ReturnValue_t getData(store_address_t packet_id, const uint8_t** packet_ptr, - uint32_t* size); - ReturnValue_t modifyData(store_address_t packet_id, uint8_t** packet_ptr, - uint32_t* size); - virtual ReturnValue_t deleteData(store_address_t); - virtual ReturnValue_t deleteData(uint8_t* ptr, uint32_t size, - store_address_t* storeId = NULL); - void clearStore(); - ReturnValue_t initialize(); }; -template -inline ReturnValue_t LocalPool::findEmpty(uint16_t pool_index, - uint16_t* element) { - ReturnValue_t status = DATA_STORAGE_FULL; - for (uint16_t foundElement = 0; foundElement < n_elements[pool_index]; - foundElement++) { - if (size_list[pool_index][foundElement] == STORAGE_FREE) { - *element = foundElement; - status = RETURN_OK; - break; - } - } - return status; -} - -template -inline void LocalPool::write(store_address_t packet_id, - const uint8_t* data, uint32_t size) { - uint8_t* ptr; - uint32_t packet_position = getRawPosition(packet_id); - - //check size? -> Not necessary, because size is checked before calling this function. - ptr = &store[packet_id.pool_index][packet_position]; - memcpy(ptr, data, size); - size_list[packet_id.pool_index][packet_id.packet_index] = size; -} - -//Returns page size of 0 in case store_index is illegal -template -inline uint32_t LocalPool::getPageSize(uint16_t pool_index) { - if (pool_index < NUMBER_OF_POOLS) { - return element_sizes[pool_index]; - } else { - return 0; - } -} - -template -inline ReturnValue_t LocalPool::getPoolIndex( - uint32_t packet_size, uint16_t* poolIndex, uint16_t startAtIndex) { - for (uint16_t n = startAtIndex; n < NUMBER_OF_POOLS; n++) { -// debug << "LocalPool " << getObjectId() << "::getPoolIndex: Pool: " << n << ", Element Size: " << element_sizes[n] << std::endl; - if (element_sizes[n] >= packet_size) { - *poolIndex = n; - return RETURN_OK; - } - } - return DATA_TOO_LARGE; -} - -template -inline uint32_t LocalPool::getRawPosition( - store_address_t packet_id) { - return packet_id.packet_index * element_sizes[packet_id.pool_index]; -} - -template -inline ReturnValue_t LocalPool::reserveSpace( - const uint32_t size, store_address_t* address, bool ignoreFault) { - ReturnValue_t status = getPoolIndex(size, &address->pool_index); - if (status != RETURN_OK) { - sif::error << "LocalPool( " << std::hex << getObjectId() << std::dec - << " )::reserveSpace: Packet too large." << std::endl; - return status; - } - status = findEmpty(address->pool_index, &address->packet_index); - while (status != RETURN_OK && spillsToHigherPools) { - status = getPoolIndex(size, &address->pool_index, address->pool_index + 1); - if (status != RETURN_OK) { - //We don't find any fitting pool anymore. - break; - } - status = findEmpty(address->pool_index, &address->packet_index); - } - if (status == RETURN_OK) { -// if (getObjectId() == objects::IPC_STORE && address->pool_index >= 3) { -// debug << "Reserve: Pool: " << std::dec << address->pool_index << " Index: " << address->packet_index << std::endl; -// } - - size_list[address->pool_index][address->packet_index] = size; - } else { - if (!ignoreFault) { - internalErrorReporter->storeFull(); - } -// error << "LocalPool( " << std::hex << getObjectId() << std::dec -// << " )::reserveSpace: Packet store is full." << std::endl; - } - return status; -} - -template -inline LocalPool::LocalPool(object_id_t setObjectId, - const uint16_t element_sizes[NUMBER_OF_POOLS], - const uint16_t n_elements[NUMBER_OF_POOLS], bool registered, bool spillsToHigherPools) : - SystemObject(setObjectId, registered), spillsToHigherPools(spillsToHigherPools), internalErrorReporter(NULL) { - for (uint16_t n = 0; n < NUMBER_OF_POOLS; n++) { - this->element_sizes[n] = element_sizes[n]; - this->n_elements[n] = n_elements[n]; - store[n] = new uint8_t[n_elements[n] * element_sizes[n]]; - size_list[n] = new uint32_t[n_elements[n]]; - memset(store[n], 0x00, (n_elements[n] * element_sizes[n])); - memset(size_list[n], STORAGE_FREE, (n_elements[n] * sizeof(**size_list))); //TODO checkme - } -} - -template -inline LocalPool::~LocalPool(void) { - for (uint16_t n = 0; n < NUMBER_OF_POOLS; n++) { - delete[] store[n]; - delete[] size_list[n]; - } -} - -template -inline ReturnValue_t LocalPool::addData( - store_address_t* storageId, const uint8_t* data, uint32_t size, bool ignoreFault) { - ReturnValue_t status = reserveSpace(size, storageId, ignoreFault); - if (status == RETURN_OK) { - write(*storageId, data, size); - } - return status; -} - -template -inline ReturnValue_t LocalPool::getFreeElement( - store_address_t* storageId, const uint32_t size, uint8_t** p_data, bool ignoreFault) { - ReturnValue_t status = reserveSpace(size, storageId, ignoreFault); - if (status == RETURN_OK) { - *p_data = &store[storageId->pool_index][getRawPosition(*storageId)]; - } else { - *p_data = NULL; - } - return status; -} - -template -inline ReturnValue_t LocalPool::getData( - store_address_t packet_id, const uint8_t** packet_ptr, uint32_t* size) { - uint8_t* tempData = NULL; - ReturnValue_t status = modifyData(packet_id, &tempData, size); - *packet_ptr = tempData; - return status; -} - -template -inline ReturnValue_t LocalPool::modifyData(store_address_t packet_id, - uint8_t** packet_ptr, uint32_t* size) { - ReturnValue_t status = RETURN_FAILED; - if (packet_id.pool_index >= NUMBER_OF_POOLS) { - return ILLEGAL_STORAGE_ID; - } - if ((packet_id.packet_index >= n_elements[packet_id.pool_index])) { - return ILLEGAL_STORAGE_ID; - } - if (size_list[packet_id.pool_index][packet_id.packet_index] - != STORAGE_FREE) { - uint32_t packet_position = getRawPosition(packet_id); - *packet_ptr = &store[packet_id.pool_index][packet_position]; - *size = size_list[packet_id.pool_index][packet_id.packet_index]; - status = RETURN_OK; - } else { - status = DATA_DOES_NOT_EXIST; - } - return status; -} - -template -inline ReturnValue_t LocalPool::deleteData( - store_address_t packet_id) { - -// if (getObjectId() == objects::IPC_STORE && packet_id.pool_index >= 3) { -// debug << "Delete: Pool: " << std::dec << packet_id.pool_index << " Index: " << packet_id.packet_index << std::endl; -// } - ReturnValue_t status = RETURN_OK; - uint32_t page_size = getPageSize(packet_id.pool_index); - if ((page_size != 0) - && (packet_id.packet_index < n_elements[packet_id.pool_index])) { - uint16_t packet_position = getRawPosition(packet_id); - uint8_t* ptr = &store[packet_id.pool_index][packet_position]; - memset(ptr, 0, page_size); - //Set free list - size_list[packet_id.pool_index][packet_id.packet_index] = STORAGE_FREE; - } else { - //pool_index or packet_index is too large - sif::error << "LocalPool:deleteData failed." << std::endl; - status = ILLEGAL_STORAGE_ID; - } - return status; -} - -template -inline void LocalPool::clearStore() { - for (uint16_t n = 0; n < NUMBER_OF_POOLS; n++) { - memset(size_list[n], STORAGE_FREE, (n_elements[n] * sizeof(**size_list)));//TODO checkme - } -} - -template -inline ReturnValue_t LocalPool::deleteData(uint8_t* ptr, - uint32_t size, store_address_t* storeId) { - store_address_t localId; - ReturnValue_t result = ILLEGAL_ADDRESS; - for (uint16_t n = 0; n < NUMBER_OF_POOLS; n++) { - //Not sure if new allocates all stores in order. so better be careful. - if ((store[n] <= ptr) && (&store[n][n_elements[n]*element_sizes[n]]) > ptr) { - localId.pool_index = n; - uint32_t deltaAddress = ptr - store[n]; - //Getting any data from the right "block" is ok. This is necessary, as IF's sometimes don't point to the first element of an object. - localId.packet_index = deltaAddress / element_sizes[n]; - result = deleteData(localId); -// if (deltaAddress % element_sizes[n] != 0) { -// error << "Pool::deleteData: address not aligned!" << std::endl; -// } - break; - } - } - if (storeId != NULL) { - *storeId = localId; - } - return result; -} - -template -inline ReturnValue_t LocalPool::initialize() { - ReturnValue_t result = SystemObject::initialize(); - if (result != RETURN_OK) { - return result; - } - internalErrorReporter = objectManager->get(objects::INTERNAL_ERROR_REPORTER); - if (internalErrorReporter == NULL){ - return RETURN_FAILED; - } - - //Check if any pool size is large than the maximum allowed. - for (uint8_t count = 0; count < NUMBER_OF_POOLS; count++) { - if (element_sizes[count] >= STORAGE_FREE) { - sif::error - << "LocalPool::initialize: Pool is too large! Max. allowed size is: " - << (STORAGE_FREE - 1) << std::endl; - return RETURN_FAILED; - } - } - return RETURN_OK; -} +#include #endif /* FRAMEWORK_STORAGEMANAGER_LOCALPOOL_H_ */ diff --git a/storagemanager/LocalPool.tpp b/storagemanager/LocalPool.tpp new file mode 100644 index 00000000..32724bd8 --- /dev/null +++ b/storagemanager/LocalPool.tpp @@ -0,0 +1,300 @@ +#ifndef FRAMEWORK_STORAGEMANAGER_LOCALPOOL_TPP_ +#define FRAMEWORK_STORAGEMANAGER_LOCALPOOL_TPP_ + +template +inline LocalPool::LocalPool(object_id_t setObjectId, + const uint16_t element_sizes[NUMBER_OF_POOLS], + const uint16_t n_elements[NUMBER_OF_POOLS], bool registered, + bool spillsToHigherPools) : + SystemObject(setObjectId, registered), internalErrorReporter(nullptr), + spillsToHigherPools(spillsToHigherPools) +{ + for (uint16_t n = 0; n < NUMBER_OF_POOLS; n++) { + this->element_sizes[n] = element_sizes[n]; + this->n_elements[n] = n_elements[n]; + store[n] = new uint8_t[n_elements[n] * element_sizes[n]]; + size_list[n] = new uint32_t[n_elements[n]]; + memset(store[n], 0x00, (n_elements[n] * element_sizes[n])); + //TODO checkme + memset(size_list[n], STORAGE_FREE, (n_elements[n] * sizeof(**size_list))); + } +} + + +template +inline ReturnValue_t LocalPool::findEmpty(uint16_t pool_index, + uint16_t* element) { + ReturnValue_t status = DATA_STORAGE_FULL; + for (uint16_t foundElement = 0; foundElement < n_elements[pool_index]; + foundElement++) { + if (size_list[pool_index][foundElement] == STORAGE_FREE) { + *element = foundElement; + status = RETURN_OK; + break; + } + } + return status; +} + +template +inline void LocalPool::write(store_address_t packet_id, + const uint8_t* data, size_t size) { + uint8_t* ptr; + uint32_t packet_position = getRawPosition(packet_id); + + //check size? -> Not necessary, because size is checked before calling this function. + ptr = &store[packet_id.pool_index][packet_position]; + memcpy(ptr, data, size); + size_list[packet_id.pool_index][packet_id.packet_index] = size; +} + +//Returns page size of 0 in case store_index is illegal +template +inline uint32_t LocalPool::getPageSize(uint16_t pool_index) { + if (pool_index < NUMBER_OF_POOLS) { + return element_sizes[pool_index]; + } else { + return 0; + } +} + +template +inline ReturnValue_t LocalPool::getPoolIndex( + size_t packet_size, uint16_t* poolIndex, uint16_t startAtIndex) { + for (uint16_t n = startAtIndex; n < NUMBER_OF_POOLS; n++) { + //debug << "LocalPool " << getObjectId() << "::getPoolIndex: Pool: " << + // n << ", Element Size: " << element_sizes[n] << std::endl; + if (element_sizes[n] >= packet_size) { + *poolIndex = n; + return RETURN_OK; + } + } + return DATA_TOO_LARGE; +} + +template +inline uint32_t LocalPool::getRawPosition( + store_address_t packet_id) { + return packet_id.packet_index * element_sizes[packet_id.pool_index]; +} + +template +inline ReturnValue_t LocalPool::reserveSpace( + const uint32_t size, store_address_t* address, bool ignoreFault) { + ReturnValue_t status = getPoolIndex(size, &address->pool_index); + if (status != RETURN_OK) { + sif::error << "LocalPool( " << std::hex << getObjectId() << std::dec + << " )::reserveSpace: Packet too large." << std::endl; + return status; + } + status = findEmpty(address->pool_index, &address->packet_index); + while (status != RETURN_OK && spillsToHigherPools) { + status = getPoolIndex(size, &address->pool_index, address->pool_index + 1); + if (status != RETURN_OK) { + //We don't find any fitting pool anymore. + break; + } + status = findEmpty(address->pool_index, &address->packet_index); + } + if (status == RETURN_OK) { + // if (getObjectId() == objects::IPC_STORE && address->pool_index >= 3) { + // debug << "Reserve: Pool: " << std::dec << address->pool_index << + // " Index: " << address->packet_index << std::endl; + // } + + size_list[address->pool_index][address->packet_index] = size; + } else { + if (!ignoreFault and internalErrorReporter != nullptr) { + internalErrorReporter->storeFull(); + } + // error << "LocalPool( " << std::hex << getObjectId() << std::dec + // << " )::reserveSpace: Packet store is full." << std::endl; + } + return status; +} + +template +inline LocalPool::~LocalPool(void) { + for (uint16_t n = 0; n < NUMBER_OF_POOLS; n++) { + delete[] store[n]; + delete[] size_list[n]; + } +} + +template inline +ReturnValue_t LocalPool::addData(store_address_t* storageId, + const uint8_t* data, size_t size, bool ignoreFault) { + ReturnValue_t status = reserveSpace(size, storageId, ignoreFault); + if (status == RETURN_OK) { + write(*storageId, data, size); + } + return status; +} + +template +inline ReturnValue_t LocalPool::getFreeElement( + store_address_t* storageId, const size_t size, + uint8_t** p_data, bool ignoreFault) { + ReturnValue_t status = reserveSpace(size, storageId, ignoreFault); + if (status == RETURN_OK) { + *p_data = &store[storageId->pool_index][getRawPosition(*storageId)]; + } else { + *p_data = NULL; + } + return status; +} + +template +inline ConstAccessorPair LocalPool::getData( + store_address_t storeId) { + uint8_t* tempData = nullptr; + ConstStorageAccessor constAccessor(storeId, this); + ReturnValue_t status = modifyData(storeId, &tempData, &constAccessor.size_); + constAccessor.constDataPointer = tempData; + return ConstAccessorPair(status, std::move(constAccessor)); +} + +template +inline ReturnValue_t LocalPool::getData(store_address_t storeId, + ConstStorageAccessor& storeAccessor) { + uint8_t* tempData = nullptr; + ReturnValue_t status = modifyData(storeId, &tempData, &storeAccessor.size_); + storeAccessor.assignStore(this); + storeAccessor.constDataPointer = tempData; + return status; +} + +template +inline ReturnValue_t LocalPool::getData( + store_address_t packet_id, const uint8_t** packet_ptr, size_t* size) { + uint8_t* tempData = NULL; + ReturnValue_t status = modifyData(packet_id, &tempData, size); + *packet_ptr = tempData; + return status; +} + +template +inline AccessorPair LocalPool::modifyData( + store_address_t storeId) { + StorageAccessor accessor(storeId, this); + ReturnValue_t status = modifyData(storeId, &accessor.dataPointer, + &accessor.size_); + accessor.assignConstPointer(); + return AccessorPair(status, std::move(accessor)); +} + +template +inline ReturnValue_t LocalPool::modifyData( + store_address_t storeId, StorageAccessor& storeAccessor) { + storeAccessor.assignStore(this); + ReturnValue_t status = modifyData(storeId, &storeAccessor.dataPointer, + &storeAccessor.size_); + storeAccessor.assignConstPointer(); + return status; +} + +template +inline ReturnValue_t LocalPool::modifyData( + store_address_t packet_id, uint8_t** packet_ptr, size_t* size) { + ReturnValue_t status = RETURN_FAILED; + if (packet_id.pool_index >= NUMBER_OF_POOLS) { + return ILLEGAL_STORAGE_ID; + } + if ((packet_id.packet_index >= n_elements[packet_id.pool_index])) { + return ILLEGAL_STORAGE_ID; + } + if (size_list[packet_id.pool_index][packet_id.packet_index] + != STORAGE_FREE) { + uint32_t packet_position = getRawPosition(packet_id); + *packet_ptr = &store[packet_id.pool_index][packet_position]; + *size = size_list[packet_id.pool_index][packet_id.packet_index]; + status = RETURN_OK; + } else { + status = DATA_DOES_NOT_EXIST; + } + return status; +} + +template +inline ReturnValue_t LocalPool::deleteData( + store_address_t packet_id) { + //if (getObjectId() == objects::IPC_STORE && packet_id.pool_index >= 3) { + // debug << "Delete: Pool: " << std::dec << packet_id.pool_index << " Index: " + // << packet_id.packet_index << std::endl; + //} + ReturnValue_t status = RETURN_OK; + uint32_t page_size = getPageSize(packet_id.pool_index); + if ((page_size != 0) + && (packet_id.packet_index < n_elements[packet_id.pool_index])) { + uint16_t packet_position = getRawPosition(packet_id); + uint8_t* ptr = &store[packet_id.pool_index][packet_position]; + memset(ptr, 0, page_size); + //Set free list + size_list[packet_id.pool_index][packet_id.packet_index] = STORAGE_FREE; + } else { + //pool_index or packet_index is too large + sif::error << "LocalPool:deleteData failed." << std::endl; + status = ILLEGAL_STORAGE_ID; + } + return status; +} + +template +inline void LocalPool::clearStore() { + for (uint16_t n = 0; n < NUMBER_OF_POOLS; n++) { + //TODO checkme + memset(size_list[n], STORAGE_FREE, (n_elements[n] * sizeof(**size_list))); + } +} + +template +inline ReturnValue_t LocalPool::deleteData(uint8_t* ptr, + size_t size, store_address_t* storeId) { + store_address_t localId; + ReturnValue_t result = ILLEGAL_ADDRESS; + for (uint16_t n = 0; n < NUMBER_OF_POOLS; n++) { + //Not sure if new allocates all stores in order. so better be careful. + if ((store[n] <= ptr) && (&store[n][n_elements[n]*element_sizes[n]]) > ptr) { + localId.pool_index = n; + uint32_t deltaAddress = ptr - store[n]; + // Getting any data from the right "block" is ok. + // This is necessary, as IF's sometimes don't point to the first + // element of an object. + localId.packet_index = deltaAddress / element_sizes[n]; + result = deleteData(localId); + //if (deltaAddress % element_sizes[n] != 0) { + // error << "Pool::deleteData: address not aligned!" << std::endl; + //} + break; + } + } + if (storeId != NULL) { + *storeId = localId; + } + return result; +} + +template +inline ReturnValue_t LocalPool::initialize() { + ReturnValue_t result = SystemObject::initialize(); + if (result != RETURN_OK) { + return result; + } + internalErrorReporter = objectManager->get( + objects::INTERNAL_ERROR_REPORTER); + if (internalErrorReporter == nullptr){ + return ObjectManagerIF::INTERNAL_ERR_REPORTER_UNINIT; + } + + //Check if any pool size is large than the maximum allowed. + for (uint8_t count = 0; count < NUMBER_OF_POOLS; count++) { + if (element_sizes[count] >= STORAGE_FREE) { + sif::error << "LocalPool::initialize: Pool is too large! " + "Max. allowed size is: " << (STORAGE_FREE - 1) << std::endl; + return StorageManagerIF::POOL_TOO_LARGE; + } + } + return RETURN_OK; +} + +#endif diff --git a/storagemanager/PoolManager.h b/storagemanager/PoolManager.h index 68a7addc..6e353de2 100644 --- a/storagemanager/PoolManager.h +++ b/storagemanager/PoolManager.h @@ -1,86 +1,44 @@ -/** - * @file PoolManager - * - * @date 02.02.2012 - * @author Bastian Baetz - * - * @brief This file contains the definition of the PoolManager class. - */ - -#ifndef POOLMANAGER_H_ -#define POOLMANAGER_H_ - +#ifndef FRAMEWORK_STORAGEMANAGER_POOLMANAGER_H_ +#define FRAMEWORK_STORAGEMANAGER_POOLMANAGER_H_ #include #include +#include /** * @brief The PoolManager class provides an intermediate data storage with * a fixed pool size policy for inter-process communication. - * \details Uses local pool, but is thread-safe. + * @details Uses local pool calls but is thread safe by protecting the call + * with a lock. */ - -template +template class PoolManager : public LocalPool { +public: + PoolManager(object_id_t setObjectId, + const uint16_t element_sizes[NUMBER_OF_POOLS], + const uint16_t n_elements[NUMBER_OF_POOLS]); + + //! @brief In the PoolManager's destructor all allocated memory is freed. + virtual ~PoolManager(); + + //! @brief LocalPool overrides for thread-safety. Decorator function which + //! wraps LocalPool calls with a mutex protection. + ReturnValue_t deleteData(store_address_t) override; + ReturnValue_t deleteData(uint8_t* buffer, size_t size, + store_address_t* storeId = nullptr) override; protected: - /** - * Overwritten for thread safety. - * Locks during execution. - */ - virtual ReturnValue_t reserveSpace(const uint32_t size, store_address_t* address, bool ignoreFault); + ReturnValue_t reserveSpace(const uint32_t size, store_address_t* address, + bool ignoreFault) override; /** - * \brief The mutex is created in the constructor and makes access mutual exclusive. - * \details Locking and unlocking is done during searching for free slots and deleting existing slots. + * @brief The mutex is created in the constructor and makes + * access mutual exclusive. + * @details Locking and unlocking is done during searching for free slots + * and deleting existing slots. */ - MutexIF* mutex; -public: - PoolManager( object_id_t setObjectId, const uint16_t element_sizes[NUMBER_OF_POOLS], const uint16_t n_elements[NUMBER_OF_POOLS] ); - /** - * @brief In the PoolManager's destructor all allocated memory is freed. - */ - virtual ~PoolManager( void ); - /** - * Overwritten for thread safety. - */ - virtual ReturnValue_t deleteData(store_address_t); - virtual ReturnValue_t deleteData(uint8_t* buffer, uint32_t size, store_address_t* storeId = NULL); + MutexIF* mutex; }; -template -inline ReturnValue_t PoolManager::reserveSpace(const uint32_t size, store_address_t* address, bool ignoreFault) { - MutexHelper mutexHelper(mutex,MutexIF::NO_TIMEOUT); - ReturnValue_t status = LocalPool::reserveSpace(size,address,ignoreFault); - return status; -} - -template -inline PoolManager::PoolManager(object_id_t setObjectId, - const uint16_t element_sizes[NUMBER_OF_POOLS], - const uint16_t n_elements[NUMBER_OF_POOLS]) : LocalPool(setObjectId, element_sizes, n_elements, true) { - mutex = MutexFactory::instance()->createMutex(); -} - -template -inline PoolManager::~PoolManager(void) { - MutexFactory::instance()->deleteMutex(mutex); -} - -template -inline ReturnValue_t PoolManager::deleteData( - store_address_t packet_id) { - // debug << "PoolManager( " << translateObject(getObjectId()) << " )::deleteData from store " << packet_id.pool_index << ". id is " << packet_id.packet_index << std::endl; - MutexHelper mutexHelper(mutex,MutexIF::NO_TIMEOUT); - ReturnValue_t status = LocalPool::deleteData(packet_id); - return status; -} - -template -inline ReturnValue_t PoolManager::deleteData(uint8_t* buffer, uint32_t size, - store_address_t* storeId) { - MutexHelper mutexHelper(mutex,MutexIF::NO_TIMEOUT); - ReturnValue_t status = LocalPool::deleteData(buffer, size, storeId); - return status; -} +#include "PoolManager.tpp" #endif /* POOLMANAGER_H_ */ diff --git a/storagemanager/PoolManager.tpp b/storagemanager/PoolManager.tpp new file mode 100644 index 00000000..854e22da --- /dev/null +++ b/storagemanager/PoolManager.tpp @@ -0,0 +1,47 @@ +#ifndef FRAMEWORK_STORAGEMANAGER_POOLMANAGER_TPP_ +#define FRAMEWORK_STORAGEMANAGER_POOLMANAGER_TPP_ + +template +inline PoolManager::PoolManager(object_id_t setObjectId, + const uint16_t element_sizes[NUMBER_OF_POOLS], + const uint16_t n_elements[NUMBER_OF_POOLS]) : + LocalPool(setObjectId, element_sizes, n_elements, true) { + mutex = MutexFactory::instance()->createMutex(); +} + +template +inline PoolManager::~PoolManager(void) { + MutexFactory::instance()->deleteMutex(mutex); +} + +template +inline ReturnValue_t PoolManager::reserveSpace( + const uint32_t size, store_address_t* address, bool ignoreFault) { + MutexHelper mutexHelper(mutex,MutexIF::NO_TIMEOUT); + ReturnValue_t status = LocalPool::reserveSpace(size, + address,ignoreFault); + return status; +} + +template +inline ReturnValue_t PoolManager::deleteData( + store_address_t packet_id) { + // debug << "PoolManager( " << translateObject(getObjectId()) << + // " )::deleteData from store " << packet_id.pool_index << + // ". id is "<< packet_id.packet_index << std::endl; + MutexHelper mutexHelper(mutex,MutexIF::NO_TIMEOUT); + ReturnValue_t status = LocalPool::deleteData(packet_id); + return status; +} + +template +inline ReturnValue_t PoolManager::deleteData(uint8_t* buffer, + size_t size, store_address_t* storeId) { + MutexHelper mutexHelper(mutex,MutexIF::NO_TIMEOUT); + ReturnValue_t status = LocalPool::deleteData(buffer, + size, storeId); + return status; +} + +#endif + diff --git a/storagemanager/StorageAccessor.cpp b/storagemanager/StorageAccessor.cpp new file mode 100644 index 00000000..c0c8126b --- /dev/null +++ b/storagemanager/StorageAccessor.cpp @@ -0,0 +1,155 @@ +#include +#include + +ConstStorageAccessor::ConstStorageAccessor(store_address_t storeId): + storeId(storeId) {} + +ConstStorageAccessor::ConstStorageAccessor(store_address_t storeId, + StorageManagerIF* store): + storeId(storeId), store(store) { + internalState = AccessState::ASSIGNED; +} + +ConstStorageAccessor::~ConstStorageAccessor() { + if(deleteData and store != nullptr) { + sif::debug << "deleting store data" << std::endl; + store->deleteData(storeId); + } +} + +ConstStorageAccessor::ConstStorageAccessor(ConstStorageAccessor&& other): + constDataPointer(other.constDataPointer), storeId(other.storeId), + size_(other.size_), store(other.store), deleteData(other.deleteData), + internalState(other.internalState) { + // This prevent premature deletion + other.store = nullptr; +} + +ConstStorageAccessor& ConstStorageAccessor::operator=( + ConstStorageAccessor&& other) { + constDataPointer = other.constDataPointer; + storeId = other.storeId; + store = other.store; + size_ = other.size_; + deleteData = other.deleteData; + this->store = other.store; + // This prevents premature deletion + other.store = nullptr; + return *this; +} + +const uint8_t* ConstStorageAccessor::data() const { + return constDataPointer; +} + +size_t ConstStorageAccessor::size() const { + if(internalState == AccessState::UNINIT) { + sif::warning << "StorageAccessor: Not initialized!" << std::endl; + } + return size_; +} + +ReturnValue_t ConstStorageAccessor::getDataCopy(uint8_t *pointer, + size_t maxSize) { + if(internalState == AccessState::UNINIT) { + sif::warning << "StorageAccessor: Not initialized!" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + if(size_ > maxSize) { + sif::error << "StorageAccessor: Supplied buffer not large enough" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + std::copy(constDataPointer, constDataPointer + size_, pointer); + return HasReturnvaluesIF::RETURN_OK; +} + +void ConstStorageAccessor::release() { + deleteData = false; +} + +store_address_t ConstStorageAccessor::getId() const { + return storeId; +} + +void ConstStorageAccessor::print() const { + if(internalState == AccessState::UNINIT) { + sif::warning << "StorageAccessor: Not initialized!" << std::endl; + return; + } + sif::info << "StorageAccessor: Printing data: ["; + for(uint16_t iPool = 0; iPool < size_; iPool++) { + sif::info << std::hex << (int)constDataPointer[iPool]; + if(iPool < size_ - 1){ + sif::info << " , "; + } + } + sif::info << " ] " << std::endl; +} + +void ConstStorageAccessor::assignStore(StorageManagerIF* store) { + internalState = AccessState::ASSIGNED; + this->store = store; +} + + +StorageAccessor::StorageAccessor(store_address_t storeId): + ConstStorageAccessor(storeId) { +} + +StorageAccessor::StorageAccessor(store_address_t storeId, + StorageManagerIF* store): + ConstStorageAccessor(storeId, store) { +} + +StorageAccessor& StorageAccessor::operator =( + StorageAccessor&& other) { + // Call the parent move assignment and also assign own member. + dataPointer = other.dataPointer; + StorageAccessor::operator=(std::move(other)); + return * this; +} + +// Call the parent move ctor and also transfer own member. +StorageAccessor::StorageAccessor(StorageAccessor&& other): + ConstStorageAccessor(std::move(other)), dataPointer(other.dataPointer) { +} + +ReturnValue_t StorageAccessor::getDataCopy(uint8_t *pointer, size_t maxSize) { + if(internalState == AccessState::UNINIT) { + sif::warning << "StorageAccessor: Not initialized!" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + if(size_ > maxSize) { + sif::error << "StorageAccessor: Supplied buffer not large enough" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + std::copy(dataPointer, dataPointer + size_, pointer); + return HasReturnvaluesIF::RETURN_OK; +} + +uint8_t* StorageAccessor::data() { + if(internalState == AccessState::UNINIT) { + sif::warning << "StorageAccessor: Not initialized!" << std::endl; + } + return dataPointer; +} + +ReturnValue_t StorageAccessor::write(uint8_t *data, size_t size, + uint16_t offset) { + if(internalState == AccessState::UNINIT) { + sif::warning << "StorageAccessor: Not initialized!" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + if(offset + size > size_) { + sif::error << "StorageAccessor: Data too large for pool entry!" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + std::copy(data, data + size, dataPointer + offset); + return HasReturnvaluesIF::RETURN_OK; +} + +void StorageAccessor::assignConstPointer() { + constDataPointer = dataPointer; +} + + diff --git a/storagemanager/StorageAccessor.h b/storagemanager/StorageAccessor.h new file mode 100644 index 00000000..57c9369c --- /dev/null +++ b/storagemanager/StorageAccessor.h @@ -0,0 +1,151 @@ +#ifndef FRAMEWORK_STORAGEMANAGER_STORAGEACCESSOR_H_ +#define FRAMEWORK_STORAGEMANAGER_STORAGEACCESSOR_H_ + +#include +#include + +class StorageManagerIF; + +/** + * @brief Helper classes to facilitate safe access to storages which is also + * conforming to RAII principles + * @details + * Accessor class which can be returned by pool manager or passed and set by + * pool managers to have safe access to the pool resources. + * + * These helper can be used together with the StorageManager classes to manage + * access to a storage. It can take care of thread-safety while also providing + * mechanisms to automatically clear storage data. + */ +class ConstStorageAccessor { + //! StorageManager classes have exclusive access to private variables. + template + friend class PoolManager; + template + friend class LocalPool; +public: + /** + * @brief Simple constructor which takes the store ID of the storage + * entry to access. + * @param storeId + */ + ConstStorageAccessor(store_address_t storeId); + ConstStorageAccessor(store_address_t storeId, StorageManagerIF* store); + + /** + * @brief The destructor in default configuration takes care of + * deleting the accessed pool entry and unlocking the mutex + */ + virtual ~ConstStorageAccessor(); + + /** + * @brief Returns a pointer to the read-only data + * @return + */ + const uint8_t* data() const; + + /** + * @brief Copies the read-only data to the supplied pointer + * @param pointer + */ + virtual ReturnValue_t getDataCopy(uint8_t *pointer, size_t maxSize); + + /** + * @brief Calling this will prevent the Accessor from deleting the data + * when the destructor is called. + */ + void release(); + + /** + * Get the size of the data + * @return + */ + size_t size() const; + + /** + * Get the storage ID. + * @return + */ + store_address_t getId() const; + + void print() const; + + /** + * @brief Move ctor and move assignment allow returning accessors as + * a returnvalue. They prevent resource being free prematurely. + * Refer to: https://github.com/MicrosoftDocs/cpp-docs/blob/master/docs/cpp/ + * move-constructors-and-move-assignment-operators-cpp.md + * @param + * @return + */ + ConstStorageAccessor& operator= (ConstStorageAccessor&&); + ConstStorageAccessor (ConstStorageAccessor&&); + + //! The copy ctor and copy assignemnt should be deleted implicitely + //! according to https://foonathan.net/2019/02/special-member-functions/ + //! but I still deleted them to make it more explicit. (remember rule of 5). + ConstStorageAccessor& operator= (ConstStorageAccessor&) = delete; + ConstStorageAccessor (ConstStorageAccessor&) = delete; +protected: + const uint8_t* constDataPointer = nullptr; + store_address_t storeId; + size_t size_ = 0; + //! Managing pool, has to assign itself. + StorageManagerIF* store = nullptr; + bool deleteData = true; + + enum class AccessState { + UNINIT, + ASSIGNED + }; + //! Internal state for safety reasons. + AccessState internalState = AccessState::UNINIT; + /** + * Used by the pool manager instances to assign themselves to the + * accessor. This is necessary to delete the data when the acessor + * exits the scope ! The internal state will be considered read + * when this function is called, so take care all data is set properly as + * well. + * @param + */ + void assignStore(StorageManagerIF*); +}; + + +/** + * @brief Child class for modifyable data. Also has a normal pointer member. + */ +class StorageAccessor: public ConstStorageAccessor { + //! StorageManager classes have exclusive access to private variables. + template + friend class PoolManager; + template + friend class LocalPool; +public: + StorageAccessor(store_address_t storeId); + StorageAccessor(store_address_t storeId, StorageManagerIF* store); + /** + * @brief Move ctor and move assignment allow returning accessors as + * a returnvalue. They prevent resource being free prematurely. + * Refer to: https://github.com/MicrosoftDocs/cpp-docs/blob/master/docs/cpp/ + * move-constructors-and-move-assignment-operators-cpp.md + * @param + * @return + */ + StorageAccessor& operator= (StorageAccessor&&); + StorageAccessor (StorageAccessor&&); + + ReturnValue_t write(uint8_t *data, size_t size, + uint16_t offset = 0); + uint8_t* data(); + ReturnValue_t getDataCopy(uint8_t *pointer, size_t maxSize) override; + +private: + //! Non-const pointer for modifyable data. + uint8_t* dataPointer = nullptr; + //! For modifyable data, the const pointer is assigned to the normal + //! pointer by the pool manager so both access functions can be used safely + void assignConstPointer(); +}; + +#endif /* TEST_PROTOTYPES_STORAGEACCESSOR_H_ */ diff --git a/storagemanager/StorageManagerIF.h b/storagemanager/StorageManagerIF.h index a0c2b23d..d5ac5818 100644 --- a/storagemanager/StorageManagerIF.h +++ b/storagemanager/StorageManagerIF.h @@ -3,56 +3,14 @@ #include #include -#include +#include +#include +#include +#include -/** - * This union defines the type that identifies where a data packet is stored in the store. - * It comprises of a raw part to read it as raw value and a structured part to use it in - * pool-like stores. - */ -union store_address_t { - /** - * Default Constructor, initializing to INVALID_ADDRESS - */ - store_address_t():raw(0xFFFFFFFF){} - /** - * Constructor to create an address object using the raw address - * - * @param rawAddress - */ - store_address_t(uint32_t rawAddress):raw(rawAddress){} +using AccessorPair = std::pair; +using ConstAccessorPair = std::pair; - /** - * Constructor to create an address object using pool - * and packet indices - * - * @param poolIndex - * @param packetIndex - */ - store_address_t(uint16_t poolIndex, uint16_t packetIndex): - pool_index(poolIndex),packet_index(packetIndex){} - /** - * A structure with two elements to access the store address pool-like. - */ - struct { - /** - * The index in which pool the packet lies. - */ - uint16_t pool_index; - /** - * The position in the chosen pool. - */ - uint16_t packet_index; - }; - /** - * Alternative access to the raw value. - */ - uint32_t raw; - - bool operator==(const store_address_t& other) const { - return raw == other.raw; - } -}; /** * @brief This class provides an interface for intermediate data storage. @@ -75,6 +33,7 @@ public: static const ReturnValue_t ILLEGAL_STORAGE_ID = MAKE_RETURN_CODE(3); //!< This return code indicates that data was requested with an illegal storage ID. static const ReturnValue_t DATA_DOES_NOT_EXIST = MAKE_RETURN_CODE(4); //!< This return code indicates that the requested ID was valid, but no data is stored there. static const ReturnValue_t ILLEGAL_ADDRESS = MAKE_RETURN_CODE(5); + static const ReturnValue_t POOL_TOO_LARGE = MAKE_RETURN_CODE(6); //!< Pool size too large on initialization. static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::OBSW; static const Event GET_DATA_FAILED = MAKE_EVENT(0, SEVERITY::LOW); @@ -98,7 +57,8 @@ public: * @li RETURN_FAILED if data could not be added. * storageId is unchanged then. */ - virtual ReturnValue_t addData(store_address_t* storageId, const uint8_t * data, uint32_t size, bool ignoreFault = false) = 0; + virtual ReturnValue_t addData(store_address_t* storageId, + const uint8_t * data, size_t size, bool ignoreFault = false) = 0; /** * @brief With deleteData, the storageManager frees the memory region * identified by packet_id. @@ -109,14 +69,37 @@ public: */ virtual ReturnValue_t deleteData(store_address_t packet_id) = 0; /** - * @brief Another deleteData which uses the pointer and size of the stored data to delete the content. + * @brief Another deleteData which uses the pointer and size of the + * stored data to delete the content. * @param buffer Pointer to the data. * @param size Size of data to be stored. * @param storeId Store id of the deleted element (optional) * @return @li RETURN_OK on success. * @li failure code if deletion did not work */ - virtual ReturnValue_t deleteData(uint8_t* buffer, uint32_t size, store_address_t* storeId = NULL) = 0; + virtual ReturnValue_t deleteData(uint8_t* buffer, size_t size, + store_address_t* storeId = nullptr) = 0; + + /** + * @brief Access the data by supplying a store ID. + * @details + * A pair consisting of the retrieval result and an instance of a + * ConstStorageAccessor class is returned + * @param storeId + * @return Pair of return value and a ConstStorageAccessor instance + */ + virtual ConstAccessorPair getData(store_address_t storeId) = 0; + + /** + * @brief Access the data by supplying a store ID and a helper + * instance + * @param storeId + * @param constAccessor Wrapper function to access store data. + * @return + */ + virtual ReturnValue_t getData(store_address_t storeId, + ConstStorageAccessor& constAccessor) = 0; + /** * @brief getData returns an address to data and the size of the data * for a given packet_id. @@ -129,12 +112,34 @@ public: * (e.g. an illegal packet_id was passed). */ virtual ReturnValue_t getData(store_address_t packet_id, - const uint8_t** packet_ptr, uint32_t* size) = 0; + const uint8_t** packet_ptr, size_t* size) = 0; + + /** - * Same as above, but not const and therefore modifiable. + * Modify data by supplying a store ID + * @param storeId + * @return Pair of return value and StorageAccessor helper + */ + virtual AccessorPair modifyData(store_address_t storeId) = 0; + + /** + * Modify data by supplying a store ID and a StorageAccessor helper instance. + * @param storeId + * @param accessor Helper class to access the modifiable data. + * @return + */ + virtual ReturnValue_t modifyData(store_address_t storeId, + StorageAccessor& accessor) = 0; + + /** + * Get pointer and size of modifiable data by supplying the storeId + * @param packet_id + * @param packet_ptr [out] Pointer to pointer of data to set + * @param size [out] Pointer to size to set + * @return */ virtual ReturnValue_t modifyData(store_address_t packet_id, - uint8_t** packet_ptr, uint32_t* size) = 0; + uint8_t** packet_ptr, size_t* size) = 0; /** * This method reserves an element of \c size. * @@ -148,13 +153,14 @@ public: * @li RETURN_FAILED if data could not be added. * storageId is unchanged then. */ - virtual ReturnValue_t getFreeElement(store_address_t* storageId, const uint32_t size, uint8_t** p_data, bool ignoreFault = false ) = 0; + virtual ReturnValue_t getFreeElement(store_address_t* storageId, + const size_t size, uint8_t** p_data, bool ignoreFault = false ) = 0; + /** * Clears the whole store. * Use with care! */ virtual void clearStore() = 0; - }; #endif /* STORAGEMANAGERIF_H_ */ diff --git a/storagemanager/storeAddress.h b/storagemanager/storeAddress.h new file mode 100644 index 00000000..5dd785a3 --- /dev/null +++ b/storagemanager/storeAddress.h @@ -0,0 +1,54 @@ +#ifndef FRAMEWORK_STORAGEMANAGER_STOREADDRESS_H_ +#define FRAMEWORK_STORAGEMANAGER_STOREADDRESS_H_ +#include + +/** + * This union defines the type that identifies where a data packet is + * stored in the store. It comprises of a raw part to read it as raw value and + * a structured part to use it in pool-like stores. + */ +union store_address_t { + /** + * Default Constructor, initializing to INVALID_ADDRESS + */ + store_address_t():raw(0xFFFFFFFF){} + /** + * Constructor to create an address object using the raw address + * + * @param rawAddress + */ + store_address_t(uint32_t rawAddress):raw(rawAddress){} + + /** + * Constructor to create an address object using pool + * and packet indices + * + * @param poolIndex + * @param packetIndex + */ + store_address_t(uint16_t poolIndex, uint16_t packetIndex): + pool_index(poolIndex),packet_index(packetIndex){} + /** + * A structure with two elements to access the store address pool-like. + */ + struct { + /** + * The index in which pool the packet lies. + */ + uint16_t pool_index; + /** + * The position in the chosen pool. + */ + uint16_t packet_index; + }; + /** + * Alternative access to the raw value. + */ + uint32_t raw; + + bool operator==(const store_address_t& other) const { + return raw == other.raw; + } +}; + +#endif /* FRAMEWORK_STORAGEMANAGER_STOREADDRESS_H_ */ From d83181cb0fddcb9ad8f2572151058ca97c2e0a96 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 29 May 2020 16:41:23 +0200 Subject: [PATCH 002/101] added author tag --- storagemanager/LocalPool.h | 1 + 1 file changed, 1 insertion(+) diff --git a/storagemanager/LocalPool.h b/storagemanager/LocalPool.h index c155f918..2d61dea5 100644 --- a/storagemanager/LocalPool.h +++ b/storagemanager/LocalPool.h @@ -22,6 +22,7 @@ * 0xFFFF-1 bytes. * It is possible to store empty packets in the pool. * The local pool is NOT thread-safe. + * @author Bastian Baetz */ template From a993223f6e32ed278b5739d407411466bea83c47 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 29 May 2020 16:44:31 +0200 Subject: [PATCH 003/101] added include protection --- storagemanager/LocalPool.tpp | 4 ++++ storagemanager/PoolManager.tpp | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/storagemanager/LocalPool.tpp b/storagemanager/LocalPool.tpp index 32724bd8..dd360a0a 100644 --- a/storagemanager/LocalPool.tpp +++ b/storagemanager/LocalPool.tpp @@ -1,6 +1,10 @@ #ifndef FRAMEWORK_STORAGEMANAGER_LOCALPOOL_TPP_ #define FRAMEWORK_STORAGEMANAGER_LOCALPOOL_TPP_ +#ifndef FRAMEWORK_STORAGEMANAGER_LOCALPOOL_H_ +#error Include LocalPool.h instead of LocalPool.tpp!. +#endif + template inline LocalPool::LocalPool(object_id_t setObjectId, const uint16_t element_sizes[NUMBER_OF_POOLS], diff --git a/storagemanager/PoolManager.tpp b/storagemanager/PoolManager.tpp index 854e22da..bdc73ec2 100644 --- a/storagemanager/PoolManager.tpp +++ b/storagemanager/PoolManager.tpp @@ -1,6 +1,10 @@ #ifndef FRAMEWORK_STORAGEMANAGER_POOLMANAGER_TPP_ #define FRAMEWORK_STORAGEMANAGER_POOLMANAGER_TPP_ +#ifndef FRAMEWORK_STORAGEMANAGER_POOLMANAGER_H_ +#error Include LocalPool.h instead of LocalPool.tpp!. +#endif + template inline PoolManager::PoolManager(object_id_t setObjectId, const uint16_t element_sizes[NUMBER_OF_POOLS], From ab17e284052297a4ab94852ecbc331a7add97159 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 29 May 2020 16:45:52 +0200 Subject: [PATCH 004/101] include protection output fix --- storagemanager/LocalPool.tpp | 2 +- storagemanager/PoolManager.tpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/storagemanager/LocalPool.tpp b/storagemanager/LocalPool.tpp index dd360a0a..b7fa0da9 100644 --- a/storagemanager/LocalPool.tpp +++ b/storagemanager/LocalPool.tpp @@ -2,7 +2,7 @@ #define FRAMEWORK_STORAGEMANAGER_LOCALPOOL_TPP_ #ifndef FRAMEWORK_STORAGEMANAGER_LOCALPOOL_H_ -#error Include LocalPool.h instead of LocalPool.tpp!. +#error Include LocalPool.h instead of LocalPool.tpp! #endif template diff --git a/storagemanager/PoolManager.tpp b/storagemanager/PoolManager.tpp index bdc73ec2..97603246 100644 --- a/storagemanager/PoolManager.tpp +++ b/storagemanager/PoolManager.tpp @@ -2,7 +2,7 @@ #define FRAMEWORK_STORAGEMANAGER_POOLMANAGER_TPP_ #ifndef FRAMEWORK_STORAGEMANAGER_POOLMANAGER_H_ -#error Include LocalPool.h instead of LocalPool.tpp!. +#error Include LocalPool.h instead of LocalPool.tpp! #endif template From acf037614ff9795ee1bea4875d76415a61388835 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 29 May 2020 16:48:53 +0200 Subject: [PATCH 005/101] added another author tag --- storagemanager/PoolManager.h | 1 + 1 file changed, 1 insertion(+) diff --git a/storagemanager/PoolManager.h b/storagemanager/PoolManager.h index 6e353de2..c74e95c0 100644 --- a/storagemanager/PoolManager.h +++ b/storagemanager/PoolManager.h @@ -10,6 +10,7 @@ * a fixed pool size policy for inter-process communication. * @details Uses local pool calls but is thread safe by protecting the call * with a lock. + * @author Bastian Baetz */ template class PoolManager : public LocalPool { From a3f379e149dd32e4ac90e1fd58038138d8a65701 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 29 May 2020 16:50:37 +0200 Subject: [PATCH 006/101] and another little include guard fix --- storagemanager/LocalPool.tpp | 2 +- storagemanager/PoolManager.tpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/storagemanager/LocalPool.tpp b/storagemanager/LocalPool.tpp index b7fa0da9..764bd7be 100644 --- a/storagemanager/LocalPool.tpp +++ b/storagemanager/LocalPool.tpp @@ -2,7 +2,7 @@ #define FRAMEWORK_STORAGEMANAGER_LOCALPOOL_TPP_ #ifndef FRAMEWORK_STORAGEMANAGER_LOCALPOOL_H_ -#error Include LocalPool.h instead of LocalPool.tpp! +#error Include LocalPool.h before LocalPool.tpp! #endif template diff --git a/storagemanager/PoolManager.tpp b/storagemanager/PoolManager.tpp index 97603246..29b2b82a 100644 --- a/storagemanager/PoolManager.tpp +++ b/storagemanager/PoolManager.tpp @@ -2,7 +2,7 @@ #define FRAMEWORK_STORAGEMANAGER_POOLMANAGER_TPP_ #ifndef FRAMEWORK_STORAGEMANAGER_POOLMANAGER_H_ -#error Include LocalPool.h instead of LocalPool.tpp! +#error Include PoolManager.h before PoolManager.tpp! #endif template From f871f75e1c8fd5f625e4a2067492eb92f3b82289 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 29 May 2020 17:10:57 +0200 Subject: [PATCH 007/101] added back default value for pool manager.h --- storagemanager/PoolManager.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storagemanager/PoolManager.h b/storagemanager/PoolManager.h index c74e95c0..144d073d 100644 --- a/storagemanager/PoolManager.h +++ b/storagemanager/PoolManager.h @@ -12,7 +12,7 @@ * with a lock. * @author Bastian Baetz */ -template +template class PoolManager : public LocalPool { public: PoolManager(object_id_t setObjectId, From 8e3f99a350be66308d9afabae8069426f67ce8e6 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 4 Jun 2020 14:59:14 +0200 Subject: [PATCH 008/101] removed object manager changes for now --- objectmanager/ObjectManagerIF.h | 29 +++++++++-------------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/objectmanager/ObjectManagerIF.h b/objectmanager/ObjectManagerIF.h index b5cab408..aca24a24 100644 --- a/objectmanager/ObjectManagerIF.h +++ b/objectmanager/ObjectManagerIF.h @@ -8,11 +8,10 @@ #ifndef OBJECTMANAGERIF_H_ #define OBJECTMANAGERIF_H_ -#include "systemObjectList.h" #include +#include #include #include -#include /** * @brief This class provides an interface to the global object manager. @@ -25,12 +24,9 @@ */ class ObjectManagerIF : public HasReturnvaluesIF { public: - static constexpr uint8_t INTERFACE_ID = CLASS_ID::OBJECT_MANAGER_IF; - static constexpr ReturnValue_t INSERTION_FAILED = MAKE_RETURN_CODE( 1 ); - static constexpr ReturnValue_t NOT_FOUND = MAKE_RETURN_CODE( 2 ); - static constexpr ReturnValue_t CHILD_INIT_FAILED = MAKE_RETURN_CODE( 3 ); - static constexpr ReturnValue_t INTERNAL_ERR_REPORTER_UNINIT = MAKE_RETURN_CODE( 4 ); - + static const uint8_t INTERFACE_ID = CLASS_ID::OBJECT_MANAGER_IF; + static const ReturnValue_t INSERTION_FAILED = MAKE_RETURN_CODE( 1 ); + static const ReturnValue_t NOT_FOUND = MAKE_RETURN_CODE( 2 ); protected: /** * @brief This method is used to hide the template-based get call from @@ -82,22 +78,15 @@ public: virtual void printList() = 0; }; +template +T* ObjectManagerIF::get( object_id_t id ) { + SystemObjectIF* temp = this->getSystemObject(id); + return dynamic_cast(temp); +} /** * @brief This is the forward declaration of the global objectManager instance. */ extern ObjectManagerIF *objectManager; -/*Documentation can be found in the class method declaration above.*/ -template -T* ObjectManagerIF::get( object_id_t id ) { - if(objectManager == nullptr) { - sif::error << "ObjectManagerIF: Global object manager has not " - "been initialized yet!" << std::endl; - std::exit(0); - } - SystemObjectIF* temp = this->getSystemObject(id); - return dynamic_cast(temp); -} - #endif /* OBJECTMANAGERIF_H_ */ From 1d99a99bbd79942b5f034705fd74f4e599b47444 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 4 Jun 2020 15:00:05 +0200 Subject: [PATCH 009/101] I now remember why I included object manager IF changes --- objectmanager/ObjectManagerIF.h | 42 ++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/objectmanager/ObjectManagerIF.h b/objectmanager/ObjectManagerIF.h index aca24a24..0dfb7f30 100644 --- a/objectmanager/ObjectManagerIF.h +++ b/objectmanager/ObjectManagerIF.h @@ -1,17 +1,10 @@ -/** - * @file ObjectManagerIF.h - * @brief This file contains the implementation of the ObjectManagerIF interface - * @date 19.09.2012 - * @author Bastian Baetz - */ - -#ifndef OBJECTMANAGERIF_H_ -#define OBJECTMANAGERIF_H_ +#ifndef FRAMEWORK_OBJECTMANAGER_OBJECTMANAGERIF_H_ +#define FRAMEWORK_OBJECTMANAGER_OBJECTMANAGERIF_H_ #include -#include #include #include +#include /** * @brief This class provides an interface to the global object manager. @@ -20,13 +13,17 @@ * inserted, removed and retrieved from the list. On getting the * object, the call checks if the object implements the requested * interface. - * \ingroup system_objects + * @author Bastian Baetz + * @ingroup system_objects */ class ObjectManagerIF : public HasReturnvaluesIF { public: - static const uint8_t INTERFACE_ID = CLASS_ID::OBJECT_MANAGER_IF; - static const ReturnValue_t INSERTION_FAILED = MAKE_RETURN_CODE( 1 ); - static const ReturnValue_t NOT_FOUND = MAKE_RETURN_CODE( 2 ); + static constexpr uint8_t INTERFACE_ID = CLASS_ID::OBJECT_MANAGER_IF; + static constexpr ReturnValue_t INSERTION_FAILED = MAKE_RETURN_CODE( 1 ); + static constexpr ReturnValue_t NOT_FOUND = MAKE_RETURN_CODE( 2 ); + static constexpr ReturnValue_t CHILD_INIT_FAILED = MAKE_RETURN_CODE( 3 ); + static constexpr ReturnValue_t INTERNAL_ERR_REPORTER_UNINIT = MAKE_RETURN_CODE( 4 ); + protected: /** * @brief This method is used to hide the template-based get call from @@ -78,15 +75,22 @@ public: virtual void printList() = 0; }; -template -T* ObjectManagerIF::get( object_id_t id ) { - SystemObjectIF* temp = this->getSystemObject(id); - return dynamic_cast(temp); -} /** * @brief This is the forward declaration of the global objectManager instance. */ extern ObjectManagerIF *objectManager; +/*Documentation can be found in the class method declaration above.*/ +template +T* ObjectManagerIF::get( object_id_t id ) { + if(objectManager == nullptr) { + sif::error << "ObjectManagerIF: Global object manager has not " + "been initialized yet!" << std::endl; + std::exit(1); + } + SystemObjectIF* temp = this->getSystemObject(id); + return dynamic_cast(temp); +} + #endif /* OBJECTMANAGERIF_H_ */ From 3d175f603c0cfdb1a8b1c7185ab15ad248f164a6 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 4 Jun 2020 15:02:14 +0200 Subject: [PATCH 010/101] removed conflict markers --- storagemanager/LocalPool.h | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/storagemanager/LocalPool.h b/storagemanager/LocalPool.h index d842294c..7e349dcd 100644 --- a/storagemanager/LocalPool.h +++ b/storagemanager/LocalPool.h @@ -1,12 +1,3 @@ -<<<<<<< HEAD -======= -/** - * @file LocalPool - * @date 02.02.2012 - * @author Bastian Baetz - * @brief This file contains the definition of the LocalPool class. - */ ->>>>>>> upstream/master #ifndef FRAMEWORK_STORAGEMANAGER_LOCALPOOL_H_ #define FRAMEWORK_STORAGEMANAGER_LOCALPOOL_H_ @@ -44,7 +35,7 @@ public: /** * @brief This is the default constructor for a pool manager instance. * @details By passing two arrays of size NUMBER_OF_POOLS, the constructor - * allocates memory (with \c new) for store and size_list. These + * allocates memory (with @c new) for store and size_list. These * regions are all set to zero on start up. * @param setObjectId The object identifier to be set. This allows for * multiple instances of LocalPool in the system. @@ -96,7 +87,7 @@ public: ReturnValue_t initialize() override; protected: /** - * With this helper method, a free element of \c size is reserved. + * With this helper method, a free element of @c size is reserved. * @param size The minimum packet size that shall be reserved. * @param[out] address Storage ID of the reserved data. * @return - #RETURN_OK on success, @@ -109,7 +100,8 @@ protected: private: /** * Indicates that this element is free. - * This value limits the maximum size of a pool. Change to larger data type if increase is required. + * This value limits the maximum size of a pool. Change to larger data type + * if increase is required. */ static const uint32_t STORAGE_FREE = 0xFFFFFFFF; /** @@ -135,7 +127,9 @@ private: * is also dynamically allocated there. */ uint32_t* size_list[NUMBER_OF_POOLS]; - bool spillsToHigherPools; //!< A variable to determine whether higher n pools are used if the store is full. + //! A variable to determine whether higher n pools are used if + //! the store is full. + bool spillsToHigherPools; /** * @brief This method safely stores the given data in the given packet_id. * @details It also sets the size in size_list. The method does not perform From a6a31801960dca7a5949daece14c1843caaa9baf Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 4 Jun 2020 15:03:29 +0200 Subject: [PATCH 011/101] removed conflict markers --- storagemanager/PoolManager.h | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/storagemanager/PoolManager.h b/storagemanager/PoolManager.h index cbb5d54b..7c2e8a71 100644 --- a/storagemanager/PoolManager.h +++ b/storagemanager/PoolManager.h @@ -22,20 +22,12 @@ public: //! @brief In the PoolManager's destructor all allocated memory is freed. virtual ~PoolManager(); -<<<<<<< HEAD //! @brief LocalPool overrides for thread-safety. Decorator function which //! wraps LocalPool calls with a mutex protection. ReturnValue_t deleteData(store_address_t) override; ReturnValue_t deleteData(uint8_t* buffer, size_t size, store_address_t* storeId = nullptr) override; -======= - //! @brief LocalPool overrides for thread-safety. - ReturnValue_t deleteData(store_address_t) override; - ReturnValue_t deleteData(uint8_t* buffer, size_t size, - store_address_t* storeId = NULL) override; - ReturnValue_t modifyData(store_address_t packet_id, uint8_t** packet_ptr, - size_t* size) override; ->>>>>>> upstream/master + protected: ReturnValue_t reserveSpace(const uint32_t size, store_address_t* address, bool ignoreFault) override; From 4c59b043e13aa8f21949d9adf9662e75ecb98611 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 23 Jun 2020 10:57:14 +0200 Subject: [PATCH 012/101] const store accessor in separate file now --- storagemanager/ConstStoreAccessor.cpp | 93 +++++++++++++++++++++ storagemanager/ConstStoreAccessor.h | 116 ++++++++++++++++++++++++++ storagemanager/StorageAccessor.cpp | 98 ++-------------------- storagemanager/StorageAccessor.h | 109 +----------------------- 4 files changed, 215 insertions(+), 201 deletions(-) create mode 100644 storagemanager/ConstStoreAccessor.cpp create mode 100644 storagemanager/ConstStoreAccessor.h diff --git a/storagemanager/ConstStoreAccessor.cpp b/storagemanager/ConstStoreAccessor.cpp new file mode 100644 index 00000000..84f40053 --- /dev/null +++ b/storagemanager/ConstStoreAccessor.cpp @@ -0,0 +1,93 @@ +#include +#include +#include + +ConstStorageAccessor::ConstStorageAccessor(store_address_t storeId): + storeId(storeId) {} + +ConstStorageAccessor::ConstStorageAccessor(store_address_t storeId, + StorageManagerIF* store): + storeId(storeId), store(store) { + internalState = AccessState::ASSIGNED; +} + +ConstStorageAccessor::~ConstStorageAccessor() { + if(deleteData and store != nullptr) { + sif::debug << "deleting store data" << std::endl; + store->deleteData(storeId); + } +} + +ConstStorageAccessor::ConstStorageAccessor(ConstStorageAccessor&& other): + constDataPointer(other.constDataPointer), storeId(other.storeId), + size_(other.size_), store(other.store), deleteData(other.deleteData), + internalState(other.internalState) { + // This prevent premature deletion + other.store = nullptr; +} + +ConstStorageAccessor& ConstStorageAccessor::operator=( + ConstStorageAccessor&& other) { + constDataPointer = other.constDataPointer; + storeId = other.storeId; + store = other.store; + size_ = other.size_; + deleteData = other.deleteData; + this->store = other.store; + // This prevents premature deletion + other.store = nullptr; + return *this; +} + +const uint8_t* ConstStorageAccessor::data() const { + return constDataPointer; +} + +size_t ConstStorageAccessor::size() const { + if(internalState == AccessState::UNINIT) { + sif::warning << "StorageAccessor: Not initialized!" << std::endl; + } + return size_; +} + +ReturnValue_t ConstStorageAccessor::getDataCopy(uint8_t *pointer, + size_t maxSize) { + if(internalState == AccessState::UNINIT) { + sif::warning << "StorageAccessor: Not initialized!" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + if(size_ > maxSize) { + sif::error << "StorageAccessor: Supplied buffer not large enough" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + std::copy(constDataPointer, constDataPointer + size_, pointer); + return HasReturnvaluesIF::RETURN_OK; +} + +void ConstStorageAccessor::release() { + deleteData = false; +} + +store_address_t ConstStorageAccessor::getId() const { + return storeId; +} + +void ConstStorageAccessor::print() const { + if(internalState == AccessState::UNINIT) { + sif::warning << "StorageAccessor: Not initialized!" << std::endl; + return; + } + sif::info << "StorageAccessor: Printing data: ["; + for(uint16_t iPool = 0; iPool < size_; iPool++) { + sif::info << std::hex << (int)constDataPointer[iPool]; + if(iPool < size_ - 1){ + sif::info << " , "; + } + } + sif::info << " ] " << std::endl; +} + +void ConstStorageAccessor::assignStore(StorageManagerIF* store) { + internalState = AccessState::ASSIGNED; + this->store = store; +} diff --git a/storagemanager/ConstStoreAccessor.h b/storagemanager/ConstStoreAccessor.h new file mode 100644 index 00000000..2420893c --- /dev/null +++ b/storagemanager/ConstStoreAccessor.h @@ -0,0 +1,116 @@ +#ifndef FRAMEWORK_STORAGEMANAGER_CONSTSTOREACCESSOR_H_ +#define FRAMEWORK_STORAGEMANAGER_CONSTSTOREACCESSOR_H_ + +#include +#include +#include + +class StorageManagerIF; + +/** + * @brief Helper classes to facilitate safe access to storages which is also + * conforming to RAII principles + * @details + * Accessor class which can be returned by pool manager or passed and set by + * pool managers to have safe access to the pool resources. + * + * These helper can be used together with the StorageManager classes to manage + * access to a storage. It can take care of thread-safety while also providing + * mechanisms to automatically clear storage data. + */ +class ConstStorageAccessor { + //! StorageManager classes have exclusive access to private variables. + template + friend class PoolManager; + template + friend class LocalPool; +public: + /** + * @brief Simple constructor which takes the store ID of the storage + * entry to access. + * @param storeId + */ + ConstStorageAccessor(store_address_t storeId); + ConstStorageAccessor(store_address_t storeId, StorageManagerIF* store); + + /** + * @brief The destructor in default configuration takes care of + * deleting the accessed pool entry and unlocking the mutex + */ + virtual ~ConstStorageAccessor(); + + /** + * @brief Returns a pointer to the read-only data + * @return + */ + const uint8_t* data() const; + + /** + * @brief Copies the read-only data to the supplied pointer + * @param pointer + */ + virtual ReturnValue_t getDataCopy(uint8_t *pointer, size_t maxSize); + + /** + * @brief Calling this will prevent the Accessor from deleting the data + * when the destructor is called. + */ + void release(); + + /** + * Get the size of the data + * @return + */ + size_t size() const; + + /** + * Get the storage ID. + * @return + */ + store_address_t getId() const; + + void print() const; + + /** + * @brief Move ctor and move assignment allow returning accessors as + * a returnvalue. They prevent resource being free prematurely. + * Refer to: https://github.com/MicrosoftDocs/cpp-docs/blob/master/docs/cpp/ + * move-constructors-and-move-assignment-operators-cpp.md + * @param + * @return + */ + ConstStorageAccessor& operator= (ConstStorageAccessor&&); + ConstStorageAccessor (ConstStorageAccessor&&); + + //! The copy ctor and copy assignemnt should be deleted implicitely + //! according to https://foonathan.net/2019/02/special-member-functions/ + //! but I still deleted them to make it more explicit. (remember rule of 5). + ConstStorageAccessor& operator= (ConstStorageAccessor&) = delete; + ConstStorageAccessor (ConstStorageAccessor&) = delete; +protected: + const uint8_t* constDataPointer = nullptr; + store_address_t storeId; + size_t size_ = 0; + //! Managing pool, has to assign itself. + StorageManagerIF* store = nullptr; + bool deleteData = true; + + enum class AccessState { + UNINIT, + ASSIGNED + }; + //! Internal state for safety reasons. + AccessState internalState = AccessState::UNINIT; + /** + * Used by the pool manager instances to assign themselves to the + * accessor. This is necessary to delete the data when the acessor + * exits the scope ! The internal state will be considered read + * when this function is called, so take care all data is set properly as + * well. + * @param + */ + void assignStore(StorageManagerIF*); +}; + + +#endif /* FRAMEWORK_STORAGEMANAGER_CONSTSTOREACCESSOR_H_ */ diff --git a/storagemanager/StorageAccessor.cpp b/storagemanager/StorageAccessor.cpp index c0c8126b..b827b9c0 100644 --- a/storagemanager/StorageAccessor.cpp +++ b/storagemanager/StorageAccessor.cpp @@ -1,96 +1,6 @@ #include #include - -ConstStorageAccessor::ConstStorageAccessor(store_address_t storeId): - storeId(storeId) {} - -ConstStorageAccessor::ConstStorageAccessor(store_address_t storeId, - StorageManagerIF* store): - storeId(storeId), store(store) { - internalState = AccessState::ASSIGNED; -} - -ConstStorageAccessor::~ConstStorageAccessor() { - if(deleteData and store != nullptr) { - sif::debug << "deleting store data" << std::endl; - store->deleteData(storeId); - } -} - -ConstStorageAccessor::ConstStorageAccessor(ConstStorageAccessor&& other): - constDataPointer(other.constDataPointer), storeId(other.storeId), - size_(other.size_), store(other.store), deleteData(other.deleteData), - internalState(other.internalState) { - // This prevent premature deletion - other.store = nullptr; -} - -ConstStorageAccessor& ConstStorageAccessor::operator=( - ConstStorageAccessor&& other) { - constDataPointer = other.constDataPointer; - storeId = other.storeId; - store = other.store; - size_ = other.size_; - deleteData = other.deleteData; - this->store = other.store; - // This prevents premature deletion - other.store = nullptr; - return *this; -} - -const uint8_t* ConstStorageAccessor::data() const { - return constDataPointer; -} - -size_t ConstStorageAccessor::size() const { - if(internalState == AccessState::UNINIT) { - sif::warning << "StorageAccessor: Not initialized!" << std::endl; - } - return size_; -} - -ReturnValue_t ConstStorageAccessor::getDataCopy(uint8_t *pointer, - size_t maxSize) { - if(internalState == AccessState::UNINIT) { - sif::warning << "StorageAccessor: Not initialized!" << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; - } - if(size_ > maxSize) { - sif::error << "StorageAccessor: Supplied buffer not large enough" << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; - } - std::copy(constDataPointer, constDataPointer + size_, pointer); - return HasReturnvaluesIF::RETURN_OK; -} - -void ConstStorageAccessor::release() { - deleteData = false; -} - -store_address_t ConstStorageAccessor::getId() const { - return storeId; -} - -void ConstStorageAccessor::print() const { - if(internalState == AccessState::UNINIT) { - sif::warning << "StorageAccessor: Not initialized!" << std::endl; - return; - } - sif::info << "StorageAccessor: Printing data: ["; - for(uint16_t iPool = 0; iPool < size_; iPool++) { - sif::info << std::hex << (int)constDataPointer[iPool]; - if(iPool < size_ - 1){ - sif::info << " , "; - } - } - sif::info << " ] " << std::endl; -} - -void ConstStorageAccessor::assignStore(StorageManagerIF* store) { - internalState = AccessState::ASSIGNED; - this->store = store; -} - +#include StorageAccessor::StorageAccessor(store_address_t storeId): ConstStorageAccessor(storeId) { @@ -120,7 +30,8 @@ ReturnValue_t StorageAccessor::getDataCopy(uint8_t *pointer, size_t maxSize) { return HasReturnvaluesIF::RETURN_FAILED; } if(size_ > maxSize) { - sif::error << "StorageAccessor: Supplied buffer not large enough" << std::endl; + sif::error << "StorageAccessor: Supplied buffer not large " + "enough" << std::endl; return HasReturnvaluesIF::RETURN_FAILED; } std::copy(dataPointer, dataPointer + size_, pointer); @@ -141,7 +52,8 @@ ReturnValue_t StorageAccessor::write(uint8_t *data, size_t size, return HasReturnvaluesIF::RETURN_FAILED; } if(offset + size > size_) { - sif::error << "StorageAccessor: Data too large for pool entry!" << std::endl; + sif::error << "StorageAccessor: Data too large for pool " + "entry!" << std::endl; return HasReturnvaluesIF::RETURN_FAILED; } std::copy(data, data + size, dataPointer + offset); diff --git a/storagemanager/StorageAccessor.h b/storagemanager/StorageAccessor.h index 57c9369c..bcefe24d 100644 --- a/storagemanager/StorageAccessor.h +++ b/storagemanager/StorageAccessor.h @@ -1,117 +1,10 @@ #ifndef FRAMEWORK_STORAGEMANAGER_STORAGEACCESSOR_H_ #define FRAMEWORK_STORAGEMANAGER_STORAGEACCESSOR_H_ -#include -#include +#include class StorageManagerIF; -/** - * @brief Helper classes to facilitate safe access to storages which is also - * conforming to RAII principles - * @details - * Accessor class which can be returned by pool manager or passed and set by - * pool managers to have safe access to the pool resources. - * - * These helper can be used together with the StorageManager classes to manage - * access to a storage. It can take care of thread-safety while also providing - * mechanisms to automatically clear storage data. - */ -class ConstStorageAccessor { - //! StorageManager classes have exclusive access to private variables. - template - friend class PoolManager; - template - friend class LocalPool; -public: - /** - * @brief Simple constructor which takes the store ID of the storage - * entry to access. - * @param storeId - */ - ConstStorageAccessor(store_address_t storeId); - ConstStorageAccessor(store_address_t storeId, StorageManagerIF* store); - - /** - * @brief The destructor in default configuration takes care of - * deleting the accessed pool entry and unlocking the mutex - */ - virtual ~ConstStorageAccessor(); - - /** - * @brief Returns a pointer to the read-only data - * @return - */ - const uint8_t* data() const; - - /** - * @brief Copies the read-only data to the supplied pointer - * @param pointer - */ - virtual ReturnValue_t getDataCopy(uint8_t *pointer, size_t maxSize); - - /** - * @brief Calling this will prevent the Accessor from deleting the data - * when the destructor is called. - */ - void release(); - - /** - * Get the size of the data - * @return - */ - size_t size() const; - - /** - * Get the storage ID. - * @return - */ - store_address_t getId() const; - - void print() const; - - /** - * @brief Move ctor and move assignment allow returning accessors as - * a returnvalue. They prevent resource being free prematurely. - * Refer to: https://github.com/MicrosoftDocs/cpp-docs/blob/master/docs/cpp/ - * move-constructors-and-move-assignment-operators-cpp.md - * @param - * @return - */ - ConstStorageAccessor& operator= (ConstStorageAccessor&&); - ConstStorageAccessor (ConstStorageAccessor&&); - - //! The copy ctor and copy assignemnt should be deleted implicitely - //! according to https://foonathan.net/2019/02/special-member-functions/ - //! but I still deleted them to make it more explicit. (remember rule of 5). - ConstStorageAccessor& operator= (ConstStorageAccessor&) = delete; - ConstStorageAccessor (ConstStorageAccessor&) = delete; -protected: - const uint8_t* constDataPointer = nullptr; - store_address_t storeId; - size_t size_ = 0; - //! Managing pool, has to assign itself. - StorageManagerIF* store = nullptr; - bool deleteData = true; - - enum class AccessState { - UNINIT, - ASSIGNED - }; - //! Internal state for safety reasons. - AccessState internalState = AccessState::UNINIT; - /** - * Used by the pool manager instances to assign themselves to the - * accessor. This is necessary to delete the data when the acessor - * exits the scope ! The internal state will be considered read - * when this function is called, so take care all data is set properly as - * well. - * @param - */ - void assignStore(StorageManagerIF*); -}; - - /** * @brief Child class for modifyable data. Also has a normal pointer member. */ From a589be7c746d9f44b3ef3b47fceaa2ae3cd8412e Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 23 Jun 2020 11:06:54 +0200 Subject: [PATCH 013/101] took over imrpvements --- ...tStoreAccessor.cpp => ConstStorageAccessor.cpp} | 14 ++++---------- ...ConstStoreAccessor.h => ConstStorageAccessor.h} | 6 +++--- storagemanager/PoolManager.h | 3 +++ storagemanager/PoolManager.tpp | 6 +++--- storagemanager/StorageAccessor.h | 2 +- 5 files changed, 14 insertions(+), 17 deletions(-) rename storagemanager/{ConstStoreAccessor.cpp => ConstStorageAccessor.cpp} (87%) rename storagemanager/{ConstStoreAccessor.h => ConstStorageAccessor.h} (94%) diff --git a/storagemanager/ConstStoreAccessor.cpp b/storagemanager/ConstStorageAccessor.cpp similarity index 87% rename from storagemanager/ConstStoreAccessor.cpp rename to storagemanager/ConstStorageAccessor.cpp index 84f40053..0bfde58c 100644 --- a/storagemanager/ConstStoreAccessor.cpp +++ b/storagemanager/ConstStorageAccessor.cpp @@ -1,6 +1,7 @@ -#include #include +#include #include +#include ConstStorageAccessor::ConstStorageAccessor(store_address_t storeId): storeId(storeId) {} @@ -73,18 +74,11 @@ store_address_t ConstStorageAccessor::getId() const { } void ConstStorageAccessor::print() const { - if(internalState == AccessState::UNINIT) { + if(internalState == AccessState::UNINIT or constDataPointer == nullptr) { sif::warning << "StorageAccessor: Not initialized!" << std::endl; return; } - sif::info << "StorageAccessor: Printing data: ["; - for(uint16_t iPool = 0; iPool < size_; iPool++) { - sif::info << std::hex << (int)constDataPointer[iPool]; - if(iPool < size_ - 1){ - sif::info << " , "; - } - } - sif::info << " ] " << std::endl; + arrayprinter::print(constDataPointer, size_); } void ConstStorageAccessor::assignStore(StorageManagerIF* store) { diff --git a/storagemanager/ConstStoreAccessor.h b/storagemanager/ConstStorageAccessor.h similarity index 94% rename from storagemanager/ConstStoreAccessor.h rename to storagemanager/ConstStorageAccessor.h index 2420893c..cf8ca08f 100644 --- a/storagemanager/ConstStoreAccessor.h +++ b/storagemanager/ConstStorageAccessor.h @@ -1,5 +1,5 @@ -#ifndef FRAMEWORK_STORAGEMANAGER_CONSTSTOREACCESSOR_H_ -#define FRAMEWORK_STORAGEMANAGER_CONSTSTOREACCESSOR_H_ +#ifndef FRAMEWORK_STORAGEMANAGER_CONSTSTORAGEACCESSOR_H_ +#define FRAMEWORK_STORAGEMANAGER_CONSTSTORAGEACCESSOR_H_ #include #include @@ -113,4 +113,4 @@ protected: }; -#endif /* FRAMEWORK_STORAGEMANAGER_CONSTSTOREACCESSOR_H_ */ +#endif /* FRAMEWORK_STORAGEMANAGER_CONSTSTORAGEACCESSOR_H_ */ diff --git a/storagemanager/PoolManager.h b/storagemanager/PoolManager.h index 7c2e8a71..3c1c1217 100644 --- a/storagemanager/PoolManager.h +++ b/storagemanager/PoolManager.h @@ -29,6 +29,9 @@ public: store_address_t* storeId = nullptr) override; protected: + //! Default mutex timeout value to prevent permanent blocking. + static constexpr uint32_t mutexTimeout = 50; + ReturnValue_t reserveSpace(const uint32_t size, store_address_t* address, bool ignoreFault) override; diff --git a/storagemanager/PoolManager.tpp b/storagemanager/PoolManager.tpp index a364f5a2..4ca22b85 100644 --- a/storagemanager/PoolManager.tpp +++ b/storagemanager/PoolManager.tpp @@ -21,7 +21,7 @@ inline PoolManager::~PoolManager(void) { template inline ReturnValue_t PoolManager::reserveSpace( const uint32_t size, store_address_t* address, bool ignoreFault) { - MutexHelper mutexHelper(mutex,MutexIF::NO_TIMEOUT); + MutexHelper mutexHelper(mutex, mutexTimeout); ReturnValue_t status = LocalPool::reserveSpace(size, address,ignoreFault); return status; @@ -33,7 +33,7 @@ inline ReturnValue_t PoolManager::deleteData( // debug << "PoolManager( " << translateObject(getObjectId()) << // " )::deleteData from store " << packet_id.pool_index << // ". id is "<< packet_id.packet_index << std::endl; - MutexHelper mutexHelper(mutex,MutexIF::NO_TIMEOUT); + MutexHelper mutexHelper(mutex, mutexTimeout); ReturnValue_t status = LocalPool::deleteData(packet_id); return status; } @@ -41,7 +41,7 @@ inline ReturnValue_t PoolManager::deleteData( template inline ReturnValue_t PoolManager::deleteData(uint8_t* buffer, size_t size, store_address_t* storeId) { - MutexHelper mutexHelper(mutex,MutexIF::NO_TIMEOUT); + MutexHelper mutexHelper(mutex, mutexTimeout); ReturnValue_t status = LocalPool::deleteData(buffer, size, storeId); return status; diff --git a/storagemanager/StorageAccessor.h b/storagemanager/StorageAccessor.h index bcefe24d..c5e38306 100644 --- a/storagemanager/StorageAccessor.h +++ b/storagemanager/StorageAccessor.h @@ -1,7 +1,7 @@ #ifndef FRAMEWORK_STORAGEMANAGER_STORAGEACCESSOR_H_ #define FRAMEWORK_STORAGEMANAGER_STORAGEACCESSOR_H_ -#include +#include class StorageManagerIF; From 549ad97bd3b2ee6b05af2383e7a30ef1ac846f5c Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 18 Aug 2020 11:25:57 +0200 Subject: [PATCH 014/101] shared ring buffer pull request --- container/SharedRingBuffer.cpp | 30 +++++++++++++++ container/SharedRingBuffer.h | 68 ++++++++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+) create mode 100644 container/SharedRingBuffer.cpp create mode 100644 container/SharedRingBuffer.h diff --git a/container/SharedRingBuffer.cpp b/container/SharedRingBuffer.cpp new file mode 100644 index 00000000..001a21ed --- /dev/null +++ b/container/SharedRingBuffer.cpp @@ -0,0 +1,30 @@ +#include +#include +#include + +SharedRingBuffer::SharedRingBuffer(object_id_t objectId, const size_t size, + bool overwriteOld, size_t maxExcessBytes): + SystemObject(objectId), SimpleRingBuffer(size, overwriteOld, + maxExcessBytes) { + mutex = MutexFactory::instance()->createMutex(); +} + +SharedRingBuffer::SharedRingBuffer(object_id_t objectId, uint8_t *buffer, + const size_t size, bool overwriteOld, size_t maxExcessBytes): + SystemObject(objectId), SimpleRingBuffer(buffer, size, overwriteOld, + maxExcessBytes) { + mutex = MutexFactory::instance()->createMutex(); +} + +ReturnValue_t SharedRingBuffer::lockRingBufferMutex( + MutexIF::TimeoutType timeoutType, dur_millis_t timeout) { + return mutex->lockMutex(timeoutType, timeout); +} + +ReturnValue_t SharedRingBuffer::unlockRingBufferMutex() { + return mutex->unlockMutex(); +} + +MutexIF* SharedRingBuffer::getMutexHandle() const { + return mutex; +} diff --git a/container/SharedRingBuffer.h b/container/SharedRingBuffer.h new file mode 100644 index 00000000..0b5be052 --- /dev/null +++ b/container/SharedRingBuffer.h @@ -0,0 +1,68 @@ +#ifndef FRAMEWORK_CONTAINER_SHAREDRINGBUFFER_H_ +#define FRAMEWORK_CONTAINER_SHAREDRINGBUFFER_H_ + +#include +#include +#include +#include + +/** + * @brief Ring buffer which can be shared among multiple objects + * @details + * This class offers a mutex to perform thread-safe operation on the ring + * buffer. It is still up to the developer to actually perform the lock + * and unlock operations. + */ +class SharedRingBuffer: public SystemObject, + public SimpleRingBuffer { +public: + /** + * This constructor allocates a new internal buffer with the supplied size. + * @param size + * @param overwriteOld + * If the ring buffer is overflowing at a write operartion, the oldest data + * will be overwritten. + */ + SharedRingBuffer(object_id_t objectId, const size_t size, + bool overwriteOld, size_t maxExcessBytes); + + /** + * This constructor takes an external buffer with the specified size. + * @param buffer + * @param size + * @param overwriteOld + * If the ring buffer is overflowing at a write operartion, the oldest data + * will be overwritten. + */ + SharedRingBuffer(object_id_t objectId, uint8_t* buffer, const size_t size, + bool overwriteOld, size_t maxExcessBytes); + + /** + * Unless a read-only constant value is read, all operations on the + * shared ring buffer should be protected by calling this function. + * @param timeoutType + * @param timeout + * @return + */ + virtual ReturnValue_t lockRingBufferMutex(MutexIF::TimeoutType timeoutType, + dur_millis_t timeout); + /** + * Any locked mutex also has to be unlocked, otherwise, access to the + * shared ring buffer will be blocked. + * @return + */ + virtual ReturnValue_t unlockRingBufferMutex(); + + /** + * The mutex handle can be accessed directly, for example to perform + * the lock with the #MutexHelper for a RAII compliant lock operation. + * @return + */ + MutexIF* getMutexHandle() const; +private: + MutexIF* mutex = nullptr; +}; + + + +#endif /* FRAMEWORK_CONTAINER_SHAREDRINGBUFFER_H_ */ From b7612bee37fdcfefa879ae80b71fdd8ebeaf198e Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 24 Aug 2020 14:55:32 +0200 Subject: [PATCH 015/101] getFreeELement function added --- container/SimpleRingBuffer.cpp | 203 ++++++++++++++++++++++----------- container/SimpleRingBuffer.h | 149 ++++++++++++++++++++---- 2 files changed, 263 insertions(+), 89 deletions(-) diff --git a/container/SimpleRingBuffer.cpp b/container/SimpleRingBuffer.cpp index ee087643..7ed019b2 100644 --- a/container/SimpleRingBuffer.cpp +++ b/container/SimpleRingBuffer.cpp @@ -1,68 +1,135 @@ -#include "SimpleRingBuffer.h" -#include - -SimpleRingBuffer::SimpleRingBuffer(uint32_t size, bool overwriteOld) : - RingBufferBase<>(0, size, overwriteOld), buffer(NULL) { - buffer = new uint8_t[size]; -} - -SimpleRingBuffer::~SimpleRingBuffer() { - delete[] buffer; -} - -ReturnValue_t SimpleRingBuffer::writeData(const uint8_t* data, - uint32_t amount) { - if (availableWriteSpace() >= amount || overwriteOld) { - uint32_t amountTillWrap = writeTillWrap(); - if (amountTillWrap >= amount) { - memcpy(&buffer[write], data, amount); - } else { - memcpy(&buffer[write], data, amountTillWrap); - memcpy(buffer, data + amountTillWrap, amount - amountTillWrap); - } - incrementWrite(amount); - return HasReturnvaluesIF::RETURN_OK; - } else { - return HasReturnvaluesIF::RETURN_FAILED; - } -} - -ReturnValue_t SimpleRingBuffer::readData(uint8_t* data, uint32_t amount, - bool readRemaining, uint32_t* trueAmount) { - uint32_t availableData = availableReadData(READ_PTR); - uint32_t amountTillWrap = readTillWrap(READ_PTR); - if (availableData < amount) { - if (readRemaining) { - amount = availableData; - } else { - return HasReturnvaluesIF::RETURN_FAILED; - } - } - if (trueAmount != NULL) { - *trueAmount = amount; - } - if (amountTillWrap >= amount) { - memcpy(data, &buffer[read[READ_PTR]], amount); - } else { - memcpy(data, &buffer[read[READ_PTR]], amountTillWrap); - memcpy(data + amountTillWrap, buffer, amount - amountTillWrap); - } - return HasReturnvaluesIF::RETURN_OK; -} - -ReturnValue_t SimpleRingBuffer::deleteData(uint32_t amount, - bool deleteRemaining, uint32_t* trueAmount) { - uint32_t availableData = availableReadData(READ_PTR); - if (availableData < amount) { - if (deleteRemaining) { - amount = availableData; - } else { - return HasReturnvaluesIF::RETURN_FAILED; - } - } - if (trueAmount != NULL) { - *trueAmount = amount; - } - incrementRead(amount, READ_PTR); - return HasReturnvaluesIF::RETURN_OK; -} +#include "../container/SimpleRingBuffer.h" +#include + +SimpleRingBuffer::SimpleRingBuffer(const size_t size, bool overwriteOld, + size_t maxExcessBytes) : + RingBufferBase<>(0, size, overwriteOld), + maxExcessBytes(maxExcessBytes) { + if(maxExcessBytes > size) { + this->maxExcessBytes = size; + } + else { + this->maxExcessBytes = maxExcessBytes; + } + buffer = new uint8_t[size + maxExcessBytes]; +} + +SimpleRingBuffer::SimpleRingBuffer(uint8_t *buffer, const size_t size, + bool overwriteOld, size_t maxExcessBytes): + RingBufferBase<>(0, size, overwriteOld), buffer(buffer) { + if(maxExcessBytes > size) { + this->maxExcessBytes = size; + } + else { + this->maxExcessBytes = maxExcessBytes; + } +} + + +SimpleRingBuffer::~SimpleRingBuffer() { + delete[] buffer; +} + + +ReturnValue_t SimpleRingBuffer::getFreeElement(uint8_t **writePointer, + size_t amount) { + if (availableWriteSpace() >= amount or overwriteOld) { + size_t amountTillWrap = writeTillWrap(); + if (amountTillWrap < amount) { + if((amount - amountTillWrap + excessBytes) > maxExcessBytes) { + return HasReturnvaluesIF::RETURN_FAILED; + } + excessBytes = amount - amountTillWrap; + } + *writePointer = &buffer[write]; + return HasReturnvaluesIF::RETURN_OK; + } + else { + return HasReturnvaluesIF::RETURN_FAILED; + } +} + +void SimpleRingBuffer::confirmBytesWritten(size_t amount) { + if(getExcessBytes() > 0) { + moveExcessBytesToStart(); + } + incrementWrite(amount); + +} + +ReturnValue_t SimpleRingBuffer::writeData(const uint8_t* data, + size_t amount) { + if (availableWriteSpace() >= amount or overwriteOld) { + size_t amountTillWrap = writeTillWrap(); + if (amountTillWrap >= amount) { + // remaining size in buffer is sufficient to fit full amount. + memcpy(&buffer[write], data, amount); + } + else { + memcpy(&buffer[write], data, amountTillWrap); + memcpy(buffer, data + amountTillWrap, amount - amountTillWrap); + } + incrementWrite(amount); + return HasReturnvaluesIF::RETURN_OK; + } else { + return HasReturnvaluesIF::RETURN_FAILED; + } +} + +ReturnValue_t SimpleRingBuffer::readData(uint8_t* data, size_t amount, + bool incrementReadPtr, bool readRemaining, size_t* trueAmount) { + size_t availableData = getAvailableReadData(READ_PTR); + size_t amountTillWrap = readTillWrap(READ_PTR); + if (availableData < amount) { + if (readRemaining) { + // more data available than amount specified. + amount = availableData; + } else { + return HasReturnvaluesIF::RETURN_FAILED; + } + } + if (trueAmount != nullptr) { + *trueAmount = amount; + } + if (amountTillWrap >= amount) { + memcpy(data, &buffer[read[READ_PTR]], amount); + } else { + memcpy(data, &buffer[read[READ_PTR]], amountTillWrap); + memcpy(data + amountTillWrap, buffer, amount - amountTillWrap); + } + + if(incrementReadPtr) { + deleteData(amount, readRemaining); + } + return HasReturnvaluesIF::RETURN_OK; +} + +size_t SimpleRingBuffer::getExcessBytes() const { + return excessBytes; +} + +void SimpleRingBuffer::moveExcessBytesToStart() { + if(excessBytes > 0) { + std::memcpy(buffer, &buffer[size], excessBytes); + excessBytes = 0; + } +} + +ReturnValue_t SimpleRingBuffer::deleteData(size_t amount, + bool deleteRemaining, size_t* trueAmount) { + size_t availableData = getAvailableReadData(READ_PTR); + if (availableData < amount) { + if (deleteRemaining) { + amount = availableData; + } else { + return HasReturnvaluesIF::RETURN_FAILED; + } + } + if (trueAmount != nullptr) { + *trueAmount = amount; + } + incrementRead(amount, READ_PTR); + return HasReturnvaluesIF::RETURN_OK; +} + + diff --git a/container/SimpleRingBuffer.h b/container/SimpleRingBuffer.h index 5d4fecab..b13e9f2a 100644 --- a/container/SimpleRingBuffer.h +++ b/container/SimpleRingBuffer.h @@ -1,21 +1,128 @@ -#ifndef FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_ -#define FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_ - -#include "RingBufferBase.h" -#include - -class SimpleRingBuffer: public RingBufferBase<> { -public: - SimpleRingBuffer(uint32_t size, bool overwriteOld); - virtual ~SimpleRingBuffer(); - ReturnValue_t writeData(const uint8_t* data, uint32_t amount); - ReturnValue_t readData(uint8_t* data, uint32_t amount, bool readRemaining = false, uint32_t* trueAmount = NULL); - ReturnValue_t deleteData(uint32_t amount, bool deleteRemaining = false, uint32_t* trueAmount = NULL); -private: -// static const uint8_t TEMP_READ_PTR = 1; - static const uint8_t READ_PTR = 0; - uint8_t* buffer; -}; - -#endif /* FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_ */ - +#ifndef FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_ +#define FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_ + +#include "../container/RingBufferBase.h" +#include + +/** + * @brief Circular buffer implementation, useful for buffering + * into data streams. + * @details + * Note that the deleteData() has to be called to increment the read pointer. + * This class allocated dynamically, so + * @ingroup containers + */ +class SimpleRingBuffer: public RingBufferBase<> { +public: + /** + * This constructor allocates a new internal buffer with the supplied size. + * + * @param size + * @param overwriteOld If the ring buffer is overflowing at a write + * operation, the oldest data will be overwritten. + * @param maxExcessBytes These additional bytes will be allocated in addtion + * to the specified size to accomodate contiguous write operations + * with getFreeElement. + * + */ + SimpleRingBuffer(const size_t size, bool overwriteOld, + size_t maxExcessBytes = 0); + /** + * This constructor takes an external buffer with the specified size. + * @param buffer + * @param size + * @param overwriteOld + * If the ring buffer is overflowing at a write operartion, the oldest data + * will be overwritten. + * @param maxExcessBytes + * If the buffer can accomodate additional bytes for contigous write + * operations with getFreeElement, this is the maximum allowed additional + * size + */ + SimpleRingBuffer(uint8_t* buffer, const size_t size, bool overwriteOld, + size_t maxExcessBytes = 0); + + virtual ~SimpleRingBuffer(); + + /** + * Write to circular buffer and increment write pointer by amount. + * @param data + * @param amount + * @return -@c RETURN_OK if write operation was successfull + * -@c RETURN_FAILED if + */ + ReturnValue_t writeData(const uint8_t* data, size_t amount); + + /** + * Returns a pointer to a free element. If the remaining buffer is + * not large enough, the data will be written past the actual size + * and the amount of excess bytes will be cached. This function + * does not increment the write pointer! + * @param writePointer Pointer to a pointer which can be used to write + * contiguous blocks into the ring buffer + * @param amount + * @return + */ + ReturnValue_t getFreeElement(uint8_t** writePointer, size_t amount); + + /** + * This increments the write pointer and also copies the excess bytes + * to the beginning. It should be called if the write operation + * conducted after calling getFreeElement() was performed. + * @return + */ + void confirmBytesWritten(size_t amount); + + virtual size_t getExcessBytes() const; + /** + * Helper functions which moves any excess bytes to the start + * of the ring buffer. + * @return + */ + virtual void moveExcessBytesToStart(); + + /** + * Read from circular buffer at read pointer. + * @param data + * @param amount + * @param incrementReadPtr + * If this is set to true, the read pointer will be incremented. + * If readRemaining is set to true, the read pointer will be incremented + * accordingly. + * @param readRemaining + * If this is set to true, the data will be read even if the amount + * specified exceeds the read data available. + * @param trueAmount [out] + * If readRemaining was set to true, the true amount read will be assigned + * to the passed value. + * @return + * - @c RETURN_OK if data was read successfully + * - @c RETURN_FAILED if not enough data was available and readRemaining + * was set to false. + */ + ReturnValue_t readData(uint8_t* data, size_t amount, + bool incrementReadPtr = false, bool readRemaining = false, + size_t* trueAmount = nullptr); + + /** + * Delete data by incrementing read pointer. + * @param amount + * @param deleteRemaining + * If the amount specified is larger than the remaing size to read and this + * is set to true, the remaining amount will be deleted as well + * @param trueAmount [out] + * If deleteRemaining was set to true, the amount deleted will be assigned + * to the passed value. + * @return + */ + ReturnValue_t deleteData(size_t amount, bool deleteRemaining = false, + size_t* trueAmount = nullptr); +private: + static const uint8_t READ_PTR = 0; + uint8_t* buffer = nullptr; + size_t maxExcessBytes; + size_t excessBytes = 0; +}; + +#endif /* FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_ */ + From 84d99a6f04b5ccd6d544c6e633247e0d10bb1fd7 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 24 Aug 2020 14:56:50 +0200 Subject: [PATCH 016/101] added brackets for boolean expressions --- container/SimpleRingBuffer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/container/SimpleRingBuffer.cpp b/container/SimpleRingBuffer.cpp index 7ed019b2..2a19d619 100644 --- a/container/SimpleRingBuffer.cpp +++ b/container/SimpleRingBuffer.cpp @@ -33,7 +33,7 @@ SimpleRingBuffer::~SimpleRingBuffer() { ReturnValue_t SimpleRingBuffer::getFreeElement(uint8_t **writePointer, size_t amount) { - if (availableWriteSpace() >= amount or overwriteOld) { + if ((availableWriteSpace() >= amount) or overwriteOld) { size_t amountTillWrap = writeTillWrap(); if (amountTillWrap < amount) { if((amount - amountTillWrap + excessBytes) > maxExcessBytes) { @@ -59,7 +59,7 @@ void SimpleRingBuffer::confirmBytesWritten(size_t amount) { ReturnValue_t SimpleRingBuffer::writeData(const uint8_t* data, size_t amount) { - if (availableWriteSpace() >= amount or overwriteOld) { + if ((availableWriteSpace() >= amount) or overwriteOld) { size_t amountTillWrap = writeTillWrap(); if (amountTillWrap >= amount) { // remaining size in buffer is sufficient to fit full amount. From 3001911d69522c3fb44a2483c25d129e6cfef98e Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 25 Aug 2020 14:00:27 +0200 Subject: [PATCH 017/101] taken over interface changes --- storagemanager/ConstStorageAccessor.cpp | 174 ++++++------ storagemanager/ConstStorageAccessor.h | 232 ++++++++-------- storagemanager/StorageAccessor.cpp | 134 +++++----- storagemanager/StorageAccessor.h | 89 +++---- storagemanager/StorageManagerIF.h | 335 ++++++++++++------------ 5 files changed, 482 insertions(+), 482 deletions(-) diff --git a/storagemanager/ConstStorageAccessor.cpp b/storagemanager/ConstStorageAccessor.cpp index 0bfde58c..ea9f2e44 100644 --- a/storagemanager/ConstStorageAccessor.cpp +++ b/storagemanager/ConstStorageAccessor.cpp @@ -1,87 +1,87 @@ -#include -#include -#include -#include - -ConstStorageAccessor::ConstStorageAccessor(store_address_t storeId): - storeId(storeId) {} - -ConstStorageAccessor::ConstStorageAccessor(store_address_t storeId, - StorageManagerIF* store): - storeId(storeId), store(store) { - internalState = AccessState::ASSIGNED; -} - -ConstStorageAccessor::~ConstStorageAccessor() { - if(deleteData and store != nullptr) { - sif::debug << "deleting store data" << std::endl; - store->deleteData(storeId); - } -} - -ConstStorageAccessor::ConstStorageAccessor(ConstStorageAccessor&& other): - constDataPointer(other.constDataPointer), storeId(other.storeId), - size_(other.size_), store(other.store), deleteData(other.deleteData), - internalState(other.internalState) { - // This prevent premature deletion - other.store = nullptr; -} - -ConstStorageAccessor& ConstStorageAccessor::operator=( - ConstStorageAccessor&& other) { - constDataPointer = other.constDataPointer; - storeId = other.storeId; - store = other.store; - size_ = other.size_; - deleteData = other.deleteData; - this->store = other.store; - // This prevents premature deletion - other.store = nullptr; - return *this; -} - -const uint8_t* ConstStorageAccessor::data() const { - return constDataPointer; -} - -size_t ConstStorageAccessor::size() const { - if(internalState == AccessState::UNINIT) { - sif::warning << "StorageAccessor: Not initialized!" << std::endl; - } - return size_; -} - -ReturnValue_t ConstStorageAccessor::getDataCopy(uint8_t *pointer, - size_t maxSize) { - if(internalState == AccessState::UNINIT) { - sif::warning << "StorageAccessor: Not initialized!" << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; - } - if(size_ > maxSize) { - sif::error << "StorageAccessor: Supplied buffer not large enough" << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; - } - std::copy(constDataPointer, constDataPointer + size_, pointer); - return HasReturnvaluesIF::RETURN_OK; -} - -void ConstStorageAccessor::release() { - deleteData = false; -} - -store_address_t ConstStorageAccessor::getId() const { - return storeId; -} - -void ConstStorageAccessor::print() const { - if(internalState == AccessState::UNINIT or constDataPointer == nullptr) { - sif::warning << "StorageAccessor: Not initialized!" << std::endl; - return; - } - arrayprinter::print(constDataPointer, size_); -} - -void ConstStorageAccessor::assignStore(StorageManagerIF* store) { - internalState = AccessState::ASSIGNED; - this->store = store; -} +#include "../serviceinterface/ServiceInterfaceStream.h" +#include "../storagemanager/ConstStorageAccessor.h" +#include "../storagemanager/StorageManagerIF.h" +#include "../globalfunctions/arrayprinter.h" + +ConstStorageAccessor::ConstStorageAccessor(store_address_t storeId): + storeId(storeId) {} + +ConstStorageAccessor::ConstStorageAccessor(store_address_t storeId, + StorageManagerIF* store): + storeId(storeId), store(store) { + internalState = AccessState::ASSIGNED; +} + +ConstStorageAccessor::~ConstStorageAccessor() { + if(deleteData and store != nullptr) { + sif::debug << "deleting store data" << std::endl; + store->deleteData(storeId); + } +} + +ConstStorageAccessor::ConstStorageAccessor(ConstStorageAccessor&& other): + constDataPointer(other.constDataPointer), storeId(other.storeId), + size_(other.size_), store(other.store), deleteData(other.deleteData), + internalState(other.internalState) { + // This prevent premature deletion + other.store = nullptr; +} + +ConstStorageAccessor& ConstStorageAccessor::operator=( + ConstStorageAccessor&& other) { + constDataPointer = other.constDataPointer; + storeId = other.storeId; + store = other.store; + size_ = other.size_; + deleteData = other.deleteData; + this->store = other.store; + // This prevents premature deletion + other.store = nullptr; + return *this; +} + +const uint8_t* ConstStorageAccessor::data() const { + return constDataPointer; +} + +size_t ConstStorageAccessor::size() const { + if(internalState == AccessState::UNINIT) { + sif::warning << "StorageAccessor: Not initialized!" << std::endl; + } + return size_; +} + +ReturnValue_t ConstStorageAccessor::getDataCopy(uint8_t *pointer, + size_t maxSize) { + if(internalState == AccessState::UNINIT) { + sif::warning << "StorageAccessor: Not initialized!" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + if(size_ > maxSize) { + sif::error << "StorageAccessor: Supplied buffer not large enough" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + std::copy(constDataPointer, constDataPointer + size_, pointer); + return HasReturnvaluesIF::RETURN_OK; +} + +void ConstStorageAccessor::release() { + deleteData = false; +} + +store_address_t ConstStorageAccessor::getId() const { + return storeId; +} + +void ConstStorageAccessor::print() const { + if(internalState == AccessState::UNINIT or constDataPointer == nullptr) { + sif::warning << "StorageAccessor: Not initialized!" << std::endl; + return; + } + arrayprinter::print(constDataPointer, size_); +} + +void ConstStorageAccessor::assignStore(StorageManagerIF* store) { + internalState = AccessState::ASSIGNED; + this->store = store; +} diff --git a/storagemanager/ConstStorageAccessor.h b/storagemanager/ConstStorageAccessor.h index bb003f55..ec2da8ce 100644 --- a/storagemanager/ConstStorageAccessor.h +++ b/storagemanager/ConstStorageAccessor.h @@ -1,116 +1,116 @@ -#ifndef FRAMEWORK_STORAGEMANAGER_CONSTSTORAGEACCESSOR_H_ -#define FRAMEWORK_STORAGEMANAGER_CONSTSTORAGEACCESSOR_H_ - -#include "storeAddress.h" -#include "../returnvalues/HasReturnvaluesIF.h" -#include - -class StorageManagerIF; - -/** - * @brief Helper classes to facilitate safe access to storages which is also - * conforming to RAII principles - * @details - * Accessor class which can be returned by pool manager or passed and set by - * pool managers to have safe access to the pool resources. - * - * These helper can be used together with the StorageManager classes to manage - * access to a storage. It can take care of thread-safety while also providing - * mechanisms to automatically clear storage data. - */ -class ConstStorageAccessor { - //! StorageManager classes have exclusive access to private variables. - template - friend class PoolManager; - template - friend class LocalPool; -public: - /** - * @brief Simple constructor which takes the store ID of the storage - * entry to access. - * @param storeId - */ - ConstStorageAccessor(store_address_t storeId); - ConstStorageAccessor(store_address_t storeId, StorageManagerIF* store); - - /** - * @brief The destructor in default configuration takes care of - * deleting the accessed pool entry and unlocking the mutex - */ - virtual ~ConstStorageAccessor(); - - /** - * @brief Returns a pointer to the read-only data - * @return - */ - const uint8_t* data() const; - - /** - * @brief Copies the read-only data to the supplied pointer - * @param pointer - */ - virtual ReturnValue_t getDataCopy(uint8_t *pointer, size_t maxSize); - - /** - * @brief Calling this will prevent the Accessor from deleting the data - * when the destructor is called. - */ - void release(); - - /** - * Get the size of the data - * @return - */ - size_t size() const; - - /** - * Get the storage ID. - * @return - */ - store_address_t getId() const; - - void print() const; - - /** - * @brief Move ctor and move assignment allow returning accessors as - * a returnvalue. They prevent resource being free prematurely. - * Refer to: https://github.com/MicrosoftDocs/cpp-docs/blob/master/docs/cpp/ - * move-constructors-and-move-assignment-operators-cpp.md - * @param - * @return - */ - ConstStorageAccessor& operator= (ConstStorageAccessor&&); - ConstStorageAccessor (ConstStorageAccessor&&); - - //! The copy ctor and copy assignemnt should be deleted implicitely - //! according to https://foonathan.net/2019/02/special-member-functions/ - //! but I still deleted them to make it more explicit. (remember rule of 5). - ConstStorageAccessor& operator= (ConstStorageAccessor&) = delete; - ConstStorageAccessor (ConstStorageAccessor&) = delete; -protected: - const uint8_t* constDataPointer = nullptr; - store_address_t storeId; - size_t size_ = 0; - //! Managing pool, has to assign itself. - StorageManagerIF* store = nullptr; - bool deleteData = true; - - enum class AccessState { - UNINIT, - ASSIGNED - }; - //! Internal state for safety reasons. - AccessState internalState = AccessState::UNINIT; - /** - * Used by the pool manager instances to assign themselves to the - * accessor. This is necessary to delete the data when the acessor - * exits the scope ! The internal state will be considered read - * when this function is called, so take care all data is set properly as - * well. - * @param - */ - void assignStore(StorageManagerIF*); -}; - - -#endif /* FRAMEWORK_STORAGEMANAGER_CONSTSTORAGEACCESSOR_H_ */ +#ifndef FRAMEWORK_STORAGEMANAGER_CONSTSTORAGEACCESSOR_H_ +#define FRAMEWORK_STORAGEMANAGER_CONSTSTORAGEACCESSOR_H_ + +#include "../storagemanager/storeAddress.h" +#include "../returnvalues/HasReturnvaluesIF.h" +#include + +class StorageManagerIF; + +/** + * @brief Helper classes to facilitate safe access to storages which is also + * conforming to RAII principles + * @details + * Accessor class which can be returned by pool manager or passed and set by + * pool managers to have safe access to the pool resources. + * + * These helper can be used together with the StorageManager classes to manage + * access to a storage. It can take care of thread-safety while also providing + * mechanisms to automatically clear storage data. + */ +class ConstStorageAccessor { + //! StorageManager classes have exclusive access to private variables. + template + friend class PoolManager; + template + friend class LocalPool; +public: + /** + * @brief Simple constructor which takes the store ID of the storage + * entry to access. + * @param storeId + */ + ConstStorageAccessor(store_address_t storeId); + ConstStorageAccessor(store_address_t storeId, StorageManagerIF* store); + + /** + * @brief The destructor in default configuration takes care of + * deleting the accessed pool entry and unlocking the mutex + */ + virtual ~ConstStorageAccessor(); + + /** + * @brief Returns a pointer to the read-only data + * @return + */ + const uint8_t* data() const; + + /** + * @brief Copies the read-only data to the supplied pointer + * @param pointer + */ + virtual ReturnValue_t getDataCopy(uint8_t *pointer, size_t maxSize); + + /** + * @brief Calling this will prevent the Accessor from deleting the data + * when the destructor is called. + */ + void release(); + + /** + * Get the size of the data + * @return + */ + size_t size() const; + + /** + * Get the storage ID. + * @return + */ + store_address_t getId() const; + + void print() const; + + /** + * @brief Move ctor and move assignment allow returning accessors as + * a returnvalue. They prevent resource being free prematurely. + * Refer to: https://github.com/MicrosoftDocs/cpp-docs/blob/master/docs/cpp/ + * move-constructors-and-move-assignment-operators-cpp.md + * @param + * @return + */ + ConstStorageAccessor& operator= (ConstStorageAccessor&&); + ConstStorageAccessor(ConstStorageAccessor&&); + + //! The copy ctor and copy assignemnt should be deleted implicitely + //! according to https://foonathan.net/2019/02/special-member-functions/ + //! but I still deleted them to make it more explicit. (remember rule of 5). + ConstStorageAccessor& operator=(const ConstStorageAccessor&) = delete; + ConstStorageAccessor(const ConstStorageAccessor&) = delete; +protected: + const uint8_t* constDataPointer = nullptr; + store_address_t storeId; + size_t size_ = 0; + //! Managing pool, has to assign itself. + StorageManagerIF* store = nullptr; + bool deleteData = true; + + enum class AccessState { + UNINIT, + ASSIGNED + }; + //! Internal state for safety reasons. + AccessState internalState = AccessState::UNINIT; + /** + * Used by the pool manager instances to assign themselves to the + * accessor. This is necessary to delete the data when the acessor + * exits the scope ! The internal state will be considered read + * when this function is called, so take care all data is set properly as + * well. + * @param + */ + void assignStore(StorageManagerIF*); +}; + + +#endif /* FRAMEWORK_STORAGEMANAGER_CONSTSTORAGEACCESSOR_H_ */ diff --git a/storagemanager/StorageAccessor.cpp b/storagemanager/StorageAccessor.cpp index 9c2f936a..d4d2a54d 100644 --- a/storagemanager/StorageAccessor.cpp +++ b/storagemanager/StorageAccessor.cpp @@ -1,67 +1,67 @@ -#include "StorageAccessor.h" -#include "StorageManagerIF.h" -#include "../serviceinterface/ServiceInterfaceStream.h" - -StorageAccessor::StorageAccessor(store_address_t storeId): - ConstStorageAccessor(storeId) { -} - -StorageAccessor::StorageAccessor(store_address_t storeId, - StorageManagerIF* store): - ConstStorageAccessor(storeId, store) { -} - -StorageAccessor& StorageAccessor::operator =( - StorageAccessor&& other) { - // Call the parent move assignment and also assign own member. - dataPointer = other.dataPointer; - StorageAccessor::operator=(std::move(other)); - return * this; -} - -// Call the parent move ctor and also transfer own member. -StorageAccessor::StorageAccessor(StorageAccessor&& other): - ConstStorageAccessor(std::move(other)), dataPointer(other.dataPointer) { -} - -ReturnValue_t StorageAccessor::getDataCopy(uint8_t *pointer, size_t maxSize) { - if(internalState == AccessState::UNINIT) { - sif::warning << "StorageAccessor: Not initialized!" << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; - } - if(size_ > maxSize) { - sif::error << "StorageAccessor: Supplied buffer not large " - "enough" << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; - } - std::copy(dataPointer, dataPointer + size_, pointer); - return HasReturnvaluesIF::RETURN_OK; -} - -uint8_t* StorageAccessor::data() { - if(internalState == AccessState::UNINIT) { - sif::warning << "StorageAccessor: Not initialized!" << std::endl; - } - return dataPointer; -} - -ReturnValue_t StorageAccessor::write(uint8_t *data, size_t size, - uint16_t offset) { - if(internalState == AccessState::UNINIT) { - sif::warning << "StorageAccessor: Not initialized!" << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; - } - if(offset + size > size_) { - sif::error << "StorageAccessor: Data too large for pool " - "entry!" << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; - } - std::copy(data, data + size, dataPointer + offset); - return HasReturnvaluesIF::RETURN_OK; -} - -void StorageAccessor::assignConstPointer() { - constDataPointer = dataPointer; -} - - +#include "../storagemanager/StorageAccessor.h" +#include "../storagemanager/StorageManagerIF.h" +#include "../serviceinterface/ServiceInterfaceStream.h" + +StorageAccessor::StorageAccessor(store_address_t storeId): + ConstStorageAccessor(storeId) { +} + +StorageAccessor::StorageAccessor(store_address_t storeId, + StorageManagerIF* store): + ConstStorageAccessor(storeId, store) { +} + +StorageAccessor& StorageAccessor::operator =( + StorageAccessor&& other) { + // Call the parent move assignment and also assign own member. + dataPointer = other.dataPointer; + StorageAccessor::operator=(std::move(other)); + return * this; +} + +// Call the parent move ctor and also transfer own member. +StorageAccessor::StorageAccessor(StorageAccessor&& other): + ConstStorageAccessor(std::move(other)), dataPointer(other.dataPointer) { +} + +ReturnValue_t StorageAccessor::getDataCopy(uint8_t *pointer, size_t maxSize) { + if(internalState == AccessState::UNINIT) { + sif::warning << "StorageAccessor: Not initialized!" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + if(size_ > maxSize) { + sif::error << "StorageAccessor: Supplied buffer not large " + "enough" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + std::copy(dataPointer, dataPointer + size_, pointer); + return HasReturnvaluesIF::RETURN_OK; +} + +uint8_t* StorageAccessor::data() { + if(internalState == AccessState::UNINIT) { + sif::warning << "StorageAccessor: Not initialized!" << std::endl; + } + return dataPointer; +} + +ReturnValue_t StorageAccessor::write(uint8_t *data, size_t size, + uint16_t offset) { + if(internalState == AccessState::UNINIT) { + sif::warning << "StorageAccessor: Not initialized!" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + if(offset + size > size_) { + sif::error << "StorageAccessor: Data too large for pool " + "entry!" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + std::copy(data, data + size, dataPointer + offset); + return HasReturnvaluesIF::RETURN_OK; +} + +void StorageAccessor::assignConstPointer() { + constDataPointer = dataPointer; +} + + diff --git a/storagemanager/StorageAccessor.h b/storagemanager/StorageAccessor.h index 5cdd82a7..1ca5f7dd 100644 --- a/storagemanager/StorageAccessor.h +++ b/storagemanager/StorageAccessor.h @@ -1,44 +1,45 @@ -#ifndef FRAMEWORK_STORAGEMANAGER_STORAGEACCESSOR_H_ -#define FRAMEWORK_STORAGEMANAGER_STORAGEACCESSOR_H_ - -#include "ConstStorageAccessor.h" - -class StorageManagerIF; - -/** - * @brief Child class for modifyable data. Also has a normal pointer member. - */ -class StorageAccessor: public ConstStorageAccessor { - //! StorageManager classes have exclusive access to private variables. - template - friend class PoolManager; - template - friend class LocalPool; -public: - StorageAccessor(store_address_t storeId); - StorageAccessor(store_address_t storeId, StorageManagerIF* store); - /** - * @brief Move ctor and move assignment allow returning accessors as - * a returnvalue. They prevent resource being free prematurely. - * Refer to: https://github.com/MicrosoftDocs/cpp-docs/blob/master/docs/cpp/ - * move-constructors-and-move-assignment-operators-cpp.md - * @param - * @return - */ - StorageAccessor& operator= (StorageAccessor&&); - StorageAccessor (StorageAccessor&&); - - ReturnValue_t write(uint8_t *data, size_t size, - uint16_t offset = 0); - uint8_t* data(); - ReturnValue_t getDataCopy(uint8_t *pointer, size_t maxSize) override; - -private: - //! Non-const pointer for modifyable data. - uint8_t* dataPointer = nullptr; - //! For modifyable data, the const pointer is assigned to the normal - //! pointer by the pool manager so both access functions can be used safely - void assignConstPointer(); -}; - -#endif /* TEST_PROTOTYPES_STORAGEACCESSOR_H_ */ +#ifndef FRAMEWORK_STORAGEMANAGER_STORAGEACCESSOR_H_ +#define FRAMEWORK_STORAGEMANAGER_STORAGEACCESSOR_H_ + +#include "../storagemanager/ConstStorageAccessor.h" + +class StorageManagerIF; + +/** + * @brief Child class for modifyable data. Also has a normal pointer member. + */ +class StorageAccessor: public ConstStorageAccessor { + //! StorageManager classes have exclusive access to private variables. + template + friend class PoolManager; + template + friend class LocalPool; +public: + StorageAccessor(store_address_t storeId); + StorageAccessor(store_address_t storeId, StorageManagerIF* store); + + /** + * @brief Move ctor and move assignment allow returning accessors as + * a returnvalue. They prevent resource being freed prematurely. + * See: https://github.com/MicrosoftDocs/cpp-docs/blob/master/docs/cpp/ + * move-constructors-and-move-assignment-operators-cpp.md + * @param + * @return + */ + StorageAccessor& operator=(StorageAccessor&&); + StorageAccessor(StorageAccessor&&); + + ReturnValue_t write(uint8_t *data, size_t size, + uint16_t offset = 0); + uint8_t* data(); + ReturnValue_t getDataCopy(uint8_t *pointer, size_t maxSize) override; + +private: + //! Non-const pointer for modifyable data. + uint8_t* dataPointer = nullptr; + //! For modifyable data, the const pointer is assigned to the normal + //! pointer by the pool manager so both access functions can be used safely + void assignConstPointer(); +}; + +#endif /* TEST_PROTOTYPES_STORAGEACCESSOR_H_ */ diff --git a/storagemanager/StorageManagerIF.h b/storagemanager/StorageManagerIF.h index a36a714a..85341f2e 100644 --- a/storagemanager/StorageManagerIF.h +++ b/storagemanager/StorageManagerIF.h @@ -1,168 +1,167 @@ -#ifndef STORAGEMANAGERIF_H_H -#define STORAGEMANAGERIF_H_H - - -#include "../events/Event.h" -#include "../returnvalues/HasReturnvaluesIF.h" -#include "../storagemanager/StorageAccessor.h" -#include "../storagemanager/storeAddress.h" -#include -#include - -using AccessorPair = std::pair; -using ConstAccessorPair = std::pair; - -/** - * @brief This class provides an interface for intermediate data storage. - * @details The Storage manager classes shall be used to store larger chunks of - * data in RAM for exchange between tasks. This interface expects the - * data to be stored in one consecutive block of memory, so tasks can - * write directly to the destination pointer. - * For interprocess communication, the stores must be locked during - * insertion and deletion. If the receiving storage identifier is - * passed token-like between tasks, a lock during read and write - * operations is not necessary. - * @author Bastian Baetz - * @date 18.09.2012 - */ -class StorageManagerIF : public HasReturnvaluesIF { -public: - static const uint8_t INTERFACE_ID = CLASS_ID::STORAGE_MANAGER_IF; //!< The unique ID for return codes for this interface. - static const ReturnValue_t DATA_TOO_LARGE = MAKE_RETURN_CODE(1); //!< This return code indicates that the data to be stored is too large for the store. - static const ReturnValue_t DATA_STORAGE_FULL = MAKE_RETURN_CODE(2); //!< This return code indicates that a data storage is full. - static const ReturnValue_t ILLEGAL_STORAGE_ID = MAKE_RETURN_CODE(3); //!< This return code indicates that data was requested with an illegal storage ID. - static const ReturnValue_t DATA_DOES_NOT_EXIST = MAKE_RETURN_CODE(4); //!< This return code indicates that the requested ID was valid, but no data is stored there. - static const ReturnValue_t ILLEGAL_ADDRESS = MAKE_RETURN_CODE(5); - static const ReturnValue_t POOL_TOO_LARGE = MAKE_RETURN_CODE(6); //!< Pool size too large on initialization. - - static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::OBSW; - static const Event GET_DATA_FAILED = MAKE_EVENT(0, SEVERITY::LOW); - static const Event STORE_DATA_FAILED = MAKE_EVENT(1, SEVERITY::LOW); - - static const uint32_t INVALID_ADDRESS = 0xFFFFFFFF; //!< Indicates an invalid (i.e unused) storage address. - /** - * @brief This is the empty virtual destructor as required for C++ interfaces. - */ - virtual ~StorageManagerIF() { - } - ; - /** - * @brief With addData, a free storage position is allocated and data - * stored there. - * @details During the allocation, the StorageManager is blocked. - * @param storageId A pointer to the storageId to retrieve. - * @param data The data to be stored in the StorageManager. - * @param size The amount of data to be stored. - * @return Returns @li RETURN_OK if data was added. - * @li RETURN_FAILED if data could not be added. - * storageId is unchanged then. - */ - virtual ReturnValue_t addData(store_address_t* storageId, - const uint8_t * data, size_t size, bool ignoreFault = false) = 0; - /** - * @brief With deleteData, the storageManager frees the memory region - * identified by packet_id. - * @param packet_id The identifier of the memory region to be freed. - * @return @li RETURN_OK on success. - * @li RETURN_FAILED if deletion did not work - * (e.g. an illegal packet_id was passed). - */ - virtual ReturnValue_t deleteData(store_address_t packet_id) = 0; - /** - * @brief Another deleteData which uses the pointer and size of the - * stored data to delete the content. - * @param buffer Pointer to the data. - * @param size Size of data to be stored. - * @param storeId Store id of the deleted element (optional) - * @return @li RETURN_OK on success. - * @li failure code if deletion did not work - */ - virtual ReturnValue_t deleteData(uint8_t* buffer, size_t size, - store_address_t* storeId = nullptr) = 0; - - - /** - * @brief Access the data by supplying a store ID. - * @details - * A pair consisting of the retrieval result and an instance of a - * ConstStorageAccessor class is returned - * @param storeId - * @return Pair of return value and a ConstStorageAccessor instance - */ - virtual ConstAccessorPair getData(store_address_t storeId) = 0; - - /** - * @brief Access the data by supplying a store ID and a helper - * instance - * @param storeId - * @param constAccessor Wrapper function to access store data. - * @return - */ - virtual ReturnValue_t getData(store_address_t storeId, - ConstStorageAccessor& constAccessor) = 0; - - - /** - * @brief getData returns an address to data and the size of the data - * for a given packet_id. - * @param packet_id The id of the data to be returned - * @param packet_ptr The passed pointer address is set to the the memory - * position - * @param size The exact size of the stored data is returned here. - * @return @li RETURN_OK on success. - * @li RETURN_FAILED if fetching data did not work - * (e.g. an illegal packet_id was passed). - */ - virtual ReturnValue_t getData(store_address_t packet_id, - const uint8_t** packet_ptr, size_t* size) = 0; - - - /** - * Modify data by supplying a store ID - * @param storeId - * @return Pair of return value and StorageAccessor helper - */ - virtual AccessorPair modifyData(store_address_t storeId) = 0; - - /** - * Modify data by supplying a store ID and a StorageAccessor helper instance. - * @param storeId - * @param accessor Helper class to access the modifiable data. - * @return - */ - virtual ReturnValue_t modifyData(store_address_t storeId, - StorageAccessor& accessor) = 0; - - /** - * Get pointer and size of modifiable data by supplying the storeId - * @param packet_id - * @param packet_ptr [out] Pointer to pointer of data to set - * @param size [out] Pointer to size to set - * @return - */ - virtual ReturnValue_t modifyData(store_address_t packet_id, - uint8_t** packet_ptr, size_t* size) = 0; - /** - * This method reserves an element of \c size. - * - * It returns the packet id of this element as well as a direct pointer to the - * data of the element. It must be assured that exactly \c size data is - * written to p_data! - * @param storageId A pointer to the storageId to retrieve. - * @param size The size of the space to be reserved. - * @param p_data A pointer to the element data is returned here. - * @return Returns @li RETURN_OK if data was added. - * @li RETURN_FAILED if data could not be added. - * storageId is unchanged then. - */ - virtual ReturnValue_t getFreeElement(store_address_t* storageId, - const size_t size, uint8_t** p_data, bool ignoreFault = false ) = 0; - - /** - * Clears the whole store. - * Use with care! - */ - virtual void clearStore() = 0; -}; - -#endif /* STORAGEMANAGERIF_H_ */ +#ifndef STORAGEMANAGERIF_H_H +#define STORAGEMANAGERIF_H_H + +#include "../events/Event.h" +#include "../returnvalues/HasReturnvaluesIF.h" +#include "../storagemanager/StorageAccessor.h" +#include "../storagemanager/storeAddress.h" +#include +#include + +using AccessorPair = std::pair; +using ConstAccessorPair = std::pair; + +/** + * @brief This class provides an interface for intermediate data storage. + * @details The Storage manager classes shall be used to store larger chunks of + * data in RAM for exchange between tasks. This interface expects the + * data to be stored in one consecutive block of memory, so tasks can + * write directly to the destination pointer. + * For interprocess communication, the stores must be locked during + * insertion and deletion. If the receiving storage identifier is + * passed token-like between tasks, a lock during read and write + * operations is not necessary. + * @author Bastian Baetz + * @date 18.09.2012 + */ +class StorageManagerIF : public HasReturnvaluesIF { +public: + static const uint8_t INTERFACE_ID = CLASS_ID::STORAGE_MANAGER_IF; //!< The unique ID for return codes for this interface. + static const ReturnValue_t DATA_TOO_LARGE = MAKE_RETURN_CODE(1); //!< This return code indicates that the data to be stored is too large for the store. + static const ReturnValue_t DATA_STORAGE_FULL = MAKE_RETURN_CODE(2); //!< This return code indicates that a data storage is full. + static const ReturnValue_t ILLEGAL_STORAGE_ID = MAKE_RETURN_CODE(3); //!< This return code indicates that data was requested with an illegal storage ID. + static const ReturnValue_t DATA_DOES_NOT_EXIST = MAKE_RETURN_CODE(4); //!< This return code indicates that the requested ID was valid, but no data is stored there. + static const ReturnValue_t ILLEGAL_ADDRESS = MAKE_RETURN_CODE(5); + static const ReturnValue_t POOL_TOO_LARGE = MAKE_RETURN_CODE(6); //!< Pool size too large on initialization. + + static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::OBSW; + static const Event GET_DATA_FAILED = MAKE_EVENT(0, SEVERITY::LOW); + static const Event STORE_DATA_FAILED = MAKE_EVENT(1, SEVERITY::LOW); + + static const uint32_t INVALID_ADDRESS = 0xFFFFFFFF; //!< Indicates an invalid (i.e unused) storage address. + /** + * @brief This is the empty virtual destructor as required for C++ interfaces. + */ + virtual ~StorageManagerIF() { + } + ; + /** + * @brief With addData, a free storage position is allocated and data + * stored there. + * @details During the allocation, the StorageManager is blocked. + * @param storageId A pointer to the storageId to retrieve. + * @param data The data to be stored in the StorageManager. + * @param size The amount of data to be stored. + * @return Returns @li RETURN_OK if data was added. + * @li RETURN_FAILED if data could not be added. + * storageId is unchanged then. + */ + virtual ReturnValue_t addData(store_address_t* storageId, + const uint8_t * data, size_t size, bool ignoreFault = false) = 0; + /** + * @brief With deleteData, the storageManager frees the memory region + * identified by packet_id. + * @param packet_id The identifier of the memory region to be freed. + * @return @li RETURN_OK on success. + * @li RETURN_FAILED if deletion did not work + * (e.g. an illegal packet_id was passed). + */ + virtual ReturnValue_t deleteData(store_address_t packet_id) = 0; + /** + * @brief Another deleteData which uses the pointer and size of the + * stored data to delete the content. + * @param buffer Pointer to the data. + * @param size Size of data to be stored. + * @param storeId Store id of the deleted element (optional) + * @return @li RETURN_OK on success. + * @li failure code if deletion did not work + */ + virtual ReturnValue_t deleteData(uint8_t* buffer, size_t size, + store_address_t* storeId = nullptr) = 0; + + + /** + * @brief Access the data by supplying a store ID. + * @details + * A pair consisting of the retrieval result and an instance of a + * ConstStorageAccessor class is returned + * @param storeId + * @return Pair of return value and a ConstStorageAccessor instance + */ + virtual ConstAccessorPair getData(store_address_t storeId) = 0; + + /** + * @brief Access the data by supplying a store ID and a helper + * instance + * @param storeId + * @param constAccessor Wrapper function to access store data. + * @return + */ + virtual ReturnValue_t getData(store_address_t storeId, + ConstStorageAccessor& constAccessor) = 0; + + + /** + * @brief getData returns an address to data and the size of the data + * for a given packet_id. + * @param packet_id The id of the data to be returned + * @param packet_ptr The passed pointer address is set to the the memory + * position + * @param size The exact size of the stored data is returned here. + * @return @li RETURN_OK on success. + * @li RETURN_FAILED if fetching data did not work + * (e.g. an illegal packet_id was passed). + */ + virtual ReturnValue_t getData(store_address_t packet_id, + const uint8_t** packet_ptr, size_t* size) = 0; + + + /** + * Modify data by supplying a store ID + * @param storeId + * @return Pair of return value and StorageAccessor helper + */ + virtual AccessorPair modifyData(store_address_t storeId) = 0; + + /** + * Modify data by supplying a store ID and a StorageAccessor helper instance. + * @param storeId + * @param accessor Helper class to access the modifiable data. + * @return + */ + virtual ReturnValue_t modifyData(store_address_t storeId, + StorageAccessor& accessor) = 0; + + /** + * Get pointer and size of modifiable data by supplying the storeId + * @param packet_id + * @param packet_ptr [out] Pointer to pointer of data to set + * @param size [out] Pointer to size to set + * @return + */ + virtual ReturnValue_t modifyData(store_address_t packet_id, + uint8_t** packet_ptr, size_t* size) = 0; + /** + * This method reserves an element of \c size. + * + * It returns the packet id of this element as well as a direct pointer to the + * data of the element. It must be assured that exactly \c size data is + * written to p_data! + * @param storageId A pointer to the storageId to retrieve. + * @param size The size of the space to be reserved. + * @param p_data A pointer to the element data is returned here. + * @return Returns @li RETURN_OK if data was added. + * @li RETURN_FAILED if data could not be added. + * storageId is unchanged then. + */ + virtual ReturnValue_t getFreeElement(store_address_t* storageId, + const size_t size, uint8_t** p_data, bool ignoreFault = false ) = 0; + + /** + * Clears the whole store. + * Use with care! + */ + virtual void clearStore() = 0; +}; + +#endif /* STORAGEMANAGERIF_H_ */ From 3f9d9b8770561a1487302d3f61e3e07aa012899d Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 25 Aug 2020 18:24:46 +0200 Subject: [PATCH 018/101] ipc update --- devicehandlers/HealthDevice.cpp | 2 +- ipc/CommandMessage.cpp | 242 +++++++++++++--------------- ipc/CommandMessage.h | 263 +++++++++++++++---------------- ipc/CommandMessageCleaner.cpp | 45 ++++++ ipc/CommandMessageCleaner.h | 16 ++ ipc/CommandMessageIF.h | 73 +++++++++ ipc/MessageQueueMessage.cpp | 149 ++++++++++-------- ipc/MessageQueueMessage.h | 268 ++++++++++++++++++-------------- ipc/MessageQueueMessageIF.h | 91 +++++++++++ 9 files changed, 700 insertions(+), 449 deletions(-) create mode 100644 ipc/CommandMessageCleaner.cpp create mode 100644 ipc/CommandMessageCleaner.h create mode 100644 ipc/CommandMessageIF.h create mode 100644 ipc/MessageQueueMessageIF.h diff --git a/devicehandlers/HealthDevice.cpp b/devicehandlers/HealthDevice.cpp index 411731dc..b15e5d2b 100644 --- a/devicehandlers/HealthDevice.cpp +++ b/devicehandlers/HealthDevice.cpp @@ -5,7 +5,7 @@ HealthDevice::HealthDevice(object_id_t setObjectId, MessageQueueId_t parentQueue) : SystemObject(setObjectId), lastHealth(HEALTHY), parentQueue( parentQueue), commandQueue(), healthHelper(this, setObjectId) { - commandQueue = QueueFactory::instance()->createMessageQueue(3, CommandMessage::COMMAND_MESSAGE_SIZE); + commandQueue = QueueFactory::instance()->createMessageQueue(3); } HealthDevice::~HealthDevice() { diff --git a/ipc/CommandMessage.cpp b/ipc/CommandMessage.cpp index dbea8533..16293608 100644 --- a/ipc/CommandMessage.cpp +++ b/ipc/CommandMessage.cpp @@ -1,131 +1,111 @@ -/** - * @file CommandMessage.cpp - * @brief This file defines the CommandMessage class. - * @date 20.06.2013 - * @author baetz - */ - -#include "../devicehandlers/DeviceHandlerMessage.h" -#include "../health/HealthMessage.h" -#include "CommandMessage.h" -#include "../memory/MemoryMessage.h" -#include "../modes/ModeMessage.h" -#include "../monitoring/MonitoringMessage.h" -#include "../subsystem/modes/ModeSequenceMessage.h" -#include "../tmstorage/TmStoreMessage.h" -#include "../parameters/ParameterMessage.h" - -namespace messagetypes { -void clearMissionMessage(CommandMessage* message); -} - - -CommandMessage::CommandMessage() { - this->messageSize = COMMAND_MESSAGE_SIZE; - setCommand(CMD_NONE); -} - -CommandMessage::CommandMessage(Command_t command, uint32_t parameter1, - uint32_t parameter2) { - this->messageSize = COMMAND_MESSAGE_SIZE; - setCommand(command); - setParameter(parameter1); - setParameter2(parameter2); -} - -Command_t CommandMessage::getCommand() const { - Command_t command; - memcpy(&command, getData(), sizeof(Command_t)); - return command; -} - -void CommandMessage::setCommand(Command_t command) { - memcpy(getData(), &command, sizeof(command)); -} - -uint32_t CommandMessage::getParameter() const { - uint32_t parameter1; - memcpy(¶meter1, getData() + sizeof(Command_t), sizeof(parameter1)); - return parameter1; -} - -void CommandMessage::setParameter(uint32_t parameter1) { - memcpy(getData() + sizeof(Command_t), ¶meter1, sizeof(parameter1)); -} - -uint32_t CommandMessage::getParameter2() const { - uint32_t parameter2; - memcpy(¶meter2, getData() + sizeof(Command_t) + sizeof(uint32_t), - sizeof(parameter2)); - return parameter2; -} - -void CommandMessage::setParameter2(uint32_t parameter2) { - memcpy(getData() + sizeof(Command_t) + sizeof(uint32_t), ¶meter2, - sizeof(parameter2)); -} - -void CommandMessage::clearCommandMessage() { - switch((getCommand()>>8) & 0xff){ - case messagetypes::MODE_COMMAND: - ModeMessage::clear(this); - break; - case messagetypes::HEALTH_COMMAND: - HealthMessage::clear(this); - break; - case messagetypes::MODE_SEQUENCE: - ModeSequenceMessage::clear(this); - break; - case messagetypes::ACTION: - ActionMessage::clear(this); - break; - case messagetypes::DEVICE_HANDLER_COMMAND: - DeviceHandlerMessage::clear(this); - break; - case messagetypes::MEMORY: - MemoryMessage::clear(this); - break; - case messagetypes::MONITORING: - MonitoringMessage::clear(this); - break; - case messagetypes::TM_STORE: - TmStoreMessage::clear(this); - break; - case messagetypes::PARAMETER: - ParameterMessage::clear(this); - break; - default: - messagetypes::clearMissionMessage(this); - break; - } -} - -bool CommandMessage::isClearedCommandMessage() { - return getCommand() == CMD_NONE; -} - -size_t CommandMessage::getMinimumMessageSize() const { - return COMMAND_MESSAGE_SIZE; -} - -void CommandMessage::setToUnknownCommand() { - Command_t initialCommand = getCommand(); - clearCommandMessage(); - setReplyRejected(UNKNOWN_COMMAND, initialCommand); -} - -void CommandMessage::setReplyRejected(ReturnValue_t reason, - Command_t initialCommand) { - setCommand(REPLY_REJECTED); - setParameter(reason); - setParameter2(initialCommand); -} - -ReturnValue_t CommandMessage::getReplyRejectedReason( - Command_t *initialCommand) const { - ReturnValue_t reason = getParameter(); - if(initialCommand != nullptr) { - *initialCommand = getParameter2(); - } - return reason; -} +#include "CommandMessage.h" +#include "CommandMessageCleaner.h" +#include + +CommandMessage::CommandMessage() { + MessageQueueMessage::setMessageSize(DEFAULT_COMMAND_MESSAGE_SIZE); + setCommand(CMD_NONE); +} + +CommandMessage::CommandMessage(Command_t command, uint32_t parameter1, + uint32_t parameter2) { + MessageQueueMessage::setMessageSize(DEFAULT_COMMAND_MESSAGE_SIZE); + setCommand(command); + setParameter(parameter1); + setParameter2(parameter2); +} + +Command_t CommandMessage::getCommand() const { + Command_t command; + std::memcpy(&command, MessageQueueMessage::getData(), sizeof(Command_t)); + return command; +} + +void CommandMessage::setCommand(Command_t command) { + std::memcpy(MessageQueueMessage::getData(), &command, sizeof(Command_t)); +} + +uint8_t CommandMessage::getMessageType() const { + // first byte of command ID. + return getCommand() >> 8 & 0xff; +} + +uint32_t CommandMessage::getParameter() const { + uint32_t parameter1; + std::memcpy(¶meter1, this->getData(), sizeof(parameter1)); + return parameter1; +} + +void CommandMessage::setParameter(uint32_t parameter1) { + std::memcpy(this->getData(), ¶meter1, sizeof(parameter1)); +} + +uint32_t CommandMessage::getParameter2() const { + uint32_t parameter2; + std::memcpy(¶meter2, this->getData() + sizeof(uint32_t), + sizeof(parameter2)); + return parameter2; +} + +void CommandMessage::setParameter2(uint32_t parameter2) { + std::memcpy(this->getData() + sizeof(uint32_t), ¶meter2, + sizeof(parameter2)); +} + +uint32_t CommandMessage::getParameter3() const { + uint32_t parameter3; + std::memcpy(¶meter3, this->getData() + 2 * sizeof(uint32_t), + sizeof(parameter3)); + return parameter3; +} + +void CommandMessage::setParameter3(uint32_t parameter3) { + std::memcpy(this->getData() + 2 * sizeof(uint32_t), ¶meter3, + sizeof(parameter3)); +} + +size_t CommandMessage::getMinimumMessageSize() const { + return MINIMUM_COMMAND_MESSAGE_SIZE; +} + +void CommandMessage::clearCommandMessage() { + clear(); +} + +void CommandMessage::clear() { + CommandMessageCleaner::clearCommandMessage(this); +} + +bool CommandMessage::isClearedCommandMessage() { + return getCommand() == CMD_NONE; +} + +void CommandMessage::setToUnknownCommand() { + Command_t initialCommand = getCommand(); + this->clear(); + setReplyRejected(UNKNOWN_COMMAND, initialCommand); +} + +void CommandMessage::setReplyRejected(ReturnValue_t reason, + Command_t initialCommand) { + setCommand(REPLY_REJECTED); + setParameter(reason); + setParameter2(initialCommand); +} + +ReturnValue_t CommandMessage::getReplyRejectedReason( + Command_t *initialCommand) const { + ReturnValue_t reason = getParameter(); + if(initialCommand != nullptr) { + *initialCommand = getParameter2(); + } + return reason; +} + +uint8_t* CommandMessage::getData() { + return MessageQueueMessage::getData() + sizeof(Command_t); +} + +const uint8_t* CommandMessage::getData() const { + return MessageQueueMessage::getData() + sizeof(Command_t); +} diff --git a/ipc/CommandMessage.h b/ipc/CommandMessage.h index e984ad3d..3be9a120 100644 --- a/ipc/CommandMessage.h +++ b/ipc/CommandMessage.h @@ -1,134 +1,129 @@ -/** - * @file CommandMessage.h - * @brief This file defines the CommandMessage class. - * @date 20.06.2013 - * @author baetz - */ - -#ifndef COMMANDMESSAGE_H_ -#define COMMANDMESSAGE_H_ - - -#include "FwMessageTypes.h" -#include - -#include "MessageQueueMessage.h" - -#define MAKE_COMMAND_ID( number ) ((MESSAGE_ID << 8) + (number)) -typedef ReturnValue_t Command_t; - -class CommandMessage : public MessageQueueMessage { -public: - static const uint8_t INTERFACE_ID = CLASS_ID::COMMAND_MESSAGE; - static const ReturnValue_t UNKNOWN_COMMAND = MAKE_RETURN_CODE(0x01); - - - static const uint8_t MESSAGE_ID = messagetypes::COMMAND; - static const Command_t CMD_NONE = MAKE_COMMAND_ID( 0 );//!< Used internally, will be ignored - static const Command_t REPLY_COMMAND_OK = MAKE_COMMAND_ID( 3 ); - static const Command_t REPLY_REJECTED = MAKE_COMMAND_ID( 0xD1 );//!< Reply indicating that the current command was rejected, par1 should contain the error code - - /** - * This is the size of a message as it is seen by the MessageQueue - */ - static const size_t COMMAND_MESSAGE_SIZE = HEADER_SIZE - + sizeof(Command_t) + 2 * sizeof(uint32_t); - - /** - * Default Constructor, does not initialize anything. - * - * This constructor should be used when receiving a Message, as the content is filled by the MessageQueue. - */ - CommandMessage(); - /** - * This constructor creates a new message with all message content initialized - * - * @param command The DeviceHandlerCommand_t that will be sent - * @param parameter1 The first parameter - * @param parameter2 The second parameter - */ - CommandMessage(Command_t command, - uint32_t parameter1, uint32_t parameter2); - - /** - * Default Destructor - */ - virtual ~CommandMessage() { - } - - /** - * Read the DeviceHandlerCommand_t that is stored in the message, usually used after receiving - * - * @return the Command stored in the Message - */ - Command_t getCommand() const; - - /** - * Set the DeviceHandlerCOmmand_t of the message - * - * @param the Command to be sent - */ - void setCommand(Command_t command); - - /** - * Get the first parameter of the message - * - * @return the first Parameter of the message - */ - uint32_t getParameter() const; - - /** - * Set the first parameter of the message - * - * @param the first parameter of the message - */ - void setParameter(uint32_t parameter1); - - /** - * Get the second parameter of the message - * - * @return the second Parameter of the message - */ - uint32_t getParameter2() const; - - /** - * Set the second parameter of the message - * - * @param the second parameter of the message - */ - void setParameter2(uint32_t parameter2); - - /** - * Set the command to CMD_NONE and try to find - * the correct class to handle a more detailed - * clear. - * Also, calls a mission-specific clearMissionMessage - * function to separate between framework and mission - * messages. Not optimal, may be replaced by totally - * different auto-delete solution (e.g. smart pointers). - * - */ - void clearCommandMessage(); - - /** - * check if a message was cleared - * - * @return if the command is CMD_NONE - */ - bool isClearedCommandMessage(); - - - /** - * Sets the command to REPLY_REJECTED with parameter UNKNOWN_COMMAND. - * Is needed quite often, so we better code it once only. - */ - void setToUnknownCommand(); - void setReplyRejected(ReturnValue_t reason, Command_t initialCommand = CMD_NONE); - ReturnValue_t getReplyRejectedReason( - Command_t *initialCommand = nullptr) const; - - size_t getMinimumMessageSize() const; -}; - - -#endif /* COMMANDMESSAGE_H_ */ +#ifndef FSFW_IPC_COMMANDMESSAGE_H_ +#define FSFW_IPC_COMMANDMESSAGE_H_ + +#include "CommandMessageIF.h" +#include "MessageQueueMessage.h" +#include "FwMessageTypes.h" + +/** + * @brief Default command message used to pass command messages between tasks. + * Primary message type for IPC. Contains sender, 2-byte command ID + * field, and 2 4-byte parameters. + * @details + * It operates on an external memory which is contained inside a + * class implementing MessageQueueMessageIF by taking its address. + * This allows for a more flexible designs of message implementations. + * The pointer can be passed to different message implementations without + * the need of unnecessary copying. + * + * The command message is based of the generic MessageQueueMessage which + * currently has an internal message size of 28 bytes. + * @author Bastian Baetz + */ +class CommandMessage: public MessageQueueMessage, public CommandMessageIF { +public: + /** + * Default size can accomodate 2 4-byte parameters. + */ + static constexpr size_t DEFAULT_COMMAND_MESSAGE_SIZE = + CommandMessageIF::MINIMUM_COMMAND_MESSAGE_SIZE + sizeof(uint32_t); + + /** + * @brief Default Constructor, does not initialize anything. + * @details + * This constructor should be used when receiving a Message, as the + * content is filled by the MessageQueue. + */ + CommandMessage(); + /** + * This constructor creates a new message with all message content + * initialized + * + * @param command The DeviceHandlerCommand_t that will be sent + * @param parameter1 The first parameter + * @param parameter2 The second parameter + */ + CommandMessage(Command_t command, uint32_t parameter1, uint32_t parameter2); + + /** + * @brief Default Destructor + */ + virtual ~CommandMessage() {} + + /** + * Read the DeviceHandlerCommand_t that is stored in the message, + * usually used after receiving. + * + * @return the Command stored in the Message + */ + virtual Command_t getCommand() const override; + /** + * Set the command type of the message. Default implementation also + * sets the message type, which will be the first byte of the command ID. + * @param the Command to be sent + */ + virtual void setCommand(Command_t command); + + virtual uint8_t* getData() override; + virtual const uint8_t* getData() const override; + + /** + * Get the first parameter of the message + * @return the first Parameter of the message + */ + uint32_t getParameter() const; + /** + * Set the first parameter of the message + * @param the first parameter of the message + */ + void setParameter(uint32_t parameter1); + uint32_t getParameter2() const; + void setParameter2(uint32_t parameter2); + uint32_t getParameter3() const; + void setParameter3(uint32_t parameter3); + + /** + * check if a message was cleared + * + * @return if the command is CMD_NONE + */ + bool isClearedCommandMessage(); + + /** + * Sets the command to REPLY_REJECTED with parameter UNKNOWN_COMMAND. + * Is needed quite often, so we better code it once only. + */ + void setToUnknownCommand() override; + + /** + * A command message can be rejected and needs to offer a function + * to set a rejected reply + * @param reason + * @param initialCommand + */ + void setReplyRejected(ReturnValue_t reason, + Command_t initialCommand) override; + /** + * Corrensonding getter function. + * @param initialCommand + * @return + */ + ReturnValue_t getReplyRejectedReason( + Command_t* initialCommand = nullptr) const override; + + + virtual void clear() override; + void clearCommandMessage(); + + /** + * Extract message ID, which is the first byte of the command ID for the + * default implementation. + * @return + */ + virtual uint8_t getMessageType() const override; + + /** MessageQueueMessageIF functions used for minimum size check. */ + size_t getMinimumMessageSize() const override; +}; + +#endif /* FSFW_IPC_COMMANDMESSAGE_H_ */ diff --git a/ipc/CommandMessageCleaner.cpp b/ipc/CommandMessageCleaner.cpp new file mode 100644 index 00000000..a4dec78d --- /dev/null +++ b/ipc/CommandMessageCleaner.cpp @@ -0,0 +1,45 @@ +#include "../ipc/CommandMessageCleaner.h" + +#include "../devicehandlers/DeviceHandlerMessage.h" +#include "../health/HealthMessage.h" +#include "../memory/MemoryMessage.h" +#include "../modes/ModeMessage.h" +#include "../monitoring/MonitoringMessage.h" +#include "../subsystem/modes/ModeSequenceMessage.h" +#include "../tmstorage/TmStoreMessage.h" +#include "../parameters/ParameterMessage.h" + +void CommandMessageCleaner::clearCommandMessage(CommandMessage* message) { + switch(message->getMessageType()){ + case messagetypes::MODE_COMMAND: + ModeMessage::clear(message); + break; + case messagetypes::HEALTH_COMMAND: + HealthMessage::clear(message); + break; + case messagetypes::MODE_SEQUENCE: + ModeSequenceMessage::clear(message); + break; + case messagetypes::ACTION: + ActionMessage::clear(message); + break; + case messagetypes::DEVICE_HANDLER_COMMAND: + DeviceHandlerMessage::clear(message); + break; + case messagetypes::MEMORY: + MemoryMessage::clear(message); + break; + case messagetypes::MONITORING: + MonitoringMessage::clear(message); + break; + case messagetypes::TM_STORE: + TmStoreMessage::clear(message); + break; + case messagetypes::PARAMETER: + ParameterMessage::clear(message); + break; + default: + messagetypes::clearMissionMessage(message); + break; + } +} diff --git a/ipc/CommandMessageCleaner.h b/ipc/CommandMessageCleaner.h new file mode 100644 index 00000000..f17bf282 --- /dev/null +++ b/ipc/CommandMessageCleaner.h @@ -0,0 +1,16 @@ +#ifndef FRAMEWORK_IPC_COMMANDMESSAGECLEANER_H_ +#define FRAMEWORK_IPC_COMMANDMESSAGECLEANER_H_ +#include "../ipc/CommandMessage.h" + +namespace messagetypes { +// Implemented in config. +void clearMissionMessage(CommandMessage* message); +} + +class CommandMessageCleaner { +public: + static void clearCommandMessage(CommandMessage* message); +}; + + +#endif /* FRAMEWORK_IPC_COMMANDMESSAGECLEANER_H_ */ diff --git a/ipc/CommandMessageIF.h b/ipc/CommandMessageIF.h new file mode 100644 index 00000000..68a8d956 --- /dev/null +++ b/ipc/CommandMessageIF.h @@ -0,0 +1,73 @@ +#ifndef FSFW_IPC_COMMANDMESSAGEIF_H_ +#define FSFW_IPC_COMMANDMESSAGEIF_H_ + +#include "MessageQueueMessageIF.h" +#include "FwMessageTypes.h" +#include "../returnvalues/HasReturnvaluesIF.h" + +#define MAKE_COMMAND_ID( number ) ((MESSAGE_ID << 8) + (number)) +typedef uint16_t Command_t; + +class CommandMessageIF { +public: + /** + * Header consists of sender ID and command ID. + */ + static constexpr size_t HEADER_SIZE = MessageQueueMessageIF::HEADER_SIZE + + sizeof(Command_t); + /** + * This minimum size is derived from the interface requirement to be able + * to set a rejected reply, which contains a returnvalue and the initial + * command. + */ + static constexpr size_t MINIMUM_COMMAND_MESSAGE_SIZE = + CommandMessageIF::HEADER_SIZE + sizeof(ReturnValue_t) + + sizeof(Command_t); + + static const uint8_t INTERFACE_ID = CLASS_ID::COMMAND_MESSAGE; + static const ReturnValue_t UNKNOWN_COMMAND = MAKE_RETURN_CODE(0x01); + + static const uint8_t MESSAGE_ID = messagetypes::COMMAND; + //! Used internally, shall be ignored + 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, + //! par1 should contain the error code + static const Command_t REPLY_REJECTED = MAKE_COMMAND_ID( 2 ); + + virtual ~CommandMessageIF() {}; + + /** + * A command message shall have a uint16_t command ID field. + * @return + */ + virtual Command_t getCommand() const = 0; + /** + * A command message shall have a uint8_t message type ID field. + * @return + */ + virtual uint8_t getMessageType() const = 0; + + /** + * A command message can be rejected and needs to offer a function + * to set a rejected reply + * @param reason + * @param initialCommand + */ + virtual void setReplyRejected(ReturnValue_t reason, + Command_t initialCommand) = 0; + /** + * Corrensonding getter function. + * @param initialCommand + * @return + */ + virtual ReturnValue_t getReplyRejectedReason( + Command_t* initialCommand = nullptr) const = 0; + + virtual void setToUnknownCommand() = 0; + + virtual void clear() = 0; + +}; + +#endif /* FSFW_IPC_COMMANDMESSAGEIF_H_ */ diff --git a/ipc/MessageQueueMessage.cpp b/ipc/MessageQueueMessage.cpp index 05dde1f5..2f79cb3b 100644 --- a/ipc/MessageQueueMessage.cpp +++ b/ipc/MessageQueueMessage.cpp @@ -1,65 +1,84 @@ -#include "MessageQueueMessage.h" -#include "../serviceinterface/ServiceInterfaceStream.h" - -#include - -MessageQueueMessage::MessageQueueMessage() : - messageSize(this->HEADER_SIZE) { - memset(this->internalBuffer, 0, sizeof(this->internalBuffer)); -} - -MessageQueueMessage::~MessageQueueMessage() { -} - -const uint8_t* MessageQueueMessage::getBuffer() const { - return this->internalBuffer; -} - -uint8_t* MessageQueueMessage::getBuffer() { - return this->internalBuffer; -} - -const uint8_t* MessageQueueMessage::getData() const { - return this->internalBuffer + this->HEADER_SIZE; -} - -uint8_t* MessageQueueMessage::getData() { - return this->internalBuffer + this->HEADER_SIZE; -} - -MessageQueueId_t MessageQueueMessage::getSender() const { - MessageQueueId_t temp_id; - memcpy(&temp_id, this->internalBuffer, sizeof(MessageQueueId_t)); - return temp_id; -} - -void MessageQueueMessage::setSender(MessageQueueId_t setId) { - memcpy(this->internalBuffer, &setId, sizeof(MessageQueueId_t)); -} - -MessageQueueMessage::MessageQueueMessage(uint8_t* data, uint32_t size) : - messageSize(this->HEADER_SIZE + size) { - if (size <= this->MAX_DATA_SIZE) { - memcpy(this->getData(), data, size); - } else { - memset(this->internalBuffer, 0, sizeof(this->internalBuffer)); - this->messageSize = this->HEADER_SIZE; - } -} - -size_t MessageQueueMessage::getMinimumMessageSize() { - return this->HEADER_SIZE; -} - -void MessageQueueMessage::print() { - sif::debug << "MessageQueueMessage has size: " << this->messageSize << std::hex - << std::endl; - for (uint8_t count = 0; count < this->messageSize; count++) { - sif::debug << (uint32_t) this->internalBuffer[count] << ":"; - } - sif::debug << std::dec << std::endl; -} - -void MessageQueueMessage::clear() { - memset(this->getBuffer(), 0, this->MAX_MESSAGE_SIZE); -} +#include "MessageQueueMessage.h" +#include "../serviceinterface/ServiceInterfaceStream.h" +#include "../globalfunctions/arrayprinter.h" +#include + +MessageQueueMessage::MessageQueueMessage() : + messageSize(getMinimumMessageSize()) { + memset(this->internalBuffer, 0, sizeof(this->internalBuffer)); +} + +MessageQueueMessage::MessageQueueMessage(uint8_t* data, size_t size) : + messageSize(this->HEADER_SIZE + size) { + if (size <= this->MAX_DATA_SIZE) { + memcpy(this->getData(), data, size); + this->messageSize = this->HEADER_SIZE + size; + } + else { + sif::warning << "MessageQueueMessage: Passed size larger than maximum" + "allowed size! Setting content to 0" << std::endl; + memset(this->internalBuffer, 0, sizeof(this->internalBuffer)); + this->messageSize = this->HEADER_SIZE; + } +} + +MessageQueueMessage::~MessageQueueMessage() { +} + +const uint8_t* MessageQueueMessage::getBuffer() const { + return this->internalBuffer; +} + +uint8_t* MessageQueueMessage::getBuffer() { + return this->internalBuffer; +} + +const uint8_t* MessageQueueMessage::getData() const { + return this->internalBuffer + this->HEADER_SIZE; +} + +uint8_t* MessageQueueMessage::getData() { + return this->internalBuffer + this->HEADER_SIZE; +} + +MessageQueueId_t MessageQueueMessage::getSender() const { + MessageQueueId_t temp_id; + memcpy(&temp_id, this->internalBuffer, sizeof(MessageQueueId_t)); + return temp_id; +} + +void MessageQueueMessage::setSender(MessageQueueId_t setId) { + memcpy(this->internalBuffer, &setId, sizeof(MessageQueueId_t)); +} + +void MessageQueueMessage::print(bool printWholeMessage) { + sif::debug << "MessageQueueMessage content: " << std::endl; + if(printWholeMessage) { + arrayprinter::print(getData(), getMaximumMessageSize()); + } + else { + arrayprinter::print(getData(), getMessageSize()); + } + +} + +void MessageQueueMessage::clear() { + memset(this->getBuffer(), 0, this->MAX_MESSAGE_SIZE); +} + +size_t MessageQueueMessage::getMessageSize() const { + return this->messageSize; +} + +void MessageQueueMessage::setMessageSize(size_t messageSize) { + this->messageSize = messageSize; +} + +size_t MessageQueueMessage::getMinimumMessageSize() const { + return this->MIN_MESSAGE_SIZE; +} + +size_t MessageQueueMessage::getMaximumMessageSize() const { + return this->MAX_MESSAGE_SIZE; +} + diff --git a/ipc/MessageQueueMessage.h b/ipc/MessageQueueMessage.h index aa3559d6..da5c78cb 100644 --- a/ipc/MessageQueueMessage.h +++ b/ipc/MessageQueueMessage.h @@ -1,118 +1,150 @@ -#ifndef MESSAGEQUEUEMESSAGE_H_ -#define MESSAGEQUEUEMESSAGE_H_ - -#include "MessageQueueSenderIF.h" -#include - -/** - * \brief This class is the representation and data organizer for interprocess messages. - * - * \details To facilitate and standardize interprocess communication, this class was created - * to handle a lightweight "interprocess message protocol". It adds a header with the - * sender's queue id to every sent message and defines the maximum total message size. - * Specialized messages, such as device commanding messages, can be created by inheriting - * from this class and filling the buffer provided by getData with additional content. - * If larger amounts of data must be sent between processes, the data shall be stored in - * the IPC Store object and only the storage id is passed in a queue message. - * The class is used both to generate and send messages and to receive messages from - * other tasks. - * \ingroup message_queue - */ -class MessageQueueMessage { -public: - /** - * \brief This constant defines the maximum size of the data content, excluding the header. - * \details It may be changed if necessary, but in general should be kept as small as possible. - */ - static const size_t MAX_DATA_SIZE = 24; - /** - * \brief This constants defines the size of the header, which is added to every message. - */ - static const size_t HEADER_SIZE = sizeof(MessageQueueId_t); - /** - * \brief This constant defines the maximum total size in bytes of a sent message. - * \details It is the sum of the maximum data and the header size. Be aware that this constant - * is used to define the buffer sizes for every message queue in the system. So, a change - * here may have significant impact on the required resources. - */ - static const size_t MAX_MESSAGE_SIZE = MAX_DATA_SIZE + HEADER_SIZE; -private: - /** - * \brief This is the internal buffer that contains the actual message data. - */ - uint8_t internalBuffer[MAX_MESSAGE_SIZE]; -public: - /** - * \brief The size information of each message is stored in this attribute. - * \details It is public to simplify usage and to allow for passing the variable's address as a - * pointer. Care must be taken when inheriting from this class, as every child class is - * responsible for managing the size information by itself. When using the class to - * receive a message, the size information is updated automatically. - */ - size_t messageSize; - /** - * \brief The class is initialized empty with this constructor. - * \details The messageSize attribute is set to the header's size and the whole content is set to - * zero. - */ - MessageQueueMessage(); - /** - * \brief With this constructor the class is initialized with the given content. - * \details If the passed message size fits into the buffer, the passed data is copied to the - * internal buffer and the messageSize information is set. Otherwise, messageSize - * is set to the header's size and the whole content is set to zero. - * \param data The data to be put in the message. - * \param size Size of the data to be copied. Must be smaller than MAX_MESSAGE_SIZE. - */ - MessageQueueMessage(uint8_t* data, uint32_t size); - /** - * \brief As no memory is allocated in this class, the destructor is empty. - */ - virtual ~MessageQueueMessage(); - /** - * \brief This method is used to get the complete data of the message. - */ - const uint8_t* getBuffer() const; - /** - * \brief This method is used to get the complete data of the message. - */ - uint8_t* getBuffer(); - /** - * \brief This method is used to fetch the data content of the message. - * \details It shall be used by child classes to add data at the right position. - */ - const uint8_t* getData() const; - /** - * \brief This method is used to fetch the data content of the message. - * \details It shall be used by child classes to add data at the right position. - */ - uint8_t* getData(); - /** - * \brief This method is used to extract the sender's message queue id information from a - * received message. - */ - MessageQueueId_t getSender() const; - /** - * \brief With this method, the whole content and the message size is set to zero. - */ - void clear(); - /** - * \brief This is a debug method that prints the content (till messageSize) to the debug output. - */ - void print(); - /** - * \brief This method is used to set the sender's message queue id information prior to - * sending the message. - * \param setId The message queue id that identifies the sending message queue. - */ - void setSender(MessageQueueId_t setId); - /** - * \brief This helper function is used by the MessageQueue class to check the size of an - * incoming message. - * \details The method must be overwritten by child classes if size checks shall be more strict. - * @return The default implementation returns HEADER_SIZE. - */ - virtual size_t getMinimumMessageSize(); -}; - -#endif /* MESSAGEQUEUEMESSAGE_H_ */ +#ifndef FSFW_IPC_MESSAGEQUEUEMESSAGE_H_ +#define FSFW_IPC_MESSAGEQUEUEMESSAGE_H_ + +#include "../ipc/MessageQueueMessageIF.h" +#include "../ipc/MessageQueueSenderIF.h" +#include + +/** + * @brief This class is the representation and data organizer + * for interprocess messages. + * @details + * To facilitate and standardize interprocess communication, this class was + * created to handle a lightweight "interprocess message protocol". + * + * It adds a header with the sender's queue id to every sent message and + * defines the maximum total message size. Specialized messages, such as + * device commanding messages, can be created by inheriting from this class + * and filling the buffer provided by getData with additional content. + * + * If larger amounts of data must be sent between processes, the data shall + * be stored in the IPC Store object and only the storage id is passed in a + * queue message.The class is used both to generate and send messages and to + * receive messages from other tasks. + * @ingroup message_queue + */ +class MessageQueueMessage: public MessageQueueMessageIF { +public: + /** + * @brief The class is initialized empty with this constructor. + * @details + * The messageSize attribute is set to the header's size and the whole + * content is set to zero. + */ + MessageQueueMessage(); + /** + * @brief With this constructor the class is initialized with + * the given content. + * @details + * If the passed message size fits into the buffer, the passed data is + * copied to the internal buffer and the messageSize information is set. + * Otherwise, messageSize is set to the header's size and the whole + * content is set to zero. + * @param data The data to be put in the message. + * @param size Size of the data to be copied. Must be smaller than + * MAX_MESSAGE_SIZE and larger than MIN_MESSAGE_SIZE. + */ + MessageQueueMessage(uint8_t* data, size_t size); + + /** + * @brief As no memory is allocated in this class, + * the destructor is empty. + */ + virtual ~MessageQueueMessage(); + + /** + * @brief The size information of each message is stored in + * this attribute. + * @details + * It is public to simplify usage and to allow for passing the size + * address as a pointer. Care must be taken when inheriting from this class, + * as every child class is responsible for managing the size information by + * itself. When using the class to receive a message, the size information + * is updated automatically. + * + * Please note that the minimum size is limited by the size of the header + * while the maximum size is limited by the maximum allowed message size. + */ + size_t messageSize; + /** + * @brief This constant defines the maximum size of the data content, + * excluding the header. + * @details + * It may be changed if necessary, but in general should be kept + * as small as possible. + */ + static const size_t MAX_DATA_SIZE = 24; + + /** + * @brief This constant defines the maximum total size in bytes + * of a sent message. + * @details + * It is the sum of the maximum data and the header size. Be aware that + * this constant is used to define the buffer sizes for every message + * queue in the system. So, a change here may have significant impact on + * the required resources. + */ + static constexpr size_t MAX_MESSAGE_SIZE = MAX_DATA_SIZE + HEADER_SIZE; + /** + * @brief Defines the minimum size of a message where only the + * header is included + */ + static constexpr size_t MIN_MESSAGE_SIZE = HEADER_SIZE; +private: + /** + * @brief This is the internal buffer that contains the + * actual message data. + */ + uint8_t internalBuffer[MAX_MESSAGE_SIZE]; +public: + /** + * @brief This method is used to get the complete data of the message. + */ + const uint8_t* getBuffer() const override; + /** + * @brief This method is used to get the complete data of the message. + */ + uint8_t* getBuffer() override; + /** + * @brief This method is used to fetch the data content of the message. + * @details + * It shall be used by child classes to add data at the right position. + */ + const uint8_t* getData() const override; + /** + * @brief This method is used to fetch the data content of the message. + * @details + * It shall be used by child classes to add data at the right position. + */ + uint8_t* getData() override; + /** + * @brief This method is used to extract the sender's message + * queue id information from a received message. + */ + MessageQueueId_t getSender() const override; + /** + * @brief With this method, the whole content + * and the message size is set to zero. + */ + void clear() override; + + /** + * @brief This method is used to set the sender's message queue id + * information prior to ing the message. + * @param setId + * The message queue id that identifies the sending message queue. + */ + void setSender(MessageQueueId_t setId) override; + + virtual size_t getMessageSize() const override; + virtual void setMessageSize(size_t messageSize) override; + virtual size_t getMinimumMessageSize() const override; + virtual size_t getMaximumMessageSize() const override; + + /** + * @brief This is a debug method that prints the content. + */ + void print(bool printWholeMessage); +}; + +#endif /* FSFW_IPC_MESSAGEQUEUEMESSAGE_H_ */ diff --git a/ipc/MessageQueueMessageIF.h b/ipc/MessageQueueMessageIF.h new file mode 100644 index 00000000..91753ced --- /dev/null +++ b/ipc/MessageQueueMessageIF.h @@ -0,0 +1,91 @@ +#ifndef FRAMEWORK_IPC_MESSAGEQUEUEMESSAGEIF_H_ +#define FRAMEWORK_IPC_MESSAGEQUEUEMESSAGEIF_H_ +#include +#include + +/* + * TODO: Actually, the definition of this ID to be a uint32_t is not ideal and + * breaks layering. However, it is difficult to keep layering, as the ID is + * stored in many places and sent around in MessageQueueMessage. + * Ideally, one would use the (current) object_id_t only, however, doing a + * lookup of queueIDs for every call does not sound ideal. + * In a first step, I'll circumvent the issue by not touching it, + * maybe in a second step. This also influences Interface design + * (getCommandQueue) and some other issues.. + */ + +typedef uint32_t MessageQueueId_t; + +class MessageQueueMessageIF { +public: + static const MessageQueueId_t NO_QUEUE = -1; + /** + * @brief This constants defines the size of the header, + * which is added to every message. + */ + static const size_t HEADER_SIZE = sizeof(MessageQueueId_t); + + virtual ~MessageQueueMessageIF() {}; + + /** + * @brief With this method, the whole content and the message + * size is set to zero. + * @details + * Implementations should also take care to clear data which is stored + * indirectly (e.g. storage data). + */ + virtual void clear() = 0; + + /** + * @brief Get read-only pointer to the complete data of the message. + * @return + */ + virtual const uint8_t* getBuffer() const = 0; + + /** + * @brief This method is used to get the complete data of the message. + */ + virtual uint8_t* getBuffer() = 0; + + /** + * @brief This method is used to set the sender's message queue id + * information prior to sending the message. + * @param setId + * The message queue id that identifies the sending message queue. + */ + virtual void setSender(MessageQueueId_t setId) = 0; + + /** + * @brief This method is used to extract the sender's message queue id + * information from a received message. + */ + virtual MessageQueueId_t getSender() const = 0; + + /** + * @brief This method is used to fetch the data content of the message. + * @details + * It shall be used by child classes to add data at the right position. + */ + virtual const uint8_t* getData() const = 0; + /** + * @brief This method is used to fetch the data content of the message. + * @details + * It shall be used by child classes to add data at the right position. + */ + virtual uint8_t* getData() = 0; + + /** + * Get constant message size of current message implementation. + * @return + */ + virtual size_t getMessageSize() const = 0; + + virtual void setMessageSize(size_t messageSize) = 0; + virtual size_t getMinimumMessageSize() const = 0; + virtual size_t getMaximumMessageSize() const = 0; + +}; + + + +#endif /* FRAMEWORK_IPC_MESSAGEQUEUEMESSAGEIF_H_ */ From 66cf2d3559b93ff78ebb043dafc4ea2abb4d6efa Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 27 Aug 2020 16:05:31 +0200 Subject: [PATCH 019/101] timeslot update for FreeRTOS --- devicehandlers/FixedSequenceSlot.cpp | 20 -- osal/FreeRTOS/FixedTimeslotTask.cpp | 328 +++++++++--------- osal/FreeRTOS/FixedTimeslotTask.h | 203 ++++++----- tasks/FixedSequenceSlot.cpp | 17 + {devicehandlers => tasks}/FixedSequenceSlot.h | 117 +++---- .../FixedSlotSequence.cpp | 270 +++++++------- {devicehandlers => tasks}/FixedSlotSequence.h | 311 +++++++++-------- 7 files changed, 647 insertions(+), 619 deletions(-) delete mode 100644 devicehandlers/FixedSequenceSlot.cpp create mode 100644 tasks/FixedSequenceSlot.cpp rename {devicehandlers => tasks}/FixedSequenceSlot.h (56%) rename {devicehandlers => tasks}/FixedSlotSequence.cpp (61%) rename {devicehandlers => tasks}/FixedSlotSequence.h (90%) diff --git a/devicehandlers/FixedSequenceSlot.cpp b/devicehandlers/FixedSequenceSlot.cpp deleted file mode 100644 index 667aba1d..00000000 --- a/devicehandlers/FixedSequenceSlot.cpp +++ /dev/null @@ -1,20 +0,0 @@ -/** - * @file PollingSlot.cpp - * @brief This file defines the PollingSlot class. - * @date 19.12.2012 - * @author baetz - */ - -#include "FixedSequenceSlot.h" -#include "../objectmanager/SystemObjectIF.h" -#include - -FixedSequenceSlot::FixedSequenceSlot(object_id_t handlerId, uint32_t setTime, - int8_t setSequenceId, PeriodicTaskIF* executingTask) : - handler(NULL), pollingTimeMs(setTime), opcode(setSequenceId) { - handler = objectManager->get(handlerId); - handler->setTaskIF(executingTask); -} - -FixedSequenceSlot::~FixedSequenceSlot() {} - diff --git a/osal/FreeRTOS/FixedTimeslotTask.cpp b/osal/FreeRTOS/FixedTimeslotTask.cpp index 4873dde4..772c4bca 100644 --- a/osal/FreeRTOS/FixedTimeslotTask.cpp +++ b/osal/FreeRTOS/FixedTimeslotTask.cpp @@ -1,162 +1,166 @@ -#include "FixedTimeslotTask.h" - -#include "../../serviceinterface/ServiceInterfaceStream.h" - -uint32_t FixedTimeslotTask::deadlineMissedCount = 0; -const size_t PeriodicTaskIF::MINIMUM_STACK_SIZE = configMINIMAL_STACK_SIZE; - -FixedTimeslotTask::FixedTimeslotTask(TaskName name, TaskPriority setPriority, - TaskStackSize setStack, TaskPeriod overallPeriod, - void (*setDeadlineMissedFunc)()) : - started(false), handle(NULL), pst(overallPeriod * 1000) { - configSTACK_DEPTH_TYPE stackSize = setStack / sizeof(configSTACK_DEPTH_TYPE); - xTaskCreate(taskEntryPoint, name, stackSize, this, setPriority, &handle); - // All additional attributes are applied to the object. - this->deadlineMissedFunc = setDeadlineMissedFunc; -} - -FixedTimeslotTask::~FixedTimeslotTask() { -} - -void FixedTimeslotTask::taskEntryPoint(void* argument) { - - // The argument is re-interpreted as FixedTimeslotTask. The Task object is - // global, so it is found from any place. - FixedTimeslotTask *originalTask(reinterpret_cast(argument)); - /* Task should not start until explicitly requested, - * but in FreeRTOS, tasks start as soon as they are created if the scheduler - * is running but not if the scheduler is not running. - * To be able to accommodate both cases we check a member which is set in - * #startTask(). If it is not set and we get here, the scheduler was started - * before #startTask() was called and we need to suspend if it is set, - * the scheduler was not running before #startTask() was called and we - * can continue */ - - if (not originalTask->started) { - vTaskSuspend(NULL); - } - - originalTask->taskFunctionality(); - sif::debug << "Polling task " << originalTask->handle - << " returned from taskFunctionality." << std::endl; -} - -void FixedTimeslotTask::missedDeadlineCounter() { - FixedTimeslotTask::deadlineMissedCount++; - if (FixedTimeslotTask::deadlineMissedCount % 10 == 0) { - sif::error << "PST missed " << FixedTimeslotTask::deadlineMissedCount - << " deadlines." << std::endl; - } -} - -ReturnValue_t FixedTimeslotTask::startTask() { - started = true; - - // We must not call resume if scheduler is not started yet - if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { - vTaskResume(handle); - } - - return HasReturnvaluesIF::RETURN_OK; -} - -ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId, - uint32_t slotTimeMs, int8_t executionStep) { - if (objectManager->get(componentId) != nullptr) { - pst.addSlot(componentId, slotTimeMs, executionStep, this); - return HasReturnvaluesIF::RETURN_OK; - } - - sif::error << "Component " << std::hex << componentId << - " not found, not adding it to pst" << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; -} - -uint32_t FixedTimeslotTask::getPeriodMs() const { - return pst.getLengthMs(); -} - -ReturnValue_t FixedTimeslotTask::checkSequence() const { - return pst.checkSequence(); -} - -void FixedTimeslotTask::taskFunctionality() { - // A local iterator for the Polling Sequence Table is created to find the - // start time for the first entry. - auto slotListIter = pst.current; - - //The start time for the first entry is read. - uint32_t intervalMs = slotListIter->pollingTimeMs; - TickType_t interval = pdMS_TO_TICKS(intervalMs); - - TickType_t xLastWakeTime; - /* The xLastWakeTime variable needs to be initialized with the current tick - count. Note that this is the only time the variable is written to - explicitly. After this assignment, xLastWakeTime is updated automatically - internally within vTaskDelayUntil(). */ - xLastWakeTime = xTaskGetTickCount(); - - // wait for first entry's start time - if(interval > 0) { - vTaskDelayUntil(&xLastWakeTime, interval); - } - - /* Enter the loop that defines the task behavior. */ - for (;;) { - //The component for this slot is executed and the next one is chosen. - this->pst.executeAndAdvance(); - if (not pst.slotFollowsImmediately()) { - // Get the interval till execution of the next slot. - intervalMs = this->pst.getIntervalToPreviousSlotMs(); - interval = pdMS_TO_TICKS(intervalMs); - - checkMissedDeadline(xLastWakeTime, interval); - - // Wait for the interval. This exits immediately if a deadline was - // missed while also updating the last wake time. - vTaskDelayUntil(&xLastWakeTime, interval); - } - } -} - -void FixedTimeslotTask::checkMissedDeadline(const TickType_t xLastWakeTime, - const TickType_t interval) { - /* Check whether deadline was missed while also taking overflows - * into account. Drawing this on paper with a timeline helps to understand - * it. */ - TickType_t currentTickCount = xTaskGetTickCount(); - TickType_t timeToWake = xLastWakeTime + interval; - // Time to wake has not overflown. - if(timeToWake > xLastWakeTime) { - /* If the current time has overflown exclusively or the current - * tick count is simply larger than the time to wake, a deadline was - * missed */ - if((currentTickCount < xLastWakeTime) or (currentTickCount > timeToWake)) { - handleMissedDeadline(); - } - } - /* Time to wake has overflown. A deadline was missed if the current time - * is larger than the time to wake */ - else if((timeToWake < xLastWakeTime) and (currentTickCount > timeToWake)) { - handleMissedDeadline(); - } -} - -void FixedTimeslotTask::handleMissedDeadline() { -#ifdef DEBUG - sif::warning << "FixedTimeslotTask: " << pcTaskGetName(NULL) << - " missed deadline!\n" << std::flush; -#endif - if(deadlineMissedFunc != nullptr) { - this->deadlineMissedFunc(); - } -} - -ReturnValue_t FixedTimeslotTask::sleepFor(uint32_t ms) { - vTaskDelay(pdMS_TO_TICKS(ms)); - return HasReturnvaluesIF::RETURN_OK; -} - -TaskHandle_t FixedTimeslotTask::getTaskHandle() { - return handle; -} +#include "FixedTimeslotTask.h" + +#include "../../serviceinterface/ServiceInterfaceStream.h" + +uint32_t FixedTimeslotTask::deadlineMissedCount = 0; +const size_t PeriodicTaskIF::MINIMUM_STACK_SIZE = configMINIMAL_STACK_SIZE; + +FixedTimeslotTask::FixedTimeslotTask(TaskName name, TaskPriority setPriority, + TaskStackSize setStack, TaskPeriod overallPeriod, + void (*setDeadlineMissedFunc)()) : + started(false), handle(nullptr), pst(overallPeriod * 1000) { + configSTACK_DEPTH_TYPE stackSize = setStack / sizeof(configSTACK_DEPTH_TYPE); + xTaskCreate(taskEntryPoint, name, stackSize, this, setPriority, &handle); + // All additional attributes are applied to the object. + this->deadlineMissedFunc = setDeadlineMissedFunc; +} + +FixedTimeslotTask::~FixedTimeslotTask() { +} + +void FixedTimeslotTask::taskEntryPoint(void* argument) { + + // The argument is re-interpreted as FixedTimeslotTask. The Task object is + // global, so it is found from any place. + FixedTimeslotTask *originalTask(reinterpret_cast(argument)); + /* Task should not start until explicitly requested, + * but in FreeRTOS, tasks start as soon as they are created if the scheduler + * is running but not if the scheduler is not running. + * To be able to accommodate both cases we check a member which is set in + * #startTask(). If it is not set and we get here, the scheduler was started + * before #startTask() was called and we need to suspend if it is set, + * the scheduler was not running before #startTask() was called and we + * can continue */ + + if (not originalTask->started) { + vTaskSuspend(NULL); + } + + originalTask->taskFunctionality(); + sif::debug << "Polling task " << originalTask->handle + << " returned from taskFunctionality." << std::endl; +} + +void FixedTimeslotTask::missedDeadlineCounter() { + FixedTimeslotTask::deadlineMissedCount++; + if (FixedTimeslotTask::deadlineMissedCount % 10 == 0) { + sif::error << "PST missed " << FixedTimeslotTask::deadlineMissedCount + << " deadlines." << std::endl; + } +} + +ReturnValue_t FixedTimeslotTask::startTask() { + started = true; + + // We must not call resume if scheduler is not started yet + if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { + vTaskResume(handle); + } + + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId, + uint32_t slotTimeMs, int8_t executionStep) { + ExecutableObjectIF* handler = + objectManager->get(componentId); + if (handler != nullptr) { + pst.addSlot(componentId, slotTimeMs, executionStep, handler, this); + return HasReturnvaluesIF::RETURN_OK; + } + + sif::error << "Component " << std::hex << componentId << + " not found, not adding it to pst" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; +} + +uint32_t FixedTimeslotTask::getPeriodMs() const { + return pst.getLengthMs(); +} + +ReturnValue_t FixedTimeslotTask::checkSequence() const { + return pst.checkSequence(); +} + +void FixedTimeslotTask::taskFunctionality() { + // A local iterator for the Polling Sequence Table is created to find the + // start time for the first entry. + auto slotListIter = pst.current; + + pst.intializeSequenceAfterTaskCreation(); + + //The start time for the first entry is read. + uint32_t intervalMs = slotListIter->pollingTimeMs; + TickType_t interval = pdMS_TO_TICKS(intervalMs); + + TickType_t xLastWakeTime; + /* The xLastWakeTime variable needs to be initialized with the current tick + count. Note that this is the only time the variable is written to + explicitly. After this assignment, xLastWakeTime is updated automatically + internally within vTaskDelayUntil(). */ + xLastWakeTime = xTaskGetTickCount(); + + // wait for first entry's start time + if(interval > 0) { + vTaskDelayUntil(&xLastWakeTime, interval); + } + + /* Enter the loop that defines the task behavior. */ + for (;;) { + //The component for this slot is executed and the next one is chosen. + this->pst.executeAndAdvance(); + if (not pst.slotFollowsImmediately()) { + // Get the interval till execution of the next slot. + intervalMs = this->pst.getIntervalToPreviousSlotMs(); + interval = pdMS_TO_TICKS(intervalMs); + + checkMissedDeadline(xLastWakeTime, interval); + + // Wait for the interval. This exits immediately if a deadline was + // missed while also updating the last wake time. + vTaskDelayUntil(&xLastWakeTime, interval); + } + } +} + +void FixedTimeslotTask::checkMissedDeadline(const TickType_t xLastWakeTime, + const TickType_t interval) { + /* Check whether deadline was missed while also taking overflows + * into account. Drawing this on paper with a timeline helps to understand + * it. */ + TickType_t currentTickCount = xTaskGetTickCount(); + TickType_t timeToWake = xLastWakeTime + interval; + // Time to wake has not overflown. + if(timeToWake > xLastWakeTime) { + /* If the current time has overflown exclusively or the current + * tick count is simply larger than the time to wake, a deadline was + * missed */ + if((currentTickCount < xLastWakeTime) or (currentTickCount > timeToWake)) { + handleMissedDeadline(); + } + } + /* Time to wake has overflown. A deadline was missed if the current time + * is larger than the time to wake */ + else if((timeToWake < xLastWakeTime) and (currentTickCount > timeToWake)) { + handleMissedDeadline(); + } +} + +void FixedTimeslotTask::handleMissedDeadline() { +#ifdef DEBUG + sif::warning << "FixedTimeslotTask: " << pcTaskGetName(NULL) << + " missed deadline!\n" << std::flush; +#endif + if(deadlineMissedFunc != nullptr) { + this->deadlineMissedFunc(); + } +} + +ReturnValue_t FixedTimeslotTask::sleepFor(uint32_t ms) { + vTaskDelay(pdMS_TO_TICKS(ms)); + return HasReturnvaluesIF::RETURN_OK; +} + +TaskHandle_t FixedTimeslotTask::getTaskHandle() { + return handle; +} diff --git a/osal/FreeRTOS/FixedTimeslotTask.h b/osal/FreeRTOS/FixedTimeslotTask.h index 84264c4c..42af14b8 100644 --- a/osal/FreeRTOS/FixedTimeslotTask.h +++ b/osal/FreeRTOS/FixedTimeslotTask.h @@ -1,102 +1,101 @@ -#ifndef FRAMEWORK_OSAL_FREERTOS_FIXEDTIMESLOTTASK_H_ -#define FRAMEWORK_OSAL_FREERTOS_FIXEDTIMESLOTTASK_H_ - -#include "FreeRTOSTaskIF.h" -#include "../../devicehandlers/FixedSlotSequence.h" -#include "../../tasks/FixedTimeslotTaskIF.h" -#include "../../tasks/Typedef.h" - - -#include -#include - -class FixedTimeslotTask: public FixedTimeslotTaskIF, public FreeRTOSTaskIF { -public: - - /** - * Keep in mind that you need to call before vTaskStartScheduler()! - * A lot of task parameters are set in "FreeRTOSConfig.h". - * @param name Name of the task, lenght limited by configMAX_TASK_NAME_LEN - * @param setPriority Number of priorities specified by - * configMAX_PRIORITIES. High taskPriority_ number means high priority. - * @param setStack Stack size in words (not bytes!). - * Lower limit specified by configMINIMAL_STACK_SIZE - * @param overallPeriod Period in seconds. - * @param setDeadlineMissedFunc Callback if a deadline was missed. - * @return Pointer to the newly created task. - */ - FixedTimeslotTask(TaskName name, TaskPriority setPriority, - TaskStackSize setStack, TaskPeriod overallPeriod, - void (*setDeadlineMissedFunc)()); - - /** - * @brief The destructor of the class. - * @details - * The destructor frees all heap memory that was allocated on thread - * initialization for the PST and the device handlers. This is done by - * calling the PST's destructor. - */ - virtual ~FixedTimeslotTask(void); - - ReturnValue_t startTask(void); - /** - * This static function can be used as #deadlineMissedFunc. - * It counts missedDeadlines and prints the number of missed deadlines - * every 10th time. - */ - static void missedDeadlineCounter(); - /** - * A helper variable to count missed deadlines. - */ - static uint32_t deadlineMissedCount; - - ReturnValue_t addSlot(object_id_t componentId, uint32_t slotTimeMs, - int8_t executionStep) override; - - uint32_t getPeriodMs() const override; - - ReturnValue_t checkSequence() const override; - - ReturnValue_t sleepFor(uint32_t ms) override; - - TaskHandle_t getTaskHandle() override; - -protected: - bool started; - TaskHandle_t handle; - - FixedSlotSequence pst; - - /** - * @brief This attribute holds a function pointer that is executed when - * a deadline was missed. - * @details - * Another function may be announced to determine the actions to perform - * when a deadline was missed. Currently, only one function for missing - * any deadline is allowed. If not used, it shall be declared NULL. - */ - void (*deadlineMissedFunc)(void); - /** - * @brief This is the entry point for a new task. - * @details - * This method starts the task by calling taskFunctionality(), as soon as - * all requirements (task scheduler has started and startTask() - * has been called) are met. - */ - static void taskEntryPoint(void* argument); - - /** - * @brief This function holds the main functionality of the thread. - * @details - * Core function holding the main functionality of the task - * It links the functionalities provided by FixedSlotSequence with the - * OS's System Calls to keep the timing of the periods. - */ - void taskFunctionality(void); - - void checkMissedDeadline(const TickType_t xLastWakeTime, - const TickType_t interval); - void handleMissedDeadline(); -}; - -#endif /* FRAMEWORK_OSAL_FREERTOS_FIXEDTIMESLOTTASK_H_ */ +#ifndef FRAMEWORK_OSAL_FREERTOS_FIXEDTIMESLOTTASK_H_ +#define FRAMEWORK_OSAL_FREERTOS_FIXEDTIMESLOTTASK_H_ + +#include "../../osal/FreeRTOS/FreeRTOSTaskIF.h" +#include "../../tasks/FixedSlotSequence.h" +#include "../../tasks/FixedTimeslotTaskIF.h" +#include "../../tasks/Typedef.h" + +#include +#include + +class FixedTimeslotTask: public FixedTimeslotTaskIF, public FreeRTOSTaskIF { +public: + + /** + * Keep in mind that you need to call before vTaskStartScheduler()! + * A lot of task parameters are set in "FreeRTOSConfig.h". + * @param name Name of the task, lenght limited by configMAX_TASK_NAME_LEN + * @param setPriority Number of priorities specified by + * configMAX_PRIORITIES. High taskPriority_ number means high priority. + * @param setStack Stack size in words (not bytes!). + * Lower limit specified by configMINIMAL_STACK_SIZE + * @param overallPeriod Period in seconds. + * @param setDeadlineMissedFunc Callback if a deadline was missed. + * @return Pointer to the newly created task. + */ + FixedTimeslotTask(TaskName name, TaskPriority setPriority, + TaskStackSize setStack, TaskPeriod overallPeriod, + void (*setDeadlineMissedFunc)()); + + /** + * @brief The destructor of the class. + * @details + * The destructor frees all heap memory that was allocated on thread + * initialization for the PST and the device handlers. This is done by + * calling the PST's destructor. + */ + virtual ~FixedTimeslotTask(void); + + ReturnValue_t startTask(void); + /** + * This static function can be used as #deadlineMissedFunc. + * It counts missedDeadlines and prints the number of missed deadlines + * every 10th time. + */ + static void missedDeadlineCounter(); + /** + * A helper variable to count missed deadlines. + */ + static uint32_t deadlineMissedCount; + + ReturnValue_t addSlot(object_id_t componentId, uint32_t slotTimeMs, + int8_t executionStep) override; + + uint32_t getPeriodMs() const override; + + ReturnValue_t checkSequence() const override; + + ReturnValue_t sleepFor(uint32_t ms) override; + + TaskHandle_t getTaskHandle() override; + +protected: + bool started; + TaskHandle_t handle; + + FixedSlotSequence pst; + + /** + * @brief This attribute holds a function pointer that is executed when + * a deadline was missed. + * @details + * Another function may be announced to determine the actions to perform + * when a deadline was missed. Currently, only one function for missing + * any deadline is allowed. If not used, it shall be declared NULL. + */ + void (*deadlineMissedFunc)(void); + /** + * @brief This is the entry point for a new task. + * @details + * This method starts the task by calling taskFunctionality(), as soon as + * all requirements (task scheduler has started and startTask() + * has been called) are met. + */ + static void taskEntryPoint(void* argument); + + /** + * @brief This function holds the main functionality of the thread. + * @details + * Core function holding the main functionality of the task + * It links the functionalities provided by FixedSlotSequence with the + * OS's System Calls to keep the timing of the periods. + */ + void taskFunctionality(void); + + void checkMissedDeadline(const TickType_t xLastWakeTime, + const TickType_t interval); + void handleMissedDeadline(); +}; + +#endif /* POLLINGTASK_H_ */ diff --git a/tasks/FixedSequenceSlot.cpp b/tasks/FixedSequenceSlot.cpp new file mode 100644 index 00000000..5fe49523 --- /dev/null +++ b/tasks/FixedSequenceSlot.cpp @@ -0,0 +1,17 @@ +#include "FixedSequenceSlot.h" +#include "../objectmanager/SystemObjectIF.h" +#include + +FixedSequenceSlot::FixedSequenceSlot(object_id_t handlerId, uint32_t setTime, + int8_t setSequenceId, ExecutableObjectIF* executableObject, + PeriodicTaskIF* executingTask) : + pollingTimeMs(setTime), opcode(setSequenceId) { + if(executableObject == nullptr) { + return; + } + this->executableObject = executableObject; + this->executableObject->setTaskIF(executingTask); +} + +FixedSequenceSlot::~FixedSequenceSlot() {} + diff --git a/devicehandlers/FixedSequenceSlot.h b/tasks/FixedSequenceSlot.h similarity index 56% rename from devicehandlers/FixedSequenceSlot.h rename to tasks/FixedSequenceSlot.h index 73504955..9cf5894c 100644 --- a/devicehandlers/FixedSequenceSlot.h +++ b/tasks/FixedSequenceSlot.h @@ -1,60 +1,57 @@ -/** - * @file FixedSequenceSlot.h - * @brief This file defines the PollingSlot class. - * @date 19.12.2012 - * @author baetz - */ - -#ifndef FIXEDSEQUENCESLOT_H_ -#define FIXEDSEQUENCESLOT_H_ - -#include "../objectmanager/ObjectManagerIF.h" -#include "../tasks/ExecutableObjectIF.h" -class PeriodicTaskIF; - -/** - * @brief This class is the representation of a single polling sequence table entry. - * - * @details The PollingSlot class is the representation of a single polling - * sequence table entry. - */ -class FixedSequenceSlot { -public: - FixedSequenceSlot( object_id_t handlerId, uint32_t setTimeMs, - int8_t setSequenceId, PeriodicTaskIF* executingTask ); - virtual ~FixedSequenceSlot(); - - /** - * @brief Handler identifies which device handler object is executed in this slot. - */ - ExecutableObjectIF* handler; - - /** - * @brief This attribute defines when a device handler object is executed. - * - * @details The pollingTime attribute identifies the time the handler is executed in ms. - * It must be smaller than the period length of the polling sequence. - */ - uint32_t pollingTimeMs; - - /** - * @brief This value defines the type of device communication. - * - * @details The state of this value decides what communication routine is - * called in the PST executable or the device handler object. - */ - uint8_t opcode; - - /** - * @brief Operator overload for the comparison operator to - * allow sorting by polling time. - * @param fixedSequenceSlot - * @return - */ - bool operator <(const FixedSequenceSlot & fixedSequenceSlot) const { - return pollingTimeMs < fixedSequenceSlot.pollingTimeMs; - } -}; - - -#endif /* FIXEDSEQUENCESLOT_H_ */ +#ifndef FRAMEWORK_TASKS_FIXEDSEQUENCESLOT_H_ +#define FRAMEWORK_TASKS_FIXEDSEQUENCESLOT_H_ + +#include "../objectmanager/ObjectManagerIF.h" +#include "../tasks/ExecutableObjectIF.h" +class PeriodicTaskIF; + +/** + * @brief This class is the representation of a single polling sequence + * table entry. + * @details + * The PollingSlot class is the representation of a single polling + * sequence table entry. + * @author baetz + */ +class FixedSequenceSlot { +public: + FixedSequenceSlot( object_id_t handlerId, uint32_t setTimeMs, + int8_t setSequenceId, ExecutableObjectIF* executableObject, + PeriodicTaskIF* executingTask); + virtual ~FixedSequenceSlot(); + + /** + * @brief Handler identifies which object is executed in this slot. + */ + ExecutableObjectIF* executableObject = nullptr; + + /** + * @brief This attribute defines when a device handler object is executed. + * @details + * The pollingTime attribute identifies the time the handler is + * executed in ms. It must be smaller than the period length of the + * polling sequence. + */ + uint32_t pollingTimeMs; + + /** + * @brief This value defines the type of device communication. + * + * @details The state of this value decides what communication routine is + * called in the PST executable or the device handler object. + */ + uint8_t opcode; + + /** + * @brief Operator overload for the comparison operator to + * allow sorting by polling time. + * @param fixedSequenceSlot + * @return + */ + bool operator <(const FixedSequenceSlot & fixedSequenceSlot) const { + return pollingTimeMs < fixedSequenceSlot.pollingTimeMs; + } +}; + + +#endif /* FIXEDSEQUENCESLOT_H_ */ diff --git a/devicehandlers/FixedSlotSequence.cpp b/tasks/FixedSlotSequence.cpp similarity index 61% rename from devicehandlers/FixedSlotSequence.cpp rename to tasks/FixedSlotSequence.cpp index 38d4dcea..78f512ca 100644 --- a/devicehandlers/FixedSlotSequence.cpp +++ b/tasks/FixedSlotSequence.cpp @@ -1,123 +1,147 @@ -#include "FixedSlotSequence.h" -#include "../serviceinterface/ServiceInterfaceStream.h" - -FixedSlotSequence::FixedSlotSequence(uint32_t setLengthMs) : - lengthMs(setLengthMs) { - current = slotList.begin(); -} - -FixedSlotSequence::~FixedSlotSequence() { - // Call the destructor on each list entry. - slotList.clear(); -} - -void FixedSlotSequence::executeAndAdvance() { - current->handler->performOperation(current->opcode); -// if (returnValue != RETURN_OK) { -// this->sendErrorMessage( returnValue ); -// } - //Increment the polling Sequence iterator - this->current++; - //Set it to the beginning, if the list's end is reached. - if (this->current == this->slotList.end()) { - this->current = this->slotList.begin(); - } -} - -uint32_t FixedSlotSequence::getIntervalToNextSlotMs() { - uint32_t oldTime; - SlotListIter slotListIter = current; - // Get the pollingTimeMs of the current slot object. - oldTime = slotListIter->pollingTimeMs; - // Advance to the next object. - slotListIter++; - // Find the next interval which is not 0. - while (slotListIter != slotList.end()) { - if (oldTime != slotListIter->pollingTimeMs) { - return slotListIter->pollingTimeMs - oldTime; - } else { - slotListIter++; - } - } - // If the list end is reached (this is definitely an interval != 0), - // the interval is calculated by subtracting the remaining time of the PST - // and adding the start time of the first handler in the list. - slotListIter = slotList.begin(); - return lengthMs - oldTime + slotListIter->pollingTimeMs; -} - -uint32_t FixedSlotSequence::getIntervalToPreviousSlotMs() { - uint32_t currentTime; - SlotListIter slotListIter = current; - // Get the pollingTimeMs of the current slot object. - currentTime = slotListIter->pollingTimeMs; - - //if it is the first slot, calculate difference to last slot - if (slotListIter == slotList.begin()){ - return lengthMs - (--slotList.end())->pollingTimeMs + currentTime; - } - // get previous slot - slotListIter--; - - return currentTime - slotListIter->pollingTimeMs; -} - -bool FixedSlotSequence::slotFollowsImmediately() { - uint32_t currentTime = current->pollingTimeMs; - SlotListIter fixedSequenceIter = this->current; - // Get the pollingTimeMs of the current slot object. - if (fixedSequenceIter == slotList.begin()) - return false; - fixedSequenceIter--; - if (fixedSequenceIter->pollingTimeMs == currentTime) { - return true; - } else { - return false; - } -} - -uint32_t FixedSlotSequence::getLengthMs() const { - return this->lengthMs; -} - -ReturnValue_t FixedSlotSequence::checkSequence() const { - if(slotList.empty()) { - sif::error << "Fixed Slot Sequence: Slot list is empty!" << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; - } - - auto slotIt = slotList.begin(); - uint32_t count = 0; - uint32_t time = 0; - while (slotIt != slotList.end()) { - if (slotIt->handler == nullptr) { - sif::error << "FixedSlotSequene::initialize: ObjectId does not exist!" - << std::endl; - count++; - } else if (slotIt->pollingTimeMs < time) { - sif::error << "FixedSlotSequence::initialize: Time: " - << slotIt->pollingTimeMs - << " is smaller than previous with " << time << std::endl; - count++; - } else { - // All ok, print slot. - //info << "Current slot polling time: " << std::endl; - //info << std::dec << slotIt->pollingTimeMs << std::endl; - } - time = slotIt->pollingTimeMs; - slotIt++; - } - //info << "Number of elements in slot list: " - // << slotList.size() << std::endl; - if (count > 0) { - return HasReturnvaluesIF::RETURN_FAILED; - } - return HasReturnvaluesIF::RETURN_OK; -} - -void FixedSlotSequence::addSlot(object_id_t componentId, uint32_t slotTimeMs, - int8_t executionStep, PeriodicTaskIF* executingTask) { - this->slotList.insert(FixedSequenceSlot(componentId, slotTimeMs, executionStep, - executingTask)); - this->current = slotList.begin(); -} +#include "FixedSlotSequence.h" +#include "../serviceinterface/ServiceInterfaceStream.h" +#include + +FixedSlotSequence::FixedSlotSequence(uint32_t setLengthMs) : + lengthMs(setLengthMs) { + current = slotList.begin(); +} + +FixedSlotSequence::~FixedSlotSequence() { + // Call the destructor on each list entry. + slotList.clear(); +} + +void FixedSlotSequence::executeAndAdvance() { + current->executableObject->performOperation(current->opcode); +// if (returnValue != RETURN_OK) { +// this->sendErrorMessage( returnValue ); +// } + //Increment the polling Sequence iterator + this->current++; + //Set it to the beginning, if the list's end is reached. + if (this->current == this->slotList.end()) { + this->current = this->slotList.begin(); + } +} + +uint32_t FixedSlotSequence::getIntervalToNextSlotMs() { + uint32_t oldTime; + SlotListIter slotListIter = current; + // Get the pollingTimeMs of the current slot object. + oldTime = slotListIter->pollingTimeMs; + // Advance to the next object. + slotListIter++; + // Find the next interval which is not 0. + while (slotListIter != slotList.end()) { + if (oldTime != slotListIter->pollingTimeMs) { + return slotListIter->pollingTimeMs - oldTime; + } else { + slotListIter++; + } + } + // If the list end is reached (this is definitely an interval != 0), + // the interval is calculated by subtracting the remaining time of the PST + // and adding the start time of the first handler in the list. + slotListIter = slotList.begin(); + return lengthMs - oldTime + slotListIter->pollingTimeMs; +} + +uint32_t FixedSlotSequence::getIntervalToPreviousSlotMs() { + uint32_t currentTime; + SlotListIter slotListIter = current; + // Get the pollingTimeMs of the current slot object. + currentTime = slotListIter->pollingTimeMs; + + //if it is the first slot, calculate difference to last slot + if (slotListIter == slotList.begin()){ + return lengthMs - (--slotList.end())->pollingTimeMs + currentTime; + } + // get previous slot + slotListIter--; + + return currentTime - slotListIter->pollingTimeMs; +} + +bool FixedSlotSequence::slotFollowsImmediately() { + uint32_t currentTime = current->pollingTimeMs; + SlotListIter fixedSequenceIter = this->current; + // Get the pollingTimeMs of the current slot object. + if (fixedSequenceIter == slotList.begin()) + return false; + fixedSequenceIter--; + if (fixedSequenceIter->pollingTimeMs == currentTime) { + return true; + } else { + return false; + } +} + +uint32_t FixedSlotSequence::getLengthMs() const { + return this->lengthMs; +} + +void FixedSlotSequence::addSlot(object_id_t componentId, uint32_t slotTimeMs, + int8_t executionStep, ExecutableObjectIF* executableObject, + PeriodicTaskIF* executingTask) { + this->slotList.insert(FixedSequenceSlot(componentId, slotTimeMs, + executionStep, executableObject, executingTask)); + this->current = slotList.begin(); +} + +ReturnValue_t FixedSlotSequence::checkSequence() const { + if(slotList.empty()) { + sif::error << "Fixed Slot Sequence: Slot list is empty!" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + + uint32_t count = 0; + uint32_t time = 0; + for(const auto& slot: slotList) { + if (slot.executableObject == nullptr) { + count++; + } + else if (slot.pollingTimeMs < time) { + sif::error << "FixedSlotSequence::initialize: Time: " + << slot.pollingTimeMs << " is smaller than previous with " + << time << std::endl; + count++; + } + else { + // All ok, print slot. + //sif::info << "Current slot polling time: " << std::endl; + //sif::info << std::dec << slotIt->pollingTimeMs << std::endl; + } + time = slot.pollingTimeMs; + + } + //sif::info << "Number of elements in slot list: " + // << slotList.size() << std::endl; + if (count > 0) { + return HasReturnvaluesIF::RETURN_FAILED; + } + return HasReturnvaluesIF::RETURN_OK; +} + + +ReturnValue_t FixedSlotSequence::intializeSequenceAfterTaskCreation() const { + std::set uniqueObjects; + uint32_t count = 0; + for(const auto& slot: slotList) { + // Ensure that each unique object is initialized once. + if(uniqueObjects.find(slot.executableObject) == uniqueObjects.end()) { + ReturnValue_t result = + slot.executableObject->initializeAfterTaskCreation(); + if(result != HasReturnvaluesIF::RETURN_OK) { + count++; + } + uniqueObjects.emplace(slot.executableObject); + } + } + if (count > 0) { + sif::error << "FixedSlotSequence::intializeSequenceAfterTaskCreation:" + "Counted " << count << " failed initializations!" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + return HasReturnvaluesIF::RETURN_OK; +} diff --git a/devicehandlers/FixedSlotSequence.h b/tasks/FixedSlotSequence.h similarity index 90% rename from devicehandlers/FixedSlotSequence.h rename to tasks/FixedSlotSequence.h index be6dc2d1..8aa04a27 100644 --- a/devicehandlers/FixedSlotSequence.h +++ b/tasks/FixedSlotSequence.h @@ -1,152 +1,159 @@ -#ifndef FRAMEWORK_DEVICEHANDLERS_FIXEDSLOTSEQUENCE_H_ -#define FRAMEWORK_DEVICEHANDLERS_FIXEDSLOTSEQUENCE_H_ - -#include "FixedSequenceSlot.h" -#include "../objectmanager/SystemObject.h" -#include - -/** - * @brief This class is the representation of a Polling Sequence Table in software. - * - * @details - * The FixedSlotSequence object maintains the dynamic execution of - * device handler objects. - * - * The main idea is to create a list of device handlers, to announce all - * handlers to thepolling sequence and to maintain a list of - * polling slot objects. This slot list represents the Polling Sequence Table - * in software. - * - * Each polling slot contains information to indicate when and - * which device handler shall be executed within a given polling period. - * The sequence is then executed by iterating through this slot list. - * Handlers are invoking by calling a certain function stored in the handler list. - */ -class FixedSlotSequence { -public: - using SlotList = std::multiset; - using SlotListIter = std::multiset::iterator; - - /** - * @brief The constructor of the FixedSlotSequence object. - * - * @details The constructor takes two arguments, the period length and the init function. - * - * @param setLength The period length, expressed in ms. - */ - FixedSlotSequence(uint32_t setLengthMs); - - /** - * @brief The destructor of the FixedSlotSequence object. - * - * @details The destructor frees all allocated memory by iterating through the slotList - * and deleting all allocated resources. - */ - virtual ~FixedSlotSequence(); - - /** - * @brief This is a method to add an PollingSlot object to slotList. - * - * @details Here, a polling slot object is added to the slot list. It is appended - * to the end of the list. The list is currently NOT reordered. - * Afterwards, the iterator current is set to the beginning of the list. - * @param Object ID of the object to add - * @param setTime Value between (0 to 1) * slotLengthMs, when a FixedTimeslotTask - * will be called inside the slot period. - * @param setSequenceId ID which can be used to distinguish - * different task operations - * @param - * @param - */ - void addSlot(object_id_t handlerId, uint32_t setTime, int8_t setSequenceId, - PeriodicTaskIF* executingTask); - - /** - * Checks if the current slot shall be executed immediately after the one before. - * This allows to distinguish between grouped and not grouped handlers. - * @return - @c true if the slot has the same polling time as the previous - * - @c false else - */ - bool slotFollowsImmediately(); - - /** - * @brief This method returns the time until the next software - * component is invoked. - * - * @details - * This method is vitally important for the operation of the PST. - * By fetching the polling time of the current slot and that of the - * next one (or the first one, if the list end is reached) - * it calculates and returns the interval in milliseconds within - * which the handler execution shall take place. - * If the next slot has the same time as the current one, it is ignored - * until a slot with different time or the end of the PST is found. - */ - uint32_t getIntervalToNextSlotMs(); - - /** - * @brief This method returns the time difference between the current - * slot and the previous slot - * - * @details - * This method is vitally important for the operation of the PST. - * By fetching the polling time of the current slot and that of the previous - * one (or the last one, if the slot is the first one) it calculates and - * returns the interval in milliseconds that the handler execution shall - * be delayed. - */ - uint32_t getIntervalToPreviousSlotMs(); - - /** - * @brief This method returns the length of this FixedSlotSequence instance. - */ - uint32_t getLengthMs() const; - - /** - * @brief The method to execute the device handler entered in the current - * PollingSlot object. - * - * @details - * Within this method the device handler object to be executed is chosen by - * looking up the handler address of the current slot in the handlerMap. - * Either the device handler's talkToInterface or its listenToInterface - * method is invoked, depending on the isTalking flag of the polling slot. - * After execution the iterator current is increased or, by reaching the - * end of slotList, reset to the beginning. - */ - void executeAndAdvance(); - - /** - * @brief An iterator that indicates the current polling slot to execute. - * - * @details This is an iterator for slotList and always points to the - * polling slot which is executed next. - */ - SlotListIter current; - - /** - * Iterate through slotList and check successful creation. - * Checks if timing is ok (must be ascending) and if all handlers were found. - * @return - */ - ReturnValue_t checkSequence() const; - -protected: - - /** - * @brief This list contains all PollingSlot objects, defining order and - * execution time of the device handler objects. - * - * @details - * The slot list is a std:list object that contains all created - * PollingSlot instances. They are NOT ordered automatically, so by - * adding entries, the correct order needs to be ensured. By iterating - * through this list the polling sequence is executed. Two entries with - * identical polling times are executed immediately one after another. - */ - SlotList slotList; - - uint32_t lengthMs; -}; - -#endif /* FIXEDSLOTSEQUENCE_H_ */ +#ifndef FRAMEWORK_TASKS_FIXEDSLOTSEQUENCE_H_ +#define FRAMEWORK_TASKS_FIXEDSLOTSEQUENCE_H_ + +#include "FixedSequenceSlot.h" +#include "../objectmanager/SystemObject.h" + +#include + +/** + * @brief This class is the representation of a Polling Sequence Table in software. + * @details + * The FixedSlotSequence object maintains the dynamic execution of + * device handler objects. + * + * The main idea is to create a list of device handlers, to announce all + * handlers to thepolling sequence and to maintain a list of + * polling slot objects. This slot list represents the Polling Sequence Table + * in software. + * + * Each polling slot contains information to indicate when and + * which device handler shall be executed within a given polling period. + * The sequence is then executed by iterating through this slot list. + * Handlers are invoking by calling a certain function stored in the handler list. + */ +class FixedSlotSequence { +public: + using SlotList = std::multiset; + using SlotListIter = std::multiset::iterator; + + /** + * @brief The constructor of the FixedSlotSequence object. + * + * @details The constructor takes two arguments, the period length and the init function. + * + * @param setLength The period length, expressed in ms. + */ + FixedSlotSequence(uint32_t setLengthMs); + + /** + * @brief The destructor of the FixedSlotSequence object. + * + * @details The destructor frees all allocated memory by iterating through the slotList + * and deleting all allocated resources. + */ + virtual ~FixedSlotSequence(); + + /** + * @brief This is a method to add an PollingSlot object to slotList. + * + * @details Here, a polling slot object is added to the slot list. It is appended + * to the end of the list. The list is currently NOT reordered. + * Afterwards, the iterator current is set to the beginning of the list. + * @param Object ID of the object to add + * @param setTime Value between (0 to 1) * slotLengthMs, when a FixedTimeslotTask + * will be called inside the slot period. + * @param setSequenceId ID which can be used to distinguish + * different task operations + * @param + * @param + */ + void addSlot(object_id_t handlerId, uint32_t setTime, int8_t setSequenceId, + ExecutableObjectIF* executableObject, PeriodicTaskIF* executingTask); + + /** + * Checks if the current slot shall be executed immediately after the one before. + * This allows to distinguish between grouped and not grouped handlers. + * @return - @c true if the slot has the same polling time as the previous + * - @c false else + */ + bool slotFollowsImmediately(); + + /** + * @brief This method returns the time until the next software + * component is invoked. + * + * @details + * This method is vitally important for the operation of the PST. + * By fetching the polling time of the current slot and that of the + * next one (or the first one, if the list end is reached) + * it calculates and returns the interval in milliseconds within + * which the handler execution shall take place. + * If the next slot has the same time as the current one, it is ignored + * until a slot with different time or the end of the PST is found. + */ + uint32_t getIntervalToNextSlotMs(); + + /** + * @brief This method returns the time difference between the current + * slot and the previous slot + * + * @details + * This method is vitally important for the operation of the PST. + * By fetching the polling time of the current slot and that of the previous + * one (or the last one, if the slot is the first one) it calculates and + * returns the interval in milliseconds that the handler execution shall + * be delayed. + */ + uint32_t getIntervalToPreviousSlotMs(); + + /** + * @brief This method returns the length of this FixedSlotSequence instance. + */ + uint32_t getLengthMs() const; + + /** + * @brief The method to execute the device handler entered in the current + * PollingSlot object. + * + * @details + * Within this method the device handler object to be executed is chosen by + * looking up the handler address of the current slot in the handlerMap. + * Either the device handler's talkToInterface or its listenToInterface + * method is invoked, depending on the isTalking flag of the polling slot. + * After execution the iterator current is increased or, by reaching the + * end of slotList, reset to the beginning. + */ + void executeAndAdvance(); + + /** + * @brief An iterator that indicates the current polling slot to execute. + * + * @details This is an iterator for slotList and always points to the + * polling slot which is executed next. + */ + SlotListIter current; + + /** + * @brief Check and initialize slot list. + * @details + * Checks if timing is ok (must be ascending) and if all handlers were found. + * Also calls any initialization steps which are required after task + * creation. + * @return + */ + ReturnValue_t checkSequence() const; + + ReturnValue_t intializeSequenceAfterTaskCreation() const; + +protected: + + /** + * @brief This list contains all PollingSlot objects, defining order and + * execution time of the device handler objects. + * + * @details + * The slot list is a std:list object that contains all created + * PollingSlot instances. They are NOT ordered automatically, so by + * adding entries, the correct order needs to be ensured. By iterating + * through this list the polling sequence is executed. Two entries with + * identical polling times are executed immediately one after another. + */ + SlotList slotList; + + uint32_t lengthMs; + + bool isEmpty = false; +}; + +#endif /* FIXEDSLOTSEQUENCE_H_ */ From 64022212f97e6726feb6a5768f44897180081e20 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 27 Aug 2020 16:20:32 +0200 Subject: [PATCH 020/101] removed is empty flag --- tasks/FixedSlotSequence.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/tasks/FixedSlotSequence.h b/tasks/FixedSlotSequence.h index 8aa04a27..026d5a3d 100644 --- a/tasks/FixedSlotSequence.h +++ b/tasks/FixedSlotSequence.h @@ -152,8 +152,6 @@ protected: SlotList slotList; uint32_t lengthMs; - - bool isEmpty = false; }; #endif /* FIXEDSLOTSEQUENCE_H_ */ From 5eaf6cfd1f3afa8a02f7ce30c0e84f6a648f7193 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 4 Sep 2020 13:52:02 +0200 Subject: [PATCH 021/101] renormalizing pull request step1 --- osal/FreeRTOS/FixedTimeslotTask.cpp | 337 ++++++++++++++-------------- osal/FreeRTOS/FixedTimeslotTask.h | 202 ++++++++--------- 2 files changed, 272 insertions(+), 267 deletions(-) diff --git a/osal/FreeRTOS/FixedTimeslotTask.cpp b/osal/FreeRTOS/FixedTimeslotTask.cpp index 772c4bca..309574eb 100644 --- a/osal/FreeRTOS/FixedTimeslotTask.cpp +++ b/osal/FreeRTOS/FixedTimeslotTask.cpp @@ -1,166 +1,171 @@ -#include "FixedTimeslotTask.h" - -#include "../../serviceinterface/ServiceInterfaceStream.h" - -uint32_t FixedTimeslotTask::deadlineMissedCount = 0; -const size_t PeriodicTaskIF::MINIMUM_STACK_SIZE = configMINIMAL_STACK_SIZE; - -FixedTimeslotTask::FixedTimeslotTask(TaskName name, TaskPriority setPriority, - TaskStackSize setStack, TaskPeriod overallPeriod, - void (*setDeadlineMissedFunc)()) : - started(false), handle(nullptr), pst(overallPeriod * 1000) { - configSTACK_DEPTH_TYPE stackSize = setStack / sizeof(configSTACK_DEPTH_TYPE); - xTaskCreate(taskEntryPoint, name, stackSize, this, setPriority, &handle); - // All additional attributes are applied to the object. - this->deadlineMissedFunc = setDeadlineMissedFunc; -} - -FixedTimeslotTask::~FixedTimeslotTask() { -} - -void FixedTimeslotTask::taskEntryPoint(void* argument) { - - // The argument is re-interpreted as FixedTimeslotTask. The Task object is - // global, so it is found from any place. - FixedTimeslotTask *originalTask(reinterpret_cast(argument)); - /* Task should not start until explicitly requested, - * but in FreeRTOS, tasks start as soon as they are created if the scheduler - * is running but not if the scheduler is not running. - * To be able to accommodate both cases we check a member which is set in - * #startTask(). If it is not set and we get here, the scheduler was started - * before #startTask() was called and we need to suspend if it is set, - * the scheduler was not running before #startTask() was called and we - * can continue */ - - if (not originalTask->started) { - vTaskSuspend(NULL); - } - - originalTask->taskFunctionality(); - sif::debug << "Polling task " << originalTask->handle - << " returned from taskFunctionality." << std::endl; -} - -void FixedTimeslotTask::missedDeadlineCounter() { - FixedTimeslotTask::deadlineMissedCount++; - if (FixedTimeslotTask::deadlineMissedCount % 10 == 0) { - sif::error << "PST missed " << FixedTimeslotTask::deadlineMissedCount - << " deadlines." << std::endl; - } -} - -ReturnValue_t FixedTimeslotTask::startTask() { - started = true; - - // We must not call resume if scheduler is not started yet - if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { - vTaskResume(handle); - } - - return HasReturnvaluesIF::RETURN_OK; -} - -ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId, - uint32_t slotTimeMs, int8_t executionStep) { - ExecutableObjectIF* handler = - objectManager->get(componentId); - if (handler != nullptr) { - pst.addSlot(componentId, slotTimeMs, executionStep, handler, this); - return HasReturnvaluesIF::RETURN_OK; - } - - sif::error << "Component " << std::hex << componentId << - " not found, not adding it to pst" << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; -} - -uint32_t FixedTimeslotTask::getPeriodMs() const { - return pst.getLengthMs(); -} - -ReturnValue_t FixedTimeslotTask::checkSequence() const { - return pst.checkSequence(); -} - -void FixedTimeslotTask::taskFunctionality() { - // A local iterator for the Polling Sequence Table is created to find the - // start time for the first entry. - auto slotListIter = pst.current; - - pst.intializeSequenceAfterTaskCreation(); - - //The start time for the first entry is read. - uint32_t intervalMs = slotListIter->pollingTimeMs; - TickType_t interval = pdMS_TO_TICKS(intervalMs); - - TickType_t xLastWakeTime; - /* The xLastWakeTime variable needs to be initialized with the current tick - count. Note that this is the only time the variable is written to - explicitly. After this assignment, xLastWakeTime is updated automatically - internally within vTaskDelayUntil(). */ - xLastWakeTime = xTaskGetTickCount(); - - // wait for first entry's start time - if(interval > 0) { - vTaskDelayUntil(&xLastWakeTime, interval); - } - - /* Enter the loop that defines the task behavior. */ - for (;;) { - //The component for this slot is executed and the next one is chosen. - this->pst.executeAndAdvance(); - if (not pst.slotFollowsImmediately()) { - // Get the interval till execution of the next slot. - intervalMs = this->pst.getIntervalToPreviousSlotMs(); - interval = pdMS_TO_TICKS(intervalMs); - - checkMissedDeadline(xLastWakeTime, interval); - - // Wait for the interval. This exits immediately if a deadline was - // missed while also updating the last wake time. - vTaskDelayUntil(&xLastWakeTime, interval); - } - } -} - -void FixedTimeslotTask::checkMissedDeadline(const TickType_t xLastWakeTime, - const TickType_t interval) { - /* Check whether deadline was missed while also taking overflows - * into account. Drawing this on paper with a timeline helps to understand - * it. */ - TickType_t currentTickCount = xTaskGetTickCount(); - TickType_t timeToWake = xLastWakeTime + interval; - // Time to wake has not overflown. - if(timeToWake > xLastWakeTime) { - /* If the current time has overflown exclusively or the current - * tick count is simply larger than the time to wake, a deadline was - * missed */ - if((currentTickCount < xLastWakeTime) or (currentTickCount > timeToWake)) { - handleMissedDeadline(); - } - } - /* Time to wake has overflown. A deadline was missed if the current time - * is larger than the time to wake */ - else if((timeToWake < xLastWakeTime) and (currentTickCount > timeToWake)) { - handleMissedDeadline(); - } -} - -void FixedTimeslotTask::handleMissedDeadline() { -#ifdef DEBUG - sif::warning << "FixedTimeslotTask: " << pcTaskGetName(NULL) << - " missed deadline!\n" << std::flush; -#endif - if(deadlineMissedFunc != nullptr) { - this->deadlineMissedFunc(); - } -} - -ReturnValue_t FixedTimeslotTask::sleepFor(uint32_t ms) { - vTaskDelay(pdMS_TO_TICKS(ms)); - return HasReturnvaluesIF::RETURN_OK; -} - -TaskHandle_t FixedTimeslotTask::getTaskHandle() { - return handle; -} +#include "FixedTimeslotTask.h" + +#include "../../serviceinterface/ServiceInterfaceStream.h" + +uint32_t FixedTimeslotTask::deadlineMissedCount = 0; +const size_t PeriodicTaskIF::MINIMUM_STACK_SIZE = configMINIMAL_STACK_SIZE; + +FixedTimeslotTask::FixedTimeslotTask(TaskName name, TaskPriority setPriority, + TaskStackSize setStack, TaskPeriod overallPeriod, + void (*setDeadlineMissedFunc)()) : + started(false), handle(nullptr), pst(overallPeriod * 1000) { + configSTACK_DEPTH_TYPE stackSize = setStack / sizeof(configSTACK_DEPTH_TYPE); + xTaskCreate(taskEntryPoint, name, stackSize, this, setPriority, &handle); + // All additional attributes are applied to the object. + this->deadlineMissedFunc = setDeadlineMissedFunc; +} + +FixedTimeslotTask::~FixedTimeslotTask() { +} + +void FixedTimeslotTask::taskEntryPoint(void* argument) { + + // The argument is re-interpreted as FixedTimeslotTask. The Task object is + // global, so it is found from any place. + FixedTimeslotTask *originalTask(reinterpret_cast(argument)); + /* Task should not start until explicitly requested, + * but in FreeRTOS, tasks start as soon as they are created if the scheduler + * is running but not if the scheduler is not running. + * To be able to accommodate both cases we check a member which is set in + * #startTask(). If it is not set and we get here, the scheduler was started + * before #startTask() was called and we need to suspend if it is set, + * the scheduler was not running before #startTask() was called and we + * can continue */ + + if (not originalTask->started) { + vTaskSuspend(NULL); + } + + originalTask->taskFunctionality(); + sif::debug << "Polling task " << originalTask->handle + << " returned from taskFunctionality." << std::endl; +} + +void FixedTimeslotTask::missedDeadlineCounter() { + FixedTimeslotTask::deadlineMissedCount++; + if (FixedTimeslotTask::deadlineMissedCount % 10 == 0) { + sif::error << "PST missed " << FixedTimeslotTask::deadlineMissedCount + << " deadlines." << std::endl; + } +} + +ReturnValue_t FixedTimeslotTask::startTask() { + started = true; + + // We must not call resume if scheduler is not started yet + if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { + vTaskResume(handle); + } + + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId, + uint32_t slotTimeMs, int8_t executionStep) { + ExecutableObjectIF* handler = + objectManager->get(componentId); + if (handler != nullptr) { + pst.addSlot(componentId, slotTimeMs, executionStep, handler, this); + return HasReturnvaluesIF::RETURN_OK; + } + + sif::error << "Component " << std::hex << componentId << + " not found, not adding it to pst" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; +} + +uint32_t FixedTimeslotTask::getPeriodMs() const { + return pst.getLengthMs(); +} + +ReturnValue_t FixedTimeslotTask::checkSequence() const { + return pst.checkSequence(); +} + +void FixedTimeslotTask::taskFunctionality() { + // A local iterator for the Polling Sequence Table is created to find the + // start time for the first entry. + auto slotListIter = pst.current; + + pst.intializeSequenceAfterTaskCreation(); + + //The start time for the first entry is read. + uint32_t intervalMs = slotListIter->pollingTimeMs; + TickType_t interval = pdMS_TO_TICKS(intervalMs); + + TickType_t xLastWakeTime; + /* The xLastWakeTime variable needs to be initialized with the current tick + count. Note that this is the only time the variable is written to + explicitly. After this assignment, xLastWakeTime is updated automatically + internally within vTaskDelayUntil(). */ + xLastWakeTime = xTaskGetTickCount(); + + // wait for first entry's start time + if(interval > 0) { + vTaskDelayUntil(&xLastWakeTime, interval); + } + + /* Enter the loop that defines the task behavior. */ + for (;;) { + //The component for this slot is executed and the next one is chosen. + this->pst.executeAndAdvance(); + if (not pst.slotFollowsImmediately()) { + // Get the interval till execution of the next slot. + intervalMs = this->pst.getIntervalToPreviousSlotMs(); + interval = pdMS_TO_TICKS(intervalMs); + + checkMissedDeadline(xLastWakeTime, interval); + + // Wait for the interval. This exits immediately if a deadline was + // missed while also updating the last wake time. + vTaskDelayUntil(&xLastWakeTime, interval); + } + } +} + +void FixedTimeslotTask::checkMissedDeadline(const TickType_t xLastWakeTime, + const TickType_t interval) { + /* Check whether deadline was missed while also taking overflows + * into account. Drawing this on paper with a timeline helps to understand + * it. */ + TickType_t currentTickCount = xTaskGetTickCount(); + TickType_t timeToWake = xLastWakeTime + interval; + // Time to wake has not overflown. + if(timeToWake > xLastWakeTime) { + /* If the current time has overflown exclusively or the current + * tick count is simply larger than the time to wake, a deadline was + * missed */ + if((currentTickCount < xLastWakeTime) or (currentTickCount > timeToWake)) { + handleMissedDeadline(); + } + } + /* Time to wake has overflown. A deadline was missed if the current time + * is larger than the time to wake */ + else if((timeToWake < xLastWakeTime) and (currentTickCount > timeToWake)) { + handleMissedDeadline(); + } +} + +void FixedTimeslotTask::handleMissedDeadline() { + if(deadlineMissedFunc != nullptr) { + this->deadlineMissedFunc(); + } + +#ifdef DEBUG + object_id_t handlerId = pst.current->handlerId; + sif::warning << "FixedTimeslotTask: " << pcTaskGetName(NULL) << " with" + << " object ID 0x" << std::setfill('0') << std::setw(8) << std::hex + << handlerId << " missed deadline!" << std::setfill(' ') + << std::dec << std::endl; +#endif + +} + +ReturnValue_t FixedTimeslotTask::sleepFor(uint32_t ms) { + vTaskDelay(pdMS_TO_TICKS(ms)); + return HasReturnvaluesIF::RETURN_OK; +} + +TaskHandle_t FixedTimeslotTask::getTaskHandle() { + return handle; +} diff --git a/osal/FreeRTOS/FixedTimeslotTask.h b/osal/FreeRTOS/FixedTimeslotTask.h index 42af14b8..c46de5b7 100644 --- a/osal/FreeRTOS/FixedTimeslotTask.h +++ b/osal/FreeRTOS/FixedTimeslotTask.h @@ -1,101 +1,101 @@ -#ifndef FRAMEWORK_OSAL_FREERTOS_FIXEDTIMESLOTTASK_H_ -#define FRAMEWORK_OSAL_FREERTOS_FIXEDTIMESLOTTASK_H_ - -#include "../../osal/FreeRTOS/FreeRTOSTaskIF.h" -#include "../../tasks/FixedSlotSequence.h" -#include "../../tasks/FixedTimeslotTaskIF.h" -#include "../../tasks/Typedef.h" - -#include -#include - -class FixedTimeslotTask: public FixedTimeslotTaskIF, public FreeRTOSTaskIF { -public: - - /** - * Keep in mind that you need to call before vTaskStartScheduler()! - * A lot of task parameters are set in "FreeRTOSConfig.h". - * @param name Name of the task, lenght limited by configMAX_TASK_NAME_LEN - * @param setPriority Number of priorities specified by - * configMAX_PRIORITIES. High taskPriority_ number means high priority. - * @param setStack Stack size in words (not bytes!). - * Lower limit specified by configMINIMAL_STACK_SIZE - * @param overallPeriod Period in seconds. - * @param setDeadlineMissedFunc Callback if a deadline was missed. - * @return Pointer to the newly created task. - */ - FixedTimeslotTask(TaskName name, TaskPriority setPriority, - TaskStackSize setStack, TaskPeriod overallPeriod, - void (*setDeadlineMissedFunc)()); - - /** - * @brief The destructor of the class. - * @details - * The destructor frees all heap memory that was allocated on thread - * initialization for the PST and the device handlers. This is done by - * calling the PST's destructor. - */ - virtual ~FixedTimeslotTask(void); - - ReturnValue_t startTask(void); - /** - * This static function can be used as #deadlineMissedFunc. - * It counts missedDeadlines and prints the number of missed deadlines - * every 10th time. - */ - static void missedDeadlineCounter(); - /** - * A helper variable to count missed deadlines. - */ - static uint32_t deadlineMissedCount; - - ReturnValue_t addSlot(object_id_t componentId, uint32_t slotTimeMs, - int8_t executionStep) override; - - uint32_t getPeriodMs() const override; - - ReturnValue_t checkSequence() const override; - - ReturnValue_t sleepFor(uint32_t ms) override; - - TaskHandle_t getTaskHandle() override; - -protected: - bool started; - TaskHandle_t handle; - - FixedSlotSequence pst; - - /** - * @brief This attribute holds a function pointer that is executed when - * a deadline was missed. - * @details - * Another function may be announced to determine the actions to perform - * when a deadline was missed. Currently, only one function for missing - * any deadline is allowed. If not used, it shall be declared NULL. - */ - void (*deadlineMissedFunc)(void); - /** - * @brief This is the entry point for a new task. - * @details - * This method starts the task by calling taskFunctionality(), as soon as - * all requirements (task scheduler has started and startTask() - * has been called) are met. - */ - static void taskEntryPoint(void* argument); - - /** - * @brief This function holds the main functionality of the thread. - * @details - * Core function holding the main functionality of the task - * It links the functionalities provided by FixedSlotSequence with the - * OS's System Calls to keep the timing of the periods. - */ - void taskFunctionality(void); - - void checkMissedDeadline(const TickType_t xLastWakeTime, - const TickType_t interval); - void handleMissedDeadline(); -}; - -#endif /* POLLINGTASK_H_ */ +#ifndef FRAMEWORK_OSAL_FREERTOS_FIXEDTIMESLOTTASK_H_ +#define FRAMEWORK_OSAL_FREERTOS_FIXEDTIMESLOTTASK_H_ + +#include "../../osal/FreeRTOS/FreeRTOSTaskIF.h" +#include "../../tasks/FixedSlotSequence.h" +#include "../../tasks/FixedTimeslotTaskIF.h" +#include "../../tasks/Typedef.h" + +#include +#include + +class FixedTimeslotTask: public FixedTimeslotTaskIF, public FreeRTOSTaskIF { +public: + + /** + * Keep in mind that you need to call before vTaskStartScheduler()! + * A lot of task parameters are set in "FreeRTOSConfig.h". + * @param name Name of the task, lenght limited by configMAX_TASK_NAME_LEN + * @param setPriority Number of priorities specified by + * configMAX_PRIORITIES. High taskPriority_ number means high priority. + * @param setStack Stack size in words (not bytes!). + * Lower limit specified by configMINIMAL_STACK_SIZE + * @param overallPeriod Period in seconds. + * @param setDeadlineMissedFunc Callback if a deadline was missed. + * @return Pointer to the newly created task. + */ + FixedTimeslotTask(TaskName name, TaskPriority setPriority, + TaskStackSize setStack, TaskPeriod overallPeriod, + void (*setDeadlineMissedFunc)()); + + /** + * @brief The destructor of the class. + * @details + * The destructor frees all heap memory that was allocated on thread + * initialization for the PST and the device handlers. This is done by + * calling the PST's destructor. + */ + virtual ~FixedTimeslotTask(void); + + ReturnValue_t startTask(void); + /** + * This static function can be used as #deadlineMissedFunc. + * It counts missedDeadlines and prints the number of missed deadlines + * every 10th time. + */ + static void missedDeadlineCounter(); + /** + * A helper variable to count missed deadlines. + */ + static uint32_t deadlineMissedCount; + + ReturnValue_t addSlot(object_id_t componentId, uint32_t slotTimeMs, + int8_t executionStep) override; + + uint32_t getPeriodMs() const override; + + ReturnValue_t checkSequence() const override; + + ReturnValue_t sleepFor(uint32_t ms) override; + + TaskHandle_t getTaskHandle() override; + +protected: + bool started; + TaskHandle_t handle; + + FixedSlotSequence pst; + + /** + * @brief This attribute holds a function pointer that is executed when + * a deadline was missed. + * @details + * Another function may be announced to determine the actions to perform + * when a deadline was missed. Currently, only one function for missing + * any deadline is allowed. If not used, it shall be declared NULL. + */ + void (*deadlineMissedFunc)(void); + /** + * @brief This is the entry point for a new task. + * @details + * This method starts the task by calling taskFunctionality(), as soon as + * all requirements (task scheduler has started and startTask() + * has been called) are met. + */ + static void taskEntryPoint(void* argument); + + /** + * @brief This function holds the main functionality of the thread. + * @details + * Core function holding the main functionality of the task + * It links the functionalities provided by FixedSlotSequence with the + * OS's System Calls to keep the timing of the periods. + */ + void taskFunctionality(void); + + void checkMissedDeadline(const TickType_t xLastWakeTime, + const TickType_t interval); + void handleMissedDeadline(); +}; + +#endif /* POLLINGTASK_H_ */ From 04532b8f6b4bbd661e53ac4b19e37824c73bd2fa Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 4 Sep 2020 13:52:54 +0200 Subject: [PATCH 022/101] renormalizing pull request step2 --- tasks/FixedSequenceSlot.cpp | 34 ++-- tasks/FixedSequenceSlot.h | 116 ++++++------- tasks/FixedSlotSequence.cpp | 294 ++++++++++++++++----------------- tasks/FixedSlotSequence.h | 316 ++++++++++++++++++------------------ 4 files changed, 382 insertions(+), 378 deletions(-) diff --git a/tasks/FixedSequenceSlot.cpp b/tasks/FixedSequenceSlot.cpp index 5fe49523..d7aeff0a 100644 --- a/tasks/FixedSequenceSlot.cpp +++ b/tasks/FixedSequenceSlot.cpp @@ -1,17 +1,17 @@ -#include "FixedSequenceSlot.h" -#include "../objectmanager/SystemObjectIF.h" -#include - -FixedSequenceSlot::FixedSequenceSlot(object_id_t handlerId, uint32_t setTime, - int8_t setSequenceId, ExecutableObjectIF* executableObject, - PeriodicTaskIF* executingTask) : - pollingTimeMs(setTime), opcode(setSequenceId) { - if(executableObject == nullptr) { - return; - } - this->executableObject = executableObject; - this->executableObject->setTaskIF(executingTask); -} - -FixedSequenceSlot::~FixedSequenceSlot() {} - +#include "../objectmanager/SystemObjectIF.h" +#include "../tasks/FixedSequenceSlot.h" +#include + +FixedSequenceSlot::FixedSequenceSlot(object_id_t handlerId, uint32_t setTime, + int8_t setSequenceId, ExecutableObjectIF* executableObject, + PeriodicTaskIF* executingTask) : handlerId(handlerId), + pollingTimeMs(setTime), opcode(setSequenceId) { + if(executableObject == nullptr) { + return; + } + this->executableObject = executableObject; + this->executableObject->setTaskIF(executingTask); +} + +FixedSequenceSlot::~FixedSequenceSlot() {} + diff --git a/tasks/FixedSequenceSlot.h b/tasks/FixedSequenceSlot.h index 9cf5894c..151173e9 100644 --- a/tasks/FixedSequenceSlot.h +++ b/tasks/FixedSequenceSlot.h @@ -1,57 +1,59 @@ -#ifndef FRAMEWORK_TASKS_FIXEDSEQUENCESLOT_H_ -#define FRAMEWORK_TASKS_FIXEDSEQUENCESLOT_H_ - -#include "../objectmanager/ObjectManagerIF.h" -#include "../tasks/ExecutableObjectIF.h" -class PeriodicTaskIF; - -/** - * @brief This class is the representation of a single polling sequence - * table entry. - * @details - * The PollingSlot class is the representation of a single polling - * sequence table entry. - * @author baetz - */ -class FixedSequenceSlot { -public: - FixedSequenceSlot( object_id_t handlerId, uint32_t setTimeMs, - int8_t setSequenceId, ExecutableObjectIF* executableObject, - PeriodicTaskIF* executingTask); - virtual ~FixedSequenceSlot(); - - /** - * @brief Handler identifies which object is executed in this slot. - */ - ExecutableObjectIF* executableObject = nullptr; - - /** - * @brief This attribute defines when a device handler object is executed. - * @details - * The pollingTime attribute identifies the time the handler is - * executed in ms. It must be smaller than the period length of the - * polling sequence. - */ - uint32_t pollingTimeMs; - - /** - * @brief This value defines the type of device communication. - * - * @details The state of this value decides what communication routine is - * called in the PST executable or the device handler object. - */ - uint8_t opcode; - - /** - * @brief Operator overload for the comparison operator to - * allow sorting by polling time. - * @param fixedSequenceSlot - * @return - */ - bool operator <(const FixedSequenceSlot & fixedSequenceSlot) const { - return pollingTimeMs < fixedSequenceSlot.pollingTimeMs; - } -}; - - -#endif /* FIXEDSEQUENCESLOT_H_ */ +#ifndef FRAMEWORK_TASKS_FIXEDSEQUENCESLOT_H_ +#define FRAMEWORK_TASKS_FIXEDSEQUENCESLOT_H_ + +#include "../objectmanager/ObjectManagerIF.h" +#include "../tasks/ExecutableObjectIF.h" +class PeriodicTaskIF; + +/** + * @brief This class is the representation of a single polling sequence + * table entry. + * @details + * The PollingSlot class is the representation of a single polling + * sequence table entry. + * @author baetz + */ +class FixedSequenceSlot { +public: + FixedSequenceSlot( object_id_t handlerId, uint32_t setTimeMs, + int8_t setSequenceId, ExecutableObjectIF* executableObject, + PeriodicTaskIF* executingTask); + virtual ~FixedSequenceSlot(); + + object_id_t handlerId; + + /** + * @brief Handler identifies which object is executed in this slot. + */ + ExecutableObjectIF* executableObject = nullptr; + + /** + * @brief This attribute defines when a device handler object is executed. + * @details + * The pollingTime attribute identifies the time the handler is + * executed in ms. It must be smaller than the period length of the + * polling sequence. + */ + uint32_t pollingTimeMs; + + /** + * @brief This value defines the type of device communication. + * + * @details The state of this value decides what communication routine is + * called in the PST executable or the device handler object. + */ + uint8_t opcode; + + /** + * @brief Operator overload for the comparison operator to + * allow sorting by polling time. + * @param fixedSequenceSlot + * @return + */ + bool operator <(const FixedSequenceSlot & fixedSequenceSlot) const { + return pollingTimeMs < fixedSequenceSlot.pollingTimeMs; + } +}; + + +#endif /* FIXEDSEQUENCESLOT_H_ */ diff --git a/tasks/FixedSlotSequence.cpp b/tasks/FixedSlotSequence.cpp index 78f512ca..59859ce5 100644 --- a/tasks/FixedSlotSequence.cpp +++ b/tasks/FixedSlotSequence.cpp @@ -1,147 +1,147 @@ -#include "FixedSlotSequence.h" -#include "../serviceinterface/ServiceInterfaceStream.h" -#include - -FixedSlotSequence::FixedSlotSequence(uint32_t setLengthMs) : - lengthMs(setLengthMs) { - current = slotList.begin(); -} - -FixedSlotSequence::~FixedSlotSequence() { - // Call the destructor on each list entry. - slotList.clear(); -} - -void FixedSlotSequence::executeAndAdvance() { - current->executableObject->performOperation(current->opcode); -// if (returnValue != RETURN_OK) { -// this->sendErrorMessage( returnValue ); -// } - //Increment the polling Sequence iterator - this->current++; - //Set it to the beginning, if the list's end is reached. - if (this->current == this->slotList.end()) { - this->current = this->slotList.begin(); - } -} - -uint32_t FixedSlotSequence::getIntervalToNextSlotMs() { - uint32_t oldTime; - SlotListIter slotListIter = current; - // Get the pollingTimeMs of the current slot object. - oldTime = slotListIter->pollingTimeMs; - // Advance to the next object. - slotListIter++; - // Find the next interval which is not 0. - while (slotListIter != slotList.end()) { - if (oldTime != slotListIter->pollingTimeMs) { - return slotListIter->pollingTimeMs - oldTime; - } else { - slotListIter++; - } - } - // If the list end is reached (this is definitely an interval != 0), - // the interval is calculated by subtracting the remaining time of the PST - // and adding the start time of the first handler in the list. - slotListIter = slotList.begin(); - return lengthMs - oldTime + slotListIter->pollingTimeMs; -} - -uint32_t FixedSlotSequence::getIntervalToPreviousSlotMs() { - uint32_t currentTime; - SlotListIter slotListIter = current; - // Get the pollingTimeMs of the current slot object. - currentTime = slotListIter->pollingTimeMs; - - //if it is the first slot, calculate difference to last slot - if (slotListIter == slotList.begin()){ - return lengthMs - (--slotList.end())->pollingTimeMs + currentTime; - } - // get previous slot - slotListIter--; - - return currentTime - slotListIter->pollingTimeMs; -} - -bool FixedSlotSequence::slotFollowsImmediately() { - uint32_t currentTime = current->pollingTimeMs; - SlotListIter fixedSequenceIter = this->current; - // Get the pollingTimeMs of the current slot object. - if (fixedSequenceIter == slotList.begin()) - return false; - fixedSequenceIter--; - if (fixedSequenceIter->pollingTimeMs == currentTime) { - return true; - } else { - return false; - } -} - -uint32_t FixedSlotSequence::getLengthMs() const { - return this->lengthMs; -} - -void FixedSlotSequence::addSlot(object_id_t componentId, uint32_t slotTimeMs, - int8_t executionStep, ExecutableObjectIF* executableObject, - PeriodicTaskIF* executingTask) { - this->slotList.insert(FixedSequenceSlot(componentId, slotTimeMs, - executionStep, executableObject, executingTask)); - this->current = slotList.begin(); -} - -ReturnValue_t FixedSlotSequence::checkSequence() const { - if(slotList.empty()) { - sif::error << "Fixed Slot Sequence: Slot list is empty!" << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; - } - - uint32_t count = 0; - uint32_t time = 0; - for(const auto& slot: slotList) { - if (slot.executableObject == nullptr) { - count++; - } - else if (slot.pollingTimeMs < time) { - sif::error << "FixedSlotSequence::initialize: Time: " - << slot.pollingTimeMs << " is smaller than previous with " - << time << std::endl; - count++; - } - else { - // All ok, print slot. - //sif::info << "Current slot polling time: " << std::endl; - //sif::info << std::dec << slotIt->pollingTimeMs << std::endl; - } - time = slot.pollingTimeMs; - - } - //sif::info << "Number of elements in slot list: " - // << slotList.size() << std::endl; - if (count > 0) { - return HasReturnvaluesIF::RETURN_FAILED; - } - return HasReturnvaluesIF::RETURN_OK; -} - - -ReturnValue_t FixedSlotSequence::intializeSequenceAfterTaskCreation() const { - std::set uniqueObjects; - uint32_t count = 0; - for(const auto& slot: slotList) { - // Ensure that each unique object is initialized once. - if(uniqueObjects.find(slot.executableObject) == uniqueObjects.end()) { - ReturnValue_t result = - slot.executableObject->initializeAfterTaskCreation(); - if(result != HasReturnvaluesIF::RETURN_OK) { - count++; - } - uniqueObjects.emplace(slot.executableObject); - } - } - if (count > 0) { - sif::error << "FixedSlotSequence::intializeSequenceAfterTaskCreation:" - "Counted " << count << " failed initializations!" << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; - } - return HasReturnvaluesIF::RETURN_OK; -} +#include "../serviceinterface/ServiceInterfaceStream.h" +#include "../tasks/FixedSlotSequence.h" +#include + +FixedSlotSequence::FixedSlotSequence(uint32_t setLengthMs) : + lengthMs(setLengthMs) { + current = slotList.begin(); +} + +FixedSlotSequence::~FixedSlotSequence() { + // Call the destructor on each list entry. + slotList.clear(); +} + +void FixedSlotSequence::executeAndAdvance() { + current->executableObject->performOperation(current->opcode); +// if (returnValue != RETURN_OK) { +// this->sendErrorMessage( returnValue ); +// } + //Increment the polling Sequence iterator + this->current++; + //Set it to the beginning, if the list's end is reached. + if (this->current == this->slotList.end()) { + this->current = this->slotList.begin(); + } +} + +uint32_t FixedSlotSequence::getIntervalToNextSlotMs() { + uint32_t oldTime; + SlotListIter slotListIter = current; + // Get the pollingTimeMs of the current slot object. + oldTime = slotListIter->pollingTimeMs; + // Advance to the next object. + slotListIter++; + // Find the next interval which is not 0. + while (slotListIter != slotList.end()) { + if (oldTime != slotListIter->pollingTimeMs) { + return slotListIter->pollingTimeMs - oldTime; + } else { + slotListIter++; + } + } + // If the list end is reached (this is definitely an interval != 0), + // the interval is calculated by subtracting the remaining time of the PST + // and adding the start time of the first handler in the list. + slotListIter = slotList.begin(); + return lengthMs - oldTime + slotListIter->pollingTimeMs; +} + +uint32_t FixedSlotSequence::getIntervalToPreviousSlotMs() { + uint32_t currentTime; + SlotListIter slotListIter = current; + // Get the pollingTimeMs of the current slot object. + currentTime = slotListIter->pollingTimeMs; + + //if it is the first slot, calculate difference to last slot + if (slotListIter == slotList.begin()){ + return lengthMs - (--slotList.end())->pollingTimeMs + currentTime; + } + // get previous slot + slotListIter--; + + return currentTime - slotListIter->pollingTimeMs; +} + +bool FixedSlotSequence::slotFollowsImmediately() { + uint32_t currentTime = current->pollingTimeMs; + SlotListIter fixedSequenceIter = this->current; + // Get the pollingTimeMs of the current slot object. + if (fixedSequenceIter == slotList.begin()) + return false; + fixedSequenceIter--; + if (fixedSequenceIter->pollingTimeMs == currentTime) { + return true; + } else { + return false; + } +} + +uint32_t FixedSlotSequence::getLengthMs() const { + return this->lengthMs; +} + +void FixedSlotSequence::addSlot(object_id_t componentId, uint32_t slotTimeMs, + int8_t executionStep, ExecutableObjectIF* executableObject, + PeriodicTaskIF* executingTask) { + this->slotList.insert(FixedSequenceSlot(componentId, slotTimeMs, + executionStep, executableObject, executingTask)); + this->current = slotList.begin(); +} + +ReturnValue_t FixedSlotSequence::checkSequence() const { + if(slotList.empty()) { + sif::error << "Fixed Slot Sequence: Slot list is empty!" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + + uint32_t count = 0; + uint32_t time = 0; + for(const auto& slot: slotList) { + if (slot.executableObject == nullptr) { + count++; + } + else if (slot.pollingTimeMs < time) { + sif::error << "FixedSlotSequence::initialize: Time: " + << slot.pollingTimeMs << " is smaller than previous with " + << time << std::endl; + count++; + } + else { + // All ok, print slot. + //sif::info << "Current slot polling time: " << std::endl; + //sif::info << std::dec << slotIt->pollingTimeMs << std::endl; + } + time = slot.pollingTimeMs; + + } + //sif::info << "Number of elements in slot list: " + // << slotList.size() << std::endl; + if (count > 0) { + return HasReturnvaluesIF::RETURN_FAILED; + } + return HasReturnvaluesIF::RETURN_OK; +} + + +ReturnValue_t FixedSlotSequence::intializeSequenceAfterTaskCreation() const { + std::set uniqueObjects; + uint32_t count = 0; + for(const auto& slot: slotList) { + // Ensure that each unique object is initialized once. + if(uniqueObjects.find(slot.executableObject) == uniqueObjects.end()) { + ReturnValue_t result = + slot.executableObject->initializeAfterTaskCreation(); + if(result != HasReturnvaluesIF::RETURN_OK) { + count++; + } + uniqueObjects.emplace(slot.executableObject); + } + } + if (count > 0) { + sif::error << "FixedSlotSequence::intializeSequenceAfterTaskCreation:" + "Counted " << count << " failed initializations!" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + return HasReturnvaluesIF::RETURN_OK; +} diff --git a/tasks/FixedSlotSequence.h b/tasks/FixedSlotSequence.h index 026d5a3d..1140dd25 100644 --- a/tasks/FixedSlotSequence.h +++ b/tasks/FixedSlotSequence.h @@ -1,157 +1,159 @@ -#ifndef FRAMEWORK_TASKS_FIXEDSLOTSEQUENCE_H_ -#define FRAMEWORK_TASKS_FIXEDSLOTSEQUENCE_H_ - -#include "FixedSequenceSlot.h" -#include "../objectmanager/SystemObject.h" - -#include - -/** - * @brief This class is the representation of a Polling Sequence Table in software. - * @details - * The FixedSlotSequence object maintains the dynamic execution of - * device handler objects. - * - * The main idea is to create a list of device handlers, to announce all - * handlers to thepolling sequence and to maintain a list of - * polling slot objects. This slot list represents the Polling Sequence Table - * in software. - * - * Each polling slot contains information to indicate when and - * which device handler shall be executed within a given polling period. - * The sequence is then executed by iterating through this slot list. - * Handlers are invoking by calling a certain function stored in the handler list. - */ -class FixedSlotSequence { -public: - using SlotList = std::multiset; - using SlotListIter = std::multiset::iterator; - - /** - * @brief The constructor of the FixedSlotSequence object. - * - * @details The constructor takes two arguments, the period length and the init function. - * - * @param setLength The period length, expressed in ms. - */ - FixedSlotSequence(uint32_t setLengthMs); - - /** - * @brief The destructor of the FixedSlotSequence object. - * - * @details The destructor frees all allocated memory by iterating through the slotList - * and deleting all allocated resources. - */ - virtual ~FixedSlotSequence(); - - /** - * @brief This is a method to add an PollingSlot object to slotList. - * - * @details Here, a polling slot object is added to the slot list. It is appended - * to the end of the list. The list is currently NOT reordered. - * Afterwards, the iterator current is set to the beginning of the list. - * @param Object ID of the object to add - * @param setTime Value between (0 to 1) * slotLengthMs, when a FixedTimeslotTask - * will be called inside the slot period. - * @param setSequenceId ID which can be used to distinguish - * different task operations - * @param - * @param - */ - void addSlot(object_id_t handlerId, uint32_t setTime, int8_t setSequenceId, - ExecutableObjectIF* executableObject, PeriodicTaskIF* executingTask); - - /** - * Checks if the current slot shall be executed immediately after the one before. - * This allows to distinguish between grouped and not grouped handlers. - * @return - @c true if the slot has the same polling time as the previous - * - @c false else - */ - bool slotFollowsImmediately(); - - /** - * @brief This method returns the time until the next software - * component is invoked. - * - * @details - * This method is vitally important for the operation of the PST. - * By fetching the polling time of the current slot and that of the - * next one (or the first one, if the list end is reached) - * it calculates and returns the interval in milliseconds within - * which the handler execution shall take place. - * If the next slot has the same time as the current one, it is ignored - * until a slot with different time or the end of the PST is found. - */ - uint32_t getIntervalToNextSlotMs(); - - /** - * @brief This method returns the time difference between the current - * slot and the previous slot - * - * @details - * This method is vitally important for the operation of the PST. - * By fetching the polling time of the current slot and that of the previous - * one (or the last one, if the slot is the first one) it calculates and - * returns the interval in milliseconds that the handler execution shall - * be delayed. - */ - uint32_t getIntervalToPreviousSlotMs(); - - /** - * @brief This method returns the length of this FixedSlotSequence instance. - */ - uint32_t getLengthMs() const; - - /** - * @brief The method to execute the device handler entered in the current - * PollingSlot object. - * - * @details - * Within this method the device handler object to be executed is chosen by - * looking up the handler address of the current slot in the handlerMap. - * Either the device handler's talkToInterface or its listenToInterface - * method is invoked, depending on the isTalking flag of the polling slot. - * After execution the iterator current is increased or, by reaching the - * end of slotList, reset to the beginning. - */ - void executeAndAdvance(); - - /** - * @brief An iterator that indicates the current polling slot to execute. - * - * @details This is an iterator for slotList and always points to the - * polling slot which is executed next. - */ - SlotListIter current; - - /** - * @brief Check and initialize slot list. - * @details - * Checks if timing is ok (must be ascending) and if all handlers were found. - * Also calls any initialization steps which are required after task - * creation. - * @return - */ - ReturnValue_t checkSequence() const; - - ReturnValue_t intializeSequenceAfterTaskCreation() const; - -protected: - - /** - * @brief This list contains all PollingSlot objects, defining order and - * execution time of the device handler objects. - * - * @details - * The slot list is a std:list object that contains all created - * PollingSlot instances. They are NOT ordered automatically, so by - * adding entries, the correct order needs to be ensured. By iterating - * through this list the polling sequence is executed. Two entries with - * identical polling times are executed immediately one after another. - */ - SlotList slotList; - - uint32_t lengthMs; -}; - -#endif /* FIXEDSLOTSEQUENCE_H_ */ +#ifndef FRAMEWORK_TASKS_FIXEDSLOTSEQUENCE_H_ +#define FRAMEWORK_TASKS_FIXEDSLOTSEQUENCE_H_ + +#include "../objectmanager/SystemObject.h" +#include "../tasks/FixedSequenceSlot.h" + +#include + +/** + * @brief This class is the representation of a Polling Sequence Table in software. + * @details + * The FixedSlotSequence object maintains the dynamic execution of + * device handler objects. + * + * The main idea is to create a list of device handlers, to announce all + * handlers to thepolling sequence and to maintain a list of + * polling slot objects. This slot list represents the Polling Sequence Table + * in software. + * + * Each polling slot contains information to indicate when and + * which device handler shall be executed within a given polling period. + * The sequence is then executed by iterating through this slot list. + * Handlers are invoking by calling a certain function stored in the handler list. + */ +class FixedSlotSequence { +public: + using SlotList = std::multiset; + using SlotListIter = std::multiset::iterator; + + /** + * @brief The constructor of the FixedSlotSequence object. + * + * @details The constructor takes two arguments, the period length and the init function. + * + * @param setLength The period length, expressed in ms. + */ + FixedSlotSequence(uint32_t setLengthMs); + + /** + * @brief The destructor of the FixedSlotSequence object. + * + * @details The destructor frees all allocated memory by iterating through the slotList + * and deleting all allocated resources. + */ + virtual ~FixedSlotSequence(); + + /** + * @brief This is a method to add an PollingSlot object to slotList. + * + * @details Here, a polling slot object is added to the slot list. It is appended + * to the end of the list. The list is currently NOT reordered. + * Afterwards, the iterator current is set to the beginning of the list. + * @param Object ID of the object to add + * @param setTime Value between (0 to 1) * slotLengthMs, when a FixedTimeslotTask + * will be called inside the slot period. + * @param setSequenceId ID which can be used to distinguish + * different task operations + * @param + * @param + */ + void addSlot(object_id_t handlerId, uint32_t setTime, int8_t setSequenceId, + ExecutableObjectIF* executableObject, PeriodicTaskIF* executingTask); + + /** + * Checks if the current slot shall be executed immediately after the one before. + * This allows to distinguish between grouped and not grouped handlers. + * @return - @c true if the slot has the same polling time as the previous + * - @c false else + */ + bool slotFollowsImmediately(); + + /** + * @brief This method returns the time until the next software + * component is invoked. + * + * @details + * This method is vitally important for the operation of the PST. + * By fetching the polling time of the current slot and that of the + * next one (or the first one, if the list end is reached) + * it calculates and returns the interval in milliseconds within + * which the handler execution shall take place. + * If the next slot has the same time as the current one, it is ignored + * until a slot with different time or the end of the PST is found. + */ + uint32_t getIntervalToNextSlotMs(); + + /** + * @brief This method returns the time difference between the current + * slot and the previous slot + * + * @details + * This method is vitally important for the operation of the PST. + * By fetching the polling time of the current slot and that of the previous + * one (or the last one, if the slot is the first one) it calculates and + * returns the interval in milliseconds that the handler execution shall + * be delayed. + */ + uint32_t getIntervalToPreviousSlotMs(); + + /** + * @brief This method returns the length of this FixedSlotSequence instance. + */ + uint32_t getLengthMs() const; + + /** + * @brief The method to execute the device handler entered in the current + * PollingSlot object. + * + * @details + * Within this method the device handler object to be executed is chosen by + * looking up the handler address of the current slot in the handlerMap. + * Either the device handler's talkToInterface or its listenToInterface + * method is invoked, depending on the isTalking flag of the polling slot. + * After execution the iterator current is increased or, by reaching the + * end of slotList, reset to the beginning. + */ + void executeAndAdvance(); + + /** + * @brief An iterator that indicates the current polling slot to execute. + * + * @details This is an iterator for slotList and always points to the + * polling slot which is executed next. + */ + SlotListIter current; + + /** + * @brief Check and initialize slot list. + * @details + * Checks if timing is ok (must be ascending) and if all handlers were found. + * Also calls any initialization steps which are required after task + * creation. + * @return + */ + ReturnValue_t checkSequence() const; + + ReturnValue_t intializeSequenceAfterTaskCreation() const; + +protected: + + /** + * @brief This list contains all PollingSlot objects, defining order and + * execution time of the device handler objects. + * + * @details + * The slot list is a std:list object that contains all created + * PollingSlot instances. They are NOT ordered automatically, so by + * adding entries, the correct order needs to be ensured. By iterating + * through this list the polling sequence is executed. Two entries with + * identical polling times are executed immediately one after another. + */ + SlotList slotList; + + uint32_t lengthMs; + + bool isEmpty = false; +}; + +#endif /* FIXEDSLOTSEQUENCE_H_ */ From 92c736927610847f18e1899f4e9fbf577d302bda Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 4 Sep 2020 13:56:12 +0200 Subject: [PATCH 023/101] include guard fix --- osal/FreeRTOS/FixedTimeslotTask.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/osal/FreeRTOS/FixedTimeslotTask.h b/osal/FreeRTOS/FixedTimeslotTask.h index c46de5b7..7d2cdb70 100644 --- a/osal/FreeRTOS/FixedTimeslotTask.h +++ b/osal/FreeRTOS/FixedTimeslotTask.h @@ -1,7 +1,7 @@ -#ifndef FRAMEWORK_OSAL_FREERTOS_FIXEDTIMESLOTTASK_H_ -#define FRAMEWORK_OSAL_FREERTOS_FIXEDTIMESLOTTASK_H_ +#ifndef FSFW_OSAL_FREERTOS_FIXEDTIMESLOTTASK_H_ +#define FSFW_OSAL_FREERTOS_FIXEDTIMESLOTTASK_H_ -#include "../../osal/FreeRTOS/FreeRTOSTaskIF.h" +#include "FreeRTOSTaskIF.h" #include "../../tasks/FixedSlotSequence.h" #include "../../tasks/FixedTimeslotTaskIF.h" #include "../../tasks/Typedef.h" @@ -98,4 +98,4 @@ protected: void handleMissedDeadline(); }; -#endif /* POLLINGTASK_H_ */ +#endif /* FSFW_OSAL_FREERTOS_FIXEDTIMESLOTTASK_H_ */ From b8754fbc1609b05ea962133a7c5fbfbeb9e17535 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 4 Sep 2020 14:11:59 +0200 Subject: [PATCH 024/101] made fixed sequence slot doc generic --- tasks/FixedSequenceSlot.cpp | 4 +- tasks/FixedSequenceSlot.h | 9 +++-- tasks/FixedSlotSequence.cpp | 2 +- tasks/FixedSlotSequence.h | 77 +++++++++++++++++++++---------------- 4 files changed, 51 insertions(+), 41 deletions(-) diff --git a/tasks/FixedSequenceSlot.cpp b/tasks/FixedSequenceSlot.cpp index d7aeff0a..f5d82178 100644 --- a/tasks/FixedSequenceSlot.cpp +++ b/tasks/FixedSequenceSlot.cpp @@ -1,5 +1,5 @@ -#include "../objectmanager/SystemObjectIF.h" -#include "../tasks/FixedSequenceSlot.h" +#include "FixedSequenceSlot.h" +#include "PeriodicTaskIF.h" #include FixedSequenceSlot::FixedSequenceSlot(object_id_t handlerId, uint32_t setTime, diff --git a/tasks/FixedSequenceSlot.h b/tasks/FixedSequenceSlot.h index 151173e9..1744ec19 100644 --- a/tasks/FixedSequenceSlot.h +++ b/tasks/FixedSequenceSlot.h @@ -1,8 +1,9 @@ -#ifndef FRAMEWORK_TASKS_FIXEDSEQUENCESLOT_H_ -#define FRAMEWORK_TASKS_FIXEDSEQUENCESLOT_H_ +#ifndef FSFW_TASKS_FIXEDSEQUENCESLOT_H_ +#define FSFW_TASKS_FIXEDSEQUENCESLOT_H_ +#include "ExecutableObjectIF.h" #include "../objectmanager/ObjectManagerIF.h" -#include "../tasks/ExecutableObjectIF.h" + class PeriodicTaskIF; /** @@ -56,4 +57,4 @@ public: }; -#endif /* FIXEDSEQUENCESLOT_H_ */ +#endif /* FSFW_TASKS_FIXEDSEQUENCESLOT_H_ */ diff --git a/tasks/FixedSlotSequence.cpp b/tasks/FixedSlotSequence.cpp index 59859ce5..2467671b 100644 --- a/tasks/FixedSlotSequence.cpp +++ b/tasks/FixedSlotSequence.cpp @@ -1,5 +1,5 @@ +#include "FixedSlotSequence.h" #include "../serviceinterface/ServiceInterfaceStream.h" -#include "../tasks/FixedSlotSequence.h" #include FixedSlotSequence::FixedSlotSequence(uint32_t setLengthMs) : diff --git a/tasks/FixedSlotSequence.h b/tasks/FixedSlotSequence.h index 1140dd25..056e0bb5 100644 --- a/tasks/FixedSlotSequence.h +++ b/tasks/FixedSlotSequence.h @@ -1,26 +1,30 @@ -#ifndef FRAMEWORK_TASKS_FIXEDSLOTSEQUENCE_H_ -#define FRAMEWORK_TASKS_FIXEDSLOTSEQUENCE_H_ +#ifndef FSFW_TASKS_FIXEDSLOTSEQUENCE_H_ +#define FSFW_TASKS_FIXEDSLOTSEQUENCE_H_ +#include "FixedSequenceSlot.h" #include "../objectmanager/SystemObject.h" -#include "../tasks/FixedSequenceSlot.h" #include /** - * @brief This class is the representation of a Polling Sequence Table in software. + * @brief This class is the representation of a + * Polling Sequence Table in software. * @details * The FixedSlotSequence object maintains the dynamic execution of - * device handler objects. + * objects with stricter timing requirements for the FixedTimeslotTask. * - * The main idea is to create a list of device handlers, to announce all - * handlers to thepolling sequence and to maintain a list of - * polling slot objects. This slot list represents the Polling Sequence Table - * in software. + * The main idea is to create a list of executable objects (for example + * device handlers), to announce all handlers to the polling sequence and to + * maintain a list of polling slot objects. + * This slot list represents the Polling Sequence Table in software. * * Each polling slot contains information to indicate when and - * which device handler shall be executed within a given polling period. - * The sequence is then executed by iterating through this slot list. - * Handlers are invoking by calling a certain function stored in the handler list. + * which executable object shall be executed within a given polling period. + * When adding a slot, a pointer to the executing task, a pointer to the + * executable object and a step number can be passed. The step number will be + * passed to the periodic handler. + * The sequence is executed by iterating through the slot sequence and + * executing the executable object in the correct timeslot. */ class FixedSlotSequence { public: @@ -29,41 +33,44 @@ public: /** * @brief The constructor of the FixedSlotSequence object. - * - * @details The constructor takes two arguments, the period length and the init function. - * * @param setLength The period length, expressed in ms. */ FixedSlotSequence(uint32_t setLengthMs); /** * @brief The destructor of the FixedSlotSequence object. - * - * @details The destructor frees all allocated memory by iterating through the slotList - * and deleting all allocated resources. + * @details + * The destructor frees all allocated memory by iterating through the + * slotList and deleting all allocated resources. */ virtual ~FixedSlotSequence(); /** * @brief This is a method to add an PollingSlot object to slotList. * - * @details Here, a polling slot object is added to the slot list. It is appended - * to the end of the list. The list is currently NOT reordered. - * Afterwards, the iterator current is set to the beginning of the list. - * @param Object ID of the object to add - * @param setTime Value between (0 to 1) * slotLengthMs, when a FixedTimeslotTask - * will be called inside the slot period. - * @param setSequenceId ID which can be used to distinguish - * different task operations + * @details + * Here, a polling slot object is added to the slot list. It is appended + * to the end of the list. The list is currently NOT reordered. + * Afterwards, the iterator current is set to the beginning of the list. + * @param handlerId ID of the object to add + * @param setTime + * Value between (0 to 1) * slotLengthMs, when a FixedTimeslotTask + * will be called inside the slot period. + * @param setSequenceId + * ID which can be used to distinguish different task operations. This + * value will be passed to the executable function. * @param * @param */ void addSlot(object_id_t handlerId, uint32_t setTime, int8_t setSequenceId, - ExecutableObjectIF* executableObject, PeriodicTaskIF* executingTask); + ExecutableObjectIF* executableObject, + PeriodicTaskIF* executingTask); /** - * Checks if the current slot shall be executed immediately after the one before. - * This allows to distinguish between grouped and not grouped handlers. + * @brief Checks if the current slot shall be executed immediately + * after the one before. + * @details + * This allows to distinguish between grouped and separated handlers. * @return - @c true if the slot has the same polling time as the previous * - @c false else */ @@ -128,12 +135,16 @@ public: * @brief Check and initialize slot list. * @details * Checks if timing is ok (must be ascending) and if all handlers were found. - * Also calls any initialization steps which are required after task - * creation. * @return */ ReturnValue_t checkSequence() const; + /** + * @brief Perform any initialization steps required after the executing + * task has been created. This function should be called from the + * executing task! + * @return + */ ReturnValue_t intializeSequenceAfterTaskCreation() const; protected: @@ -152,8 +163,6 @@ protected: SlotList slotList; uint32_t lengthMs; - - bool isEmpty = false; }; -#endif /* FIXEDSLOTSEQUENCE_H_ */ +#endif /* FSFW_TASKS_FIXEDSLOTSEQUENCE_H_ */ From 4d7d48e8ca5206e384cf8bcd4241c0ac39f4104c Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 4 Sep 2020 14:24:34 +0200 Subject: [PATCH 025/101] added a generic way to add a custom check --- tasks/FixedSlotSequence.cpp | 27 +++++++++++++++++++++------ tasks/FixedSlotSequence.h | 4 ++++ 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/tasks/FixedSlotSequence.cpp b/tasks/FixedSlotSequence.cpp index 2467671b..e5db4301 100644 --- a/tasks/FixedSlotSequence.cpp +++ b/tasks/FixedSlotSequence.cpp @@ -91,21 +91,31 @@ void FixedSlotSequence::addSlot(object_id_t componentId, uint32_t slotTimeMs, ReturnValue_t FixedSlotSequence::checkSequence() const { if(slotList.empty()) { - sif::error << "Fixed Slot Sequence: Slot list is empty!" << std::endl; + sif::error << "FixedSlotSequence::checkSequence:" + << " Slot list is empty!" << std::endl; return HasReturnvaluesIF::RETURN_FAILED; } - uint32_t count = 0; + if(customCheckFunction != nullptr) { + ReturnValue_t result = customCheckFunction(slotList); + if(result != HasReturnvaluesIF::RETURN_OK) { + // Continue for now but print error output. + sif::error << "FixedSlotSequence::checkSequence:" + << " Custom check failed!" << std::endl; + } + } + + uint32_t errorCount = 0; uint32_t time = 0; for(const auto& slot: slotList) { if (slot.executableObject == nullptr) { - count++; + errorCount++; } else if (slot.pollingTimeMs < time) { - sif::error << "FixedSlotSequence::initialize: Time: " + sif::error << "FixedSlotSequence::checkSequence: Time: " << slot.pollingTimeMs << " is smaller than previous with " << time << std::endl; - count++; + errorCount++; } else { // All ok, print slot. @@ -117,7 +127,7 @@ ReturnValue_t FixedSlotSequence::checkSequence() const { } //sif::info << "Number of elements in slot list: " // << slotList.size() << std::endl; - if (count > 0) { + if (errorCount > 0) { return HasReturnvaluesIF::RETURN_FAILED; } return HasReturnvaluesIF::RETURN_OK; @@ -145,3 +155,8 @@ ReturnValue_t FixedSlotSequence::intializeSequenceAfterTaskCreation() const { } return HasReturnvaluesIF::RETURN_OK; } + +void FixedSlotSequence::addCustomCheck(ReturnValue_t + (*customCheckFunction)(const SlotList&)) { + this->customCheckFunction = customCheckFunction; +} diff --git a/tasks/FixedSlotSequence.h b/tasks/FixedSlotSequence.h index 056e0bb5..19a05f21 100644 --- a/tasks/FixedSlotSequence.h +++ b/tasks/FixedSlotSequence.h @@ -139,6 +139,8 @@ public: */ ReturnValue_t checkSequence() const; + void addCustomCheck(ReturnValue_t (*customCheckFunction)(const SlotList &)); + /** * @brief Perform any initialization steps required after the executing * task has been created. This function should be called from the @@ -162,6 +164,8 @@ protected: */ SlotList slotList; + ReturnValue_t (*customCheckFunction)(const SlotList&) = nullptr; + uint32_t lengthMs; }; From 0eb4c3817edb8abe0cfcf979d6fd5db9ff2a5c9d Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 4 Sep 2020 14:31:39 +0200 Subject: [PATCH 026/101] added initialize after taks creation for linux --- osal/linux/FixedTimeslotTask.cpp | 14 ++++++++++---- osal/linux/FixedTimeslotTask.h | 10 +++++----- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/osal/linux/FixedTimeslotTask.cpp b/osal/linux/FixedTimeslotTask.cpp index 858a39a7..247a34ed 100644 --- a/osal/linux/FixedTimeslotTask.cpp +++ b/osal/linux/FixedTimeslotTask.cpp @@ -1,5 +1,5 @@ -#include "../../serviceinterface/ServiceInterfaceStream.h" #include "FixedTimeslotTask.h" +#include "../../serviceinterface/ServiceInterfaceStream.h" #include @@ -39,13 +39,16 @@ uint32_t FixedTimeslotTask::getPeriodMs() const { ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId, uint32_t slotTimeMs, int8_t executionStep) { - if (objectManager->get(componentId) != nullptr) { - pst.addSlot(componentId, slotTimeMs, executionStep, this); + ExecutableObjectIF* executableObject = + objectManager->get(componentId); + if (executableObject != nullptr) { + pst.addSlot(componentId, slotTimeMs, executionStep, + executableObject,this); return HasReturnvaluesIF::RETURN_OK; } sif::error << "Component " << std::hex << componentId << - " not found, not adding it to pst" << std::endl; + " not found, not adding it to pst" << std::dec << std::endl; return HasReturnvaluesIF::RETURN_FAILED; } @@ -58,6 +61,9 @@ void FixedTimeslotTask::taskFunctionality() { if (!started) { suspend(); } + + pst.intializeSequenceAfterTaskCreation(); + //The start time for the first entry is read. uint64_t lastWakeTime = getCurrentMonotonicTimeMs(); uint64_t interval = pst.getIntervalToNextSlotMs(); diff --git a/osal/linux/FixedTimeslotTask.h b/osal/linux/FixedTimeslotTask.h index 42802b1d..5c5c1814 100644 --- a/osal/linux/FixedTimeslotTask.h +++ b/osal/linux/FixedTimeslotTask.h @@ -1,9 +1,9 @@ -#ifndef FRAMEWORK_OSAL_LINUX_FIXEDTIMESLOTTASK_H_ -#define FRAMEWORK_OSAL_LINUX_FIXEDTIMESLOTTASK_H_ +#ifndef FSFW_OSAL_LINUX_FIXEDTIMESLOTTASK_H_ +#define FSFW_OSAL_LINUX_FIXEDTIMESLOTTASK_H_ -#include "../../tasks/FixedTimeslotTaskIF.h" -#include "../../devicehandlers/FixedSlotSequence.h" #include "PosixThread.h" +#include "../../tasks/FixedTimeslotTaskIF.h" +#include "../../tasks/FixedSlotSequence.h" #include class FixedTimeslotTask: public FixedTimeslotTaskIF, public PosixThread { @@ -74,4 +74,4 @@ private: bool started; }; -#endif /* FRAMEWORK_OSAL_LINUX_FIXEDTIMESLOTTASK_H_ */ +#endif /* FSFW_OSAL_LINUX_FIXEDTIMESLOTTASK_H_ */ From a6b2b4dd934f3268c6867b450d8218ca8dcc6aba Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 4 Sep 2020 14:58:36 +0200 Subject: [PATCH 027/101] renormalization --- ipc/CommandMessage.cpp | 222 ++++++++++++++++++++--------------------- 1 file changed, 111 insertions(+), 111 deletions(-) diff --git a/ipc/CommandMessage.cpp b/ipc/CommandMessage.cpp index 16293608..513debd3 100644 --- a/ipc/CommandMessage.cpp +++ b/ipc/CommandMessage.cpp @@ -1,111 +1,111 @@ -#include "CommandMessage.h" -#include "CommandMessageCleaner.h" -#include - -CommandMessage::CommandMessage() { - MessageQueueMessage::setMessageSize(DEFAULT_COMMAND_MESSAGE_SIZE); - setCommand(CMD_NONE); -} - -CommandMessage::CommandMessage(Command_t command, uint32_t parameter1, - uint32_t parameter2) { - MessageQueueMessage::setMessageSize(DEFAULT_COMMAND_MESSAGE_SIZE); - setCommand(command); - setParameter(parameter1); - setParameter2(parameter2); -} - -Command_t CommandMessage::getCommand() const { - Command_t command; - std::memcpy(&command, MessageQueueMessage::getData(), sizeof(Command_t)); - return command; -} - -void CommandMessage::setCommand(Command_t command) { - std::memcpy(MessageQueueMessage::getData(), &command, sizeof(Command_t)); -} - -uint8_t CommandMessage::getMessageType() const { - // first byte of command ID. - return getCommand() >> 8 & 0xff; -} - -uint32_t CommandMessage::getParameter() const { - uint32_t parameter1; - std::memcpy(¶meter1, this->getData(), sizeof(parameter1)); - return parameter1; -} - -void CommandMessage::setParameter(uint32_t parameter1) { - std::memcpy(this->getData(), ¶meter1, sizeof(parameter1)); -} - -uint32_t CommandMessage::getParameter2() const { - uint32_t parameter2; - std::memcpy(¶meter2, this->getData() + sizeof(uint32_t), - sizeof(parameter2)); - return parameter2; -} - -void CommandMessage::setParameter2(uint32_t parameter2) { - std::memcpy(this->getData() + sizeof(uint32_t), ¶meter2, - sizeof(parameter2)); -} - -uint32_t CommandMessage::getParameter3() const { - uint32_t parameter3; - std::memcpy(¶meter3, this->getData() + 2 * sizeof(uint32_t), - sizeof(parameter3)); - return parameter3; -} - -void CommandMessage::setParameter3(uint32_t parameter3) { - std::memcpy(this->getData() + 2 * sizeof(uint32_t), ¶meter3, - sizeof(parameter3)); -} - -size_t CommandMessage::getMinimumMessageSize() const { - return MINIMUM_COMMAND_MESSAGE_SIZE; -} - -void CommandMessage::clearCommandMessage() { - clear(); -} - -void CommandMessage::clear() { - CommandMessageCleaner::clearCommandMessage(this); -} - -bool CommandMessage::isClearedCommandMessage() { - return getCommand() == CMD_NONE; -} - -void CommandMessage::setToUnknownCommand() { - Command_t initialCommand = getCommand(); - this->clear(); - setReplyRejected(UNKNOWN_COMMAND, initialCommand); -} - -void CommandMessage::setReplyRejected(ReturnValue_t reason, - Command_t initialCommand) { - setCommand(REPLY_REJECTED); - setParameter(reason); - setParameter2(initialCommand); -} - -ReturnValue_t CommandMessage::getReplyRejectedReason( - Command_t *initialCommand) const { - ReturnValue_t reason = getParameter(); - if(initialCommand != nullptr) { - *initialCommand = getParameter2(); - } - return reason; -} - -uint8_t* CommandMessage::getData() { - return MessageQueueMessage::getData() + sizeof(Command_t); -} - -const uint8_t* CommandMessage::getData() const { - return MessageQueueMessage::getData() + sizeof(Command_t); -} +#include "CommandMessage.h" +#include "CommandMessageCleaner.h" +#include + +CommandMessage::CommandMessage() { + MessageQueueMessage::setMessageSize(DEFAULT_COMMAND_MESSAGE_SIZE); + setCommand(CMD_NONE); +} + +CommandMessage::CommandMessage(Command_t command, uint32_t parameter1, + uint32_t parameter2) { + MessageQueueMessage::setMessageSize(DEFAULT_COMMAND_MESSAGE_SIZE); + setCommand(command); + setParameter(parameter1); + setParameter2(parameter2); +} + +Command_t CommandMessage::getCommand() const { + Command_t command; + std::memcpy(&command, MessageQueueMessage::getData(), sizeof(Command_t)); + return command; +} + +void CommandMessage::setCommand(Command_t command) { + std::memcpy(MessageQueueMessage::getData(), &command, sizeof(Command_t)); +} + +uint8_t CommandMessage::getMessageType() const { + // first byte of command ID. + return getCommand() >> 8 & 0xff; +} + +uint32_t CommandMessage::getParameter() const { + uint32_t parameter1; + std::memcpy(¶meter1, this->getData(), sizeof(parameter1)); + return parameter1; +} + +void CommandMessage::setParameter(uint32_t parameter1) { + std::memcpy(this->getData(), ¶meter1, sizeof(parameter1)); +} + +uint32_t CommandMessage::getParameter2() const { + uint32_t parameter2; + std::memcpy(¶meter2, this->getData() + sizeof(uint32_t), + sizeof(parameter2)); + return parameter2; +} + +void CommandMessage::setParameter2(uint32_t parameter2) { + std::memcpy(this->getData() + sizeof(uint32_t), ¶meter2, + sizeof(parameter2)); +} + +uint32_t CommandMessage::getParameter3() const { + uint32_t parameter3; + std::memcpy(¶meter3, this->getData() + 2 * sizeof(uint32_t), + sizeof(parameter3)); + return parameter3; +} + +void CommandMessage::setParameter3(uint32_t parameter3) { + std::memcpy(this->getData() + 2 * sizeof(uint32_t), ¶meter3, + sizeof(parameter3)); +} + +size_t CommandMessage::getMinimumMessageSize() const { + return MINIMUM_COMMAND_MESSAGE_SIZE; +} + +void CommandMessage::clearCommandMessage() { + clear(); +} + +void CommandMessage::clear() { + CommandMessageCleaner::clearCommandMessage(this); +} + +bool CommandMessage::isClearedCommandMessage() { + return getCommand() == CMD_NONE; +} + +void CommandMessage::setToUnknownCommand() { + Command_t initialCommand = getCommand(); + this->clear(); + setReplyRejected(UNKNOWN_COMMAND, initialCommand); +} + +void CommandMessage::setReplyRejected(ReturnValue_t reason, + Command_t initialCommand) { + setCommand(REPLY_REJECTED); + setParameter(reason); + setParameter2(initialCommand); +} + +ReturnValue_t CommandMessage::getReplyRejectedReason( + Command_t *initialCommand) const { + ReturnValue_t reason = getParameter(); + if(initialCommand != nullptr) { + *initialCommand = getParameter2(); + } + return reason; +} + +uint8_t* CommandMessage::getData() { + return MessageQueueMessage::getData() + sizeof(Command_t); +} + +const uint8_t* CommandMessage::getData() const { + return MessageQueueMessage::getData() + sizeof(Command_t); +} From a53b9dc3dbfd5339c81c611123341cb3fcb63eea Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 4 Sep 2020 14:59:59 +0200 Subject: [PATCH 028/101] renormalization --- ipc/CommandMessage.h | 258 ++++++++++++++--------------- ipc/CommandMessageCleaner.cpp | 90 +++++----- ipc/CommandMessageCleaner.h | 32 ++-- ipc/CommandMessageIF.h | 146 ++++++++--------- ipc/MessageQueueMessage.cpp | 168 +++++++++---------- ipc/MessageQueueMessage.h | 300 +++++++++++++++++----------------- 6 files changed, 497 insertions(+), 497 deletions(-) diff --git a/ipc/CommandMessage.h b/ipc/CommandMessage.h index 3be9a120..ca7b817f 100644 --- a/ipc/CommandMessage.h +++ b/ipc/CommandMessage.h @@ -1,129 +1,129 @@ -#ifndef FSFW_IPC_COMMANDMESSAGE_H_ -#define FSFW_IPC_COMMANDMESSAGE_H_ - -#include "CommandMessageIF.h" -#include "MessageQueueMessage.h" -#include "FwMessageTypes.h" - -/** - * @brief Default command message used to pass command messages between tasks. - * Primary message type for IPC. Contains sender, 2-byte command ID - * field, and 2 4-byte parameters. - * @details - * It operates on an external memory which is contained inside a - * class implementing MessageQueueMessageIF by taking its address. - * This allows for a more flexible designs of message implementations. - * The pointer can be passed to different message implementations without - * the need of unnecessary copying. - * - * The command message is based of the generic MessageQueueMessage which - * currently has an internal message size of 28 bytes. - * @author Bastian Baetz - */ -class CommandMessage: public MessageQueueMessage, public CommandMessageIF { -public: - /** - * Default size can accomodate 2 4-byte parameters. - */ - static constexpr size_t DEFAULT_COMMAND_MESSAGE_SIZE = - CommandMessageIF::MINIMUM_COMMAND_MESSAGE_SIZE + sizeof(uint32_t); - - /** - * @brief Default Constructor, does not initialize anything. - * @details - * This constructor should be used when receiving a Message, as the - * content is filled by the MessageQueue. - */ - CommandMessage(); - /** - * This constructor creates a new message with all message content - * initialized - * - * @param command The DeviceHandlerCommand_t that will be sent - * @param parameter1 The first parameter - * @param parameter2 The second parameter - */ - CommandMessage(Command_t command, uint32_t parameter1, uint32_t parameter2); - - /** - * @brief Default Destructor - */ - virtual ~CommandMessage() {} - - /** - * Read the DeviceHandlerCommand_t that is stored in the message, - * usually used after receiving. - * - * @return the Command stored in the Message - */ - virtual Command_t getCommand() const override; - /** - * Set the command type of the message. Default implementation also - * sets the message type, which will be the first byte of the command ID. - * @param the Command to be sent - */ - virtual void setCommand(Command_t command); - - virtual uint8_t* getData() override; - virtual const uint8_t* getData() const override; - - /** - * Get the first parameter of the message - * @return the first Parameter of the message - */ - uint32_t getParameter() const; - /** - * Set the first parameter of the message - * @param the first parameter of the message - */ - void setParameter(uint32_t parameter1); - uint32_t getParameter2() const; - void setParameter2(uint32_t parameter2); - uint32_t getParameter3() const; - void setParameter3(uint32_t parameter3); - - /** - * check if a message was cleared - * - * @return if the command is CMD_NONE - */ - bool isClearedCommandMessage(); - - /** - * Sets the command to REPLY_REJECTED with parameter UNKNOWN_COMMAND. - * Is needed quite often, so we better code it once only. - */ - void setToUnknownCommand() override; - - /** - * A command message can be rejected and needs to offer a function - * to set a rejected reply - * @param reason - * @param initialCommand - */ - void setReplyRejected(ReturnValue_t reason, - Command_t initialCommand) override; - /** - * Corrensonding getter function. - * @param initialCommand - * @return - */ - ReturnValue_t getReplyRejectedReason( - Command_t* initialCommand = nullptr) const override; - - - virtual void clear() override; - void clearCommandMessage(); - - /** - * Extract message ID, which is the first byte of the command ID for the - * default implementation. - * @return - */ - virtual uint8_t getMessageType() const override; - - /** MessageQueueMessageIF functions used for minimum size check. */ - size_t getMinimumMessageSize() const override; -}; - -#endif /* FSFW_IPC_COMMANDMESSAGE_H_ */ +#ifndef FSFW_IPC_COMMANDMESSAGE_H_ +#define FSFW_IPC_COMMANDMESSAGE_H_ + +#include "CommandMessageIF.h" +#include "MessageQueueMessage.h" +#include "FwMessageTypes.h" + +/** + * @brief Default command message used to pass command messages between tasks. + * Primary message type for IPC. Contains sender, 2-byte command ID + * field, and 2 4-byte parameters. + * @details + * It operates on an external memory which is contained inside a + * class implementing MessageQueueMessageIF by taking its address. + * This allows for a more flexible designs of message implementations. + * The pointer can be passed to different message implementations without + * the need of unnecessary copying. + * + * The command message is based of the generic MessageQueueMessage which + * currently has an internal message size of 28 bytes. + * @author Bastian Baetz + */ +class CommandMessage: public MessageQueueMessage, public CommandMessageIF { +public: + /** + * Default size can accomodate 2 4-byte parameters. + */ + static constexpr size_t DEFAULT_COMMAND_MESSAGE_SIZE = + CommandMessageIF::MINIMUM_COMMAND_MESSAGE_SIZE + sizeof(uint32_t); + + /** + * @brief Default Constructor, does not initialize anything. + * @details + * This constructor should be used when receiving a Message, as the + * content is filled by the MessageQueue. + */ + CommandMessage(); + /** + * This constructor creates a new message with all message content + * initialized + * + * @param command The DeviceHandlerCommand_t that will be sent + * @param parameter1 The first parameter + * @param parameter2 The second parameter + */ + CommandMessage(Command_t command, uint32_t parameter1, uint32_t parameter2); + + /** + * @brief Default Destructor + */ + virtual ~CommandMessage() {} + + /** + * Read the DeviceHandlerCommand_t that is stored in the message, + * usually used after receiving. + * + * @return the Command stored in the Message + */ + virtual Command_t getCommand() const override; + /** + * Set the command type of the message. Default implementation also + * sets the message type, which will be the first byte of the command ID. + * @param the Command to be sent + */ + virtual void setCommand(Command_t command); + + virtual uint8_t* getData() override; + virtual const uint8_t* getData() const override; + + /** + * Get the first parameter of the message + * @return the first Parameter of the message + */ + uint32_t getParameter() const; + /** + * Set the first parameter of the message + * @param the first parameter of the message + */ + void setParameter(uint32_t parameter1); + uint32_t getParameter2() const; + void setParameter2(uint32_t parameter2); + uint32_t getParameter3() const; + void setParameter3(uint32_t parameter3); + + /** + * check if a message was cleared + * + * @return if the command is CMD_NONE + */ + bool isClearedCommandMessage(); + + /** + * Sets the command to REPLY_REJECTED with parameter UNKNOWN_COMMAND. + * Is needed quite often, so we better code it once only. + */ + void setToUnknownCommand() override; + + /** + * A command message can be rejected and needs to offer a function + * to set a rejected reply + * @param reason + * @param initialCommand + */ + void setReplyRejected(ReturnValue_t reason, + Command_t initialCommand) override; + /** + * Corrensonding getter function. + * @param initialCommand + * @return + */ + ReturnValue_t getReplyRejectedReason( + Command_t* initialCommand = nullptr) const override; + + + virtual void clear() override; + void clearCommandMessage(); + + /** + * Extract message ID, which is the first byte of the command ID for the + * default implementation. + * @return + */ + virtual uint8_t getMessageType() const override; + + /** MessageQueueMessageIF functions used for minimum size check. */ + size_t getMinimumMessageSize() const override; +}; + +#endif /* FSFW_IPC_COMMANDMESSAGE_H_ */ diff --git a/ipc/CommandMessageCleaner.cpp b/ipc/CommandMessageCleaner.cpp index a4dec78d..6a99b4d2 100644 --- a/ipc/CommandMessageCleaner.cpp +++ b/ipc/CommandMessageCleaner.cpp @@ -1,45 +1,45 @@ -#include "../ipc/CommandMessageCleaner.h" - -#include "../devicehandlers/DeviceHandlerMessage.h" -#include "../health/HealthMessage.h" -#include "../memory/MemoryMessage.h" -#include "../modes/ModeMessage.h" -#include "../monitoring/MonitoringMessage.h" -#include "../subsystem/modes/ModeSequenceMessage.h" -#include "../tmstorage/TmStoreMessage.h" -#include "../parameters/ParameterMessage.h" - -void CommandMessageCleaner::clearCommandMessage(CommandMessage* message) { - switch(message->getMessageType()){ - case messagetypes::MODE_COMMAND: - ModeMessage::clear(message); - break; - case messagetypes::HEALTH_COMMAND: - HealthMessage::clear(message); - break; - case messagetypes::MODE_SEQUENCE: - ModeSequenceMessage::clear(message); - break; - case messagetypes::ACTION: - ActionMessage::clear(message); - break; - case messagetypes::DEVICE_HANDLER_COMMAND: - DeviceHandlerMessage::clear(message); - break; - case messagetypes::MEMORY: - MemoryMessage::clear(message); - break; - case messagetypes::MONITORING: - MonitoringMessage::clear(message); - break; - case messagetypes::TM_STORE: - TmStoreMessage::clear(message); - break; - case messagetypes::PARAMETER: - ParameterMessage::clear(message); - break; - default: - messagetypes::clearMissionMessage(message); - break; - } -} +#include "../ipc/CommandMessageCleaner.h" + +#include "../devicehandlers/DeviceHandlerMessage.h" +#include "../health/HealthMessage.h" +#include "../memory/MemoryMessage.h" +#include "../modes/ModeMessage.h" +#include "../monitoring/MonitoringMessage.h" +#include "../subsystem/modes/ModeSequenceMessage.h" +#include "../tmstorage/TmStoreMessage.h" +#include "../parameters/ParameterMessage.h" + +void CommandMessageCleaner::clearCommandMessage(CommandMessage* message) { + switch(message->getMessageType()){ + case messagetypes::MODE_COMMAND: + ModeMessage::clear(message); + break; + case messagetypes::HEALTH_COMMAND: + HealthMessage::clear(message); + break; + case messagetypes::MODE_SEQUENCE: + ModeSequenceMessage::clear(message); + break; + case messagetypes::ACTION: + ActionMessage::clear(message); + break; + case messagetypes::DEVICE_HANDLER_COMMAND: + DeviceHandlerMessage::clear(message); + break; + case messagetypes::MEMORY: + MemoryMessage::clear(message); + break; + case messagetypes::MONITORING: + MonitoringMessage::clear(message); + break; + case messagetypes::TM_STORE: + TmStoreMessage::clear(message); + break; + case messagetypes::PARAMETER: + ParameterMessage::clear(message); + break; + default: + messagetypes::clearMissionMessage(message); + break; + } +} diff --git a/ipc/CommandMessageCleaner.h b/ipc/CommandMessageCleaner.h index f17bf282..2bf4a193 100644 --- a/ipc/CommandMessageCleaner.h +++ b/ipc/CommandMessageCleaner.h @@ -1,16 +1,16 @@ -#ifndef FRAMEWORK_IPC_COMMANDMESSAGECLEANER_H_ -#define FRAMEWORK_IPC_COMMANDMESSAGECLEANER_H_ -#include "../ipc/CommandMessage.h" - -namespace messagetypes { -// Implemented in config. -void clearMissionMessage(CommandMessage* message); -} - -class CommandMessageCleaner { -public: - static void clearCommandMessage(CommandMessage* message); -}; - - -#endif /* FRAMEWORK_IPC_COMMANDMESSAGECLEANER_H_ */ +#ifndef FRAMEWORK_IPC_COMMANDMESSAGECLEANER_H_ +#define FRAMEWORK_IPC_COMMANDMESSAGECLEANER_H_ +#include "../ipc/CommandMessage.h" + +namespace messagetypes { +// Implemented in config. +void clearMissionMessage(CommandMessage* message); +} + +class CommandMessageCleaner { +public: + static void clearCommandMessage(CommandMessage* message); +}; + + +#endif /* FRAMEWORK_IPC_COMMANDMESSAGECLEANER_H_ */ diff --git a/ipc/CommandMessageIF.h b/ipc/CommandMessageIF.h index 68a8d956..aafa40ef 100644 --- a/ipc/CommandMessageIF.h +++ b/ipc/CommandMessageIF.h @@ -1,73 +1,73 @@ -#ifndef FSFW_IPC_COMMANDMESSAGEIF_H_ -#define FSFW_IPC_COMMANDMESSAGEIF_H_ - -#include "MessageQueueMessageIF.h" -#include "FwMessageTypes.h" -#include "../returnvalues/HasReturnvaluesIF.h" - -#define MAKE_COMMAND_ID( number ) ((MESSAGE_ID << 8) + (number)) -typedef uint16_t Command_t; - -class CommandMessageIF { -public: - /** - * Header consists of sender ID and command ID. - */ - static constexpr size_t HEADER_SIZE = MessageQueueMessageIF::HEADER_SIZE + - sizeof(Command_t); - /** - * This minimum size is derived from the interface requirement to be able - * to set a rejected reply, which contains a returnvalue and the initial - * command. - */ - static constexpr size_t MINIMUM_COMMAND_MESSAGE_SIZE = - CommandMessageIF::HEADER_SIZE + sizeof(ReturnValue_t) + - sizeof(Command_t); - - static const uint8_t INTERFACE_ID = CLASS_ID::COMMAND_MESSAGE; - static const ReturnValue_t UNKNOWN_COMMAND = MAKE_RETURN_CODE(0x01); - - static const uint8_t MESSAGE_ID = messagetypes::COMMAND; - //! Used internally, shall be ignored - 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, - //! par1 should contain the error code - static const Command_t REPLY_REJECTED = MAKE_COMMAND_ID( 2 ); - - virtual ~CommandMessageIF() {}; - - /** - * A command message shall have a uint16_t command ID field. - * @return - */ - virtual Command_t getCommand() const = 0; - /** - * A command message shall have a uint8_t message type ID field. - * @return - */ - virtual uint8_t getMessageType() const = 0; - - /** - * A command message can be rejected and needs to offer a function - * to set a rejected reply - * @param reason - * @param initialCommand - */ - virtual void setReplyRejected(ReturnValue_t reason, - Command_t initialCommand) = 0; - /** - * Corrensonding getter function. - * @param initialCommand - * @return - */ - virtual ReturnValue_t getReplyRejectedReason( - Command_t* initialCommand = nullptr) const = 0; - - virtual void setToUnknownCommand() = 0; - - virtual void clear() = 0; - -}; - -#endif /* FSFW_IPC_COMMANDMESSAGEIF_H_ */ +#ifndef FSFW_IPC_COMMANDMESSAGEIF_H_ +#define FSFW_IPC_COMMANDMESSAGEIF_H_ + +#include "MessageQueueMessageIF.h" +#include "FwMessageTypes.h" +#include "../returnvalues/HasReturnvaluesIF.h" + +#define MAKE_COMMAND_ID( number ) ((MESSAGE_ID << 8) + (number)) +typedef uint16_t Command_t; + +class CommandMessageIF { +public: + /** + * Header consists of sender ID and command ID. + */ + static constexpr size_t HEADER_SIZE = MessageQueueMessageIF::HEADER_SIZE + + sizeof(Command_t); + /** + * This minimum size is derived from the interface requirement to be able + * to set a rejected reply, which contains a returnvalue and the initial + * command. + */ + static constexpr size_t MINIMUM_COMMAND_MESSAGE_SIZE = + CommandMessageIF::HEADER_SIZE + sizeof(ReturnValue_t) + + sizeof(Command_t); + + static const uint8_t INTERFACE_ID = CLASS_ID::COMMAND_MESSAGE; + static const ReturnValue_t UNKNOWN_COMMAND = MAKE_RETURN_CODE(0x01); + + static const uint8_t MESSAGE_ID = messagetypes::COMMAND; + //! Used internally, shall be ignored + 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, + //! par1 should contain the error code + static const Command_t REPLY_REJECTED = MAKE_COMMAND_ID( 2 ); + + virtual ~CommandMessageIF() {}; + + /** + * A command message shall have a uint16_t command ID field. + * @return + */ + virtual Command_t getCommand() const = 0; + /** + * A command message shall have a uint8_t message type ID field. + * @return + */ + virtual uint8_t getMessageType() const = 0; + + /** + * A command message can be rejected and needs to offer a function + * to set a rejected reply + * @param reason + * @param initialCommand + */ + virtual void setReplyRejected(ReturnValue_t reason, + Command_t initialCommand) = 0; + /** + * Corrensonding getter function. + * @param initialCommand + * @return + */ + virtual ReturnValue_t getReplyRejectedReason( + Command_t* initialCommand = nullptr) const = 0; + + virtual void setToUnknownCommand() = 0; + + virtual void clear() = 0; + +}; + +#endif /* FSFW_IPC_COMMANDMESSAGEIF_H_ */ diff --git a/ipc/MessageQueueMessage.cpp b/ipc/MessageQueueMessage.cpp index 2f79cb3b..dcd4def3 100644 --- a/ipc/MessageQueueMessage.cpp +++ b/ipc/MessageQueueMessage.cpp @@ -1,84 +1,84 @@ -#include "MessageQueueMessage.h" -#include "../serviceinterface/ServiceInterfaceStream.h" -#include "../globalfunctions/arrayprinter.h" -#include - -MessageQueueMessage::MessageQueueMessage() : - messageSize(getMinimumMessageSize()) { - memset(this->internalBuffer, 0, sizeof(this->internalBuffer)); -} - -MessageQueueMessage::MessageQueueMessage(uint8_t* data, size_t size) : - messageSize(this->HEADER_SIZE + size) { - if (size <= this->MAX_DATA_SIZE) { - memcpy(this->getData(), data, size); - this->messageSize = this->HEADER_SIZE + size; - } - else { - sif::warning << "MessageQueueMessage: Passed size larger than maximum" - "allowed size! Setting content to 0" << std::endl; - memset(this->internalBuffer, 0, sizeof(this->internalBuffer)); - this->messageSize = this->HEADER_SIZE; - } -} - -MessageQueueMessage::~MessageQueueMessage() { -} - -const uint8_t* MessageQueueMessage::getBuffer() const { - return this->internalBuffer; -} - -uint8_t* MessageQueueMessage::getBuffer() { - return this->internalBuffer; -} - -const uint8_t* MessageQueueMessage::getData() const { - return this->internalBuffer + this->HEADER_SIZE; -} - -uint8_t* MessageQueueMessage::getData() { - return this->internalBuffer + this->HEADER_SIZE; -} - -MessageQueueId_t MessageQueueMessage::getSender() const { - MessageQueueId_t temp_id; - memcpy(&temp_id, this->internalBuffer, sizeof(MessageQueueId_t)); - return temp_id; -} - -void MessageQueueMessage::setSender(MessageQueueId_t setId) { - memcpy(this->internalBuffer, &setId, sizeof(MessageQueueId_t)); -} - -void MessageQueueMessage::print(bool printWholeMessage) { - sif::debug << "MessageQueueMessage content: " << std::endl; - if(printWholeMessage) { - arrayprinter::print(getData(), getMaximumMessageSize()); - } - else { - arrayprinter::print(getData(), getMessageSize()); - } - -} - -void MessageQueueMessage::clear() { - memset(this->getBuffer(), 0, this->MAX_MESSAGE_SIZE); -} - -size_t MessageQueueMessage::getMessageSize() const { - return this->messageSize; -} - -void MessageQueueMessage::setMessageSize(size_t messageSize) { - this->messageSize = messageSize; -} - -size_t MessageQueueMessage::getMinimumMessageSize() const { - return this->MIN_MESSAGE_SIZE; -} - -size_t MessageQueueMessage::getMaximumMessageSize() const { - return this->MAX_MESSAGE_SIZE; -} - +#include "MessageQueueMessage.h" +#include "../serviceinterface/ServiceInterfaceStream.h" +#include "../globalfunctions/arrayprinter.h" +#include + +MessageQueueMessage::MessageQueueMessage() : + messageSize(getMinimumMessageSize()) { + memset(this->internalBuffer, 0, sizeof(this->internalBuffer)); +} + +MessageQueueMessage::MessageQueueMessage(uint8_t* data, size_t size) : + messageSize(this->HEADER_SIZE + size) { + if (size <= this->MAX_DATA_SIZE) { + memcpy(this->getData(), data, size); + this->messageSize = this->HEADER_SIZE + size; + } + else { + sif::warning << "MessageQueueMessage: Passed size larger than maximum" + "allowed size! Setting content to 0" << std::endl; + memset(this->internalBuffer, 0, sizeof(this->internalBuffer)); + this->messageSize = this->HEADER_SIZE; + } +} + +MessageQueueMessage::~MessageQueueMessage() { +} + +const uint8_t* MessageQueueMessage::getBuffer() const { + return this->internalBuffer; +} + +uint8_t* MessageQueueMessage::getBuffer() { + return this->internalBuffer; +} + +const uint8_t* MessageQueueMessage::getData() const { + return this->internalBuffer + this->HEADER_SIZE; +} + +uint8_t* MessageQueueMessage::getData() { + return this->internalBuffer + this->HEADER_SIZE; +} + +MessageQueueId_t MessageQueueMessage::getSender() const { + MessageQueueId_t temp_id; + memcpy(&temp_id, this->internalBuffer, sizeof(MessageQueueId_t)); + return temp_id; +} + +void MessageQueueMessage::setSender(MessageQueueId_t setId) { + memcpy(this->internalBuffer, &setId, sizeof(MessageQueueId_t)); +} + +void MessageQueueMessage::print(bool printWholeMessage) { + sif::debug << "MessageQueueMessage content: " << std::endl; + if(printWholeMessage) { + arrayprinter::print(getData(), getMaximumMessageSize()); + } + else { + arrayprinter::print(getData(), getMessageSize()); + } + +} + +void MessageQueueMessage::clear() { + memset(this->getBuffer(), 0, this->MAX_MESSAGE_SIZE); +} + +size_t MessageQueueMessage::getMessageSize() const { + return this->messageSize; +} + +void MessageQueueMessage::setMessageSize(size_t messageSize) { + this->messageSize = messageSize; +} + +size_t MessageQueueMessage::getMinimumMessageSize() const { + return this->MIN_MESSAGE_SIZE; +} + +size_t MessageQueueMessage::getMaximumMessageSize() const { + return this->MAX_MESSAGE_SIZE; +} + diff --git a/ipc/MessageQueueMessage.h b/ipc/MessageQueueMessage.h index da5c78cb..f68e9b9f 100644 --- a/ipc/MessageQueueMessage.h +++ b/ipc/MessageQueueMessage.h @@ -1,150 +1,150 @@ -#ifndef FSFW_IPC_MESSAGEQUEUEMESSAGE_H_ -#define FSFW_IPC_MESSAGEQUEUEMESSAGE_H_ - -#include "../ipc/MessageQueueMessageIF.h" -#include "../ipc/MessageQueueSenderIF.h" -#include - -/** - * @brief This class is the representation and data organizer - * for interprocess messages. - * @details - * To facilitate and standardize interprocess communication, this class was - * created to handle a lightweight "interprocess message protocol". - * - * It adds a header with the sender's queue id to every sent message and - * defines the maximum total message size. Specialized messages, such as - * device commanding messages, can be created by inheriting from this class - * and filling the buffer provided by getData with additional content. - * - * If larger amounts of data must be sent between processes, the data shall - * be stored in the IPC Store object and only the storage id is passed in a - * queue message.The class is used both to generate and send messages and to - * receive messages from other tasks. - * @ingroup message_queue - */ -class MessageQueueMessage: public MessageQueueMessageIF { -public: - /** - * @brief The class is initialized empty with this constructor. - * @details - * The messageSize attribute is set to the header's size and the whole - * content is set to zero. - */ - MessageQueueMessage(); - /** - * @brief With this constructor the class is initialized with - * the given content. - * @details - * If the passed message size fits into the buffer, the passed data is - * copied to the internal buffer and the messageSize information is set. - * Otherwise, messageSize is set to the header's size and the whole - * content is set to zero. - * @param data The data to be put in the message. - * @param size Size of the data to be copied. Must be smaller than - * MAX_MESSAGE_SIZE and larger than MIN_MESSAGE_SIZE. - */ - MessageQueueMessage(uint8_t* data, size_t size); - - /** - * @brief As no memory is allocated in this class, - * the destructor is empty. - */ - virtual ~MessageQueueMessage(); - - /** - * @brief The size information of each message is stored in - * this attribute. - * @details - * It is public to simplify usage and to allow for passing the size - * address as a pointer. Care must be taken when inheriting from this class, - * as every child class is responsible for managing the size information by - * itself. When using the class to receive a message, the size information - * is updated automatically. - * - * Please note that the minimum size is limited by the size of the header - * while the maximum size is limited by the maximum allowed message size. - */ - size_t messageSize; - /** - * @brief This constant defines the maximum size of the data content, - * excluding the header. - * @details - * It may be changed if necessary, but in general should be kept - * as small as possible. - */ - static const size_t MAX_DATA_SIZE = 24; - - /** - * @brief This constant defines the maximum total size in bytes - * of a sent message. - * @details - * It is the sum of the maximum data and the header size. Be aware that - * this constant is used to define the buffer sizes for every message - * queue in the system. So, a change here may have significant impact on - * the required resources. - */ - static constexpr size_t MAX_MESSAGE_SIZE = MAX_DATA_SIZE + HEADER_SIZE; - /** - * @brief Defines the minimum size of a message where only the - * header is included - */ - static constexpr size_t MIN_MESSAGE_SIZE = HEADER_SIZE; -private: - /** - * @brief This is the internal buffer that contains the - * actual message data. - */ - uint8_t internalBuffer[MAX_MESSAGE_SIZE]; -public: - /** - * @brief This method is used to get the complete data of the message. - */ - const uint8_t* getBuffer() const override; - /** - * @brief This method is used to get the complete data of the message. - */ - uint8_t* getBuffer() override; - /** - * @brief This method is used to fetch the data content of the message. - * @details - * It shall be used by child classes to add data at the right position. - */ - const uint8_t* getData() const override; - /** - * @brief This method is used to fetch the data content of the message. - * @details - * It shall be used by child classes to add data at the right position. - */ - uint8_t* getData() override; - /** - * @brief This method is used to extract the sender's message - * queue id information from a received message. - */ - MessageQueueId_t getSender() const override; - /** - * @brief With this method, the whole content - * and the message size is set to zero. - */ - void clear() override; - - /** - * @brief This method is used to set the sender's message queue id - * information prior to ing the message. - * @param setId - * The message queue id that identifies the sending message queue. - */ - void setSender(MessageQueueId_t setId) override; - - virtual size_t getMessageSize() const override; - virtual void setMessageSize(size_t messageSize) override; - virtual size_t getMinimumMessageSize() const override; - virtual size_t getMaximumMessageSize() const override; - - /** - * @brief This is a debug method that prints the content. - */ - void print(bool printWholeMessage); -}; - -#endif /* FSFW_IPC_MESSAGEQUEUEMESSAGE_H_ */ +#ifndef FSFW_IPC_MESSAGEQUEUEMESSAGE_H_ +#define FSFW_IPC_MESSAGEQUEUEMESSAGE_H_ + +#include "../ipc/MessageQueueMessageIF.h" +#include "../ipc/MessageQueueSenderIF.h" +#include + +/** + * @brief This class is the representation and data organizer + * for interprocess messages. + * @details + * To facilitate and standardize interprocess communication, this class was + * created to handle a lightweight "interprocess message protocol". + * + * It adds a header with the sender's queue id to every sent message and + * defines the maximum total message size. Specialized messages, such as + * device commanding messages, can be created by inheriting from this class + * and filling the buffer provided by getData with additional content. + * + * If larger amounts of data must be sent between processes, the data shall + * be stored in the IPC Store object and only the storage id is passed in a + * queue message.The class is used both to generate and send messages and to + * receive messages from other tasks. + * @ingroup message_queue + */ +class MessageQueueMessage: public MessageQueueMessageIF { +public: + /** + * @brief The class is initialized empty with this constructor. + * @details + * The messageSize attribute is set to the header's size and the whole + * content is set to zero. + */ + MessageQueueMessage(); + /** + * @brief With this constructor the class is initialized with + * the given content. + * @details + * If the passed message size fits into the buffer, the passed data is + * copied to the internal buffer and the messageSize information is set. + * Otherwise, messageSize is set to the header's size and the whole + * content is set to zero. + * @param data The data to be put in the message. + * @param size Size of the data to be copied. Must be smaller than + * MAX_MESSAGE_SIZE and larger than MIN_MESSAGE_SIZE. + */ + MessageQueueMessage(uint8_t* data, size_t size); + + /** + * @brief As no memory is allocated in this class, + * the destructor is empty. + */ + virtual ~MessageQueueMessage(); + + /** + * @brief The size information of each message is stored in + * this attribute. + * @details + * It is public to simplify usage and to allow for passing the size + * address as a pointer. Care must be taken when inheriting from this class, + * as every child class is responsible for managing the size information by + * itself. When using the class to receive a message, the size information + * is updated automatically. + * + * Please note that the minimum size is limited by the size of the header + * while the maximum size is limited by the maximum allowed message size. + */ + size_t messageSize; + /** + * @brief This constant defines the maximum size of the data content, + * excluding the header. + * @details + * It may be changed if necessary, but in general should be kept + * as small as possible. + */ + static const size_t MAX_DATA_SIZE = 24; + + /** + * @brief This constant defines the maximum total size in bytes + * of a sent message. + * @details + * It is the sum of the maximum data and the header size. Be aware that + * this constant is used to define the buffer sizes for every message + * queue in the system. So, a change here may have significant impact on + * the required resources. + */ + static constexpr size_t MAX_MESSAGE_SIZE = MAX_DATA_SIZE + HEADER_SIZE; + /** + * @brief Defines the minimum size of a message where only the + * header is included + */ + static constexpr size_t MIN_MESSAGE_SIZE = HEADER_SIZE; +private: + /** + * @brief This is the internal buffer that contains the + * actual message data. + */ + uint8_t internalBuffer[MAX_MESSAGE_SIZE]; +public: + /** + * @brief This method is used to get the complete data of the message. + */ + const uint8_t* getBuffer() const override; + /** + * @brief This method is used to get the complete data of the message. + */ + uint8_t* getBuffer() override; + /** + * @brief This method is used to fetch the data content of the message. + * @details + * It shall be used by child classes to add data at the right position. + */ + const uint8_t* getData() const override; + /** + * @brief This method is used to fetch the data content of the message. + * @details + * It shall be used by child classes to add data at the right position. + */ + uint8_t* getData() override; + /** + * @brief This method is used to extract the sender's message + * queue id information from a received message. + */ + MessageQueueId_t getSender() const override; + /** + * @brief With this method, the whole content + * and the message size is set to zero. + */ + void clear() override; + + /** + * @brief This method is used to set the sender's message queue id + * information prior to ing the message. + * @param setId + * The message queue id that identifies the sending message queue. + */ + void setSender(MessageQueueId_t setId) override; + + virtual size_t getMessageSize() const override; + virtual void setMessageSize(size_t messageSize) override; + virtual size_t getMinimumMessageSize() const override; + virtual size_t getMaximumMessageSize() const override; + + /** + * @brief This is a debug method that prints the content. + */ + void print(bool printWholeMessage); +}; + +#endif /* FSFW_IPC_MESSAGEQUEUEMESSAGE_H_ */ From d885dddee8c8f053207c5c652f5acc81d66efff8 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 4 Sep 2020 15:04:53 +0200 Subject: [PATCH 029/101] renormalize files --- container/SimpleRingBuffer.cpp | 270 ++++++++++++++++----------------- container/SimpleRingBuffer.h | 256 +++++++++++++++---------------- 2 files changed, 263 insertions(+), 263 deletions(-) diff --git a/container/SimpleRingBuffer.cpp b/container/SimpleRingBuffer.cpp index 2a19d619..d6b6f5af 100644 --- a/container/SimpleRingBuffer.cpp +++ b/container/SimpleRingBuffer.cpp @@ -1,135 +1,135 @@ -#include "../container/SimpleRingBuffer.h" -#include - -SimpleRingBuffer::SimpleRingBuffer(const size_t size, bool overwriteOld, - size_t maxExcessBytes) : - RingBufferBase<>(0, size, overwriteOld), - maxExcessBytes(maxExcessBytes) { - if(maxExcessBytes > size) { - this->maxExcessBytes = size; - } - else { - this->maxExcessBytes = maxExcessBytes; - } - buffer = new uint8_t[size + maxExcessBytes]; -} - -SimpleRingBuffer::SimpleRingBuffer(uint8_t *buffer, const size_t size, - bool overwriteOld, size_t maxExcessBytes): - RingBufferBase<>(0, size, overwriteOld), buffer(buffer) { - if(maxExcessBytes > size) { - this->maxExcessBytes = size; - } - else { - this->maxExcessBytes = maxExcessBytes; - } -} - - -SimpleRingBuffer::~SimpleRingBuffer() { - delete[] buffer; -} - - -ReturnValue_t SimpleRingBuffer::getFreeElement(uint8_t **writePointer, - size_t amount) { - if ((availableWriteSpace() >= amount) or overwriteOld) { - size_t amountTillWrap = writeTillWrap(); - if (amountTillWrap < amount) { - if((amount - amountTillWrap + excessBytes) > maxExcessBytes) { - return HasReturnvaluesIF::RETURN_FAILED; - } - excessBytes = amount - amountTillWrap; - } - *writePointer = &buffer[write]; - return HasReturnvaluesIF::RETURN_OK; - } - else { - return HasReturnvaluesIF::RETURN_FAILED; - } -} - -void SimpleRingBuffer::confirmBytesWritten(size_t amount) { - if(getExcessBytes() > 0) { - moveExcessBytesToStart(); - } - incrementWrite(amount); - -} - -ReturnValue_t SimpleRingBuffer::writeData(const uint8_t* data, - size_t amount) { - if ((availableWriteSpace() >= amount) or overwriteOld) { - size_t amountTillWrap = writeTillWrap(); - if (amountTillWrap >= amount) { - // remaining size in buffer is sufficient to fit full amount. - memcpy(&buffer[write], data, amount); - } - else { - memcpy(&buffer[write], data, amountTillWrap); - memcpy(buffer, data + amountTillWrap, amount - amountTillWrap); - } - incrementWrite(amount); - return HasReturnvaluesIF::RETURN_OK; - } else { - return HasReturnvaluesIF::RETURN_FAILED; - } -} - -ReturnValue_t SimpleRingBuffer::readData(uint8_t* data, size_t amount, - bool incrementReadPtr, bool readRemaining, size_t* trueAmount) { - size_t availableData = getAvailableReadData(READ_PTR); - size_t amountTillWrap = readTillWrap(READ_PTR); - if (availableData < amount) { - if (readRemaining) { - // more data available than amount specified. - amount = availableData; - } else { - return HasReturnvaluesIF::RETURN_FAILED; - } - } - if (trueAmount != nullptr) { - *trueAmount = amount; - } - if (amountTillWrap >= amount) { - memcpy(data, &buffer[read[READ_PTR]], amount); - } else { - memcpy(data, &buffer[read[READ_PTR]], amountTillWrap); - memcpy(data + amountTillWrap, buffer, amount - amountTillWrap); - } - - if(incrementReadPtr) { - deleteData(amount, readRemaining); - } - return HasReturnvaluesIF::RETURN_OK; -} - -size_t SimpleRingBuffer::getExcessBytes() const { - return excessBytes; -} - -void SimpleRingBuffer::moveExcessBytesToStart() { - if(excessBytes > 0) { - std::memcpy(buffer, &buffer[size], excessBytes); - excessBytes = 0; - } -} - -ReturnValue_t SimpleRingBuffer::deleteData(size_t amount, - bool deleteRemaining, size_t* trueAmount) { - size_t availableData = getAvailableReadData(READ_PTR); - if (availableData < amount) { - if (deleteRemaining) { - amount = availableData; - } else { - return HasReturnvaluesIF::RETURN_FAILED; - } - } - if (trueAmount != nullptr) { - *trueAmount = amount; - } - incrementRead(amount, READ_PTR); - return HasReturnvaluesIF::RETURN_OK; -} - - +#include "../container/SimpleRingBuffer.h" +#include + +SimpleRingBuffer::SimpleRingBuffer(const size_t size, bool overwriteOld, + size_t maxExcessBytes) : + RingBufferBase<>(0, size, overwriteOld), + maxExcessBytes(maxExcessBytes) { + if(maxExcessBytes > size) { + this->maxExcessBytes = size; + } + else { + this->maxExcessBytes = maxExcessBytes; + } + buffer = new uint8_t[size + maxExcessBytes]; +} + +SimpleRingBuffer::SimpleRingBuffer(uint8_t *buffer, const size_t size, + bool overwriteOld, size_t maxExcessBytes): + RingBufferBase<>(0, size, overwriteOld), buffer(buffer) { + if(maxExcessBytes > size) { + this->maxExcessBytes = size; + } + else { + this->maxExcessBytes = maxExcessBytes; + } +} + + +SimpleRingBuffer::~SimpleRingBuffer() { + delete[] buffer; +} + + +ReturnValue_t SimpleRingBuffer::getFreeElement(uint8_t **writePointer, + size_t amount) { + if (availableWriteSpace() >= amount or overwriteOld) { + size_t amountTillWrap = writeTillWrap(); + if (amountTillWrap < amount) { + if((amount - amountTillWrap + excessBytes) > maxExcessBytes) { + return HasReturnvaluesIF::RETURN_FAILED; + } + excessBytes = amount - amountTillWrap; + } + *writePointer = &buffer[write]; + return HasReturnvaluesIF::RETURN_OK; + } + else { + return HasReturnvaluesIF::RETURN_FAILED; + } +} + +void SimpleRingBuffer::confirmBytesWritten(size_t amount) { + if(getExcessBytes() > 0) { + moveExcessBytesToStart(); + } + incrementWrite(amount); + +} + +ReturnValue_t SimpleRingBuffer::writeData(const uint8_t* data, + size_t amount) { + if (availableWriteSpace() >= amount or overwriteOld) { + size_t amountTillWrap = writeTillWrap(); + if (amountTillWrap >= amount) { + // remaining size in buffer is sufficient to fit full amount. + memcpy(&buffer[write], data, amount); + } + else { + memcpy(&buffer[write], data, amountTillWrap); + memcpy(buffer, data + amountTillWrap, amount - amountTillWrap); + } + incrementWrite(amount); + return HasReturnvaluesIF::RETURN_OK; + } else { + return HasReturnvaluesIF::RETURN_FAILED; + } +} + +ReturnValue_t SimpleRingBuffer::readData(uint8_t* data, size_t amount, + bool incrementReadPtr, bool readRemaining, size_t* trueAmount) { + size_t availableData = getAvailableReadData(READ_PTR); + size_t amountTillWrap = readTillWrap(READ_PTR); + if (availableData < amount) { + if (readRemaining) { + // more data available than amount specified. + amount = availableData; + } else { + return HasReturnvaluesIF::RETURN_FAILED; + } + } + if (trueAmount != nullptr) { + *trueAmount = amount; + } + if (amountTillWrap >= amount) { + memcpy(data, &buffer[read[READ_PTR]], amount); + } else { + memcpy(data, &buffer[read[READ_PTR]], amountTillWrap); + memcpy(data + amountTillWrap, buffer, amount - amountTillWrap); + } + + if(incrementReadPtr) { + deleteData(amount, readRemaining); + } + return HasReturnvaluesIF::RETURN_OK; +} + +size_t SimpleRingBuffer::getExcessBytes() const { + return excessBytes; +} + +void SimpleRingBuffer::moveExcessBytesToStart() { + if(excessBytes > 0) { + std::memcpy(buffer, &buffer[size], excessBytes); + excessBytes = 0; + } +} + +ReturnValue_t SimpleRingBuffer::deleteData(size_t amount, + bool deleteRemaining, size_t* trueAmount) { + size_t availableData = getAvailableReadData(READ_PTR); + if (availableData < amount) { + if (deleteRemaining) { + amount = availableData; + } else { + return HasReturnvaluesIF::RETURN_FAILED; + } + } + if (trueAmount != nullptr) { + *trueAmount = amount; + } + incrementRead(amount, READ_PTR); + return HasReturnvaluesIF::RETURN_OK; +} + + diff --git a/container/SimpleRingBuffer.h b/container/SimpleRingBuffer.h index b13e9f2a..dcf2684b 100644 --- a/container/SimpleRingBuffer.h +++ b/container/SimpleRingBuffer.h @@ -1,128 +1,128 @@ -#ifndef FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_ -#define FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_ - -#include "../container/RingBufferBase.h" -#include - -/** - * @brief Circular buffer implementation, useful for buffering - * into data streams. - * @details - * Note that the deleteData() has to be called to increment the read pointer. - * This class allocated dynamically, so - * @ingroup containers - */ -class SimpleRingBuffer: public RingBufferBase<> { -public: - /** - * This constructor allocates a new internal buffer with the supplied size. - * - * @param size - * @param overwriteOld If the ring buffer is overflowing at a write - * operation, the oldest data will be overwritten. - * @param maxExcessBytes These additional bytes will be allocated in addtion - * to the specified size to accomodate contiguous write operations - * with getFreeElement. - * - */ - SimpleRingBuffer(const size_t size, bool overwriteOld, - size_t maxExcessBytes = 0); - /** - * This constructor takes an external buffer with the specified size. - * @param buffer - * @param size - * @param overwriteOld - * If the ring buffer is overflowing at a write operartion, the oldest data - * will be overwritten. - * @param maxExcessBytes - * If the buffer can accomodate additional bytes for contigous write - * operations with getFreeElement, this is the maximum allowed additional - * size - */ - SimpleRingBuffer(uint8_t* buffer, const size_t size, bool overwriteOld, - size_t maxExcessBytes = 0); - - virtual ~SimpleRingBuffer(); - - /** - * Write to circular buffer and increment write pointer by amount. - * @param data - * @param amount - * @return -@c RETURN_OK if write operation was successfull - * -@c RETURN_FAILED if - */ - ReturnValue_t writeData(const uint8_t* data, size_t amount); - - /** - * Returns a pointer to a free element. If the remaining buffer is - * not large enough, the data will be written past the actual size - * and the amount of excess bytes will be cached. This function - * does not increment the write pointer! - * @param writePointer Pointer to a pointer which can be used to write - * contiguous blocks into the ring buffer - * @param amount - * @return - */ - ReturnValue_t getFreeElement(uint8_t** writePointer, size_t amount); - - /** - * This increments the write pointer and also copies the excess bytes - * to the beginning. It should be called if the write operation - * conducted after calling getFreeElement() was performed. - * @return - */ - void confirmBytesWritten(size_t amount); - - virtual size_t getExcessBytes() const; - /** - * Helper functions which moves any excess bytes to the start - * of the ring buffer. - * @return - */ - virtual void moveExcessBytesToStart(); - - /** - * Read from circular buffer at read pointer. - * @param data - * @param amount - * @param incrementReadPtr - * If this is set to true, the read pointer will be incremented. - * If readRemaining is set to true, the read pointer will be incremented - * accordingly. - * @param readRemaining - * If this is set to true, the data will be read even if the amount - * specified exceeds the read data available. - * @param trueAmount [out] - * If readRemaining was set to true, the true amount read will be assigned - * to the passed value. - * @return - * - @c RETURN_OK if data was read successfully - * - @c RETURN_FAILED if not enough data was available and readRemaining - * was set to false. - */ - ReturnValue_t readData(uint8_t* data, size_t amount, - bool incrementReadPtr = false, bool readRemaining = false, - size_t* trueAmount = nullptr); - - /** - * Delete data by incrementing read pointer. - * @param amount - * @param deleteRemaining - * If the amount specified is larger than the remaing size to read and this - * is set to true, the remaining amount will be deleted as well - * @param trueAmount [out] - * If deleteRemaining was set to true, the amount deleted will be assigned - * to the passed value. - * @return - */ - ReturnValue_t deleteData(size_t amount, bool deleteRemaining = false, - size_t* trueAmount = nullptr); -private: - static const uint8_t READ_PTR = 0; - uint8_t* buffer = nullptr; - size_t maxExcessBytes; - size_t excessBytes = 0; -}; - -#endif /* FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_ */ - +#ifndef FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_ +#define FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_ + +#include "../container/RingBufferBase.h" +#include + +/** + * @brief Circular buffer implementation, useful for buffering + * into data streams. + * @details + * Note that the deleteData() has to be called to increment the read pointer. + * This class allocated dynamically, so + * @ingroup containers + */ +class SimpleRingBuffer: public RingBufferBase<> { +public: + /** + * This constructor allocates a new internal buffer with the supplied size. + * + * @param size + * @param overwriteOld If the ring buffer is overflowing at a write + * operation, the oldest data will be overwritten. + * @param maxExcessBytes These additional bytes will be allocated in addtion + * to the specified size to accomodate contiguous write operations + * with getFreeElement. + * + */ + SimpleRingBuffer(const size_t size, bool overwriteOld, + size_t maxExcessBytes = 0); + /** + * This constructor takes an external buffer with the specified size. + * @param buffer + * @param size + * @param overwriteOld + * If the ring buffer is overflowing at a write operartion, the oldest data + * will be overwritten. + * @param maxExcessBytes + * If the buffer can accomodate additional bytes for contigous write + * operations with getFreeElement, this is the maximum allowed additional + * size + */ + SimpleRingBuffer(uint8_t* buffer, const size_t size, bool overwriteOld, + size_t maxExcessBytes = 0); + + virtual ~SimpleRingBuffer(); + + /** + * Write to circular buffer and increment write pointer by amount. + * @param data + * @param amount + * @return -@c RETURN_OK if write operation was successfull + * -@c RETURN_FAILED if + */ + ReturnValue_t writeData(const uint8_t* data, size_t amount); + + /** + * Returns a pointer to a free element. If the remaining buffer is + * not large enough, the data will be written past the actual size + * and the amount of excess bytes will be cached. This function + * does not increment the write pointer! + * @param writePointer Pointer to a pointer which can be used to write + * contiguous blocks into the ring buffer + * @param amount + * @return + */ + ReturnValue_t getFreeElement(uint8_t** writePointer, size_t amount); + + /** + * This increments the write pointer and also copies the excess bytes + * to the beginning. It should be called if the write operation + * conducted after calling getFreeElement() was performed. + * @return + */ + void confirmBytesWritten(size_t amount); + + virtual size_t getExcessBytes() const; + /** + * Helper functions which moves any excess bytes to the start + * of the ring buffer. + * @return + */ + virtual void moveExcessBytesToStart(); + + /** + * Read from circular buffer at read pointer. + * @param data + * @param amount + * @param incrementReadPtr + * If this is set to true, the read pointer will be incremented. + * If readRemaining is set to true, the read pointer will be incremented + * accordingly. + * @param readRemaining + * If this is set to true, the data will be read even if the amount + * specified exceeds the read data available. + * @param trueAmount [out] + * If readRemaining was set to true, the true amount read will be assigned + * to the passed value. + * @return + * - @c RETURN_OK if data was read successfully + * - @c RETURN_FAILED if not enough data was available and readRemaining + * was set to false. + */ + ReturnValue_t readData(uint8_t* data, size_t amount, + bool incrementReadPtr = false, bool readRemaining = false, + size_t* trueAmount = nullptr); + + /** + * Delete data by incrementing read pointer. + * @param amount + * @param deleteRemaining + * If the amount specified is larger than the remaing size to read and this + * is set to true, the remaining amount will be deleted as well + * @param trueAmount [out] + * If deleteRemaining was set to true, the amount deleted will be assigned + * to the passed value. + * @return + */ + ReturnValue_t deleteData(size_t amount, bool deleteRemaining = false, + size_t* trueAmount = nullptr); +private: + static const uint8_t READ_PTR = 0; + uint8_t* buffer = nullptr; + size_t maxExcessBytes; + size_t excessBytes = 0; +}; + +#endif /* FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_ */ + From e105be229a075bb83e867cf00baa9f392d9d5468 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 4 Sep 2020 15:06:48 +0200 Subject: [PATCH 030/101] include guards fand include improvements --- container/SimpleRingBuffer.cpp | 2 +- container/SimpleRingBuffer.h | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/container/SimpleRingBuffer.cpp b/container/SimpleRingBuffer.cpp index d6b6f5af..01c22463 100644 --- a/container/SimpleRingBuffer.cpp +++ b/container/SimpleRingBuffer.cpp @@ -1,4 +1,4 @@ -#include "../container/SimpleRingBuffer.h" +#include "SimpleRingBuffer.h" #include SimpleRingBuffer::SimpleRingBuffer(const size_t size, bool overwriteOld, diff --git a/container/SimpleRingBuffer.h b/container/SimpleRingBuffer.h index dcf2684b..a790712f 100644 --- a/container/SimpleRingBuffer.h +++ b/container/SimpleRingBuffer.h @@ -1,7 +1,7 @@ -#ifndef FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_ -#define FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_ +#ifndef FSFW_CONTAINER_SIMPLERINGBUFFER_H_ +#define FSFW_CONTAINER_SIMPLERINGBUFFER_H_ -#include "../container/RingBufferBase.h" +#include "RingBufferBase.h" #include /** @@ -124,5 +124,5 @@ private: size_t excessBytes = 0; }; -#endif /* FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_ */ +#endif /* FSFW_CONTAINER_SIMPLERINGBUFFER_H_ */ From 3e67701933e6e64ac998691cd4e2e043e7786427 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 4 Sep 2020 15:09:24 +0200 Subject: [PATCH 031/101] taken over ring buffer base changes --- container/RingBufferBase.h | 125 +++++++++++++++++++++---------------- 1 file changed, 71 insertions(+), 54 deletions(-) diff --git a/container/RingBufferBase.h b/container/RingBufferBase.h index e3a87d9d..886b9fab 100644 --- a/container/RingBufferBase.h +++ b/container/RingBufferBase.h @@ -1,96 +1,113 @@ -#ifndef FRAMEWORK_CONTAINER_RINGBUFFERBASE_H_ -#define FRAMEWORK_CONTAINER_RINGBUFFERBASE_H_ +#ifndef FSFW_CONTAINER_RINGBUFFERBASE_H_ +#define FSFW_CONTAINER_RINGBUFFERBASE_H_ #include "../returnvalues/HasReturnvaluesIF.h" +#include template class RingBufferBase { public: - RingBufferBase(uint32_t startAddress, uint32_t size, bool overwriteOld) : - start(startAddress), write(startAddress), size(size), overwriteOld(overwriteOld) { + RingBufferBase(size_t startAddress, const size_t size, bool overwriteOld) : + start(startAddress), write(startAddress), size(size), + overwriteOld(overwriteOld) { for (uint8_t count = 0; count < N_READ_PTRS; count++) { read[count] = startAddress; } } - ReturnValue_t readData(uint32_t amount, uint8_t n = 0) { - if (availableReadData(n) >= amount) { - incrementRead(amount, n); - return HasReturnvaluesIF::RETURN_OK; - } else { - return HasReturnvaluesIF::RETURN_FAILED; - } - } - ReturnValue_t writeData(uint32_t amount) { - if (availableWriteSpace() >= amount || overwriteOld) { - incrementWrite(amount); - return HasReturnvaluesIF::RETURN_OK; - } else { - return HasReturnvaluesIF::RETURN_FAILED; - } - } - uint32_t availableReadData(uint8_t n = 0) const { - return ((write + size) - read[n]) % size; - } - uint32_t availableWriteSpace(uint8_t n = 0) const { - //One less to avoid ambiguous full/empty problem. - return (((read[n] + size) - write - 1) % size); - } + + virtual ~RingBufferBase() {} + bool isFull(uint8_t n = 0) { return (availableWriteSpace(n) == 0); } bool isEmpty(uint8_t n = 0) { - return (availableReadData(n) == 0); + return (getAvailableReadData(n) == 0); } - virtual ~RingBufferBase() { + size_t getAvailableReadData(uint8_t n = 0) const { + return ((write + size) - read[n]) % size; } - uint32_t getRead(uint8_t n = 0) const { - return read[n]; + size_t availableWriteSpace(uint8_t n = 0) const { + //One less to avoid ambiguous full/empty problem. + return (((read[n] + size) - write - 1) % size); } - void setRead(uint32_t read, uint8_t n = 0) { - if (read >= start && read < (start+size)) { - this->read[n] = read; - } + + bool overwritesOld() const { + return overwriteOld; } - uint32_t getWrite() const { - return write; - } - void setWrite(uint32_t write) { - this->write = write; + + size_t getMaxSize() const { + return size - 1; } + void clear() { write = start; for (uint8_t count = 0; count < N_READ_PTRS; count++) { read[count] = start; } } - uint32_t writeTillWrap() { + + size_t writeTillWrap() { return (start + size) - write; } - uint32_t readTillWrap(uint8_t n = 0) { + + size_t readTillWrap(uint8_t n = 0) { return (start + size) - read[n]; } - uint32_t getStart() const { + + size_t getStart() const { return start; } - bool overwritesOld() const { - return overwriteOld; - } - uint32_t maxSize() const { - return size - 1; - } + protected: - const uint32_t start; - uint32_t write; - uint32_t read[N_READ_PTRS]; - const uint32_t size; + const size_t start; + size_t write; + size_t read[N_READ_PTRS]; + const size_t size; const bool overwriteOld; + void incrementWrite(uint32_t amount) { write = ((write + amount - start) % size) + start; } void incrementRead(uint32_t amount, uint8_t n = 0) { read[n] = ((read[n] + amount - start) % size) + start; } + + ReturnValue_t readData(uint32_t amount, uint8_t n = 0) { + if (getAvailableReadData(n) >= amount) { + incrementRead(amount, n); + return HasReturnvaluesIF::RETURN_OK; + } else { + return HasReturnvaluesIF::RETURN_FAILED; + } + } + + ReturnValue_t writeData(uint32_t amount) { + if (availableWriteSpace() >= amount or overwriteOld) { + incrementWrite(amount); + return HasReturnvaluesIF::RETURN_OK; + } else { + return HasReturnvaluesIF::RETURN_FAILED; + } + } + + size_t getRead(uint8_t n = 0) const { + return read[n]; + } + + void setRead(uint32_t read, uint8_t n = 0) { + if (read >= start && read < (start+size)) { + this->read[n] = read; + } + } + + uint32_t getWrite() const { + return write; + } + + void setWrite(uint32_t write) { + this->write = write; + } }; -#endif /* FRAMEWORK_CONTAINER_RINGBUFFERBASE_H_ */ +#endif /* FSFW_CONTAINER_RINGBUFFERBASE_H_ */ From 06400fa7bbd89792bc1e508aa6ecf424981ab453 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 4 Sep 2020 15:10:44 +0200 Subject: [PATCH 032/101] share dring buffer update --- container/SharedRingBuffer.cpp | 6 +++--- container/SharedRingBuffer.h | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/container/SharedRingBuffer.cpp b/container/SharedRingBuffer.cpp index 001a21ed..490988e5 100644 --- a/container/SharedRingBuffer.cpp +++ b/container/SharedRingBuffer.cpp @@ -1,6 +1,6 @@ -#include -#include -#include +#include "../container/SharedRingBuffer.h" +#include "../ipc/MutexFactory.h" +#include "../ipc/MutexHelper.h" SharedRingBuffer::SharedRingBuffer(object_id_t objectId, const size_t size, bool overwriteOld, size_t maxExcessBytes): diff --git a/container/SharedRingBuffer.h b/container/SharedRingBuffer.h index 0b5be052..394dcaaa 100644 --- a/container/SharedRingBuffer.h +++ b/container/SharedRingBuffer.h @@ -1,10 +1,10 @@ #ifndef FRAMEWORK_CONTAINER_SHAREDRINGBUFFER_H_ #define FRAMEWORK_CONTAINER_SHAREDRINGBUFFER_H_ -#include -#include -#include -#include +#include "../container/SimpleRingBuffer.h" +#include "../ipc/MutexIF.h" +#include "../objectmanager/SystemObject.h" +#include "../timemanager/Clock.h" /** * @brief Ring buffer which can be shared among multiple objects From dbac6e139b6e7991d5f0997d7b2a9f7daebbbe44 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 4 Sep 2020 15:11:53 +0200 Subject: [PATCH 033/101] shared ring buffer update --- container/SharedRingBuffer.cpp | 2 +- container/SharedRingBuffer.h | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/container/SharedRingBuffer.cpp b/container/SharedRingBuffer.cpp index 490988e5..800e75d3 100644 --- a/container/SharedRingBuffer.cpp +++ b/container/SharedRingBuffer.cpp @@ -1,4 +1,4 @@ -#include "../container/SharedRingBuffer.h" +#include "SharedRingBuffer.h" #include "../ipc/MutexFactory.h" #include "../ipc/MutexHelper.h" diff --git a/container/SharedRingBuffer.h b/container/SharedRingBuffer.h index 394dcaaa..80c068b3 100644 --- a/container/SharedRingBuffer.h +++ b/container/SharedRingBuffer.h @@ -1,7 +1,7 @@ -#ifndef FRAMEWORK_CONTAINER_SHAREDRINGBUFFER_H_ -#define FRAMEWORK_CONTAINER_SHAREDRINGBUFFER_H_ +#ifndef FSFW_CONTAINER_SHAREDRINGBUFFER_H_ +#define FSFW_CONTAINER_SHAREDRINGBUFFER_H_ -#include "../container/SimpleRingBuffer.h" +#include "SimpleRingBuffer.h" #include "../ipc/MutexIF.h" #include "../objectmanager/SystemObject.h" #include "../timemanager/Clock.h" @@ -65,4 +65,4 @@ private: -#endif /* FRAMEWORK_CONTAINER_SHAREDRINGBUFFER_H_ */ +#endif /* FSFW_CONTAINER_SHAREDRINGBUFFER_H_ */ From e96ab123121d5d0039e60f3069b4a8b226fa7751 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 15 Sep 2020 15:55:35 +0200 Subject: [PATCH 034/101] comment and calculation fix --- ipc/CommandMessage.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/ipc/CommandMessage.h b/ipc/CommandMessage.h index ca7b817f..8f5daa04 100644 --- a/ipc/CommandMessage.h +++ b/ipc/CommandMessage.h @@ -8,7 +8,7 @@ /** * @brief Default command message used to pass command messages between tasks. * Primary message type for IPC. Contains sender, 2-byte command ID - * field, and 2 4-byte parameters. + * field, and 3 4-byte parameter * @details * It operates on an external memory which is contained inside a * class implementing MessageQueueMessageIF by taking its address. @@ -23,10 +23,11 @@ class CommandMessage: public MessageQueueMessage, public CommandMessageIF { public: /** - * Default size can accomodate 2 4-byte parameters. + * Default size can accomodate 3 4-byte parameters. */ static constexpr size_t DEFAULT_COMMAND_MESSAGE_SIZE = - CommandMessageIF::MINIMUM_COMMAND_MESSAGE_SIZE + sizeof(uint32_t); + CommandMessageIF::MINIMUM_COMMAND_MESSAGE_SIZE + + 3 * sizeof(uint32_t); /** * @brief Default Constructor, does not initialize anything. From 3fcbb988ae0c299b48ed632761d690467426ca23 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 15 Sep 2020 16:47:01 +0200 Subject: [PATCH 035/101] new file for typedef to avoid circular include --- ipc/MessageQueueMessageIF.h | 17 +++-------------- ipc/MessageQueueSenderIF.h | 23 ++++++----------------- ipc/messageQueueDefinitions.h | 18 ++++++++++++++++++ 3 files changed, 27 insertions(+), 31 deletions(-) create mode 100644 ipc/messageQueueDefinitions.h diff --git a/ipc/MessageQueueMessageIF.h b/ipc/MessageQueueMessageIF.h index 91753ced..b5a30c08 100644 --- a/ipc/MessageQueueMessageIF.h +++ b/ipc/MessageQueueMessageIF.h @@ -1,24 +1,13 @@ #ifndef FRAMEWORK_IPC_MESSAGEQUEUEMESSAGEIF_H_ #define FRAMEWORK_IPC_MESSAGEQUEUEMESSAGEIF_H_ + +#include #include #include -/* - * TODO: Actually, the definition of this ID to be a uint32_t is not ideal and - * breaks layering. However, it is difficult to keep layering, as the ID is - * stored in many places and sent around in MessageQueueMessage. - * Ideally, one would use the (current) object_id_t only, however, doing a - * lookup of queueIDs for every call does not sound ideal. - * In a first step, I'll circumvent the issue by not touching it, - * maybe in a second step. This also influences Interface design - * (getCommandQueue) and some other issues.. - */ - -typedef uint32_t MessageQueueId_t; - class MessageQueueMessageIF { public: - static const MessageQueueId_t NO_QUEUE = -1; + /** * @brief This constants defines the size of the header, * which is added to every message. diff --git a/ipc/MessageQueueSenderIF.h b/ipc/MessageQueueSenderIF.h index d9692f54..beb27f50 100644 --- a/ipc/MessageQueueSenderIF.h +++ b/ipc/MessageQueueSenderIF.h @@ -1,37 +1,26 @@ #ifndef FRAMEWORK_IPC_MESSAGEQUEUESENDERIF_H_ #define FRAMEWORK_IPC_MESSAGEQUEUESENDERIF_H_ +#include "../ipc/MessageQueueIF.h" +#include "../ipc/MessageQueueMessageIF.h" #include "../objectmanager/ObjectManagerIF.h" -class MessageQueueMessage; - - -//TODO: Actually, the definition of this ID to be a uint32_t is not ideal and breaks layering. -//However, it is difficult to keep layering, as the ID is stored in many places and sent around in -//MessageQueueMessage. -//Ideally, one would use the (current) object_id_t only, however, doing a lookup of queueIDs for every -//call does not sound ideal. -//In a first step, I'll circumvent the issue by not touching it, maybe in a second step. -//This also influences Interface design (getCommandQueue) and some other issues.. -typedef uint32_t MessageQueueId_t; class MessageQueueSenderIF { public: - static const MessageQueueId_t NO_QUEUE = 0; virtual ~MessageQueueSenderIF() {} /** - * Allows sending messages without actually "owing" a message queue. + * Allows sending messages without actually "owning" a message queue. * Not sure whether this is actually a good idea. - * Must be implemented by a subclass. */ static ReturnValue_t sendMessage(MessageQueueId_t sendTo, - MessageQueueMessage* message, MessageQueueId_t sentFrom = - MessageQueueSenderIF::NO_QUEUE, bool ignoreFault=false); + MessageQueueMessageIF* message, + MessageQueueId_t sentFrom = MessageQueueIF::NO_QUEUE, + bool ignoreFault = false); private: MessageQueueSenderIF() {} }; - #endif /* FRAMEWORK_IPC_MESSAGEQUEUESENDERIF_H_ */ diff --git a/ipc/messageQueueDefinitions.h b/ipc/messageQueueDefinitions.h new file mode 100644 index 00000000..d30e6984 --- /dev/null +++ b/ipc/messageQueueDefinitions.h @@ -0,0 +1,18 @@ +#ifndef FSFW_IPC_MESSAGEQUEUEDEFINITIONS_H_ +#define FSFW_IPC_MESSAGEQUEUEDEFINITIONS_H_ + +#include + +/* + * TODO: Actually, the definition of this ID to be a uint32_t is not ideal and + * breaks layering. However, it is difficult to keep layering, as the ID is + * stored in many places and sent around in MessageQueueMessage. + * Ideally, one would use the (current) object_id_t only, however, doing a + * lookup of queueIDs for every call does not sound ideal. + * In a first step, I'll circumvent the issue by not touching it, + * maybe in a second step. This also influences Interface design + * (getCommandQueue) and some other issues.. + */ +using MessageQueueId_t = uint32_t; + +#endif /* FSFW_IPC_MESSAGEQUEUEDEFINITIONS_H_ */ From 21346e40a54e93a3753042fd4259ddc4154d9622 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 15 Sep 2020 16:58:38 +0200 Subject: [PATCH 036/101] some improvements --- action/ActionHelper.cpp | 1 + datalinklayer/MapPacketExtraction.cpp | 2 +- ipc/MessageQueueIF.h | 10 +++++----- ipc/MessageQueueMessage.h | 1 - ipc/MessageQueueSenderIF.h | 8 ++++---- ipc/messageQueueDefinitions.h | 1 + modes/ModeHelper.cpp | 8 ++++---- osal/FreeRTOS/MessageQueue.cpp | 4 +++- osal/FreeRTOS/QueueFactory.cpp | 7 +++++-- 9 files changed, 24 insertions(+), 18 deletions(-) diff --git a/action/ActionHelper.cpp b/action/ActionHelper.cpp index b43c676d..361f7dc3 100644 --- a/action/ActionHelper.cpp +++ b/action/ActionHelper.cpp @@ -1,5 +1,6 @@ #include "ActionHelper.h" #include "HasActionsIF.h" +#include "../ipc/MessageQueueSenderIF.h" #include "../objectmanager/ObjectManagerIF.h" ActionHelper::ActionHelper(HasActionsIF* setOwner, MessageQueueIF* useThisQueue) : diff --git a/datalinklayer/MapPacketExtraction.cpp b/datalinklayer/MapPacketExtraction.cpp index cb12b321..d64348e1 100644 --- a/datalinklayer/MapPacketExtraction.cpp +++ b/datalinklayer/MapPacketExtraction.cpp @@ -18,7 +18,7 @@ MapPacketExtraction::MapPacketExtraction(uint8_t setMapId, object_id_t setPacketDestination) : lastSegmentationFlag(NO_SEGMENTATION), mapId(setMapId), packetLength(0), bufferPosition( packetBuffer), packetDestination(setPacketDestination), packetStore( - NULL), tcQueueId(MessageQueueSenderIF::NO_QUEUE) { + NULL), tcQueueId(MessageQueueIF::NO_QUEUE) { memset(packetBuffer, 0, sizeof(packetBuffer)); } diff --git a/ipc/MessageQueueIF.h b/ipc/MessageQueueIF.h index 9fff5287..b0347db9 100644 --- a/ipc/MessageQueueIF.h +++ b/ipc/MessageQueueIF.h @@ -1,15 +1,15 @@ -#ifndef FRAMEWORK_IPC_MESSAGEQUEUEIF_H_ -#define FRAMEWORK_IPC_MESSAGEQUEUEIF_H_ +#ifndef FSFW_IPC_MESSAGEQUEUEIF_H_ +#define FSFW_IPC_MESSAGEQUEUEIF_H_ // COULDDO: We could support blocking calls +#include "messageQueueDefinitions.h" #include "MessageQueueMessage.h" -#include "MessageQueueSenderIF.h" #include "../returnvalues/HasReturnvaluesIF.h" + class MessageQueueIF { public: - - static const MessageQueueId_t NO_QUEUE = MessageQueueSenderIF::NO_QUEUE; //!< Ugly hack. + static const MessageQueueId_t NO_QUEUE = 0; static const uint8_t INTERFACE_ID = CLASS_ID::MESSAGE_QUEUE_IF; /** diff --git a/ipc/MessageQueueMessage.h b/ipc/MessageQueueMessage.h index f68e9b9f..5234f64f 100644 --- a/ipc/MessageQueueMessage.h +++ b/ipc/MessageQueueMessage.h @@ -2,7 +2,6 @@ #define FSFW_IPC_MESSAGEQUEUEMESSAGE_H_ #include "../ipc/MessageQueueMessageIF.h" -#include "../ipc/MessageQueueSenderIF.h" #include /** diff --git a/ipc/MessageQueueSenderIF.h b/ipc/MessageQueueSenderIF.h index beb27f50..7eea5146 100644 --- a/ipc/MessageQueueSenderIF.h +++ b/ipc/MessageQueueSenderIF.h @@ -1,5 +1,5 @@ -#ifndef FRAMEWORK_IPC_MESSAGEQUEUESENDERIF_H_ -#define FRAMEWORK_IPC_MESSAGEQUEUESENDERIF_H_ +#ifndef FSFW_IPC_MESSAGEQUEUESENDERIF_H_ +#define FSFW_IPC_MESSAGEQUEUESENDERIF_H_ #include "../ipc/MessageQueueIF.h" #include "../ipc/MessageQueueMessageIF.h" @@ -15,7 +15,7 @@ public: * Not sure whether this is actually a good idea. */ static ReturnValue_t sendMessage(MessageQueueId_t sendTo, - MessageQueueMessageIF* message, + MessageQueueMessage* message, MessageQueueId_t sentFrom = MessageQueueIF::NO_QUEUE, bool ignoreFault = false); private: @@ -23,4 +23,4 @@ private: }; -#endif /* FRAMEWORK_IPC_MESSAGEQUEUESENDERIF_H_ */ +#endif /* FSFW_IPC_MESSAGEQUEUESENDERIF_H_ */ diff --git a/ipc/messageQueueDefinitions.h b/ipc/messageQueueDefinitions.h index d30e6984..60c09b05 100644 --- a/ipc/messageQueueDefinitions.h +++ b/ipc/messageQueueDefinitions.h @@ -15,4 +15,5 @@ */ using MessageQueueId_t = uint32_t; + #endif /* FSFW_IPC_MESSAGEQUEUEDEFINITIONS_H_ */ diff --git a/modes/ModeHelper.cpp b/modes/ModeHelper.cpp index cb62c468..f464a743 100644 --- a/modes/ModeHelper.cpp +++ b/modes/ModeHelper.cpp @@ -36,7 +36,7 @@ ReturnValue_t ModeHelper::handleModeCommand(CommandMessage* message) { commandedMode = mode; commandedSubmode = submode; - if ((parentQueueId != MessageQueueSenderIF::NO_QUEUE) + if ((parentQueueId != MessageQueueIF::NO_QUEUE) && (theOneWhoCommandedAMode != parentQueueId)) { owner->setToExternalControl(); } @@ -74,7 +74,7 @@ ReturnValue_t ModeHelper::initialize(MessageQueueId_t parentQueueId) { void ModeHelper::modeChanged(Mode_t mode, Submode_t submode) { forced = false; CommandMessage reply; - if (theOneWhoCommandedAMode != MessageQueueSenderIF::NO_QUEUE) { + if (theOneWhoCommandedAMode != MessageQueueIF::NO_QUEUE) { if ((mode != commandedMode) || (submode != commandedSubmode)) { ModeMessage::setModeMessage(&reply, ModeMessage::REPLY_WRONG_MODE_REPLY, mode, submode); @@ -86,12 +86,12 @@ void ModeHelper::modeChanged(Mode_t mode, Submode_t submode) { owner->getCommandQueue()); } if (theOneWhoCommandedAMode != parentQueueId - && parentQueueId != MessageQueueSenderIF::NO_QUEUE) { + && parentQueueId != MessageQueueIF::NO_QUEUE) { ModeMessage::setModeMessage(&reply, ModeMessage::REPLY_MODE_INFO, mode, submode); MessageQueueSenderIF::sendMessage(parentQueueId, &reply, owner->getCommandQueue()); } - theOneWhoCommandedAMode = MessageQueueSenderIF::NO_QUEUE; + theOneWhoCommandedAMode = MessageQueueIF::NO_QUEUE; } void ModeHelper::startTimer(uint32_t timeoutMs) { diff --git a/osal/FreeRTOS/MessageQueue.cpp b/osal/FreeRTOS/MessageQueue.cpp index 3bbd4d9d..6c8e1de9 100644 --- a/osal/FreeRTOS/MessageQueue.cpp +++ b/osal/FreeRTOS/MessageQueue.cpp @@ -1,5 +1,6 @@ #include "MessageQueue.h" +#include "../../objectmanager/ObjectManagerIF.h" #include "../../serviceinterface/ServiceInterfaceStream.h" // TODO I guess we should have a way of checking if we are in an ISR and then use the "fromISR" versions of all calls @@ -101,7 +102,8 @@ ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo, reinterpret_cast(message->getBuffer()), 0); if (result != pdPASS) { if (!ignoreFault) { - InternalErrorReporterIF* internalErrorReporter = objectManager->get( + InternalErrorReporterIF* internalErrorReporter = + objectManager->get( objects::INTERNAL_ERROR_REPORTER); if (internalErrorReporter != NULL) { internalErrorReporter->queueMessageNotSent(); diff --git a/osal/FreeRTOS/QueueFactory.cpp b/osal/FreeRTOS/QueueFactory.cpp index e639179a..0de6ad4f 100644 --- a/osal/FreeRTOS/QueueFactory.cpp +++ b/osal/FreeRTOS/QueueFactory.cpp @@ -1,3 +1,4 @@ +#include "../../ipc/MessageQueueSenderIF.h" #include "../../ipc/QueueFactory.h" #include "MessageQueue.h" @@ -7,8 +8,10 @@ QueueFactory* QueueFactory::factoryInstance = NULL; ReturnValue_t MessageQueueSenderIF::sendMessage(MessageQueueId_t sendTo, - MessageQueueMessage* message, MessageQueueId_t sentFrom,bool ignoreFault) { - return MessageQueue::sendMessageFromMessageQueue(sendTo,message,sentFrom,ignoreFault); + MessageQueueMessage* message, MessageQueueId_t sentFrom, + bool ignoreFault) { + return MessageQueue::sendMessageFromMessageQueue(sendTo, message, + sentFrom, ignoreFault); } QueueFactory* QueueFactory::instance() { From a5c6be9dd94cc213c752936634a991545a5ffa7e Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Wed, 16 Sep 2020 19:05:25 +0200 Subject: [PATCH 037/101] added srv17 --- events/fwSubsystemIdRanges.h | 7 +++--- pus/Service17Test.cpp | 41 +++++++++++++++++++++++++++++++++ pus/Service17Test.h | 44 ++++++++++++++++++++++++++++++++++++ 3 files changed, 89 insertions(+), 3 deletions(-) create mode 100644 pus/Service17Test.cpp create mode 100644 pus/Service17Test.h diff --git a/events/fwSubsystemIdRanges.h b/events/fwSubsystemIdRanges.h index a05652c2..e21d16b8 100644 --- a/events/fwSubsystemIdRanges.h +++ b/events/fwSubsystemIdRanges.h @@ -1,5 +1,5 @@ -#ifndef FRAMEWORK_EVENTS_FWSUBSYSTEMIDRANGES_H_ -#define FRAMEWORK_EVENTS_FWSUBSYSTEMIDRANGES_H_ +#ifndef FSFW_EVENTS_FWSUBSYSTEMIDRANGES_H_ +#define FSFW_EVENTS_FWSUBSYSTEMIDRANGES_H_ namespace SUBSYSTEM_ID { enum { @@ -19,10 +19,11 @@ enum { SYSTEM_MANAGER_1 = 75, SYSTEM_1 = 79, PUS_SERVICE_1 = 80, + PUS_SERVICE_17 = 97, FW_SUBSYSTEM_ID_RANGE }; } -#endif /* FRAMEWORK_EVENTS_FWSUBSYSTEMIDRANGES_H_ */ +#endif /* FSFW_EVENTS_FWSUBSYSTEMIDRANGES_H_ */ diff --git a/pus/Service17Test.cpp b/pus/Service17Test.cpp new file mode 100644 index 00000000..2ef44490 --- /dev/null +++ b/pus/Service17Test.cpp @@ -0,0 +1,41 @@ +#include "Service17Test.h" + +#include "../serviceinterface/ServiceInterfaceStream.h" +#include "../objectmanager/SystemObject.h" +#include "../tmtcpacket/pus/TmPacketStored.h" + + +Service17Test::Service17Test(object_id_t objectId, + uint16_t apid, uint8_t serviceId): + PusServiceBase(objectId, apid, serviceId), + packetSubCounter(0) { +} + +Service17Test::~Service17Test() { +} + +ReturnValue_t Service17Test::handleRequest(uint8_t subservice) { + switch(subservice){ + case Subservice::CONNECTION_TEST: { + TmPacketStored connectionPacket(apid, serviceId, + Subservice::CONNECTION_TEST_REPORT, packetSubCounter++); + connectionPacket.sendPacket(requestQueue->getDefaultDestination(), + requestQueue->getId()); + return HasReturnvaluesIF::RETURN_OK; + } + case Subservice::EVENT_TRIGGER_TEST: { + TmPacketStored connectionPacket(apid, serviceId, + Subservice::CONNECTION_TEST_REPORT, packetSubCounter++); + connectionPacket.sendPacket(requestQueue->getDefaultDestination(), + requestQueue->getId()); + triggerEvent(TEST, 1234, 5678); + return RETURN_OK; + } + default: + return AcceptsTelecommandsIF::INVALID_SUBSERVICE; + } +} + +ReturnValue_t Service17Test::performService() { + return HasReturnvaluesIF::RETURN_OK; +} diff --git a/pus/Service17Test.h b/pus/Service17Test.h new file mode 100644 index 00000000..e2681865 --- /dev/null +++ b/pus/Service17Test.h @@ -0,0 +1,44 @@ +#ifndef FSFW_PUS_SERVICE17TEST_H_ +#define FSFW_PUS_SERVICE17TEST_H_ + +#include "../tmtcservices/PusServiceBase.h" +#include "../objectmanager/SystemObject.h" + +/** + * @brief Test Service + * Full Documentation: ECSS-E70-41A p.167 + * + * The test service provides the capability to activate test functions + * implemented on-board and to report the results of such tests. + * Service capability: + * - TC[17,1]: Perform connection test + * - TM[17,2]: Send Connection Test Report + * - TC[17,128]: Perform connection test and trigger event + * + * @ingroup pus_services + */ +class Service17Test: public PusServiceBase { +public: + // Custom events which can be triggered + static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PUS_SERVICE_17; + static constexpr Event TEST = MAKE_EVENT(0, SEVERITY::INFO); + + enum Subservice: uint8_t { + //! [EXPORT] : [COMMAND] Perform connection test + CONNECTION_TEST = 1, + //! [EXPORT] : [REPLY] Connection test reply + CONNECTION_TEST_REPORT = 2, + //! [EXPORT] : [COMMAND] Trigger test reply and test event + EVENT_TRIGGER_TEST = 128, + }; + + Service17Test(object_id_t objectId, uint16_t apid, uint8_t serviceId); + virtual ~Service17Test(); + virtual ReturnValue_t handleRequest(uint8_t subservice) override; + virtual ReturnValue_t performService() override; + +protected: + uint16_t packetSubCounter = 0; +}; + +#endif /* FSFW_PUS_SERVICE17TEST_H_ */ From ae426c50baf54d7c8f6b022da434dbc510fcef0c Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Wed, 16 Sep 2020 19:09:51 +0200 Subject: [PATCH 038/101] space replaced by tab --- events/fwSubsystemIdRanges.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/events/fwSubsystemIdRanges.h b/events/fwSubsystemIdRanges.h index e21d16b8..5e086f0e 100644 --- a/events/fwSubsystemIdRanges.h +++ b/events/fwSubsystemIdRanges.h @@ -19,7 +19,7 @@ enum { SYSTEM_MANAGER_1 = 75, SYSTEM_1 = 79, PUS_SERVICE_1 = 80, - PUS_SERVICE_17 = 97, + PUS_SERVICE_17 = 97, FW_SUBSYSTEM_ID_RANGE }; } From b31bee4fdac61bc103b62fb881b617b808840129 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Wed, 16 Sep 2020 19:11:50 +0200 Subject: [PATCH 039/101] added srv9 --- pus/Service9TimeManagement.cpp | 58 ++++++++++++++++++++++++++++ pus/Service9TimeManagement.h | 42 ++++++++++++++++++++ pus/servicepackets/Service9Packets.h | 32 +++++++++++++++ 3 files changed, 132 insertions(+) create mode 100644 pus/Service9TimeManagement.cpp create mode 100644 pus/Service9TimeManagement.h create mode 100644 pus/servicepackets/Service9Packets.h diff --git a/pus/Service9TimeManagement.cpp b/pus/Service9TimeManagement.cpp new file mode 100644 index 00000000..5625bdd8 --- /dev/null +++ b/pus/Service9TimeManagement.cpp @@ -0,0 +1,58 @@ +#include "Service9TimeManagement.h" +#include "servicepackets/Service9Packets.h" + +#include "../timemanager/CCSDSTime.h" +#include "../events/EventManagerIF.h" +#include "../serviceinterface/ServiceInterfaceStream.h" + + +Service9TimeManagement::Service9TimeManagement(object_id_t objectId, + uint16_t apid, uint8_t serviceId) : + PusServiceBase(objectId, apid , serviceId) { +} + +Service9TimeManagement::~Service9TimeManagement() {} + +ReturnValue_t Service9TimeManagement::performService() { + return RETURN_OK; +} + +ReturnValue_t Service9TimeManagement::handleRequest(uint8_t subservice) { + switch(subservice){ + case SUBSERVICE::SET_TIME:{ + return setTime(); + } + default: + return AcceptsTelecommandsIF::INVALID_SUBSERVICE; + } +} + +ReturnValue_t Service9TimeManagement::setTime() { + Clock::TimeOfDay_t timeToSet; + TimePacket timePacket(currentPacket.getApplicationData(), + currentPacket.getApplicationDataSize()); + ReturnValue_t result = CCSDSTime::convertFromCcsds(&timeToSet, + timePacket.getTime(), timePacket.getTimeSize()); + if(result != RETURN_OK) { + triggerEvent(CLOCK_SET_FAILURE, result, 0); + return result; + } + + uint32_t formerUptime; + Clock::getUptime(&formerUptime); + result = Clock::setClock(&timeToSet); + + if(result == RETURN_OK) { + uint32_t newUptime; + Clock::getUptime(&newUptime); + triggerEvent(CLOCK_SET,newUptime,formerUptime); + return RETURN_OK; + } + else { + triggerEvent(CLOCK_SET_FAILURE, result, 0); + return RETURN_FAILED; + } +} + + + diff --git a/pus/Service9TimeManagement.h b/pus/Service9TimeManagement.h new file mode 100644 index 00000000..4ad6be6e --- /dev/null +++ b/pus/Service9TimeManagement.h @@ -0,0 +1,42 @@ +#ifndef FSFW_PUS_SERVICE9TIMEMANAGEMENT_H_ +#define FSFW_PUS_SERVICE9TIMEMANAGEMENT_H_ + +#include + +class Service9TimeManagement: public PusServiceBase { +public: + + static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::PUS_SERVICE_9; + 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; + + /** + * @brief This service provides the capability to set the on-board time. + */ + Service9TimeManagement(object_id_t objectId, uint16_t apid, + uint8_t serviceId); + + virtual ~Service9TimeManagement(); + + virtual ReturnValue_t performService() override; + + /** + * @brief Sets the onboard-time by retrieving the time to set from TC[9,128]. + */ + virtual ReturnValue_t handleRequest(uint8_t subservice) override; + + virtual ReturnValue_t setTime(); +private: + + enum SUBSERVICE { + SET_TIME = 128 //!< [EXPORT] : [COMMAND] Time command in ASCII, CUC or CDS format + }; + + void setIsisClock(Clock::TimeOfDay_t& timeOfDay); +}; + + + +#endif /* FSFW_PUS_SERVICE9TIMEMANAGEMENT_H_ */ diff --git a/pus/servicepackets/Service9Packets.h b/pus/servicepackets/Service9Packets.h new file mode 100644 index 00000000..11bd2600 --- /dev/null +++ b/pus/servicepackets/Service9Packets.h @@ -0,0 +1,32 @@ +#ifndef FSFW_PUS_SERVICEPACKETS_SERVICE9PACKETS_H_ +#define FSFW_PUS_SERVICEPACKETS_SERVICE9PACKETS_H_ + +#include "../../serialize/SerialLinkedListAdapter.h" + +/** + * @brief Subservice 128 + * @details + * It only contains the time encoded as ASCII, CRC, CUC or CDS + * @ingroup spacepackets + */ +class TimePacket : SerialLinkedListAdapter { //!< [EXPORT] : [SUBSERVICE] 128 +public: + TimePacket(const uint8_t * timeBuffer_, uint32_t timeSize_) { + timeBuffer = timeBuffer_; + timeSize = timeSize_; + } + const uint8_t* getTime() { + return timeBuffer; + } + + uint32_t getTimeSize() const { + return timeSize; + } + +private: + TimePacket(const TimePacket &command); + const uint8_t * timeBuffer; + uint32_t timeSize; //!< [EXPORT] : [IGNORE] +}; + +#endif /* FSFW_PUS_SERVICEPACKETS_SERVICE9PACKETS_H_ */ From 85d6e81881f22037176c2f3e457bbd35733d9035 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Wed, 16 Sep 2020 19:17:00 +0200 Subject: [PATCH 040/101] added srv9 to class IDs --- returnvalues/FwClassIds.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/returnvalues/FwClassIds.h b/returnvalues/FwClassIds.h index 80df5741..e547025b 100644 --- a/returnvalues/FwClassIds.h +++ b/returnvalues/FwClassIds.h @@ -1,5 +1,5 @@ -#ifndef FRAMEWORK_RETURNVALUES_FWCLASSIDS_H_ -#define FRAMEWORK_RETURNVALUES_FWCLASSIDS_H_ +#ifndef FSFW_RETURNVALUES_FWCLASSIDS_H_ +#define FSFW_RETURNVALUES_FWCLASSIDS_H_ namespace CLASS_ID { enum { @@ -65,9 +65,10 @@ enum { POOL_VARIABLE_IF, //PVA 59 HOUSEKEEPING_MANAGER, //HKM 60 DLE_ENCODER, //DLEE 61 + PUS_SERVICE_9, //PUS9 62 FW_CLASS_ID_COUNT //is actually count + 1 ! }; } -#endif /* FRAMEWORK_RETURNVALUES_FWCLASSIDS_H_ */ +#endif /* FSFW_RETURNVALUES_FWCLASSIDS_H_ */ From 963015513f8e8825deaa95a7cabafd878d4811f4 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Wed, 16 Sep 2020 19:36:15 +0200 Subject: [PATCH 041/101] added time stamper to framework --- timemanager/TimeStamper.cpp | 23 +++++++++++++++++++++++ timemanager/TimeStamper.h | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 timemanager/TimeStamper.cpp create mode 100644 timemanager/TimeStamper.h diff --git a/timemanager/TimeStamper.cpp b/timemanager/TimeStamper.cpp new file mode 100644 index 00000000..07c3530c --- /dev/null +++ b/timemanager/TimeStamper.cpp @@ -0,0 +1,23 @@ +#include +#include +#include + +TimeStamper::TimeStamper(object_id_t objectId): SystemObject(objectId) {} + + +ReturnValue_t TimeStamper::addTimeStamp(uint8_t* buffer, + const uint8_t maxSize) { + if(maxSize < TimeStamperIF::MISSION_TIMESTAMP_SIZE){ + return HasReturnvaluesIF::RETURN_FAILED; + } + + timeval now; + Clock::getClock_timeval(&now); + CCSDSTime::CDS_short cds; + ReturnValue_t result = CCSDSTime::convertToCcsds(&cds,&now); + if(result != HasReturnvaluesIF::RETURN_OK){ + return result; + } + memcpy(buffer,&cds,sizeof(cds)); + return result; +} diff --git a/timemanager/TimeStamper.h b/timemanager/TimeStamper.h new file mode 100644 index 00000000..80139c50 --- /dev/null +++ b/timemanager/TimeStamper.h @@ -0,0 +1,36 @@ +#ifndef FSFW_TIMEMANAGER_TIMESTAMPER_H_ +#define FSFW_TIMEMANAGER_TIMESTAMPER_H_ + +#include +#include +#include + +/** + * @brief Time stamper which can be used to add any timestamp to a + * given buffer. + * @details + * This time stamper uses the CCSDS CDC short timestamp as a fault timestamp. + * This timestamp has a size of 8 bytes. A custom timestamp can be used by + * overriding the #addTimeStamp function. + * @ingroup utility + */ +class TimeStamper: public TimeStamperIF, public SystemObject { +public: + /** + * @brief Default constructor which also registers the time stamper as a + * system object so it can be found with the #objectManager. + * @param objectId + */ + TimeStamper(object_id_t objectId); + + /** + * Adds a CCSDS CDC short 8 byte timestamp to the given buffer. + * This function can be overriden to use a custom timestamp. + * @param buffer + * @param maxSize + * @return + */ + virtual ReturnValue_t addTimeStamp(uint8_t* buffer, const uint8_t maxSize); +}; + +#endif /* FSFW_TIMEMANAGER_TIMESTAMPER_H_ */ From b0a816490e89c639e34849587eb4bc11d619b99f Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Wed, 16 Sep 2020 19:37:17 +0200 Subject: [PATCH 042/101] fixed includes --- timemanager/TimeStamper.cpp | 6 +++--- timemanager/TimeStamper.h | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/timemanager/TimeStamper.cpp b/timemanager/TimeStamper.cpp index 07c3530c..d9f0f2f3 100644 --- a/timemanager/TimeStamper.cpp +++ b/timemanager/TimeStamper.cpp @@ -1,5 +1,5 @@ -#include -#include +#include "TimeStamper.h" +#include "Clock.h" #include TimeStamper::TimeStamper(object_id_t objectId): SystemObject(objectId) {} @@ -18,6 +18,6 @@ ReturnValue_t TimeStamper::addTimeStamp(uint8_t* buffer, if(result != HasReturnvaluesIF::RETURN_OK){ return result; } - memcpy(buffer,&cds,sizeof(cds)); + std::memcpy(buffer,&cds,sizeof(cds)); return result; } diff --git a/timemanager/TimeStamper.h b/timemanager/TimeStamper.h index 80139c50..6895c14b 100644 --- a/timemanager/TimeStamper.h +++ b/timemanager/TimeStamper.h @@ -1,9 +1,9 @@ #ifndef FSFW_TIMEMANAGER_TIMESTAMPER_H_ #define FSFW_TIMEMANAGER_TIMESTAMPER_H_ -#include -#include -#include +#include "TimeStamperIF.h" +#include "CCSDSTime.h" +#include "../objectmanager/SystemObject.h" /** * @brief Time stamper which can be used to add any timestamp to a From 53723b0795f703cc1c2e004df37882d2a6da5424 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Wed, 16 Sep 2020 19:38:43 +0200 Subject: [PATCH 043/101] include fix --- pus/Service9TimeManagement.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pus/Service9TimeManagement.h b/pus/Service9TimeManagement.h index 4ad6be6e..9eed12ca 100644 --- a/pus/Service9TimeManagement.h +++ b/pus/Service9TimeManagement.h @@ -1,7 +1,7 @@ #ifndef FSFW_PUS_SERVICE9TIMEMANAGEMENT_H_ #define FSFW_PUS_SERVICE9TIMEMANAGEMENT_H_ -#include +#include "../tmtcservices/PusServiceBase.h" class Service9TimeManagement: public PusServiceBase { public: From 0f0ddfc37553fa2b922696ba373c2450d7cbb45d Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 18 Sep 2020 12:27:40 +0200 Subject: [PATCH 044/101] stopwatch update --- osal/linux/Clock.cpp | 27 +++++++++------------------ timemanager/Clock.h | 3 +-- timemanager/Stopwatch.cpp | 15 +++++++++------ timemanager/Stopwatch.h | 13 ++++++------- 4 files changed, 25 insertions(+), 33 deletions(-) diff --git a/osal/linux/Clock.cpp b/osal/linux/Clock.cpp index 5f764a6f..b3b09923 100644 --- a/osal/linux/Clock.cpp +++ b/osal/linux/Clock.cpp @@ -75,24 +75,15 @@ timeval Clock::getUptime() { } ReturnValue_t Clock::getUptime(timeval* uptime) { - //TODO This is not posix compatible and delivers only seconds precision - struct sysinfo sysInfo; - int result = sysinfo(&sysInfo); - if(result != 0){ - return HasReturnvaluesIF::RETURN_FAILED; - } - uptime->tv_sec = sysInfo.uptime; - uptime->tv_usec = 0; - - - //Linux specific file read but more precise -// double uptimeSeconds; -// if(std::ifstream("/proc/uptime",std::ios::in) >> uptimeSeconds){ -// uptime->tv_sec = uptimeSeconds; -// uptime->tv_usec = uptimeSeconds *(double) 1e6 - (uptime->tv_sec *1e6); -// } - - return HasReturnvaluesIF::RETURN_OK; + //TODO This is not posix compatible and delivers only seconds precision + // is the OS not called Linux? + //Linux specific file read but more precise + double uptimeSeconds; + if(std::ifstream("/proc/uptime",std::ios::in) >> uptimeSeconds){ + uptime->tv_sec = uptimeSeconds; + uptime->tv_usec = uptimeSeconds *(double) 1e6 - (uptime->tv_sec *1e6); + } + return HasReturnvaluesIF::RETURN_OK; } ReturnValue_t Clock::getUptime(uint32_t* uptimeMs) { diff --git a/timemanager/Clock.h b/timemanager/Clock.h index 6f6a97da..acb68e2e 100644 --- a/timemanager/Clock.h +++ b/timemanager/Clock.h @@ -9,8 +9,7 @@ #include //! Don't use these for time points, type is not large enough for UNIX epoch. -typedef uint32_t dur_millis_t; -typedef double dur_seconds_t; +using dur_millis_t = uint32_t; class Clock { public: diff --git a/timemanager/Stopwatch.cpp b/timemanager/Stopwatch.cpp index 00373bd7..2cd31969 100644 --- a/timemanager/Stopwatch.cpp +++ b/timemanager/Stopwatch.cpp @@ -1,4 +1,4 @@ -#include "Stopwatch.h" +#include "../timemanager/Stopwatch.h" #include "../serviceinterface/ServiceInterfaceStream.h" #include @@ -6,19 +6,22 @@ Stopwatch::Stopwatch(bool displayOnDestruction, StopwatchDisplayMode displayMode): displayOnDestruction( displayOnDestruction), displayMode(displayMode) { // Measures start time on initialization. - Clock::getClock_timeval(&startTime); + Clock::getUptime(&startTime); } void Stopwatch::start() { - Clock::getClock_timeval(&startTime); + Clock::getUptime(&startTime); } -dur_millis_t Stopwatch::stop() { +dur_millis_t Stopwatch::stop(bool display) { stopInternal(); + if(display) { + this->display(); + } return elapsedTime.tv_sec * 1000 + elapsedTime.tv_usec / 1000; } -dur_seconds_t Stopwatch::stopSeconds() { +double Stopwatch::stopSeconds() { stopInternal(); return timevalOperations::toDouble(elapsedTime); } @@ -52,6 +55,6 @@ StopwatchDisplayMode Stopwatch::getDisplayMode() const { void Stopwatch::stopInternal() { timeval endTime; - Clock::getClock_timeval(&endTime); + Clock::getUptime(&endTime); elapsedTime = endTime - startTime; } diff --git a/timemanager/Stopwatch.h b/timemanager/Stopwatch.h index f216b7e1..ea72c66e 100644 --- a/timemanager/Stopwatch.h +++ b/timemanager/Stopwatch.h @@ -1,5 +1,6 @@ -#ifndef FRAMEWORK_TIMEMANAGER_STOPWATCH_H_ -#define FRAMEWORK_TIMEMANAGER_STOPWATCH_H_ +#ifndef FSFW_TIMEMANAGER_STOPWATCH_H_ +#define FSFW_TIMEMANAGER_STOPWATCH_H_ + #include "Clock.h" enum class StopwatchDisplayMode { @@ -40,12 +41,12 @@ public: * Calculates the elapsed time since start and returns it * @return elapsed time in milliseconds (rounded) */ - dur_millis_t stop(); + dur_millis_t stop(bool display = false); /** * Calculates the elapsed time since start and returns it * @return elapsed time in seconds (double precision) */ - dur_seconds_t stopSeconds(); + double stopSeconds(); /** * Displays the elapsed times on the osstream, depending on internal display @@ -66,6 +67,4 @@ private: }; - - -#endif /* FRAMEWORK_TIMEMANAGER_STOPWATCH_H_ */ +#endif /* FSFW_TIMEMANAGER_STOPWATCH_H_ */ From ad8c6f3528a27dcc1153264e9e1fb7fd8d687c04 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 18 Sep 2020 12:58:38 +0200 Subject: [PATCH 045/101] commented out code added back --- osal/linux/Clock.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/osal/linux/Clock.cpp b/osal/linux/Clock.cpp index b3b09923..b14f2a97 100644 --- a/osal/linux/Clock.cpp +++ b/osal/linux/Clock.cpp @@ -83,6 +83,16 @@ ReturnValue_t Clock::getUptime(timeval* uptime) { uptime->tv_sec = uptimeSeconds; uptime->tv_usec = uptimeSeconds *(double) 1e6 - (uptime->tv_sec *1e6); } + + //TODO This is not posix compatible and delivers only seconds precision + // I suggest this is moved into another clock function which will + // deliver second precision later. +// struct sysinfo sysInfo; +// int result = sysinfo(&sysInfo); +// if(result != 0){ +// return HasReturnvaluesIF::RETURN_FAILED; +// } +// return sysInfo.uptime; return HasReturnvaluesIF::RETURN_OK; } From 56ff2aef26209d7c5db76ab2794df4517b0ca35d Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 18 Sep 2020 13:03:48 +0200 Subject: [PATCH 046/101] include replacement --- timemanager/Stopwatch.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/timemanager/Stopwatch.cpp b/timemanager/Stopwatch.cpp index 2cd31969..302e2ac0 100644 --- a/timemanager/Stopwatch.cpp +++ b/timemanager/Stopwatch.cpp @@ -1,4 +1,4 @@ -#include "../timemanager/Stopwatch.h" +#include "Stopwatch.h" #include "../serviceinterface/ServiceInterfaceStream.h" #include From 386f3475741bd07af46a313b78dd77882a697f76 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 18 Sep 2020 13:15:14 +0200 Subject: [PATCH 047/101] renormalized files --- contrib/sgp4/sgp4unit.cpp | 4180 ++++++++++----------- contrib/sgp4/sgp4unit.h | 234 +- globalfunctions/timevalOperations.cpp | 198 +- osal/FreeRTOS/BinSemaphUsingTask.cpp | 190 +- osal/FreeRTOS/BinSemaphUsingTask.h | 152 +- osal/FreeRTOS/BinarySemaphore.cpp | 216 +- osal/FreeRTOS/BinarySemaphore.h | 214 +- osal/FreeRTOS/CountingSemaphUsingTask.cpp | 228 +- osal/FreeRTOS/CountingSemaphUsingTask.h | 204 +- osal/FreeRTOS/CountingSemaphore.cpp | 86 +- osal/FreeRTOS/CountingSemaphore.h | 68 +- osal/FreeRTOS/SemaphoreFactory.cpp | 118 +- osal/FreeRTOS/TaskManagement.cpp | 48 +- osal/FreeRTOS/TaskManagement.h | 128 +- osal/linux/BinarySemaphore.cpp | 298 +- osal/linux/BinarySemaphore.h | 162 +- osal/linux/CountingSemaphore.cpp | 108 +- osal/linux/CountingSemaphore.h | 74 +- osal/linux/SemaphoreFactory.cpp | 66 +- serialize/SerialBufferAdapter.cpp | 258 +- serialize/SerialBufferAdapter.h | 156 +- tasks/SemaphoreFactory.h | 100 +- tasks/SemaphoreIF.h | 136 +- 23 files changed, 3811 insertions(+), 3811 deletions(-) diff --git a/contrib/sgp4/sgp4unit.cpp b/contrib/sgp4/sgp4unit.cpp index 24d63aa9..b707a7a2 100644 --- a/contrib/sgp4/sgp4unit.cpp +++ b/contrib/sgp4/sgp4unit.cpp @@ -1,2090 +1,2090 @@ -/* ---------------------------------------------------------------- -* -* sgp4unit.cpp -* -* this file contains the sgp4 procedures for analytical propagation -* of a satellite. the code was originally released in the 1980 and 1986 -* spacetrack papers. a detailed discussion of the theory and history -* may be found in the 2006 aiaa paper by vallado, crawford, hujsak, -* and kelso. -* -* companion code for -* fundamentals of astrodynamics and applications -* 2007 -* by david vallado -* -* (w) 719-573-2600, email dvallado@agi.com -* -* current : -* 16 nov 07 david vallado -* misc fixes for better compliance -* changes : -* 20 apr 07 david vallado -* misc fixes for constants -* 11 aug 06 david vallado -* chg lyddane choice back to strn3, constants, misc doc -* 15 dec 05 david vallado -* misc fixes -* 26 jul 05 david vallado -* fixes for paper -* note that each fix is preceded by a -* comment with "sgp4fix" and an explanation of -* what was changed -* 10 aug 04 david vallado -* 2nd printing baseline working -* 14 may 01 david vallado -* 2nd edition baseline -* 80 norad -* original baseline -* ---------------------------------------------------------------- */ - -#include "sgp4unit.h" - -const char help = 'n'; -FILE *dbgfile; - -#define pi 3.14159265358979323846 - - -/* ----------- local functions - only ever used internally by sgp4 ---------- */ -static void dpper - ( - double e3, double ee2, double peo, double pgho, double pho, - double pinco, double plo, double se2, double se3, double sgh2, - double sgh3, double sgh4, double sh2, double sh3, double si2, - double si3, double sl2, double sl3, double sl4, double t, - double xgh2, double xgh3, double xgh4, double xh2, double xh3, - double xi2, double xi3, double xl2, double xl3, double xl4, - double zmol, double zmos, double inclo, - char init, - double& ep, double& inclp, double& nodep, double& argpp, double& mp - ); - -static void dscom - ( - double epoch, double ep, double argpp, double tc, double inclp, - double nodep, double np, - double& snodm, double& cnodm, double& sinim, double& cosim, double& sinomm, - double& cosomm,double& day, double& e3, double& ee2, double& em, - double& emsq, double& gam, double& peo, double& pgho, double& pho, - double& pinco, double& plo, double& rtemsq, double& se2, double& se3, - double& sgh2, double& sgh3, double& sgh4, double& sh2, double& sh3, - double& si2, double& si3, double& sl2, double& sl3, double& sl4, - double& s1, double& s2, double& s3, double& s4, double& s5, - double& s6, double& s7, double& ss1, double& ss2, double& ss3, - double& ss4, double& ss5, double& ss6, double& ss7, double& sz1, - double& sz2, double& sz3, double& sz11, double& sz12, double& sz13, - double& sz21, double& sz22, double& sz23, double& sz31, double& sz32, - double& sz33, double& xgh2, double& xgh3, double& xgh4, double& xh2, - double& xh3, double& xi2, double& xi3, double& xl2, double& xl3, - double& xl4, double& nm, double& z1, double& z2, double& z3, - double& z11, double& z12, double& z13, double& z21, double& z22, - double& z23, double& z31, double& z32, double& z33, double& zmol, - double& zmos - ); - -static void dsinit - ( - gravconsttype whichconst, - double cosim, double emsq, double argpo, double s1, double s2, - double s3, double s4, double s5, double sinim, double ss1, - double ss2, double ss3, double ss4, double ss5, double sz1, - double sz3, double sz11, double sz13, double sz21, double sz23, - double sz31, double sz33, double t, double tc, double gsto, - double mo, double mdot, double no, double nodeo, double nodedot, - double xpidot, double z1, double z3, double z11, double z13, - double z21, double z23, double z31, double z33, double ecco, - double eccsq, double& em, double& argpm, double& inclm, double& mm, - double& nm, double& nodem, - int& irez, - double& atime, double& d2201, double& d2211, double& d3210, double& d3222, - double& d4410, double& d4422, double& d5220, double& d5232, double& d5421, - double& d5433, double& dedt, double& didt, double& dmdt, double& dndt, - double& dnodt, double& domdt, double& del1, double& del2, double& del3, - double& xfact, double& xlamo, double& xli, double& xni - ); - -static void dspace - ( - int irez, - double d2201, double d2211, double d3210, double d3222, double d4410, - double d4422, double d5220, double d5232, double d5421, double d5433, - double dedt, double del1, double del2, double del3, double didt, - double dmdt, double dnodt, double domdt, double argpo, double argpdot, - double t, double tc, double gsto, double xfact, double xlamo, - double no, - double& atime, double& em, double& argpm, double& inclm, double& xli, - double& mm, double& xni, double& nodem, double& dndt, double& nm - ); - -static void initl - ( - int satn, gravconsttype whichconst, - double ecco, double epoch, double inclo, double& no, - char& method, - double& ainv, double& ao, double& con41, double& con42, double& cosio, - double& cosio2,double& eccsq, double& omeosq, double& posq, - double& rp, double& rteosq,double& sinio , double& gsto - ); - -/* ----------------------------------------------------------------------------- -* -* procedure dpper -* -* this procedure provides deep space long period periodic contributions -* to the mean elements. by design, these periodics are zero at epoch. -* this used to be dscom which included initialization, but it's really a -* recurring function. -* -* author : david vallado 719-573-2600 28 jun 2005 -* -* inputs : -* e3 - -* ee2 - -* peo - -* pgho - -* pho - -* pinco - -* plo - -* se2 , se3 , sgh2, sgh3, sgh4, sh2, sh3, si2, si3, sl2, sl3, sl4 - -* t - -* xh2, xh3, xi2, xi3, xl2, xl3, xl4 - -* zmol - -* zmos - -* ep - eccentricity 0.0 - 1.0 -* inclo - inclination - needed for lyddane modification -* nodep - right ascension of ascending node -* argpp - argument of perigee -* mp - mean anomaly -* -* outputs : -* ep - eccentricity 0.0 - 1.0 -* inclp - inclination -* nodep - right ascension of ascending node -* argpp - argument of perigee -* mp - mean anomaly -* -* locals : -* alfdp - -* betdp - -* cosip , sinip , cosop , sinop , -* dalf - -* dbet - -* dls - -* f2, f3 - -* pe - -* pgh - -* ph - -* pinc - -* pl - -* sel , ses , sghl , sghs , shl , shs , sil , sinzf , sis , -* sll , sls -* xls - -* xnoh - -* zf - -* zm - -* -* coupling : -* none. -* -* references : -* hoots, roehrich, norad spacetrack report #3 1980 -* hoots, norad spacetrack report #6 1986 -* hoots, schumacher and glover 2004 -* vallado, crawford, hujsak, kelso 2006 - ----------------------------------------------------------------------------*/ - -static void dpper - ( - double e3, double ee2, double peo, double pgho, double pho, - double pinco, double plo, double se2, double se3, double sgh2, - double sgh3, double sgh4, double sh2, double sh3, double si2, - double si3, double sl2, double sl3, double sl4, double t, - double xgh2, double xgh3, double xgh4, double xh2, double xh3, - double xi2, double xi3, double xl2, double xl3, double xl4, - double zmol, double zmos, double inclo, - char init, - double& ep, double& inclp, double& nodep, double& argpp, double& mp - ) -{ - /* --------------------- local variables ------------------------ */ - const double twopi = 2.0 * pi; - double alfdp, betdp, cosip, cosop, dalf, dbet, dls, - f2, f3, pe, pgh, ph, pinc, pl , - sel, ses, sghl, sghs, shll, shs, sil, - sinip, sinop, sinzf, sis, sll, sls, xls, - xnoh, zf, zm, zel, zes, znl, zns; - - /* ---------------------- constants ----------------------------- */ - zns = 1.19459e-5; - zes = 0.01675; - znl = 1.5835218e-4; - zel = 0.05490; - - /* --------------- calculate time varying periodics ----------- */ - zm = zmos + zns * t; - // be sure that the initial call has time set to zero - if (init == 'y') - zm = zmos; - zf = zm + 2.0 * zes * sin(zm); - sinzf = sin(zf); - f2 = 0.5 * sinzf * sinzf - 0.25; - f3 = -0.5 * sinzf * cos(zf); - ses = se2* f2 + se3 * f3; - sis = si2 * f2 + si3 * f3; - sls = sl2 * f2 + sl3 * f3 + sl4 * sinzf; - sghs = sgh2 * f2 + sgh3 * f3 + sgh4 * sinzf; - shs = sh2 * f2 + sh3 * f3; - zm = zmol + znl * t; - if (init == 'y') - zm = zmol; - zf = zm + 2.0 * zel * sin(zm); - sinzf = sin(zf); - f2 = 0.5 * sinzf * sinzf - 0.25; - f3 = -0.5 * sinzf * cos(zf); - sel = ee2 * f2 + e3 * f3; - sil = xi2 * f2 + xi3 * f3; - sll = xl2 * f2 + xl3 * f3 + xl4 * sinzf; - sghl = xgh2 * f2 + xgh3 * f3 + xgh4 * sinzf; - shll = xh2 * f2 + xh3 * f3; - pe = ses + sel; - pinc = sis + sil; - pl = sls + sll; - pgh = sghs + sghl; - ph = shs + shll; - - if (init == 'n') - { - pe = pe - peo; - pinc = pinc - pinco; - pl = pl - plo; - pgh = pgh - pgho; - ph = ph - pho; - inclp = inclp + pinc; - ep = ep + pe; - sinip = sin(inclp); - cosip = cos(inclp); - - /* ----------------- apply periodics directly ------------ */ - // sgp4fix for lyddane choice - // strn3 used original inclination - this is technically feasible - // gsfc used perturbed inclination - also technically feasible - // probably best to readjust the 0.2 limit value and limit discontinuity - // 0.2 rad = 11.45916 deg - // use next line for original strn3 approach and original inclination - // if (inclo >= 0.2) - // use next line for gsfc version and perturbed inclination - if (inclp >= 0.2) - { - ph = ph / sinip; - pgh = pgh - cosip * ph; - argpp = argpp + pgh; - nodep = nodep + ph; - mp = mp + pl; - } - else - { - /* ---- apply periodics with lyddane modification ---- */ - sinop = sin(nodep); - cosop = cos(nodep); - alfdp = sinip * sinop; - betdp = sinip * cosop; - dalf = ph * cosop + pinc * cosip * sinop; - dbet = -ph * sinop + pinc * cosip * cosop; - alfdp = alfdp + dalf; - betdp = betdp + dbet; - nodep = fmod(nodep, twopi); - // sgp4fix for afspc written intrinsic functions - // nodep used without a trigonometric function ahead - if (nodep < 0.0) - nodep = nodep + twopi; - xls = mp + argpp + cosip * nodep; - dls = pl + pgh - pinc * nodep * sinip; - xls = xls + dls; - xnoh = nodep; - nodep = atan2(alfdp, betdp); - // sgp4fix for afspc written intrinsic functions - // nodep used without a trigonometric function ahead - if (nodep < 0.0) - nodep = nodep + twopi; - if (fabs(xnoh - nodep) > pi){ - if (nodep < xnoh) - nodep = nodep + twopi; - else - nodep = nodep - twopi; - } - mp = mp + pl; - argpp = xls - mp - cosip * nodep; - } - } // if init == 'n' - -//#include "debug1.cpp" -} // end dpper - -/*----------------------------------------------------------------------------- -* -* procedure dscom -* -* this procedure provides deep space common items used by both the secular -* and periodics subroutines. input is provided as shown. this routine -* used to be called dpper, but the functions inside weren't well organized. -* -* author : david vallado 719-573-2600 28 jun 2005 -* -* inputs : -* epoch - -* ep - eccentricity -* argpp - argument of perigee -* tc - -* inclp - inclination -* nodep - right ascension of ascending node -* np - mean motion -* -* outputs : -* sinim , cosim , sinomm , cosomm , snodm , cnodm -* day - -* e3 - -* ee2 - -* em - eccentricity -* emsq - eccentricity squared -* gam - -* peo - -* pgho - -* pho - -* pinco - -* plo - -* rtemsq - -* se2, se3 - -* sgh2, sgh3, sgh4 - -* sh2, sh3, si2, si3, sl2, sl3, sl4 - -* s1, s2, s3, s4, s5, s6, s7 - -* ss1, ss2, ss3, ss4, ss5, ss6, ss7, sz1, sz2, sz3 - -* sz11, sz12, sz13, sz21, sz22, sz23, sz31, sz32, sz33 - -* xgh2, xgh3, xgh4, xh2, xh3, xi2, xi3, xl2, xl3, xl4 - -* nm - mean motion -* z1, z2, z3, z11, z12, z13, z21, z22, z23, z31, z32, z33 - -* zmol - -* zmos - -* -* locals : -* a1, a2, a3, a4, a5, a6, a7, a8, a9, a10 - -* betasq - -* cc - -* ctem, stem - -* x1, x2, x3, x4, x5, x6, x7, x8 - -* xnodce - -* xnoi - -* zcosg , zsing , zcosgl , zsingl , zcosh , zsinh , zcoshl , zsinhl , -* zcosi , zsini , zcosil , zsinil , -* zx - -* zy - -* -* coupling : -* none. -* -* references : -* hoots, roehrich, norad spacetrack report #3 1980 -* hoots, norad spacetrack report #6 1986 -* hoots, schumacher and glover 2004 -* vallado, crawford, hujsak, kelso 2006 - ----------------------------------------------------------------------------*/ - -static void dscom - ( - double epoch, double ep, double argpp, double tc, double inclp, - double nodep, double np, - double& snodm, double& cnodm, double& sinim, double& cosim, double& sinomm, - double& cosomm,double& day, double& e3, double& ee2, double& em, - double& emsq, double& gam, double& peo, double& pgho, double& pho, - double& pinco, double& plo, double& rtemsq, double& se2, double& se3, - double& sgh2, double& sgh3, double& sgh4, double& sh2, double& sh3, - double& si2, double& si3, double& sl2, double& sl3, double& sl4, - double& s1, double& s2, double& s3, double& s4, double& s5, - double& s6, double& s7, double& ss1, double& ss2, double& ss3, - double& ss4, double& ss5, double& ss6, double& ss7, double& sz1, - double& sz2, double& sz3, double& sz11, double& sz12, double& sz13, - double& sz21, double& sz22, double& sz23, double& sz31, double& sz32, - double& sz33, double& xgh2, double& xgh3, double& xgh4, double& xh2, - double& xh3, double& xi2, double& xi3, double& xl2, double& xl3, - double& xl4, double& nm, double& z1, double& z2, double& z3, - double& z11, double& z12, double& z13, double& z21, double& z22, - double& z23, double& z31, double& z32, double& z33, double& zmol, - double& zmos - ) -{ - /* -------------------------- constants ------------------------- */ - const double zes = 0.01675; - const double zel = 0.05490; - const double c1ss = 2.9864797e-6; - const double c1l = 4.7968065e-7; - const double zsinis = 0.39785416; - const double zcosis = 0.91744867; - const double zcosgs = 0.1945905; - const double zsings = -0.98088458; - const double twopi = 2.0 * pi; - - /* --------------------- local variables ------------------------ */ - int lsflg; - double a1 , a2 , a3 , a4 , a5 , a6 , a7 , - a8 , a9 , a10 , betasq, cc , ctem , stem , - x1 , x2 , x3 , x4 , x5 , x6 , x7 , - x8 , xnodce, xnoi , zcosg , zcosgl, zcosh , zcoshl, - zcosi , zcosil, zsing , zsingl, zsinh , zsinhl, zsini , - zsinil, zx , zy; - - nm = np; - em = ep; - snodm = sin(nodep); - cnodm = cos(nodep); - sinomm = sin(argpp); - cosomm = cos(argpp); - sinim = sin(inclp); - cosim = cos(inclp); - emsq = em * em; - betasq = 1.0 - emsq; - rtemsq = sqrt(betasq); - - /* ----------------- initialize lunar solar terms --------------- */ - peo = 0.0; - pinco = 0.0; - plo = 0.0; - pgho = 0.0; - pho = 0.0; - day = epoch + 18261.5 + tc / 1440.0; - xnodce = fmod(4.5236020 - 9.2422029e-4 * day, twopi); - stem = sin(xnodce); - ctem = cos(xnodce); - zcosil = 0.91375164 - 0.03568096 * ctem; - zsinil = sqrt(1.0 - zcosil * zcosil); - zsinhl = 0.089683511 * stem / zsinil; - zcoshl = sqrt(1.0 - zsinhl * zsinhl); - gam = 5.8351514 + 0.0019443680 * day; - zx = 0.39785416 * stem / zsinil; - zy = zcoshl * ctem + 0.91744867 * zsinhl * stem; - zx = atan2(zx, zy); - zx = gam + zx - xnodce; - zcosgl = cos(zx); - zsingl = sin(zx); - - /* ------------------------- do solar terms --------------------- */ - zcosg = zcosgs; - zsing = zsings; - zcosi = zcosis; - zsini = zsinis; - zcosh = cnodm; - zsinh = snodm; - cc = c1ss; - xnoi = 1.0 / nm; - - for (lsflg = 1; lsflg <= 2; lsflg++) - { - a1 = zcosg * zcosh + zsing * zcosi * zsinh; - a3 = -zsing * zcosh + zcosg * zcosi * zsinh; - a7 = -zcosg * zsinh + zsing * zcosi * zcosh; - a8 = zsing * zsini; - a9 = zsing * zsinh + zcosg * zcosi * zcosh; - a10 = zcosg * zsini; - a2 = cosim * a7 + sinim * a8; - a4 = cosim * a9 + sinim * a10; - a5 = -sinim * a7 + cosim * a8; - a6 = -sinim * a9 + cosim * a10; - - x1 = a1 * cosomm + a2 * sinomm; - x2 = a3 * cosomm + a4 * sinomm; - x3 = -a1 * sinomm + a2 * cosomm; - x4 = -a3 * sinomm + a4 * cosomm; - x5 = a5 * sinomm; - x6 = a6 * sinomm; - x7 = a5 * cosomm; - x8 = a6 * cosomm; - - z31 = 12.0 * x1 * x1 - 3.0 * x3 * x3; - z32 = 24.0 * x1 * x2 - 6.0 * x3 * x4; - z33 = 12.0 * x2 * x2 - 3.0 * x4 * x4; - z1 = 3.0 * (a1 * a1 + a2 * a2) + z31 * emsq; - z2 = 6.0 * (a1 * a3 + a2 * a4) + z32 * emsq; - z3 = 3.0 * (a3 * a3 + a4 * a4) + z33 * emsq; - z11 = -6.0 * a1 * a5 + emsq * (-24.0 * x1 * x7-6.0 * x3 * x5); - z12 = -6.0 * (a1 * a6 + a3 * a5) + emsq * - (-24.0 * (x2 * x7 + x1 * x8) - 6.0 * (x3 * x6 + x4 * x5)); - z13 = -6.0 * a3 * a6 + emsq * (-24.0 * x2 * x8 - 6.0 * x4 * x6); - z21 = 6.0 * a2 * a5 + emsq * (24.0 * x1 * x5 - 6.0 * x3 * x7); - z22 = 6.0 * (a4 * a5 + a2 * a6) + emsq * - (24.0 * (x2 * x5 + x1 * x6) - 6.0 * (x4 * x7 + x3 * x8)); - z23 = 6.0 * a4 * a6 + emsq * (24.0 * x2 * x6 - 6.0 * x4 * x8); - z1 = z1 + z1 + betasq * z31; - z2 = z2 + z2 + betasq * z32; - z3 = z3 + z3 + betasq * z33; - s3 = cc * xnoi; - s2 = -0.5 * s3 / rtemsq; - s4 = s3 * rtemsq; - s1 = -15.0 * em * s4; - s5 = x1 * x3 + x2 * x4; - s6 = x2 * x3 + x1 * x4; - s7 = x2 * x4 - x1 * x3; - - /* ----------------------- do lunar terms ------------------- */ - if (lsflg == 1) - { - ss1 = s1; - ss2 = s2; - ss3 = s3; - ss4 = s4; - ss5 = s5; - ss6 = s6; - ss7 = s7; - sz1 = z1; - sz2 = z2; - sz3 = z3; - sz11 = z11; - sz12 = z12; - sz13 = z13; - sz21 = z21; - sz22 = z22; - sz23 = z23; - sz31 = z31; - sz32 = z32; - sz33 = z33; - zcosg = zcosgl; - zsing = zsingl; - zcosi = zcosil; - zsini = zsinil; - zcosh = zcoshl * cnodm + zsinhl * snodm; - zsinh = snodm * zcoshl - cnodm * zsinhl; - cc = c1l; - } - } - - zmol = fmod(4.7199672 + 0.22997150 * day - gam, twopi); - zmos = fmod(6.2565837 + 0.017201977 * day, twopi); - - /* ------------------------ do solar terms ---------------------- */ - se2 = 2.0 * ss1 * ss6; - se3 = 2.0 * ss1 * ss7; - si2 = 2.0 * ss2 * sz12; - si3 = 2.0 * ss2 * (sz13 - sz11); - sl2 = -2.0 * ss3 * sz2; - sl3 = -2.0 * ss3 * (sz3 - sz1); - sl4 = -2.0 * ss3 * (-21.0 - 9.0 * emsq) * zes; - sgh2 = 2.0 * ss4 * sz32; - sgh3 = 2.0 * ss4 * (sz33 - sz31); - sgh4 = -18.0 * ss4 * zes; - sh2 = -2.0 * ss2 * sz22; - sh3 = -2.0 * ss2 * (sz23 - sz21); - - /* ------------------------ do lunar terms ---------------------- */ - ee2 = 2.0 * s1 * s6; - e3 = 2.0 * s1 * s7; - xi2 = 2.0 * s2 * z12; - xi3 = 2.0 * s2 * (z13 - z11); - xl2 = -2.0 * s3 * z2; - xl3 = -2.0 * s3 * (z3 - z1); - xl4 = -2.0 * s3 * (-21.0 - 9.0 * emsq) * zel; - xgh2 = 2.0 * s4 * z32; - xgh3 = 2.0 * s4 * (z33 - z31); - xgh4 = -18.0 * s4 * zel; - xh2 = -2.0 * s2 * z22; - xh3 = -2.0 * s2 * (z23 - z21); - -//#include "debug2.cpp" -} // end dscom - -/*----------------------------------------------------------------------------- -* -* procedure dsinit -* -* this procedure provides deep space contributions to mean motion dot due -* to geopotential resonance with half day and one day orbits. -* -* author : david vallado 719-573-2600 28 jun 2005 -* -* inputs : -* cosim, sinim- -* emsq - eccentricity squared -* argpo - argument of perigee -* s1, s2, s3, s4, s5 - -* ss1, ss2, ss3, ss4, ss5 - -* sz1, sz3, sz11, sz13, sz21, sz23, sz31, sz33 - -* t - time -* tc - -* gsto - greenwich sidereal time rad -* mo - mean anomaly -* mdot - mean anomaly dot (rate) -* no - mean motion -* nodeo - right ascension of ascending node -* nodedot - right ascension of ascending node dot (rate) -* xpidot - -* z1, z3, z11, z13, z21, z23, z31, z33 - -* eccm - eccentricity -* argpm - argument of perigee -* inclm - inclination -* mm - mean anomaly -* xn - mean motion -* nodem - right ascension of ascending node -* -* outputs : -* em - eccentricity -* argpm - argument of perigee -* inclm - inclination -* mm - mean anomaly -* nm - mean motion -* nodem - right ascension of ascending node -* irez - flag for resonance 0-none, 1-one day, 2-half day -* atime - -* d2201, d2211, d3210, d3222, d4410, d4422, d5220, d5232, d5421, d5433 - -* dedt - -* didt - -* dmdt - -* dndt - -* dnodt - -* domdt - -* del1, del2, del3 - -* ses , sghl , sghs , sgs , shl , shs , sis , sls -* theta - -* xfact - -* xlamo - -* xli - -* xni -* -* locals : -* ainv2 - -* aonv - -* cosisq - -* eoc - -* f220, f221, f311, f321, f322, f330, f441, f442, f522, f523, f542, f543 - -* g200, g201, g211, g300, g310, g322, g410, g422, g520, g521, g532, g533 - -* sini2 - -* temp - -* temp1 - -* theta - -* xno2 - -* -* coupling : -* getgravconst -* -* references : -* hoots, roehrich, norad spacetrack report #3 1980 -* hoots, norad spacetrack report #6 1986 -* hoots, schumacher and glover 2004 -* vallado, crawford, hujsak, kelso 2006 - ----------------------------------------------------------------------------*/ - -static void dsinit - ( - gravconsttype whichconst, - double cosim, double emsq, double argpo, double s1, double s2, - double s3, double s4, double s5, double sinim, double ss1, - double ss2, double ss3, double ss4, double ss5, double sz1, - double sz3, double sz11, double sz13, double sz21, double sz23, - double sz31, double sz33, double t, double tc, double gsto, - double mo, double mdot, double no, double nodeo, double nodedot, - double xpidot, double z1, double z3, double z11, double z13, - double z21, double z23, double z31, double z33, double ecco, - double eccsq, double& em, double& argpm, double& inclm, double& mm, - double& nm, double& nodem, - int& irez, - double& atime, double& d2201, double& d2211, double& d3210, double& d3222, - double& d4410, double& d4422, double& d5220, double& d5232, double& d5421, - double& d5433, double& dedt, double& didt, double& dmdt, double& dndt, - double& dnodt, double& domdt, double& del1, double& del2, double& del3, - double& xfact, double& xlamo, double& xli, double& xni - ) -{ - /* --------------------- local variables ------------------------ */ - const double twopi = 2.0 * pi; - - double ainv2 , aonv=0.0, cosisq, eoc, f220 , f221 , f311 , - f321 , f322 , f330 , f441 , f442 , f522 , f523 , - f542 , f543 , g200 , g201 , g211 , g300 , g310 , - g322 , g410 , g422 , g520 , g521 , g532 , g533 , - ses , sgs , sghl , sghs , shs , shll , sis , - sini2 , sls , temp , temp1 , theta , xno2 , q22 , - q31 , q33 , root22, root44, root54, rptim , root32, - root52, x2o3 , xke , znl , emo , zns , emsqo, - tumin, mu, radiusearthkm, j2, j3, j4, j3oj2; - - q22 = 1.7891679e-6; - q31 = 2.1460748e-6; - q33 = 2.2123015e-7; - root22 = 1.7891679e-6; - root44 = 7.3636953e-9; - root54 = 2.1765803e-9; - rptim = 4.37526908801129966e-3; // this equates to 7.29211514668855e-5 rad/sec - root32 = 3.7393792e-7; - root52 = 1.1428639e-7; - x2o3 = 2.0 / 3.0; - znl = 1.5835218e-4; - zns = 1.19459e-5; - - // sgp4fix identify constants and allow alternate values - getgravconst( whichconst, tumin, mu, radiusearthkm, xke, j2, j3, j4, j3oj2 ); - - /* -------------------- deep space initialization ------------ */ - irez = 0; - if ((nm < 0.0052359877) && (nm > 0.0034906585)) - irez = 1; - if ((nm >= 8.26e-3) && (nm <= 9.24e-3) && (em >= 0.5)) - irez = 2; - - /* ------------------------ do solar terms ------------------- */ - ses = ss1 * zns * ss5; - sis = ss2 * zns * (sz11 + sz13); - sls = -zns * ss3 * (sz1 + sz3 - 14.0 - 6.0 * emsq); - sghs = ss4 * zns * (sz31 + sz33 - 6.0); - shs = -zns * ss2 * (sz21 + sz23); - // sgp4fix for 180 deg incl - if ((inclm < 5.2359877e-2) || (inclm > pi - 5.2359877e-2)) - shs = 0.0; - if (sinim != 0.0) - shs = shs / sinim; - sgs = sghs - cosim * shs; - - /* ------------------------- do lunar terms ------------------ */ - dedt = ses + s1 * znl * s5; - didt = sis + s2 * znl * (z11 + z13); - dmdt = sls - znl * s3 * (z1 + z3 - 14.0 - 6.0 * emsq); - sghl = s4 * znl * (z31 + z33 - 6.0); - shll = -znl * s2 * (z21 + z23); - // sgp4fix for 180 deg incl - if ((inclm < 5.2359877e-2) || (inclm > pi - 5.2359877e-2)) - shll = 0.0; - domdt = sgs + sghl; - dnodt = shs; - if (sinim != 0.0) - { - domdt = domdt - cosim / sinim * shll; - dnodt = dnodt + shll / sinim; - } - - /* ----------- calculate deep space resonance effects -------- */ - dndt = 0.0; - theta = fmod(gsto + tc * rptim, twopi); - em = em + dedt * t; - inclm = inclm + didt * t; - argpm = argpm + domdt * t; - nodem = nodem + dnodt * t; - mm = mm + dmdt * t; - // sgp4fix for negative inclinations - // the following if statement should be commented out - //if (inclm < 0.0) - // { - // inclm = -inclm; - // argpm = argpm - pi; - // nodem = nodem + pi; - // } - - /* -------------- initialize the resonance terms ------------- */ - if (irez != 0) - { - aonv = pow(nm / xke, x2o3); - - /* ---------- geopotential resonance for 12 hour orbits ------ */ - if (irez == 2) - { - cosisq = cosim * cosim; - emo = em; - em = ecco; - emsqo = emsq; - emsq = eccsq; - eoc = em * emsq; - g201 = -0.306 - (em - 0.64) * 0.440; - - if (em <= 0.65) - { - g211 = 3.616 - 13.2470 * em + 16.2900 * emsq; - g310 = -19.302 + 117.3900 * em - 228.4190 * emsq + 156.5910 * eoc; - g322 = -18.9068 + 109.7927 * em - 214.6334 * emsq + 146.5816 * eoc; - g410 = -41.122 + 242.6940 * em - 471.0940 * emsq + 313.9530 * eoc; - g422 = -146.407 + 841.8800 * em - 1629.014 * emsq + 1083.4350 * eoc; - g520 = -532.114 + 3017.977 * em - 5740.032 * emsq + 3708.2760 * eoc; - } - else - { - g211 = -72.099 + 331.819 * em - 508.738 * emsq + 266.724 * eoc; - g310 = -346.844 + 1582.851 * em - 2415.925 * emsq + 1246.113 * eoc; - g322 = -342.585 + 1554.908 * em - 2366.899 * emsq + 1215.972 * eoc; - g410 = -1052.797 + 4758.686 * em - 7193.992 * emsq + 3651.957 * eoc; - g422 = -3581.690 + 16178.110 * em - 24462.770 * emsq + 12422.520 * eoc; - if (em > 0.715) - g520 =-5149.66 + 29936.92 * em - 54087.36 * emsq + 31324.56 * eoc; - else - g520 = 1464.74 - 4664.75 * em + 3763.64 * emsq; - } - if (em < 0.7) - { - g533 = -919.22770 + 4988.6100 * em - 9064.7700 * emsq + 5542.21 * eoc; - g521 = -822.71072 + 4568.6173 * em - 8491.4146 * emsq + 5337.524 * eoc; - g532 = -853.66600 + 4690.2500 * em - 8624.7700 * emsq + 5341.4 * eoc; - } - else - { - g533 =-37995.780 + 161616.52 * em - 229838.20 * emsq + 109377.94 * eoc; - g521 =-51752.104 + 218913.95 * em - 309468.16 * emsq + 146349.42 * eoc; - g532 =-40023.880 + 170470.89 * em - 242699.48 * emsq + 115605.82 * eoc; - } - - sini2= sinim * sinim; - f220 = 0.75 * (1.0 + 2.0 * cosim+cosisq); - f221 = 1.5 * sini2; - f321 = 1.875 * sinim * (1.0 - 2.0 * cosim - 3.0 * cosisq); - f322 = -1.875 * sinim * (1.0 + 2.0 * cosim - 3.0 * cosisq); - f441 = 35.0 * sini2 * f220; - f442 = 39.3750 * sini2 * sini2; - f522 = 9.84375 * sinim * (sini2 * (1.0 - 2.0 * cosim- 5.0 * cosisq) + - 0.33333333 * (-2.0 + 4.0 * cosim + 6.0 * cosisq) ); - f523 = sinim * (4.92187512 * sini2 * (-2.0 - 4.0 * cosim + - 10.0 * cosisq) + 6.56250012 * (1.0+2.0 * cosim - 3.0 * cosisq)); - f542 = 29.53125 * sinim * (2.0 - 8.0 * cosim+cosisq * - (-12.0 + 8.0 * cosim + 10.0 * cosisq)); - f543 = 29.53125 * sinim * (-2.0 - 8.0 * cosim+cosisq * - (12.0 + 8.0 * cosim - 10.0 * cosisq)); - xno2 = nm * nm; - ainv2 = aonv * aonv; - temp1 = 3.0 * xno2 * ainv2; - temp = temp1 * root22; - d2201 = temp * f220 * g201; - d2211 = temp * f221 * g211; - temp1 = temp1 * aonv; - temp = temp1 * root32; - d3210 = temp * f321 * g310; - d3222 = temp * f322 * g322; - temp1 = temp1 * aonv; - temp = 2.0 * temp1 * root44; - d4410 = temp * f441 * g410; - d4422 = temp * f442 * g422; - temp1 = temp1 * aonv; - temp = temp1 * root52; - d5220 = temp * f522 * g520; - d5232 = temp * f523 * g532; - temp = 2.0 * temp1 * root54; - d5421 = temp * f542 * g521; - d5433 = temp * f543 * g533; - xlamo = fmod(mo + nodeo + nodeo-theta - theta, twopi); - xfact = mdot + dmdt + 2.0 * (nodedot + dnodt - rptim) - no; - em = emo; - emsq = emsqo; - } - - /* ---------------- synchronous resonance terms -------------- */ - if (irez == 1) - { - g200 = 1.0 + emsq * (-2.5 + 0.8125 * emsq); - g310 = 1.0 + 2.0 * emsq; - g300 = 1.0 + emsq * (-6.0 + 6.60937 * emsq); - f220 = 0.75 * (1.0 + cosim) * (1.0 + cosim); - f311 = 0.9375 * sinim * sinim * (1.0 + 3.0 * cosim) - 0.75 * (1.0 + cosim); - f330 = 1.0 + cosim; - f330 = 1.875 * f330 * f330 * f330; - del1 = 3.0 * nm * nm * aonv * aonv; - del2 = 2.0 * del1 * f220 * g200 * q22; - del3 = 3.0 * del1 * f330 * g300 * q33 * aonv; - del1 = del1 * f311 * g310 * q31 * aonv; - xlamo = fmod(mo + nodeo + argpo - theta, twopi); - xfact = mdot + xpidot - rptim + dmdt + domdt + dnodt - no; - } - - /* ------------ for sgp4, initialize the integrator ---------- */ - xli = xlamo; - xni = no; - atime = 0.0; - nm = no + dndt; - } - -//#include "debug3.cpp" -} // end dsinit - -/*----------------------------------------------------------------------------- -* -* procedure dspace -* -* this procedure provides deep space contributions to mean elements for -* perturbing third body. these effects have been averaged over one -* revolution of the sun and moon. for earth resonance effects, the -* effects have been averaged over no revolutions of the satellite. -* (mean motion) -* -* author : david vallado 719-573-2600 28 jun 2005 -* -* inputs : -* d2201, d2211, d3210, d3222, d4410, d4422, d5220, d5232, d5421, d5433 - -* dedt - -* del1, del2, del3 - -* didt - -* dmdt - -* dnodt - -* domdt - -* irez - flag for resonance 0-none, 1-one day, 2-half day -* argpo - argument of perigee -* argpdot - argument of perigee dot (rate) -* t - time -* tc - -* gsto - gst -* xfact - -* xlamo - -* no - mean motion -* atime - -* em - eccentricity -* ft - -* argpm - argument of perigee -* inclm - inclination -* xli - -* mm - mean anomaly -* xni - mean motion -* nodem - right ascension of ascending node -* -* outputs : -* atime - -* em - eccentricity -* argpm - argument of perigee -* inclm - inclination -* xli - -* mm - mean anomaly -* xni - -* nodem - right ascension of ascending node -* dndt - -* nm - mean motion -* -* locals : -* delt - -* ft - -* theta - -* x2li - -* x2omi - -* xl - -* xldot - -* xnddt - -* xndt - -* xomi - -* -* coupling : -* none - -* -* references : -* hoots, roehrich, norad spacetrack report #3 1980 -* hoots, norad spacetrack report #6 1986 -* hoots, schumacher and glover 2004 -* vallado, crawford, hujsak, kelso 2006 - ----------------------------------------------------------------------------*/ - -static void dspace - ( - int irez, - double d2201, double d2211, double d3210, double d3222, double d4410, - double d4422, double d5220, double d5232, double d5421, double d5433, - double dedt, double del1, double del2, double del3, double didt, - double dmdt, double dnodt, double domdt, double argpo, double argpdot, - double t, double tc, double gsto, double xfact, double xlamo, - double no, - double& atime, double& em, double& argpm, double& inclm, double& xli, - double& mm, double& xni, double& nodem, double& dndt, double& nm - ) -{ - const double twopi = 2.0 * pi; - int iretn , iret; - double delt, ft, theta, x2li, x2omi, xl, xldot , xnddt, xndt, xomi, g22, g32, - g44, g52, g54, fasx2, fasx4, fasx6, rptim , step2, stepn , stepp; - - ft = 0.0; - fasx2 = 0.13130908; - fasx4 = 2.8843198; - fasx6 = 0.37448087; - g22 = 5.7686396; - g32 = 0.95240898; - g44 = 1.8014998; - g52 = 1.0508330; - g54 = 4.4108898; - rptim = 4.37526908801129966e-3; // this equates to 7.29211514668855e-5 rad/sec - stepp = 720.0; - stepn = -720.0; - step2 = 259200.0; - - /* ----------- calculate deep space resonance effects ----------- */ - dndt = 0.0; - theta = fmod(gsto + tc * rptim, twopi); - em = em + dedt * t; - - inclm = inclm + didt * t; - argpm = argpm + domdt * t; - nodem = nodem + dnodt * t; - mm = mm + dmdt * t; - - // sgp4fix for negative inclinations - // the following if statement should be commented out - // if (inclm < 0.0) - // { - // inclm = -inclm; - // argpm = argpm - pi; - // nodem = nodem + pi; - // } - - /* - update resonances : numerical (euler-maclaurin) integration - */ - /* ------------------------- epoch restart ---------------------- */ - // sgp4fix for propagator problems - // the following integration works for negative time steps and periods - // the specific changes are unknown because the original code was so convoluted - - ft = 0.0; - atime = 0.0; - if (irez != 0) - { - if ((atime == 0.0) || ((t >= 0.0) && (atime < 0.0)) || - ((t < 0.0) && (atime >= 0.0))) - { - if (t >= 0.0) - delt = stepp; - else - delt = stepn; - atime = 0.0; - xni = no; - xli = xlamo; - } - iretn = 381; // added for do loop - iret = 0; // added for loop - while (iretn == 381) - { - if ((fabs(t) < fabs(atime)) || (iret == 351)) - { - if (t >= 0.0) - delt = stepn; - else - delt = stepp; - iret = 351; - iretn = 381; - } - else - { - if (t > 0.0) // error if prev if has atime:=0.0 and t:=0.0 (ge) - delt = stepp; - else - delt = stepn; - if (fabs(t - atime) >= stepp) - { - iret = 0; - iretn = 381; - } - else - { - ft = t - atime; - iretn = 0; - } - } - - /* ------------------- dot terms calculated ------------- */ - /* ----------- near - synchronous resonance terms ------- */ - if (irez != 2) - { - xndt = del1 * sin(xli - fasx2) + del2 * sin(2.0 * (xli - fasx4)) + - del3 * sin(3.0 * (xli - fasx6)); - xldot = xni + xfact; - xnddt = del1 * cos(xli - fasx2) + - 2.0 * del2 * cos(2.0 * (xli - fasx4)) + - 3.0 * del3 * cos(3.0 * (xli - fasx6)); - xnddt = xnddt * xldot; - } - else - { - /* --------- near - half-day resonance terms -------- */ - xomi = argpo + argpdot * atime; - x2omi = xomi + xomi; - x2li = xli + xli; - xndt = d2201 * sin(x2omi + xli - g22) + d2211 * sin(xli - g22) + - d3210 * sin(xomi + xli - g32) + d3222 * sin(-xomi + xli - g32)+ - d4410 * sin(x2omi + x2li - g44)+ d4422 * sin(x2li - g44) + - d5220 * sin(xomi + xli - g52) + d5232 * sin(-xomi + xli - g52)+ - d5421 * sin(xomi + x2li - g54) + d5433 * sin(-xomi + x2li - g54); - xldot = xni + xfact; - xnddt = d2201 * cos(x2omi + xli - g22) + d2211 * cos(xli - g22) + - d3210 * cos(xomi + xli - g32) + d3222 * cos(-xomi + xli - g32) + - d5220 * cos(xomi + xli - g52) + d5232 * cos(-xomi + xli - g52) + - 2.0 * (d4410 * cos(x2omi + x2li - g44) + - d4422 * cos(x2li - g44) + d5421 * cos(xomi + x2li - g54) + - d5433 * cos(-xomi + x2li - g54)); - xnddt = xnddt * xldot; - } - - /* ----------------------- integrator ------------------- */ - if (iretn == 381) - { - xli = xli + xldot * delt + xndt * step2; - xni = xni + xndt * delt + xnddt * step2; - atime = atime + delt; - } - } // while iretn = 381 - - nm = xni + xndt * ft + xnddt * ft * ft * 0.5; - xl = xli + xldot * ft + xndt * ft * ft * 0.5; - if (irez != 1) - { - mm = xl - 2.0 * nodem + 2.0 * theta; - dndt = nm - no; - } - else - { - mm = xl - nodem - argpm + theta; - dndt = nm - no; - } - nm = no + dndt; - } - -//#include "debug4.cpp" -} // end dsspace - -/*----------------------------------------------------------------------------- -* -* procedure initl -* -* this procedure initializes the spg4 propagator. all the initialization is -* consolidated here instead of having multiple loops inside other routines. -* -* author : david vallado 719-573-2600 28 jun 2005 -* -* inputs : -* ecco - eccentricity 0.0 - 1.0 -* epoch - epoch time in days from jan 0, 1950. 0 hr -* inclo - inclination of satellite -* no - mean motion of satellite -* satn - satellite number -* -* outputs : -* ainv - 1.0 / a -* ao - semi major axis -* con41 - -* con42 - 1.0 - 5.0 cos(i) -* cosio - cosine of inclination -* cosio2 - cosio squared -* eccsq - eccentricity squared -* method - flag for deep space 'd', 'n' -* omeosq - 1.0 - ecco * ecco -* posq - semi-parameter squared -* rp - radius of perigee -* rteosq - square root of (1.0 - ecco*ecco) -* sinio - sine of inclination -* gsto - gst at time of observation rad -* no - mean motion of satellite -* -* locals : -* ak - -* d1 - -* del - -* adel - -* po - -* -* coupling : -* getgravconst -* gstime - find greenwich sidereal time from the julian date -* -* references : -* hoots, roehrich, norad spacetrack report #3 1980 -* hoots, norad spacetrack report #6 1986 -* hoots, schumacher and glover 2004 -* vallado, crawford, hujsak, kelso 2006 - ----------------------------------------------------------------------------*/ - -static void initl - ( - int satn, gravconsttype whichconst, - double ecco, double epoch, double inclo, double& no, - char& method, - double& ainv, double& ao, double& con41, double& con42, double& cosio, - double& cosio2,double& eccsq, double& omeosq, double& posq, - double& rp, double& rteosq,double& sinio , double& gsto - ) -{ - /* --------------------- local variables ------------------------ */ - double ak, d1, del, adel, po, x2o3, j2, xke, - tumin, mu, radiusearthkm, j3, j4, j3oj2; - - // sgp4fix use old way of finding gst - int ids70; - double ts70, ds70, tfrac, c1, thgr70, fk5r, c1p2p; - const double twopi = 2.0 * pi; - - /* ----------------------- earth constants ---------------------- */ - // sgp4fix identify constants and allow alternate values - getgravconst( whichconst, tumin, mu, radiusearthkm, xke, j2, j3, j4, j3oj2 ); - x2o3 = 2.0 / 3.0; - - /* ------------- calculate auxillary epoch quantities ---------- */ - eccsq = ecco * ecco; - omeosq = 1.0 - eccsq; - rteosq = sqrt(omeosq); - cosio = cos(inclo); - cosio2 = cosio * cosio; - - /* ------------------ un-kozai the mean motion ----------------- */ - ak = pow(xke / no, x2o3); - d1 = 0.75 * j2 * (3.0 * cosio2 - 1.0) / (rteosq * omeosq); - del = d1 / (ak * ak); - adel = ak * (1.0 - del * del - del * - (1.0 / 3.0 + 134.0 * del * del / 81.0)); - del = d1/(adel * adel); - no = no / (1.0 + del); - - ao = pow(xke / no, x2o3); - sinio = sin(inclo); - po = ao * omeosq; - con42 = 1.0 - 5.0 * cosio2; - con41 = -con42-cosio2-cosio2; - ainv = 1.0 / ao; - posq = po * po; - rp = ao * (1.0 - ecco); - method = 'n'; - - // sgp4fix modern approach to finding sidereal timew - // gsto = gstime(epoch + 2433281.5); - - // sgp4fix use old way of finding gst - // count integer number of days from 0 jan 1970 - ts70 = epoch - 7305.0; - ids70 = floor(ts70 + 1.0e-8); - ds70 = ids70; - tfrac = ts70 - ds70; - // find greenwich location at epoch - c1 = 1.72027916940703639e-2; - thgr70= 1.7321343856509374; - fk5r = 5.07551419432269442e-15; - c1p2p = c1 + twopi; - gsto = fmod( thgr70 + c1*ds70 + c1p2p*tfrac + ts70*ts70*fk5r, twopi); - if ( gsto < 0.0 ) - gsto = gsto + twopi; - -//#include "debug5.cpp" -} // end initl - -/*----------------------------------------------------------------------------- -* -* procedure sgp4init -* -* this procedure initializes variables for sgp4. -* -* author : david vallado 719-573-2600 28 jun 2005 -* -* inputs : -* satn - satellite number -* bstar - sgp4 type drag coefficient kg/m2er -* ecco - eccentricity -* epoch - epoch time in days from jan 0, 1950. 0 hr -* argpo - argument of perigee (output if ds) -* inclo - inclination -* mo - mean anomaly (output if ds) -* no - mean motion -* nodeo - right ascension of ascending node -* -* outputs : -* satrec - common values for subsequent calls -* return code - non-zero on error. -* 1 - mean elements, ecc >= 1.0 or ecc < -0.001 or a < 0.95 er -* 2 - mean motion less than 0.0 -* 3 - pert elements, ecc < 0.0 or ecc > 1.0 -* 4 - semi-latus rectum < 0.0 -* 5 - epoch elements are sub-orbital -* 6 - satellite has decayed -* -* locals : -* cnodm , snodm , cosim , sinim , cosomm , sinomm -* cc1sq , cc2 , cc3 -* coef , coef1 -* cosio4 - -* day - -* dndt - -* em - eccentricity -* emsq - eccentricity squared -* eeta - -* etasq - -* gam - -* argpm - argument of perigee -* nodem - -* inclm - inclination -* mm - mean anomaly -* nm - mean motion -* perige - perigee -* pinvsq - -* psisq - -* qzms24 - -* rtemsq - -* s1, s2, s3, s4, s5, s6, s7 - -* sfour - -* ss1, ss2, ss3, ss4, ss5, ss6, ss7 - -* sz1, sz2, sz3 -* sz11, sz12, sz13, sz21, sz22, sz23, sz31, sz32, sz33 - -* tc - -* temp - -* temp1, temp2, temp3 - -* tsi - -* xpidot - -* xhdot1 - -* z1, z2, z3 - -* z11, z12, z13, z21, z22, z23, z31, z32, z33 - -* -* coupling : -* getgravconst- -* initl - -* dscom - -* dpper - -* dsinit - -* sgp4 - -* -* references : -* hoots, roehrich, norad spacetrack report #3 1980 -* hoots, norad spacetrack report #6 1986 -* hoots, schumacher and glover 2004 -* vallado, crawford, hujsak, kelso 2006 - ----------------------------------------------------------------------------*/ - -int sgp4init - ( - gravconsttype whichconst, const int satn, const double epoch, - const double xbstar, const double xecco, const double xargpo, - const double xinclo, const double xmo, const double xno, - const double xnodeo, elsetrec& satrec - ) -{ - /* --------------------- local variables ------------------------ */ - double ao, ainv, con42, cosio, sinio, cosio2, eccsq, - omeosq, posq, rp, rteosq, - cnodm , snodm , cosim , sinim , cosomm, sinomm, cc1sq , - cc2 , cc3 , coef , coef1 , cosio4, day , dndt , - em , emsq , eeta , etasq , gam , argpm , nodem , - inclm , mm , nm , perige, pinvsq, psisq , qzms24, - rtemsq, s1 , s2 , s3 , s4 , s5 , s6 , - s7 , sfour , ss1 = 0 , ss2 = 0 , ss3 = 0 , ss4 = 0 , ss5 = 0 , - ss6 = 0 , ss7 = 0 , sz1 = 0 , sz2 = 0 , sz3 = 0 , sz11 = 0 , sz12 = 0 , - sz13 = 0 , sz21 = 0 , sz22 = 0 , sz23 = 0 , sz31 = 0 , sz32 = 0 , sz33 = 0 , - tc , temp , temp1 , temp2 , temp3 , tsi , xpidot, - xhdot1, z1 , z2 , z3 , z11 , z12 , z13 , - z21 , z22 , z23 , z31 , z32 , z33, - qzms2t, ss, j2, j3oj2, j4, x2o3, r[3], v[3], - tumin, mu, radiusearthkm, xke, j3; - - /* ------------------------ initialization --------------------- */ - // sgp4fix divisor for divide by zero check on inclination - const double temp4 = 1.0 + cos(pi-1.0e-9); - - /* ----------- set all near earth variables to zero ------------ */ - satrec.isimp = 0; satrec.method = 'n'; satrec.aycof = 0.0; - satrec.con41 = 0.0; satrec.cc1 = 0.0; satrec.cc4 = 0.0; - satrec.cc5 = 0.0; satrec.d2 = 0.0; satrec.d3 = 0.0; - satrec.d4 = 0.0; satrec.delmo = 0.0; satrec.eta = 0.0; - satrec.argpdot = 0.0; satrec.omgcof = 0.0; satrec.sinmao = 0.0; - satrec.t = 0.0; satrec.t2cof = 0.0; satrec.t3cof = 0.0; - satrec.t4cof = 0.0; satrec.t5cof = 0.0; satrec.x1mth2 = 0.0; - satrec.x7thm1 = 0.0; satrec.mdot = 0.0; satrec.nodedot = 0.0; - satrec.xlcof = 0.0; satrec.xmcof = 0.0; satrec.nodecf = 0.0; - - /* ----------- set all deep space variables to zero ------------ */ - satrec.irez = 0; satrec.d2201 = 0.0; satrec.d2211 = 0.0; - satrec.d3210 = 0.0; satrec.d3222 = 0.0; satrec.d4410 = 0.0; - satrec.d4422 = 0.0; satrec.d5220 = 0.0; satrec.d5232 = 0.0; - satrec.d5421 = 0.0; satrec.d5433 = 0.0; satrec.dedt = 0.0; - satrec.del1 = 0.0; satrec.del2 = 0.0; satrec.del3 = 0.0; - satrec.didt = 0.0; satrec.dmdt = 0.0; satrec.dnodt = 0.0; - satrec.domdt = 0.0; satrec.e3 = 0.0; satrec.ee2 = 0.0; - satrec.peo = 0.0; satrec.pgho = 0.0; satrec.pho = 0.0; - satrec.pinco = 0.0; satrec.plo = 0.0; satrec.se2 = 0.0; - satrec.se3 = 0.0; satrec.sgh2 = 0.0; satrec.sgh3 = 0.0; - satrec.sgh4 = 0.0; satrec.sh2 = 0.0; satrec.sh3 = 0.0; - satrec.si2 = 0.0; satrec.si3 = 0.0; satrec.sl2 = 0.0; - satrec.sl3 = 0.0; satrec.sl4 = 0.0; satrec.gsto = 0.0; - satrec.xfact = 0.0; satrec.xgh2 = 0.0; satrec.xgh3 = 0.0; - satrec.xgh4 = 0.0; satrec.xh2 = 0.0; satrec.xh3 = 0.0; - satrec.xi2 = 0.0; satrec.xi3 = 0.0; satrec.xl2 = 0.0; - satrec.xl3 = 0.0; satrec.xl4 = 0.0; satrec.xlamo = 0.0; - satrec.zmol = 0.0; satrec.zmos = 0.0; satrec.atime = 0.0; - satrec.xli = 0.0; satrec.xni = 0.0; - - // sgp4fix - note the following variables are also passed directly via satrec. - // it is possible to streamline the sgp4init call by deleting the "x" - // variables, but the user would need to set the satrec.* values first. we - // include the additional assignments in case twoline2rv is not used. - satrec.bstar = xbstar; - satrec.ecco = xecco; - satrec.argpo = xargpo; - satrec.inclo = xinclo; - satrec.mo = xmo; - satrec.no = xno; - satrec.nodeo = xnodeo; - - /* ------------------------ earth constants ----------------------- */ - // sgp4fix identify constants and allow alternate values - getgravconst( whichconst, tumin, mu, radiusearthkm, xke, j2, j3, j4, j3oj2 ); - ss = 78.0 / radiusearthkm + 1.0; - qzms2t = pow(((120.0 - 78.0) / radiusearthkm), 4); - x2o3 = 2.0 / 3.0; - - satrec.init = 'y'; - satrec.t = 0.0; - - initl - ( - satn, whichconst, satrec.ecco, epoch, satrec.inclo, satrec.no, satrec.method, - ainv, ao, satrec.con41, con42, cosio, cosio2, eccsq, omeosq, - posq, rp, rteosq, sinio, satrec.gsto - ); - satrec.error = 0; - - if (rp < 1.0) - { -// printf("# *** satn%d epoch elts sub-orbital ***\n", satn); - satrec.error = 5; - } - - if ((omeosq >= 0.0 ) || ( satrec.no >= 0.0)) - { - satrec.isimp = 0; - if (rp < (220.0 / radiusearthkm + 1.0)) - satrec.isimp = 1; - sfour = ss; - qzms24 = qzms2t; - perige = (rp - 1.0) * radiusearthkm; - - /* - for perigees below 156 km, s and qoms2t are altered - */ - if (perige < 156.0) - { - sfour = perige - 78.0; - if (perige < 98.0) - sfour = 20.0; - qzms24 = pow(((120.0 - sfour) / radiusearthkm), 4.0); - sfour = sfour / radiusearthkm + 1.0; - } - pinvsq = 1.0 / posq; - - tsi = 1.0 / (ao - sfour); - satrec.eta = ao * satrec.ecco * tsi; - etasq = satrec.eta * satrec.eta; - eeta = satrec.ecco * satrec.eta; - psisq = fabs(1.0 - etasq); - coef = qzms24 * pow(tsi, 4.0); - coef1 = coef / pow(psisq, 3.5); - cc2 = coef1 * satrec.no * (ao * (1.0 + 1.5 * etasq + eeta * - (4.0 + etasq)) + 0.375 * j2 * tsi / psisq * satrec.con41 * - (8.0 + 3.0 * etasq * (8.0 + etasq))); - satrec.cc1 = satrec.bstar * cc2; - cc3 = 0.0; - if (satrec.ecco > 1.0e-4) - cc3 = -2.0 * coef * tsi * j3oj2 * satrec.no * sinio / satrec.ecco; - satrec.x1mth2 = 1.0 - cosio2; - satrec.cc4 = 2.0* satrec.no * coef1 * ao * omeosq * - (satrec.eta * (2.0 + 0.5 * etasq) + satrec.ecco * - (0.5 + 2.0 * etasq) - j2 * tsi / (ao * psisq) * - (-3.0 * satrec.con41 * (1.0 - 2.0 * eeta + etasq * - (1.5 - 0.5 * eeta)) + 0.75 * satrec.x1mth2 * - (2.0 * etasq - eeta * (1.0 + etasq)) * cos(2.0 * satrec.argpo))); - satrec.cc5 = 2.0 * coef1 * ao * omeosq * (1.0 + 2.75 * - (etasq + eeta) + eeta * etasq); - cosio4 = cosio2 * cosio2; - temp1 = 1.5 * j2 * pinvsq * satrec.no; - temp2 = 0.5 * temp1 * j2 * pinvsq; - temp3 = -0.46875 * j4 * pinvsq * pinvsq * satrec.no; - satrec.mdot = satrec.no + 0.5 * temp1 * rteosq * satrec.con41 + 0.0625 * - temp2 * rteosq * (13.0 - 78.0 * cosio2 + 137.0 * cosio4); - satrec.argpdot = -0.5 * temp1 * con42 + 0.0625 * temp2 * - (7.0 - 114.0 * cosio2 + 395.0 * cosio4) + - temp3 * (3.0 - 36.0 * cosio2 + 49.0 * cosio4); - xhdot1 = -temp1 * cosio; - satrec.nodedot = xhdot1 + (0.5 * temp2 * (4.0 - 19.0 * cosio2) + - 2.0 * temp3 * (3.0 - 7.0 * cosio2)) * cosio; - xpidot = satrec.argpdot+ satrec.nodedot; - satrec.omgcof = satrec.bstar * cc3 * cos(satrec.argpo); - satrec.xmcof = 0.0; - if (satrec.ecco > 1.0e-4) - satrec.xmcof = -x2o3 * coef * satrec.bstar / eeta; - satrec.nodecf = 3.5 * omeosq * xhdot1 * satrec.cc1; - satrec.t2cof = 1.5 * satrec.cc1; - // sgp4fix for divide by zero with xinco = 180 deg - if (fabs(cosio+1.0) > 1.5e-12) - satrec.xlcof = -0.25 * j3oj2 * sinio * (3.0 + 5.0 * cosio) / (1.0 + cosio); - else - satrec.xlcof = -0.25 * j3oj2 * sinio * (3.0 + 5.0 * cosio) / temp4; - satrec.aycof = -0.5 * j3oj2 * sinio; - satrec.delmo = pow((1.0 + satrec.eta * cos(satrec.mo)), 3); - satrec.sinmao = sin(satrec.mo); - satrec.x7thm1 = 7.0 * cosio2 - 1.0; - - /* --------------- deep space initialization ------------- */ - if ((2*pi / satrec.no) >= 225.0) - { - satrec.method = 'd'; - satrec.isimp = 1; - tc = 0.0; - inclm = satrec.inclo; - - dscom - ( - epoch, satrec.ecco, satrec.argpo, tc, satrec.inclo, satrec.nodeo, - satrec.no, snodm, cnodm, sinim, cosim,sinomm, cosomm, - day, satrec.e3, satrec.ee2, em, emsq, gam, - satrec.peo, satrec.pgho, satrec.pho, satrec.pinco, - satrec.plo, rtemsq, satrec.se2, satrec.se3, - satrec.sgh2, satrec.sgh3, satrec.sgh4, - satrec.sh2, satrec.sh3, satrec.si2, satrec.si3, - satrec.sl2, satrec.sl3, satrec.sl4, s1, s2, s3, s4, s5, - s6, s7, ss1, ss2, ss3, ss4, ss5, ss6, ss7, sz1, sz2, sz3, - sz11, sz12, sz13, sz21, sz22, sz23, sz31, sz32, sz33, - satrec.xgh2, satrec.xgh3, satrec.xgh4, satrec.xh2, - satrec.xh3, satrec.xi2, satrec.xi3, satrec.xl2, - satrec.xl3, satrec.xl4, nm, z1, z2, z3, z11, - z12, z13, z21, z22, z23, z31, z32, z33, - satrec.zmol, satrec.zmos - ); - dpper - ( - satrec.e3, satrec.ee2, satrec.peo, satrec.pgho, - satrec.pho, satrec.pinco, satrec.plo, satrec.se2, - satrec.se3, satrec.sgh2, satrec.sgh3, satrec.sgh4, - satrec.sh2, satrec.sh3, satrec.si2, satrec.si3, - satrec.sl2, satrec.sl3, satrec.sl4, satrec.t, - satrec.xgh2,satrec.xgh3,satrec.xgh4, satrec.xh2, - satrec.xh3, satrec.xi2, satrec.xi3, satrec.xl2, - satrec.xl3, satrec.xl4, satrec.zmol, satrec.zmos, inclm, satrec.init, - satrec.ecco, satrec.inclo, satrec.nodeo, satrec.argpo, satrec.mo - ); - - argpm = 0.0; - nodem = 0.0; - mm = 0.0; - - dsinit - ( - whichconst, - cosim, emsq, satrec.argpo, s1, s2, s3, s4, s5, sinim, ss1, ss2, ss3, ss4, - ss5, sz1, sz3, sz11, sz13, sz21, sz23, sz31, sz33, satrec.t, tc, - satrec.gsto, satrec.mo, satrec.mdot, satrec.no, satrec.nodeo, - satrec.nodedot, xpidot, z1, z3, z11, z13, z21, z23, z31, z33, - satrec.ecco, eccsq, em, argpm, inclm, mm, nm, nodem, - satrec.irez, satrec.atime, - satrec.d2201, satrec.d2211, satrec.d3210, satrec.d3222 , - satrec.d4410, satrec.d4422, satrec.d5220, satrec.d5232, - satrec.d5421, satrec.d5433, satrec.dedt, satrec.didt, - satrec.dmdt, dndt, satrec.dnodt, satrec.domdt , - satrec.del1, satrec.del2, satrec.del3, satrec.xfact, - satrec.xlamo, satrec.xli, satrec.xni - ); - } - - /* ----------- set variables if not deep space ----------- */ - if (satrec.isimp != 1) - { - cc1sq = satrec.cc1 * satrec.cc1; - satrec.d2 = 4.0 * ao * tsi * cc1sq; - temp = satrec.d2 * tsi * satrec.cc1 / 3.0; - satrec.d3 = (17.0 * ao + sfour) * temp; - satrec.d4 = 0.5 * temp * ao * tsi * (221.0 * ao + 31.0 * sfour) * - satrec.cc1; - satrec.t3cof = satrec.d2 + 2.0 * cc1sq; - satrec.t4cof = 0.25 * (3.0 * satrec.d3 + satrec.cc1 * - (12.0 * satrec.d2 + 10.0 * cc1sq)); - satrec.t5cof = 0.2 * (3.0 * satrec.d4 + - 12.0 * satrec.cc1 * satrec.d3 + - 6.0 * satrec.d2 * satrec.d2 + - 15.0 * cc1sq * (2.0 * satrec.d2 + cc1sq)); - } - } // if omeosq = 0 ... - - /* finally propogate to zero epoch to initialise all others. */ - if(satrec.error == 0) - sgp4(whichconst, satrec, 0.0, r, v); - - satrec.init = 'n'; - -//#include "debug6.cpp" - return satrec.error; -} // end sgp4init - -/*----------------------------------------------------------------------------- -* -* procedure sgp4 -* -* this procedure is the sgp4 prediction model from space command. this is an -* updated and combined version of sgp4 and sdp4, which were originally -* published separately in spacetrack report #3. this version follows the -* methodology from the aiaa paper (2006) describing the history and -* development of the code. -* -* author : david vallado 719-573-2600 28 jun 2005 -* -* inputs : -* satrec - initialised structure from sgp4init() call. -* tsince - time eince epoch (minutes) -* -* outputs : -* r - position vector km -* v - velocity km/sec -* return code - non-zero on error. -* 1 - mean elements, ecc >= 1.0 or ecc < -0.001 or a < 0.95 er -* 2 - mean motion less than 0.0 -* 3 - pert elements, ecc < 0.0 or ecc > 1.0 -* 4 - semi-latus rectum < 0.0 -* 5 - epoch elements are sub-orbital -* 6 - satellite has decayed -* -* locals : -* am - -* axnl, aynl - -* betal - -* cosim , sinim , cosomm , sinomm , cnod , snod , cos2u , -* sin2u , coseo1 , sineo1 , cosi , sini , cosip , sinip , -* cosisq , cossu , sinsu , cosu , sinu -* delm - -* delomg - -* dndt - -* eccm - -* emsq - -* ecose - -* el2 - -* eo1 - -* eccp - -* esine - -* argpm - -* argpp - -* omgadf - -* pl - -* r - -* rtemsq - -* rdotl - -* rl - -* rvdot - -* rvdotl - -* su - -* t2 , t3 , t4 , tc -* tem5, temp , temp1 , temp2 , tempa , tempe , templ -* u , ux , uy , uz , vx , vy , vz -* inclm - inclination -* mm - mean anomaly -* nm - mean motion -* nodem - right asc of ascending node -* xinc - -* xincp - -* xl - -* xlm - -* mp - -* xmdf - -* xmx - -* xmy - -* nodedf - -* xnode - -* nodep - -* np - -* -* coupling : -* getgravconst- -* dpper -* dpspace -* -* references : -* hoots, roehrich, norad spacetrack report #3 1980 -* hoots, norad spacetrack report #6 1986 -* hoots, schumacher and glover 2004 -* vallado, crawford, hujsak, kelso 2006 - ----------------------------------------------------------------------------*/ - -int sgp4 - ( - gravconsttype whichconst, elsetrec& satrec, double tsince, - double r[3], double v[3] - ) -{ - double am , axnl , aynl , betal , cosim , cnod , - cos2u, coseo1, cosi , cosip , cosisq, cossu , cosu, - delm , delomg, em , emsq , ecose , el2 , eo1 , - ep , esine , argpm, argpp , argpdf, pl, mrt = 0.0, - mvt , rdotl , rl , rvdot , rvdotl, sinim , - sin2u, sineo1, sini , sinip , sinsu , sinu , - snod , su , t2 , t3 , t4 , tem5 , temp, - temp1, temp2 , tempa, tempe , templ , u , ux , - uy , uz , vx , vy , vz , inclm , mm , - nm , nodem, xinc , xincp , xl , xlm , mp , - xmdf , xmx , xmy , nodedf, xnode , nodep, tc , dndt, - twopi, x2o3 , j2 , j3 , tumin, j4 , xke , j3oj2, radiusearthkm, - mu, vkmpersec; - int ktr; - - /* ------------------ set mathematical constants --------------- */ - // sgp4fix divisor for divide by zero check on inclination - const double temp4 = 1.0 + cos(pi-1.0e-9); - twopi = 2.0 * pi; - x2o3 = 2.0 / 3.0; - // sgp4fix identify constants and allow alternate values - getgravconst( whichconst, tumin, mu, radiusearthkm, xke, j2, j3, j4, j3oj2 ); - vkmpersec = radiusearthkm * xke/60.0; - - /* --------------------- clear sgp4 error flag ----------------- */ - satrec.t = tsince; - satrec.error = 0; - - /* ------- update for secular gravity and atmospheric drag ----- */ - xmdf = satrec.mo + satrec.mdot * satrec.t; - argpdf = satrec.argpo + satrec.argpdot * satrec.t; - nodedf = satrec.nodeo + satrec.nodedot * satrec.t; - argpm = argpdf; - mm = xmdf; - t2 = satrec.t * satrec.t; - nodem = nodedf + satrec.nodecf * t2; - tempa = 1.0 - satrec.cc1 * satrec.t; - tempe = satrec.bstar * satrec.cc4 * satrec.t; - templ = satrec.t2cof * t2; - - if (satrec.isimp != 1) - { - delomg = satrec.omgcof * satrec.t; - delm = satrec.xmcof * - (pow((1.0 + satrec.eta * cos(xmdf)), 3) - - satrec.delmo); - temp = delomg + delm; - mm = xmdf + temp; - argpm = argpdf - temp; - t3 = t2 * satrec.t; - t4 = t3 * satrec.t; - tempa = tempa - satrec.d2 * t2 - satrec.d3 * t3 - - satrec.d4 * t4; - tempe = tempe + satrec.bstar * satrec.cc5 * (sin(mm) - - satrec.sinmao); - templ = templ + satrec.t3cof * t3 + t4 * (satrec.t4cof + - satrec.t * satrec.t5cof); - } - - nm = satrec.no; - em = satrec.ecco; - inclm = satrec.inclo; - if (satrec.method == 'd') - { - tc = satrec.t; - dspace - ( - satrec.irez, - satrec.d2201, satrec.d2211, satrec.d3210, - satrec.d3222, satrec.d4410, satrec.d4422, - satrec.d5220, satrec.d5232, satrec.d5421, - satrec.d5433, satrec.dedt, satrec.del1, - satrec.del2, satrec.del3, satrec.didt, - satrec.dmdt, satrec.dnodt, satrec.domdt, - satrec.argpo, satrec.argpdot, satrec.t, tc, - satrec.gsto, satrec.xfact, satrec.xlamo, - satrec.no, satrec.atime, - em, argpm, inclm, satrec.xli, mm, satrec.xni, - nodem, dndt, nm - ); - } // if method = d - - if (nm <= 0.0) - { -// printf("# error nm %f\n", nm); - satrec.error = 2; - } - am = pow((xke / nm),x2o3) * tempa * tempa; - nm = xke / pow(am, 1.5); - em = em - tempe; - - // fix tolerance for error recognition - if ((em >= 1.0) || (em < -0.001) || (am < 0.95)) - { -// printf("# error em %f\n", em); - satrec.error = 1; - } - if (em < 0.0) - em = 1.0e-6; - mm = mm + satrec.no * templ; - xlm = mm + argpm + nodem; - emsq = em * em; - temp = 1.0 - emsq; - - nodem = fmod(nodem, twopi); - argpm = fmod(argpm, twopi); - xlm = fmod(xlm, twopi); - mm = fmod(xlm - argpm - nodem, twopi); - - /* ----------------- compute extra mean quantities ------------- */ - sinim = sin(inclm); - cosim = cos(inclm); - - /* -------------------- add lunar-solar periodics -------------- */ - ep = em; - xincp = inclm; - argpp = argpm; - nodep = nodem; - mp = mm; - sinip = sinim; - cosip = cosim; - if (satrec.method == 'd') - { - dpper - ( - satrec.e3, satrec.ee2, satrec.peo, - satrec.pgho, satrec.pho, satrec.pinco, - satrec.plo, satrec.se2, satrec.se3, - satrec.sgh2, satrec.sgh3, satrec.sgh4, - satrec.sh2, satrec.sh3, satrec.si2, - satrec.si3, satrec.sl2, satrec.sl3, - satrec.sl4, satrec.t, satrec.xgh2, - satrec.xgh3, satrec.xgh4, satrec.xh2, - satrec.xh3, satrec.xi2, satrec.xi3, - satrec.xl2, satrec.xl3, satrec.xl4, - satrec.zmol, satrec.zmos, satrec.inclo, - 'n', ep, xincp, nodep, argpp, mp - ); - if (xincp < 0.0) - { - xincp = -xincp; - nodep = nodep + pi; - argpp = argpp - pi; - } - if ((ep < 0.0 ) || ( ep > 1.0)) - { - // printf("# error ep %f\n", ep); - satrec.error = 3; - } - } // if method = d - - /* -------------------- long period periodics ------------------ */ - if (satrec.method == 'd') - { - sinip = sin(xincp); - cosip = cos(xincp); - satrec.aycof = -0.5*j3oj2*sinip; - // sgp4fix for divide by zero for xincp = 180 deg - if (fabs(cosip+1.0) > 1.5e-12) - satrec.xlcof = -0.25 * j3oj2 * sinip * (3.0 + 5.0 * cosip) / (1.0 + cosip); - else - satrec.xlcof = -0.25 * j3oj2 * sinip * (3.0 + 5.0 * cosip) / temp4; - } - axnl = ep * cos(argpp); - temp = 1.0 / (am * (1.0 - ep * ep)); - aynl = ep* sin(argpp) + temp * satrec.aycof; - xl = mp + argpp + nodep + temp * satrec.xlcof * axnl; - - /* --------------------- solve kepler's equation --------------- */ - u = fmod(xl - nodep, twopi); - eo1 = u; - tem5 = 9999.9; - ktr = 1; - // sgp4fix for kepler iteration - // the following iteration needs better limits on corrections - while (( fabs(tem5) >= 1.0e-12) && (ktr <= 10) ) - { - sineo1 = sin(eo1); - coseo1 = cos(eo1); - tem5 = 1.0 - coseo1 * axnl - sineo1 * aynl; - tem5 = (u - aynl * coseo1 + axnl * sineo1 - eo1) / tem5; - if(fabs(tem5) >= 0.95) - tem5 = tem5 > 0.0 ? 0.95 : -0.95; - eo1 = eo1 + tem5; - ktr = ktr + 1; - } - - /* ------------- short period preliminary quantities ----------- */ - ecose = axnl*coseo1 + aynl*sineo1; - esine = axnl*sineo1 - aynl*coseo1; - el2 = axnl*axnl + aynl*aynl; - pl = am*(1.0-el2); - if (pl < 0.0) - { -// printf("# error pl %f\n", pl); - satrec.error = 4; - } - else - { - rl = am * (1.0 - ecose); - rdotl = sqrt(am) * esine/rl; - rvdotl = sqrt(pl) / rl; - betal = sqrt(1.0 - el2); - temp = esine / (1.0 + betal); - sinu = am / rl * (sineo1 - aynl - axnl * temp); - cosu = am / rl * (coseo1 - axnl + aynl * temp); - su = atan2(sinu, cosu); - sin2u = (cosu + cosu) * sinu; - cos2u = 1.0 - 2.0 * sinu * sinu; - temp = 1.0 / pl; - temp1 = 0.5 * j2 * temp; - temp2 = temp1 * temp; - - /* -------------- update for short period periodics ------------ */ - if (satrec.method == 'd') - { - cosisq = cosip * cosip; - satrec.con41 = 3.0*cosisq - 1.0; - satrec.x1mth2 = 1.0 - cosisq; - satrec.x7thm1 = 7.0*cosisq - 1.0; - } - mrt = rl * (1.0 - 1.5 * temp2 * betal * satrec.con41) + - 0.5 * temp1 * satrec.x1mth2 * cos2u; - su = su - 0.25 * temp2 * satrec.x7thm1 * sin2u; - xnode = nodep + 1.5 * temp2 * cosip * sin2u; - xinc = xincp + 1.5 * temp2 * cosip * sinip * cos2u; - mvt = rdotl - nm * temp1 * satrec.x1mth2 * sin2u / xke; - rvdot = rvdotl + nm * temp1 * (satrec.x1mth2 * cos2u + - 1.5 * satrec.con41) / xke; - - /* --------------------- orientation vectors ------------------- */ - sinsu = sin(su); - cossu = cos(su); - snod = sin(xnode); - cnod = cos(xnode); - sini = sin(xinc); - cosi = cos(xinc); - xmx = -snod * cosi; - xmy = cnod * cosi; - ux = xmx * sinsu + cnod * cossu; - uy = xmy * sinsu + snod * cossu; - uz = sini * sinsu; - vx = xmx * cossu - cnod * sinsu; - vy = xmy * cossu - snod * sinsu; - vz = sini * cossu; - - /* --------- position and velocity (in km and km/sec) ---------- */ - r[0] = (mrt * ux)* radiusearthkm; - r[1] = (mrt * uy)* radiusearthkm; - r[2] = (mrt * uz)* radiusearthkm; - v[0] = (mvt * ux + rvdot * vx) * vkmpersec; - v[1] = (mvt * uy + rvdot * vy) * vkmpersec; - v[2] = (mvt * uz + rvdot * vz) * vkmpersec; - } // if pl > 0 - - // sgp4fix for decaying satellites - if (mrt < 1.0) - { -// printf("# decay condition %11.6f \n",mrt); - satrec.error = 6; - } - - -//#include "debug7.cpp" - return satrec.error; -} // end sgp4 - - -/* ----------------------------------------------------------------------------- -* -* function gstime -* -* this function finds the greenwich sidereal time. -* -* author : david vallado 719-573-2600 1 mar 2001 -* -* inputs description range / units -* jdut1 - julian date in ut1 days from 4713 bc -* -* outputs : -* gstime - greenwich sidereal time 0 to 2pi rad -* -* locals : -* temp - temporary variable for doubles rad -* tut1 - julian centuries from the -* jan 1, 2000 12 h epoch (ut1) -* -* coupling : -* none -* -* references : -* vallado 2004, 191, eq 3-45 -* --------------------------------------------------------------------------- */ - -double gstime - ( - double jdut1 - ) - { - const double twopi = 2.0 * pi; - const double deg2rad = pi / 180.0; - double temp, tut1; - - tut1 = (jdut1 - 2451545.0) / 36525.0; - temp = -6.2e-6* tut1 * tut1 * tut1 + 0.093104 * tut1 * tut1 + - (876600.0*3600 + 8640184.812866) * tut1 + 67310.54841; // sec - temp = fmod(temp * deg2rad / 240.0, twopi); //360/86400 = 1/240, to deg, to rad - - // ------------------------ check quadrants --------------------- - if (temp < 0.0) - temp += twopi; - - return temp; - } // end gstime - -/* ----------------------------------------------------------------------------- -* -* function getgravconst -* -* this function gets constants for the propagator. note that mu is identified to -* facilitiate comparisons with newer models. the common useage is wgs72. -* -* author : david vallado 719-573-2600 21 jul 2006 -* -* inputs : -* whichconst - which set of constants to use wgs72old, wgs72, wgs84 -* -* outputs : -* tumin - minutes in one time unit -* mu - earth gravitational parameter -* radiusearthkm - radius of the earth in km -* xke - reciprocal of tumin -* j2, j3, j4 - un-normalized zonal harmonic values -* j3oj2 - j3 divided by j2 -* -* locals : -* -* coupling : -* none -* -* references : -* norad spacetrack report #3 -* vallado, crawford, hujsak, kelso 2006 - --------------------------------------------------------------------------- */ - -void getgravconst - ( - gravconsttype whichconst, - double& tumin, - double& mu, - double& radiusearthkm, - double& xke, - double& j2, - double& j3, - double& j4, - double& j3oj2 - ) - { - - switch (whichconst) - { - // -- wgs-72 low precision str#3 constants -- - case wgs72old: - mu = 398600.79964; // in km3 / s2 - radiusearthkm = 6378.135; // km - xke = 0.0743669161; - tumin = 1.0 / xke; - j2 = 0.001082616; - j3 = -0.00000253881; - j4 = -0.00000165597; - j3oj2 = j3 / j2; - break; - // ------------ wgs-72 constants ------------ - case wgs72: - mu = 398600.8; // in km3 / s2 - radiusearthkm = 6378.135; // km - xke = 60.0 / sqrt(radiusearthkm*radiusearthkm*radiusearthkm/mu); - tumin = 1.0 / xke; - j2 = 0.001082616; - j3 = -0.00000253881; - j4 = -0.00000165597; - j3oj2 = j3 / j2; - break; - case wgs84: - // ------------ wgs-84 constants ------------ - mu = 398600.5; // in km3 / s2 - radiusearthkm = 6378.137; // km - xke = 60.0 / sqrt(radiusearthkm*radiusearthkm*radiusearthkm/mu); - tumin = 1.0 / xke; - j2 = 0.00108262998905; - j3 = -0.00000253215306; - j4 = -0.00000161098761; - j3oj2 = j3 / j2; - break; - default: - fprintf(stderr,"unknown gravity option (%d)\n",whichconst); - break; - } - - } // end getgravconst - - - - - +/* ---------------------------------------------------------------- +* +* sgp4unit.cpp +* +* this file contains the sgp4 procedures for analytical propagation +* of a satellite. the code was originally released in the 1980 and 1986 +* spacetrack papers. a detailed discussion of the theory and history +* may be found in the 2006 aiaa paper by vallado, crawford, hujsak, +* and kelso. +* +* companion code for +* fundamentals of astrodynamics and applications +* 2007 +* by david vallado +* +* (w) 719-573-2600, email dvallado@agi.com +* +* current : +* 16 nov 07 david vallado +* misc fixes for better compliance +* changes : +* 20 apr 07 david vallado +* misc fixes for constants +* 11 aug 06 david vallado +* chg lyddane choice back to strn3, constants, misc doc +* 15 dec 05 david vallado +* misc fixes +* 26 jul 05 david vallado +* fixes for paper +* note that each fix is preceded by a +* comment with "sgp4fix" and an explanation of +* what was changed +* 10 aug 04 david vallado +* 2nd printing baseline working +* 14 may 01 david vallado +* 2nd edition baseline +* 80 norad +* original baseline +* ---------------------------------------------------------------- */ + +#include "sgp4unit.h" + +const char help = 'n'; +FILE *dbgfile; + +#define pi 3.14159265358979323846 + + +/* ----------- local functions - only ever used internally by sgp4 ---------- */ +static void dpper + ( + double e3, double ee2, double peo, double pgho, double pho, + double pinco, double plo, double se2, double se3, double sgh2, + double sgh3, double sgh4, double sh2, double sh3, double si2, + double si3, double sl2, double sl3, double sl4, double t, + double xgh2, double xgh3, double xgh4, double xh2, double xh3, + double xi2, double xi3, double xl2, double xl3, double xl4, + double zmol, double zmos, double inclo, + char init, + double& ep, double& inclp, double& nodep, double& argpp, double& mp + ); + +static void dscom + ( + double epoch, double ep, double argpp, double tc, double inclp, + double nodep, double np, + double& snodm, double& cnodm, double& sinim, double& cosim, double& sinomm, + double& cosomm,double& day, double& e3, double& ee2, double& em, + double& emsq, double& gam, double& peo, double& pgho, double& pho, + double& pinco, double& plo, double& rtemsq, double& se2, double& se3, + double& sgh2, double& sgh3, double& sgh4, double& sh2, double& sh3, + double& si2, double& si3, double& sl2, double& sl3, double& sl4, + double& s1, double& s2, double& s3, double& s4, double& s5, + double& s6, double& s7, double& ss1, double& ss2, double& ss3, + double& ss4, double& ss5, double& ss6, double& ss7, double& sz1, + double& sz2, double& sz3, double& sz11, double& sz12, double& sz13, + double& sz21, double& sz22, double& sz23, double& sz31, double& sz32, + double& sz33, double& xgh2, double& xgh3, double& xgh4, double& xh2, + double& xh3, double& xi2, double& xi3, double& xl2, double& xl3, + double& xl4, double& nm, double& z1, double& z2, double& z3, + double& z11, double& z12, double& z13, double& z21, double& z22, + double& z23, double& z31, double& z32, double& z33, double& zmol, + double& zmos + ); + +static void dsinit + ( + gravconsttype whichconst, + double cosim, double emsq, double argpo, double s1, double s2, + double s3, double s4, double s5, double sinim, double ss1, + double ss2, double ss3, double ss4, double ss5, double sz1, + double sz3, double sz11, double sz13, double sz21, double sz23, + double sz31, double sz33, double t, double tc, double gsto, + double mo, double mdot, double no, double nodeo, double nodedot, + double xpidot, double z1, double z3, double z11, double z13, + double z21, double z23, double z31, double z33, double ecco, + double eccsq, double& em, double& argpm, double& inclm, double& mm, + double& nm, double& nodem, + int& irez, + double& atime, double& d2201, double& d2211, double& d3210, double& d3222, + double& d4410, double& d4422, double& d5220, double& d5232, double& d5421, + double& d5433, double& dedt, double& didt, double& dmdt, double& dndt, + double& dnodt, double& domdt, double& del1, double& del2, double& del3, + double& xfact, double& xlamo, double& xli, double& xni + ); + +static void dspace + ( + int irez, + double d2201, double d2211, double d3210, double d3222, double d4410, + double d4422, double d5220, double d5232, double d5421, double d5433, + double dedt, double del1, double del2, double del3, double didt, + double dmdt, double dnodt, double domdt, double argpo, double argpdot, + double t, double tc, double gsto, double xfact, double xlamo, + double no, + double& atime, double& em, double& argpm, double& inclm, double& xli, + double& mm, double& xni, double& nodem, double& dndt, double& nm + ); + +static void initl + ( + int satn, gravconsttype whichconst, + double ecco, double epoch, double inclo, double& no, + char& method, + double& ainv, double& ao, double& con41, double& con42, double& cosio, + double& cosio2,double& eccsq, double& omeosq, double& posq, + double& rp, double& rteosq,double& sinio , double& gsto + ); + +/* ----------------------------------------------------------------------------- +* +* procedure dpper +* +* this procedure provides deep space long period periodic contributions +* to the mean elements. by design, these periodics are zero at epoch. +* this used to be dscom which included initialization, but it's really a +* recurring function. +* +* author : david vallado 719-573-2600 28 jun 2005 +* +* inputs : +* e3 - +* ee2 - +* peo - +* pgho - +* pho - +* pinco - +* plo - +* se2 , se3 , sgh2, sgh3, sgh4, sh2, sh3, si2, si3, sl2, sl3, sl4 - +* t - +* xh2, xh3, xi2, xi3, xl2, xl3, xl4 - +* zmol - +* zmos - +* ep - eccentricity 0.0 - 1.0 +* inclo - inclination - needed for lyddane modification +* nodep - right ascension of ascending node +* argpp - argument of perigee +* mp - mean anomaly +* +* outputs : +* ep - eccentricity 0.0 - 1.0 +* inclp - inclination +* nodep - right ascension of ascending node +* argpp - argument of perigee +* mp - mean anomaly +* +* locals : +* alfdp - +* betdp - +* cosip , sinip , cosop , sinop , +* dalf - +* dbet - +* dls - +* f2, f3 - +* pe - +* pgh - +* ph - +* pinc - +* pl - +* sel , ses , sghl , sghs , shl , shs , sil , sinzf , sis , +* sll , sls +* xls - +* xnoh - +* zf - +* zm - +* +* coupling : +* none. +* +* references : +* hoots, roehrich, norad spacetrack report #3 1980 +* hoots, norad spacetrack report #6 1986 +* hoots, schumacher and glover 2004 +* vallado, crawford, hujsak, kelso 2006 + ----------------------------------------------------------------------------*/ + +static void dpper + ( + double e3, double ee2, double peo, double pgho, double pho, + double pinco, double plo, double se2, double se3, double sgh2, + double sgh3, double sgh4, double sh2, double sh3, double si2, + double si3, double sl2, double sl3, double sl4, double t, + double xgh2, double xgh3, double xgh4, double xh2, double xh3, + double xi2, double xi3, double xl2, double xl3, double xl4, + double zmol, double zmos, double inclo, + char init, + double& ep, double& inclp, double& nodep, double& argpp, double& mp + ) +{ + /* --------------------- local variables ------------------------ */ + const double twopi = 2.0 * pi; + double alfdp, betdp, cosip, cosop, dalf, dbet, dls, + f2, f3, pe, pgh, ph, pinc, pl , + sel, ses, sghl, sghs, shll, shs, sil, + sinip, sinop, sinzf, sis, sll, sls, xls, + xnoh, zf, zm, zel, zes, znl, zns; + + /* ---------------------- constants ----------------------------- */ + zns = 1.19459e-5; + zes = 0.01675; + znl = 1.5835218e-4; + zel = 0.05490; + + /* --------------- calculate time varying periodics ----------- */ + zm = zmos + zns * t; + // be sure that the initial call has time set to zero + if (init == 'y') + zm = zmos; + zf = zm + 2.0 * zes * sin(zm); + sinzf = sin(zf); + f2 = 0.5 * sinzf * sinzf - 0.25; + f3 = -0.5 * sinzf * cos(zf); + ses = se2* f2 + se3 * f3; + sis = si2 * f2 + si3 * f3; + sls = sl2 * f2 + sl3 * f3 + sl4 * sinzf; + sghs = sgh2 * f2 + sgh3 * f3 + sgh4 * sinzf; + shs = sh2 * f2 + sh3 * f3; + zm = zmol + znl * t; + if (init == 'y') + zm = zmol; + zf = zm + 2.0 * zel * sin(zm); + sinzf = sin(zf); + f2 = 0.5 * sinzf * sinzf - 0.25; + f3 = -0.5 * sinzf * cos(zf); + sel = ee2 * f2 + e3 * f3; + sil = xi2 * f2 + xi3 * f3; + sll = xl2 * f2 + xl3 * f3 + xl4 * sinzf; + sghl = xgh2 * f2 + xgh3 * f3 + xgh4 * sinzf; + shll = xh2 * f2 + xh3 * f3; + pe = ses + sel; + pinc = sis + sil; + pl = sls + sll; + pgh = sghs + sghl; + ph = shs + shll; + + if (init == 'n') + { + pe = pe - peo; + pinc = pinc - pinco; + pl = pl - plo; + pgh = pgh - pgho; + ph = ph - pho; + inclp = inclp + pinc; + ep = ep + pe; + sinip = sin(inclp); + cosip = cos(inclp); + + /* ----------------- apply periodics directly ------------ */ + // sgp4fix for lyddane choice + // strn3 used original inclination - this is technically feasible + // gsfc used perturbed inclination - also technically feasible + // probably best to readjust the 0.2 limit value and limit discontinuity + // 0.2 rad = 11.45916 deg + // use next line for original strn3 approach and original inclination + // if (inclo >= 0.2) + // use next line for gsfc version and perturbed inclination + if (inclp >= 0.2) + { + ph = ph / sinip; + pgh = pgh - cosip * ph; + argpp = argpp + pgh; + nodep = nodep + ph; + mp = mp + pl; + } + else + { + /* ---- apply periodics with lyddane modification ---- */ + sinop = sin(nodep); + cosop = cos(nodep); + alfdp = sinip * sinop; + betdp = sinip * cosop; + dalf = ph * cosop + pinc * cosip * sinop; + dbet = -ph * sinop + pinc * cosip * cosop; + alfdp = alfdp + dalf; + betdp = betdp + dbet; + nodep = fmod(nodep, twopi); + // sgp4fix for afspc written intrinsic functions + // nodep used without a trigonometric function ahead + if (nodep < 0.0) + nodep = nodep + twopi; + xls = mp + argpp + cosip * nodep; + dls = pl + pgh - pinc * nodep * sinip; + xls = xls + dls; + xnoh = nodep; + nodep = atan2(alfdp, betdp); + // sgp4fix for afspc written intrinsic functions + // nodep used without a trigonometric function ahead + if (nodep < 0.0) + nodep = nodep + twopi; + if (fabs(xnoh - nodep) > pi){ + if (nodep < xnoh) + nodep = nodep + twopi; + else + nodep = nodep - twopi; + } + mp = mp + pl; + argpp = xls - mp - cosip * nodep; + } + } // if init == 'n' + +//#include "debug1.cpp" +} // end dpper + +/*----------------------------------------------------------------------------- +* +* procedure dscom +* +* this procedure provides deep space common items used by both the secular +* and periodics subroutines. input is provided as shown. this routine +* used to be called dpper, but the functions inside weren't well organized. +* +* author : david vallado 719-573-2600 28 jun 2005 +* +* inputs : +* epoch - +* ep - eccentricity +* argpp - argument of perigee +* tc - +* inclp - inclination +* nodep - right ascension of ascending node +* np - mean motion +* +* outputs : +* sinim , cosim , sinomm , cosomm , snodm , cnodm +* day - +* e3 - +* ee2 - +* em - eccentricity +* emsq - eccentricity squared +* gam - +* peo - +* pgho - +* pho - +* pinco - +* plo - +* rtemsq - +* se2, se3 - +* sgh2, sgh3, sgh4 - +* sh2, sh3, si2, si3, sl2, sl3, sl4 - +* s1, s2, s3, s4, s5, s6, s7 - +* ss1, ss2, ss3, ss4, ss5, ss6, ss7, sz1, sz2, sz3 - +* sz11, sz12, sz13, sz21, sz22, sz23, sz31, sz32, sz33 - +* xgh2, xgh3, xgh4, xh2, xh3, xi2, xi3, xl2, xl3, xl4 - +* nm - mean motion +* z1, z2, z3, z11, z12, z13, z21, z22, z23, z31, z32, z33 - +* zmol - +* zmos - +* +* locals : +* a1, a2, a3, a4, a5, a6, a7, a8, a9, a10 - +* betasq - +* cc - +* ctem, stem - +* x1, x2, x3, x4, x5, x6, x7, x8 - +* xnodce - +* xnoi - +* zcosg , zsing , zcosgl , zsingl , zcosh , zsinh , zcoshl , zsinhl , +* zcosi , zsini , zcosil , zsinil , +* zx - +* zy - +* +* coupling : +* none. +* +* references : +* hoots, roehrich, norad spacetrack report #3 1980 +* hoots, norad spacetrack report #6 1986 +* hoots, schumacher and glover 2004 +* vallado, crawford, hujsak, kelso 2006 + ----------------------------------------------------------------------------*/ + +static void dscom + ( + double epoch, double ep, double argpp, double tc, double inclp, + double nodep, double np, + double& snodm, double& cnodm, double& sinim, double& cosim, double& sinomm, + double& cosomm,double& day, double& e3, double& ee2, double& em, + double& emsq, double& gam, double& peo, double& pgho, double& pho, + double& pinco, double& plo, double& rtemsq, double& se2, double& se3, + double& sgh2, double& sgh3, double& sgh4, double& sh2, double& sh3, + double& si2, double& si3, double& sl2, double& sl3, double& sl4, + double& s1, double& s2, double& s3, double& s4, double& s5, + double& s6, double& s7, double& ss1, double& ss2, double& ss3, + double& ss4, double& ss5, double& ss6, double& ss7, double& sz1, + double& sz2, double& sz3, double& sz11, double& sz12, double& sz13, + double& sz21, double& sz22, double& sz23, double& sz31, double& sz32, + double& sz33, double& xgh2, double& xgh3, double& xgh4, double& xh2, + double& xh3, double& xi2, double& xi3, double& xl2, double& xl3, + double& xl4, double& nm, double& z1, double& z2, double& z3, + double& z11, double& z12, double& z13, double& z21, double& z22, + double& z23, double& z31, double& z32, double& z33, double& zmol, + double& zmos + ) +{ + /* -------------------------- constants ------------------------- */ + const double zes = 0.01675; + const double zel = 0.05490; + const double c1ss = 2.9864797e-6; + const double c1l = 4.7968065e-7; + const double zsinis = 0.39785416; + const double zcosis = 0.91744867; + const double zcosgs = 0.1945905; + const double zsings = -0.98088458; + const double twopi = 2.0 * pi; + + /* --------------------- local variables ------------------------ */ + int lsflg; + double a1 , a2 , a3 , a4 , a5 , a6 , a7 , + a8 , a9 , a10 , betasq, cc , ctem , stem , + x1 , x2 , x3 , x4 , x5 , x6 , x7 , + x8 , xnodce, xnoi , zcosg , zcosgl, zcosh , zcoshl, + zcosi , zcosil, zsing , zsingl, zsinh , zsinhl, zsini , + zsinil, zx , zy; + + nm = np; + em = ep; + snodm = sin(nodep); + cnodm = cos(nodep); + sinomm = sin(argpp); + cosomm = cos(argpp); + sinim = sin(inclp); + cosim = cos(inclp); + emsq = em * em; + betasq = 1.0 - emsq; + rtemsq = sqrt(betasq); + + /* ----------------- initialize lunar solar terms --------------- */ + peo = 0.0; + pinco = 0.0; + plo = 0.0; + pgho = 0.0; + pho = 0.0; + day = epoch + 18261.5 + tc / 1440.0; + xnodce = fmod(4.5236020 - 9.2422029e-4 * day, twopi); + stem = sin(xnodce); + ctem = cos(xnodce); + zcosil = 0.91375164 - 0.03568096 * ctem; + zsinil = sqrt(1.0 - zcosil * zcosil); + zsinhl = 0.089683511 * stem / zsinil; + zcoshl = sqrt(1.0 - zsinhl * zsinhl); + gam = 5.8351514 + 0.0019443680 * day; + zx = 0.39785416 * stem / zsinil; + zy = zcoshl * ctem + 0.91744867 * zsinhl * stem; + zx = atan2(zx, zy); + zx = gam + zx - xnodce; + zcosgl = cos(zx); + zsingl = sin(zx); + + /* ------------------------- do solar terms --------------------- */ + zcosg = zcosgs; + zsing = zsings; + zcosi = zcosis; + zsini = zsinis; + zcosh = cnodm; + zsinh = snodm; + cc = c1ss; + xnoi = 1.0 / nm; + + for (lsflg = 1; lsflg <= 2; lsflg++) + { + a1 = zcosg * zcosh + zsing * zcosi * zsinh; + a3 = -zsing * zcosh + zcosg * zcosi * zsinh; + a7 = -zcosg * zsinh + zsing * zcosi * zcosh; + a8 = zsing * zsini; + a9 = zsing * zsinh + zcosg * zcosi * zcosh; + a10 = zcosg * zsini; + a2 = cosim * a7 + sinim * a8; + a4 = cosim * a9 + sinim * a10; + a5 = -sinim * a7 + cosim * a8; + a6 = -sinim * a9 + cosim * a10; + + x1 = a1 * cosomm + a2 * sinomm; + x2 = a3 * cosomm + a4 * sinomm; + x3 = -a1 * sinomm + a2 * cosomm; + x4 = -a3 * sinomm + a4 * cosomm; + x5 = a5 * sinomm; + x6 = a6 * sinomm; + x7 = a5 * cosomm; + x8 = a6 * cosomm; + + z31 = 12.0 * x1 * x1 - 3.0 * x3 * x3; + z32 = 24.0 * x1 * x2 - 6.0 * x3 * x4; + z33 = 12.0 * x2 * x2 - 3.0 * x4 * x4; + z1 = 3.0 * (a1 * a1 + a2 * a2) + z31 * emsq; + z2 = 6.0 * (a1 * a3 + a2 * a4) + z32 * emsq; + z3 = 3.0 * (a3 * a3 + a4 * a4) + z33 * emsq; + z11 = -6.0 * a1 * a5 + emsq * (-24.0 * x1 * x7-6.0 * x3 * x5); + z12 = -6.0 * (a1 * a6 + a3 * a5) + emsq * + (-24.0 * (x2 * x7 + x1 * x8) - 6.0 * (x3 * x6 + x4 * x5)); + z13 = -6.0 * a3 * a6 + emsq * (-24.0 * x2 * x8 - 6.0 * x4 * x6); + z21 = 6.0 * a2 * a5 + emsq * (24.0 * x1 * x5 - 6.0 * x3 * x7); + z22 = 6.0 * (a4 * a5 + a2 * a6) + emsq * + (24.0 * (x2 * x5 + x1 * x6) - 6.0 * (x4 * x7 + x3 * x8)); + z23 = 6.0 * a4 * a6 + emsq * (24.0 * x2 * x6 - 6.0 * x4 * x8); + z1 = z1 + z1 + betasq * z31; + z2 = z2 + z2 + betasq * z32; + z3 = z3 + z3 + betasq * z33; + s3 = cc * xnoi; + s2 = -0.5 * s3 / rtemsq; + s4 = s3 * rtemsq; + s1 = -15.0 * em * s4; + s5 = x1 * x3 + x2 * x4; + s6 = x2 * x3 + x1 * x4; + s7 = x2 * x4 - x1 * x3; + + /* ----------------------- do lunar terms ------------------- */ + if (lsflg == 1) + { + ss1 = s1; + ss2 = s2; + ss3 = s3; + ss4 = s4; + ss5 = s5; + ss6 = s6; + ss7 = s7; + sz1 = z1; + sz2 = z2; + sz3 = z3; + sz11 = z11; + sz12 = z12; + sz13 = z13; + sz21 = z21; + sz22 = z22; + sz23 = z23; + sz31 = z31; + sz32 = z32; + sz33 = z33; + zcosg = zcosgl; + zsing = zsingl; + zcosi = zcosil; + zsini = zsinil; + zcosh = zcoshl * cnodm + zsinhl * snodm; + zsinh = snodm * zcoshl - cnodm * zsinhl; + cc = c1l; + } + } + + zmol = fmod(4.7199672 + 0.22997150 * day - gam, twopi); + zmos = fmod(6.2565837 + 0.017201977 * day, twopi); + + /* ------------------------ do solar terms ---------------------- */ + se2 = 2.0 * ss1 * ss6; + se3 = 2.0 * ss1 * ss7; + si2 = 2.0 * ss2 * sz12; + si3 = 2.0 * ss2 * (sz13 - sz11); + sl2 = -2.0 * ss3 * sz2; + sl3 = -2.0 * ss3 * (sz3 - sz1); + sl4 = -2.0 * ss3 * (-21.0 - 9.0 * emsq) * zes; + sgh2 = 2.0 * ss4 * sz32; + sgh3 = 2.0 * ss4 * (sz33 - sz31); + sgh4 = -18.0 * ss4 * zes; + sh2 = -2.0 * ss2 * sz22; + sh3 = -2.0 * ss2 * (sz23 - sz21); + + /* ------------------------ do lunar terms ---------------------- */ + ee2 = 2.0 * s1 * s6; + e3 = 2.0 * s1 * s7; + xi2 = 2.0 * s2 * z12; + xi3 = 2.0 * s2 * (z13 - z11); + xl2 = -2.0 * s3 * z2; + xl3 = -2.0 * s3 * (z3 - z1); + xl4 = -2.0 * s3 * (-21.0 - 9.0 * emsq) * zel; + xgh2 = 2.0 * s4 * z32; + xgh3 = 2.0 * s4 * (z33 - z31); + xgh4 = -18.0 * s4 * zel; + xh2 = -2.0 * s2 * z22; + xh3 = -2.0 * s2 * (z23 - z21); + +//#include "debug2.cpp" +} // end dscom + +/*----------------------------------------------------------------------------- +* +* procedure dsinit +* +* this procedure provides deep space contributions to mean motion dot due +* to geopotential resonance with half day and one day orbits. +* +* author : david vallado 719-573-2600 28 jun 2005 +* +* inputs : +* cosim, sinim- +* emsq - eccentricity squared +* argpo - argument of perigee +* s1, s2, s3, s4, s5 - +* ss1, ss2, ss3, ss4, ss5 - +* sz1, sz3, sz11, sz13, sz21, sz23, sz31, sz33 - +* t - time +* tc - +* gsto - greenwich sidereal time rad +* mo - mean anomaly +* mdot - mean anomaly dot (rate) +* no - mean motion +* nodeo - right ascension of ascending node +* nodedot - right ascension of ascending node dot (rate) +* xpidot - +* z1, z3, z11, z13, z21, z23, z31, z33 - +* eccm - eccentricity +* argpm - argument of perigee +* inclm - inclination +* mm - mean anomaly +* xn - mean motion +* nodem - right ascension of ascending node +* +* outputs : +* em - eccentricity +* argpm - argument of perigee +* inclm - inclination +* mm - mean anomaly +* nm - mean motion +* nodem - right ascension of ascending node +* irez - flag for resonance 0-none, 1-one day, 2-half day +* atime - +* d2201, d2211, d3210, d3222, d4410, d4422, d5220, d5232, d5421, d5433 - +* dedt - +* didt - +* dmdt - +* dndt - +* dnodt - +* domdt - +* del1, del2, del3 - +* ses , sghl , sghs , sgs , shl , shs , sis , sls +* theta - +* xfact - +* xlamo - +* xli - +* xni +* +* locals : +* ainv2 - +* aonv - +* cosisq - +* eoc - +* f220, f221, f311, f321, f322, f330, f441, f442, f522, f523, f542, f543 - +* g200, g201, g211, g300, g310, g322, g410, g422, g520, g521, g532, g533 - +* sini2 - +* temp - +* temp1 - +* theta - +* xno2 - +* +* coupling : +* getgravconst +* +* references : +* hoots, roehrich, norad spacetrack report #3 1980 +* hoots, norad spacetrack report #6 1986 +* hoots, schumacher and glover 2004 +* vallado, crawford, hujsak, kelso 2006 + ----------------------------------------------------------------------------*/ + +static void dsinit + ( + gravconsttype whichconst, + double cosim, double emsq, double argpo, double s1, double s2, + double s3, double s4, double s5, double sinim, double ss1, + double ss2, double ss3, double ss4, double ss5, double sz1, + double sz3, double sz11, double sz13, double sz21, double sz23, + double sz31, double sz33, double t, double tc, double gsto, + double mo, double mdot, double no, double nodeo, double nodedot, + double xpidot, double z1, double z3, double z11, double z13, + double z21, double z23, double z31, double z33, double ecco, + double eccsq, double& em, double& argpm, double& inclm, double& mm, + double& nm, double& nodem, + int& irez, + double& atime, double& d2201, double& d2211, double& d3210, double& d3222, + double& d4410, double& d4422, double& d5220, double& d5232, double& d5421, + double& d5433, double& dedt, double& didt, double& dmdt, double& dndt, + double& dnodt, double& domdt, double& del1, double& del2, double& del3, + double& xfact, double& xlamo, double& xli, double& xni + ) +{ + /* --------------------- local variables ------------------------ */ + const double twopi = 2.0 * pi; + + double ainv2 , aonv=0.0, cosisq, eoc, f220 , f221 , f311 , + f321 , f322 , f330 , f441 , f442 , f522 , f523 , + f542 , f543 , g200 , g201 , g211 , g300 , g310 , + g322 , g410 , g422 , g520 , g521 , g532 , g533 , + ses , sgs , sghl , sghs , shs , shll , sis , + sini2 , sls , temp , temp1 , theta , xno2 , q22 , + q31 , q33 , root22, root44, root54, rptim , root32, + root52, x2o3 , xke , znl , emo , zns , emsqo, + tumin, mu, radiusearthkm, j2, j3, j4, j3oj2; + + q22 = 1.7891679e-6; + q31 = 2.1460748e-6; + q33 = 2.2123015e-7; + root22 = 1.7891679e-6; + root44 = 7.3636953e-9; + root54 = 2.1765803e-9; + rptim = 4.37526908801129966e-3; // this equates to 7.29211514668855e-5 rad/sec + root32 = 3.7393792e-7; + root52 = 1.1428639e-7; + x2o3 = 2.0 / 3.0; + znl = 1.5835218e-4; + zns = 1.19459e-5; + + // sgp4fix identify constants and allow alternate values + getgravconst( whichconst, tumin, mu, radiusearthkm, xke, j2, j3, j4, j3oj2 ); + + /* -------------------- deep space initialization ------------ */ + irez = 0; + if ((nm < 0.0052359877) && (nm > 0.0034906585)) + irez = 1; + if ((nm >= 8.26e-3) && (nm <= 9.24e-3) && (em >= 0.5)) + irez = 2; + + /* ------------------------ do solar terms ------------------- */ + ses = ss1 * zns * ss5; + sis = ss2 * zns * (sz11 + sz13); + sls = -zns * ss3 * (sz1 + sz3 - 14.0 - 6.0 * emsq); + sghs = ss4 * zns * (sz31 + sz33 - 6.0); + shs = -zns * ss2 * (sz21 + sz23); + // sgp4fix for 180 deg incl + if ((inclm < 5.2359877e-2) || (inclm > pi - 5.2359877e-2)) + shs = 0.0; + if (sinim != 0.0) + shs = shs / sinim; + sgs = sghs - cosim * shs; + + /* ------------------------- do lunar terms ------------------ */ + dedt = ses + s1 * znl * s5; + didt = sis + s2 * znl * (z11 + z13); + dmdt = sls - znl * s3 * (z1 + z3 - 14.0 - 6.0 * emsq); + sghl = s4 * znl * (z31 + z33 - 6.0); + shll = -znl * s2 * (z21 + z23); + // sgp4fix for 180 deg incl + if ((inclm < 5.2359877e-2) || (inclm > pi - 5.2359877e-2)) + shll = 0.0; + domdt = sgs + sghl; + dnodt = shs; + if (sinim != 0.0) + { + domdt = domdt - cosim / sinim * shll; + dnodt = dnodt + shll / sinim; + } + + /* ----------- calculate deep space resonance effects -------- */ + dndt = 0.0; + theta = fmod(gsto + tc * rptim, twopi); + em = em + dedt * t; + inclm = inclm + didt * t; + argpm = argpm + domdt * t; + nodem = nodem + dnodt * t; + mm = mm + dmdt * t; + // sgp4fix for negative inclinations + // the following if statement should be commented out + //if (inclm < 0.0) + // { + // inclm = -inclm; + // argpm = argpm - pi; + // nodem = nodem + pi; + // } + + /* -------------- initialize the resonance terms ------------- */ + if (irez != 0) + { + aonv = pow(nm / xke, x2o3); + + /* ---------- geopotential resonance for 12 hour orbits ------ */ + if (irez == 2) + { + cosisq = cosim * cosim; + emo = em; + em = ecco; + emsqo = emsq; + emsq = eccsq; + eoc = em * emsq; + g201 = -0.306 - (em - 0.64) * 0.440; + + if (em <= 0.65) + { + g211 = 3.616 - 13.2470 * em + 16.2900 * emsq; + g310 = -19.302 + 117.3900 * em - 228.4190 * emsq + 156.5910 * eoc; + g322 = -18.9068 + 109.7927 * em - 214.6334 * emsq + 146.5816 * eoc; + g410 = -41.122 + 242.6940 * em - 471.0940 * emsq + 313.9530 * eoc; + g422 = -146.407 + 841.8800 * em - 1629.014 * emsq + 1083.4350 * eoc; + g520 = -532.114 + 3017.977 * em - 5740.032 * emsq + 3708.2760 * eoc; + } + else + { + g211 = -72.099 + 331.819 * em - 508.738 * emsq + 266.724 * eoc; + g310 = -346.844 + 1582.851 * em - 2415.925 * emsq + 1246.113 * eoc; + g322 = -342.585 + 1554.908 * em - 2366.899 * emsq + 1215.972 * eoc; + g410 = -1052.797 + 4758.686 * em - 7193.992 * emsq + 3651.957 * eoc; + g422 = -3581.690 + 16178.110 * em - 24462.770 * emsq + 12422.520 * eoc; + if (em > 0.715) + g520 =-5149.66 + 29936.92 * em - 54087.36 * emsq + 31324.56 * eoc; + else + g520 = 1464.74 - 4664.75 * em + 3763.64 * emsq; + } + if (em < 0.7) + { + g533 = -919.22770 + 4988.6100 * em - 9064.7700 * emsq + 5542.21 * eoc; + g521 = -822.71072 + 4568.6173 * em - 8491.4146 * emsq + 5337.524 * eoc; + g532 = -853.66600 + 4690.2500 * em - 8624.7700 * emsq + 5341.4 * eoc; + } + else + { + g533 =-37995.780 + 161616.52 * em - 229838.20 * emsq + 109377.94 * eoc; + g521 =-51752.104 + 218913.95 * em - 309468.16 * emsq + 146349.42 * eoc; + g532 =-40023.880 + 170470.89 * em - 242699.48 * emsq + 115605.82 * eoc; + } + + sini2= sinim * sinim; + f220 = 0.75 * (1.0 + 2.0 * cosim+cosisq); + f221 = 1.5 * sini2; + f321 = 1.875 * sinim * (1.0 - 2.0 * cosim - 3.0 * cosisq); + f322 = -1.875 * sinim * (1.0 + 2.0 * cosim - 3.0 * cosisq); + f441 = 35.0 * sini2 * f220; + f442 = 39.3750 * sini2 * sini2; + f522 = 9.84375 * sinim * (sini2 * (1.0 - 2.0 * cosim- 5.0 * cosisq) + + 0.33333333 * (-2.0 + 4.0 * cosim + 6.0 * cosisq) ); + f523 = sinim * (4.92187512 * sini2 * (-2.0 - 4.0 * cosim + + 10.0 * cosisq) + 6.56250012 * (1.0+2.0 * cosim - 3.0 * cosisq)); + f542 = 29.53125 * sinim * (2.0 - 8.0 * cosim+cosisq * + (-12.0 + 8.0 * cosim + 10.0 * cosisq)); + f543 = 29.53125 * sinim * (-2.0 - 8.0 * cosim+cosisq * + (12.0 + 8.0 * cosim - 10.0 * cosisq)); + xno2 = nm * nm; + ainv2 = aonv * aonv; + temp1 = 3.0 * xno2 * ainv2; + temp = temp1 * root22; + d2201 = temp * f220 * g201; + d2211 = temp * f221 * g211; + temp1 = temp1 * aonv; + temp = temp1 * root32; + d3210 = temp * f321 * g310; + d3222 = temp * f322 * g322; + temp1 = temp1 * aonv; + temp = 2.0 * temp1 * root44; + d4410 = temp * f441 * g410; + d4422 = temp * f442 * g422; + temp1 = temp1 * aonv; + temp = temp1 * root52; + d5220 = temp * f522 * g520; + d5232 = temp * f523 * g532; + temp = 2.0 * temp1 * root54; + d5421 = temp * f542 * g521; + d5433 = temp * f543 * g533; + xlamo = fmod(mo + nodeo + nodeo-theta - theta, twopi); + xfact = mdot + dmdt + 2.0 * (nodedot + dnodt - rptim) - no; + em = emo; + emsq = emsqo; + } + + /* ---------------- synchronous resonance terms -------------- */ + if (irez == 1) + { + g200 = 1.0 + emsq * (-2.5 + 0.8125 * emsq); + g310 = 1.0 + 2.0 * emsq; + g300 = 1.0 + emsq * (-6.0 + 6.60937 * emsq); + f220 = 0.75 * (1.0 + cosim) * (1.0 + cosim); + f311 = 0.9375 * sinim * sinim * (1.0 + 3.0 * cosim) - 0.75 * (1.0 + cosim); + f330 = 1.0 + cosim; + f330 = 1.875 * f330 * f330 * f330; + del1 = 3.0 * nm * nm * aonv * aonv; + del2 = 2.0 * del1 * f220 * g200 * q22; + del3 = 3.0 * del1 * f330 * g300 * q33 * aonv; + del1 = del1 * f311 * g310 * q31 * aonv; + xlamo = fmod(mo + nodeo + argpo - theta, twopi); + xfact = mdot + xpidot - rptim + dmdt + domdt + dnodt - no; + } + + /* ------------ for sgp4, initialize the integrator ---------- */ + xli = xlamo; + xni = no; + atime = 0.0; + nm = no + dndt; + } + +//#include "debug3.cpp" +} // end dsinit + +/*----------------------------------------------------------------------------- +* +* procedure dspace +* +* this procedure provides deep space contributions to mean elements for +* perturbing third body. these effects have been averaged over one +* revolution of the sun and moon. for earth resonance effects, the +* effects have been averaged over no revolutions of the satellite. +* (mean motion) +* +* author : david vallado 719-573-2600 28 jun 2005 +* +* inputs : +* d2201, d2211, d3210, d3222, d4410, d4422, d5220, d5232, d5421, d5433 - +* dedt - +* del1, del2, del3 - +* didt - +* dmdt - +* dnodt - +* domdt - +* irez - flag for resonance 0-none, 1-one day, 2-half day +* argpo - argument of perigee +* argpdot - argument of perigee dot (rate) +* t - time +* tc - +* gsto - gst +* xfact - +* xlamo - +* no - mean motion +* atime - +* em - eccentricity +* ft - +* argpm - argument of perigee +* inclm - inclination +* xli - +* mm - mean anomaly +* xni - mean motion +* nodem - right ascension of ascending node +* +* outputs : +* atime - +* em - eccentricity +* argpm - argument of perigee +* inclm - inclination +* xli - +* mm - mean anomaly +* xni - +* nodem - right ascension of ascending node +* dndt - +* nm - mean motion +* +* locals : +* delt - +* ft - +* theta - +* x2li - +* x2omi - +* xl - +* xldot - +* xnddt - +* xndt - +* xomi - +* +* coupling : +* none - +* +* references : +* hoots, roehrich, norad spacetrack report #3 1980 +* hoots, norad spacetrack report #6 1986 +* hoots, schumacher and glover 2004 +* vallado, crawford, hujsak, kelso 2006 + ----------------------------------------------------------------------------*/ + +static void dspace + ( + int irez, + double d2201, double d2211, double d3210, double d3222, double d4410, + double d4422, double d5220, double d5232, double d5421, double d5433, + double dedt, double del1, double del2, double del3, double didt, + double dmdt, double dnodt, double domdt, double argpo, double argpdot, + double t, double tc, double gsto, double xfact, double xlamo, + double no, + double& atime, double& em, double& argpm, double& inclm, double& xli, + double& mm, double& xni, double& nodem, double& dndt, double& nm + ) +{ + const double twopi = 2.0 * pi; + int iretn , iret; + double delt, ft, theta, x2li, x2omi, xl, xldot , xnddt, xndt, xomi, g22, g32, + g44, g52, g54, fasx2, fasx4, fasx6, rptim , step2, stepn , stepp; + + ft = 0.0; + fasx2 = 0.13130908; + fasx4 = 2.8843198; + fasx6 = 0.37448087; + g22 = 5.7686396; + g32 = 0.95240898; + g44 = 1.8014998; + g52 = 1.0508330; + g54 = 4.4108898; + rptim = 4.37526908801129966e-3; // this equates to 7.29211514668855e-5 rad/sec + stepp = 720.0; + stepn = -720.0; + step2 = 259200.0; + + /* ----------- calculate deep space resonance effects ----------- */ + dndt = 0.0; + theta = fmod(gsto + tc * rptim, twopi); + em = em + dedt * t; + + inclm = inclm + didt * t; + argpm = argpm + domdt * t; + nodem = nodem + dnodt * t; + mm = mm + dmdt * t; + + // sgp4fix for negative inclinations + // the following if statement should be commented out + // if (inclm < 0.0) + // { + // inclm = -inclm; + // argpm = argpm - pi; + // nodem = nodem + pi; + // } + + /* - update resonances : numerical (euler-maclaurin) integration - */ + /* ------------------------- epoch restart ---------------------- */ + // sgp4fix for propagator problems + // the following integration works for negative time steps and periods + // the specific changes are unknown because the original code was so convoluted + + ft = 0.0; + atime = 0.0; + if (irez != 0) + { + if ((atime == 0.0) || ((t >= 0.0) && (atime < 0.0)) || + ((t < 0.0) && (atime >= 0.0))) + { + if (t >= 0.0) + delt = stepp; + else + delt = stepn; + atime = 0.0; + xni = no; + xli = xlamo; + } + iretn = 381; // added for do loop + iret = 0; // added for loop + while (iretn == 381) + { + if ((fabs(t) < fabs(atime)) || (iret == 351)) + { + if (t >= 0.0) + delt = stepn; + else + delt = stepp; + iret = 351; + iretn = 381; + } + else + { + if (t > 0.0) // error if prev if has atime:=0.0 and t:=0.0 (ge) + delt = stepp; + else + delt = stepn; + if (fabs(t - atime) >= stepp) + { + iret = 0; + iretn = 381; + } + else + { + ft = t - atime; + iretn = 0; + } + } + + /* ------------------- dot terms calculated ------------- */ + /* ----------- near - synchronous resonance terms ------- */ + if (irez != 2) + { + xndt = del1 * sin(xli - fasx2) + del2 * sin(2.0 * (xli - fasx4)) + + del3 * sin(3.0 * (xli - fasx6)); + xldot = xni + xfact; + xnddt = del1 * cos(xli - fasx2) + + 2.0 * del2 * cos(2.0 * (xli - fasx4)) + + 3.0 * del3 * cos(3.0 * (xli - fasx6)); + xnddt = xnddt * xldot; + } + else + { + /* --------- near - half-day resonance terms -------- */ + xomi = argpo + argpdot * atime; + x2omi = xomi + xomi; + x2li = xli + xli; + xndt = d2201 * sin(x2omi + xli - g22) + d2211 * sin(xli - g22) + + d3210 * sin(xomi + xli - g32) + d3222 * sin(-xomi + xli - g32)+ + d4410 * sin(x2omi + x2li - g44)+ d4422 * sin(x2li - g44) + + d5220 * sin(xomi + xli - g52) + d5232 * sin(-xomi + xli - g52)+ + d5421 * sin(xomi + x2li - g54) + d5433 * sin(-xomi + x2li - g54); + xldot = xni + xfact; + xnddt = d2201 * cos(x2omi + xli - g22) + d2211 * cos(xli - g22) + + d3210 * cos(xomi + xli - g32) + d3222 * cos(-xomi + xli - g32) + + d5220 * cos(xomi + xli - g52) + d5232 * cos(-xomi + xli - g52) + + 2.0 * (d4410 * cos(x2omi + x2li - g44) + + d4422 * cos(x2li - g44) + d5421 * cos(xomi + x2li - g54) + + d5433 * cos(-xomi + x2li - g54)); + xnddt = xnddt * xldot; + } + + /* ----------------------- integrator ------------------- */ + if (iretn == 381) + { + xli = xli + xldot * delt + xndt * step2; + xni = xni + xndt * delt + xnddt * step2; + atime = atime + delt; + } + } // while iretn = 381 + + nm = xni + xndt * ft + xnddt * ft * ft * 0.5; + xl = xli + xldot * ft + xndt * ft * ft * 0.5; + if (irez != 1) + { + mm = xl - 2.0 * nodem + 2.0 * theta; + dndt = nm - no; + } + else + { + mm = xl - nodem - argpm + theta; + dndt = nm - no; + } + nm = no + dndt; + } + +//#include "debug4.cpp" +} // end dsspace + +/*----------------------------------------------------------------------------- +* +* procedure initl +* +* this procedure initializes the spg4 propagator. all the initialization is +* consolidated here instead of having multiple loops inside other routines. +* +* author : david vallado 719-573-2600 28 jun 2005 +* +* inputs : +* ecco - eccentricity 0.0 - 1.0 +* epoch - epoch time in days from jan 0, 1950. 0 hr +* inclo - inclination of satellite +* no - mean motion of satellite +* satn - satellite number +* +* outputs : +* ainv - 1.0 / a +* ao - semi major axis +* con41 - +* con42 - 1.0 - 5.0 cos(i) +* cosio - cosine of inclination +* cosio2 - cosio squared +* eccsq - eccentricity squared +* method - flag for deep space 'd', 'n' +* omeosq - 1.0 - ecco * ecco +* posq - semi-parameter squared +* rp - radius of perigee +* rteosq - square root of (1.0 - ecco*ecco) +* sinio - sine of inclination +* gsto - gst at time of observation rad +* no - mean motion of satellite +* +* locals : +* ak - +* d1 - +* del - +* adel - +* po - +* +* coupling : +* getgravconst +* gstime - find greenwich sidereal time from the julian date +* +* references : +* hoots, roehrich, norad spacetrack report #3 1980 +* hoots, norad spacetrack report #6 1986 +* hoots, schumacher and glover 2004 +* vallado, crawford, hujsak, kelso 2006 + ----------------------------------------------------------------------------*/ + +static void initl + ( + int satn, gravconsttype whichconst, + double ecco, double epoch, double inclo, double& no, + char& method, + double& ainv, double& ao, double& con41, double& con42, double& cosio, + double& cosio2,double& eccsq, double& omeosq, double& posq, + double& rp, double& rteosq,double& sinio , double& gsto + ) +{ + /* --------------------- local variables ------------------------ */ + double ak, d1, del, adel, po, x2o3, j2, xke, + tumin, mu, radiusearthkm, j3, j4, j3oj2; + + // sgp4fix use old way of finding gst + int ids70; + double ts70, ds70, tfrac, c1, thgr70, fk5r, c1p2p; + const double twopi = 2.0 * pi; + + /* ----------------------- earth constants ---------------------- */ + // sgp4fix identify constants and allow alternate values + getgravconst( whichconst, tumin, mu, radiusearthkm, xke, j2, j3, j4, j3oj2 ); + x2o3 = 2.0 / 3.0; + + /* ------------- calculate auxillary epoch quantities ---------- */ + eccsq = ecco * ecco; + omeosq = 1.0 - eccsq; + rteosq = sqrt(omeosq); + cosio = cos(inclo); + cosio2 = cosio * cosio; + + /* ------------------ un-kozai the mean motion ----------------- */ + ak = pow(xke / no, x2o3); + d1 = 0.75 * j2 * (3.0 * cosio2 - 1.0) / (rteosq * omeosq); + del = d1 / (ak * ak); + adel = ak * (1.0 - del * del - del * + (1.0 / 3.0 + 134.0 * del * del / 81.0)); + del = d1/(adel * adel); + no = no / (1.0 + del); + + ao = pow(xke / no, x2o3); + sinio = sin(inclo); + po = ao * omeosq; + con42 = 1.0 - 5.0 * cosio2; + con41 = -con42-cosio2-cosio2; + ainv = 1.0 / ao; + posq = po * po; + rp = ao * (1.0 - ecco); + method = 'n'; + + // sgp4fix modern approach to finding sidereal timew + // gsto = gstime(epoch + 2433281.5); + + // sgp4fix use old way of finding gst + // count integer number of days from 0 jan 1970 + ts70 = epoch - 7305.0; + ids70 = floor(ts70 + 1.0e-8); + ds70 = ids70; + tfrac = ts70 - ds70; + // find greenwich location at epoch + c1 = 1.72027916940703639e-2; + thgr70= 1.7321343856509374; + fk5r = 5.07551419432269442e-15; + c1p2p = c1 + twopi; + gsto = fmod( thgr70 + c1*ds70 + c1p2p*tfrac + ts70*ts70*fk5r, twopi); + if ( gsto < 0.0 ) + gsto = gsto + twopi; + +//#include "debug5.cpp" +} // end initl + +/*----------------------------------------------------------------------------- +* +* procedure sgp4init +* +* this procedure initializes variables for sgp4. +* +* author : david vallado 719-573-2600 28 jun 2005 +* +* inputs : +* satn - satellite number +* bstar - sgp4 type drag coefficient kg/m2er +* ecco - eccentricity +* epoch - epoch time in days from jan 0, 1950. 0 hr +* argpo - argument of perigee (output if ds) +* inclo - inclination +* mo - mean anomaly (output if ds) +* no - mean motion +* nodeo - right ascension of ascending node +* +* outputs : +* satrec - common values for subsequent calls +* return code - non-zero on error. +* 1 - mean elements, ecc >= 1.0 or ecc < -0.001 or a < 0.95 er +* 2 - mean motion less than 0.0 +* 3 - pert elements, ecc < 0.0 or ecc > 1.0 +* 4 - semi-latus rectum < 0.0 +* 5 - epoch elements are sub-orbital +* 6 - satellite has decayed +* +* locals : +* cnodm , snodm , cosim , sinim , cosomm , sinomm +* cc1sq , cc2 , cc3 +* coef , coef1 +* cosio4 - +* day - +* dndt - +* em - eccentricity +* emsq - eccentricity squared +* eeta - +* etasq - +* gam - +* argpm - argument of perigee +* nodem - +* inclm - inclination +* mm - mean anomaly +* nm - mean motion +* perige - perigee +* pinvsq - +* psisq - +* qzms24 - +* rtemsq - +* s1, s2, s3, s4, s5, s6, s7 - +* sfour - +* ss1, ss2, ss3, ss4, ss5, ss6, ss7 - +* sz1, sz2, sz3 +* sz11, sz12, sz13, sz21, sz22, sz23, sz31, sz32, sz33 - +* tc - +* temp - +* temp1, temp2, temp3 - +* tsi - +* xpidot - +* xhdot1 - +* z1, z2, z3 - +* z11, z12, z13, z21, z22, z23, z31, z32, z33 - +* +* coupling : +* getgravconst- +* initl - +* dscom - +* dpper - +* dsinit - +* sgp4 - +* +* references : +* hoots, roehrich, norad spacetrack report #3 1980 +* hoots, norad spacetrack report #6 1986 +* hoots, schumacher and glover 2004 +* vallado, crawford, hujsak, kelso 2006 + ----------------------------------------------------------------------------*/ + +int sgp4init + ( + gravconsttype whichconst, const int satn, const double epoch, + const double xbstar, const double xecco, const double xargpo, + const double xinclo, const double xmo, const double xno, + const double xnodeo, elsetrec& satrec + ) +{ + /* --------------------- local variables ------------------------ */ + double ao, ainv, con42, cosio, sinio, cosio2, eccsq, + omeosq, posq, rp, rteosq, + cnodm , snodm , cosim , sinim , cosomm, sinomm, cc1sq , + cc2 , cc3 , coef , coef1 , cosio4, day , dndt , + em , emsq , eeta , etasq , gam , argpm , nodem , + inclm , mm , nm , perige, pinvsq, psisq , qzms24, + rtemsq, s1 , s2 , s3 , s4 , s5 , s6 , + s7 , sfour , ss1 = 0 , ss2 = 0 , ss3 = 0 , ss4 = 0 , ss5 = 0 , + ss6 = 0 , ss7 = 0 , sz1 = 0 , sz2 = 0 , sz3 = 0 , sz11 = 0 , sz12 = 0 , + sz13 = 0 , sz21 = 0 , sz22 = 0 , sz23 = 0 , sz31 = 0 , sz32 = 0 , sz33 = 0 , + tc , temp , temp1 , temp2 , temp3 , tsi , xpidot, + xhdot1, z1 , z2 , z3 , z11 , z12 , z13 , + z21 , z22 , z23 , z31 , z32 , z33, + qzms2t, ss, j2, j3oj2, j4, x2o3, r[3], v[3], + tumin, mu, radiusearthkm, xke, j3; + + /* ------------------------ initialization --------------------- */ + // sgp4fix divisor for divide by zero check on inclination + const double temp4 = 1.0 + cos(pi-1.0e-9); + + /* ----------- set all near earth variables to zero ------------ */ + satrec.isimp = 0; satrec.method = 'n'; satrec.aycof = 0.0; + satrec.con41 = 0.0; satrec.cc1 = 0.0; satrec.cc4 = 0.0; + satrec.cc5 = 0.0; satrec.d2 = 0.0; satrec.d3 = 0.0; + satrec.d4 = 0.0; satrec.delmo = 0.0; satrec.eta = 0.0; + satrec.argpdot = 0.0; satrec.omgcof = 0.0; satrec.sinmao = 0.0; + satrec.t = 0.0; satrec.t2cof = 0.0; satrec.t3cof = 0.0; + satrec.t4cof = 0.0; satrec.t5cof = 0.0; satrec.x1mth2 = 0.0; + satrec.x7thm1 = 0.0; satrec.mdot = 0.0; satrec.nodedot = 0.0; + satrec.xlcof = 0.0; satrec.xmcof = 0.0; satrec.nodecf = 0.0; + + /* ----------- set all deep space variables to zero ------------ */ + satrec.irez = 0; satrec.d2201 = 0.0; satrec.d2211 = 0.0; + satrec.d3210 = 0.0; satrec.d3222 = 0.0; satrec.d4410 = 0.0; + satrec.d4422 = 0.0; satrec.d5220 = 0.0; satrec.d5232 = 0.0; + satrec.d5421 = 0.0; satrec.d5433 = 0.0; satrec.dedt = 0.0; + satrec.del1 = 0.0; satrec.del2 = 0.0; satrec.del3 = 0.0; + satrec.didt = 0.0; satrec.dmdt = 0.0; satrec.dnodt = 0.0; + satrec.domdt = 0.0; satrec.e3 = 0.0; satrec.ee2 = 0.0; + satrec.peo = 0.0; satrec.pgho = 0.0; satrec.pho = 0.0; + satrec.pinco = 0.0; satrec.plo = 0.0; satrec.se2 = 0.0; + satrec.se3 = 0.0; satrec.sgh2 = 0.0; satrec.sgh3 = 0.0; + satrec.sgh4 = 0.0; satrec.sh2 = 0.0; satrec.sh3 = 0.0; + satrec.si2 = 0.0; satrec.si3 = 0.0; satrec.sl2 = 0.0; + satrec.sl3 = 0.0; satrec.sl4 = 0.0; satrec.gsto = 0.0; + satrec.xfact = 0.0; satrec.xgh2 = 0.0; satrec.xgh3 = 0.0; + satrec.xgh4 = 0.0; satrec.xh2 = 0.0; satrec.xh3 = 0.0; + satrec.xi2 = 0.0; satrec.xi3 = 0.0; satrec.xl2 = 0.0; + satrec.xl3 = 0.0; satrec.xl4 = 0.0; satrec.xlamo = 0.0; + satrec.zmol = 0.0; satrec.zmos = 0.0; satrec.atime = 0.0; + satrec.xli = 0.0; satrec.xni = 0.0; + + // sgp4fix - note the following variables are also passed directly via satrec. + // it is possible to streamline the sgp4init call by deleting the "x" + // variables, but the user would need to set the satrec.* values first. we + // include the additional assignments in case twoline2rv is not used. + satrec.bstar = xbstar; + satrec.ecco = xecco; + satrec.argpo = xargpo; + satrec.inclo = xinclo; + satrec.mo = xmo; + satrec.no = xno; + satrec.nodeo = xnodeo; + + /* ------------------------ earth constants ----------------------- */ + // sgp4fix identify constants and allow alternate values + getgravconst( whichconst, tumin, mu, radiusearthkm, xke, j2, j3, j4, j3oj2 ); + ss = 78.0 / radiusearthkm + 1.0; + qzms2t = pow(((120.0 - 78.0) / radiusearthkm), 4); + x2o3 = 2.0 / 3.0; + + satrec.init = 'y'; + satrec.t = 0.0; + + initl + ( + satn, whichconst, satrec.ecco, epoch, satrec.inclo, satrec.no, satrec.method, + ainv, ao, satrec.con41, con42, cosio, cosio2, eccsq, omeosq, + posq, rp, rteosq, sinio, satrec.gsto + ); + satrec.error = 0; + + if (rp < 1.0) + { +// printf("# *** satn%d epoch elts sub-orbital ***\n", satn); + satrec.error = 5; + } + + if ((omeosq >= 0.0 ) || ( satrec.no >= 0.0)) + { + satrec.isimp = 0; + if (rp < (220.0 / radiusearthkm + 1.0)) + satrec.isimp = 1; + sfour = ss; + qzms24 = qzms2t; + perige = (rp - 1.0) * radiusearthkm; + + /* - for perigees below 156 km, s and qoms2t are altered - */ + if (perige < 156.0) + { + sfour = perige - 78.0; + if (perige < 98.0) + sfour = 20.0; + qzms24 = pow(((120.0 - sfour) / radiusearthkm), 4.0); + sfour = sfour / radiusearthkm + 1.0; + } + pinvsq = 1.0 / posq; + + tsi = 1.0 / (ao - sfour); + satrec.eta = ao * satrec.ecco * tsi; + etasq = satrec.eta * satrec.eta; + eeta = satrec.ecco * satrec.eta; + psisq = fabs(1.0 - etasq); + coef = qzms24 * pow(tsi, 4.0); + coef1 = coef / pow(psisq, 3.5); + cc2 = coef1 * satrec.no * (ao * (1.0 + 1.5 * etasq + eeta * + (4.0 + etasq)) + 0.375 * j2 * tsi / psisq * satrec.con41 * + (8.0 + 3.0 * etasq * (8.0 + etasq))); + satrec.cc1 = satrec.bstar * cc2; + cc3 = 0.0; + if (satrec.ecco > 1.0e-4) + cc3 = -2.0 * coef * tsi * j3oj2 * satrec.no * sinio / satrec.ecco; + satrec.x1mth2 = 1.0 - cosio2; + satrec.cc4 = 2.0* satrec.no * coef1 * ao * omeosq * + (satrec.eta * (2.0 + 0.5 * etasq) + satrec.ecco * + (0.5 + 2.0 * etasq) - j2 * tsi / (ao * psisq) * + (-3.0 * satrec.con41 * (1.0 - 2.0 * eeta + etasq * + (1.5 - 0.5 * eeta)) + 0.75 * satrec.x1mth2 * + (2.0 * etasq - eeta * (1.0 + etasq)) * cos(2.0 * satrec.argpo))); + satrec.cc5 = 2.0 * coef1 * ao * omeosq * (1.0 + 2.75 * + (etasq + eeta) + eeta * etasq); + cosio4 = cosio2 * cosio2; + temp1 = 1.5 * j2 * pinvsq * satrec.no; + temp2 = 0.5 * temp1 * j2 * pinvsq; + temp3 = -0.46875 * j4 * pinvsq * pinvsq * satrec.no; + satrec.mdot = satrec.no + 0.5 * temp1 * rteosq * satrec.con41 + 0.0625 * + temp2 * rteosq * (13.0 - 78.0 * cosio2 + 137.0 * cosio4); + satrec.argpdot = -0.5 * temp1 * con42 + 0.0625 * temp2 * + (7.0 - 114.0 * cosio2 + 395.0 * cosio4) + + temp3 * (3.0 - 36.0 * cosio2 + 49.0 * cosio4); + xhdot1 = -temp1 * cosio; + satrec.nodedot = xhdot1 + (0.5 * temp2 * (4.0 - 19.0 * cosio2) + + 2.0 * temp3 * (3.0 - 7.0 * cosio2)) * cosio; + xpidot = satrec.argpdot+ satrec.nodedot; + satrec.omgcof = satrec.bstar * cc3 * cos(satrec.argpo); + satrec.xmcof = 0.0; + if (satrec.ecco > 1.0e-4) + satrec.xmcof = -x2o3 * coef * satrec.bstar / eeta; + satrec.nodecf = 3.5 * omeosq * xhdot1 * satrec.cc1; + satrec.t2cof = 1.5 * satrec.cc1; + // sgp4fix for divide by zero with xinco = 180 deg + if (fabs(cosio+1.0) > 1.5e-12) + satrec.xlcof = -0.25 * j3oj2 * sinio * (3.0 + 5.0 * cosio) / (1.0 + cosio); + else + satrec.xlcof = -0.25 * j3oj2 * sinio * (3.0 + 5.0 * cosio) / temp4; + satrec.aycof = -0.5 * j3oj2 * sinio; + satrec.delmo = pow((1.0 + satrec.eta * cos(satrec.mo)), 3); + satrec.sinmao = sin(satrec.mo); + satrec.x7thm1 = 7.0 * cosio2 - 1.0; + + /* --------------- deep space initialization ------------- */ + if ((2*pi / satrec.no) >= 225.0) + { + satrec.method = 'd'; + satrec.isimp = 1; + tc = 0.0; + inclm = satrec.inclo; + + dscom + ( + epoch, satrec.ecco, satrec.argpo, tc, satrec.inclo, satrec.nodeo, + satrec.no, snodm, cnodm, sinim, cosim,sinomm, cosomm, + day, satrec.e3, satrec.ee2, em, emsq, gam, + satrec.peo, satrec.pgho, satrec.pho, satrec.pinco, + satrec.plo, rtemsq, satrec.se2, satrec.se3, + satrec.sgh2, satrec.sgh3, satrec.sgh4, + satrec.sh2, satrec.sh3, satrec.si2, satrec.si3, + satrec.sl2, satrec.sl3, satrec.sl4, s1, s2, s3, s4, s5, + s6, s7, ss1, ss2, ss3, ss4, ss5, ss6, ss7, sz1, sz2, sz3, + sz11, sz12, sz13, sz21, sz22, sz23, sz31, sz32, sz33, + satrec.xgh2, satrec.xgh3, satrec.xgh4, satrec.xh2, + satrec.xh3, satrec.xi2, satrec.xi3, satrec.xl2, + satrec.xl3, satrec.xl4, nm, z1, z2, z3, z11, + z12, z13, z21, z22, z23, z31, z32, z33, + satrec.zmol, satrec.zmos + ); + dpper + ( + satrec.e3, satrec.ee2, satrec.peo, satrec.pgho, + satrec.pho, satrec.pinco, satrec.plo, satrec.se2, + satrec.se3, satrec.sgh2, satrec.sgh3, satrec.sgh4, + satrec.sh2, satrec.sh3, satrec.si2, satrec.si3, + satrec.sl2, satrec.sl3, satrec.sl4, satrec.t, + satrec.xgh2,satrec.xgh3,satrec.xgh4, satrec.xh2, + satrec.xh3, satrec.xi2, satrec.xi3, satrec.xl2, + satrec.xl3, satrec.xl4, satrec.zmol, satrec.zmos, inclm, satrec.init, + satrec.ecco, satrec.inclo, satrec.nodeo, satrec.argpo, satrec.mo + ); + + argpm = 0.0; + nodem = 0.0; + mm = 0.0; + + dsinit + ( + whichconst, + cosim, emsq, satrec.argpo, s1, s2, s3, s4, s5, sinim, ss1, ss2, ss3, ss4, + ss5, sz1, sz3, sz11, sz13, sz21, sz23, sz31, sz33, satrec.t, tc, + satrec.gsto, satrec.mo, satrec.mdot, satrec.no, satrec.nodeo, + satrec.nodedot, xpidot, z1, z3, z11, z13, z21, z23, z31, z33, + satrec.ecco, eccsq, em, argpm, inclm, mm, nm, nodem, + satrec.irez, satrec.atime, + satrec.d2201, satrec.d2211, satrec.d3210, satrec.d3222 , + satrec.d4410, satrec.d4422, satrec.d5220, satrec.d5232, + satrec.d5421, satrec.d5433, satrec.dedt, satrec.didt, + satrec.dmdt, dndt, satrec.dnodt, satrec.domdt , + satrec.del1, satrec.del2, satrec.del3, satrec.xfact, + satrec.xlamo, satrec.xli, satrec.xni + ); + } + + /* ----------- set variables if not deep space ----------- */ + if (satrec.isimp != 1) + { + cc1sq = satrec.cc1 * satrec.cc1; + satrec.d2 = 4.0 * ao * tsi * cc1sq; + temp = satrec.d2 * tsi * satrec.cc1 / 3.0; + satrec.d3 = (17.0 * ao + sfour) * temp; + satrec.d4 = 0.5 * temp * ao * tsi * (221.0 * ao + 31.0 * sfour) * + satrec.cc1; + satrec.t3cof = satrec.d2 + 2.0 * cc1sq; + satrec.t4cof = 0.25 * (3.0 * satrec.d3 + satrec.cc1 * + (12.0 * satrec.d2 + 10.0 * cc1sq)); + satrec.t5cof = 0.2 * (3.0 * satrec.d4 + + 12.0 * satrec.cc1 * satrec.d3 + + 6.0 * satrec.d2 * satrec.d2 + + 15.0 * cc1sq * (2.0 * satrec.d2 + cc1sq)); + } + } // if omeosq = 0 ... + + /* finally propogate to zero epoch to initialise all others. */ + if(satrec.error == 0) + sgp4(whichconst, satrec, 0.0, r, v); + + satrec.init = 'n'; + +//#include "debug6.cpp" + return satrec.error; +} // end sgp4init + +/*----------------------------------------------------------------------------- +* +* procedure sgp4 +* +* this procedure is the sgp4 prediction model from space command. this is an +* updated and combined version of sgp4 and sdp4, which were originally +* published separately in spacetrack report #3. this version follows the +* methodology from the aiaa paper (2006) describing the history and +* development of the code. +* +* author : david vallado 719-573-2600 28 jun 2005 +* +* inputs : +* satrec - initialised structure from sgp4init() call. +* tsince - time eince epoch (minutes) +* +* outputs : +* r - position vector km +* v - velocity km/sec +* return code - non-zero on error. +* 1 - mean elements, ecc >= 1.0 or ecc < -0.001 or a < 0.95 er +* 2 - mean motion less than 0.0 +* 3 - pert elements, ecc < 0.0 or ecc > 1.0 +* 4 - semi-latus rectum < 0.0 +* 5 - epoch elements are sub-orbital +* 6 - satellite has decayed +* +* locals : +* am - +* axnl, aynl - +* betal - +* cosim , sinim , cosomm , sinomm , cnod , snod , cos2u , +* sin2u , coseo1 , sineo1 , cosi , sini , cosip , sinip , +* cosisq , cossu , sinsu , cosu , sinu +* delm - +* delomg - +* dndt - +* eccm - +* emsq - +* ecose - +* el2 - +* eo1 - +* eccp - +* esine - +* argpm - +* argpp - +* omgadf - +* pl - +* r - +* rtemsq - +* rdotl - +* rl - +* rvdot - +* rvdotl - +* su - +* t2 , t3 , t4 , tc +* tem5, temp , temp1 , temp2 , tempa , tempe , templ +* u , ux , uy , uz , vx , vy , vz +* inclm - inclination +* mm - mean anomaly +* nm - mean motion +* nodem - right asc of ascending node +* xinc - +* xincp - +* xl - +* xlm - +* mp - +* xmdf - +* xmx - +* xmy - +* nodedf - +* xnode - +* nodep - +* np - +* +* coupling : +* getgravconst- +* dpper +* dpspace +* +* references : +* hoots, roehrich, norad spacetrack report #3 1980 +* hoots, norad spacetrack report #6 1986 +* hoots, schumacher and glover 2004 +* vallado, crawford, hujsak, kelso 2006 + ----------------------------------------------------------------------------*/ + +int sgp4 + ( + gravconsttype whichconst, elsetrec& satrec, double tsince, + double r[3], double v[3] + ) +{ + double am , axnl , aynl , betal , cosim , cnod , + cos2u, coseo1, cosi , cosip , cosisq, cossu , cosu, + delm , delomg, em , emsq , ecose , el2 , eo1 , + ep , esine , argpm, argpp , argpdf, pl, mrt = 0.0, + mvt , rdotl , rl , rvdot , rvdotl, sinim , + sin2u, sineo1, sini , sinip , sinsu , sinu , + snod , su , t2 , t3 , t4 , tem5 , temp, + temp1, temp2 , tempa, tempe , templ , u , ux , + uy , uz , vx , vy , vz , inclm , mm , + nm , nodem, xinc , xincp , xl , xlm , mp , + xmdf , xmx , xmy , nodedf, xnode , nodep, tc , dndt, + twopi, x2o3 , j2 , j3 , tumin, j4 , xke , j3oj2, radiusearthkm, + mu, vkmpersec; + int ktr; + + /* ------------------ set mathematical constants --------------- */ + // sgp4fix divisor for divide by zero check on inclination + const double temp4 = 1.0 + cos(pi-1.0e-9); + twopi = 2.0 * pi; + x2o3 = 2.0 / 3.0; + // sgp4fix identify constants and allow alternate values + getgravconst( whichconst, tumin, mu, radiusearthkm, xke, j2, j3, j4, j3oj2 ); + vkmpersec = radiusearthkm * xke/60.0; + + /* --------------------- clear sgp4 error flag ----------------- */ + satrec.t = tsince; + satrec.error = 0; + + /* ------- update for secular gravity and atmospheric drag ----- */ + xmdf = satrec.mo + satrec.mdot * satrec.t; + argpdf = satrec.argpo + satrec.argpdot * satrec.t; + nodedf = satrec.nodeo + satrec.nodedot * satrec.t; + argpm = argpdf; + mm = xmdf; + t2 = satrec.t * satrec.t; + nodem = nodedf + satrec.nodecf * t2; + tempa = 1.0 - satrec.cc1 * satrec.t; + tempe = satrec.bstar * satrec.cc4 * satrec.t; + templ = satrec.t2cof * t2; + + if (satrec.isimp != 1) + { + delomg = satrec.omgcof * satrec.t; + delm = satrec.xmcof * + (pow((1.0 + satrec.eta * cos(xmdf)), 3) - + satrec.delmo); + temp = delomg + delm; + mm = xmdf + temp; + argpm = argpdf - temp; + t3 = t2 * satrec.t; + t4 = t3 * satrec.t; + tempa = tempa - satrec.d2 * t2 - satrec.d3 * t3 - + satrec.d4 * t4; + tempe = tempe + satrec.bstar * satrec.cc5 * (sin(mm) - + satrec.sinmao); + templ = templ + satrec.t3cof * t3 + t4 * (satrec.t4cof + + satrec.t * satrec.t5cof); + } + + nm = satrec.no; + em = satrec.ecco; + inclm = satrec.inclo; + if (satrec.method == 'd') + { + tc = satrec.t; + dspace + ( + satrec.irez, + satrec.d2201, satrec.d2211, satrec.d3210, + satrec.d3222, satrec.d4410, satrec.d4422, + satrec.d5220, satrec.d5232, satrec.d5421, + satrec.d5433, satrec.dedt, satrec.del1, + satrec.del2, satrec.del3, satrec.didt, + satrec.dmdt, satrec.dnodt, satrec.domdt, + satrec.argpo, satrec.argpdot, satrec.t, tc, + satrec.gsto, satrec.xfact, satrec.xlamo, + satrec.no, satrec.atime, + em, argpm, inclm, satrec.xli, mm, satrec.xni, + nodem, dndt, nm + ); + } // if method = d + + if (nm <= 0.0) + { +// printf("# error nm %f\n", nm); + satrec.error = 2; + } + am = pow((xke / nm),x2o3) * tempa * tempa; + nm = xke / pow(am, 1.5); + em = em - tempe; + + // fix tolerance for error recognition + if ((em >= 1.0) || (em < -0.001) || (am < 0.95)) + { +// printf("# error em %f\n", em); + satrec.error = 1; + } + if (em < 0.0) + em = 1.0e-6; + mm = mm + satrec.no * templ; + xlm = mm + argpm + nodem; + emsq = em * em; + temp = 1.0 - emsq; + + nodem = fmod(nodem, twopi); + argpm = fmod(argpm, twopi); + xlm = fmod(xlm, twopi); + mm = fmod(xlm - argpm - nodem, twopi); + + /* ----------------- compute extra mean quantities ------------- */ + sinim = sin(inclm); + cosim = cos(inclm); + + /* -------------------- add lunar-solar periodics -------------- */ + ep = em; + xincp = inclm; + argpp = argpm; + nodep = nodem; + mp = mm; + sinip = sinim; + cosip = cosim; + if (satrec.method == 'd') + { + dpper + ( + satrec.e3, satrec.ee2, satrec.peo, + satrec.pgho, satrec.pho, satrec.pinco, + satrec.plo, satrec.se2, satrec.se3, + satrec.sgh2, satrec.sgh3, satrec.sgh4, + satrec.sh2, satrec.sh3, satrec.si2, + satrec.si3, satrec.sl2, satrec.sl3, + satrec.sl4, satrec.t, satrec.xgh2, + satrec.xgh3, satrec.xgh4, satrec.xh2, + satrec.xh3, satrec.xi2, satrec.xi3, + satrec.xl2, satrec.xl3, satrec.xl4, + satrec.zmol, satrec.zmos, satrec.inclo, + 'n', ep, xincp, nodep, argpp, mp + ); + if (xincp < 0.0) + { + xincp = -xincp; + nodep = nodep + pi; + argpp = argpp - pi; + } + if ((ep < 0.0 ) || ( ep > 1.0)) + { + // printf("# error ep %f\n", ep); + satrec.error = 3; + } + } // if method = d + + /* -------------------- long period periodics ------------------ */ + if (satrec.method == 'd') + { + sinip = sin(xincp); + cosip = cos(xincp); + satrec.aycof = -0.5*j3oj2*sinip; + // sgp4fix for divide by zero for xincp = 180 deg + if (fabs(cosip+1.0) > 1.5e-12) + satrec.xlcof = -0.25 * j3oj2 * sinip * (3.0 + 5.0 * cosip) / (1.0 + cosip); + else + satrec.xlcof = -0.25 * j3oj2 * sinip * (3.0 + 5.0 * cosip) / temp4; + } + axnl = ep * cos(argpp); + temp = 1.0 / (am * (1.0 - ep * ep)); + aynl = ep* sin(argpp) + temp * satrec.aycof; + xl = mp + argpp + nodep + temp * satrec.xlcof * axnl; + + /* --------------------- solve kepler's equation --------------- */ + u = fmod(xl - nodep, twopi); + eo1 = u; + tem5 = 9999.9; + ktr = 1; + // sgp4fix for kepler iteration + // the following iteration needs better limits on corrections + while (( fabs(tem5) >= 1.0e-12) && (ktr <= 10) ) + { + sineo1 = sin(eo1); + coseo1 = cos(eo1); + tem5 = 1.0 - coseo1 * axnl - sineo1 * aynl; + tem5 = (u - aynl * coseo1 + axnl * sineo1 - eo1) / tem5; + if(fabs(tem5) >= 0.95) + tem5 = tem5 > 0.0 ? 0.95 : -0.95; + eo1 = eo1 + tem5; + ktr = ktr + 1; + } + + /* ------------- short period preliminary quantities ----------- */ + ecose = axnl*coseo1 + aynl*sineo1; + esine = axnl*sineo1 - aynl*coseo1; + el2 = axnl*axnl + aynl*aynl; + pl = am*(1.0-el2); + if (pl < 0.0) + { +// printf("# error pl %f\n", pl); + satrec.error = 4; + } + else + { + rl = am * (1.0 - ecose); + rdotl = sqrt(am) * esine/rl; + rvdotl = sqrt(pl) / rl; + betal = sqrt(1.0 - el2); + temp = esine / (1.0 + betal); + sinu = am / rl * (sineo1 - aynl - axnl * temp); + cosu = am / rl * (coseo1 - axnl + aynl * temp); + su = atan2(sinu, cosu); + sin2u = (cosu + cosu) * sinu; + cos2u = 1.0 - 2.0 * sinu * sinu; + temp = 1.0 / pl; + temp1 = 0.5 * j2 * temp; + temp2 = temp1 * temp; + + /* -------------- update for short period periodics ------------ */ + if (satrec.method == 'd') + { + cosisq = cosip * cosip; + satrec.con41 = 3.0*cosisq - 1.0; + satrec.x1mth2 = 1.0 - cosisq; + satrec.x7thm1 = 7.0*cosisq - 1.0; + } + mrt = rl * (1.0 - 1.5 * temp2 * betal * satrec.con41) + + 0.5 * temp1 * satrec.x1mth2 * cos2u; + su = su - 0.25 * temp2 * satrec.x7thm1 * sin2u; + xnode = nodep + 1.5 * temp2 * cosip * sin2u; + xinc = xincp + 1.5 * temp2 * cosip * sinip * cos2u; + mvt = rdotl - nm * temp1 * satrec.x1mth2 * sin2u / xke; + rvdot = rvdotl + nm * temp1 * (satrec.x1mth2 * cos2u + + 1.5 * satrec.con41) / xke; + + /* --------------------- orientation vectors ------------------- */ + sinsu = sin(su); + cossu = cos(su); + snod = sin(xnode); + cnod = cos(xnode); + sini = sin(xinc); + cosi = cos(xinc); + xmx = -snod * cosi; + xmy = cnod * cosi; + ux = xmx * sinsu + cnod * cossu; + uy = xmy * sinsu + snod * cossu; + uz = sini * sinsu; + vx = xmx * cossu - cnod * sinsu; + vy = xmy * cossu - snod * sinsu; + vz = sini * cossu; + + /* --------- position and velocity (in km and km/sec) ---------- */ + r[0] = (mrt * ux)* radiusearthkm; + r[1] = (mrt * uy)* radiusearthkm; + r[2] = (mrt * uz)* radiusearthkm; + v[0] = (mvt * ux + rvdot * vx) * vkmpersec; + v[1] = (mvt * uy + rvdot * vy) * vkmpersec; + v[2] = (mvt * uz + rvdot * vz) * vkmpersec; + } // if pl > 0 + + // sgp4fix for decaying satellites + if (mrt < 1.0) + { +// printf("# decay condition %11.6f \n",mrt); + satrec.error = 6; + } + + +//#include "debug7.cpp" + return satrec.error; +} // end sgp4 + + +/* ----------------------------------------------------------------------------- +* +* function gstime +* +* this function finds the greenwich sidereal time. +* +* author : david vallado 719-573-2600 1 mar 2001 +* +* inputs description range / units +* jdut1 - julian date in ut1 days from 4713 bc +* +* outputs : +* gstime - greenwich sidereal time 0 to 2pi rad +* +* locals : +* temp - temporary variable for doubles rad +* tut1 - julian centuries from the +* jan 1, 2000 12 h epoch (ut1) +* +* coupling : +* none +* +* references : +* vallado 2004, 191, eq 3-45 +* --------------------------------------------------------------------------- */ + +double gstime + ( + double jdut1 + ) + { + const double twopi = 2.0 * pi; + const double deg2rad = pi / 180.0; + double temp, tut1; + + tut1 = (jdut1 - 2451545.0) / 36525.0; + temp = -6.2e-6* tut1 * tut1 * tut1 + 0.093104 * tut1 * tut1 + + (876600.0*3600 + 8640184.812866) * tut1 + 67310.54841; // sec + temp = fmod(temp * deg2rad / 240.0, twopi); //360/86400 = 1/240, to deg, to rad + + // ------------------------ check quadrants --------------------- + if (temp < 0.0) + temp += twopi; + + return temp; + } // end gstime + +/* ----------------------------------------------------------------------------- +* +* function getgravconst +* +* this function gets constants for the propagator. note that mu is identified to +* facilitiate comparisons with newer models. the common useage is wgs72. +* +* author : david vallado 719-573-2600 21 jul 2006 +* +* inputs : +* whichconst - which set of constants to use wgs72old, wgs72, wgs84 +* +* outputs : +* tumin - minutes in one time unit +* mu - earth gravitational parameter +* radiusearthkm - radius of the earth in km +* xke - reciprocal of tumin +* j2, j3, j4 - un-normalized zonal harmonic values +* j3oj2 - j3 divided by j2 +* +* locals : +* +* coupling : +* none +* +* references : +* norad spacetrack report #3 +* vallado, crawford, hujsak, kelso 2006 + --------------------------------------------------------------------------- */ + +void getgravconst + ( + gravconsttype whichconst, + double& tumin, + double& mu, + double& radiusearthkm, + double& xke, + double& j2, + double& j3, + double& j4, + double& j3oj2 + ) + { + + switch (whichconst) + { + // -- wgs-72 low precision str#3 constants -- + case wgs72old: + mu = 398600.79964; // in km3 / s2 + radiusearthkm = 6378.135; // km + xke = 0.0743669161; + tumin = 1.0 / xke; + j2 = 0.001082616; + j3 = -0.00000253881; + j4 = -0.00000165597; + j3oj2 = j3 / j2; + break; + // ------------ wgs-72 constants ------------ + case wgs72: + mu = 398600.8; // in km3 / s2 + radiusearthkm = 6378.135; // km + xke = 60.0 / sqrt(radiusearthkm*radiusearthkm*radiusearthkm/mu); + tumin = 1.0 / xke; + j2 = 0.001082616; + j3 = -0.00000253881; + j4 = -0.00000165597; + j3oj2 = j3 / j2; + break; + case wgs84: + // ------------ wgs-84 constants ------------ + mu = 398600.5; // in km3 / s2 + radiusearthkm = 6378.137; // km + xke = 60.0 / sqrt(radiusearthkm*radiusearthkm*radiusearthkm/mu); + tumin = 1.0 / xke; + j2 = 0.00108262998905; + j3 = -0.00000253215306; + j4 = -0.00000161098761; + j3oj2 = j3 / j2; + break; + default: + fprintf(stderr,"unknown gravity option (%d)\n",whichconst); + break; + } + + } // end getgravconst + + + + + diff --git a/contrib/sgp4/sgp4unit.h b/contrib/sgp4/sgp4unit.h index 48c113d7..f16acbd9 100644 --- a/contrib/sgp4/sgp4unit.h +++ b/contrib/sgp4/sgp4unit.h @@ -1,117 +1,117 @@ -#ifndef _sgp4unit_ -#define _sgp4unit_ -/* ---------------------------------------------------------------- -* -* sgp4unit.h -* -* this file contains the sgp4 procedures for analytical propagation -* of a satellite. the code was originally released in the 1980 and 1986 -* spacetrack papers. a detailed discussion of the theory and history -* may be found in the 2006 aiaa paper by vallado, crawford, hujsak, -* and kelso. -* -* companion code for -* fundamentals of astrodynamics and applications -* 2007 -* by david vallado -* -* (w) 719-573-2600, email dvallado@agi.com -* -* current : -* 20 apr 07 david vallado -* misc fixes for constants -* changes : -* 11 aug 06 david vallado -* chg lyddane choice back to strn3, constants, misc doc -* 15 dec 05 david vallado -* misc fixes -* 26 jul 05 david vallado -* fixes for paper -* note that each fix is preceded by a -* comment with "sgp4fix" and an explanation of -* what was changed -* 10 aug 04 david vallado -* 2nd printing baseline working -* 14 may 01 david vallado -* 2nd edition baseline -* 80 norad -* original baseline -* ---------------------------------------------------------------- */ - -#include -#include - -// -------------------------- structure declarations ---------------------------- -typedef enum -{ - wgs72old, - wgs72, - wgs84 -} gravconsttype; - -typedef struct elsetrec -{ - long int satnum; - int epochyr, epochtynumrev; - int error; - char init, method; - - /* Near Earth */ - int isimp; - double aycof , con41 , cc1 , cc4 , cc5 , d2 , d3 , d4 , - delmo , eta , argpdot, omgcof , sinmao , t , t2cof, t3cof , - t4cof , t5cof , x1mth2 , x7thm1 , mdot , nodedot, xlcof , xmcof , - nodecf; - - /* Deep Space */ - int irez; - double d2201 , d2211 , d3210 , d3222 , d4410 , d4422 , d5220 , d5232 , - d5421 , d5433 , dedt , del1 , del2 , del3 , didt , dmdt , - dnodt , domdt , e3 , ee2 , peo , pgho , pho , pinco , - plo , se2 , se3 , sgh2 , sgh3 , sgh4 , sh2 , sh3 , - si2 , si3 , sl2 , sl3 , sl4 , gsto , xfact , xgh2 , - xgh3 , xgh4 , xh2 , xh3 , xi2 , xi3 , xl2 , xl3 , - xl4 , xlamo , zmol , zmos , atime , xli , xni; - - double a , altp , alta , epochdays, jdsatepoch , nddot , ndot , - bstar , rcse , inclo , nodeo , ecco , argpo , mo , - no; -} elsetrec; - -// --------------------------- function declarations ---------------------------- -int sgp4init - ( - gravconsttype whichconst, const int satn, const double epoch, - const double xbstar, const double xecco, const double xargpo, - const double xinclo, const double xmo, const double xno, - const double xnodeo, - elsetrec& satrec - ); - -int sgp4 - ( - gravconsttype whichconst, - elsetrec& satrec, double tsince, - double r[], double v[] - ); - -double gstime - ( - double - ); - -void getgravconst - ( - gravconsttype, - double&, - double&, - double&, - double&, - double&, - double&, - double&, - double& - ); - -#endif - +#ifndef _sgp4unit_ +#define _sgp4unit_ +/* ---------------------------------------------------------------- +* +* sgp4unit.h +* +* this file contains the sgp4 procedures for analytical propagation +* of a satellite. the code was originally released in the 1980 and 1986 +* spacetrack papers. a detailed discussion of the theory and history +* may be found in the 2006 aiaa paper by vallado, crawford, hujsak, +* and kelso. +* +* companion code for +* fundamentals of astrodynamics and applications +* 2007 +* by david vallado +* +* (w) 719-573-2600, email dvallado@agi.com +* +* current : +* 20 apr 07 david vallado +* misc fixes for constants +* changes : +* 11 aug 06 david vallado +* chg lyddane choice back to strn3, constants, misc doc +* 15 dec 05 david vallado +* misc fixes +* 26 jul 05 david vallado +* fixes for paper +* note that each fix is preceded by a +* comment with "sgp4fix" and an explanation of +* what was changed +* 10 aug 04 david vallado +* 2nd printing baseline working +* 14 may 01 david vallado +* 2nd edition baseline +* 80 norad +* original baseline +* ---------------------------------------------------------------- */ + +#include +#include + +// -------------------------- structure declarations ---------------------------- +typedef enum +{ + wgs72old, + wgs72, + wgs84 +} gravconsttype; + +typedef struct elsetrec +{ + long int satnum; + int epochyr, epochtynumrev; + int error; + char init, method; + + /* Near Earth */ + int isimp; + double aycof , con41 , cc1 , cc4 , cc5 , d2 , d3 , d4 , + delmo , eta , argpdot, omgcof , sinmao , t , t2cof, t3cof , + t4cof , t5cof , x1mth2 , x7thm1 , mdot , nodedot, xlcof , xmcof , + nodecf; + + /* Deep Space */ + int irez; + double d2201 , d2211 , d3210 , d3222 , d4410 , d4422 , d5220 , d5232 , + d5421 , d5433 , dedt , del1 , del2 , del3 , didt , dmdt , + dnodt , domdt , e3 , ee2 , peo , pgho , pho , pinco , + plo , se2 , se3 , sgh2 , sgh3 , sgh4 , sh2 , sh3 , + si2 , si3 , sl2 , sl3 , sl4 , gsto , xfact , xgh2 , + xgh3 , xgh4 , xh2 , xh3 , xi2 , xi3 , xl2 , xl3 , + xl4 , xlamo , zmol , zmos , atime , xli , xni; + + double a , altp , alta , epochdays, jdsatepoch , nddot , ndot , + bstar , rcse , inclo , nodeo , ecco , argpo , mo , + no; +} elsetrec; + +// --------------------------- function declarations ---------------------------- +int sgp4init + ( + gravconsttype whichconst, const int satn, const double epoch, + const double xbstar, const double xecco, const double xargpo, + const double xinclo, const double xmo, const double xno, + const double xnodeo, + elsetrec& satrec + ); + +int sgp4 + ( + gravconsttype whichconst, + elsetrec& satrec, double tsince, + double r[], double v[] + ); + +double gstime + ( + double + ); + +void getgravconst + ( + gravconsttype, + double&, + double&, + double&, + double&, + double&, + double&, + double&, + double& + ); + +#endif + diff --git a/globalfunctions/timevalOperations.cpp b/globalfunctions/timevalOperations.cpp index ae49ef21..1228da04 100644 --- a/globalfunctions/timevalOperations.cpp +++ b/globalfunctions/timevalOperations.cpp @@ -1,99 +1,99 @@ -#include "timevalOperations.h" - -timeval& operator+=(timeval& lhs, const timeval& rhs) { - int64_t sum = lhs.tv_sec * 1000000. + lhs.tv_usec; - sum += rhs.tv_sec * 1000000. + rhs.tv_usec; - lhs.tv_sec = sum / 1000000; - lhs.tv_usec = sum - lhs.tv_sec * 1000000; - return lhs; -} - -timeval operator+(timeval lhs, const timeval& rhs) { - lhs += rhs; - return lhs; -} - -timeval& operator-=(timeval& lhs, const timeval& rhs) { - int64_t sum = lhs.tv_sec * 1000000. + lhs.tv_usec; - sum -= rhs.tv_sec * 1000000. + rhs.tv_usec; - lhs.tv_sec = sum / 1000000; - lhs.tv_usec = sum - lhs.tv_sec * 1000000; - return lhs; -} - -timeval operator-(timeval lhs, const timeval& rhs) { - lhs -= rhs; - return lhs; -} - -double operator/(const timeval& lhs, const timeval& rhs) { - double lhs64 = lhs.tv_sec * 1000000. + lhs.tv_usec; - double rhs64 = rhs.tv_sec * 1000000. + rhs.tv_usec; - return lhs64 / rhs64; -} - -timeval& operator/=(timeval& lhs, double scalar) { - int64_t product = lhs.tv_sec * 1000000. + lhs.tv_usec; - product /= scalar; - lhs.tv_sec = product / 1000000; - lhs.tv_usec = product - lhs.tv_sec * 1000000; - return lhs; -} - -timeval operator/(timeval lhs, double scalar) { - lhs /= scalar; - return lhs; -} - -timeval& operator*=(timeval& lhs, double scalar) { - int64_t product = lhs.tv_sec * 1000000. + lhs.tv_usec; - product *= scalar; - lhs.tv_sec = product / 1000000; - lhs.tv_usec = product - lhs.tv_sec * 1000000; - return lhs; -} - -timeval operator*(timeval lhs, double scalar) { - lhs *= scalar; - return lhs; -} - -timeval operator*(double scalar, timeval rhs) { - rhs *= scalar; - return rhs; -} - -bool operator==(const timeval& lhs, const timeval& rhs) { - int64_t lhs64 = lhs.tv_sec * 1000000. + lhs.tv_usec; - int64_t rhs64 = rhs.tv_sec * 1000000. + rhs.tv_usec; - return lhs64 == rhs64; -} -bool operator!=(const timeval& lhs, const timeval& rhs) { - return !operator==(lhs, rhs); -} -bool operator<(const timeval& lhs, const timeval& rhs) { - int64_t lhs64 = lhs.tv_sec * 1000000. + lhs.tv_usec; - int64_t rhs64 = rhs.tv_sec * 1000000. + rhs.tv_usec; - return lhs64 < rhs64; -} -bool operator>(const timeval& lhs, const timeval& rhs) { - return operator<(rhs, lhs); -} -bool operator<=(const timeval& lhs, const timeval& rhs) { - return !operator>(lhs, rhs); -} -bool operator>=(const timeval& lhs, const timeval& rhs) { - return !operator<(lhs, rhs); -} - -double timevalOperations::toDouble(const timeval timeval) { - double result = timeval.tv_sec * 1000000. + timeval.tv_usec; - return result / 1000000.; -} - -timeval timevalOperations::toTimeval(const double seconds) { - timeval tval; - tval.tv_sec = seconds; - tval.tv_usec = seconds *(double) 1e6 - (tval.tv_sec *1e6); - return tval; -} +#include "timevalOperations.h" + +timeval& operator+=(timeval& lhs, const timeval& rhs) { + int64_t sum = lhs.tv_sec * 1000000. + lhs.tv_usec; + sum += rhs.tv_sec * 1000000. + rhs.tv_usec; + lhs.tv_sec = sum / 1000000; + lhs.tv_usec = sum - lhs.tv_sec * 1000000; + return lhs; +} + +timeval operator+(timeval lhs, const timeval& rhs) { + lhs += rhs; + return lhs; +} + +timeval& operator-=(timeval& lhs, const timeval& rhs) { + int64_t sum = lhs.tv_sec * 1000000. + lhs.tv_usec; + sum -= rhs.tv_sec * 1000000. + rhs.tv_usec; + lhs.tv_sec = sum / 1000000; + lhs.tv_usec = sum - lhs.tv_sec * 1000000; + return lhs; +} + +timeval operator-(timeval lhs, const timeval& rhs) { + lhs -= rhs; + return lhs; +} + +double operator/(const timeval& lhs, const timeval& rhs) { + double lhs64 = lhs.tv_sec * 1000000. + lhs.tv_usec; + double rhs64 = rhs.tv_sec * 1000000. + rhs.tv_usec; + return lhs64 / rhs64; +} + +timeval& operator/=(timeval& lhs, double scalar) { + int64_t product = lhs.tv_sec * 1000000. + lhs.tv_usec; + product /= scalar; + lhs.tv_sec = product / 1000000; + lhs.tv_usec = product - lhs.tv_sec * 1000000; + return lhs; +} + +timeval operator/(timeval lhs, double scalar) { + lhs /= scalar; + return lhs; +} + +timeval& operator*=(timeval& lhs, double scalar) { + int64_t product = lhs.tv_sec * 1000000. + lhs.tv_usec; + product *= scalar; + lhs.tv_sec = product / 1000000; + lhs.tv_usec = product - lhs.tv_sec * 1000000; + return lhs; +} + +timeval operator*(timeval lhs, double scalar) { + lhs *= scalar; + return lhs; +} + +timeval operator*(double scalar, timeval rhs) { + rhs *= scalar; + return rhs; +} + +bool operator==(const timeval& lhs, const timeval& rhs) { + int64_t lhs64 = lhs.tv_sec * 1000000. + lhs.tv_usec; + int64_t rhs64 = rhs.tv_sec * 1000000. + rhs.tv_usec; + return lhs64 == rhs64; +} +bool operator!=(const timeval& lhs, const timeval& rhs) { + return !operator==(lhs, rhs); +} +bool operator<(const timeval& lhs, const timeval& rhs) { + int64_t lhs64 = lhs.tv_sec * 1000000. + lhs.tv_usec; + int64_t rhs64 = rhs.tv_sec * 1000000. + rhs.tv_usec; + return lhs64 < rhs64; +} +bool operator>(const timeval& lhs, const timeval& rhs) { + return operator<(rhs, lhs); +} +bool operator<=(const timeval& lhs, const timeval& rhs) { + return !operator>(lhs, rhs); +} +bool operator>=(const timeval& lhs, const timeval& rhs) { + return !operator<(lhs, rhs); +} + +double timevalOperations::toDouble(const timeval timeval) { + double result = timeval.tv_sec * 1000000. + timeval.tv_usec; + return result / 1000000.; +} + +timeval timevalOperations::toTimeval(const double seconds) { + timeval tval; + tval.tv_sec = seconds; + tval.tv_usec = seconds *(double) 1e6 - (tval.tv_sec *1e6); + return tval; +} diff --git a/osal/FreeRTOS/BinSemaphUsingTask.cpp b/osal/FreeRTOS/BinSemaphUsingTask.cpp index 8c831bbe..dd1e48ca 100644 --- a/osal/FreeRTOS/BinSemaphUsingTask.cpp +++ b/osal/FreeRTOS/BinSemaphUsingTask.cpp @@ -1,95 +1,95 @@ -#include "../../osal/FreeRTOS/BinSemaphUsingTask.h" -#include "../../osal/FreeRTOS/TaskManagement.h" -#include "../../serviceinterface/ServiceInterfaceStream.h" - -BinarySemaphoreUsingTask::BinarySemaphoreUsingTask() { - handle = TaskManagement::getCurrentTaskHandle(); - if(handle == nullptr) { - sif::error << "Could not retrieve task handle. Please ensure the" - "constructor was called inside a task." << std::endl; - } - xTaskNotifyGive(handle); -} - -BinarySemaphoreUsingTask::~BinarySemaphoreUsingTask() { - // Clear notification value on destruction. - xTaskNotifyAndQuery(handle, 0, eSetValueWithOverwrite, nullptr); -} - -ReturnValue_t BinarySemaphoreUsingTask::acquire(TimeoutType timeoutType, - uint32_t timeoutMs) { - TickType_t timeout = 0; - if(timeoutType == TimeoutType::POLLING) { - timeout = 0; - } - else if(timeoutType == TimeoutType::WAITING){ - timeout = pdMS_TO_TICKS(timeoutMs); - } - else { - timeout = portMAX_DELAY; - } - return acquireWithTickTimeout(timeoutType, timeout); -} - -ReturnValue_t BinarySemaphoreUsingTask::acquireWithTickTimeout( - TimeoutType timeoutType, TickType_t timeoutTicks) { - BaseType_t returncode = ulTaskNotifyTake(pdTRUE, timeoutTicks); - if (returncode == pdPASS) { - return HasReturnvaluesIF::RETURN_OK; - } - else { - return SemaphoreIF::SEMAPHORE_TIMEOUT; - } -} - -ReturnValue_t BinarySemaphoreUsingTask::release() { - return release(this->handle); -} - -ReturnValue_t BinarySemaphoreUsingTask::release( - TaskHandle_t taskHandle) { - if(getSemaphoreCounter(taskHandle) == 1) { - return SemaphoreIF::SEMAPHORE_NOT_OWNED; - } - BaseType_t returncode = xTaskNotifyGive(taskHandle); - if (returncode == pdPASS) { - return HasReturnvaluesIF::RETURN_OK; - } - else { - // This should never happen. - return HasReturnvaluesIF::RETURN_FAILED; - } -} - -TaskHandle_t BinarySemaphoreUsingTask::getTaskHandle() { - return handle; -} - -uint8_t BinarySemaphoreUsingTask::getSemaphoreCounter() const { - return getSemaphoreCounter(this->handle); -} - -uint8_t BinarySemaphoreUsingTask::getSemaphoreCounter( - TaskHandle_t taskHandle) { - uint32_t notificationValue; - xTaskNotifyAndQuery(taskHandle, 0, eNoAction, ¬ificationValue); - return notificationValue; -} - -// Be careful with the stack size here. This is called from an ISR! -ReturnValue_t BinarySemaphoreUsingTask::releaseFromISR( - TaskHandle_t taskHandle, BaseType_t * higherPriorityTaskWoken) { - if(getSemaphoreCounterFromISR(taskHandle, higherPriorityTaskWoken) == 1) { - return SemaphoreIF::SEMAPHORE_NOT_OWNED; - } - vTaskNotifyGiveFromISR(taskHandle, higherPriorityTaskWoken); - return HasReturnvaluesIF::RETURN_OK; -} - -uint8_t BinarySemaphoreUsingTask::getSemaphoreCounterFromISR( - TaskHandle_t taskHandle, BaseType_t* higherPriorityTaskWoken) { - uint32_t notificationValue = 0; - xTaskNotifyAndQueryFromISR(taskHandle, 0, eNoAction, ¬ificationValue, - higherPriorityTaskWoken); - return notificationValue; -} +#include "../../osal/FreeRTOS/BinSemaphUsingTask.h" +#include "../../osal/FreeRTOS/TaskManagement.h" +#include "../../serviceinterface/ServiceInterfaceStream.h" + +BinarySemaphoreUsingTask::BinarySemaphoreUsingTask() { + handle = TaskManagement::getCurrentTaskHandle(); + if(handle == nullptr) { + sif::error << "Could not retrieve task handle. Please ensure the" + "constructor was called inside a task." << std::endl; + } + xTaskNotifyGive(handle); +} + +BinarySemaphoreUsingTask::~BinarySemaphoreUsingTask() { + // Clear notification value on destruction. + xTaskNotifyAndQuery(handle, 0, eSetValueWithOverwrite, nullptr); +} + +ReturnValue_t BinarySemaphoreUsingTask::acquire(TimeoutType timeoutType, + uint32_t timeoutMs) { + TickType_t timeout = 0; + if(timeoutType == TimeoutType::POLLING) { + timeout = 0; + } + else if(timeoutType == TimeoutType::WAITING){ + timeout = pdMS_TO_TICKS(timeoutMs); + } + else { + timeout = portMAX_DELAY; + } + return acquireWithTickTimeout(timeoutType, timeout); +} + +ReturnValue_t BinarySemaphoreUsingTask::acquireWithTickTimeout( + TimeoutType timeoutType, TickType_t timeoutTicks) { + BaseType_t returncode = ulTaskNotifyTake(pdTRUE, timeoutTicks); + if (returncode == pdPASS) { + return HasReturnvaluesIF::RETURN_OK; + } + else { + return SemaphoreIF::SEMAPHORE_TIMEOUT; + } +} + +ReturnValue_t BinarySemaphoreUsingTask::release() { + return release(this->handle); +} + +ReturnValue_t BinarySemaphoreUsingTask::release( + TaskHandle_t taskHandle) { + if(getSemaphoreCounter(taskHandle) == 1) { + return SemaphoreIF::SEMAPHORE_NOT_OWNED; + } + BaseType_t returncode = xTaskNotifyGive(taskHandle); + if (returncode == pdPASS) { + return HasReturnvaluesIF::RETURN_OK; + } + else { + // This should never happen. + return HasReturnvaluesIF::RETURN_FAILED; + } +} + +TaskHandle_t BinarySemaphoreUsingTask::getTaskHandle() { + return handle; +} + +uint8_t BinarySemaphoreUsingTask::getSemaphoreCounter() const { + return getSemaphoreCounter(this->handle); +} + +uint8_t BinarySemaphoreUsingTask::getSemaphoreCounter( + TaskHandle_t taskHandle) { + uint32_t notificationValue; + xTaskNotifyAndQuery(taskHandle, 0, eNoAction, ¬ificationValue); + return notificationValue; +} + +// Be careful with the stack size here. This is called from an ISR! +ReturnValue_t BinarySemaphoreUsingTask::releaseFromISR( + TaskHandle_t taskHandle, BaseType_t * higherPriorityTaskWoken) { + if(getSemaphoreCounterFromISR(taskHandle, higherPriorityTaskWoken) == 1) { + return SemaphoreIF::SEMAPHORE_NOT_OWNED; + } + vTaskNotifyGiveFromISR(taskHandle, higherPriorityTaskWoken); + return HasReturnvaluesIF::RETURN_OK; +} + +uint8_t BinarySemaphoreUsingTask::getSemaphoreCounterFromISR( + TaskHandle_t taskHandle, BaseType_t* higherPriorityTaskWoken) { + uint32_t notificationValue = 0; + xTaskNotifyAndQueryFromISR(taskHandle, 0, eNoAction, ¬ificationValue, + higherPriorityTaskWoken); + return notificationValue; +} diff --git a/osal/FreeRTOS/BinSemaphUsingTask.h b/osal/FreeRTOS/BinSemaphUsingTask.h index 2d2cf159..f3c0b0ea 100644 --- a/osal/FreeRTOS/BinSemaphUsingTask.h +++ b/osal/FreeRTOS/BinSemaphUsingTask.h @@ -1,76 +1,76 @@ -#ifndef FRAMEWORK_OSAL_FREERTOS_BINSEMAPHUSINGTASK_H_ -#define FRAMEWORK_OSAL_FREERTOS_BINSEMAPHUSINGTASK_H_ - -#include "../../returnvalues/HasReturnvaluesIF.h" -#include "../../tasks/SemaphoreIF.h" - -#include -#include - -/** - * @brief Binary Semaphore implementation using the task notification value. - * The notification value should therefore not be used - * for other purposes. - * @details - * Additional information: https://www.freertos.org/RTOS-task-notifications.html - * and general semaphore documentation. - */ -class BinarySemaphoreUsingTask: public SemaphoreIF, - public HasReturnvaluesIF { -public: - static const uint8_t INTERFACE_ID = CLASS_ID::SEMAPHORE_IF; - - //! @brief Default ctor - BinarySemaphoreUsingTask(); - //! @brief Default dtor - virtual~ BinarySemaphoreUsingTask(); - - ReturnValue_t acquire(TimeoutType timeoutType = TimeoutType::BLOCKING, - uint32_t timeoutMs = portMAX_DELAY) override; - ReturnValue_t release() override; - uint8_t getSemaphoreCounter() const override; - static uint8_t getSemaphoreCounter(TaskHandle_t taskHandle); - static uint8_t getSemaphoreCounterFromISR(TaskHandle_t taskHandle, - BaseType_t* higherPriorityTaskWoken); - - /** - * Same as acquire() with timeout in FreeRTOS ticks. - * @param timeoutTicks - * @return - @c RETURN_OK on success - * - @c RETURN_FAILED on failure - */ - ReturnValue_t acquireWithTickTimeout( - TimeoutType timeoutType = TimeoutType::BLOCKING, - TickType_t timeoutTicks = portMAX_DELAY); - - /** - * Get handle to the task related to the semaphore. - * @return - */ - TaskHandle_t getTaskHandle(); - - /** - * Wrapper function to give back semaphore from handle - * @param semaphore - * @return - @c RETURN_OK on success - * - @c RETURN_FAILED on failure - */ - static ReturnValue_t release(TaskHandle_t taskToNotify); - - /** - * Wrapper function to give back semaphore from handle when called from an ISR - * @param semaphore - * @param higherPriorityTaskWoken This will be set to pdPASS if a task with - * a higher priority was unblocked. A context switch should be requested - * from an ISR if this is the case (see TaskManagement functions) - * @return - @c RETURN_OK on success - * - @c RETURN_FAILED on failure - */ - static ReturnValue_t releaseFromISR(TaskHandle_t taskToNotify, - BaseType_t * higherPriorityTaskWoken); - -protected: - TaskHandle_t handle; -}; - -#endif /* FRAMEWORK_OSAL_FREERTOS_BINSEMAPHUSINGTASK_H_ */ +#ifndef FRAMEWORK_OSAL_FREERTOS_BINSEMAPHUSINGTASK_H_ +#define FRAMEWORK_OSAL_FREERTOS_BINSEMAPHUSINGTASK_H_ + +#include "../../returnvalues/HasReturnvaluesIF.h" +#include "../../tasks/SemaphoreIF.h" + +#include +#include + +/** + * @brief Binary Semaphore implementation using the task notification value. + * The notification value should therefore not be used + * for other purposes. + * @details + * Additional information: https://www.freertos.org/RTOS-task-notifications.html + * and general semaphore documentation. + */ +class BinarySemaphoreUsingTask: public SemaphoreIF, + public HasReturnvaluesIF { +public: + static const uint8_t INTERFACE_ID = CLASS_ID::SEMAPHORE_IF; + + //! @brief Default ctor + BinarySemaphoreUsingTask(); + //! @brief Default dtor + virtual~ BinarySemaphoreUsingTask(); + + ReturnValue_t acquire(TimeoutType timeoutType = TimeoutType::BLOCKING, + uint32_t timeoutMs = portMAX_DELAY) override; + ReturnValue_t release() override; + uint8_t getSemaphoreCounter() const override; + static uint8_t getSemaphoreCounter(TaskHandle_t taskHandle); + static uint8_t getSemaphoreCounterFromISR(TaskHandle_t taskHandle, + BaseType_t* higherPriorityTaskWoken); + + /** + * Same as acquire() with timeout in FreeRTOS ticks. + * @param timeoutTicks + * @return - @c RETURN_OK on success + * - @c RETURN_FAILED on failure + */ + ReturnValue_t acquireWithTickTimeout( + TimeoutType timeoutType = TimeoutType::BLOCKING, + TickType_t timeoutTicks = portMAX_DELAY); + + /** + * Get handle to the task related to the semaphore. + * @return + */ + TaskHandle_t getTaskHandle(); + + /** + * Wrapper function to give back semaphore from handle + * @param semaphore + * @return - @c RETURN_OK on success + * - @c RETURN_FAILED on failure + */ + static ReturnValue_t release(TaskHandle_t taskToNotify); + + /** + * Wrapper function to give back semaphore from handle when called from an ISR + * @param semaphore + * @param higherPriorityTaskWoken This will be set to pdPASS if a task with + * a higher priority was unblocked. A context switch should be requested + * from an ISR if this is the case (see TaskManagement functions) + * @return - @c RETURN_OK on success + * - @c RETURN_FAILED on failure + */ + static ReturnValue_t releaseFromISR(TaskHandle_t taskToNotify, + BaseType_t * higherPriorityTaskWoken); + +protected: + TaskHandle_t handle; +}; + +#endif /* FRAMEWORK_OSAL_FREERTOS_BINSEMAPHUSINGTASK_H_ */ diff --git a/osal/FreeRTOS/BinarySemaphore.cpp b/osal/FreeRTOS/BinarySemaphore.cpp index f1c78473..8cc3c495 100644 --- a/osal/FreeRTOS/BinarySemaphore.cpp +++ b/osal/FreeRTOS/BinarySemaphore.cpp @@ -1,108 +1,108 @@ -#include "../../osal/FreeRTOS/BinarySemaphore.h" -#include "../../osal/FreeRTOS/TaskManagement.h" -#include "../../serviceinterface/ServiceInterfaceStream.h" - -BinarySemaphore::BinarySemaphore() { - handle = xSemaphoreCreateBinary(); - if(handle == nullptr) { - sif::error << "Semaphore: Binary semaph creation failure" << std::endl; - } - // Initiated semaphore must be given before it can be taken. - xSemaphoreGive(handle); -} - -BinarySemaphore::~BinarySemaphore() { - vSemaphoreDelete(handle); -} - -BinarySemaphore::BinarySemaphore(BinarySemaphore&& s) { - handle = xSemaphoreCreateBinary(); - if(handle == nullptr) { - sif::error << "Binary semaphore creation failure" << std::endl; - } - xSemaphoreGive(handle); -} - -BinarySemaphore& BinarySemaphore::operator =( - BinarySemaphore&& s) { - if(&s != this) { - handle = xSemaphoreCreateBinary(); - if(handle == nullptr) { - sif::error << "Binary semaphore creation failure" << std::endl; - } - xSemaphoreGive(handle); - } - return *this; -} - -ReturnValue_t BinarySemaphore::acquire(TimeoutType timeoutType, - uint32_t timeoutMs) { - TickType_t timeout = 0; - if(timeoutType == TimeoutType::POLLING) { - timeout = 0; - } - else if(timeoutType == TimeoutType::WAITING){ - timeout = pdMS_TO_TICKS(timeoutMs); - } - else { - timeout = portMAX_DELAY; - } - return acquireWithTickTimeout(timeoutType, timeout); -} - -ReturnValue_t BinarySemaphore::acquireWithTickTimeout(TimeoutType timeoutType, - TickType_t timeoutTicks) { - if(handle == nullptr) { - return SemaphoreIF::SEMAPHORE_INVALID; - } - - BaseType_t returncode = xSemaphoreTake(handle, timeoutTicks); - if (returncode == pdPASS) { - return HasReturnvaluesIF::RETURN_OK; - } - else { - return SemaphoreIF::SEMAPHORE_TIMEOUT; - } -} - -ReturnValue_t BinarySemaphore::release() { - return release(handle); -} - -ReturnValue_t BinarySemaphore::release(SemaphoreHandle_t semaphore) { - if (semaphore == nullptr) { - return SemaphoreIF::SEMAPHORE_INVALID; - } - BaseType_t returncode = xSemaphoreGive(semaphore); - if (returncode == pdPASS) { - return HasReturnvaluesIF::RETURN_OK; - } - else { - return SemaphoreIF::SEMAPHORE_NOT_OWNED; - } -} - -uint8_t BinarySemaphore::getSemaphoreCounter() const { - return uxSemaphoreGetCount(handle); -} - -SemaphoreHandle_t BinarySemaphore::getSemaphore() { - return handle; -} - - -// Be careful with the stack size here. This is called from an ISR! -ReturnValue_t BinarySemaphore::releaseFromISR( - SemaphoreHandle_t semaphore, BaseType_t * higherPriorityTaskWoken) { - if (semaphore == nullptr) { - return SemaphoreIF::SEMAPHORE_INVALID; - } - BaseType_t returncode = xSemaphoreGiveFromISR(semaphore, - higherPriorityTaskWoken); - if (returncode == pdPASS) { - return HasReturnvaluesIF::RETURN_OK; - } - else { - return SemaphoreIF::SEMAPHORE_NOT_OWNED; - } -} +#include "../../osal/FreeRTOS/BinarySemaphore.h" +#include "../../osal/FreeRTOS/TaskManagement.h" +#include "../../serviceinterface/ServiceInterfaceStream.h" + +BinarySemaphore::BinarySemaphore() { + handle = xSemaphoreCreateBinary(); + if(handle == nullptr) { + sif::error << "Semaphore: Binary semaph creation failure" << std::endl; + } + // Initiated semaphore must be given before it can be taken. + xSemaphoreGive(handle); +} + +BinarySemaphore::~BinarySemaphore() { + vSemaphoreDelete(handle); +} + +BinarySemaphore::BinarySemaphore(BinarySemaphore&& s) { + handle = xSemaphoreCreateBinary(); + if(handle == nullptr) { + sif::error << "Binary semaphore creation failure" << std::endl; + } + xSemaphoreGive(handle); +} + +BinarySemaphore& BinarySemaphore::operator =( + BinarySemaphore&& s) { + if(&s != this) { + handle = xSemaphoreCreateBinary(); + if(handle == nullptr) { + sif::error << "Binary semaphore creation failure" << std::endl; + } + xSemaphoreGive(handle); + } + return *this; +} + +ReturnValue_t BinarySemaphore::acquire(TimeoutType timeoutType, + uint32_t timeoutMs) { + TickType_t timeout = 0; + if(timeoutType == TimeoutType::POLLING) { + timeout = 0; + } + else if(timeoutType == TimeoutType::WAITING){ + timeout = pdMS_TO_TICKS(timeoutMs); + } + else { + timeout = portMAX_DELAY; + } + return acquireWithTickTimeout(timeoutType, timeout); +} + +ReturnValue_t BinarySemaphore::acquireWithTickTimeout(TimeoutType timeoutType, + TickType_t timeoutTicks) { + if(handle == nullptr) { + return SemaphoreIF::SEMAPHORE_INVALID; + } + + BaseType_t returncode = xSemaphoreTake(handle, timeoutTicks); + if (returncode == pdPASS) { + return HasReturnvaluesIF::RETURN_OK; + } + else { + return SemaphoreIF::SEMAPHORE_TIMEOUT; + } +} + +ReturnValue_t BinarySemaphore::release() { + return release(handle); +} + +ReturnValue_t BinarySemaphore::release(SemaphoreHandle_t semaphore) { + if (semaphore == nullptr) { + return SemaphoreIF::SEMAPHORE_INVALID; + } + BaseType_t returncode = xSemaphoreGive(semaphore); + if (returncode == pdPASS) { + return HasReturnvaluesIF::RETURN_OK; + } + else { + return SemaphoreIF::SEMAPHORE_NOT_OWNED; + } +} + +uint8_t BinarySemaphore::getSemaphoreCounter() const { + return uxSemaphoreGetCount(handle); +} + +SemaphoreHandle_t BinarySemaphore::getSemaphore() { + return handle; +} + + +// Be careful with the stack size here. This is called from an ISR! +ReturnValue_t BinarySemaphore::releaseFromISR( + SemaphoreHandle_t semaphore, BaseType_t * higherPriorityTaskWoken) { + if (semaphore == nullptr) { + return SemaphoreIF::SEMAPHORE_INVALID; + } + BaseType_t returncode = xSemaphoreGiveFromISR(semaphore, + higherPriorityTaskWoken); + if (returncode == pdPASS) { + return HasReturnvaluesIF::RETURN_OK; + } + else { + return SemaphoreIF::SEMAPHORE_NOT_OWNED; + } +} diff --git a/osal/FreeRTOS/BinarySemaphore.h b/osal/FreeRTOS/BinarySemaphore.h index 5a32088a..c6cedc53 100644 --- a/osal/FreeRTOS/BinarySemaphore.h +++ b/osal/FreeRTOS/BinarySemaphore.h @@ -1,107 +1,107 @@ -#ifndef FRAMEWORK_OSAL_FREERTOS_BINARYSEMPAHORE_H_ -#define FRAMEWORK_OSAL_FREERTOS_BINARYSEMPAHORE_H_ - -#include "../../returnvalues/HasReturnvaluesIF.h" -#include "../../tasks/SemaphoreIF.h" - -#include -#include - -/** - * @brief OS Tool to achieve synchronization of between tasks or between - * task and ISR. The default semaphore implementation creates a - * binary semaphore, which can only be taken once. - * @details - * Documentation: https://www.freertos.org/Embedded-RTOS-Binary-Semaphores.html - * - * Please note that if the semaphore implementation is only related to - * the synchronization of one task, the new task notifications can be used, - * also see the BinSemaphUsingTask and CountingSemaphUsingTask classes. - * These use the task notification value instead of a queue and are - * faster and more efficient. - * - * @author R. Mueller - * @ingroup osal - */ -class BinarySemaphore: public SemaphoreIF, - public HasReturnvaluesIF { -public: - static const uint8_t INTERFACE_ID = CLASS_ID::SEMAPHORE_IF; - - //! @brief Default ctor - BinarySemaphore(); - //! @brief Copy ctor, deleted explicitely. - BinarySemaphore(const BinarySemaphore&) = delete; - //! @brief Copy assignment, deleted explicitely. - BinarySemaphore& operator=(const BinarySemaphore&) = delete; - //! @brief Move ctor - BinarySemaphore (BinarySemaphore &&); - //! @brief Move assignment - BinarySemaphore & operator=(BinarySemaphore &&); - //! @brief Destructor - virtual ~BinarySemaphore(); - - uint8_t getSemaphoreCounter() const override; - - /** - * Take the binary semaphore. - * If the semaphore has already been taken, the task will be blocked - * for a maximum of #timeoutMs or until the semaphore is given back, - * for example by an ISR or another task. - * @param timeoutMs - * @return -@c RETURN_OK on success - * -@c SemaphoreIF::SEMAPHORE_TIMEOUT on timeout - */ - ReturnValue_t acquire(TimeoutType timeoutType = - TimeoutType::BLOCKING, uint32_t timeoutMs = portMAX_DELAY) override; - - /** - * Same as lockBinarySemaphore() with timeout in FreeRTOS ticks. - * @param timeoutTicks - * @return -@c RETURN_OK on success - * -@c SemaphoreIF::SEMAPHORE_TIMEOUT on timeout - */ - ReturnValue_t acquireWithTickTimeout(TimeoutType timeoutType = - TimeoutType::BLOCKING, TickType_t timeoutTicks = portMAX_DELAY); - - /** - * Release the binary semaphore. - * @return -@c RETURN_OK on success - * -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if the semaphores is - * already available. - */ - ReturnValue_t release() override; - - /** - * Get Handle to the semaphore. - * @return - */ - SemaphoreHandle_t getSemaphore(); - - /** - * Wrapper function to give back semaphore from handle - * @param semaphore - * @return -@c RETURN_OK on success - * -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if the semaphores is - * already available. - */ - static ReturnValue_t release(SemaphoreHandle_t semaphore); - - /** - * Wrapper function to give back semaphore from handle when called from an ISR - * @param semaphore - * @param higherPriorityTaskWoken This will be set to pdPASS if a task with - * a higher priority was unblocked. A context switch from an ISR should - * then be requested (see TaskManagement functions) - * @return -@c RETURN_OK on success - * -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if the semaphores is - * already available. - */ - static ReturnValue_t releaseFromISR(SemaphoreHandle_t semaphore, - BaseType_t * higherPriorityTaskWoken); - -protected: - SemaphoreHandle_t handle; -}; - -#endif /* FRAMEWORK_OSAL_FREERTOS_BINARYSEMPAHORE_H_ */ +#ifndef FRAMEWORK_OSAL_FREERTOS_BINARYSEMPAHORE_H_ +#define FRAMEWORK_OSAL_FREERTOS_BINARYSEMPAHORE_H_ + +#include "../../returnvalues/HasReturnvaluesIF.h" +#include "../../tasks/SemaphoreIF.h" + +#include +#include + +/** + * @brief OS Tool to achieve synchronization of between tasks or between + * task and ISR. The default semaphore implementation creates a + * binary semaphore, which can only be taken once. + * @details + * Documentation: https://www.freertos.org/Embedded-RTOS-Binary-Semaphores.html + * + * Please note that if the semaphore implementation is only related to + * the synchronization of one task, the new task notifications can be used, + * also see the BinSemaphUsingTask and CountingSemaphUsingTask classes. + * These use the task notification value instead of a queue and are + * faster and more efficient. + * + * @author R. Mueller + * @ingroup osal + */ +class BinarySemaphore: public SemaphoreIF, + public HasReturnvaluesIF { +public: + static const uint8_t INTERFACE_ID = CLASS_ID::SEMAPHORE_IF; + + //! @brief Default ctor + BinarySemaphore(); + //! @brief Copy ctor, deleted explicitely. + BinarySemaphore(const BinarySemaphore&) = delete; + //! @brief Copy assignment, deleted explicitely. + BinarySemaphore& operator=(const BinarySemaphore&) = delete; + //! @brief Move ctor + BinarySemaphore (BinarySemaphore &&); + //! @brief Move assignment + BinarySemaphore & operator=(BinarySemaphore &&); + //! @brief Destructor + virtual ~BinarySemaphore(); + + uint8_t getSemaphoreCounter() const override; + + /** + * Take the binary semaphore. + * If the semaphore has already been taken, the task will be blocked + * for a maximum of #timeoutMs or until the semaphore is given back, + * for example by an ISR or another task. + * @param timeoutMs + * @return -@c RETURN_OK on success + * -@c SemaphoreIF::SEMAPHORE_TIMEOUT on timeout + */ + ReturnValue_t acquire(TimeoutType timeoutType = + TimeoutType::BLOCKING, uint32_t timeoutMs = portMAX_DELAY) override; + + /** + * Same as lockBinarySemaphore() with timeout in FreeRTOS ticks. + * @param timeoutTicks + * @return -@c RETURN_OK on success + * -@c SemaphoreIF::SEMAPHORE_TIMEOUT on timeout + */ + ReturnValue_t acquireWithTickTimeout(TimeoutType timeoutType = + TimeoutType::BLOCKING, TickType_t timeoutTicks = portMAX_DELAY); + + /** + * Release the binary semaphore. + * @return -@c RETURN_OK on success + * -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if the semaphores is + * already available. + */ + ReturnValue_t release() override; + + /** + * Get Handle to the semaphore. + * @return + */ + SemaphoreHandle_t getSemaphore(); + + /** + * Wrapper function to give back semaphore from handle + * @param semaphore + * @return -@c RETURN_OK on success + * -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if the semaphores is + * already available. + */ + static ReturnValue_t release(SemaphoreHandle_t semaphore); + + /** + * Wrapper function to give back semaphore from handle when called from an ISR + * @param semaphore + * @param higherPriorityTaskWoken This will be set to pdPASS if a task with + * a higher priority was unblocked. A context switch from an ISR should + * then be requested (see TaskManagement functions) + * @return -@c RETURN_OK on success + * -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if the semaphores is + * already available. + */ + static ReturnValue_t releaseFromISR(SemaphoreHandle_t semaphore, + BaseType_t * higherPriorityTaskWoken); + +protected: + SemaphoreHandle_t handle; +}; + +#endif /* FRAMEWORK_OSAL_FREERTOS_BINARYSEMPAHORE_H_ */ diff --git a/osal/FreeRTOS/CountingSemaphUsingTask.cpp b/osal/FreeRTOS/CountingSemaphUsingTask.cpp index e66671ac..a47341bc 100644 --- a/osal/FreeRTOS/CountingSemaphUsingTask.cpp +++ b/osal/FreeRTOS/CountingSemaphUsingTask.cpp @@ -1,114 +1,114 @@ -#include "../../osal/FreeRTOS/CountingSemaphUsingTask.h" -#include "../../osal/FreeRTOS/TaskManagement.h" -#include "../../serviceinterface/ServiceInterfaceStream.h" - -CountingSemaphoreUsingTask::CountingSemaphoreUsingTask(const uint8_t maxCount, - uint8_t initCount): maxCount(maxCount) { - if(initCount > maxCount) { - sif::error << "CountingSemaphoreUsingTask: Max count bigger than " - "intial cout. Setting initial count to max count." << std::endl; - initCount = maxCount; - } - - handle = TaskManagement::getCurrentTaskHandle(); - if(handle == nullptr) { - sif::error << "CountingSemaphoreUsingTask: Could not retrieve task " - "handle. Please ensure the constructor was called inside a " - "task." << std::endl; - } - - uint32_t oldNotificationValue; - xTaskNotifyAndQuery(handle, 0, eSetValueWithOverwrite, - &oldNotificationValue); - if(oldNotificationValue != 0) { - sif::warning << "CountinSemaphoreUsingTask: Semaphore initiated but " - "current notification value is not 0. Please ensure the " - "notification value is not used for other purposes!" << std::endl; - } - for(int i = 0; i < initCount; i++) { - xTaskNotifyGive(handle); - } -} - -CountingSemaphoreUsingTask::~CountingSemaphoreUsingTask() { - // Clear notification value on destruction. - // If this is not desired, don't call the destructor - // (or implement a boolean which disables the reset) - xTaskNotifyAndQuery(handle, 0, eSetValueWithOverwrite, nullptr); -} - -ReturnValue_t CountingSemaphoreUsingTask::acquire(TimeoutType timeoutType, - uint32_t timeoutMs) { - TickType_t timeout = 0; - if(timeoutType == TimeoutType::POLLING) { - timeout = 0; - } - else if(timeoutType == TimeoutType::WAITING){ - timeout = pdMS_TO_TICKS(timeoutMs); - } - else { - timeout = portMAX_DELAY; - } - return acquireWithTickTimeout(timeoutType, timeout); - -} - -ReturnValue_t CountingSemaphoreUsingTask::acquireWithTickTimeout( - TimeoutType timeoutType, TickType_t timeoutTicks) { - // Decrement notfication value without resetting it. - BaseType_t oldCount = ulTaskNotifyTake(pdFALSE, timeoutTicks); - if (getSemaphoreCounter() == oldCount - 1) { - return HasReturnvaluesIF::RETURN_OK; - } - else { - return SemaphoreIF::SEMAPHORE_TIMEOUT; - } -} - -ReturnValue_t CountingSemaphoreUsingTask::release() { - if(getSemaphoreCounter() == maxCount) { - return SemaphoreIF::SEMAPHORE_NOT_OWNED; - } - return release(handle); -} - -ReturnValue_t CountingSemaphoreUsingTask::release( - TaskHandle_t taskToNotify) { - BaseType_t returncode = xTaskNotifyGive(taskToNotify); - if (returncode == pdPASS) { - return HasReturnvaluesIF::RETURN_OK; - } - else { - // This should never happen. - return HasReturnvaluesIF::RETURN_FAILED; - } -} - - -uint8_t CountingSemaphoreUsingTask::getSemaphoreCounter() const { - uint32_t notificationValue = 0; - xTaskNotifyAndQuery(handle, 0, eNoAction, ¬ificationValue); - return notificationValue; -} - -TaskHandle_t CountingSemaphoreUsingTask::getTaskHandle() { - return handle; -} - -ReturnValue_t CountingSemaphoreUsingTask::releaseFromISR( - TaskHandle_t taskToNotify, BaseType_t* higherPriorityTaskWoken) { - vTaskNotifyGiveFromISR(taskToNotify, higherPriorityTaskWoken); - return HasReturnvaluesIF::RETURN_OK; -} - -uint8_t CountingSemaphoreUsingTask::getSemaphoreCounterFromISR( - TaskHandle_t task, BaseType_t* higherPriorityTaskWoken) { - uint32_t notificationValue; - xTaskNotifyAndQueryFromISR(task, 0, eNoAction, ¬ificationValue, - higherPriorityTaskWoken); - return notificationValue; -} - -uint8_t CountingSemaphoreUsingTask::getMaxCount() const { - return maxCount; -} +#include "../../osal/FreeRTOS/CountingSemaphUsingTask.h" +#include "../../osal/FreeRTOS/TaskManagement.h" +#include "../../serviceinterface/ServiceInterfaceStream.h" + +CountingSemaphoreUsingTask::CountingSemaphoreUsingTask(const uint8_t maxCount, + uint8_t initCount): maxCount(maxCount) { + if(initCount > maxCount) { + sif::error << "CountingSemaphoreUsingTask: Max count bigger than " + "intial cout. Setting initial count to max count." << std::endl; + initCount = maxCount; + } + + handle = TaskManagement::getCurrentTaskHandle(); + if(handle == nullptr) { + sif::error << "CountingSemaphoreUsingTask: Could not retrieve task " + "handle. Please ensure the constructor was called inside a " + "task." << std::endl; + } + + uint32_t oldNotificationValue; + xTaskNotifyAndQuery(handle, 0, eSetValueWithOverwrite, + &oldNotificationValue); + if(oldNotificationValue != 0) { + sif::warning << "CountinSemaphoreUsingTask: Semaphore initiated but " + "current notification value is not 0. Please ensure the " + "notification value is not used for other purposes!" << std::endl; + } + for(int i = 0; i < initCount; i++) { + xTaskNotifyGive(handle); + } +} + +CountingSemaphoreUsingTask::~CountingSemaphoreUsingTask() { + // Clear notification value on destruction. + // If this is not desired, don't call the destructor + // (or implement a boolean which disables the reset) + xTaskNotifyAndQuery(handle, 0, eSetValueWithOverwrite, nullptr); +} + +ReturnValue_t CountingSemaphoreUsingTask::acquire(TimeoutType timeoutType, + uint32_t timeoutMs) { + TickType_t timeout = 0; + if(timeoutType == TimeoutType::POLLING) { + timeout = 0; + } + else if(timeoutType == TimeoutType::WAITING){ + timeout = pdMS_TO_TICKS(timeoutMs); + } + else { + timeout = portMAX_DELAY; + } + return acquireWithTickTimeout(timeoutType, timeout); + +} + +ReturnValue_t CountingSemaphoreUsingTask::acquireWithTickTimeout( + TimeoutType timeoutType, TickType_t timeoutTicks) { + // Decrement notfication value without resetting it. + BaseType_t oldCount = ulTaskNotifyTake(pdFALSE, timeoutTicks); + if (getSemaphoreCounter() == oldCount - 1) { + return HasReturnvaluesIF::RETURN_OK; + } + else { + return SemaphoreIF::SEMAPHORE_TIMEOUT; + } +} + +ReturnValue_t CountingSemaphoreUsingTask::release() { + if(getSemaphoreCounter() == maxCount) { + return SemaphoreIF::SEMAPHORE_NOT_OWNED; + } + return release(handle); +} + +ReturnValue_t CountingSemaphoreUsingTask::release( + TaskHandle_t taskToNotify) { + BaseType_t returncode = xTaskNotifyGive(taskToNotify); + if (returncode == pdPASS) { + return HasReturnvaluesIF::RETURN_OK; + } + else { + // This should never happen. + return HasReturnvaluesIF::RETURN_FAILED; + } +} + + +uint8_t CountingSemaphoreUsingTask::getSemaphoreCounter() const { + uint32_t notificationValue = 0; + xTaskNotifyAndQuery(handle, 0, eNoAction, ¬ificationValue); + return notificationValue; +} + +TaskHandle_t CountingSemaphoreUsingTask::getTaskHandle() { + return handle; +} + +ReturnValue_t CountingSemaphoreUsingTask::releaseFromISR( + TaskHandle_t taskToNotify, BaseType_t* higherPriorityTaskWoken) { + vTaskNotifyGiveFromISR(taskToNotify, higherPriorityTaskWoken); + return HasReturnvaluesIF::RETURN_OK; +} + +uint8_t CountingSemaphoreUsingTask::getSemaphoreCounterFromISR( + TaskHandle_t task, BaseType_t* higherPriorityTaskWoken) { + uint32_t notificationValue; + xTaskNotifyAndQueryFromISR(task, 0, eNoAction, ¬ificationValue, + higherPriorityTaskWoken); + return notificationValue; +} + +uint8_t CountingSemaphoreUsingTask::getMaxCount() const { + return maxCount; +} diff --git a/osal/FreeRTOS/CountingSemaphUsingTask.h b/osal/FreeRTOS/CountingSemaphUsingTask.h index e3733382..8977258c 100644 --- a/osal/FreeRTOS/CountingSemaphUsingTask.h +++ b/osal/FreeRTOS/CountingSemaphUsingTask.h @@ -1,102 +1,102 @@ -#ifndef FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHUSINGTASK_H_ -#define FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHUSINGTASK_H_ - -#include "../../osal/FreeRTOS/CountingSemaphUsingTask.h" -#include "../../tasks/SemaphoreIF.h" - -extern "C" { -#include -#include -} - -/** - * @brief Couting Semaphore implementation which uses the notification value - * of the task. The notification value should therefore not be used - * for other purposes. - * @details - * Additional information: https://www.freertos.org/RTOS-task-notifications.html - * and general semaphore documentation. - */ -class CountingSemaphoreUsingTask: public SemaphoreIF { -public: - CountingSemaphoreUsingTask(const uint8_t maxCount, uint8_t initCount); - virtual ~CountingSemaphoreUsingTask(); - - /** - * Acquire the counting semaphore. - * If no semaphores are available, the task will be blocked - * for a maximum of #timeoutMs or until one is given back, - * for example by an ISR or another task. - * @param timeoutMs - * @return -@c RETURN_OK on success - * -@c SemaphoreIF::SEMAPHORE_TIMEOUT on timeout - */ - ReturnValue_t acquire(TimeoutType timeoutType = TimeoutType::BLOCKING, - uint32_t timeoutMs = portMAX_DELAY) override; - - /** - * Release a semaphore, increasing the number of available counting - * semaphores up to the #maxCount value. - * @return -@c RETURN_OK on success - * -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if #maxCount semaphores are - * already available. - */ - ReturnValue_t release() override; - - uint8_t getSemaphoreCounter() const override; - /** - * Get the semaphore counter from an ISR. - * @param task - * @param higherPriorityTaskWoken This will be set to pdPASS if a task with - * a higher priority was unblocked. A context switch should be requested - * from an ISR if this is the case (see TaskManagement functions) - * @return - */ - static uint8_t getSemaphoreCounterFromISR(TaskHandle_t task, - BaseType_t* higherPriorityTaskWoken); - - /** - * Acquire with a timeout value in ticks - * @param timeoutTicks - * @return -@c RETURN_OK on success - * -@c SemaphoreIF::SEMAPHORE_TIMEOUT on timeout - */ - ReturnValue_t acquireWithTickTimeout( - TimeoutType timeoutType = TimeoutType::BLOCKING, - TickType_t timeoutTicks = portMAX_DELAY); - - /** - * Get handle to the task related to the semaphore. - * @return - */ - TaskHandle_t getTaskHandle(); - - /** - * Release semaphore of task by supplying task handle - * @param taskToNotify - * @return -@c RETURN_OK on success - * -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if #maxCount semaphores are - * already available. - */ - static ReturnValue_t release(TaskHandle_t taskToNotify); - /** - * Release seamphore of a task from an ISR. - * @param taskToNotify - * @param higherPriorityTaskWoken This will be set to pdPASS if a task with - * a higher priority was unblocked. A context switch should be requested - * from an ISR if this is the case (see TaskManagement functions) - * @return -@c RETURN_OK on success - * -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if #maxCount semaphores are - * already available. - */ - static ReturnValue_t releaseFromISR(TaskHandle_t taskToNotify, - BaseType_t* higherPriorityTaskWoken); - - uint8_t getMaxCount() const; - -private: - TaskHandle_t handle; - const uint8_t maxCount; -}; - -#endif /* FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHUSINGTASK_H_ */ +#ifndef FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHUSINGTASK_H_ +#define FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHUSINGTASK_H_ + +#include "../../osal/FreeRTOS/CountingSemaphUsingTask.h" +#include "../../tasks/SemaphoreIF.h" + +extern "C" { +#include +#include +} + +/** + * @brief Couting Semaphore implementation which uses the notification value + * of the task. The notification value should therefore not be used + * for other purposes. + * @details + * Additional information: https://www.freertos.org/RTOS-task-notifications.html + * and general semaphore documentation. + */ +class CountingSemaphoreUsingTask: public SemaphoreIF { +public: + CountingSemaphoreUsingTask(const uint8_t maxCount, uint8_t initCount); + virtual ~CountingSemaphoreUsingTask(); + + /** + * Acquire the counting semaphore. + * If no semaphores are available, the task will be blocked + * for a maximum of #timeoutMs or until one is given back, + * for example by an ISR or another task. + * @param timeoutMs + * @return -@c RETURN_OK on success + * -@c SemaphoreIF::SEMAPHORE_TIMEOUT on timeout + */ + ReturnValue_t acquire(TimeoutType timeoutType = TimeoutType::BLOCKING, + uint32_t timeoutMs = portMAX_DELAY) override; + + /** + * Release a semaphore, increasing the number of available counting + * semaphores up to the #maxCount value. + * @return -@c RETURN_OK on success + * -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if #maxCount semaphores are + * already available. + */ + ReturnValue_t release() override; + + uint8_t getSemaphoreCounter() const override; + /** + * Get the semaphore counter from an ISR. + * @param task + * @param higherPriorityTaskWoken This will be set to pdPASS if a task with + * a higher priority was unblocked. A context switch should be requested + * from an ISR if this is the case (see TaskManagement functions) + * @return + */ + static uint8_t getSemaphoreCounterFromISR(TaskHandle_t task, + BaseType_t* higherPriorityTaskWoken); + + /** + * Acquire with a timeout value in ticks + * @param timeoutTicks + * @return -@c RETURN_OK on success + * -@c SemaphoreIF::SEMAPHORE_TIMEOUT on timeout + */ + ReturnValue_t acquireWithTickTimeout( + TimeoutType timeoutType = TimeoutType::BLOCKING, + TickType_t timeoutTicks = portMAX_DELAY); + + /** + * Get handle to the task related to the semaphore. + * @return + */ + TaskHandle_t getTaskHandle(); + + /** + * Release semaphore of task by supplying task handle + * @param taskToNotify + * @return -@c RETURN_OK on success + * -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if #maxCount semaphores are + * already available. + */ + static ReturnValue_t release(TaskHandle_t taskToNotify); + /** + * Release seamphore of a task from an ISR. + * @param taskToNotify + * @param higherPriorityTaskWoken This will be set to pdPASS if a task with + * a higher priority was unblocked. A context switch should be requested + * from an ISR if this is the case (see TaskManagement functions) + * @return -@c RETURN_OK on success + * -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if #maxCount semaphores are + * already available. + */ + static ReturnValue_t releaseFromISR(TaskHandle_t taskToNotify, + BaseType_t* higherPriorityTaskWoken); + + uint8_t getMaxCount() const; + +private: + TaskHandle_t handle; + const uint8_t maxCount; +}; + +#endif /* FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHUSINGTASK_H_ */ diff --git a/osal/FreeRTOS/CountingSemaphore.cpp b/osal/FreeRTOS/CountingSemaphore.cpp index 0b218e54..d1310a6a 100644 --- a/osal/FreeRTOS/CountingSemaphore.cpp +++ b/osal/FreeRTOS/CountingSemaphore.cpp @@ -1,43 +1,43 @@ -#include "../../osal/FreeRTOS/CountingSemaphore.h" -#include "../../serviceinterface/ServiceInterfaceStream.h" -#include "../../osal/FreeRTOS/TaskManagement.h" - -#include - -// Make sure #define configUSE_COUNTING_SEMAPHORES 1 is set in -// free FreeRTOSConfig.h file. -CountingSemaphore::CountingSemaphore(const uint8_t maxCount, uint8_t initCount): - maxCount(maxCount), initCount(initCount) { - if(initCount > maxCount) { - sif::error << "CountingSemaphoreUsingTask: Max count bigger than " - "intial cout. Setting initial count to max count." << std::endl; - initCount = maxCount; - } - - handle = xSemaphoreCreateCounting(maxCount, initCount); - if(handle == nullptr) { - sif::error << "CountingSemaphore: Creation failure" << std::endl; - } -} - -CountingSemaphore::CountingSemaphore(CountingSemaphore&& other): - maxCount(other.maxCount), initCount(other.initCount) { - handle = xSemaphoreCreateCounting(other.maxCount, other.initCount); - if(handle == nullptr) { - sif::error << "CountingSemaphore: Creation failure" << std::endl; - } -} - -CountingSemaphore& CountingSemaphore::operator =( - CountingSemaphore&& other) { - handle = xSemaphoreCreateCounting(other.maxCount, other.initCount); - if(handle == nullptr) { - sif::error << "CountingSemaphore: Creation failure" << std::endl; - } - return * this; -} - - -uint8_t CountingSemaphore::getMaxCount() const { - return maxCount; -} +#include "../../osal/FreeRTOS/CountingSemaphore.h" +#include "../../serviceinterface/ServiceInterfaceStream.h" +#include "../../osal/FreeRTOS/TaskManagement.h" + +#include + +// Make sure #define configUSE_COUNTING_SEMAPHORES 1 is set in +// free FreeRTOSConfig.h file. +CountingSemaphore::CountingSemaphore(const uint8_t maxCount, uint8_t initCount): + maxCount(maxCount), initCount(initCount) { + if(initCount > maxCount) { + sif::error << "CountingSemaphoreUsingTask: Max count bigger than " + "intial cout. Setting initial count to max count." << std::endl; + initCount = maxCount; + } + + handle = xSemaphoreCreateCounting(maxCount, initCount); + if(handle == nullptr) { + sif::error << "CountingSemaphore: Creation failure" << std::endl; + } +} + +CountingSemaphore::CountingSemaphore(CountingSemaphore&& other): + maxCount(other.maxCount), initCount(other.initCount) { + handle = xSemaphoreCreateCounting(other.maxCount, other.initCount); + if(handle == nullptr) { + sif::error << "CountingSemaphore: Creation failure" << std::endl; + } +} + +CountingSemaphore& CountingSemaphore::operator =( + CountingSemaphore&& other) { + handle = xSemaphoreCreateCounting(other.maxCount, other.initCount); + if(handle == nullptr) { + sif::error << "CountingSemaphore: Creation failure" << std::endl; + } + return * this; +} + + +uint8_t CountingSemaphore::getMaxCount() const { + return maxCount; +} diff --git a/osal/FreeRTOS/CountingSemaphore.h b/osal/FreeRTOS/CountingSemaphore.h index 9432ed81..ae2f62ae 100644 --- a/osal/FreeRTOS/CountingSemaphore.h +++ b/osal/FreeRTOS/CountingSemaphore.h @@ -1,34 +1,34 @@ -#ifndef FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHORE_H_ -#define FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHORE_H_ -#include "../../osal/FreeRTOS/BinarySemaphore.h" - -/** - * @brief Counting semaphores, which can be acquire more than once. - * @details - * See: https://www.freertos.org/CreateCounting.html - * API of counting semaphores is almost identical to binary semaphores, - * so we just inherit from binary semaphore and provide the respective - * constructors. - */ -class CountingSemaphore: public BinarySemaphore { -public: - CountingSemaphore(const uint8_t maxCount, uint8_t initCount); - //! @brief Copy ctor, disabled - CountingSemaphore(const CountingSemaphore&) = delete; - //! @brief Copy assignment, disabled - CountingSemaphore& operator=(const CountingSemaphore&) = delete; - //! @brief Move ctor - CountingSemaphore (CountingSemaphore &&); - //! @brief Move assignment - CountingSemaphore & operator=(CountingSemaphore &&); - - /* Same API as binary semaphore otherwise. acquire() can be called - * until there are not semaphores left and release() can be called - * until maxCount is reached. */ - uint8_t getMaxCount() const; -private: - const uint8_t maxCount; - uint8_t initCount = 0; -}; - -#endif /* FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHORE_H_ */ +#ifndef FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHORE_H_ +#define FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHORE_H_ +#include "../../osal/FreeRTOS/BinarySemaphore.h" + +/** + * @brief Counting semaphores, which can be acquire more than once. + * @details + * See: https://www.freertos.org/CreateCounting.html + * API of counting semaphores is almost identical to binary semaphores, + * so we just inherit from binary semaphore and provide the respective + * constructors. + */ +class CountingSemaphore: public BinarySemaphore { +public: + CountingSemaphore(const uint8_t maxCount, uint8_t initCount); + //! @brief Copy ctor, disabled + CountingSemaphore(const CountingSemaphore&) = delete; + //! @brief Copy assignment, disabled + CountingSemaphore& operator=(const CountingSemaphore&) = delete; + //! @brief Move ctor + CountingSemaphore (CountingSemaphore &&); + //! @brief Move assignment + CountingSemaphore & operator=(CountingSemaphore &&); + + /* Same API as binary semaphore otherwise. acquire() can be called + * until there are not semaphores left and release() can be called + * until maxCount is reached. */ + uint8_t getMaxCount() const; +private: + const uint8_t maxCount; + uint8_t initCount = 0; +}; + +#endif /* FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHORE_H_ */ diff --git a/osal/FreeRTOS/SemaphoreFactory.cpp b/osal/FreeRTOS/SemaphoreFactory.cpp index 8575cf4a..beb0d096 100644 --- a/osal/FreeRTOS/SemaphoreFactory.cpp +++ b/osal/FreeRTOS/SemaphoreFactory.cpp @@ -1,59 +1,59 @@ -#include "../../osal/FreeRTOS/BinarySemaphore.h" -#include "../../osal/FreeRTOS/BinSemaphUsingTask.h" -#include "../../osal/FreeRTOS/CountingSemaphore.h" -#include "../../osal/FreeRTOS/CountingSemaphUsingTask.h" -#include "../../tasks/SemaphoreFactory.h" -#include "../../serviceinterface/ServiceInterfaceStream.h" - -SemaphoreFactory* SemaphoreFactory::factoryInstance = nullptr; - -static const uint32_t USE_REGULAR_SEMAPHORES = 0; -static const uint32_t USE_TASK_NOTIFICATIONS = 1; - -SemaphoreFactory::SemaphoreFactory() { -} - -SemaphoreFactory::~SemaphoreFactory() { - delete factoryInstance; -} - -SemaphoreFactory* SemaphoreFactory::instance() { - if (factoryInstance == nullptr){ - factoryInstance = new SemaphoreFactory(); - } - return SemaphoreFactory::factoryInstance; -} - -SemaphoreIF* SemaphoreFactory::createBinarySemaphore(uint32_t argument) { - if(argument == USE_REGULAR_SEMAPHORES) { - return new BinarySemaphore(); - } - else if(argument == USE_TASK_NOTIFICATIONS) { - return new BinarySemaphoreUsingTask(); - } - else { - sif::warning << "SemaphoreFactory: Invalid argument, return regular" - "binary semaphore" << std::endl; - return new BinarySemaphore(); - } -} - -SemaphoreIF* SemaphoreFactory::createCountingSemaphore(uint8_t maxCount, - uint8_t initCount, uint32_t argument) { - if(argument == USE_REGULAR_SEMAPHORES) { - return new CountingSemaphore(maxCount, initCount); - } - else if(argument == USE_TASK_NOTIFICATIONS) { - return new CountingSemaphoreUsingTask(maxCount, initCount); - } - else { - sif::warning << "SemaphoreFactory: Invalid argument, return regular" - "binary semaphore" << std::endl; - return new CountingSemaphore(maxCount, initCount); - } - -} - -void SemaphoreFactory::deleteSemaphore(SemaphoreIF* semaphore) { - delete semaphore; -} +#include "../../osal/FreeRTOS/BinarySemaphore.h" +#include "../../osal/FreeRTOS/BinSemaphUsingTask.h" +#include "../../osal/FreeRTOS/CountingSemaphore.h" +#include "../../osal/FreeRTOS/CountingSemaphUsingTask.h" +#include "../../tasks/SemaphoreFactory.h" +#include "../../serviceinterface/ServiceInterfaceStream.h" + +SemaphoreFactory* SemaphoreFactory::factoryInstance = nullptr; + +static const uint32_t USE_REGULAR_SEMAPHORES = 0; +static const uint32_t USE_TASK_NOTIFICATIONS = 1; + +SemaphoreFactory::SemaphoreFactory() { +} + +SemaphoreFactory::~SemaphoreFactory() { + delete factoryInstance; +} + +SemaphoreFactory* SemaphoreFactory::instance() { + if (factoryInstance == nullptr){ + factoryInstance = new SemaphoreFactory(); + } + return SemaphoreFactory::factoryInstance; +} + +SemaphoreIF* SemaphoreFactory::createBinarySemaphore(uint32_t argument) { + if(argument == USE_REGULAR_SEMAPHORES) { + return new BinarySemaphore(); + } + else if(argument == USE_TASK_NOTIFICATIONS) { + return new BinarySemaphoreUsingTask(); + } + else { + sif::warning << "SemaphoreFactory: Invalid argument, return regular" + "binary semaphore" << std::endl; + return new BinarySemaphore(); + } +} + +SemaphoreIF* SemaphoreFactory::createCountingSemaphore(uint8_t maxCount, + uint8_t initCount, uint32_t argument) { + if(argument == USE_REGULAR_SEMAPHORES) { + return new CountingSemaphore(maxCount, initCount); + } + else if(argument == USE_TASK_NOTIFICATIONS) { + return new CountingSemaphoreUsingTask(maxCount, initCount); + } + else { + sif::warning << "SemaphoreFactory: Invalid argument, return regular" + "binary semaphore" << std::endl; + return new CountingSemaphore(maxCount, initCount); + } + +} + +void SemaphoreFactory::deleteSemaphore(SemaphoreIF* semaphore) { + delete semaphore; +} diff --git a/osal/FreeRTOS/TaskManagement.cpp b/osal/FreeRTOS/TaskManagement.cpp index 16682d36..b77f12a9 100644 --- a/osal/FreeRTOS/TaskManagement.cpp +++ b/osal/FreeRTOS/TaskManagement.cpp @@ -1,24 +1,24 @@ -#include "../../osal/FreeRTOS/TaskManagement.h" - -void TaskManagement::vRequestContextSwitchFromTask() { - vTaskDelay(0); -} - -void TaskManagement::requestContextSwitch( - CallContext callContext = CallContext::TASK) { - if(callContext == CallContext::ISR) { - // This function depends on the partmacro.h definition for the specific device - vRequestContextSwitchFromISR(); - } else { - vRequestContextSwitchFromTask(); - } -} - -TaskHandle_t TaskManagement::getCurrentTaskHandle() { - return xTaskGetCurrentTaskHandle(); -} - -size_t TaskManagement::getTaskStackHighWatermark( - TaskHandle_t task) { - return uxTaskGetStackHighWaterMark(task) * sizeof(StackType_t); -} +#include "../../osal/FreeRTOS/TaskManagement.h" + +void TaskManagement::vRequestContextSwitchFromTask() { + vTaskDelay(0); +} + +void TaskManagement::requestContextSwitch( + CallContext callContext = CallContext::TASK) { + if(callContext == CallContext::ISR) { + // This function depends on the partmacro.h definition for the specific device + vRequestContextSwitchFromISR(); + } else { + vRequestContextSwitchFromTask(); + } +} + +TaskHandle_t TaskManagement::getCurrentTaskHandle() { + return xTaskGetCurrentTaskHandle(); +} + +size_t TaskManagement::getTaskStackHighWatermark( + TaskHandle_t task) { + return uxTaskGetStackHighWaterMark(task) * sizeof(StackType_t); +} diff --git a/osal/FreeRTOS/TaskManagement.h b/osal/FreeRTOS/TaskManagement.h index 43003d76..4b7fe3eb 100644 --- a/osal/FreeRTOS/TaskManagement.h +++ b/osal/FreeRTOS/TaskManagement.h @@ -1,64 +1,64 @@ -#ifndef FRAMEWORK_OSAL_FREERTOS_TASKMANAGEMENT_H_ -#define FRAMEWORK_OSAL_FREERTOS_TASKMANAGEMENT_H_ - -#include "../../returnvalues/HasReturnvaluesIF.h" - -extern "C" { -#include -#include -} -#include - -/** - * Architecture dependant portmacro.h function call. - * Should be implemented in bsp. - */ -extern void vRequestContextSwitchFromISR(); - -/*! - * Used by functions to tell if they are being called from - * within an ISR or from a regular task. This is required because FreeRTOS - * has different functions for handling semaphores and messages from within - * an ISR and task. - */ -enum class CallContext { - TASK = 0x00,//!< task_context - ISR = 0xFF //!< isr_context -}; - - -class TaskManagement { -public: - /** - * @brief In this function, a function dependant on the portmacro.h header - * function calls to request a context switch can be specified. - * This can be used if sending to the queue from an ISR caused a task - * to unblock and a context switch is required. - */ - static void requestContextSwitch(CallContext callContext); - - /** - * If task preemption in FreeRTOS is disabled, a context switch - * can be requested manually by calling this function. - */ - static void vRequestContextSwitchFromTask(void); - - /** - * @return The current task handle - */ - static TaskHandle_t getCurrentTaskHandle(); - - /** - * Get returns the minimum amount of remaining stack space in words - * that was a available to the task since the task started executing. - * Please note that the actual value in bytes depends - * on the stack depth type. - * E.g. on a 32 bit machine, a value of 200 means 800 bytes. - * @return Smallest value of stack remaining since the task was started in - * words. - */ - static size_t getTaskStackHighWatermark( - TaskHandle_t task = nullptr); -}; - -#endif /* FRAMEWORK_OSAL_FREERTOS_TASKMANAGEMENT_H_ */ +#ifndef FRAMEWORK_OSAL_FREERTOS_TASKMANAGEMENT_H_ +#define FRAMEWORK_OSAL_FREERTOS_TASKMANAGEMENT_H_ + +#include "../../returnvalues/HasReturnvaluesIF.h" + +extern "C" { +#include +#include +} +#include + +/** + * Architecture dependant portmacro.h function call. + * Should be implemented in bsp. + */ +extern void vRequestContextSwitchFromISR(); + +/*! + * Used by functions to tell if they are being called from + * within an ISR or from a regular task. This is required because FreeRTOS + * has different functions for handling semaphores and messages from within + * an ISR and task. + */ +enum class CallContext { + TASK = 0x00,//!< task_context + ISR = 0xFF //!< isr_context +}; + + +class TaskManagement { +public: + /** + * @brief In this function, a function dependant on the portmacro.h header + * function calls to request a context switch can be specified. + * This can be used if sending to the queue from an ISR caused a task + * to unblock and a context switch is required. + */ + static void requestContextSwitch(CallContext callContext); + + /** + * If task preemption in FreeRTOS is disabled, a context switch + * can be requested manually by calling this function. + */ + static void vRequestContextSwitchFromTask(void); + + /** + * @return The current task handle + */ + static TaskHandle_t getCurrentTaskHandle(); + + /** + * Get returns the minimum amount of remaining stack space in words + * that was a available to the task since the task started executing. + * Please note that the actual value in bytes depends + * on the stack depth type. + * E.g. on a 32 bit machine, a value of 200 means 800 bytes. + * @return Smallest value of stack remaining since the task was started in + * words. + */ + static size_t getTaskStackHighWatermark( + TaskHandle_t task = nullptr); +}; + +#endif /* FRAMEWORK_OSAL_FREERTOS_TASKMANAGEMENT_H_ */ diff --git a/osal/linux/BinarySemaphore.cpp b/osal/linux/BinarySemaphore.cpp index 5216ff37..8c0eeae7 100644 --- a/osal/linux/BinarySemaphore.cpp +++ b/osal/linux/BinarySemaphore.cpp @@ -1,149 +1,149 @@ -#include "../../osal/linux/BinarySemaphore.h" -#include "../../serviceinterface/ServiceInterfaceStream.h" - -extern "C" { -#include -#include -} - -BinarySemaphore::BinarySemaphore() { - // Using unnamed semaphores for now - initSemaphore(); -} - -BinarySemaphore::~BinarySemaphore() { - sem_destroy(&handle); -} - -BinarySemaphore::BinarySemaphore(BinarySemaphore&& s) { - initSemaphore(); -} - -BinarySemaphore& BinarySemaphore::operator =( - BinarySemaphore&& s) { - initSemaphore(); - return * this; -} - -ReturnValue_t BinarySemaphore::acquire(TimeoutType timeoutType, - uint32_t timeoutMs) { - int result = 0; - if(timeoutType == TimeoutType::POLLING) { - result = sem_trywait(&handle); - } - else if(timeoutType == TimeoutType::BLOCKING) { - result = sem_wait(&handle); - } - else if(timeoutType == TimeoutType::WAITING){ - timespec timeOut; - clock_gettime(CLOCK_REALTIME, &timeOut); - uint64_t nseconds = timeOut.tv_sec * 1000000000 + timeOut.tv_nsec; - nseconds += timeoutMs * 1000000; - timeOut.tv_sec = nseconds / 1000000000; - timeOut.tv_nsec = nseconds - timeOut.tv_sec * 1000000000; - result = sem_timedwait(&handle, &timeOut); - if(result != 0 and errno == EINVAL) { - sif::debug << "BinarySemaphore::acquire: Invalid time value possible" - << std::endl; - } - } - if(result == 0) { - return HasReturnvaluesIF::RETURN_OK; - } - - switch(errno) { - case(EAGAIN): - // Operation could not be performed without blocking (for sem_trywait) - case(ETIMEDOUT): - // Semaphore is 0 - return SemaphoreIF::SEMAPHORE_TIMEOUT; - case(EINVAL): - // Semaphore invalid - return SemaphoreIF::SEMAPHORE_INVALID; - case(EINTR): - // Call was interrupted by signal handler - sif::debug << "BinarySemaphore::acquire: Signal handler interrupted." - "Code " << strerror(errno) << std::endl; - /* No break */ - default: - return HasReturnvaluesIF::RETURN_FAILED; - } -} - -ReturnValue_t BinarySemaphore::release() { - return BinarySemaphore::release(&this->handle); -} - -ReturnValue_t BinarySemaphore::release(sem_t *handle) { - ReturnValue_t countResult = checkCount(handle, 1); - if(countResult != HasReturnvaluesIF::RETURN_OK) { - return countResult; - } - - int result = sem_post(handle); - if(result == 0) { - return HasReturnvaluesIF::RETURN_OK; - } - - switch(errno) { - case(EINVAL): - // Semaphore invalid - return SemaphoreIF::SEMAPHORE_INVALID; - case(EOVERFLOW): - // SEM_MAX_VALUE overflow. This should never happen - default: - return HasReturnvaluesIF::RETURN_FAILED; - } -} - -uint8_t BinarySemaphore::getSemaphoreCounter() const { - // And another ugly cast :-D - return getSemaphoreCounter(const_cast(&this->handle)); -} - -uint8_t BinarySemaphore::getSemaphoreCounter(sem_t *handle) { - int value = 0; - int result = sem_getvalue(handle, &value); - if (result == 0) { - return value; - } - else if(result != 0 and errno == EINVAL) { - // Could be called from interrupt, use lightweight printf - printf("BinarySemaphore::getSemaphoreCounter: Invalid semaphore\n"); - return 0; - } - else { - // This should never happen. - return 0; - } -} - -void BinarySemaphore::initSemaphore(uint8_t initCount) { - auto result = sem_init(&handle, true, initCount); - if(result == -1) { - switch(errno) { - case(EINVAL): - // Value exceeds SEM_VALUE_MAX - case(ENOSYS): - // System does not support process-shared semaphores - sif::error << "BinarySemaphore: Init failed with" << strerror(errno) - << std::endl; - } - } -} - -ReturnValue_t BinarySemaphore::checkCount(sem_t* handle, uint8_t maxCount) { - int value = getSemaphoreCounter(handle); - if(value >= maxCount) { - if(maxCount == 1 and value > 1) { - // Binary Semaphore special case. - // This is a config error use lightweight printf is this is called - // from an interrupt - printf("BinarySemaphore::release: Value of binary semaphore greater" - " than 1!\n"); - return HasReturnvaluesIF::RETURN_FAILED; - } - return SemaphoreIF::SEMAPHORE_NOT_OWNED; - } - return HasReturnvaluesIF::RETURN_OK; -} +#include "../../osal/linux/BinarySemaphore.h" +#include "../../serviceinterface/ServiceInterfaceStream.h" + +extern "C" { +#include +#include +} + +BinarySemaphore::BinarySemaphore() { + // Using unnamed semaphores for now + initSemaphore(); +} + +BinarySemaphore::~BinarySemaphore() { + sem_destroy(&handle); +} + +BinarySemaphore::BinarySemaphore(BinarySemaphore&& s) { + initSemaphore(); +} + +BinarySemaphore& BinarySemaphore::operator =( + BinarySemaphore&& s) { + initSemaphore(); + return * this; +} + +ReturnValue_t BinarySemaphore::acquire(TimeoutType timeoutType, + uint32_t timeoutMs) { + int result = 0; + if(timeoutType == TimeoutType::POLLING) { + result = sem_trywait(&handle); + } + else if(timeoutType == TimeoutType::BLOCKING) { + result = sem_wait(&handle); + } + else if(timeoutType == TimeoutType::WAITING){ + timespec timeOut; + clock_gettime(CLOCK_REALTIME, &timeOut); + uint64_t nseconds = timeOut.tv_sec * 1000000000 + timeOut.tv_nsec; + nseconds += timeoutMs * 1000000; + timeOut.tv_sec = nseconds / 1000000000; + timeOut.tv_nsec = nseconds - timeOut.tv_sec * 1000000000; + result = sem_timedwait(&handle, &timeOut); + if(result != 0 and errno == EINVAL) { + sif::debug << "BinarySemaphore::acquire: Invalid time value possible" + << std::endl; + } + } + if(result == 0) { + return HasReturnvaluesIF::RETURN_OK; + } + + switch(errno) { + case(EAGAIN): + // Operation could not be performed without blocking (for sem_trywait) + case(ETIMEDOUT): + // Semaphore is 0 + return SemaphoreIF::SEMAPHORE_TIMEOUT; + case(EINVAL): + // Semaphore invalid + return SemaphoreIF::SEMAPHORE_INVALID; + case(EINTR): + // Call was interrupted by signal handler + sif::debug << "BinarySemaphore::acquire: Signal handler interrupted." + "Code " << strerror(errno) << std::endl; + /* No break */ + default: + return HasReturnvaluesIF::RETURN_FAILED; + } +} + +ReturnValue_t BinarySemaphore::release() { + return BinarySemaphore::release(&this->handle); +} + +ReturnValue_t BinarySemaphore::release(sem_t *handle) { + ReturnValue_t countResult = checkCount(handle, 1); + if(countResult != HasReturnvaluesIF::RETURN_OK) { + return countResult; + } + + int result = sem_post(handle); + if(result == 0) { + return HasReturnvaluesIF::RETURN_OK; + } + + switch(errno) { + case(EINVAL): + // Semaphore invalid + return SemaphoreIF::SEMAPHORE_INVALID; + case(EOVERFLOW): + // SEM_MAX_VALUE overflow. This should never happen + default: + return HasReturnvaluesIF::RETURN_FAILED; + } +} + +uint8_t BinarySemaphore::getSemaphoreCounter() const { + // And another ugly cast :-D + return getSemaphoreCounter(const_cast(&this->handle)); +} + +uint8_t BinarySemaphore::getSemaphoreCounter(sem_t *handle) { + int value = 0; + int result = sem_getvalue(handle, &value); + if (result == 0) { + return value; + } + else if(result != 0 and errno == EINVAL) { + // Could be called from interrupt, use lightweight printf + printf("BinarySemaphore::getSemaphoreCounter: Invalid semaphore\n"); + return 0; + } + else { + // This should never happen. + return 0; + } +} + +void BinarySemaphore::initSemaphore(uint8_t initCount) { + auto result = sem_init(&handle, true, initCount); + if(result == -1) { + switch(errno) { + case(EINVAL): + // Value exceeds SEM_VALUE_MAX + case(ENOSYS): + // System does not support process-shared semaphores + sif::error << "BinarySemaphore: Init failed with" << strerror(errno) + << std::endl; + } + } +} + +ReturnValue_t BinarySemaphore::checkCount(sem_t* handle, uint8_t maxCount) { + int value = getSemaphoreCounter(handle); + if(value >= maxCount) { + if(maxCount == 1 and value > 1) { + // Binary Semaphore special case. + // This is a config error use lightweight printf is this is called + // from an interrupt + printf("BinarySemaphore::release: Value of binary semaphore greater" + " than 1!\n"); + return HasReturnvaluesIF::RETURN_FAILED; + } + return SemaphoreIF::SEMAPHORE_NOT_OWNED; + } + return HasReturnvaluesIF::RETURN_OK; +} diff --git a/osal/linux/BinarySemaphore.h b/osal/linux/BinarySemaphore.h index 4181de85..e9bb8bb6 100644 --- a/osal/linux/BinarySemaphore.h +++ b/osal/linux/BinarySemaphore.h @@ -1,81 +1,81 @@ -#ifndef FRAMEWORK_OSAL_LINUX_BINARYSEMPAHORE_H_ -#define FRAMEWORK_OSAL_LINUX_BINARYSEMPAHORE_H_ - -#include "../../returnvalues/HasReturnvaluesIF.h" -#include "../../tasks/SemaphoreIF.h" - -extern "C" { -#include -} - -/** - * @brief OS Tool to achieve synchronization of between tasks or between - * task and ISR. The default semaphore implementation creates a - * binary semaphore, which can only be taken once. - * @details - * See: http://www.man7.org/linux/man-pages/man7/sem_overview.7.html - * @author R. Mueller - * @ingroup osal - */ -class BinarySemaphore: public SemaphoreIF, - public HasReturnvaluesIF { -public: - static const uint8_t INTERFACE_ID = CLASS_ID::SEMAPHORE_IF; - - //! @brief Default ctor - BinarySemaphore(); - //! @brief Copy ctor, deleted explicitely. - BinarySemaphore(const BinarySemaphore&) = delete; - //! @brief Copy assignment, deleted explicitely. - BinarySemaphore& operator=(const BinarySemaphore&) = delete; - //! @brief Move ctor - BinarySemaphore (BinarySemaphore &&); - //! @brief Move assignment - BinarySemaphore & operator=(BinarySemaphore &&); - //! @brief Destructor - virtual ~BinarySemaphore(); - - void initSemaphore(uint8_t initCount = 1); - - uint8_t getSemaphoreCounter() const override; - static uint8_t getSemaphoreCounter(sem_t* handle); - - /** - * Take the binary semaphore. - * If the semaphore has already been taken, the task will be blocked - * for a maximum of #timeoutMs or until the semaphore is given back, - * for example by an ISR or another task. - * @param timeoutMs - * @return -@c RETURN_OK on success - * -@c SemaphoreIF::SEMAPHORE_TIMEOUT on timeout - */ - ReturnValue_t acquire(TimeoutType timeoutType = TimeoutType::BLOCKING, - uint32_t timeoutMs = 0) override; - - /** - * Release the binary semaphore. - * @return -@c RETURN_OK on success - * -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if the semaphores is - * already available. - */ - virtual ReturnValue_t release() override; - /** - * This static function can be used to release a semaphore by providing - * its handle. - * @param handle - * @return - */ - static ReturnValue_t release(sem_t* handle); - - /** Checks the validity of the semaphore count against a specified - * known maxCount - * @param handle - * @param maxCount - * @return - */ - static ReturnValue_t checkCount(sem_t* handle, uint8_t maxCount); -protected: - sem_t handle; -}; - -#endif /* FRAMEWORK_OSAL_FREERTOS_BINARYSEMPAHORE_H_ */ +#ifndef FRAMEWORK_OSAL_LINUX_BINARYSEMPAHORE_H_ +#define FRAMEWORK_OSAL_LINUX_BINARYSEMPAHORE_H_ + +#include "../../returnvalues/HasReturnvaluesIF.h" +#include "../../tasks/SemaphoreIF.h" + +extern "C" { +#include +} + +/** + * @brief OS Tool to achieve synchronization of between tasks or between + * task and ISR. The default semaphore implementation creates a + * binary semaphore, which can only be taken once. + * @details + * See: http://www.man7.org/linux/man-pages/man7/sem_overview.7.html + * @author R. Mueller + * @ingroup osal + */ +class BinarySemaphore: public SemaphoreIF, + public HasReturnvaluesIF { +public: + static const uint8_t INTERFACE_ID = CLASS_ID::SEMAPHORE_IF; + + //! @brief Default ctor + BinarySemaphore(); + //! @brief Copy ctor, deleted explicitely. + BinarySemaphore(const BinarySemaphore&) = delete; + //! @brief Copy assignment, deleted explicitely. + BinarySemaphore& operator=(const BinarySemaphore&) = delete; + //! @brief Move ctor + BinarySemaphore (BinarySemaphore &&); + //! @brief Move assignment + BinarySemaphore & operator=(BinarySemaphore &&); + //! @brief Destructor + virtual ~BinarySemaphore(); + + void initSemaphore(uint8_t initCount = 1); + + uint8_t getSemaphoreCounter() const override; + static uint8_t getSemaphoreCounter(sem_t* handle); + + /** + * Take the binary semaphore. + * If the semaphore has already been taken, the task will be blocked + * for a maximum of #timeoutMs or until the semaphore is given back, + * for example by an ISR or another task. + * @param timeoutMs + * @return -@c RETURN_OK on success + * -@c SemaphoreIF::SEMAPHORE_TIMEOUT on timeout + */ + ReturnValue_t acquire(TimeoutType timeoutType = TimeoutType::BLOCKING, + uint32_t timeoutMs = 0) override; + + /** + * Release the binary semaphore. + * @return -@c RETURN_OK on success + * -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if the semaphores is + * already available. + */ + virtual ReturnValue_t release() override; + /** + * This static function can be used to release a semaphore by providing + * its handle. + * @param handle + * @return + */ + static ReturnValue_t release(sem_t* handle); + + /** Checks the validity of the semaphore count against a specified + * known maxCount + * @param handle + * @param maxCount + * @return + */ + static ReturnValue_t checkCount(sem_t* handle, uint8_t maxCount); +protected: + sem_t handle; +}; + +#endif /* FRAMEWORK_OSAL_FREERTOS_BINARYSEMPAHORE_H_ */ diff --git a/osal/linux/CountingSemaphore.cpp b/osal/linux/CountingSemaphore.cpp index ef32539b..18339399 100644 --- a/osal/linux/CountingSemaphore.cpp +++ b/osal/linux/CountingSemaphore.cpp @@ -1,54 +1,54 @@ -#include "../../osal/linux/CountingSemaphore.h" -#include "../../serviceinterface/ServiceInterfaceStream.h" - -CountingSemaphore::CountingSemaphore(const uint8_t maxCount, uint8_t initCount): - maxCount(maxCount), initCount(initCount) { - if(initCount > maxCount) { - sif::error << "CountingSemaphoreUsingTask: Max count bigger than " - "intial cout. Setting initial count to max count." << std::endl; - initCount = maxCount; - } - - initSemaphore(initCount); -} - -CountingSemaphore::CountingSemaphore(CountingSemaphore&& other): - maxCount(other.maxCount), initCount(other.initCount) { - initSemaphore(initCount); -} - -CountingSemaphore& CountingSemaphore::operator =( - CountingSemaphore&& other) { - initSemaphore(other.initCount); - return * this; -} - -ReturnValue_t CountingSemaphore::release() { - ReturnValue_t result = checkCount(&handle, maxCount); - if(result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - return CountingSemaphore::release(&this->handle); -} - -ReturnValue_t CountingSemaphore::release(sem_t* handle) { - int result = sem_post(handle); - if(result == 0) { - return HasReturnvaluesIF::RETURN_OK; - } - - switch(errno) { - case(EINVAL): - // Semaphore invalid - return SemaphoreIF::SEMAPHORE_INVALID; - case(EOVERFLOW): - // SEM_MAX_VALUE overflow. This should never happen - default: - return HasReturnvaluesIF::RETURN_FAILED; - } -} - -uint8_t CountingSemaphore::getMaxCount() const { - return maxCount; -} - +#include "../../osal/linux/CountingSemaphore.h" +#include "../../serviceinterface/ServiceInterfaceStream.h" + +CountingSemaphore::CountingSemaphore(const uint8_t maxCount, uint8_t initCount): + maxCount(maxCount), initCount(initCount) { + if(initCount > maxCount) { + sif::error << "CountingSemaphoreUsingTask: Max count bigger than " + "intial cout. Setting initial count to max count." << std::endl; + initCount = maxCount; + } + + initSemaphore(initCount); +} + +CountingSemaphore::CountingSemaphore(CountingSemaphore&& other): + maxCount(other.maxCount), initCount(other.initCount) { + initSemaphore(initCount); +} + +CountingSemaphore& CountingSemaphore::operator =( + CountingSemaphore&& other) { + initSemaphore(other.initCount); + return * this; +} + +ReturnValue_t CountingSemaphore::release() { + ReturnValue_t result = checkCount(&handle, maxCount); + if(result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + return CountingSemaphore::release(&this->handle); +} + +ReturnValue_t CountingSemaphore::release(sem_t* handle) { + int result = sem_post(handle); + if(result == 0) { + return HasReturnvaluesIF::RETURN_OK; + } + + switch(errno) { + case(EINVAL): + // Semaphore invalid + return SemaphoreIF::SEMAPHORE_INVALID; + case(EOVERFLOW): + // SEM_MAX_VALUE overflow. This should never happen + default: + return HasReturnvaluesIF::RETURN_FAILED; + } +} + +uint8_t CountingSemaphore::getMaxCount() const { + return maxCount; +} + diff --git a/osal/linux/CountingSemaphore.h b/osal/linux/CountingSemaphore.h index afe21a61..e0fbb992 100644 --- a/osal/linux/CountingSemaphore.h +++ b/osal/linux/CountingSemaphore.h @@ -1,37 +1,37 @@ -#ifndef FRAMEWORK_OSAL_LINUX_COUNTINGSEMAPHORE_H_ -#define FRAMEWORK_OSAL_LINUX_COUNTINGSEMAPHORE_H_ -#include "../../osal/linux/BinarySemaphore.h" - -/** - * @brief Counting semaphores, which can be acquired more than once. - * @details - * See: https://www.freertos.org/CreateCounting.html - * API of counting semaphores is almost identical to binary semaphores, - * so we just inherit from binary semaphore and provide the respective - * constructors. - */ -class CountingSemaphore: public BinarySemaphore { -public: - CountingSemaphore(const uint8_t maxCount, uint8_t initCount); - //! @brief Copy ctor, disabled - CountingSemaphore(const CountingSemaphore&) = delete; - //! @brief Copy assignment, disabled - CountingSemaphore& operator=(const CountingSemaphore&) = delete; - //! @brief Move ctor - CountingSemaphore (CountingSemaphore &&); - //! @brief Move assignment - CountingSemaphore & operator=(CountingSemaphore &&); - - ReturnValue_t release() override; - static ReturnValue_t release(sem_t* sem); - /* Same API as binary semaphore otherwise. acquire() can be called - * until there are not semaphores left and release() can be called - * until maxCount is reached. */ - - uint8_t getMaxCount() const; -private: - const uint8_t maxCount; - uint8_t initCount = 0; -}; - -#endif /* FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHORE_H_ */ +#ifndef FRAMEWORK_OSAL_LINUX_COUNTINGSEMAPHORE_H_ +#define FRAMEWORK_OSAL_LINUX_COUNTINGSEMAPHORE_H_ +#include "../../osal/linux/BinarySemaphore.h" + +/** + * @brief Counting semaphores, which can be acquired more than once. + * @details + * See: https://www.freertos.org/CreateCounting.html + * API of counting semaphores is almost identical to binary semaphores, + * so we just inherit from binary semaphore and provide the respective + * constructors. + */ +class CountingSemaphore: public BinarySemaphore { +public: + CountingSemaphore(const uint8_t maxCount, uint8_t initCount); + //! @brief Copy ctor, disabled + CountingSemaphore(const CountingSemaphore&) = delete; + //! @brief Copy assignment, disabled + CountingSemaphore& operator=(const CountingSemaphore&) = delete; + //! @brief Move ctor + CountingSemaphore (CountingSemaphore &&); + //! @brief Move assignment + CountingSemaphore & operator=(CountingSemaphore &&); + + ReturnValue_t release() override; + static ReturnValue_t release(sem_t* sem); + /* Same API as binary semaphore otherwise. acquire() can be called + * until there are not semaphores left and release() can be called + * until maxCount is reached. */ + + uint8_t getMaxCount() const; +private: + const uint8_t maxCount; + uint8_t initCount = 0; +}; + +#endif /* FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHORE_H_ */ diff --git a/osal/linux/SemaphoreFactory.cpp b/osal/linux/SemaphoreFactory.cpp index bcb5d16f..e4710933 100644 --- a/osal/linux/SemaphoreFactory.cpp +++ b/osal/linux/SemaphoreFactory.cpp @@ -1,33 +1,33 @@ -#include "../../tasks/SemaphoreFactory.h" -#include "BinarySemaphore.h" -#include "CountingSemaphore.h" -#include "../../serviceinterface/ServiceInterfaceStream.h" - -SemaphoreFactory* SemaphoreFactory::factoryInstance = nullptr; - -SemaphoreFactory::SemaphoreFactory() { -} - -SemaphoreFactory::~SemaphoreFactory() { - delete factoryInstance; -} - -SemaphoreFactory* SemaphoreFactory::instance() { - if (factoryInstance == nullptr){ - factoryInstance = new SemaphoreFactory(); - } - return SemaphoreFactory::factoryInstance; -} - -SemaphoreIF* SemaphoreFactory::createBinarySemaphore(uint32_t arguments) { - return new BinarySemaphore(); -} - -SemaphoreIF* SemaphoreFactory::createCountingSemaphore(const uint8_t maxCount, - uint8_t initCount, uint32_t arguments) { - return new CountingSemaphore(maxCount, initCount); -} - -void SemaphoreFactory::deleteSemaphore(SemaphoreIF* semaphore) { - delete semaphore; -} +#include "../../tasks/SemaphoreFactory.h" +#include "BinarySemaphore.h" +#include "CountingSemaphore.h" +#include "../../serviceinterface/ServiceInterfaceStream.h" + +SemaphoreFactory* SemaphoreFactory::factoryInstance = nullptr; + +SemaphoreFactory::SemaphoreFactory() { +} + +SemaphoreFactory::~SemaphoreFactory() { + delete factoryInstance; +} + +SemaphoreFactory* SemaphoreFactory::instance() { + if (factoryInstance == nullptr){ + factoryInstance = new SemaphoreFactory(); + } + return SemaphoreFactory::factoryInstance; +} + +SemaphoreIF* SemaphoreFactory::createBinarySemaphore(uint32_t arguments) { + return new BinarySemaphore(); +} + +SemaphoreIF* SemaphoreFactory::createCountingSemaphore(const uint8_t maxCount, + uint8_t initCount, uint32_t arguments) { + return new CountingSemaphore(maxCount, initCount); +} + +void SemaphoreFactory::deleteSemaphore(SemaphoreIF* semaphore) { + delete semaphore; +} diff --git a/serialize/SerialBufferAdapter.cpp b/serialize/SerialBufferAdapter.cpp index 812cd34b..1c11afd4 100644 --- a/serialize/SerialBufferAdapter.cpp +++ b/serialize/SerialBufferAdapter.cpp @@ -1,129 +1,129 @@ -#include "../serialize/SerialBufferAdapter.h" -#include "../serviceinterface/ServiceInterfaceStream.h" -#include - -template -SerialBufferAdapter::SerialBufferAdapter(const uint8_t* buffer, - count_t bufferLength, bool serializeLength) : - serializeLength(serializeLength), - constBuffer(buffer), buffer(nullptr), - bufferLength(bufferLength) {} - -template -SerialBufferAdapter::SerialBufferAdapter(uint8_t* buffer, - count_t bufferLength, bool serializeLength) : - serializeLength(serializeLength), constBuffer(buffer), buffer(buffer), - bufferLength(bufferLength) {} - - -template -SerialBufferAdapter::~SerialBufferAdapter() { -} - -template -ReturnValue_t SerialBufferAdapter::serialize(uint8_t** buffer, - size_t* size, size_t maxSize, Endianness streamEndianness) const { - if (serializeLength) { - ReturnValue_t result = SerializeAdapter::serialize(&bufferLength, - buffer, size, maxSize, streamEndianness); - if(result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - } - - if (*size + bufferLength > maxSize) { - return BUFFER_TOO_SHORT; - } - - if (this->constBuffer != nullptr) { - std::memcpy(*buffer, this->constBuffer, bufferLength); - } - else if (this->buffer != nullptr) { - // This will propably be never reached, constBuffer should always be - // set if non-const buffer is set. - std::memcpy(*buffer, this->buffer, bufferLength); - } - else { - return HasReturnvaluesIF::RETURN_FAILED; - } - *size += bufferLength; - (*buffer) += bufferLength; - return HasReturnvaluesIF::RETURN_OK; - -} - -template -size_t SerialBufferAdapter::getSerializedSize() const { - if (serializeLength) { - return bufferLength + SerializeAdapter::getSerializedSize(&bufferLength); - } else { - return bufferLength; - } -} - -template -ReturnValue_t SerialBufferAdapter::deSerialize(const uint8_t** buffer, - size_t* size, Endianness streamEndianness) { - if (this->buffer == nullptr) { - return HasReturnvaluesIF::RETURN_FAILED; - } - - if(serializeLength){ - count_t lengthField = 0; - ReturnValue_t result = SerializeAdapter::deSerialize(&lengthField, - buffer, size, streamEndianness); - if(result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - if(lengthField > bufferLength) { - return TOO_MANY_ELEMENTS; - } - bufferLength = lengthField; - } - - if (bufferLength <= *size) { - *size -= bufferLength; - std::memcpy(this->buffer, *buffer, bufferLength); - (*buffer) += bufferLength; - return HasReturnvaluesIF::RETURN_OK; - } - else { - return STREAM_TOO_SHORT; - } -} - -template -uint8_t * SerialBufferAdapter::getBuffer() { - if(buffer == nullptr) { - sif::error << "Wrong access function for stored type !" - " Use getConstBuffer()." << std::endl; - return nullptr; - } - return buffer; -} - -template -const uint8_t * SerialBufferAdapter::getConstBuffer() { - if(constBuffer == nullptr) { - sif::error << "SerialBufferAdapter::getConstBuffer:" - " Buffers are unitialized!" << std::endl; - return nullptr; - } - return constBuffer; -} - -template -void SerialBufferAdapter::setBuffer(uint8_t* buffer, - count_t bufferLength) { - this->buffer = buffer; - this->constBuffer = buffer; - this->bufferLength = bufferLength; -} - - -//forward Template declaration for linker -template class SerialBufferAdapter; -template class SerialBufferAdapter; -template class SerialBufferAdapter; -template class SerialBufferAdapter; - +#include "../serialize/SerialBufferAdapter.h" +#include "../serviceinterface/ServiceInterfaceStream.h" +#include + +template +SerialBufferAdapter::SerialBufferAdapter(const uint8_t* buffer, + count_t bufferLength, bool serializeLength) : + serializeLength(serializeLength), + constBuffer(buffer), buffer(nullptr), + bufferLength(bufferLength) {} + +template +SerialBufferAdapter::SerialBufferAdapter(uint8_t* buffer, + count_t bufferLength, bool serializeLength) : + serializeLength(serializeLength), constBuffer(buffer), buffer(buffer), + bufferLength(bufferLength) {} + + +template +SerialBufferAdapter::~SerialBufferAdapter() { +} + +template +ReturnValue_t SerialBufferAdapter::serialize(uint8_t** buffer, + size_t* size, size_t maxSize, Endianness streamEndianness) const { + if (serializeLength) { + ReturnValue_t result = SerializeAdapter::serialize(&bufferLength, + buffer, size, maxSize, streamEndianness); + if(result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + } + + if (*size + bufferLength > maxSize) { + return BUFFER_TOO_SHORT; + } + + if (this->constBuffer != nullptr) { + std::memcpy(*buffer, this->constBuffer, bufferLength); + } + else if (this->buffer != nullptr) { + // This will propably be never reached, constBuffer should always be + // set if non-const buffer is set. + std::memcpy(*buffer, this->buffer, bufferLength); + } + else { + return HasReturnvaluesIF::RETURN_FAILED; + } + *size += bufferLength; + (*buffer) += bufferLength; + return HasReturnvaluesIF::RETURN_OK; + +} + +template +size_t SerialBufferAdapter::getSerializedSize() const { + if (serializeLength) { + return bufferLength + SerializeAdapter::getSerializedSize(&bufferLength); + } else { + return bufferLength; + } +} + +template +ReturnValue_t SerialBufferAdapter::deSerialize(const uint8_t** buffer, + size_t* size, Endianness streamEndianness) { + if (this->buffer == nullptr) { + return HasReturnvaluesIF::RETURN_FAILED; + } + + if(serializeLength){ + count_t lengthField = 0; + ReturnValue_t result = SerializeAdapter::deSerialize(&lengthField, + buffer, size, streamEndianness); + if(result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + if(lengthField > bufferLength) { + return TOO_MANY_ELEMENTS; + } + bufferLength = lengthField; + } + + if (bufferLength <= *size) { + *size -= bufferLength; + std::memcpy(this->buffer, *buffer, bufferLength); + (*buffer) += bufferLength; + return HasReturnvaluesIF::RETURN_OK; + } + else { + return STREAM_TOO_SHORT; + } +} + +template +uint8_t * SerialBufferAdapter::getBuffer() { + if(buffer == nullptr) { + sif::error << "Wrong access function for stored type !" + " Use getConstBuffer()." << std::endl; + return nullptr; + } + return buffer; +} + +template +const uint8_t * SerialBufferAdapter::getConstBuffer() { + if(constBuffer == nullptr) { + sif::error << "SerialBufferAdapter::getConstBuffer:" + " Buffers are unitialized!" << std::endl; + return nullptr; + } + return constBuffer; +} + +template +void SerialBufferAdapter::setBuffer(uint8_t* buffer, + count_t bufferLength) { + this->buffer = buffer; + this->constBuffer = buffer; + this->bufferLength = bufferLength; +} + + +//forward Template declaration for linker +template class SerialBufferAdapter; +template class SerialBufferAdapter; +template class SerialBufferAdapter; +template class SerialBufferAdapter; + diff --git a/serialize/SerialBufferAdapter.h b/serialize/SerialBufferAdapter.h index c3dfcd8f..9a89e18b 100644 --- a/serialize/SerialBufferAdapter.h +++ b/serialize/SerialBufferAdapter.h @@ -1,78 +1,78 @@ -#ifndef SERIALBUFFERADAPTER_H_ -#define SERIALBUFFERADAPTER_H_ - -#include "../serialize/SerializeIF.h" -#include "../serialize/SerializeAdapter.h" - -/** - * This adapter provides an interface for SerializeIF to serialize or deserialize - * buffers with no length header but a known size. - * - * Additionally, the buffer length can be serialized too and will be put in - * front of the serialized buffer. - * - * Can be used with SerialLinkedListAdapter by declaring a SerializeElement with - * SerialElement>. - * Right now, the SerialBufferAdapter must always - * be initialized with the buffer and size ! - * - * \ingroup serialize - */ -template -class SerialBufferAdapter: public SerializeIF { -public: - - /** - * Constructor for constant uint8_t buffer. Length field can be serialized optionally. - * Type of length can be supplied as template type. - * @param buffer - * @param bufferLength - * @param serializeLength - */ - SerialBufferAdapter(const uint8_t* buffer, count_t bufferLength, - bool serializeLength = false); - - /** - * Constructor for non-constant uint8_t buffer. - * Length field can be serialized optionally. - * Type of length can be supplied as template type. - * @param buffer - * @param bufferLength - * @param serializeLength Length field will be serialized with size count_t - */ - SerialBufferAdapter(uint8_t* buffer, count_t bufferLength, - bool serializeLength = false); - - virtual ~SerialBufferAdapter(); - - virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, - size_t maxSize, Endianness streamEndianness) const override; - - virtual size_t getSerializedSize() const override; - - /** - * @brief This function deserializes a buffer into the member buffer. - * @details - * If a length field is present, it is ignored, as the size should have - * been set in the constructor. If the size is not known beforehand, - * consider using SerialFixedArrayListAdapter instead. - * @param buffer [out] Resulting buffer - * @param size remaining size to deserialize, should be larger than buffer - * + size field size - * @param bigEndian - * @return - */ - virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, - Endianness streamEndianness) override; - - uint8_t * getBuffer(); - const uint8_t * getConstBuffer(); - void setBuffer(uint8_t* buffer, count_t bufferLength); -private: - bool serializeLength = false; - const uint8_t *constBuffer = nullptr; - uint8_t *buffer = nullptr; - count_t bufferLength = 0; -}; - -#endif /* SERIALBUFFERADAPTER_H_ */ +#ifndef SERIALBUFFERADAPTER_H_ +#define SERIALBUFFERADAPTER_H_ + +#include "../serialize/SerializeIF.h" +#include "../serialize/SerializeAdapter.h" + +/** + * This adapter provides an interface for SerializeIF to serialize or deserialize + * buffers with no length header but a known size. + * + * Additionally, the buffer length can be serialized too and will be put in + * front of the serialized buffer. + * + * Can be used with SerialLinkedListAdapter by declaring a SerializeElement with + * SerialElement>. + * Right now, the SerialBufferAdapter must always + * be initialized with the buffer and size ! + * + * \ingroup serialize + */ +template +class SerialBufferAdapter: public SerializeIF { +public: + + /** + * Constructor for constant uint8_t buffer. Length field can be serialized optionally. + * Type of length can be supplied as template type. + * @param buffer + * @param bufferLength + * @param serializeLength + */ + SerialBufferAdapter(const uint8_t* buffer, count_t bufferLength, + bool serializeLength = false); + + /** + * Constructor for non-constant uint8_t buffer. + * Length field can be serialized optionally. + * Type of length can be supplied as template type. + * @param buffer + * @param bufferLength + * @param serializeLength Length field will be serialized with size count_t + */ + SerialBufferAdapter(uint8_t* buffer, count_t bufferLength, + bool serializeLength = false); + + virtual ~SerialBufferAdapter(); + + virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, + size_t maxSize, Endianness streamEndianness) const override; + + virtual size_t getSerializedSize() const override; + + /** + * @brief This function deserializes a buffer into the member buffer. + * @details + * If a length field is present, it is ignored, as the size should have + * been set in the constructor. If the size is not known beforehand, + * consider using SerialFixedArrayListAdapter instead. + * @param buffer [out] Resulting buffer + * @param size remaining size to deserialize, should be larger than buffer + * + size field size + * @param bigEndian + * @return + */ + virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, + Endianness streamEndianness) override; + + uint8_t * getBuffer(); + const uint8_t * getConstBuffer(); + void setBuffer(uint8_t* buffer, count_t bufferLength); +private: + bool serializeLength = false; + const uint8_t *constBuffer = nullptr; + uint8_t *buffer = nullptr; + count_t bufferLength = 0; +}; + +#endif /* SERIALBUFFERADAPTER_H_ */ diff --git a/tasks/SemaphoreFactory.h b/tasks/SemaphoreFactory.h index 2c41a135..01c09d1b 100644 --- a/tasks/SemaphoreFactory.h +++ b/tasks/SemaphoreFactory.h @@ -1,50 +1,50 @@ -#ifndef FSFW_TASKS_SEMAPHOREFACTORY_H_ -#define FSFW_TASKS_SEMAPHOREFACTORY_H_ - -#include "../tasks/SemaphoreIF.h" - -/** - * Creates Semaphore. - * This class is a "singleton" interface, i.e. it provides an - * interface, but also is the base class for a singleton. - */ -class SemaphoreFactory { -public: - virtual ~SemaphoreFactory(); - /** - * Returns the single instance of SemaphoreFactory. - * The implementation of #instance is found in its subclasses. - * Thus, we choose link-time variability of the instance. - */ - static SemaphoreFactory* instance(); - - /** - * Create a binary semaphore. - * Creator function for a binary semaphore which may only be acquired once - * @param argument Can be used to pass implementation specific information. - * @return Pointer to newly created semaphore class instance. - */ - SemaphoreIF* createBinarySemaphore(uint32_t arguments = 0); - /** - * Create a counting semaphore. - * Creator functons for a counting semaphore which may be acquired multiple - * times. - * @param count Semaphore can be taken count times. - * @param initCount Initial count value. - * @param argument Can be used to pass implementation specific information. - * @return - */ - SemaphoreIF* createCountingSemaphore(const uint8_t maxCount, - uint8_t initCount, uint32_t arguments = 0); - - void deleteSemaphore(SemaphoreIF* semaphore); - -private: - /** - * External instantiation is not allowed. - */ - SemaphoreFactory(); - static SemaphoreFactory* factoryInstance; -}; - -#endif /* FSFW_TASKS_SEMAPHOREFACTORY_H_ */ +#ifndef FSFW_TASKS_SEMAPHOREFACTORY_H_ +#define FSFW_TASKS_SEMAPHOREFACTORY_H_ + +#include "../tasks/SemaphoreIF.h" + +/** + * Creates Semaphore. + * This class is a "singleton" interface, i.e. it provides an + * interface, but also is the base class for a singleton. + */ +class SemaphoreFactory { +public: + virtual ~SemaphoreFactory(); + /** + * Returns the single instance of SemaphoreFactory. + * The implementation of #instance is found in its subclasses. + * Thus, we choose link-time variability of the instance. + */ + static SemaphoreFactory* instance(); + + /** + * Create a binary semaphore. + * Creator function for a binary semaphore which may only be acquired once + * @param argument Can be used to pass implementation specific information. + * @return Pointer to newly created semaphore class instance. + */ + SemaphoreIF* createBinarySemaphore(uint32_t arguments = 0); + /** + * Create a counting semaphore. + * Creator functons for a counting semaphore which may be acquired multiple + * times. + * @param count Semaphore can be taken count times. + * @param initCount Initial count value. + * @param argument Can be used to pass implementation specific information. + * @return + */ + SemaphoreIF* createCountingSemaphore(const uint8_t maxCount, + uint8_t initCount, uint32_t arguments = 0); + + void deleteSemaphore(SemaphoreIF* semaphore); + +private: + /** + * External instantiation is not allowed. + */ + SemaphoreFactory(); + static SemaphoreFactory* factoryInstance; +}; + +#endif /* FSFW_TASKS_SEMAPHOREFACTORY_H_ */ diff --git a/tasks/SemaphoreIF.h b/tasks/SemaphoreIF.h index 30d4ed88..dd327e23 100644 --- a/tasks/SemaphoreIF.h +++ b/tasks/SemaphoreIF.h @@ -1,68 +1,68 @@ -#ifndef FRAMEWORK_TASKS_SEMAPHOREIF_H_ -#define FRAMEWORK_TASKS_SEMAPHOREIF_H_ -#include "../returnvalues/FwClassIds.h" -#include "../returnvalues/HasReturnvaluesIF.h" -#include - -/** - * @brief Generic interface for semaphores, which can be used to achieve - * task synchronization. This is a generic interface which can be - * used for both binary semaphores and counting semaphores. - * @details - * A semaphore is a synchronization primitive. - * See: https://en.wikipedia.org/wiki/Semaphore_(programming) - * A semaphore can be used to achieve task synchonization and track the - * availability of resources by using either the binary or the counting - * semaphore types. - * - * If mutual exlcusion of a resource is desired, a mutex should be used, - * which is a special form of a semaphore and has an own interface. - */ -class SemaphoreIF { -public: - /** - * Different types of timeout for the mutex lock. - */ - enum TimeoutType { - POLLING, //!< If mutex is not available, return immediately - WAITING, //!< Wait a specified time for the mutex to become available - BLOCKING //!< Block indefinitely until the mutex becomes available. - }; - - virtual~ SemaphoreIF() {}; - - static const uint8_t INTERFACE_ID = CLASS_ID::SEMAPHORE_IF; - //! Semaphore timeout - static constexpr ReturnValue_t SEMAPHORE_TIMEOUT = MAKE_RETURN_CODE(1); - //! The current semaphore can not be given, because it is not owned - static constexpr ReturnValue_t SEMAPHORE_NOT_OWNED = MAKE_RETURN_CODE(2); - static constexpr ReturnValue_t SEMAPHORE_INVALID = MAKE_RETURN_CODE(3); - - /** - * Generic call to acquire a semaphore. - * If there are no more semaphores to be taken (for a counting semaphore, - * a semaphore may be taken more than once), the taks will block - * for a maximum of timeoutMs while trying to acquire the semaphore. - * This can be used to achieve task synchrnization. - * @param timeoutMs - * @return - c RETURN_OK for successfull acquisition - */ - virtual ReturnValue_t acquire(TimeoutType timeoutType = - TimeoutType::BLOCKING, uint32_t timeoutMs = 0) = 0; - - /** - * Corrensponding call to release a semaphore. - * @return -@c RETURN_OK for successfull release - */ - virtual ReturnValue_t release() = 0; - - /** - * If the semaphore is a counting semaphore then the semaphores current - * count value is returned. If the semaphore is a binary semaphore then 1 - * is returned if the semaphore is available, and 0 is returned if the - * semaphore is not available. - */ - virtual uint8_t getSemaphoreCounter() const = 0; -}; - -#endif /* FRAMEWORK_TASKS_SEMAPHOREIF_H_ */ +#ifndef FRAMEWORK_TASKS_SEMAPHOREIF_H_ +#define FRAMEWORK_TASKS_SEMAPHOREIF_H_ +#include "../returnvalues/FwClassIds.h" +#include "../returnvalues/HasReturnvaluesIF.h" +#include + +/** + * @brief Generic interface for semaphores, which can be used to achieve + * task synchronization. This is a generic interface which can be + * used for both binary semaphores and counting semaphores. + * @details + * A semaphore is a synchronization primitive. + * See: https://en.wikipedia.org/wiki/Semaphore_(programming) + * A semaphore can be used to achieve task synchonization and track the + * availability of resources by using either the binary or the counting + * semaphore types. + * + * If mutual exlcusion of a resource is desired, a mutex should be used, + * which is a special form of a semaphore and has an own interface. + */ +class SemaphoreIF { +public: + /** + * Different types of timeout for the mutex lock. + */ + enum TimeoutType { + POLLING, //!< If mutex is not available, return immediately + WAITING, //!< Wait a specified time for the mutex to become available + BLOCKING //!< Block indefinitely until the mutex becomes available. + }; + + virtual~ SemaphoreIF() {}; + + static const uint8_t INTERFACE_ID = CLASS_ID::SEMAPHORE_IF; + //! Semaphore timeout + static constexpr ReturnValue_t SEMAPHORE_TIMEOUT = MAKE_RETURN_CODE(1); + //! The current semaphore can not be given, because it is not owned + static constexpr ReturnValue_t SEMAPHORE_NOT_OWNED = MAKE_RETURN_CODE(2); + static constexpr ReturnValue_t SEMAPHORE_INVALID = MAKE_RETURN_CODE(3); + + /** + * Generic call to acquire a semaphore. + * If there are no more semaphores to be taken (for a counting semaphore, + * a semaphore may be taken more than once), the taks will block + * for a maximum of timeoutMs while trying to acquire the semaphore. + * This can be used to achieve task synchrnization. + * @param timeoutMs + * @return - c RETURN_OK for successfull acquisition + */ + virtual ReturnValue_t acquire(TimeoutType timeoutType = + TimeoutType::BLOCKING, uint32_t timeoutMs = 0) = 0; + + /** + * Corrensponding call to release a semaphore. + * @return -@c RETURN_OK for successfull release + */ + virtual ReturnValue_t release() = 0; + + /** + * If the semaphore is a counting semaphore then the semaphores current + * count value is returned. If the semaphore is a binary semaphore then 1 + * is returned if the semaphore is available, and 0 is returned if the + * semaphore is not available. + */ + virtual uint8_t getSemaphoreCounter() const = 0; +}; + +#endif /* FRAMEWORK_TASKS_SEMAPHOREIF_H_ */ From 85f21b05165efeabb626fcb5f7d8c7d3bc8a18ea Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 18 Sep 2020 13:32:53 +0200 Subject: [PATCH 048/101] object manager convergence --- objectmanager/ObjectManager.h | 23 +++++-------- objectmanager/ObjectManagerIF.h | 8 ++--- objectmanager/SystemObject.cpp | 2 +- objectmanager/SystemObject.h | 30 ++++++++--------- objectmanager/SystemObjectIF.h | 56 +++++++++++++++----------------- objectmanager/frameworkObjects.h | 14 ++++++-- 6 files changed, 65 insertions(+), 68 deletions(-) diff --git a/objectmanager/ObjectManager.h b/objectmanager/ObjectManager.h index 0d2b3c4a..69a74f73 100644 --- a/objectmanager/ObjectManager.h +++ b/objectmanager/ObjectManager.h @@ -1,12 +1,5 @@ -/** - * @file ObjectManager.h - * @brief This file contains the implementation of the ObjectManager class - * @date 18.09.2012 - * @author Bastian Baetz - */ - -#ifndef OBJECTMANAGER_H_ -#define OBJECTMANAGER_H_ +#ifndef FSFW_OBJECTMANAGER_OBJECTMANAGER_H_ +#define FSFW_OBJECTMANAGER_OBJECTMANAGER_H_ #include "ObjectManagerIF.h" #include "SystemObjectIF.h" @@ -22,14 +15,15 @@ * most of the system initialization. * As the system is static after initialization, no new objects are * created or inserted into the list after startup. - * \ingroup system_objects + * @ingroup system_objects + * @author Bastian Baetz */ class ObjectManager : public ObjectManagerIF { private: //comparison? /** - * \brief This is the map of all initialized objects in the manager. - * \details Objects in the List must inherit the SystemObjectIF. + * @brief This is the map of all initialized objects in the manager. + * @details Objects in the List must inherit the SystemObjectIF. */ std::map objectList; protected: @@ -54,7 +48,8 @@ public: /** * @brief In the class's destructor, all objects in the list are deleted. */ - //SHOULDDO: If, for some reason, deleting an ObjectManager instance is required, check if this works. + // SHOULDDO: If, for some reason, deleting an ObjectManager instance is + // required, check if this works. virtual ~ObjectManager( void ); ReturnValue_t insert( object_id_t id, SystemObjectIF* object ); ReturnValue_t remove( object_id_t id ); @@ -64,4 +59,4 @@ public: -#endif /* OBJECTMANAGER_H_ */ +#endif /* FSFW_OBJECTMANAGER_OBJECTMANAGER_H_ */ diff --git a/objectmanager/ObjectManagerIF.h b/objectmanager/ObjectManagerIF.h index e0162af9..1f462509 100644 --- a/objectmanager/ObjectManagerIF.h +++ b/objectmanager/ObjectManagerIF.h @@ -1,5 +1,5 @@ -#ifndef FRAMEWORK_OBJECTMANAGER_OBJECTMANAGERIF_H_ -#define FRAMEWORK_OBJECTMANAGER_OBJECTMANAGERIF_H_ +#ifndef FSFW_OBJECTMANAGER_OBJECTMANAGERIF_H_ +#define FSFW_OBJECTMANAGER_OBJECTMANAGERIF_H_ #include "frameworkObjects.h" #include "SystemObjectIF.h" @@ -21,8 +21,7 @@ public: static constexpr uint8_t INTERFACE_ID = CLASS_ID::OBJECT_MANAGER_IF; static constexpr ReturnValue_t INSERTION_FAILED = MAKE_RETURN_CODE( 1 ); static constexpr ReturnValue_t NOT_FOUND = MAKE_RETURN_CODE( 2 ); - - static constexpr ReturnValue_t CHILD_INIT_FAILED = MAKE_RETURN_CODE( 3 ); //!< Can be used if the initialization of a SystemObject failed. + static constexpr ReturnValue_t CHILD_INIT_FAILED = MAKE_RETURN_CODE( 3 ); static constexpr ReturnValue_t INTERNAL_ERR_REPORTER_UNINIT = MAKE_RETURN_CODE( 4 ); protected: @@ -80,6 +79,7 @@ public: /** * @brief This is the forward declaration of the global objectManager instance. */ +// maybe but this in the glob namespace to explicitely mark it global? extern ObjectManagerIF *objectManager; /*Documentation can be found in the class method declaration above.*/ diff --git a/objectmanager/SystemObject.cpp b/objectmanager/SystemObject.cpp index 53aac599..64330fbc 100644 --- a/objectmanager/SystemObject.cpp +++ b/objectmanager/SystemObject.cpp @@ -1,6 +1,6 @@ -#include "../events/EventManagerIF.h" #include "ObjectManager.h" #include "SystemObject.h" +#include "../events/EventManagerIF.h" SystemObject::SystemObject(object_id_t setObjectId, bool doRegister) : objectId(setObjectId), registered(doRegister) { diff --git a/objectmanager/SystemObject.h b/objectmanager/SystemObject.h index 8e9f20d5..9188693e 100644 --- a/objectmanager/SystemObject.h +++ b/objectmanager/SystemObject.h @@ -1,16 +1,9 @@ -/** - * @file SystemObject.h - * @brief This file contains the definition of the SystemObject class. - * @date 07.11.2012 - * @author Ulrich Mohr - */ - -#ifndef SYSTEMOBJECT_H_ -#define SYSTEMOBJECT_H_ +#ifndef FSFW_OBJECTMANAGER_SYSTEMOBJECT_H_ +#define FSFW_OBJECTMANAGER_SYSTEMOBJECT_H_ +#include "SystemObjectIF.h" #include "../events/Event.h" #include "../events/EventReportingProxyIF.h" -#include "SystemObjectIF.h" #include "../timemanager/Clock.h" /** @@ -20,7 +13,7 @@ * class that is announced to ObjectManager. It automatically includes * itself (and therefore the inheriting class) in the object manager's * list. - * \ingroup system_objects + * @ingroup system_objects */ class SystemObject: public SystemObjectIF { private: @@ -37,25 +30,28 @@ public: * @param parameter1 * @param parameter2 */ - virtual void triggerEvent(Event event, uint32_t parameter1 = 0, uint32_t parameter2 = 0); + virtual void triggerEvent(Event event, uint32_t parameter1 = 0, + uint32_t parameter2 = 0); /** * @brief The class's constructor. * @details In the constructor, the object id is set and the class is * inserted in the object manager. * @param setObjectId The id the object shall have. - * @param doRegister Determines if the object is registered in the global object manager. + * @param doRegister Determines if the object is registered in + * the global object manager. */ SystemObject(object_id_t setObjectId, bool doRegister = true); /** * @brief On destruction, the object removes itself from the list. */ virtual ~SystemObject(); - object_id_t getObjectId() const; - virtual ReturnValue_t initialize(); + object_id_t getObjectId() const override; + virtual ReturnValue_t initialize() override; virtual ReturnValue_t checkObjectConnections(); - virtual void forwardEvent(Event event, uint32_t parameter1 = 0, uint32_t parameter2 = 0) const; + virtual void forwardEvent(Event event, uint32_t parameter1 = 0, + uint32_t parameter2 = 0) const; }; -#endif /* SYSTEMOBJECT_H_ */ +#endif /* FSFW_OBJECTMANAGER_SYSTEMOBJECT_H_ */ diff --git a/objectmanager/SystemObjectIF.h b/objectmanager/SystemObjectIF.h index c5a92196..315fde9b 100644 --- a/objectmanager/SystemObjectIF.h +++ b/objectmanager/SystemObjectIF.h @@ -1,26 +1,19 @@ -/** - * @file SystemObjectIF.h - * @brief This file contains the definition of the SystemObjectIF interface. - * @date 18.09.2012 - * @author Bastian Baetz - */ - -#ifndef SYSTEMOBJECTIF_H_ -#define SYSTEMOBJECTIF_H_ +#ifndef FSFW_OBJECTMANAGER_SYSTEMOBJECTIF_H_ +#define FSFW_OBJECTMANAGER_SYSTEMOBJECTIF_H_ #include "../events/EventReportingProxyIF.h" #include "../returnvalues/HasReturnvaluesIF.h" -#include +#include /** - * \defgroup system_objects Software System Object Management - * The classes to create System Objects and classes to manage these are contained in this group. - * System Objects are software elements that can be controlled externally. They all have a unique - * object identifier. + * @defgroup system_objects Software System Object Management + * The classes to create System Objects and classes to manage these are + * contained in this group. System Objects are software elements that can be + * controlled externally. They all have a unique object identifier. */ /** * This is the typedef for object identifiers. - * \ingroup system_objects + * @ingroup system_objects */ typedef uint32_t object_id_t; @@ -29,7 +22,8 @@ typedef uint32_t object_id_t; * list. * It does not provide any method definitions, still it is required to * perform a type check with dynamic_cast. - * \ingroup system_objects + * @author Bastian Baetz + * @ingroup system_objects */ class SystemObjectIF : public EventReportingProxyIF { public: @@ -41,24 +35,28 @@ public: /** * The empty virtual destructor as required for C++ interfaces. */ - virtual ~SystemObjectIF() { - } + virtual ~SystemObjectIF() {} /** - * Initializes all inter-object dependencies. - * This is necessary to avoid circular dependencies of not-fully - * initialized objects on start up. - * @return - \c RETURN_OK in case the initialization was successful - * - \c RETURN_FAILED otherwise + * @brief Initializes the object. + * There are initialization steps which can also be done in the constructor. + * However, there is no clean way to get a returnvalue from a constructor. + * Furthermore some components require other system object to be created + * which might not have been built yet. + * Therefore, a two-step initialization resolves this problem and prevents + * circular dependencies of not-fully initialized objects on start up. + * @return - @c RETURN_OK in case the initialization was successful + * - @c RETURN_FAILED otherwise */ virtual ReturnValue_t initialize() = 0; /** - * Checks, if all object-object interconnections are satisfying for operation. - * Some objects need certain other objects (or a certain number), to be registered as children. - * These checks can be done in this method. - * @return - \c RETURN_OK in case the check was successful - * - \c any other code otherwise + * @brief Checks if all object-object interconnections are satisfying + * for operation. + * Some objects need certain other objects (or a certain number), to be + * registered as children. These checks can be done in this method. + * @return - @c RETURN_OK in case the check was successful + * - @c any other code otherwise */ virtual ReturnValue_t checkObjectConnections() = 0; }; -#endif /* SYSTEMOBJECTIF_H_ */ +#endif /* #ifndef FSFW_OBJECTMANAGER_SYSTEMOBJECTIF_H_ */ diff --git a/objectmanager/frameworkObjects.h b/objectmanager/frameworkObjects.h index c3deafc4..4a30e70a 100644 --- a/objectmanager/frameworkObjects.h +++ b/objectmanager/frameworkObjects.h @@ -1,8 +1,15 @@ -#ifndef FRAMEWORK_OBJECTMANAGER_FRAMEWORKOBJECTS_H_ -#define FRAMEWORK_OBJECTMANAGER_FRAMEWORKOBJECTS_H_ +#ifndef FSFW_OBJECTMANAGER_FRAMEWORKOBJECTS_H_ +#define FSFW_OBJECTMANAGER_FRAMEWORKOBJECTS_H_ namespace objects { enum framework_objects { + // Default verification reporter. + PUS_SERVICE_1 = 0x53000001, + PUS_SERVICE_2 = 0x53000002, + PUS_SERVICE_5 = 0x53000005, + PUS_SERVICE_8 = 0x53000008, + PUS_SERVICE_200 = 0x53000200, + //Generic IDs for IPC, modes, health, events HEALTH_TABLE = 0x53010000, // MODE_STORE = 0x53010100, @@ -12,10 +19,11 @@ enum framework_objects { //IDs for PUS Packet Communication TC_STORE = 0x534f0100, TM_STORE = 0x534f0200, + NO_OBJECT = 0xFFFFFFFF }; } -#endif /* FRAMEWORK_OBJECTMANAGER_FRAMEWORKOBJECTS_H_ */ +#endif /* FSFW_OBJECTMANAGER_FRAMEWORKOBJECTS_H_ */ From 6062192bf0a5865fe3c1edb23aa2bc1e1b19d122 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 18 Sep 2020 13:37:06 +0200 Subject: [PATCH 049/101] dded back retval expalanation --- objectmanager/ObjectManagerIF.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/objectmanager/ObjectManagerIF.h b/objectmanager/ObjectManagerIF.h index 1f462509..8bae800b 100644 --- a/objectmanager/ObjectManagerIF.h +++ b/objectmanager/ObjectManagerIF.h @@ -21,7 +21,7 @@ public: static constexpr uint8_t INTERFACE_ID = CLASS_ID::OBJECT_MANAGER_IF; static constexpr ReturnValue_t INSERTION_FAILED = MAKE_RETURN_CODE( 1 ); static constexpr ReturnValue_t NOT_FOUND = MAKE_RETURN_CODE( 2 ); - static constexpr ReturnValue_t CHILD_INIT_FAILED = MAKE_RETURN_CODE( 3 ); + static constexpr ReturnValue_t CHILD_INIT_FAILED = MAKE_RETURN_CODE( 3 ); //!< Can be used if the initialization of a SystemObject failed. static constexpr ReturnValue_t INTERNAL_ERR_REPORTER_UNINIT = MAKE_RETURN_CODE( 4 ); protected: From 8ea0a38658b1322a6bee67b7c656544d1f4d3467 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 18 Sep 2020 13:37:38 +0200 Subject: [PATCH 050/101] shoulddo fix --- objectmanager/ObjectManagerIF.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/objectmanager/ObjectManagerIF.h b/objectmanager/ObjectManagerIF.h index 8bae800b..4bd1d915 100644 --- a/objectmanager/ObjectManagerIF.h +++ b/objectmanager/ObjectManagerIF.h @@ -79,7 +79,7 @@ public: /** * @brief This is the forward declaration of the global objectManager instance. */ -// maybe but this in the glob namespace to explicitely mark it global? +// SHOULDDO: maybe put this in the glob namespace to explicitely mark it global? extern ObjectManagerIF *objectManager; /*Documentation can be found in the class method declaration above.*/ From 721793a0582174e2edfa1e624bcf67377c8ce981 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 18 Sep 2020 13:38:53 +0200 Subject: [PATCH 051/101] added author tag back --- objectmanager/SystemObject.h | 1 + 1 file changed, 1 insertion(+) diff --git a/objectmanager/SystemObject.h b/objectmanager/SystemObject.h index 9188693e..d9c4236d 100644 --- a/objectmanager/SystemObject.h +++ b/objectmanager/SystemObject.h @@ -13,6 +13,7 @@ * class that is announced to ObjectManager. It automatically includes * itself (and therefore the inheriting class) in the object manager's * list. + * @author Ulrich Mohr * @ingroup system_objects */ class SystemObject: public SystemObjectIF { From 7851a71a8eb96931fbdc5f24ef40b5326665a892 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 22 Sep 2020 14:00:18 +0200 Subject: [PATCH 052/101] commanding service base hotfix --- tmtcservices/CommandingServiceBase.cpp | 2 +- tmtcservices/CommandingServiceBase.h | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/tmtcservices/CommandingServiceBase.cpp b/tmtcservices/CommandingServiceBase.cpp index 4cead0e9..0ebc3944 100644 --- a/tmtcservices/CommandingServiceBase.cpp +++ b/tmtcservices/CommandingServiceBase.cpp @@ -384,7 +384,7 @@ void CommandingServiceBase::acceptPacket(uint8_t reportId, } -void CommandingServiceBase::checkAndExecuteFifo(CommandMapIter iter) { +void CommandingServiceBase::checkAndExecuteFifo(CommandMapIter& iter) { store_address_t address; if (iter->second.fifo.retrieve(&address) != RETURN_OK) { commandMap.erase(&iter); diff --git a/tmtcservices/CommandingServiceBase.h b/tmtcservices/CommandingServiceBase.h index 23b08acf..252b6943 100644 --- a/tmtcservices/CommandingServiceBase.h +++ b/tmtcservices/CommandingServiceBase.h @@ -39,7 +39,11 @@ class CommandingServiceBase: public SystemObject, public HasReturnvaluesIF { friend void (Factory::setStaticFrameworkObjectIds)(); public: + // We could make this configurable via preprocessor and the FSFWConfig file. + static constexpr uint8_t COMMAND_INFO_FIFO_DEPTH = 3; + static const uint8_t INTERFACE_ID = CLASS_ID::COMMAND_SERVICE_BASE; + static const ReturnValue_t EXECUTION_COMPLETE = MAKE_RETURN_CODE(1); static const ReturnValue_t NO_STEP_MESSAGE = MAKE_RETURN_CODE(2); static const ReturnValue_t OBJECT_BUSY = MAKE_RETURN_CODE(3); @@ -223,7 +227,7 @@ protected: uint32_t state; Command_t command; object_id_t objectId; - FIFO fifo; + FIFO fifo; virtual ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize, Endianness streamEndianness) const override{ @@ -235,7 +239,7 @@ protected: }; virtual ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size, - Endianness streamEndianness) override{ + Endianness streamEndianness) override { return HasReturnvaluesIF::RETURN_FAILED; }; }; @@ -312,7 +316,7 @@ protected: ReturnValue_t sendTmPacket(uint8_t subservice, SerializeIF* content, SerializeIF* header = nullptr); - void checkAndExecuteFifo(CommandMapIter iter); + void checkAndExecuteFifo(CommandMapIter& iter); private: /** From 4587fbb76d1bc356227229dcb1ad44d389d4a5c0 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 22 Sep 2020 14:52:24 +0200 Subject: [PATCH 053/101] srv9 func removed --- pus/Service9TimeManagement.h | 1 - 1 file changed, 1 deletion(-) diff --git a/pus/Service9TimeManagement.h b/pus/Service9TimeManagement.h index 9eed12ca..4802cdec 100644 --- a/pus/Service9TimeManagement.h +++ b/pus/Service9TimeManagement.h @@ -34,7 +34,6 @@ private: SET_TIME = 128 //!< [EXPORT] : [COMMAND] Time command in ASCII, CUC or CDS format }; - void setIsisClock(Clock::TimeOfDay_t& timeOfDay); }; From b2777faf66885ee6dc440cf1633e7e34c39c4e1a Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 22 Sep 2020 15:29:28 +0200 Subject: [PATCH 054/101] queueue factory update --- osal/linux/QueueFactory.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/osal/linux/QueueFactory.cpp b/osal/linux/QueueFactory.cpp index afeca547..44def48a 100644 --- a/osal/linux/QueueFactory.cpp +++ b/osal/linux/QueueFactory.cpp @@ -1,15 +1,21 @@ #include "../../ipc/QueueFactory.h" +#include "MessageQueue.h" + +#include "../../ipc/messageQueueDefinitions.h" +#include "../../ipc/MessageQueueSenderIF.h" +#include "../../serviceinterface/ServiceInterfaceStream.h" + #include #include -#include "MessageQueue.h" -#include "../../serviceinterface/ServiceInterfaceStream.h" + + #include QueueFactory* QueueFactory::factoryInstance = nullptr; ReturnValue_t MessageQueueSenderIF::sendMessage(MessageQueueId_t sendTo, - MessageQueueMessage* message, MessageQueueId_t sentFrom, + MessageQueueMessageIF* message, MessageQueueId_t sentFrom, bool ignoreFault) { return MessageQueue::sendMessageFromMessageQueue(sendTo,message, sentFrom,ignoreFault); From 7dc3a7ecbd79440c69cf28cec16950bdc8f44419 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 22 Sep 2020 15:31:15 +0200 Subject: [PATCH 055/101] fix so it compiles --- osal/linux/QueueFactory.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osal/linux/QueueFactory.cpp b/osal/linux/QueueFactory.cpp index 44def48a..0860950c 100644 --- a/osal/linux/QueueFactory.cpp +++ b/osal/linux/QueueFactory.cpp @@ -15,7 +15,7 @@ QueueFactory* QueueFactory::factoryInstance = nullptr; ReturnValue_t MessageQueueSenderIF::sendMessage(MessageQueueId_t sendTo, - MessageQueueMessageIF* message, MessageQueueId_t sentFrom, + MessageQueueMessage* message, MessageQueueId_t sentFrom, bool ignoreFault) { return MessageQueue::sendMessageFromMessageQueue(sendTo,message, sentFrom,ignoreFault); From 74b9aef36b2dd920565ed119172cade85bcfd421 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 22 Sep 2020 15:33:28 +0200 Subject: [PATCH 056/101] freeRTOS update --- osal/FreeRTOS/QueueFactory.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/osal/FreeRTOS/QueueFactory.cpp b/osal/FreeRTOS/QueueFactory.cpp index 0de6ad4f..153d9b51 100644 --- a/osal/FreeRTOS/QueueFactory.cpp +++ b/osal/FreeRTOS/QueueFactory.cpp @@ -4,18 +4,18 @@ #include "MessageQueue.h" -QueueFactory* QueueFactory::factoryInstance = NULL; +QueueFactory* QueueFactory::factoryInstance = nullptr; ReturnValue_t MessageQueueSenderIF::sendMessage(MessageQueueId_t sendTo, MessageQueueMessage* message, MessageQueueId_t sentFrom, bool ignoreFault) { - return MessageQueue::sendMessageFromMessageQueue(sendTo, message, - sentFrom, ignoreFault); + return MessageQueue::sendMessageFromMessageQueue(sendTo,message, + sentFrom,ignoreFault); } QueueFactory* QueueFactory::instance() { - if (factoryInstance == NULL) { + if (factoryInstance == nullptr) { factoryInstance = new QueueFactory; } return factoryInstance; @@ -27,9 +27,9 @@ QueueFactory::QueueFactory() { QueueFactory::~QueueFactory() { } -MessageQueueIF* QueueFactory::createMessageQueue(uint32_t message_depth, +MessageQueueIF* QueueFactory::createMessageQueue(uint32_t messageDepth, size_t maxMessageSize) { - return new MessageQueue(message_depth, maxMessageSize); + return new MessageQueue(messageDepth, maxMessageSize); } void QueueFactory::deleteMessageQueue(MessageQueueIF* queue) { From 98333b92eff9389783a2b70c4979eed4b96d5e88 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 22 Sep 2020 15:57:26 +0200 Subject: [PATCH 057/101] srv17 id added, include fix for linux --- objectmanager/frameworkObjects.h | 1 + osal/linux/Clock.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/objectmanager/frameworkObjects.h b/objectmanager/frameworkObjects.h index 4a30e70a..a7103018 100644 --- a/objectmanager/frameworkObjects.h +++ b/objectmanager/frameworkObjects.h @@ -8,6 +8,7 @@ enum framework_objects { PUS_SERVICE_2 = 0x53000002, PUS_SERVICE_5 = 0x53000005, PUS_SERVICE_8 = 0x53000008, + PUS_SERVICE_17 = 0x53000017, PUS_SERVICE_200 = 0x53000200, //Generic IDs for IPC, modes, health, events diff --git a/osal/linux/Clock.cpp b/osal/linux/Clock.cpp index b14f2a97..4de18f83 100644 --- a/osal/linux/Clock.cpp +++ b/osal/linux/Clock.cpp @@ -6,8 +6,8 @@ #include #include #include +#include -//#include uint16_t Clock::leapSeconds = 0; MutexIF* Clock::timeMutex = NULL; From ab0f4d8c87aedf5013debc6012da3aebb4389f8a Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 22 Sep 2020 16:01:34 +0200 Subject: [PATCH 058/101] service 9 ID added --- objectmanager/frameworkObjects.h | 1 + 1 file changed, 1 insertion(+) diff --git a/objectmanager/frameworkObjects.h b/objectmanager/frameworkObjects.h index a7103018..87439c88 100644 --- a/objectmanager/frameworkObjects.h +++ b/objectmanager/frameworkObjects.h @@ -8,6 +8,7 @@ enum framework_objects { PUS_SERVICE_2 = 0x53000002, PUS_SERVICE_5 = 0x53000005, PUS_SERVICE_8 = 0x53000008, + PUS_SERVICE_9 = 0x53000009, PUS_SERVICE_17 = 0x53000017, PUS_SERVICE_200 = 0x53000200, From ed80768c66335e7404e905a94db33ae0e0cc2f78 Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Tue, 22 Sep 2020 16:13:45 +0200 Subject: [PATCH 059/101] Fixes #194 --- container/ArrayList.h | 5 ++--- container/FixedOrderedMultimap.h | 7 +++---- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/container/ArrayList.h b/container/ArrayList.h index be89761e..37df6d54 100644 --- a/container/ArrayList.h +++ b/container/ArrayList.h @@ -95,10 +95,9 @@ public: //SHOULDDO this should be implemented as non-member bool operator!=(const typename ArrayList::Iterator& other) const { - return !(*this == other); + return !(*this ==other); } - } - ; + }; /** * Number of Elements stored in this List diff --git a/container/FixedOrderedMultimap.h b/container/FixedOrderedMultimap.h index 31282f80..c5fd2184 100644 --- a/container/FixedOrderedMultimap.h +++ b/container/FixedOrderedMultimap.h @@ -10,10 +10,9 @@ template> class FixedOrderedMultimap { public: - static const uint8_t INTERFACE_ID = CLASS_ID::FIXED_MAP; - static const ReturnValue_t KEY_ALREADY_EXISTS = MAKE_RETURN_CODE(0x01); - static const ReturnValue_t MAP_FULL = MAKE_RETURN_CODE(0x02); - static const ReturnValue_t KEY_DOES_NOT_EXIST = MAKE_RETURN_CODE(0x03); + static const uint8_t INTERFACE_ID = CLASS_ID::FIXED_MULTIMAP; + static const ReturnValue_t MAP_FULL = MAKE_RETURN_CODE(0x01); + static const ReturnValue_t KEY_DOES_NOT_EXIST = MAKE_RETURN_CODE(0x02); private: typedef KEY_COMPARE compare; From 74a4c98ca73b25de31e2ec678aeb9aff5f900e96 Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Tue, 22 Sep 2020 16:23:35 +0200 Subject: [PATCH 060/101] Small format stuff --- container/ArrayList.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/container/ArrayList.h b/container/ArrayList.h index 37df6d54..19454777 100644 --- a/container/ArrayList.h +++ b/container/ArrayList.h @@ -95,7 +95,7 @@ public: //SHOULDDO this should be implemented as non-member bool operator!=(const typename ArrayList::Iterator& other) const { - return !(*this ==other); + return !(*this == other); } }; From 59f72d1031a20e403cd52d2e3922e28c293b6537 Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Tue, 22 Sep 2020 16:59:13 +0200 Subject: [PATCH 061/101] Small fix with new pus services --- events/fwSubsystemIdRanges.h | 1 + returnvalues/FwClassIds.h | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/events/fwSubsystemIdRanges.h b/events/fwSubsystemIdRanges.h index 5e086f0e..1b0b238e 100644 --- a/events/fwSubsystemIdRanges.h +++ b/events/fwSubsystemIdRanges.h @@ -19,6 +19,7 @@ enum { SYSTEM_MANAGER_1 = 75, SYSTEM_1 = 79, PUS_SERVICE_1 = 80, + PUS_SERVICE_9 = 89, PUS_SERVICE_17 = 97, FW_SUBSYSTEM_ID_RANGE }; diff --git a/returnvalues/FwClassIds.h b/returnvalues/FwClassIds.h index e547025b..53add6a0 100644 --- a/returnvalues/FwClassIds.h +++ b/returnvalues/FwClassIds.h @@ -56,7 +56,6 @@ enum { DEVICE_COMMUNICATION_IF, //DC BSP, //BSP TIME_STAMPER_IF, //TSI 53 - //TODO This will shift all IDs for FLP SGP4PROPAGATOR_CLASS, //SGP4 54 MUTEX_IF, //MUX 55 MESSAGE_QUEUE_IF,//MQI 56 From 22d9b771654aba5698c6e4f94d8eb7a925d159e2 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sat, 26 Sep 2020 14:19:51 +0200 Subject: [PATCH 062/101] added documentation --- tasks/FixedSlotSequence.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tasks/FixedSlotSequence.h b/tasks/FixedSlotSequence.h index 19a05f21..077dd10b 100644 --- a/tasks/FixedSlotSequence.h +++ b/tasks/FixedSlotSequence.h @@ -139,6 +139,15 @@ public: */ ReturnValue_t checkSequence() const; + /** + * @brief A custom check can be injected for the respective slot list. + * @details + * This can be used by the developer to check the validity of a certain + * sequence. The function will be run in the #checkSequence function. + * The general check will be continued for now if the custom check function + * fails but a diagnostic debug output will be given. + * @param customCheckFunction + */ void addCustomCheck(ReturnValue_t (*customCheckFunction)(const SlotList &)); /** From 7b57f372bfa3347eb01d22d6e666446f468a3bb2 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sat, 26 Sep 2020 14:51:00 +0200 Subject: [PATCH 063/101] starting convergence --- memory/AcceptsMemoryMessagesIF.h | 13 ++---- memory/MemoryHelper.cpp | 47 ++++++++++---------- memory/MemoryHelper.h | 42 +++++++++++------- memory/MemoryMessage.cpp | 13 +++--- memory/MemoryMessage.h | 43 ++++++++++-------- memory/MemoryProxyIF.h | 2 +- modes/HasModesIF.h | 16 +++---- modes/ModeHelper.cpp | 75 ++++++++++++++++++++------------ modes/ModeHelper.h | 10 +++-- modes/ModeMessage.cpp | 2 +- 10 files changed, 147 insertions(+), 116 deletions(-) diff --git a/memory/AcceptsMemoryMessagesIF.h b/memory/AcceptsMemoryMessagesIF.h index a1cbddf8..cf8aa5ec 100644 --- a/memory/AcceptsMemoryMessagesIF.h +++ b/memory/AcceptsMemoryMessagesIF.h @@ -1,12 +1,5 @@ -/** - * @file AcceptsMemoryMessagesIF.h - * @brief This file defines the AcceptsMemoryMessagesIF class. - * @date 11.07.2013 - * @author baetz - */ - -#ifndef ACCEPTSMEMORYMESSAGESIF_H_ -#define ACCEPTSMEMORYMESSAGESIF_H_ +#ifndef FSFW_MEMORY_ACCEPTSMEMORYMESSAGESIF_H_ +#define FSFW_MEMORY_ACCEPTSMEMORYMESSAGESIF_H_ #include "HasMemoryIF.h" #include "MemoryMessage.h" @@ -18,4 +11,4 @@ public: }; -#endif /* ACCEPTSMEMORYMESSAGESIF_H_ */ +#endif /* AFSFW_MEMORY_ACCEPTSMEMORYMESSAGESIF_H_ */ diff --git a/memory/MemoryHelper.cpp b/memory/MemoryHelper.cpp index 48a605be..6b11882f 100644 --- a/memory/MemoryHelper.cpp +++ b/memory/MemoryHelper.cpp @@ -1,14 +1,15 @@ -#include "../globalfunctions/CRC.h" #include "MemoryHelper.h" #include "MemoryMessage.h" + +#include "../globalfunctions/CRC.h" #include "../objectmanager/ObjectManagerIF.h" #include "../serialize/EndianConverter.h" #include "../serviceinterface/ServiceInterfaceStream.h" -MemoryHelper::MemoryHelper(HasMemoryIF* workOnThis, MessageQueueIF* useThisQueue) : - workOnThis(workOnThis), queueToUse(useThisQueue), ipcStore(NULL), ipcAddress(), lastCommand( - CommandMessage::CMD_NONE), lastSender(0), reservedSpaceInIPC( - NULL), busy(false) { +MemoryHelper::MemoryHelper(HasMemoryIF* workOnThis, + MessageQueueIF* useThisQueue): + workOnThis(workOnThis), queueToUse(useThisQueue), ipcAddress(), + lastCommand(CommandMessage::CMD_NONE), busy(false) { } ReturnValue_t MemoryHelper::handleMemoryCommand(CommandMessage* message) { @@ -33,17 +34,8 @@ ReturnValue_t MemoryHelper::handleMemoryCommand(CommandMessage* message) { } } -ReturnValue_t MemoryHelper::initialize() { - ipcStore = objectManager->get(objects::IPC_STORE); - if (ipcStore != NULL) { - return RETURN_OK; - } else { - return RETURN_FAILED; - } -} - void MemoryHelper::completeLoad(ReturnValue_t errorCode, - const uint8_t* dataToCopy, const uint32_t size, uint8_t* copyHere) { + const uint8_t* dataToCopy, const size_t size, uint8_t* copyHere) { busy = false; switch (errorCode) { case HasMemoryIF::DO_IT_MYSELF: @@ -67,13 +59,13 @@ void MemoryHelper::completeLoad(ReturnValue_t errorCode, return; } //Only reached on success - CommandMessage reply(CommandMessage::REPLY_COMMAND_OK, 0, 0); + CommandMessage reply( CommandMessage::REPLY_COMMAND_OK, 0, 0); queueToUse->sendMessage(lastSender, &reply); ipcStore->deleteData(ipcAddress); } void MemoryHelper::completeDump(ReturnValue_t errorCode, - const uint8_t* dataToCopy, const uint32_t size) { + const uint8_t* dataToCopy, const size_t size) { busy = false; CommandMessage reply; MemoryMessage::setMemoryReplyFailed(&reply, errorCode, lastCommand); @@ -125,12 +117,12 @@ void MemoryHelper::completeDump(ReturnValue_t errorCode, break; } if (queueToUse->sendMessage(lastSender, &reply) != RETURN_OK) { - reply.clearCommandMessage(); + reply.clear(); } } void MemoryHelper::swapMatrixCopy(uint8_t* out, const uint8_t *in, - uint32_t totalSize, uint8_t datatypeSize) { + size_t totalSize, uint8_t datatypeSize) { if (totalSize % datatypeSize != 0){ return; } @@ -185,11 +177,18 @@ void MemoryHelper::handleMemoryCheckOrDump(CommandMessage* message) { } ReturnValue_t MemoryHelper::initialize(MessageQueueIF* queueToUse_) { - if(queueToUse_!=NULL){ - this->queueToUse = queueToUse_; - }else{ - return MessageQueueIF::NO_QUEUE; + if(queueToUse_ == nullptr) { + return HasReturnvaluesIF::RETURN_FAILED; } - + this->queueToUse = queueToUse_; return initialize(); } + +ReturnValue_t MemoryHelper::initialize() { + ipcStore = objectManager->get(objects::IPC_STORE); + if (ipcStore != nullptr) { + return RETURN_OK; + } else { + return RETURN_FAILED; + } +} diff --git a/memory/MemoryHelper.h b/memory/MemoryHelper.h index 5e1a99b6..a651861c 100644 --- a/memory/MemoryHelper.h +++ b/memory/MemoryHelper.h @@ -1,11 +1,16 @@ -#ifndef MEMORYHELPER_H_ -#define MEMORYHELPER_H_ -#include "../ipc/CommandMessage.h" +#ifndef FSFW_MEMORY_MEMORYHELPER_H_ +#define FSFW_MEMORY_MEMORYHELPER_H_ + #include "AcceptsMemoryMessagesIF.h" + +#include "../ipc/CommandMessage.h" #include "../returnvalues/HasReturnvaluesIF.h" #include "../storagemanager/StorageManagerIF.h" #include "../ipc/MessageQueueIF.h" +/** + * @brief TODO: documentation. + */ class MemoryHelper : public HasReturnvaluesIF { public: static const uint8_t INTERFACE_ID = CLASS_ID::MEMORY_HELPER; @@ -13,25 +18,32 @@ public: static const ReturnValue_t INVALID_ADDRESS = MAKE_RETURN_CODE(0xE1); static const ReturnValue_t INVALID_SIZE = MAKE_RETURN_CODE(0xE2); static const ReturnValue_t STATE_MISMATCH = MAKE_RETURN_CODE(0xE3); + + MemoryHelper(HasMemoryIF* workOnThis, MessageQueueIF* useThisQueue); + ~MemoryHelper(); + + ReturnValue_t handleMemoryCommand(CommandMessage* message); + void completeLoad(ReturnValue_t errorCode, + const uint8_t* dataToCopy = nullptr, const size_t size = 0, + uint8_t* copyHere = nullptr); + void completeDump(ReturnValue_t errorCode, + const uint8_t* dataToCopy = nullptr, const size_t size = 0); + void swapMatrixCopy(uint8_t *out, const uint8_t *in, size_t totalSize, + uint8_t datatypeSize); + ReturnValue_t initialize(MessageQueueIF* queueToUse_); + private: HasMemoryIF* workOnThis; MessageQueueIF* queueToUse; - StorageManagerIF* ipcStore; + StorageManagerIF* ipcStore = nullptr; store_address_t ipcAddress; Command_t lastCommand; - MessageQueueId_t lastSender; - uint8_t* reservedSpaceInIPC; + MessageQueueId_t lastSender = MessageQueueIF::NO_QUEUE; + uint8_t* reservedSpaceInIPC = nullptr; bool busy; void handleMemoryLoad(CommandMessage* message); void handleMemoryCheckOrDump(CommandMessage* message); ReturnValue_t initialize(); -public: - ReturnValue_t handleMemoryCommand(CommandMessage* message); - void completeLoad( ReturnValue_t errorCode, const uint8_t* dataToCopy = NULL, const uint32_t size = 0, uint8_t* copyHere = NULL ); - void completeDump( ReturnValue_t errorCode, const uint8_t* dataToCopy = NULL, const uint32_t size = 0); - void swapMatrixCopy( uint8_t *out, const uint8_t *in, uint32_t totalSize, uint8_t datatypeSize); - ReturnValue_t initialize(MessageQueueIF* queueToUse_); - MemoryHelper( HasMemoryIF* workOnThis, MessageQueueIF* useThisQueue ); - ~MemoryHelper(); + }; -#endif /* MEMORYHELPER_H_ */ +#endif /* FSFW_MEMORY_MEMORYHELPER_H_ */ diff --git a/memory/MemoryMessage.cpp b/memory/MemoryMessage.cpp index 741565fc..e1db004a 100644 --- a/memory/MemoryMessage.cpp +++ b/memory/MemoryMessage.cpp @@ -1,7 +1,6 @@ #include "MemoryMessage.h" + #include "../objectmanager/ObjectManagerIF.h" -MemoryMessage::MemoryMessage() { -} uint32_t MemoryMessage::getAddress(const CommandMessage* message) { return message->getParameter(); @@ -17,26 +16,24 @@ uint32_t MemoryMessage::getLength(const CommandMessage* message) { return message->getParameter2(); } -ReturnValue_t MemoryMessage::setMemoryDumpCommand(CommandMessage* message, +void MemoryMessage::setMemoryDumpCommand(CommandMessage* message, uint32_t address, uint32_t length) { message->setCommand(CMD_MEMORY_DUMP); message->setParameter( address ); message->setParameter2( length ); - return HasReturnvaluesIF::RETURN_OK; } -ReturnValue_t MemoryMessage::setMemoryDumpReply(CommandMessage* message, store_address_t storageID) { +void MemoryMessage::setMemoryDumpReply(CommandMessage* message, + store_address_t storageID) { message->setCommand(REPLY_MEMORY_DUMP); message->setParameter2( storageID.raw ); - return HasReturnvaluesIF::RETURN_OK; } -ReturnValue_t MemoryMessage::setMemoryLoadCommand(CommandMessage* message, +void MemoryMessage::setMemoryLoadCommand(CommandMessage* message, uint32_t address, store_address_t storageID) { message->setCommand(CMD_MEMORY_LOAD); message->setParameter( address ); message->setParameter2( storageID.raw ); - return HasReturnvaluesIF::RETURN_OK; } ReturnValue_t MemoryMessage::getErrorCode(const CommandMessage* message) { diff --git a/memory/MemoryMessage.h b/memory/MemoryMessage.h index a4c2de63..207e539f 100644 --- a/memory/MemoryMessage.h +++ b/memory/MemoryMessage.h @@ -1,14 +1,15 @@ -#ifndef MEMORYMESSAGE_H_ -#define MEMORYMESSAGE_H_ +#ifndef FSFW_MEMORY_MEMORYMESSAGE_H_ +#define FSFW_MEMORY_MEMORYMESSAGE_H_ #include "../ipc/CommandMessage.h" #include "../storagemanager/StorageManagerIF.h" class MemoryMessage { -private: - MemoryMessage(); //A private ctor inhibits instantiation public: + // Instantiation forbidden. + MemoryMessage() = delete; + static const uint8_t MESSAGE_ID = messagetypes::MEMORY; static const Command_t CMD_MEMORY_LOAD = MAKE_COMMAND_ID( 0x01 ); static const Command_t CMD_MEMORY_DUMP = MAKE_COMMAND_ID( 0x02 ); @@ -19,21 +20,29 @@ public: static const Command_t END_OF_MEMORY_COPY = MAKE_COMMAND_ID(0xF0); static uint32_t getAddress( const CommandMessage* message ); - static store_address_t getStoreID( const CommandMessage* message ); + static store_address_t getStoreID(const CommandMessage* message); static uint32_t getLength( const CommandMessage* message ); - static ReturnValue_t getErrorCode( const CommandMessage* message ); - static ReturnValue_t setMemoryDumpCommand( CommandMessage* message, uint32_t address, uint32_t length ); - static ReturnValue_t setMemoryDumpReply( CommandMessage* message, store_address_t storageID ); - static ReturnValue_t setMemoryLoadCommand( CommandMessage* message, uint32_t address, store_address_t storageID ); - static ReturnValue_t setMemoryCheckCommand( CommandMessage* message, uint32_t address, uint32_t length ); - static ReturnValue_t setMemoryCheckReply( CommandMessage* message, uint16_t crc ); - static ReturnValue_t setMemoryReplyFailed( CommandMessage* message, ReturnValue_t errorCode, Command_t initialCommand ); - static ReturnValue_t setMemoryCopyEnd( CommandMessage* message); + static ReturnValue_t getErrorCode(const CommandMessage* message); + static uint16_t getCrc(const CommandMessage* message ); + static ReturnValue_t getCrcReturnValue(const CommandMessage* message); + static Command_t getInitialCommand(const CommandMessage* message); + + static void setMemoryDumpCommand(CommandMessage* message, + uint32_t address, uint32_t length ); + static void setMemoryDumpReply(CommandMessage* message, + store_address_t storageID); + static void setMemoryLoadCommand(CommandMessage* message, + uint32_t address, store_address_t storageID ); + static ReturnValue_t setMemoryCheckCommand(CommandMessage* message, + uint32_t address, uint32_t length); + static ReturnValue_t setMemoryCheckReply(CommandMessage* message, + uint16_t crc); + static ReturnValue_t setMemoryReplyFailed(CommandMessage* message, + ReturnValue_t errorCode, Command_t initialCommand); + static ReturnValue_t setMemoryCopyEnd(CommandMessage* message); static void setCrcReturnValue(CommandMessage*, ReturnValue_t returnValue); - static uint16_t getCrc( const CommandMessage* message ); - static ReturnValue_t getCrcReturnValue(const CommandMessage* message); - static Command_t getInitialCommand( const CommandMessage* message ); + static void clear(CommandMessage* message); }; -#endif /* MEMORYMESSAGE_H_ */ +#endif /* FSFW_MEMORY_MEMORYMESSAGE_H_ */ diff --git a/memory/MemoryProxyIF.h b/memory/MemoryProxyIF.h index 1494d523..31045d3f 100644 --- a/memory/MemoryProxyIF.h +++ b/memory/MemoryProxyIF.h @@ -1,7 +1,7 @@ #ifndef FRAMEWORK_MEMORY_MEMORYPROXYIF_H_ #define FRAMEWORK_MEMORY_MEMORYPROXYIF_H_ -#include "AcceptsMemoryMessagesIF.h" +#include "../memory/AcceptsMemoryMessagesIF.h" /** * This was a nice idea to transparently forward incoming messages to another object. diff --git a/modes/HasModesIF.h b/modes/HasModesIF.h index 4381046c..39a50c2a 100644 --- a/modes/HasModesIF.h +++ b/modes/HasModesIF.h @@ -9,8 +9,8 @@ #define HASMODESIF_H_ #include "../events/Event.h" -#include "ModeHelper.h" -#include "ModeMessage.h" +#include "../modes/ModeHelper.h" +#include "../modes/ModeMessage.h" #include "../returnvalues/HasReturnvaluesIF.h" #include @@ -46,12 +46,12 @@ protected: uint32_t *msToReachTheMode) { return HasReturnvaluesIF::RETURN_FAILED; } - virtual void startTransition(Mode_t mode, Submode_t submode) { - } - virtual void setToExternalControl() { - } - virtual void announceMode(bool recursive) { - } + + virtual void startTransition(Mode_t mode, Submode_t submode) {} + + virtual void setToExternalControl() {} + + virtual void announceMode(bool recursive) {} }; #endif /* HASMODESIF_H_ */ diff --git a/modes/ModeHelper.cpp b/modes/ModeHelper.cpp index cb62c468..68f009e7 100644 --- a/modes/ModeHelper.cpp +++ b/modes/ModeHelper.cpp @@ -1,48 +1,47 @@ -#include "HasModesIF.h" -#include "ModeHelper.h" #include "../ipc/MessageQueueSenderIF.h" +#include "../modes/HasModesIF.h" +#include "../modes/ModeHelper.h" +#include "../serviceinterface/ServiceInterfaceStream.h" ModeHelper::ModeHelper(HasModesIF *owner) : - theOneWhoCommandedAMode(0), commandedMode(HasModesIF::MODE_OFF), commandedSubmode( - HasModesIF::SUBMODE_NONE), owner(owner), parentQueueId(0), forced( - false) { -} + commandedMode(HasModesIF::MODE_OFF), + commandedSubmode(HasModesIF::SUBMODE_NONE), + owner(owner), forced(false) {} ModeHelper::~ModeHelper() { } -ReturnValue_t ModeHelper::handleModeCommand(CommandMessage* message) { +ReturnValue_t ModeHelper::handleModeCommand(CommandMessage* command) { CommandMessage reply; Mode_t mode; Submode_t submode; - switch (message->getCommand()) { + switch (command->getCommand()) { case ModeMessage::CMD_MODE_COMMAND_FORCED: forced = true; /* NO BREAK falls through*/ case ModeMessage::CMD_MODE_COMMAND: { - mode = ModeMessage::getMode(message); - submode = ModeMessage::getSubmode(message); + mode = ModeMessage::getMode(command); + submode = ModeMessage::getSubmode(command); uint32_t timeout; ReturnValue_t result = owner->checkModeCommand(mode, submode, &timeout); if (result != HasReturnvaluesIF::RETURN_OK) { ModeMessage::cantReachMode(&reply, result); - MessageQueueSenderIF::sendMessage(message->getSender(), &reply, - owner->getCommandQueue()); + MessageQueueSenderIF::sendMessage(command->getSender(), &reply, + owner->getCommandQueue()); break; } //Free to start transition - theOneWhoCommandedAMode = message->getSender(); + theOneWhoCommandedAMode = command->getSender(); commandedMode = mode; commandedSubmode = submode; - if ((parentQueueId != MessageQueueSenderIF::NO_QUEUE) + if ((parentQueueId != MessageQueueIF::NO_QUEUE) && (theOneWhoCommandedAMode != parentQueueId)) { owner->setToExternalControl(); } countdown.setTimeout(timeout); - owner->startTransition(mode, submode); } break; @@ -50,8 +49,8 @@ ReturnValue_t ModeHelper::handleModeCommand(CommandMessage* message) { owner->getMode(&mode, &submode); ModeMessage::setModeMessage(&reply, ModeMessage::REPLY_MODE_REPLY, mode, submode); - MessageQueueSenderIF::sendMessage(message->getSender(), &reply, - owner->getCommandQueue()); + MessageQueueSenderIF::sendMessage(command->getSender(), &reply, + owner->getCommandQueue()); } break; case ModeMessage::CMD_MODE_ANNOUNCE: @@ -71,27 +70,45 @@ ReturnValue_t ModeHelper::initialize(MessageQueueId_t parentQueueId) { return initialize(); } -void ModeHelper::modeChanged(Mode_t mode, Submode_t submode) { +void ModeHelper::modeChanged(Mode_t ownerMode, Submode_t ownerSubmode) { forced = false; + sendModeReplyMessage(ownerMode, ownerSubmode); + sendModeInfoMessage(ownerMode, ownerSubmode); + theOneWhoCommandedAMode = MessageQueueIF::NO_QUEUE; +} + +void ModeHelper::sendModeReplyMessage(Mode_t ownerMode, + Submode_t ownerSubmode) { CommandMessage reply; - if (theOneWhoCommandedAMode != MessageQueueSenderIF::NO_QUEUE) { - if ((mode != commandedMode) || (submode != commandedSubmode)) { + if (theOneWhoCommandedAMode != MessageQueueIF::NO_QUEUE) + { + if (ownerMode != commandedMode or ownerSubmode != commandedSubmode) + { ModeMessage::setModeMessage(&reply, - ModeMessage::REPLY_WRONG_MODE_REPLY, mode, submode); - } else { + ModeMessage::REPLY_WRONG_MODE_REPLY, ownerMode, + ownerSubmode); + } + else + { ModeMessage::setModeMessage(&reply, ModeMessage::REPLY_MODE_REPLY, - mode, submode); + ownerMode, ownerSubmode); } MessageQueueSenderIF::sendMessage(theOneWhoCommandedAMode, &reply, - owner->getCommandQueue()); + owner->getCommandQueue()); } +} + +void ModeHelper::sendModeInfoMessage(Mode_t ownerMode, + Submode_t ownerSubmode) { + CommandMessage reply; if (theOneWhoCommandedAMode != parentQueueId - && parentQueueId != MessageQueueSenderIF::NO_QUEUE) { - ModeMessage::setModeMessage(&reply, ModeMessage::REPLY_MODE_INFO, mode, - submode); - MessageQueueSenderIF::sendMessage(parentQueueId, &reply, owner->getCommandQueue()); + and parentQueueId != MessageQueueIF::NO_QUEUE) + { + ModeMessage::setModeMessage(&reply, ModeMessage::REPLY_MODE_INFO, + ownerMode, ownerSubmode); + MessageQueueSenderIF::sendMessage(parentQueueId, &reply, + owner->getCommandQueue()); } - theOneWhoCommandedAMode = MessageQueueSenderIF::NO_QUEUE; } void ModeHelper::startTimer(uint32_t timeoutMs) { diff --git a/modes/ModeHelper.h b/modes/ModeHelper.h index 542fe780..02cf5799 100644 --- a/modes/ModeHelper.h +++ b/modes/ModeHelper.h @@ -1,7 +1,8 @@ #ifndef MODEHELPER_H_ #define MODEHELPER_H_ -#include "ModeMessage.h" +#include "../ipc/MessageQueueIF.h" +#include "../modes/ModeMessage.h" #include "../returnvalues/HasReturnvaluesIF.h" #include "../timemanager/Countdown.h" @@ -9,7 +10,7 @@ class HasModesIF; class ModeHelper { public: - MessageQueueId_t theOneWhoCommandedAMode; + MessageQueueId_t theOneWhoCommandedAMode = MessageQueueIF::NO_QUEUE; Mode_t commandedMode; Submode_t commandedSubmode; @@ -39,11 +40,14 @@ public: void setForced(bool forced); protected: HasModesIF *owner; - MessageQueueId_t parentQueueId; + MessageQueueId_t parentQueueId = MessageQueueIF::NO_QUEUE; Countdown countdown; bool forced; +private: + void sendModeReplyMessage(Mode_t ownerMode, Submode_t ownerSubmode); + void sendModeInfoMessage(Mode_t ownerMode, Submode_t ownerSubmode); }; #endif /* MODEHELPER_H_ */ diff --git a/modes/ModeMessage.cpp b/modes/ModeMessage.cpp index 14dbbb31..7ad7d06f 100644 --- a/modes/ModeMessage.cpp +++ b/modes/ModeMessage.cpp @@ -1,4 +1,4 @@ -#include "ModeMessage.h" +#include "../modes/ModeMessage.h" Mode_t ModeMessage::getMode(const CommandMessage* message) { return message->getParameter(); From 9d4c2b90f375ed5b5940b33a6087067294388179 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sat, 26 Sep 2020 14:54:23 +0200 Subject: [PATCH 064/101] removed proxy/ not used&working? --- memory/MemoryMessage.cpp | 15 ++++++--------- memory/MemoryMessage.h | 8 ++++---- memory/MemoryProxyIF.h | 22 ---------------------- 3 files changed, 10 insertions(+), 35 deletions(-) delete mode 100644 memory/MemoryProxyIF.h diff --git a/memory/MemoryMessage.cpp b/memory/MemoryMessage.cpp index e1db004a..94fa4691 100644 --- a/memory/MemoryMessage.cpp +++ b/memory/MemoryMessage.cpp @@ -62,22 +62,21 @@ void MemoryMessage::clear(CommandMessage* message) { } } -ReturnValue_t MemoryMessage::setMemoryCheckCommand(CommandMessage* message, +void MemoryMessage::setMemoryCheckCommand(CommandMessage* message, uint32_t address, uint32_t length) { message->setCommand(CMD_MEMORY_CHECK); message->setParameter( address ); message->setParameter2( length ); - return HasReturnvaluesIF::RETURN_OK; } -ReturnValue_t MemoryMessage::setMemoryCheckReply(CommandMessage* message, +void MemoryMessage::setMemoryCheckReply(CommandMessage* message, uint16_t crc) { message->setCommand(REPLY_MEMORY_CHECK); message->setParameter( crc ); - return HasReturnvaluesIF::RETURN_OK; } -void MemoryMessage::setCrcReturnValue(CommandMessage* message, ReturnValue_t returnValue){ +void MemoryMessage::setCrcReturnValue(CommandMessage* message, + ReturnValue_t returnValue){ message->setParameter(returnValue<<16); }; @@ -93,18 +92,16 @@ Command_t MemoryMessage::getInitialCommand(const CommandMessage* message) { return message->getParameter2(); } -ReturnValue_t MemoryMessage::setMemoryReplyFailed(CommandMessage* message, +void MemoryMessage::setMemoryReplyFailed(CommandMessage* message, ReturnValue_t errorCode, Command_t initialCommand) { message->setCommand(REPLY_MEMORY_FAILED); message->setParameter(errorCode); message->setParameter2(initialCommand); - return HasReturnvaluesIF::RETURN_OK; } -ReturnValue_t MemoryMessage::setMemoryCopyEnd(CommandMessage* message) { +void MemoryMessage::setMemoryCopyEnd(CommandMessage* message) { message->setCommand(END_OF_MEMORY_COPY); message->setParameter(0); message->setParameter2(0); - return HasReturnvaluesIF::RETURN_OK; } diff --git a/memory/MemoryMessage.h b/memory/MemoryMessage.h index 207e539f..05b9926d 100644 --- a/memory/MemoryMessage.h +++ b/memory/MemoryMessage.h @@ -33,13 +33,13 @@ public: store_address_t storageID); static void setMemoryLoadCommand(CommandMessage* message, uint32_t address, store_address_t storageID ); - static ReturnValue_t setMemoryCheckCommand(CommandMessage* message, + static void setMemoryCheckCommand(CommandMessage* message, uint32_t address, uint32_t length); - static ReturnValue_t setMemoryCheckReply(CommandMessage* message, + static void setMemoryCheckReply(CommandMessage* message, uint16_t crc); - static ReturnValue_t setMemoryReplyFailed(CommandMessage* message, + static void setMemoryReplyFailed(CommandMessage* message, ReturnValue_t errorCode, Command_t initialCommand); - static ReturnValue_t setMemoryCopyEnd(CommandMessage* message); + static void setMemoryCopyEnd(CommandMessage* message); static void setCrcReturnValue(CommandMessage*, ReturnValue_t returnValue); static void clear(CommandMessage* message); diff --git a/memory/MemoryProxyIF.h b/memory/MemoryProxyIF.h deleted file mode 100644 index 31045d3f..00000000 --- a/memory/MemoryProxyIF.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef FRAMEWORK_MEMORY_MEMORYPROXYIF_H_ -#define FRAMEWORK_MEMORY_MEMORYPROXYIF_H_ - -#include "../memory/AcceptsMemoryMessagesIF.h" - -/** - * This was a nice idea to transparently forward incoming messages to another object. - * But it doesn't work like that. - */ -class MemoryProxyIF : public AcceptsMemoryMessagesIF { -public: - virtual MessageQueueId_t getProxyQueue() const = 0; - MessageQueueId_t getCommandQueue() const { - return getProxyQueue(); - } - virtual ~MemoryProxyIF() {} - -}; - - - -#endif /* FRAMEWORK_MEMORY_MEMORYPROXYIF_H_ */ From 6d2266f7d0c9b4c8e219e00afebb6bff41b16d9f Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sat, 26 Sep 2020 14:58:53 +0200 Subject: [PATCH 065/101] equalization complete --- modes/HasModesIF.h | 24 +++++++++--------------- modes/ModeHelper.cpp | 7 ++++--- modes/ModeHelper.h | 14 +++++++------- modes/ModeMessage.cpp | 10 +++++----- modes/ModeMessage.h | 20 +++++++------------- 5 files changed, 32 insertions(+), 43 deletions(-) diff --git a/modes/HasModesIF.h b/modes/HasModesIF.h index 39a50c2a..34a15937 100644 --- a/modes/HasModesIF.h +++ b/modes/HasModesIF.h @@ -1,18 +1,11 @@ -/** - * @file HasModesIF.h - * @brief This file defines the HasModesIF class. - * @date 20.06.2013 - * @author baetz - */ - -#ifndef HASMODESIF_H_ -#define HASMODESIF_H_ +#ifndef FSFW_MODES_HASMODESIF_H_ +#define FSFW_MODES_HASMODESIF_H_ +#include "ModeHelper.h" +#include "ModeMessage.h" #include "../events/Event.h" -#include "../modes/ModeHelper.h" -#include "../modes/ModeMessage.h" #include "../returnvalues/HasReturnvaluesIF.h" -#include +#include class HasModesIF { @@ -37,10 +30,11 @@ public: 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 ~HasModesIF() {} virtual MessageQueueId_t getCommandQueue() const = 0; virtual void getMode(Mode_t *mode, Submode_t *submode) = 0; + protected: virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode, uint32_t *msToReachTheMode) { @@ -54,4 +48,4 @@ protected: virtual void announceMode(bool recursive) {} }; -#endif /* HASMODESIF_H_ */ +#endif /*FSFW_MODES_HASMODESIF_H_ */ diff --git a/modes/ModeHelper.cpp b/modes/ModeHelper.cpp index 68f009e7..6be4f776 100644 --- a/modes/ModeHelper.cpp +++ b/modes/ModeHelper.cpp @@ -1,6 +1,7 @@ +#include "HasModesIF.h" +#include "ModeHelper.h" + #include "../ipc/MessageQueueSenderIF.h" -#include "../modes/HasModesIF.h" -#include "../modes/ModeHelper.h" #include "../serviceinterface/ServiceInterfaceStream.h" ModeHelper::ModeHelper(HasModesIF *owner) : @@ -26,7 +27,7 @@ ReturnValue_t ModeHelper::handleModeCommand(CommandMessage* command) { uint32_t timeout; ReturnValue_t result = owner->checkModeCommand(mode, submode, &timeout); if (result != HasReturnvaluesIF::RETURN_OK) { - ModeMessage::cantReachMode(&reply, result); + ModeMessage::setCantReachMode(&reply, result); MessageQueueSenderIF::sendMessage(command->getSender(), &reply, owner->getCommandQueue()); break; diff --git a/modes/ModeHelper.h b/modes/ModeHelper.h index 02cf5799..c2f089ec 100644 --- a/modes/ModeHelper.h +++ b/modes/ModeHelper.h @@ -1,8 +1,8 @@ -#ifndef MODEHELPER_H_ -#define MODEHELPER_H_ +#ifndef FSFW_MODES_MODEHELPER_H_ +#define FSFW_MODES_MODEHELPER_H_ +#include "ModeMessage.h" #include "../ipc/MessageQueueIF.h" -#include "../modes/ModeMessage.h" #include "../returnvalues/HasReturnvaluesIF.h" #include "../timemanager/Countdown.h" @@ -20,14 +20,14 @@ public: ReturnValue_t handleModeCommand(CommandMessage *message); /** - * - * @param parentQueue the Queue id of the parent object. Set to 0 if no parent present + * @param parentQueue the Queue id of the parent object. + * Set to 0 if no parent present */ void setParentQueue(MessageQueueId_t parentQueueId); ReturnValue_t initialize(MessageQueueId_t parentQueueId); - ReturnValue_t initialize(void); //void is there to stop eclipse CODAN from falsely reporting an error + ReturnValue_t initialize(void); void modeChanged(Mode_t mode, Submode_t submode); @@ -50,4 +50,4 @@ private: void sendModeInfoMessage(Mode_t ownerMode, Submode_t ownerSubmode); }; -#endif /* MODEHELPER_H_ */ +#endif /* FSFW_MODES_MODEHELPER_H_ */ diff --git a/modes/ModeMessage.cpp b/modes/ModeMessage.cpp index 7ad7d06f..b33bba60 100644 --- a/modes/ModeMessage.cpp +++ b/modes/ModeMessage.cpp @@ -1,4 +1,4 @@ -#include "../modes/ModeMessage.h" +#include "ModeMessage.h" Mode_t ModeMessage::getMode(const CommandMessage* message) { return message->getParameter(); @@ -8,12 +8,11 @@ Submode_t ModeMessage::getSubmode(const CommandMessage* message) { return message->getParameter2(); } -ReturnValue_t ModeMessage::setModeMessage(CommandMessage* message, Command_t command, - Mode_t mode, Submode_t submode) { +void ModeMessage::setModeMessage(CommandMessage* message, + Command_t command, Mode_t mode, Submode_t submode) { message->setCommand( command ); message->setParameter( mode ); message->setParameter2( submode ); - return HasReturnvaluesIF::RETURN_OK; } ReturnValue_t ModeMessage::getCantReachModeReason(const CommandMessage* message) { @@ -24,7 +23,8 @@ void ModeMessage::clear(CommandMessage* message) { message->setCommand(CommandMessage::CMD_NONE); } -void ModeMessage::cantReachMode(CommandMessage* message, ReturnValue_t reason) { +void ModeMessage::setCantReachMode(CommandMessage* message, + ReturnValue_t reason) { message->setCommand(REPLY_CANT_REACH_MODE); message->setParameter(reason); message->setParameter2(0); diff --git a/modes/ModeMessage.h b/modes/ModeMessage.h index 925f3fc1..856996cf 100644 --- a/modes/ModeMessage.h +++ b/modes/ModeMessage.h @@ -1,12 +1,5 @@ -/** - * @file ModeMessage.h - * @brief This file defines the ModeMessage class. - * @date 17.07.2013 - * @author baetz - */ - -#ifndef MODEMESSAGE_H_ -#define MODEMESSAGE_H_ +#ifndef FSFW_MODES_MODEMESSAGE_H_ +#define FSFW_MODES_MODEMESSAGE_H_ #include "../ipc/CommandMessage.h" @@ -30,11 +23,12 @@ public: static Mode_t getMode(const CommandMessage* message); static Submode_t getSubmode(const CommandMessage* message); - static ReturnValue_t setModeMessage(CommandMessage* message, + static ReturnValue_t getCantReachModeReason(const CommandMessage* message); + + static void setModeMessage(CommandMessage* message, Command_t command, Mode_t mode, Submode_t submode); - static void cantReachMode(CommandMessage* message, ReturnValue_t reason); - static ReturnValue_t getCantReachModeReason(const CommandMessage* message); + static void setCantReachMode(CommandMessage* message, ReturnValue_t reason); static void clear(CommandMessage* message); }; -#endif /* MODEMESSAGE_H_ */ +#endif /* FSFW_MODES_MODEMESSAGE_H_ */ From 183b6a419338dbc2680526ab02314b62b1f3fa1d Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 29 Sep 2020 13:34:27 +0200 Subject: [PATCH 066/101] small bugfix --- objectmanager/frameworkObjects.h | 14 ++--- tmtcservices/VerificationReporter.cpp | 77 +++++++++++++++------------ tmtcservices/VerificationReporter.h | 41 ++++++++++---- 3 files changed, 81 insertions(+), 51 deletions(-) diff --git a/objectmanager/frameworkObjects.h b/objectmanager/frameworkObjects.h index 87439c88..4d08f084 100644 --- a/objectmanager/frameworkObjects.h +++ b/objectmanager/frameworkObjects.h @@ -4,13 +4,13 @@ namespace objects { enum framework_objects { // Default verification reporter. - PUS_SERVICE_1 = 0x53000001, - PUS_SERVICE_2 = 0x53000002, - PUS_SERVICE_5 = 0x53000005, - PUS_SERVICE_8 = 0x53000008, - PUS_SERVICE_9 = 0x53000009, - PUS_SERVICE_17 = 0x53000017, - PUS_SERVICE_200 = 0x53000200, + PUS_SERVICE_1_VERIFICATION = 0x53000001, + PUS_SERVICE_2_DEVICE_ACCESS = 0x53000002, + PUS_SERVICE_5_EVENT_REPORTING = 0x53000005, + PUS_SERVICE_8_FUNCTION_MGMT = 0x53000008, + PUS_SERVICE_9_TIME_MGMT = 0x53000009, + PUS_SERVICE_17_TEST = 0x53000017, + PUS_SERVICE_200_MODE_MGMT = 0x53000200, //Generic IDs for IPC, modes, health, events HEALTH_TABLE = 0x53010000, diff --git a/tmtcservices/VerificationReporter.cpp b/tmtcservices/VerificationReporter.cpp index 43e712a2..7e40bd27 100644 --- a/tmtcservices/VerificationReporter.cpp +++ b/tmtcservices/VerificationReporter.cpp @@ -1,55 +1,59 @@ -#include "../serviceinterface/ServiceInterfaceStream.h" +#include "VerificationReporter.h" #include "AcceptsVerifyMessageIF.h" #include "PusVerificationReport.h" -#include "VerificationReporter.h" -object_id_t VerificationReporter::messageReceiver = 0; +#include "../ipc/MessageQueueIF.h" +#include "../serviceinterface/ServiceInterfaceStream.h" +#include "../objectmanager/frameworkObjects.h" + +object_id_t VerificationReporter::messageReceiver = + objects::PUS_SERVICE_1_VERIFICATION; VerificationReporter::VerificationReporter() : - acknowledgeQueue() { + acknowledgeQueue(MessageQueueIF::NO_QUEUE) { } -VerificationReporter::~VerificationReporter() { - //Default, empty -} +VerificationReporter::~VerificationReporter() {} void VerificationReporter::sendSuccessReport(uint8_t set_report_id, TcPacketBase* current_packet, uint8_t set_step) { - if (this->acknowledgeQueue == 0) { + if (acknowledgeQueue == MessageQueueIF::NO_QUEUE) { this->initialize(); } PusVerificationMessage message(set_report_id, current_packet->getAcknowledgeFlags(), current_packet->getPacketId(), current_packet->getPacketSequenceControl(), 0, set_step); - ReturnValue_t status = MessageQueueSenderIF::sendMessage(acknowledgeQueue, &message); + ReturnValue_t status = MessageQueueSenderIF::sendMessage(acknowledgeQueue, + &message); if (status != HasReturnvaluesIF::RETURN_OK) { - sif::error - << "VerificationReporter::sendSuccessReport: Error writing to queue. Code: " - << (uint16_t) status << std::endl; + sif::error << "VerificationReporter::sendSuccessReport: Error writing " + << "to queue. Code: " << std::hex << status << std::dec + << std::endl; } } void VerificationReporter::sendSuccessReport(uint8_t set_report_id, uint8_t ackFlags, uint16_t tcPacketId, uint16_t tcSequenceControl, uint8_t set_step) { - if (this->acknowledgeQueue == 0) { + if (acknowledgeQueue == MessageQueueIF::NO_QUEUE) { this->initialize(); } PusVerificationMessage message(set_report_id, ackFlags, tcPacketId, tcSequenceControl, 0, set_step); - ReturnValue_t status = MessageQueueSenderIF::sendMessage(acknowledgeQueue, &message); + ReturnValue_t status = MessageQueueSenderIF::sendMessage(acknowledgeQueue, + &message); if (status != HasReturnvaluesIF::RETURN_OK) { - sif::error - << "VerificationReporter::sendSuccessReport: Error writing to queue. Code: " - << (uint16_t) status << std::endl; + sif::error << "VerificationReporter::sendSuccessReport: Error writing " + << "to queue. Code: " << std::hex << status << std::dec + << std::endl; } } void VerificationReporter::sendFailureReport(uint8_t report_id, TcPacketBase* current_packet, ReturnValue_t error_code, uint8_t step, uint32_t parameter1, uint32_t parameter2) { - if (this->acknowledgeQueue == 0) { + if (acknowledgeQueue == MessageQueueIF::NO_QUEUE) { this->initialize(); } PusVerificationMessage message(report_id, @@ -57,11 +61,12 @@ void VerificationReporter::sendFailureReport(uint8_t report_id, current_packet->getPacketId(), current_packet->getPacketSequenceControl(), error_code, step, parameter1, parameter2); - ReturnValue_t status = MessageQueueSenderIF::sendMessage(acknowledgeQueue, &message); + ReturnValue_t status = MessageQueueSenderIF::sendMessage(acknowledgeQueue, + &message); if (status != HasReturnvaluesIF::RETURN_OK) { - sif::error - << "VerificationReporter::sendFailureReport Error writing to queue. Code: " - << (uint16_t) status << std::endl; + sif::error << "VerificationReporter::sendFailureReport: Error writing " + << "to queue. Code: " << std::hex << "0x" << status << std::dec + << std::endl; } } @@ -69,27 +74,33 @@ void VerificationReporter::sendFailureReport(uint8_t report_id, uint8_t ackFlags, uint16_t tcPacketId, uint16_t tcSequenceControl, ReturnValue_t error_code, uint8_t step, uint32_t parameter1, uint32_t parameter2) { - if (this->acknowledgeQueue == 0) { + if (acknowledgeQueue == MessageQueueIF::NO_QUEUE) { this->initialize(); } PusVerificationMessage message(report_id, ackFlags, tcPacketId, tcSequenceControl, error_code, step, parameter1, parameter2); - ReturnValue_t status = MessageQueueSenderIF::sendMessage(acknowledgeQueue, &message); + ReturnValue_t status = MessageQueueSenderIF::sendMessage(acknowledgeQueue, + &message); if (status != HasReturnvaluesIF::RETURN_OK) { - sif::error - << "VerificationReporter::sendFailureReport Error writing to queue. Code: " - << (uint16_t) status << std::endl; + sif::error << "VerificationReporter::sendFailureReport: Error writing " + << "to queue. Code: " << std::hex << "0x" << status << std::dec + << std::endl; } } void VerificationReporter::initialize() { + if(messageReceiver == objects::NO_OBJECT) { + sif::warning << "VerificationReporter::initialize: Verification message" + " receiver object ID not set yet in Factory!" << std::endl; + return; + } AcceptsVerifyMessageIF* temp = objectManager->get( messageReceiver); - if (temp != NULL) { - this->acknowledgeQueue = temp->getVerificationQueue(); - } else { - sif::error - << "VerificationReporter::VerificationReporter: Configuration error." - << std::endl; + if (temp == nullptr) { + sif::error << "VerificationReporter::initialize: Message " + << "receiver invalid. Make sure it is set up properly and " + << "implementsAcceptsVerifyMessageIF" << std::endl; + return; } + this->acknowledgeQueue = temp->getVerificationQueue(); } diff --git a/tmtcservices/VerificationReporter.h b/tmtcservices/VerificationReporter.h index 29a273c5..f26fa54f 100644 --- a/tmtcservices/VerificationReporter.h +++ b/tmtcservices/VerificationReporter.h @@ -1,31 +1,50 @@ -#ifndef VERIFICATIONREPORTER_H_ -#define VERIFICATIONREPORTER_H_ +#ifndef FSFW_TMTCSERVICES_VERIFICATIONREPORTER_H_ +#define FSFW_TMTCSERVICES_VERIFICATIONREPORTER_H_ -#include "../objectmanager/ObjectManagerIF.h" #include "PusVerificationReport.h" +#include "../objectmanager/ObjectManagerIF.h" namespace Factory{ void setStaticFrameworkObjectIds(); } +/** + * @brief This helper object is used to forward verification messages + * which are generated by the Flight Software Framework. + * @details + * The messages can be relayed to an arbitrary object, for example a dedicated + * Verification Reporter. The destination is set by setting the static framework + * Id VerificationReporter::messageReceiver. The default verification reporter + * will be the PUS service 1, which sends verification messages according + * to the PUS standard. + * + */ class VerificationReporter { friend void (Factory::setStaticFrameworkObjectIds)(); public: VerificationReporter(); virtual ~VerificationReporter(); - void sendSuccessReport( uint8_t set_report_id, TcPacketBase* current_packet, uint8_t set_step = 0 ); - void sendSuccessReport(uint8_t set_report_id, uint8_t ackFlags, uint16_t tcPacketId, uint16_t tcSequenceControl, uint8_t set_step = 0); - void sendFailureReport( uint8_t report_id, TcPacketBase* current_packet, ReturnValue_t error_code = 0, - uint8_t step = 0, uint32_t parameter1 = 0, uint32_t parameter2 = 0 ); + + void sendSuccessReport( uint8_t set_report_id, TcPacketBase* current_packet, + uint8_t set_step = 0 ); + void sendSuccessReport(uint8_t set_report_id, uint8_t ackFlags, + uint16_t tcPacketId, uint16_t tcSequenceControl, + uint8_t set_step = 0); + + void sendFailureReport( uint8_t report_id, TcPacketBase* current_packet, + ReturnValue_t error_code = 0, + uint8_t step = 0, uint32_t parameter1 = 0, + uint32_t parameter2 = 0 ); void sendFailureReport(uint8_t report_id, - uint8_t ackFlags, uint16_t tcPacketId, uint16_t tcSequenceControl, ReturnValue_t error_code = 0, uint8_t step = 0, + uint8_t ackFlags, uint16_t tcPacketId, uint16_t tcSequenceControl, + ReturnValue_t error_code = 0, uint8_t step = 0, uint32_t parameter1 = 0, uint32_t parameter2 = 0); + void initialize(); + private: static object_id_t messageReceiver; MessageQueueId_t acknowledgeQueue; - - }; -#endif /* VERIFICATIONREPORTER_H_ */ +#endif /* FSFW_TMTCSERVICES_VERIFICATIONREPORTER_H_ */ From 7dbb73b7d8e7cb9e655327e7341aeb5a23c1b046 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 29 Sep 2020 14:29:57 +0200 Subject: [PATCH 067/101] removed dbeug printout --- osal/FreeRTOS/FixedTimeslotTask.cpp | 9 --------- osal/FreeRTOS/PeriodicTask.cpp | 4 ---- 2 files changed, 13 deletions(-) diff --git a/osal/FreeRTOS/FixedTimeslotTask.cpp b/osal/FreeRTOS/FixedTimeslotTask.cpp index 309574eb..062686e2 100644 --- a/osal/FreeRTOS/FixedTimeslotTask.cpp +++ b/osal/FreeRTOS/FixedTimeslotTask.cpp @@ -150,15 +150,6 @@ void FixedTimeslotTask::handleMissedDeadline() { if(deadlineMissedFunc != nullptr) { this->deadlineMissedFunc(); } - -#ifdef DEBUG - object_id_t handlerId = pst.current->handlerId; - sif::warning << "FixedTimeslotTask: " << pcTaskGetName(NULL) << " with" - << " object ID 0x" << std::setfill('0') << std::setw(8) << std::hex - << handlerId << " missed deadline!" << std::setfill(' ') - << std::dec << std::endl; -#endif - } ReturnValue_t FixedTimeslotTask::sleepFor(uint32_t ms) { diff --git a/osal/FreeRTOS/PeriodicTask.cpp b/osal/FreeRTOS/PeriodicTask.cpp index 990d38d6..5c0a840d 100644 --- a/osal/FreeRTOS/PeriodicTask.cpp +++ b/osal/FreeRTOS/PeriodicTask.cpp @@ -133,10 +133,6 @@ TaskHandle_t PeriodicTask::getTaskHandle() { } void PeriodicTask::handleMissedDeadline() { -#ifdef DEBUG - sif::warning << "PeriodicTask: " << pcTaskGetName(NULL) << - " missed deadline!\n" << std::flush; -#endif if(deadlineMissedFunc != nullptr) { this->deadlineMissedFunc(); } From cef84b13d923524e10e497602b6b6c27a62a34d0 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 29 Sep 2020 14:35:05 +0200 Subject: [PATCH 068/101] renormalization --- ipc/messageQueueDefinitions.h | 38 +-- storagemanager/ConstStorageAccessor.cpp | 174 ++++++------ storagemanager/ConstStorageAccessor.h | 232 ++++++++-------- storagemanager/StorageAccessor.cpp | 134 +++++----- storagemanager/StorageAccessor.h | 90 +++---- storagemanager/StorageManagerIF.h | 334 ++++++++++++------------ 6 files changed, 501 insertions(+), 501 deletions(-) diff --git a/ipc/messageQueueDefinitions.h b/ipc/messageQueueDefinitions.h index 60c09b05..b4f861b8 100644 --- a/ipc/messageQueueDefinitions.h +++ b/ipc/messageQueueDefinitions.h @@ -1,19 +1,19 @@ -#ifndef FSFW_IPC_MESSAGEQUEUEDEFINITIONS_H_ -#define FSFW_IPC_MESSAGEQUEUEDEFINITIONS_H_ - -#include - -/* - * TODO: Actually, the definition of this ID to be a uint32_t is not ideal and - * breaks layering. However, it is difficult to keep layering, as the ID is - * stored in many places and sent around in MessageQueueMessage. - * Ideally, one would use the (current) object_id_t only, however, doing a - * lookup of queueIDs for every call does not sound ideal. - * In a first step, I'll circumvent the issue by not touching it, - * maybe in a second step. This also influences Interface design - * (getCommandQueue) and some other issues.. - */ -using MessageQueueId_t = uint32_t; - - -#endif /* FSFW_IPC_MESSAGEQUEUEDEFINITIONS_H_ */ +#ifndef FSFW_IPC_MESSAGEQUEUEDEFINITIONS_H_ +#define FSFW_IPC_MESSAGEQUEUEDEFINITIONS_H_ + +#include + +/* + * TODO: Actually, the definition of this ID to be a uint32_t is not ideal and + * breaks layering. However, it is difficult to keep layering, as the ID is + * stored in many places and sent around in MessageQueueMessage. + * Ideally, one would use the (current) object_id_t only, however, doing a + * lookup of queueIDs for every call does not sound ideal. + * In a first step, I'll circumvent the issue by not touching it, + * maybe in a second step. This also influences Interface design + * (getCommandQueue) and some other issues.. + */ +using MessageQueueId_t = uint32_t; + + +#endif /* FSFW_IPC_MESSAGEQUEUEDEFINITIONS_H_ */ diff --git a/storagemanager/ConstStorageAccessor.cpp b/storagemanager/ConstStorageAccessor.cpp index ea9f2e44..4ada7f80 100644 --- a/storagemanager/ConstStorageAccessor.cpp +++ b/storagemanager/ConstStorageAccessor.cpp @@ -1,87 +1,87 @@ -#include "../serviceinterface/ServiceInterfaceStream.h" -#include "../storagemanager/ConstStorageAccessor.h" -#include "../storagemanager/StorageManagerIF.h" -#include "../globalfunctions/arrayprinter.h" - -ConstStorageAccessor::ConstStorageAccessor(store_address_t storeId): - storeId(storeId) {} - -ConstStorageAccessor::ConstStorageAccessor(store_address_t storeId, - StorageManagerIF* store): - storeId(storeId), store(store) { - internalState = AccessState::ASSIGNED; -} - -ConstStorageAccessor::~ConstStorageAccessor() { - if(deleteData and store != nullptr) { - sif::debug << "deleting store data" << std::endl; - store->deleteData(storeId); - } -} - -ConstStorageAccessor::ConstStorageAccessor(ConstStorageAccessor&& other): - constDataPointer(other.constDataPointer), storeId(other.storeId), - size_(other.size_), store(other.store), deleteData(other.deleteData), - internalState(other.internalState) { - // This prevent premature deletion - other.store = nullptr; -} - -ConstStorageAccessor& ConstStorageAccessor::operator=( - ConstStorageAccessor&& other) { - constDataPointer = other.constDataPointer; - storeId = other.storeId; - store = other.store; - size_ = other.size_; - deleteData = other.deleteData; - this->store = other.store; - // This prevents premature deletion - other.store = nullptr; - return *this; -} - -const uint8_t* ConstStorageAccessor::data() const { - return constDataPointer; -} - -size_t ConstStorageAccessor::size() const { - if(internalState == AccessState::UNINIT) { - sif::warning << "StorageAccessor: Not initialized!" << std::endl; - } - return size_; -} - -ReturnValue_t ConstStorageAccessor::getDataCopy(uint8_t *pointer, - size_t maxSize) { - if(internalState == AccessState::UNINIT) { - sif::warning << "StorageAccessor: Not initialized!" << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; - } - if(size_ > maxSize) { - sif::error << "StorageAccessor: Supplied buffer not large enough" << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; - } - std::copy(constDataPointer, constDataPointer + size_, pointer); - return HasReturnvaluesIF::RETURN_OK; -} - -void ConstStorageAccessor::release() { - deleteData = false; -} - -store_address_t ConstStorageAccessor::getId() const { - return storeId; -} - -void ConstStorageAccessor::print() const { - if(internalState == AccessState::UNINIT or constDataPointer == nullptr) { - sif::warning << "StorageAccessor: Not initialized!" << std::endl; - return; - } - arrayprinter::print(constDataPointer, size_); -} - -void ConstStorageAccessor::assignStore(StorageManagerIF* store) { - internalState = AccessState::ASSIGNED; - this->store = store; -} +#include "../serviceinterface/ServiceInterfaceStream.h" +#include "../storagemanager/ConstStorageAccessor.h" +#include "../storagemanager/StorageManagerIF.h" +#include "../globalfunctions/arrayprinter.h" + +ConstStorageAccessor::ConstStorageAccessor(store_address_t storeId): + storeId(storeId) {} + +ConstStorageAccessor::ConstStorageAccessor(store_address_t storeId, + StorageManagerIF* store): + storeId(storeId), store(store) { + internalState = AccessState::ASSIGNED; +} + +ConstStorageAccessor::~ConstStorageAccessor() { + if(deleteData and store != nullptr) { + sif::debug << "deleting store data" << std::endl; + store->deleteData(storeId); + } +} + +ConstStorageAccessor::ConstStorageAccessor(ConstStorageAccessor&& other): + constDataPointer(other.constDataPointer), storeId(other.storeId), + size_(other.size_), store(other.store), deleteData(other.deleteData), + internalState(other.internalState) { + // This prevent premature deletion + other.store = nullptr; +} + +ConstStorageAccessor& ConstStorageAccessor::operator=( + ConstStorageAccessor&& other) { + constDataPointer = other.constDataPointer; + storeId = other.storeId; + store = other.store; + size_ = other.size_; + deleteData = other.deleteData; + this->store = other.store; + // This prevents premature deletion + other.store = nullptr; + return *this; +} + +const uint8_t* ConstStorageAccessor::data() const { + return constDataPointer; +} + +size_t ConstStorageAccessor::size() const { + if(internalState == AccessState::UNINIT) { + sif::warning << "StorageAccessor: Not initialized!" << std::endl; + } + return size_; +} + +ReturnValue_t ConstStorageAccessor::getDataCopy(uint8_t *pointer, + size_t maxSize) { + if(internalState == AccessState::UNINIT) { + sif::warning << "StorageAccessor: Not initialized!" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + if(size_ > maxSize) { + sif::error << "StorageAccessor: Supplied buffer not large enough" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + std::copy(constDataPointer, constDataPointer + size_, pointer); + return HasReturnvaluesIF::RETURN_OK; +} + +void ConstStorageAccessor::release() { + deleteData = false; +} + +store_address_t ConstStorageAccessor::getId() const { + return storeId; +} + +void ConstStorageAccessor::print() const { + if(internalState == AccessState::UNINIT or constDataPointer == nullptr) { + sif::warning << "StorageAccessor: Not initialized!" << std::endl; + return; + } + arrayprinter::print(constDataPointer, size_); +} + +void ConstStorageAccessor::assignStore(StorageManagerIF* store) { + internalState = AccessState::ASSIGNED; + this->store = store; +} diff --git a/storagemanager/ConstStorageAccessor.h b/storagemanager/ConstStorageAccessor.h index ec2da8ce..573892da 100644 --- a/storagemanager/ConstStorageAccessor.h +++ b/storagemanager/ConstStorageAccessor.h @@ -1,116 +1,116 @@ -#ifndef FRAMEWORK_STORAGEMANAGER_CONSTSTORAGEACCESSOR_H_ -#define FRAMEWORK_STORAGEMANAGER_CONSTSTORAGEACCESSOR_H_ - -#include "../storagemanager/storeAddress.h" -#include "../returnvalues/HasReturnvaluesIF.h" -#include - -class StorageManagerIF; - -/** - * @brief Helper classes to facilitate safe access to storages which is also - * conforming to RAII principles - * @details - * Accessor class which can be returned by pool manager or passed and set by - * pool managers to have safe access to the pool resources. - * - * These helper can be used together with the StorageManager classes to manage - * access to a storage. It can take care of thread-safety while also providing - * mechanisms to automatically clear storage data. - */ -class ConstStorageAccessor { - //! StorageManager classes have exclusive access to private variables. - template - friend class PoolManager; - template - friend class LocalPool; -public: - /** - * @brief Simple constructor which takes the store ID of the storage - * entry to access. - * @param storeId - */ - ConstStorageAccessor(store_address_t storeId); - ConstStorageAccessor(store_address_t storeId, StorageManagerIF* store); - - /** - * @brief The destructor in default configuration takes care of - * deleting the accessed pool entry and unlocking the mutex - */ - virtual ~ConstStorageAccessor(); - - /** - * @brief Returns a pointer to the read-only data - * @return - */ - const uint8_t* data() const; - - /** - * @brief Copies the read-only data to the supplied pointer - * @param pointer - */ - virtual ReturnValue_t getDataCopy(uint8_t *pointer, size_t maxSize); - - /** - * @brief Calling this will prevent the Accessor from deleting the data - * when the destructor is called. - */ - void release(); - - /** - * Get the size of the data - * @return - */ - size_t size() const; - - /** - * Get the storage ID. - * @return - */ - store_address_t getId() const; - - void print() const; - - /** - * @brief Move ctor and move assignment allow returning accessors as - * a returnvalue. They prevent resource being free prematurely. - * Refer to: https://github.com/MicrosoftDocs/cpp-docs/blob/master/docs/cpp/ - * move-constructors-and-move-assignment-operators-cpp.md - * @param - * @return - */ - ConstStorageAccessor& operator= (ConstStorageAccessor&&); - ConstStorageAccessor(ConstStorageAccessor&&); - - //! The copy ctor and copy assignemnt should be deleted implicitely - //! according to https://foonathan.net/2019/02/special-member-functions/ - //! but I still deleted them to make it more explicit. (remember rule of 5). - ConstStorageAccessor& operator=(const ConstStorageAccessor&) = delete; - ConstStorageAccessor(const ConstStorageAccessor&) = delete; -protected: - const uint8_t* constDataPointer = nullptr; - store_address_t storeId; - size_t size_ = 0; - //! Managing pool, has to assign itself. - StorageManagerIF* store = nullptr; - bool deleteData = true; - - enum class AccessState { - UNINIT, - ASSIGNED - }; - //! Internal state for safety reasons. - AccessState internalState = AccessState::UNINIT; - /** - * Used by the pool manager instances to assign themselves to the - * accessor. This is necessary to delete the data when the acessor - * exits the scope ! The internal state will be considered read - * when this function is called, so take care all data is set properly as - * well. - * @param - */ - void assignStore(StorageManagerIF*); -}; - - -#endif /* FRAMEWORK_STORAGEMANAGER_CONSTSTORAGEACCESSOR_H_ */ +#ifndef FRAMEWORK_STORAGEMANAGER_CONSTSTORAGEACCESSOR_H_ +#define FRAMEWORK_STORAGEMANAGER_CONSTSTORAGEACCESSOR_H_ + +#include "../storagemanager/storeAddress.h" +#include "../returnvalues/HasReturnvaluesIF.h" +#include + +class StorageManagerIF; + +/** + * @brief Helper classes to facilitate safe access to storages which is also + * conforming to RAII principles + * @details + * Accessor class which can be returned by pool manager or passed and set by + * pool managers to have safe access to the pool resources. + * + * These helper can be used together with the StorageManager classes to manage + * access to a storage. It can take care of thread-safety while also providing + * mechanisms to automatically clear storage data. + */ +class ConstStorageAccessor { + //! StorageManager classes have exclusive access to private variables. + template + friend class PoolManager; + template + friend class LocalPool; +public: + /** + * @brief Simple constructor which takes the store ID of the storage + * entry to access. + * @param storeId + */ + ConstStorageAccessor(store_address_t storeId); + ConstStorageAccessor(store_address_t storeId, StorageManagerIF* store); + + /** + * @brief The destructor in default configuration takes care of + * deleting the accessed pool entry and unlocking the mutex + */ + virtual ~ConstStorageAccessor(); + + /** + * @brief Returns a pointer to the read-only data + * @return + */ + const uint8_t* data() const; + + /** + * @brief Copies the read-only data to the supplied pointer + * @param pointer + */ + virtual ReturnValue_t getDataCopy(uint8_t *pointer, size_t maxSize); + + /** + * @brief Calling this will prevent the Accessor from deleting the data + * when the destructor is called. + */ + void release(); + + /** + * Get the size of the data + * @return + */ + size_t size() const; + + /** + * Get the storage ID. + * @return + */ + store_address_t getId() const; + + void print() const; + + /** + * @brief Move ctor and move assignment allow returning accessors as + * a returnvalue. They prevent resource being free prematurely. + * Refer to: https://github.com/MicrosoftDocs/cpp-docs/blob/master/docs/cpp/ + * move-constructors-and-move-assignment-operators-cpp.md + * @param + * @return + */ + ConstStorageAccessor& operator= (ConstStorageAccessor&&); + ConstStorageAccessor(ConstStorageAccessor&&); + + //! The copy ctor and copy assignemnt should be deleted implicitely + //! according to https://foonathan.net/2019/02/special-member-functions/ + //! but I still deleted them to make it more explicit. (remember rule of 5). + ConstStorageAccessor& operator=(const ConstStorageAccessor&) = delete; + ConstStorageAccessor(const ConstStorageAccessor&) = delete; +protected: + const uint8_t* constDataPointer = nullptr; + store_address_t storeId; + size_t size_ = 0; + //! Managing pool, has to assign itself. + StorageManagerIF* store = nullptr; + bool deleteData = true; + + enum class AccessState { + UNINIT, + ASSIGNED + }; + //! Internal state for safety reasons. + AccessState internalState = AccessState::UNINIT; + /** + * Used by the pool manager instances to assign themselves to the + * accessor. This is necessary to delete the data when the acessor + * exits the scope ! The internal state will be considered read + * when this function is called, so take care all data is set properly as + * well. + * @param + */ + void assignStore(StorageManagerIF*); +}; + + +#endif /* FRAMEWORK_STORAGEMANAGER_CONSTSTORAGEACCESSOR_H_ */ diff --git a/storagemanager/StorageAccessor.cpp b/storagemanager/StorageAccessor.cpp index d4d2a54d..60bd4130 100644 --- a/storagemanager/StorageAccessor.cpp +++ b/storagemanager/StorageAccessor.cpp @@ -1,67 +1,67 @@ -#include "../storagemanager/StorageAccessor.h" -#include "../storagemanager/StorageManagerIF.h" -#include "../serviceinterface/ServiceInterfaceStream.h" - -StorageAccessor::StorageAccessor(store_address_t storeId): - ConstStorageAccessor(storeId) { -} - -StorageAccessor::StorageAccessor(store_address_t storeId, - StorageManagerIF* store): - ConstStorageAccessor(storeId, store) { -} - -StorageAccessor& StorageAccessor::operator =( - StorageAccessor&& other) { - // Call the parent move assignment and also assign own member. - dataPointer = other.dataPointer; - StorageAccessor::operator=(std::move(other)); - return * this; -} - -// Call the parent move ctor and also transfer own member. -StorageAccessor::StorageAccessor(StorageAccessor&& other): - ConstStorageAccessor(std::move(other)), dataPointer(other.dataPointer) { -} - -ReturnValue_t StorageAccessor::getDataCopy(uint8_t *pointer, size_t maxSize) { - if(internalState == AccessState::UNINIT) { - sif::warning << "StorageAccessor: Not initialized!" << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; - } - if(size_ > maxSize) { - sif::error << "StorageAccessor: Supplied buffer not large " - "enough" << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; - } - std::copy(dataPointer, dataPointer + size_, pointer); - return HasReturnvaluesIF::RETURN_OK; -} - -uint8_t* StorageAccessor::data() { - if(internalState == AccessState::UNINIT) { - sif::warning << "StorageAccessor: Not initialized!" << std::endl; - } - return dataPointer; -} - -ReturnValue_t StorageAccessor::write(uint8_t *data, size_t size, - uint16_t offset) { - if(internalState == AccessState::UNINIT) { - sif::warning << "StorageAccessor: Not initialized!" << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; - } - if(offset + size > size_) { - sif::error << "StorageAccessor: Data too large for pool " - "entry!" << std::endl; - return HasReturnvaluesIF::RETURN_FAILED; - } - std::copy(data, data + size, dataPointer + offset); - return HasReturnvaluesIF::RETURN_OK; -} - -void StorageAccessor::assignConstPointer() { - constDataPointer = dataPointer; -} - - +#include "../storagemanager/StorageAccessor.h" +#include "../storagemanager/StorageManagerIF.h" +#include "../serviceinterface/ServiceInterfaceStream.h" + +StorageAccessor::StorageAccessor(store_address_t storeId): + ConstStorageAccessor(storeId) { +} + +StorageAccessor::StorageAccessor(store_address_t storeId, + StorageManagerIF* store): + ConstStorageAccessor(storeId, store) { +} + +StorageAccessor& StorageAccessor::operator =( + StorageAccessor&& other) { + // Call the parent move assignment and also assign own member. + dataPointer = other.dataPointer; + StorageAccessor::operator=(std::move(other)); + return * this; +} + +// Call the parent move ctor and also transfer own member. +StorageAccessor::StorageAccessor(StorageAccessor&& other): + ConstStorageAccessor(std::move(other)), dataPointer(other.dataPointer) { +} + +ReturnValue_t StorageAccessor::getDataCopy(uint8_t *pointer, size_t maxSize) { + if(internalState == AccessState::UNINIT) { + sif::warning << "StorageAccessor: Not initialized!" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + if(size_ > maxSize) { + sif::error << "StorageAccessor: Supplied buffer not large " + "enough" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + std::copy(dataPointer, dataPointer + size_, pointer); + return HasReturnvaluesIF::RETURN_OK; +} + +uint8_t* StorageAccessor::data() { + if(internalState == AccessState::UNINIT) { + sif::warning << "StorageAccessor: Not initialized!" << std::endl; + } + return dataPointer; +} + +ReturnValue_t StorageAccessor::write(uint8_t *data, size_t size, + uint16_t offset) { + if(internalState == AccessState::UNINIT) { + sif::warning << "StorageAccessor: Not initialized!" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + if(offset + size > size_) { + sif::error << "StorageAccessor: Data too large for pool " + "entry!" << std::endl; + return HasReturnvaluesIF::RETURN_FAILED; + } + std::copy(data, data + size, dataPointer + offset); + return HasReturnvaluesIF::RETURN_OK; +} + +void StorageAccessor::assignConstPointer() { + constDataPointer = dataPointer; +} + + diff --git a/storagemanager/StorageAccessor.h b/storagemanager/StorageAccessor.h index 1ca5f7dd..a65427b8 100644 --- a/storagemanager/StorageAccessor.h +++ b/storagemanager/StorageAccessor.h @@ -1,45 +1,45 @@ -#ifndef FRAMEWORK_STORAGEMANAGER_STORAGEACCESSOR_H_ -#define FRAMEWORK_STORAGEMANAGER_STORAGEACCESSOR_H_ - -#include "../storagemanager/ConstStorageAccessor.h" - -class StorageManagerIF; - -/** - * @brief Child class for modifyable data. Also has a normal pointer member. - */ -class StorageAccessor: public ConstStorageAccessor { - //! StorageManager classes have exclusive access to private variables. - template - friend class PoolManager; - template - friend class LocalPool; -public: - StorageAccessor(store_address_t storeId); - StorageAccessor(store_address_t storeId, StorageManagerIF* store); - - /** - * @brief Move ctor and move assignment allow returning accessors as - * a returnvalue. They prevent resource being freed prematurely. - * See: https://github.com/MicrosoftDocs/cpp-docs/blob/master/docs/cpp/ - * move-constructors-and-move-assignment-operators-cpp.md - * @param - * @return - */ - StorageAccessor& operator=(StorageAccessor&&); - StorageAccessor(StorageAccessor&&); - - ReturnValue_t write(uint8_t *data, size_t size, - uint16_t offset = 0); - uint8_t* data(); - ReturnValue_t getDataCopy(uint8_t *pointer, size_t maxSize) override; - -private: - //! Non-const pointer for modifyable data. - uint8_t* dataPointer = nullptr; - //! For modifyable data, the const pointer is assigned to the normal - //! pointer by the pool manager so both access functions can be used safely - void assignConstPointer(); -}; - -#endif /* TEST_PROTOTYPES_STORAGEACCESSOR_H_ */ +#ifndef FRAMEWORK_STORAGEMANAGER_STORAGEACCESSOR_H_ +#define FRAMEWORK_STORAGEMANAGER_STORAGEACCESSOR_H_ + +#include "../storagemanager/ConstStorageAccessor.h" + +class StorageManagerIF; + +/** + * @brief Child class for modifyable data. Also has a normal pointer member. + */ +class StorageAccessor: public ConstStorageAccessor { + //! StorageManager classes have exclusive access to private variables. + template + friend class PoolManager; + template + friend class LocalPool; +public: + StorageAccessor(store_address_t storeId); + StorageAccessor(store_address_t storeId, StorageManagerIF* store); + + /** + * @brief Move ctor and move assignment allow returning accessors as + * a returnvalue. They prevent resource being freed prematurely. + * See: https://github.com/MicrosoftDocs/cpp-docs/blob/master/docs/cpp/ + * move-constructors-and-move-assignment-operators-cpp.md + * @param + * @return + */ + StorageAccessor& operator=(StorageAccessor&&); + StorageAccessor(StorageAccessor&&); + + ReturnValue_t write(uint8_t *data, size_t size, + uint16_t offset = 0); + uint8_t* data(); + ReturnValue_t getDataCopy(uint8_t *pointer, size_t maxSize) override; + +private: + //! Non-const pointer for modifyable data. + uint8_t* dataPointer = nullptr; + //! For modifyable data, the const pointer is assigned to the normal + //! pointer by the pool manager so both access functions can be used safely + void assignConstPointer(); +}; + +#endif /* TEST_PROTOTYPES_STORAGEACCESSOR_H_ */ diff --git a/storagemanager/StorageManagerIF.h b/storagemanager/StorageManagerIF.h index 85341f2e..2229cdf8 100644 --- a/storagemanager/StorageManagerIF.h +++ b/storagemanager/StorageManagerIF.h @@ -1,167 +1,167 @@ -#ifndef STORAGEMANAGERIF_H_H -#define STORAGEMANAGERIF_H_H - -#include "../events/Event.h" -#include "../returnvalues/HasReturnvaluesIF.h" -#include "../storagemanager/StorageAccessor.h" -#include "../storagemanager/storeAddress.h" -#include -#include - -using AccessorPair = std::pair; -using ConstAccessorPair = std::pair; - -/** - * @brief This class provides an interface for intermediate data storage. - * @details The Storage manager classes shall be used to store larger chunks of - * data in RAM for exchange between tasks. This interface expects the - * data to be stored in one consecutive block of memory, so tasks can - * write directly to the destination pointer. - * For interprocess communication, the stores must be locked during - * insertion and deletion. If the receiving storage identifier is - * passed token-like between tasks, a lock during read and write - * operations is not necessary. - * @author Bastian Baetz - * @date 18.09.2012 - */ -class StorageManagerIF : public HasReturnvaluesIF { -public: - static const uint8_t INTERFACE_ID = CLASS_ID::STORAGE_MANAGER_IF; //!< The unique ID for return codes for this interface. - static const ReturnValue_t DATA_TOO_LARGE = MAKE_RETURN_CODE(1); //!< This return code indicates that the data to be stored is too large for the store. - static const ReturnValue_t DATA_STORAGE_FULL = MAKE_RETURN_CODE(2); //!< This return code indicates that a data storage is full. - static const ReturnValue_t ILLEGAL_STORAGE_ID = MAKE_RETURN_CODE(3); //!< This return code indicates that data was requested with an illegal storage ID. - static const ReturnValue_t DATA_DOES_NOT_EXIST = MAKE_RETURN_CODE(4); //!< This return code indicates that the requested ID was valid, but no data is stored there. - static const ReturnValue_t ILLEGAL_ADDRESS = MAKE_RETURN_CODE(5); - static const ReturnValue_t POOL_TOO_LARGE = MAKE_RETURN_CODE(6); //!< Pool size too large on initialization. - - static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::OBSW; - static const Event GET_DATA_FAILED = MAKE_EVENT(0, SEVERITY::LOW); - static const Event STORE_DATA_FAILED = MAKE_EVENT(1, SEVERITY::LOW); - - static const uint32_t INVALID_ADDRESS = 0xFFFFFFFF; //!< Indicates an invalid (i.e unused) storage address. - /** - * @brief This is the empty virtual destructor as required for C++ interfaces. - */ - virtual ~StorageManagerIF() { - } - ; - /** - * @brief With addData, a free storage position is allocated and data - * stored there. - * @details During the allocation, the StorageManager is blocked. - * @param storageId A pointer to the storageId to retrieve. - * @param data The data to be stored in the StorageManager. - * @param size The amount of data to be stored. - * @return Returns @li RETURN_OK if data was added. - * @li RETURN_FAILED if data could not be added. - * storageId is unchanged then. - */ - virtual ReturnValue_t addData(store_address_t* storageId, - const uint8_t * data, size_t size, bool ignoreFault = false) = 0; - /** - * @brief With deleteData, the storageManager frees the memory region - * identified by packet_id. - * @param packet_id The identifier of the memory region to be freed. - * @return @li RETURN_OK on success. - * @li RETURN_FAILED if deletion did not work - * (e.g. an illegal packet_id was passed). - */ - virtual ReturnValue_t deleteData(store_address_t packet_id) = 0; - /** - * @brief Another deleteData which uses the pointer and size of the - * stored data to delete the content. - * @param buffer Pointer to the data. - * @param size Size of data to be stored. - * @param storeId Store id of the deleted element (optional) - * @return @li RETURN_OK on success. - * @li failure code if deletion did not work - */ - virtual ReturnValue_t deleteData(uint8_t* buffer, size_t size, - store_address_t* storeId = nullptr) = 0; - - - /** - * @brief Access the data by supplying a store ID. - * @details - * A pair consisting of the retrieval result and an instance of a - * ConstStorageAccessor class is returned - * @param storeId - * @return Pair of return value and a ConstStorageAccessor instance - */ - virtual ConstAccessorPair getData(store_address_t storeId) = 0; - - /** - * @brief Access the data by supplying a store ID and a helper - * instance - * @param storeId - * @param constAccessor Wrapper function to access store data. - * @return - */ - virtual ReturnValue_t getData(store_address_t storeId, - ConstStorageAccessor& constAccessor) = 0; - - - /** - * @brief getData returns an address to data and the size of the data - * for a given packet_id. - * @param packet_id The id of the data to be returned - * @param packet_ptr The passed pointer address is set to the the memory - * position - * @param size The exact size of the stored data is returned here. - * @return @li RETURN_OK on success. - * @li RETURN_FAILED if fetching data did not work - * (e.g. an illegal packet_id was passed). - */ - virtual ReturnValue_t getData(store_address_t packet_id, - const uint8_t** packet_ptr, size_t* size) = 0; - - - /** - * Modify data by supplying a store ID - * @param storeId - * @return Pair of return value and StorageAccessor helper - */ - virtual AccessorPair modifyData(store_address_t storeId) = 0; - - /** - * Modify data by supplying a store ID and a StorageAccessor helper instance. - * @param storeId - * @param accessor Helper class to access the modifiable data. - * @return - */ - virtual ReturnValue_t modifyData(store_address_t storeId, - StorageAccessor& accessor) = 0; - - /** - * Get pointer and size of modifiable data by supplying the storeId - * @param packet_id - * @param packet_ptr [out] Pointer to pointer of data to set - * @param size [out] Pointer to size to set - * @return - */ - virtual ReturnValue_t modifyData(store_address_t packet_id, - uint8_t** packet_ptr, size_t* size) = 0; - /** - * This method reserves an element of \c size. - * - * It returns the packet id of this element as well as a direct pointer to the - * data of the element. It must be assured that exactly \c size data is - * written to p_data! - * @param storageId A pointer to the storageId to retrieve. - * @param size The size of the space to be reserved. - * @param p_data A pointer to the element data is returned here. - * @return Returns @li RETURN_OK if data was added. - * @li RETURN_FAILED if data could not be added. - * storageId is unchanged then. - */ - virtual ReturnValue_t getFreeElement(store_address_t* storageId, - const size_t size, uint8_t** p_data, bool ignoreFault = false ) = 0; - - /** - * Clears the whole store. - * Use with care! - */ - virtual void clearStore() = 0; -}; - -#endif /* STORAGEMANAGERIF_H_ */ +#ifndef STORAGEMANAGERIF_H_H +#define STORAGEMANAGERIF_H_H + +#include "../events/Event.h" +#include "../returnvalues/HasReturnvaluesIF.h" +#include "../storagemanager/StorageAccessor.h" +#include "../storagemanager/storeAddress.h" +#include +#include + +using AccessorPair = std::pair; +using ConstAccessorPair = std::pair; + +/** + * @brief This class provides an interface for intermediate data storage. + * @details The Storage manager classes shall be used to store larger chunks of + * data in RAM for exchange between tasks. This interface expects the + * data to be stored in one consecutive block of memory, so tasks can + * write directly to the destination pointer. + * For interprocess communication, the stores must be locked during + * insertion and deletion. If the receiving storage identifier is + * passed token-like between tasks, a lock during read and write + * operations is not necessary. + * @author Bastian Baetz + * @date 18.09.2012 + */ +class StorageManagerIF : public HasReturnvaluesIF { +public: + static const uint8_t INTERFACE_ID = CLASS_ID::STORAGE_MANAGER_IF; //!< The unique ID for return codes for this interface. + static const ReturnValue_t DATA_TOO_LARGE = MAKE_RETURN_CODE(1); //!< This return code indicates that the data to be stored is too large for the store. + static const ReturnValue_t DATA_STORAGE_FULL = MAKE_RETURN_CODE(2); //!< This return code indicates that a data storage is full. + static const ReturnValue_t ILLEGAL_STORAGE_ID = MAKE_RETURN_CODE(3); //!< This return code indicates that data was requested with an illegal storage ID. + static const ReturnValue_t DATA_DOES_NOT_EXIST = MAKE_RETURN_CODE(4); //!< This return code indicates that the requested ID was valid, but no data is stored there. + static const ReturnValue_t ILLEGAL_ADDRESS = MAKE_RETURN_CODE(5); + static const ReturnValue_t POOL_TOO_LARGE = MAKE_RETURN_CODE(6); //!< Pool size too large on initialization. + + static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::OBSW; + static const Event GET_DATA_FAILED = MAKE_EVENT(0, SEVERITY::LOW); + static const Event STORE_DATA_FAILED = MAKE_EVENT(1, SEVERITY::LOW); + + static const uint32_t INVALID_ADDRESS = 0xFFFFFFFF; //!< Indicates an invalid (i.e unused) storage address. + /** + * @brief This is the empty virtual destructor as required for C++ interfaces. + */ + virtual ~StorageManagerIF() { + } + ; + /** + * @brief With addData, a free storage position is allocated and data + * stored there. + * @details During the allocation, the StorageManager is blocked. + * @param storageId A pointer to the storageId to retrieve. + * @param data The data to be stored in the StorageManager. + * @param size The amount of data to be stored. + * @return Returns @li RETURN_OK if data was added. + * @li RETURN_FAILED if data could not be added. + * storageId is unchanged then. + */ + virtual ReturnValue_t addData(store_address_t* storageId, + const uint8_t * data, size_t size, bool ignoreFault = false) = 0; + /** + * @brief With deleteData, the storageManager frees the memory region + * identified by packet_id. + * @param packet_id The identifier of the memory region to be freed. + * @return @li RETURN_OK on success. + * @li RETURN_FAILED if deletion did not work + * (e.g. an illegal packet_id was passed). + */ + virtual ReturnValue_t deleteData(store_address_t packet_id) = 0; + /** + * @brief Another deleteData which uses the pointer and size of the + * stored data to delete the content. + * @param buffer Pointer to the data. + * @param size Size of data to be stored. + * @param storeId Store id of the deleted element (optional) + * @return @li RETURN_OK on success. + * @li failure code if deletion did not work + */ + virtual ReturnValue_t deleteData(uint8_t* buffer, size_t size, + store_address_t* storeId = nullptr) = 0; + + + /** + * @brief Access the data by supplying a store ID. + * @details + * A pair consisting of the retrieval result and an instance of a + * ConstStorageAccessor class is returned + * @param storeId + * @return Pair of return value and a ConstStorageAccessor instance + */ + virtual ConstAccessorPair getData(store_address_t storeId) = 0; + + /** + * @brief Access the data by supplying a store ID and a helper + * instance + * @param storeId + * @param constAccessor Wrapper function to access store data. + * @return + */ + virtual ReturnValue_t getData(store_address_t storeId, + ConstStorageAccessor& constAccessor) = 0; + + + /** + * @brief getData returns an address to data and the size of the data + * for a given packet_id. + * @param packet_id The id of the data to be returned + * @param packet_ptr The passed pointer address is set to the the memory + * position + * @param size The exact size of the stored data is returned here. + * @return @li RETURN_OK on success. + * @li RETURN_FAILED if fetching data did not work + * (e.g. an illegal packet_id was passed). + */ + virtual ReturnValue_t getData(store_address_t packet_id, + const uint8_t** packet_ptr, size_t* size) = 0; + + + /** + * Modify data by supplying a store ID + * @param storeId + * @return Pair of return value and StorageAccessor helper + */ + virtual AccessorPair modifyData(store_address_t storeId) = 0; + + /** + * Modify data by supplying a store ID and a StorageAccessor helper instance. + * @param storeId + * @param accessor Helper class to access the modifiable data. + * @return + */ + virtual ReturnValue_t modifyData(store_address_t storeId, + StorageAccessor& accessor) = 0; + + /** + * Get pointer and size of modifiable data by supplying the storeId + * @param packet_id + * @param packet_ptr [out] Pointer to pointer of data to set + * @param size [out] Pointer to size to set + * @return + */ + virtual ReturnValue_t modifyData(store_address_t packet_id, + uint8_t** packet_ptr, size_t* size) = 0; + /** + * This method reserves an element of \c size. + * + * It returns the packet id of this element as well as a direct pointer to the + * data of the element. It must be assured that exactly \c size data is + * written to p_data! + * @param storageId A pointer to the storageId to retrieve. + * @param size The size of the space to be reserved. + * @param p_data A pointer to the element data is returned here. + * @return Returns @li RETURN_OK if data was added. + * @li RETURN_FAILED if data could not be added. + * storageId is unchanged then. + */ + virtual ReturnValue_t getFreeElement(store_address_t* storageId, + const size_t size, uint8_t** p_data, bool ignoreFault = false ) = 0; + + /** + * Clears the whole store. + * Use with care! + */ + virtual void clearStore() = 0; +}; + +#endif /* STORAGEMANAGERIF_H_ */ From 1ff85c88b2e05749050aabea2dcb91ed544f9ab3 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 29 Sep 2020 14:42:48 +0200 Subject: [PATCH 069/101] store accessor small changes --- storagemanager/ConstStorageAccessor.cpp | 5 +++-- storagemanager/ConstStorageAccessor.h | 8 ++++---- storagemanager/LocalPool.h | 6 +++--- storagemanager/LocalPool.tpp | 8 ++++---- storagemanager/PoolManager.h | 19 ++++++++++++------- storagemanager/PoolManager.tpp | 4 ++-- storagemanager/StorageAccessor.cpp | 4 ++-- storagemanager/StorageAccessor.h | 8 ++++---- storagemanager/StorageManagerIF.h | 12 +++++++----- 9 files changed, 41 insertions(+), 33 deletions(-) diff --git a/storagemanager/ConstStorageAccessor.cpp b/storagemanager/ConstStorageAccessor.cpp index 4ada7f80..71d732bf 100644 --- a/storagemanager/ConstStorageAccessor.cpp +++ b/storagemanager/ConstStorageAccessor.cpp @@ -1,6 +1,7 @@ +#include "ConstStorageAccessor.h" +#include "StorageManagerIF.h" + #include "../serviceinterface/ServiceInterfaceStream.h" -#include "../storagemanager/ConstStorageAccessor.h" -#include "../storagemanager/StorageManagerIF.h" #include "../globalfunctions/arrayprinter.h" ConstStorageAccessor::ConstStorageAccessor(store_address_t storeId): diff --git a/storagemanager/ConstStorageAccessor.h b/storagemanager/ConstStorageAccessor.h index 573892da..96d2dca2 100644 --- a/storagemanager/ConstStorageAccessor.h +++ b/storagemanager/ConstStorageAccessor.h @@ -1,7 +1,7 @@ -#ifndef FRAMEWORK_STORAGEMANAGER_CONSTSTORAGEACCESSOR_H_ -#define FRAMEWORK_STORAGEMANAGER_CONSTSTORAGEACCESSOR_H_ +#ifndef FSFW_STORAGEMANAGER_CONSTSTORAGEACCESSOR_H_ +#define FSFW_STORAGEMANAGER_CONSTSTORAGEACCESSOR_H_ -#include "../storagemanager/storeAddress.h" +#include "storeAddress.h" #include "../returnvalues/HasReturnvaluesIF.h" #include @@ -113,4 +113,4 @@ protected: }; -#endif /* FRAMEWORK_STORAGEMANAGER_CONSTSTORAGEACCESSOR_H_ */ +#endif /* FSFW_STORAGEMANAGER_CONSTSTORAGEACCESSOR_H_ */ diff --git a/storagemanager/LocalPool.h b/storagemanager/LocalPool.h index 8d300f8f..3a94c03d 100644 --- a/storagemanager/LocalPool.h +++ b/storagemanager/LocalPool.h @@ -1,5 +1,5 @@ -#ifndef FRAMEWORK_STORAGEMANAGER_LOCALPOOL_H_ -#define FRAMEWORK_STORAGEMANAGER_LOCALPOOL_H_ +#ifndef FSFW_STORAGEMANAGER_LOCALPOOL_H_ +#define FSFW_STORAGEMANAGER_LOCALPOOL_H_ #include "StorageManagerIF.h" #include "../objectmanager/SystemObject.h" @@ -187,4 +187,4 @@ private: #include "LocalPool.tpp" -#endif /* FRAMEWORK_STORAGEMANAGER_LOCALPOOL_H_ */ +#endif /* FSFW_STORAGEMANAGER_LOCALPOOL_H_ */ diff --git a/storagemanager/LocalPool.tpp b/storagemanager/LocalPool.tpp index 764bd7be..83c7a718 100644 --- a/storagemanager/LocalPool.tpp +++ b/storagemanager/LocalPool.tpp @@ -1,7 +1,7 @@ -#ifndef FRAMEWORK_STORAGEMANAGER_LOCALPOOL_TPP_ -#define FRAMEWORK_STORAGEMANAGER_LOCALPOOL_TPP_ +#ifndef FSFW_STORAGEMANAGER_LOCALPOOL_TPP_ +#define FSFW_STORAGEMANAGER_LOCALPOOL_TPP_ -#ifndef FRAMEWORK_STORAGEMANAGER_LOCALPOOL_H_ +#ifndef FSFW_STORAGEMANAGER_LOCALPOOL_H_ #error Include LocalPool.h before LocalPool.tpp! #endif @@ -301,4 +301,4 @@ inline ReturnValue_t LocalPool::initialize() { return RETURN_OK; } -#endif +#endif /* FSFW_STORAGEMANAGER_LOCALPOOL_TPP_ */ diff --git a/storagemanager/PoolManager.h b/storagemanager/PoolManager.h index ae719e87..84c88682 100644 --- a/storagemanager/PoolManager.h +++ b/storagemanager/PoolManager.h @@ -1,9 +1,9 @@ -#ifndef FRAMEWORK_STORAGEMANAGER_POOLMANAGER_H_ -#define FRAMEWORK_STORAGEMANAGER_POOLMANAGER_H_ +#ifndef FSFW_STORAGEMANAGER_POOLMANAGER_H_ +#define FSFW_STORAGEMANAGER_POOLMANAGER_H_ #include "LocalPool.h" +#include "StorageAccessor.h" #include "../ipc/MutexHelper.h" -#include "../storagemanager/StorageAccessor.h" /** @@ -20,11 +20,16 @@ public: const uint16_t element_sizes[NUMBER_OF_POOLS], const uint16_t n_elements[NUMBER_OF_POOLS]); - //! @brief In the PoolManager's destructor all allocated memory is freed. + /** + * @brief In the PoolManager's destructor all allocated memory + * is freed. + */ virtual ~PoolManager(); - //! @brief LocalPool overrides for thread-safety. Decorator function which - //! wraps LocalPool calls with a mutex protection. + /** + * @brief LocalPool overrides for thread-safety. Decorator function + * which wraps LocalPool calls with a mutex protection. + */ ReturnValue_t deleteData(store_address_t) override; ReturnValue_t deleteData(uint8_t* buffer, size_t size, store_address_t* storeId = nullptr) override; @@ -47,4 +52,4 @@ protected: #include "PoolManager.tpp" -#endif /* POOLMANAGER_H_ */ +#endif /* FSFW_STORAGEMANAGER_POOLMANAGER_H_ */ diff --git a/storagemanager/PoolManager.tpp b/storagemanager/PoolManager.tpp index d72346d3..ba7f63b7 100644 --- a/storagemanager/PoolManager.tpp +++ b/storagemanager/PoolManager.tpp @@ -1,7 +1,7 @@ #ifndef FRAMEWORK_STORAGEMANAGER_POOLMANAGER_TPP_ #define FRAMEWORK_STORAGEMANAGER_POOLMANAGER_TPP_ -#ifndef FRAMEWORK_STORAGEMANAGER_POOLMANAGER_H_ +#ifndef FSFW_STORAGEMANAGER_POOLMANAGER_H_ #error Include PoolManager.h before PoolManager.tpp! #endif @@ -48,4 +48,4 @@ inline ReturnValue_t PoolManager::deleteData(uint8_t* buffer, } -#endif +#endif /* FRAMEWORK_STORAGEMANAGER_POOLMANAGER_TPP_ */ diff --git a/storagemanager/StorageAccessor.cpp b/storagemanager/StorageAccessor.cpp index 60bd4130..9c2f936a 100644 --- a/storagemanager/StorageAccessor.cpp +++ b/storagemanager/StorageAccessor.cpp @@ -1,5 +1,5 @@ -#include "../storagemanager/StorageAccessor.h" -#include "../storagemanager/StorageManagerIF.h" +#include "StorageAccessor.h" +#include "StorageManagerIF.h" #include "../serviceinterface/ServiceInterfaceStream.h" StorageAccessor::StorageAccessor(store_address_t storeId): diff --git a/storagemanager/StorageAccessor.h b/storagemanager/StorageAccessor.h index a65427b8..5cf15d50 100644 --- a/storagemanager/StorageAccessor.h +++ b/storagemanager/StorageAccessor.h @@ -1,7 +1,7 @@ -#ifndef FRAMEWORK_STORAGEMANAGER_STORAGEACCESSOR_H_ -#define FRAMEWORK_STORAGEMANAGER_STORAGEACCESSOR_H_ +#ifndef FSFW_STORAGEMANAGER_STORAGEACCESSOR_H_ +#define FSFW_STORAGEMANAGER_STORAGEACCESSOR_H_ -#include "../storagemanager/ConstStorageAccessor.h" +#include "ConstStorageAccessor.h" class StorageManagerIF; @@ -42,4 +42,4 @@ private: void assignConstPointer(); }; -#endif /* TEST_PROTOTYPES_STORAGEACCESSOR_H_ */ +#endif /* FSFW_STORAGEMANAGER_STORAGEACCESSOR_H_ */ diff --git a/storagemanager/StorageManagerIF.h b/storagemanager/StorageManagerIF.h index 2229cdf8..834e7563 100644 --- a/storagemanager/StorageManagerIF.h +++ b/storagemanager/StorageManagerIF.h @@ -1,10 +1,12 @@ -#ifndef STORAGEMANAGERIF_H_H -#define STORAGEMANAGERIF_H_H +#ifndef FSFW_STORAGEMANAGER_STORAGEMANAGERIF_H_ +#define FSFW_STORAGEMANAGER_STORAGEMANAGERIF_H_ + +#include "StorageAccessor.h" +#include "storeAddress.h" #include "../events/Event.h" #include "../returnvalues/HasReturnvaluesIF.h" -#include "../storagemanager/StorageAccessor.h" -#include "../storagemanager/storeAddress.h" + #include #include @@ -164,4 +166,4 @@ public: virtual void clearStore() = 0; }; -#endif /* STORAGEMANAGERIF_H_ */ +#endif /* FSFW_STORAGEMANAGER_STORAGEMANAGERIF_H_ */ From bed4e7affa0b0a832f877768b18a57a463a89b0a Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 29 Sep 2020 14:43:23 +0200 Subject: [PATCH 070/101] nullptr replacement --- storagemanager/LocalPool.tpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storagemanager/LocalPool.tpp b/storagemanager/LocalPool.tpp index 83c7a718..7a6c5c9c 100644 --- a/storagemanager/LocalPool.tpp +++ b/storagemanager/LocalPool.tpp @@ -171,7 +171,7 @@ inline ReturnValue_t LocalPool::getData(store_address_t storeId template inline ReturnValue_t LocalPool::getData( store_address_t packet_id, const uint8_t** packet_ptr, size_t* size) { - uint8_t* tempData = NULL; + uint8_t* tempData = nullptr; ReturnValue_t status = modifyData(packet_id, &tempData, size); *packet_ptr = tempData; return status; From 622c7a5a0d5db90cf27a8b06a21888dd3ffd0eb8 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 29 Sep 2020 14:45:23 +0200 Subject: [PATCH 071/101] debug output removed --- storagemanager/ConstStorageAccessor.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/storagemanager/ConstStorageAccessor.cpp b/storagemanager/ConstStorageAccessor.cpp index 71d732bf..842f1ce8 100644 --- a/storagemanager/ConstStorageAccessor.cpp +++ b/storagemanager/ConstStorageAccessor.cpp @@ -15,7 +15,6 @@ ConstStorageAccessor::ConstStorageAccessor(store_address_t storeId, ConstStorageAccessor::~ConstStorageAccessor() { if(deleteData and store != nullptr) { - sif::debug << "deleting store data" << std::endl; store->deleteData(storeId); } } @@ -59,7 +58,8 @@ ReturnValue_t ConstStorageAccessor::getDataCopy(uint8_t *pointer, return HasReturnvaluesIF::RETURN_FAILED; } if(size_ > maxSize) { - sif::error << "StorageAccessor: Supplied buffer not large enough" << std::endl; + sif::error << "StorageAccessor: Supplied buffer not large enough" + << std::endl; return HasReturnvaluesIF::RETURN_FAILED; } std::copy(constDataPointer, constDataPointer + size_, pointer); From a58e47623f7bfec389da6d05d35fe1e9831cb462 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 29 Sep 2020 14:50:16 +0200 Subject: [PATCH 072/101] update --- storagemanager/LocalPool.tpp | 7 ++++--- storagemanager/PoolManager.h | 3 ++- storagemanager/PoolManager.tpp | 11 ++++++++--- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/storagemanager/LocalPool.tpp b/storagemanager/LocalPool.tpp index 7a6c5c9c..5e61efe4 100644 --- a/storagemanager/LocalPool.tpp +++ b/storagemanager/LocalPool.tpp @@ -125,9 +125,10 @@ inline LocalPool::~LocalPool(void) { } } -template inline -ReturnValue_t LocalPool::addData(store_address_t* storageId, - const uint8_t* data, size_t size, bool ignoreFault) { +template +inline ReturnValue_t LocalPool::addData( + store_address_t* storageId, const uint8_t* data, size_t size, + bool ignoreFault) { ReturnValue_t status = reserveSpace(size, storageId, ignoreFault); if (status == RETURN_OK) { write(*storageId, data, size); diff --git a/storagemanager/PoolManager.h b/storagemanager/PoolManager.h index 84c88682..8cc6c065 100644 --- a/storagemanager/PoolManager.h +++ b/storagemanager/PoolManager.h @@ -34,9 +34,10 @@ public: ReturnValue_t deleteData(uint8_t* buffer, size_t size, store_address_t* storeId = nullptr) override; + void setMutexTimeout(uint32_t mutexTimeoutMs); protected: //! Default mutex timeout value to prevent permanent blocking. - static constexpr uint32_t mutexTimeout = 50; + uint32_t mutexTimeoutMs = 20; ReturnValue_t reserveSpace(const uint32_t size, store_address_t* address, bool ignoreFault) override; diff --git a/storagemanager/PoolManager.tpp b/storagemanager/PoolManager.tpp index ba7f63b7..2be44ece 100644 --- a/storagemanager/PoolManager.tpp +++ b/storagemanager/PoolManager.tpp @@ -21,7 +21,7 @@ inline PoolManager::~PoolManager(void) { template inline ReturnValue_t PoolManager::reserveSpace( const uint32_t size, store_address_t* address, bool ignoreFault) { - MutexHelper mutexHelper(mutex,MutexIF::BLOCKING); + MutexHelper mutexHelper(mutex,MutexIF::WAITING, mutexTimeoutMs); ReturnValue_t status = LocalPool::reserveSpace(size, address,ignoreFault); return status; @@ -33,7 +33,7 @@ inline ReturnValue_t PoolManager::deleteData( // debug << "PoolManager( " << translateObject(getObjectId()) << // " )::deleteData from store " << packet_id.pool_index << // ". id is "<< packet_id.packet_index << std::endl; - MutexHelper mutexHelper(mutex,MutexIF::BLOCKING); + MutexHelper mutexHelper(mutex,MutexIF::WAITING, mutexTimeoutMs); ReturnValue_t status = LocalPool::deleteData(packet_id); return status; } @@ -41,11 +41,16 @@ inline ReturnValue_t PoolManager::deleteData( template inline ReturnValue_t PoolManager::deleteData(uint8_t* buffer, size_t size, store_address_t* storeId) { - MutexHelper mutexHelper(mutex,MutexIF::BLOCKING); + MutexHelper mutexHelper(mutex,MutexIF::WAITING, mutexTimeoutMs); ReturnValue_t status = LocalPool::deleteData(buffer, size, storeId); return status; } +template +inline void PoolManager::setMutexTimeout( + uint32_t mutexTimeoutMs) { + this->mutexTimeout = mutexTimeoutMs; +} #endif /* FRAMEWORK_STORAGEMANAGER_POOLMANAGER_TPP_ */ From 1ed1b7ea06fca6199ea5957e0b91affb4dfce47f Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 29 Sep 2020 14:51:08 +0200 Subject: [PATCH 073/101] include guard fix --- storagemanager/storeAddress.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/storagemanager/storeAddress.h b/storagemanager/storeAddress.h index 5dd785a3..044c0790 100644 --- a/storagemanager/storeAddress.h +++ b/storagemanager/storeAddress.h @@ -1,5 +1,6 @@ -#ifndef FRAMEWORK_STORAGEMANAGER_STOREADDRESS_H_ -#define FRAMEWORK_STORAGEMANAGER_STOREADDRESS_H_ +#ifndef FSFW_STORAGEMANAGER_STOREADDRESS_H_ +#define FSFW_STORAGEMANAGER_STOREADDRESS_H_ + #include /** @@ -51,4 +52,4 @@ union store_address_t { } }; -#endif /* FRAMEWORK_STORAGEMANAGER_STOREADDRESS_H_ */ +#endif /* FSFW_STORAGEMANAGER_STOREADDRESS_H_ */ From 352ce13fb391d13b3b4ccfd94437e9b3a189bc03 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 29 Sep 2020 14:55:17 +0200 Subject: [PATCH 074/101] removed line break --- ipc/messageQueueDefinitions.h | 1 - 1 file changed, 1 deletion(-) diff --git a/ipc/messageQueueDefinitions.h b/ipc/messageQueueDefinitions.h index b4f861b8..d250da8a 100644 --- a/ipc/messageQueueDefinitions.h +++ b/ipc/messageQueueDefinitions.h @@ -15,5 +15,4 @@ */ using MessageQueueId_t = uint32_t; - #endif /* FSFW_IPC_MESSAGEQUEUEDEFINITIONS_H_ */ From 6a5268f5b0439ed1b368c311dd45b4e2fb7012d9 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 29 Sep 2020 15:05:18 +0200 Subject: [PATCH 075/101] typo fix --- memory/AcceptsMemoryMessagesIF.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/memory/AcceptsMemoryMessagesIF.h b/memory/AcceptsMemoryMessagesIF.h index cf8aa5ec..7491f47d 100644 --- a/memory/AcceptsMemoryMessagesIF.h +++ b/memory/AcceptsMemoryMessagesIF.h @@ -11,4 +11,4 @@ public: }; -#endif /* AFSFW_MEMORY_ACCEPTSMEMORYMESSAGESIF_H_ */ +#endif /* FSFW_MEMORY_ACCEPTSMEMORYMESSAGESIF_H_ */ From a71528551ae4f821d029994d13000942e592a215 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 29 Sep 2020 15:10:08 +0200 Subject: [PATCH 076/101] include added --- tmtcservices/PusVerificationReport.h | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/tmtcservices/PusVerificationReport.h b/tmtcservices/PusVerificationReport.h index b4739577..9dce95ac 100644 --- a/tmtcservices/PusVerificationReport.h +++ b/tmtcservices/PusVerificationReport.h @@ -1,9 +1,11 @@ -#ifndef PUSVERIFICATIONREPORT_H_ -#define PUSVERIFICATIONREPORT_H_ +#ifndef FSFW_TMTCSERVICES_PUSVERIFICATIONREPORT_H_ +#define FSFW_TMTCSERVICES_PUSVERIFICATIONREPORT_H_ + +#include "VerificationCodes.h" #include "../ipc/MessageQueueMessage.h" #include "../tmtcpacket/pus/TcPacketBase.h" -#include "VerificationCodes.h" +#include "../returnvalues/HasReturnvaluesIF.h" class PusVerificationMessage: public MessageQueueMessage { private: @@ -30,7 +32,7 @@ private: public: static const uint8_t VERIFICATION_MIN_SIZE = 6; PusVerificationMessage(); -// PusVerificationMessage( uint8_t set_report_id, TcPacketBase* current_packet, ReturnValue_t set_error_code = 0, uint8_t set_step = 0, uint32_t parameter1 = 0, uint32_t parameter2 = 0 ); + PusVerificationMessage(uint8_t set_report_id, uint8_t ackFlags, uint16_t tcPacketId, uint16_t tcSequenceControl, ReturnValue_t set_error_code = 0, uint8_t set_step = 0, @@ -74,4 +76,4 @@ public: uint8_t* getReport(); }; -#endif /* PUSVERIFICATIONREPORT_H_ */ +#endif /* FSFW_TMTCSERVICES_PUSVERIFICATIONREPORT_H_ */ From e71020d631c6875427aa590ed7c2e68a77b50af1 Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Tue, 29 Sep 2020 15:24:29 +0200 Subject: [PATCH 077/101] Removed comments and added include --- tmtcservices/PusVerificationReport.cpp | 25 ------------------------- tmtcservices/PusVerificationReport.h | 2 ++ 2 files changed, 2 insertions(+), 25 deletions(-) diff --git a/tmtcservices/PusVerificationReport.cpp b/tmtcservices/PusVerificationReport.cpp index b047576b..bfad9ec5 100644 --- a/tmtcservices/PusVerificationReport.cpp +++ b/tmtcservices/PusVerificationReport.cpp @@ -4,31 +4,6 @@ PusVerificationMessage::PusVerificationMessage() { } -//PusVerificationMessage::PusVerificationMessage(uint8_t set_report_id, -// TcPacketBase* current_packet, ReturnValue_t set_error_code, -// uint8_t set_step, uint32_t parameter1, uint32_t parameter2) { -// uint8_t ackFlags = current_packet->getAcknowledgeFlags(); -// uint16_t tcPacketId = current_packet->getPacketId(); -// uint16_t tcSequenceControl = current_packet->getPacketSequenceControl(); -// uint8_t* data = this->getBuffer(); -// data[messageSize] = set_report_id; -// messageSize += sizeof(set_report_id); -// data[messageSize] = ackFlags; -// messageSize += sizeof(ackFlags); -// memcpy(&data[messageSize], &tcPacketId, sizeof(tcPacketId)); -// messageSize += sizeof(tcPacketId); -// memcpy(&data[messageSize], &tcSequenceControl, sizeof(tcSequenceControl)); -// messageSize += sizeof(tcSequenceControl); -// data[messageSize] = set_step; -// messageSize += sizeof(set_step); -// memcpy(&data[messageSize], &set_error_code, sizeof(set_error_code)); -// messageSize += sizeof(set_error_code); -// memcpy(&data[messageSize], ¶meter1, sizeof(parameter1)); -// messageSize += sizeof(parameter1); -// memcpy(&data[messageSize], ¶meter2, sizeof(parameter2)); -// messageSize += sizeof(parameter2); -//} - PusVerificationMessage::PusVerificationMessage(uint8_t set_report_id, uint8_t ackFlags, uint16_t tcPacketId, uint16_t tcSequenceControl, ReturnValue_t set_error_code, uint8_t set_step, uint32_t parameter1, diff --git a/tmtcservices/PusVerificationReport.h b/tmtcservices/PusVerificationReport.h index 9dce95ac..88954cfd 100644 --- a/tmtcservices/PusVerificationReport.h +++ b/tmtcservices/PusVerificationReport.h @@ -7,6 +7,8 @@ #include "../tmtcpacket/pus/TcPacketBase.h" #include "../returnvalues/HasReturnvaluesIF.h" +#include + class PusVerificationMessage: public MessageQueueMessage { private: struct verifciationMessageContent { From 1bdccedabe963f93d14fe58ae162bccc7f26360b Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Tue, 29 Sep 2020 15:39:24 +0200 Subject: [PATCH 078/101] Fixes #86 --- pus/CService200ModeCommanding.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/pus/CService200ModeCommanding.cpp b/pus/CService200ModeCommanding.cpp index 32f7e5a7..c63b47a6 100644 --- a/pus/CService200ModeCommanding.cpp +++ b/pus/CService200ModeCommanding.cpp @@ -107,13 +107,23 @@ ReturnValue_t CService200ModeCommanding::prepareWrongModeReply( const CommandMessage *reply, object_id_t objectId) { ModePacket wrongModeReply(objectId, ModeMessage::getMode(reply), ModeMessage::getSubmode(reply)); - return sendTmPacket(Subservice::REPLY_WRONG_MODE_REPLY, &wrongModeReply); + ReturnValue_t result = sendTmPacket(Subservice::REPLY_WRONG_MODE_REPLY, &wrongModeReply); + if(result == RETURN_OK){ + // We want to produce an error here in any case because the mode was not correct + return RETURN_FAILED; + } + return result; } ReturnValue_t CService200ModeCommanding::prepareCantReachModeReply( const CommandMessage *reply, object_id_t objectId) { CantReachModePacket cantReachModePacket(objectId, ModeMessage::getCantReachModeReason(reply)); - return sendTmPacket(Subservice::REPLY_CANT_REACH_MODE, + ReturnValue_t result = sendTmPacket(Subservice::REPLY_CANT_REACH_MODE, &cantReachModePacket); + if(result == RETURN_OK){ + // We want to produce an error here in any case because the mode was not reached + return RETURN_FAILED; + } + return result; } From 17d5de15c990be42ad98da412059d7588ded15bd Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 29 Sep 2020 16:10:35 +0200 Subject: [PATCH 079/101] slight changes ,size t replacement --- container/ArrayList.h | 218 +++++++++++++++++++++--------------------- 1 file changed, 107 insertions(+), 111 deletions(-) diff --git a/container/ArrayList.h b/container/ArrayList.h index 19454777..f347da8e 100644 --- a/container/ArrayList.h +++ b/container/ArrayList.h @@ -1,15 +1,15 @@ -#ifndef ARRAYLIST_H_ -#define ARRAYLIST_H_ +#ifndef FSFW_CONTAINER_ARRAYLIST_H_ +#define FSFW_CONTAINER_ARRAYLIST_H_ #include "../returnvalues/HasReturnvaluesIF.h" #include "../serialize/SerializeAdapter.h" #include "../serialize/SerializeIF.h" /** - * A List that stores its values in an array. - * - * The backend is an array that can be allocated by the class itself or supplied via ctor. - * + * @brief A List that stores its values in an array. + * @details + * The underlying storage is an array that can be allocated by the class + * itself or supplied via ctor. * * @ingroup container */ @@ -21,94 +21,8 @@ public: static const ReturnValue_t FULL = MAKE_RETURN_CODE(0x01); /** - * An Iterator to go trough an ArrayList - * - * It stores a pointer to an element and increments the - * pointer when incremented itself. - */ - class Iterator { - public: - /** - * Empty ctor, points to NULL - */ - Iterator() : - value(0) { - - } - - /** - * Initializes the Iterator to point to an element - * - * @param initialize - */ - Iterator(T *initialize) { - value = initialize; - } - - /** - * The current element the iterator points to - */ - T *value; - - Iterator& operator++() { - value++; - return *this; - } - - Iterator operator++(int) { - Iterator tmp(*this); - operator++(); - return tmp; - } - - Iterator& operator--() { - value--; - return *this; - } - - Iterator operator--(int) { - Iterator tmp(*this); - operator--(); - return tmp; - } - - T& operator*(){ - return *value; - } - - const T& operator*() const{ - return *value; - } - - T *operator->(){ - return value; - } - - const T *operator->() const{ - return value; - } - - //SHOULDDO this should be implemented as non-member - bool operator==(const typename ArrayList::Iterator& other) const{ - return (value == other.value); - } - - //SHOULDDO this should be implemented as non-member - bool operator!=(const typename ArrayList::Iterator& other) const { - return !(*this == other); - } - }; - - /** - * Number of Elements stored in this List - */ - count_t size; - - /** - * This is the allocating constructor; - * + * This is the allocating constructor. * It allocates an array of the specified size. - * * @param maxSize */ ArrayList(count_t maxSize) : @@ -119,7 +33,8 @@ public: /** * This is the non-allocating constructor * - * It expects a pointer to an array of a certain size and initializes itself to it. + * It expects a pointer to an array of a certain size and initializes + * itself to it. * * @param storage the array to use as backend * @param maxSize size of storage @@ -129,6 +44,20 @@ public: size(size), entries(storage), maxSize_(maxSize), allocated(false) { } + /** + * Copying is forbiden by declaring copy ctor and copy assignment deleted + * It is too ambigous in this case. + * (Allocate a new backend? Use the same? What to do in an modifying call?) + */ + ArrayList(const ArrayList& other) = delete; + const ArrayList& operator=(const ArrayList& other) = delete; + + /** + * Number of Elements stored in this List + */ + count_t size; + + /** * Destructor, if the allocating constructor was used, it deletes the array. */ @@ -138,6 +67,85 @@ public: } } + /** + * An Iterator to go trough an ArrayList + * + * It stores a pointer to an element and increments the + * pointer when incremented itself. + */ + class Iterator { + public: + /** + * Empty ctor, points to NULL + */ + Iterator(): value(0) {} + + /** + * Initializes the Iterator to point to an element + * + * @param initialize + */ + Iterator(T *initialize) { + value = initialize; + } + + /** + * The current element the iterator points to + */ + T *value; + + Iterator& operator++() { + value++; + return *this; + } + + Iterator operator++(int) { + Iterator tmp(*this); + operator++(); + return tmp; + } + + Iterator& operator--() { + value--; + return *this; + } + + Iterator operator--(int) { + Iterator tmp(*this); + operator--(); + return tmp; + } + + T& operator*() { + return *value; + } + + const T& operator*() const { + return *value; + } + + T *operator->() { + return value; + } + + const T *operator->() const { + return value; + } + + + //SHOULDDO this should be implemented as non-member + bool operator==(const typename + ArrayList::Iterator& other) const { + return (value == other.value); + } + + //SHOULDDO this should be implemented as non-member + bool operator!=(const typename + ArrayList::Iterator& other) const { + return !(*this == other); + } + }; + /** * Iterator pointing to the first stored elmement * @@ -191,7 +199,7 @@ public: * * @return maximum number of elements */ - uint32_t maxSize() const { + size_t maxSize() const { return this->maxSize_; } @@ -226,19 +234,7 @@ public: count_t remaining() { return (maxSize_ - size); } -private: - /** - * This is the copy constructor - * - * It is private, as copying is too ambigous in this case. (Allocate a new backend? Use the same? - * What to do in an modifying call?) - * - * @param other - */ - ArrayList(const ArrayList& other) : - size(other.size), entries(other.entries), maxSize_(other.maxSize_), allocated( - false) { - } + protected: /** * pointer to the array in which the entries are stored @@ -247,12 +243,12 @@ protected: /** * remembering the maximum size */ - uint32_t maxSize_; + size_t maxSize_; /** * true if the array was allocated and needs to be deleted in the destructor. */ bool allocated; - }; -#endif /* ARRAYLIST_H_ */ + +#endif /* FSFW_CONTAINER_ARRAYLIST_H_ */ From 4eef7bfc0133f56021914028818107cbe0e41b64 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 29 Sep 2020 16:12:43 +0200 Subject: [PATCH 080/101] changes taken over --- container/ArrayList.h | 144 +++++++++++++++++++++--------------------- 1 file changed, 72 insertions(+), 72 deletions(-) diff --git a/container/ArrayList.h b/container/ArrayList.h index f347da8e..426e02b3 100644 --- a/container/ArrayList.h +++ b/container/ArrayList.h @@ -26,7 +26,7 @@ public: * @param maxSize */ ArrayList(count_t maxSize) : - size(0), maxSize_(maxSize), allocated(true) { + size(0), maxSize_(maxSize), allocated(true) { entries = new T[maxSize]; } @@ -41,14 +41,14 @@ public: * @param size size of data already present in storage */ ArrayList(T *storage, count_t maxSize, count_t size = 0) : - size(size), entries(storage), maxSize_(maxSize), allocated(false) { + size(size), entries(storage), maxSize_(maxSize), allocated(false) { } - /** - * Copying is forbiden by declaring copy ctor and copy assignment deleted - * It is too ambigous in this case. - * (Allocate a new backend? Use the same? What to do in an modifying call?) - */ + /** + * Copying is forbiden by declaring copy ctor and copy assignment deleted + * It is too ambigous in this case. + * (Allocate a new backend? Use the same? What to do in an modifying call?) + */ ArrayList(const ArrayList& other) = delete; const ArrayList& operator=(const ArrayList& other) = delete; @@ -67,84 +67,84 @@ public: } } - /** - * An Iterator to go trough an ArrayList - * - * It stores a pointer to an element and increments the - * pointer when incremented itself. - */ - class Iterator { - public: - /** - * Empty ctor, points to NULL - */ - Iterator(): value(0) {} + /** + * An Iterator to go trough an ArrayList + * + * It stores a pointer to an element and increments the + * pointer when incremented itself. + */ + class Iterator { + public: + /** + * Empty ctor, points to NULL + */ + Iterator(): value(0) {} - /** - * Initializes the Iterator to point to an element - * - * @param initialize - */ - Iterator(T *initialize) { - value = initialize; - } + /** + * Initializes the Iterator to point to an element + * + * @param initialize + */ + Iterator(T *initialize) { + value = initialize; + } - /** - * The current element the iterator points to - */ - T *value; + /** + * The current element the iterator points to + */ + T *value; - Iterator& operator++() { - value++; - return *this; - } + Iterator& operator++() { + value++; + return *this; + } - Iterator operator++(int) { - Iterator tmp(*this); - operator++(); - return tmp; - } + Iterator operator++(int) { + Iterator tmp(*this); + operator++(); + return tmp; + } - Iterator& operator--() { - value--; - return *this; - } + Iterator& operator--() { + value--; + return *this; + } - Iterator operator--(int) { - Iterator tmp(*this); - operator--(); - return tmp; - } + Iterator operator--(int) { + Iterator tmp(*this); + operator--(); + return tmp; + } - T& operator*() { - return *value; - } + T& operator*() { + return *value; + } - const T& operator*() const { - return *value; - } + const T& operator*() const { + return *value; + } - T *operator->() { - return value; - } + T *operator->() { + return value; + } - const T *operator->() const { - return value; - } + const T *operator->() const { + return value; + } - //SHOULDDO this should be implemented as non-member - bool operator==(const typename - ArrayList::Iterator& other) const { - return (value == other.value); - } + //SHOULDDO this should be implemented as non-member + bool operator==(const typename + ArrayList::Iterator& other) const { + return (value == other.value); + } - //SHOULDDO this should be implemented as non-member - bool operator!=(const typename - ArrayList::Iterator& other) const { - return !(*this == other); - } - }; + //SHOULDDO this should be implemented as non-member + bool operator!=(const typename + ArrayList::Iterator& other) const { + return !(*this == other); + } + }; /** * Iterator pointing to the first stored elmement From 4fce0377a951b1a2b27a128b09baf949f6b7415d Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 29 Sep 2020 17:28:02 +0200 Subject: [PATCH 081/101] missing include for linux --- osal/linux/MessageQueue.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/osal/linux/MessageQueue.cpp b/osal/linux/MessageQueue.cpp index e5c61cae..f2e5a5ec 100644 --- a/osal/linux/MessageQueue.cpp +++ b/osal/linux/MessageQueue.cpp @@ -1,14 +1,16 @@ -#include "../../serviceinterface/ServiceInterfaceStream.h" #include "MessageQueue.h" +#include "../../serviceinterface/ServiceInterfaceStream.h" +#include "../../objectmanager/ObjectManagerIF.h" #include - #include /* For O_* constants */ #include /* For mode constants */ #include #include + + MessageQueue::MessageQueue(uint32_t messageDepth, size_t maxMessageSize): id(MessageQueueIF::NO_QUEUE),lastPartner(MessageQueueIF::NO_QUEUE), defaultDestination(MessageQueueIF::NO_QUEUE) { From f73f798a4d606e2fe66d592494ad52e0ba4e50a3 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 29 Sep 2020 17:28:37 +0200 Subject: [PATCH 082/101] lines removed --- osal/linux/MessageQueue.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/osal/linux/MessageQueue.cpp b/osal/linux/MessageQueue.cpp index f2e5a5ec..cb5ffd04 100644 --- a/osal/linux/MessageQueue.cpp +++ b/osal/linux/MessageQueue.cpp @@ -9,8 +9,6 @@ #include - - MessageQueue::MessageQueue(uint32_t messageDepth, size_t maxMessageSize): id(MessageQueueIF::NO_QUEUE),lastPartner(MessageQueueIF::NO_QUEUE), defaultDestination(MessageQueueIF::NO_QUEUE) { From 303fcec9f656308ef4b50fb1da9f1dcbc2f13192 Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Tue, 29 Sep 2020 17:49:04 +0200 Subject: [PATCH 083/101] Added a missing include --- osal/linux/MessageQueue.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/osal/linux/MessageQueue.cpp b/osal/linux/MessageQueue.cpp index e5c61cae..76f66170 100644 --- a/osal/linux/MessageQueue.cpp +++ b/osal/linux/MessageQueue.cpp @@ -1,5 +1,6 @@ #include "../../serviceinterface/ServiceInterfaceStream.h" #include "MessageQueue.h" +#include "../../objectmanager/ObjectManagerIF.h" #include From 6c0bb23ed6f24e84a52a2b37c3bf082a39b0c43d Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 29 Sep 2020 17:51:16 +0200 Subject: [PATCH 084/101] non member bool operator --- container/ArrayList.h | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/container/ArrayList.h b/container/ArrayList.h index 426e02b3..6bd5c1d5 100644 --- a/container/ArrayList.h +++ b/container/ArrayList.h @@ -131,21 +131,18 @@ public: const T *operator->() const { return value; } - - - //SHOULDDO this should be implemented as non-member - bool operator==(const typename - ArrayList::Iterator& other) const { - return (value == other.value); - } - - //SHOULDDO this should be implemented as non-member - bool operator!=(const typename - ArrayList::Iterator& other) const { - return !(*this == other); - } }; + friend bool operator==(const ArrayList::Iterator& lhs, + const ArrayList::Iterator& rhs) { + return (lhs.value == rhs.value); + } + + friend bool operator!=(const ArrayList::Iterator& lhs, + const ArrayList::Iterator& rhs) { + return not (lhs.value == rhs.value); + } + /** * Iterator pointing to the first stored elmement * @@ -251,4 +248,6 @@ protected: bool allocated; }; + + #endif /* FSFW_CONTAINER_ARRAYLIST_H_ */ From 5fc583117d1291976281ec40e448376257a94ba8 Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Wed, 30 Sep 2020 10:55:34 +0200 Subject: [PATCH 085/101] Typo in FixedOrderedMultimap --- container/FixedOrderedMultimap.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/container/FixedOrderedMultimap.h b/container/FixedOrderedMultimap.h index c5fd2184..717575d7 100644 --- a/container/FixedOrderedMultimap.h +++ b/container/FixedOrderedMultimap.h @@ -98,7 +98,7 @@ public: } ReturnValue_t insert(std::pair pair) { - return insert(pair.fist, pair.second); + return insert(pair.first, pair.second); } ReturnValue_t exists(key_t key) const { From ecc4bdf11a2144f37e20631c17f3d58132499398 Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Wed, 30 Sep 2020 12:50:52 +0200 Subject: [PATCH 086/101] Added a compile time check for MAX_SIZE Compiler may warn if MAX_SIZE value overflows by itself but this checks gives a more verbose warning --- container/FixedArrayList.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/container/FixedArrayList.h b/container/FixedArrayList.h index 42b59177..505097c9 100644 --- a/container/FixedArrayList.h +++ b/container/FixedArrayList.h @@ -2,11 +2,13 @@ #define FIXEDARRAYLIST_H_ #include "ArrayList.h" +#include /** * \ingroup container */ -template +template class FixedArrayList: public ArrayList { + static_assert(MAX_SIZE <= (pow(2,sizeof(count_t)*8)-1), "count_t is not large enough to hold MAX_SIZE"); private: T data[MAX_SIZE]; public: From 8d8e918aeb299ceb1b1279a93a289c37419cf325 Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Wed, 30 Sep 2020 13:05:55 +0200 Subject: [PATCH 087/101] Fixed copying of FixedArrayList --- container/FixedArrayList.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/container/FixedArrayList.h b/container/FixedArrayList.h index 505097c9..e9e127cf 100644 --- a/container/FixedArrayList.h +++ b/container/FixedArrayList.h @@ -20,11 +20,13 @@ public: ArrayList(data, MAX_SIZE) { memcpy(this->data, other.data, sizeof(this->data)); this->entries = data; + this->size = other.size; } FixedArrayList& operator=(FixedArrayList other) { memcpy(this->data, other.data, sizeof(this->data)); this->entries = data; + this->size = other.size; return *this; } From aeeef53508627aa802d14ed9b45a93689171cac6 Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Wed, 30 Sep 2020 14:34:02 +0200 Subject: [PATCH 088/101] Added Documentation to placement factory --- container/PlacementFactory.h | 42 +++++++++++++++++++++++++++++++++--- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/container/PlacementFactory.h b/container/PlacementFactory.h index 05538478..529c7804 100644 --- a/container/PlacementFactory.h +++ b/container/PlacementFactory.h @@ -3,26 +3,62 @@ #include "../storagemanager/StorageManagerIF.h" #include - +/** + * The Placement Factory is used to create objects at runtime in a specific pool. + * In general this should be avoided and is should only be used if you know what you are doing. + * You are not allowed to use this container with a type that allocates memory internally like ArrayList. + * + * You have to check the returned pointer against nullptr! + * + * A backend of Type StorageManagerIF must be given as a place to store the new objects. + * Objects must be destroyed by the user with "destroy"! Otherwise the pool will not be cleared. + * + * + * + * The concept is based on the placement new operator. + * + * @warning Do not use with any Type that allocates memory internally! + * @ingroup container + */ class PlacementFactory { public: PlacementFactory(StorageManagerIF* backend) : dataBackend(backend) { } + + /*** + * Generates an object of type T in the backend storage. + * + * @warning Do not use with any Type that allocates memory internally! + * + * @tparam T Type of Object + * @param args Constructor Arguments to be passed + * @return A pointer to the new object or a nullptr in case of failure + */ template T* generate(Args&&... args) { store_address_t tempId; - uint8_t* pData = NULL; + uint8_t* pData = nullptr; ReturnValue_t result = dataBackend->getFreeElement(&tempId, sizeof(T), &pData); if (result != HasReturnvaluesIF::RETURN_OK) { - return NULL; + return nullptr; } T* temp = new (pData) T(std::forward(args)...); return temp; } + /*** + * Function to destroy the object allocated with generate and free space in backend. + * This must be called by the user. + * + * @param thisElement Element to be destroyed + * @return RETURN_OK if the element was destroyed, different errors on failure + */ template ReturnValue_t destroy(T* thisElement) { + if (thisElement == nullptr){ + return HasReturnvaluesIF::RETURN_FAILED; + } //Need to call destructor first, in case something was allocated by the object (shouldn't do that, however). thisElement->~T(); uint8_t* pointer = (uint8_t*) (thisElement); From 2f61bd0a0f5ac7f9252e9d18b60253fbf39e53f5 Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Wed, 30 Sep 2020 14:38:46 +0200 Subject: [PATCH 089/101] A few typos and more docu --- container/PlacementFactory.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/container/PlacementFactory.h b/container/PlacementFactory.h index 529c7804..a0aebb7d 100644 --- a/container/PlacementFactory.h +++ b/container/PlacementFactory.h @@ -5,16 +5,16 @@ #include /** * The Placement Factory is used to create objects at runtime in a specific pool. - * In general this should be avoided and is should only be used if you know what you are doing. + * In general, this should be avoided and it should only be used if you know what you are doing. * You are not allowed to use this container with a type that allocates memory internally like ArrayList. * - * You have to check the returned pointer against nullptr! + * Also, you have to check the returned pointer in generate against nullptr! * * A backend of Type StorageManagerIF must be given as a place to store the new objects. + * Therefore ThreadSafety is only provided by your StorageManager Implementation. + * * Objects must be destroyed by the user with "destroy"! Otherwise the pool will not be cleared. * - * - * * The concept is based on the placement new operator. * * @warning Do not use with any Type that allocates memory internally! From 823bae1a2a993af3ff700c0d7eb4709c8176d87d Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Wed, 30 Sep 2020 16:06:17 +0200 Subject: [PATCH 090/101] Added null pointer checks for FIFO Base --- container/FIFOBase.tpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/container/FIFOBase.tpp b/container/FIFOBase.tpp index d54b3f8f..763004b6 100644 --- a/container/FIFOBase.tpp +++ b/container/FIFOBase.tpp @@ -26,6 +26,9 @@ inline ReturnValue_t FIFOBase::retrieve(T* value) { if (empty()) { return EMPTY; } else { + if (value == nullptr){ + return HasReturnvaluesIF::RETURN_FAILED; + } *value = values[readIndex]; readIndex = next(readIndex); --currentSize; @@ -38,6 +41,9 @@ inline ReturnValue_t FIFOBase::peek(T* value) { if(empty()) { return EMPTY; } else { + if (value == nullptr){ + return HasReturnvaluesIF::RETURN_FAILED; + } *value = values[readIndex]; return HasReturnvaluesIF::RETURN_OK; } From ab9858b0c78fa6283b7218e7c9339444b91a5c39 Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Wed, 30 Sep 2020 16:15:48 +0200 Subject: [PATCH 091/101] Added comments --- container/FIFOBase.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/container/FIFOBase.h b/container/FIFOBase.h index b744706d..201d488d 100644 --- a/container/FIFOBase.h +++ b/container/FIFOBase.h @@ -19,24 +19,24 @@ public: /** * Insert value into FIFO * @param value - * @return + * @return RETURN_OK on success, FULL if full */ ReturnValue_t insert(T value); /** * Retrieve item from FIFO. This removes the item from the FIFO. - * @param value - * @return + * @param value Must point to a valid T + * @return RETURN_OK on success, EMPTY if empty and FAILED if nullptr check failed */ ReturnValue_t retrieve(T *value); /** * Retrieve item from FIFO without removing it from FIFO. - * @param value - * @return + * @param value Must point to a valid T + * @return RETURN_OK on success, EMPTY if empty and FAILED if nullptr check failed */ ReturnValue_t peek(T * value); /** * Remove item from FIFO. - * @return + * @return RETURN_OK on success, EMPTY if empty */ ReturnValue_t pop(); From fcabf93af33c61d989bf06555bf3a005e985ff7a Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Wed, 30 Sep 2020 16:27:18 +0200 Subject: [PATCH 092/101] Added a few comments --- container/FIFOBase.h | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/container/FIFOBase.h b/container/FIFOBase.h index 201d488d..edd66d37 100644 --- a/container/FIFOBase.h +++ b/container/FIFOBase.h @@ -40,11 +40,25 @@ public: */ ReturnValue_t pop(); + /*** + * Check if FIFO is empty + * @return True if empty, False if not + */ bool empty(); + /*** + * Check if FIFO is Full + * @return True if full, False if not + */ bool full(); + /*** + * Current used size (elements) used + * @return size_t in elements + */ size_t size(); - - + /*** + * Get maximal capacity of fifo + * @return size_t with max capacity of this fifo + */ size_t getMaxCapacity() const; protected: From a0098e8b17e42d43e64d7d9ef7a78f8cc66b137b Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Wed, 30 Sep 2020 18:57:30 +0200 Subject: [PATCH 093/101] non member comp operator for iterators --- container/FixedMap.h | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/container/FixedMap.h b/container/FixedMap.h index d1cc31ff..7a5220fa 100644 --- a/container/FixedMap.h +++ b/container/FixedMap.h @@ -7,14 +7,21 @@ #include /** + * @brief Map implementation for maps with a pre-defined size. + * @details + * Can be initialized with desired maximum size. + * Iterator is used to access pair and iterate through map entries. + * Complexity O(n). * @warning Iterators return a non-const key_t in the pair. * @warning A User is not allowed to change the key, otherwise the map is corrupted. * @ingroup container */ template class FixedMap: public SerializeIF { - static_assert (std::is_trivially_copyable::value or std::is_base_of::value, - "Types used in FixedMap must either be trivial copy-able or a derived Class from SerializeIF to be serialize-able"); + static_assert (std::is_trivially_copyable::value or + std::is_base_of::value, + "Types used in FixedMap must either be trivial copy-able or a " + "derived class from SerializeIF to be serialize-able"); public: static const uint8_t INTERFACE_ID = CLASS_ID::FIXED_MAP; static const ReturnValue_t KEY_ALREADY_EXISTS = MAKE_RETURN_CODE(0x01); @@ -54,6 +61,16 @@ public: } }; + friend bool operator==(const typename FixedMap::Iterator& lhs, + const typename FixedMap::Iterator& rhs) { + return (lhs.value == rhs.value); + } + + friend bool operator!=(const typename FixedMap::Iterator& lhs, + const typename FixedMap::Iterator& rhs) { + return not (lhs.value == rhs.value); + } + Iterator begin() const { return Iterator(&theMap[0]); } @@ -136,6 +153,24 @@ public: return HasReturnvaluesIF::RETURN_OK; } + bool empty() { + if(_size == 0) { + return true; + } + else { + return false; + } + } + + bool full() { + if(_size >= theMap.maxSize()) { + return true; + } + else { + return false; + } + } + void clear() { _size = 0; } From a14558ef1fd308ba23757916590af1376a663791 Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Wed, 30 Sep 2020 20:25:02 +0200 Subject: [PATCH 094/101] Removed old test files --- container/RingBufferTest.cpp.ignore | 79 ------ container/listTest.cpp.ignore | 365 ---------------------------- 2 files changed, 444 deletions(-) delete mode 100644 container/RingBufferTest.cpp.ignore delete mode 100644 container/listTest.cpp.ignore diff --git a/container/RingBufferTest.cpp.ignore b/container/RingBufferTest.cpp.ignore deleted file mode 100644 index d660e29c..00000000 --- a/container/RingBufferTest.cpp.ignore +++ /dev/null @@ -1,79 +0,0 @@ - -#include -#include "SimpleRingBuffer.h" - - -int main() { - using namespace std; - SimpleRingBuffer buffer(64, false); - uint8_t data[8] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'}; - ReturnValue_t result = buffer.writeData(data, 8); - if (result != HasReturnvaluesIF::RETURN_OK) { - cout << "writeData failed." << endl; - } - result = buffer.writeData(data, 8); - if (result != HasReturnvaluesIF::RETURN_OK) { - cout << "writeData failed." << endl; - } - uint8_t buffer2[47] = {0}; - for (uint8_t count = 0; count - -/* - -class Packet: public SinglyLinkedList { -public: - SinglyLinkedList::Element element1; - SinglyLinkedList::Element element2; - - Packet() { - this->start = &element1; - element1.next = &element2; - } -}; - -class Packet2: public SinglyLinkedList { -public: - SinglyLinkedList::Element element1; - SinglyLinkedList::Element, 2>> element2; - SinglyLinkedList::Element element3; - - Packet2() { - this->start = &element1; - element1.next = &element2; - element2.next = &element3; - } -}; - -class Packet3: public SinglyLinkedList { -public: - SinglyLinkedList::TypedElement element1; - SinglyLinkedList::TypedElement element2; - - Packet3() { - this->start = &element1; - element1.next = &element2; - } -}; - -void arrayList() { - puts("** Array List **"); - FixedArrayList list; - FixedArrayList list2; - - list.size = 2; - - list[0] = 0xcafecafe; - - list[1] = 0x12345678; - - uint8_t buffer[100]; - uint8_t *pointer = buffer; - uint32_t size = 0; - uint32_t maxSize = 100; - uint32_t i; - int32_t size2; - - printf("printsize: %i\n", list.getPrintSize()); - - list.print(&pointer, &size, 100, true); - - printf("buffer(%i):", size); - for (i = 0; i < size; ++i) { - printf("%02x", buffer[i]); - } - printf("\n"); - - pointer = buffer; - - size2 = size; - - printf("list2 read: %x\n", list2.read(&pointer, &size2, true)); - - printf("list2(%i):", list2.size); - for (ArrayList::Iterator iter = list2.begin(); - iter != list2.end(); iter++) { - printf("0x%04x ", *iter); - } - printf("\n"); - - HybridIterator hiter(list.begin(),list.end()); - - printf("hybrid1: 0x%04x\n", *(hiter++)); - printf("hybrid2: 0x%04x\n", *hiter); - -} - -void allocatingList() { - puts("** Allocating List **"); - ArrayList myList(3), myList2(2); - myList[0] = 0xab; - myList[1] = 0xcd; - myList.size = 2; - - uint8_t buffer[100]; - uint8_t *pointer = buffer; - uint32_t size = 0; - uint32_t maxSize = 100; - uint32_t i; - int32_t size2; - - myList.print(&pointer, &size, 100, true); - - pointer = buffer; - size2 = size; - - printf("Read %x\n", myList2.read(&pointer, &size2, true)); - - printf("%x,%x\n", myList2[0], myList2[1]); - -} - -void linkedList() { - puts("** Linked List **"); - uint8_t buffer[100]; - uint8_t *pointer = buffer; - uint32_t size = 0; - uint32_t maxSize = 100; - uint32_t i; - int32_t size2; - - Packet myPacket; - myPacket.element1.entry = 0x12345678; - myPacket.element2.entry = 0x9abcdef0; - - pointer = buffer; - size = 0; - ReturnValue_t result = myPacket.print(&pointer, &size, 100, true); - - printf("result %02x\n", result); - - printf("printsize: %i\n", myPacket.getPrintSize()); - - printf("buffer(%i):", size); - for (i = 0; i < size; ++i) { - printf("%02x", buffer[i]); - } - printf("\n"); - - Packet3 myPacket3; - - myPacket3.element1.entry = 0x12345678; - myPacket3.element2.entry = 0xabcdeff; - - SinglyLinkedList::TypedIterator titer(&myPacket3.element1); - - printf("0x%04x\n", *titer); - - HybridIterator hiter(&myPacket3.element1); - - printf("hybrid1: 0x%04x\n", *hiter); - hiter++; - printf("hybrid2: 0x%04x\n", *hiter); -} - -void complex() { - puts("** complex **"); - uint8_t buffer[100]; - uint8_t *pointer = buffer; - uint32_t size = 0; - uint32_t maxSize = 100; - uint32_t i; - int32_t size2 = size; - - Packet myPacket2; - - size2 = size; - pointer = buffer; - - myPacket2.read(&pointer, &size2, true); - - printf("packet: 0x%04x, 0x%04x\n", myPacket2.element1.entry, - myPacket2.element2.entry); - - buffer[0] = 0x12; - buffer[1] = 0x34; - buffer[2] = 0x56; - buffer[3] = 0x78; - buffer[4] = 0x2; - buffer[5] = 0x3; - buffer[6] = 0xab; - buffer[7] = 0xcd; - buffer[8] = 0xef; - buffer[9] = 0x2; - buffer[10] = 0x11; - buffer[11] = 0x22; - buffer[12] = 0xca; - buffer[13] = 0xfe; - buffer[14] = 0x5a; - buffer[15] = 0xfe; - - pointer = buffer; - size2 = 23; - - Packet2 p2; - - ReturnValue_t result = p2.read(&pointer, &size2, true); - printf("result is %02x\n", result); - - printf("%04x; %i: %i: %x %x %x; %i: %x %x;; %04x\n", p2.element1.entry, - p2.element2.entry.size, p2.element2.entry[0].size, - p2.element2.entry[0][0], p2.element2.entry[0][1], - p2.element2.entry[0][2], p2.element2.entry[1].size, - p2.element2.entry[1][0], p2.element2.entry[1][1], - p2.element3.entry); - -} -*/ -struct Test { - uint32_t a; - uint32_t b; -}; - -template -void printMap(FixedMap *map) { - typename FixedMap::Iterator iter; - printf("Map (%i): ", map->getSize()); - for (iter = map->begin(); iter != map->end(); ++iter) { - printf("%x:%08x,%08x ", iter.value->first, (*iter).a, (*iter).b); - } - printf("\n"); -} - -template -void map() { - puts("** Map **"); - typename FixedMap::Iterator iter; - ReturnValue_t result; - FixedMap myMap(5); - - printMap(&myMap); - - Test a; - a.a = 0x01234567; - a.b = 0xabcdef89; - - myMap.insert(1, a); - printMap(&myMap); - - a.a = 0; - - myMap.insert(2, a); - printMap(&myMap); - - printf("2 exists: %x\n", myMap.exists(0x02)); - - printf("ff exists: %x\n", myMap.exists(0xff)); - - a.a = 1; - printf("insert 0x2: %x\n", myMap.insert(2, a)); - - result = myMap.insert(0xff, a); - a.a = 0x44; - result = myMap.insert(0xab, a); - result = myMap.insert(0xa, a); - - printMap(&myMap); - - printf("insert 0x5: %x\n", myMap.insert(5, a)); - - printf("erase 0xfe: %x\n", myMap.erase(0xfe)); - - printf("erase 0x2: %x\n", myMap.erase(0x2)); - - printMap(&myMap); - - printf("erase 0xab: %x\n", myMap.erase(0xab)); - printMap(&myMap); - - printf("insert 0x5: %x\n", myMap.insert(5, a)); - printMap(&myMap); - - iter = myMap.begin(); - ++iter; - ++iter; - ++iter; - - printf("iter: %i: %x,%x\n",iter.value->first, iter->a, iter->b); - - myMap.erase(&iter); - - printf("iter: %i: %x,%x\n",iter.value->first, iter->a, iter->b); - printMap(&myMap); - -} - -/* -void mapPrint() { - puts("** Map Print **"); - FixedMap myMap(5); - Packet2 myPacket; - myPacket.element1.entry = 0x12345678; - - myPacket.element2.entry[0][0] = 0xab; - myPacket.element2.entry[0][1] = 0xcd; - myPacket.element2.entry[0].size = 2; - myPacket.element2.entry.size = 1; - - myPacket.element3.entry = 0xabcdef90; - - myMap.insert(0x1234, myPacket); - - uint8_t buffer[100]; - uint32_t size = 0, i; - uint8_t *pointer = buffer; - - printf("printsize: %i\n", myMap.getPrintSize()); - - SerializeAdapter>::print(&myMap, &pointer, - &size, 100, false); - - printf("buffer(%i):", size); - for (i = 0; i < size; ++i) { - printf("%02x", buffer[i]); - } - printf("\n"); - - int32_t size2 = size; - pointer = buffer; - - FixedMap myMap2(5); - - ReturnValue_t result = SerializeAdapter>::read( - &myMap2, &pointer, &size2, false); - - Packet2 *myPacket2 = myMap2.find(0x1234); - - printf("Map (%i): Packet2: %x, Array (%i): Array (%i): %x, %x; %x\n", - myMap2.getSize(), myPacket2->element1.entry, - myPacket2->element2.entry.size, myPacket2->element2.entry[0].size, - myPacket2->element2.entry[0][0], myPacket2->element2.entry[0][1], - myPacket2->element3.entry); - -} - -void empty() { - puts("** Empty **"); - ArrayList list(0); - printf("%p %p\n", list.front(), list.back()); -} -*/ - -int main(void) { - -// arrayList(); -// linkedList(); -// allocatingList(); -// complex(); - - map(); -// -// mapPrint(); - -// empty(); - - - - return 0; -} From adf528fce91412c43daf349c02cee9710bf54363 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 1 Oct 2020 11:01:52 +0200 Subject: [PATCH 095/101] DH IF and DH message form improved --- devicehandlers/DeviceHandlerIF.h | 20 +++++-- devicehandlers/DeviceHandlerMessage.cpp | 19 +----- devicehandlers/DeviceHandlerMessage.h | 78 ++++++++++--------------- 3 files changed, 48 insertions(+), 69 deletions(-) diff --git a/devicehandlers/DeviceHandlerIF.h b/devicehandlers/DeviceHandlerIF.h index 52a3be4d..9c8eb098 100644 --- a/devicehandlers/DeviceHandlerIF.h +++ b/devicehandlers/DeviceHandlerIF.h @@ -1,12 +1,19 @@ -#ifndef DEVICEHANDLERIF_H_ -#define DEVICEHANDLERIF_H_ +#ifndef FSFW_DEVICEHANDLERS_DEVICEHANDLERIF_H_ +#define FSFW_DEVICEHANDLERS_DEVICEHANDLERIF_H_ + +#include "DeviceHandlerMessage.h" #include "../action/HasActionsIF.h" -#include "DeviceHandlerMessage.h" #include "../events/Event.h" #include "../modes/HasModesIF.h" #include "../ipc/MessageQueueSenderIF.h" +/** + * This is used to uniquely identify commands that are sent to a device + * The values are defined in the device-specific implementations + */ +using DeviceCommandId_t = uint32_t; + /** * @brief This is the Interface used to communicate with a device handler. * @details Includes all expected return values, events and modes. @@ -15,6 +22,7 @@ class DeviceHandlerIF { public: + static const uint8_t TRANSITION_MODE_CHILD_ACTION_MASK = 0x20; static const uint8_t TRANSITION_MODE_BASE_ACTION_MASK = 0x10; @@ -47,6 +55,8 @@ public: //! 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. @@ -96,7 +106,7 @@ public: static const uint8_t INTERFACE_ID = CLASS_ID::DEVICE_HANDLER_IF; // Standard codes used when building commands. - static const ReturnValue_t NO_COMMAND_DATA = MAKE_RETURN_CODE(0xA0); //!< If the command size is 0. Checked in DHB + static const ReturnValue_t NO_COMMAND_DATA = MAKE_RETURN_CODE(0xA0); //!< If no command data was given when expected. static const ReturnValue_t COMMAND_NOT_SUPPORTED = MAKE_RETURN_CODE(0xA1); //!< Command ID not in commandMap. Checked in DHB static const ReturnValue_t COMMAND_ALREADY_SENT = MAKE_RETURN_CODE(0xA2); //!< Command was already executed. Checked in DHB static const ReturnValue_t COMMAND_WAS_NOT_SENT = MAKE_RETURN_CODE(0xA3); @@ -150,4 +160,4 @@ public: }; -#endif /* DEVICEHANDLERIF_H_ */ +#endif /* FSFW_DEVICEHANDLERS_DEVICEHANDLERIF_H_ */ diff --git a/devicehandlers/DeviceHandlerMessage.cpp b/devicehandlers/DeviceHandlerMessage.cpp index 564fae21..cb9043db 100644 --- a/devicehandlers/DeviceHandlerMessage.cpp +++ b/devicehandlers/DeviceHandlerMessage.cpp @@ -1,10 +1,6 @@ -#include "../objectmanager/ObjectManagerIF.h" #include "DeviceHandlerMessage.h" #include "../objectmanager/ObjectManagerIF.h" -DeviceHandlerMessage::DeviceHandlerMessage() { -} - store_address_t DeviceHandlerMessage::getStoreAddress( const CommandMessage* message) { return store_address_t(message->getParameter2()); @@ -25,14 +21,6 @@ uint8_t DeviceHandlerMessage::getWiretappingMode( return message->getParameter(); } -//void DeviceHandlerMessage::setDeviceHandlerDirectCommandMessage( -// CommandMessage* message, DeviceCommandId_t deviceCommand, -// store_address_t commandParametersStoreId) { -// message->setCommand(CMD_DIRECT); -// message->setParameter(deviceCommand); -// message->setParameter2(commandParametersStoreId.raw); -//} - void DeviceHandlerMessage::setDeviceHandlerRawCommandMessage( CommandMessage* message, store_address_t rawPacketStoreId) { message->setCommand(CMD_RAW); @@ -47,7 +35,7 @@ void DeviceHandlerMessage::setDeviceHandlerWiretappingMessage( void DeviceHandlerMessage::setDeviceHandlerSwitchIoBoardMessage( CommandMessage* message, uint32_t ioBoardIdentifier) { - message->setCommand(CMD_SWITCH_IOBOARD); + message->setCommand(CMD_SWITCH_ADDRESS); message->setParameter(ioBoardIdentifier); } @@ -79,18 +67,17 @@ void DeviceHandlerMessage::setDeviceHandlerDirectCommandReply( void DeviceHandlerMessage::clear(CommandMessage* message) { switch (message->getCommand()) { case CMD_RAW: -// case CMD_DIRECT: case REPLY_RAW_COMMAND: case REPLY_RAW_REPLY: case REPLY_DIRECT_COMMAND_DATA: { StorageManagerIF *ipcStore = objectManager->get( objects::IPC_STORE); - if (ipcStore != NULL) { + if (ipcStore != nullptr) { ipcStore->deleteData(getStoreAddress(message)); } } /* NO BREAK falls through*/ - case CMD_SWITCH_IOBOARD: + case CMD_SWITCH_ADDRESS: case CMD_WIRETAPPING: message->setCommand(CommandMessage::CMD_NONE); message->setParameter(0); diff --git a/devicehandlers/DeviceHandlerMessage.h b/devicehandlers/DeviceHandlerMessage.h index 8d1c94f4..e5da01c8 100644 --- a/devicehandlers/DeviceHandlerMessage.h +++ b/devicehandlers/DeviceHandlerMessage.h @@ -1,69 +1,56 @@ -#ifndef DEVICEHANDLERMESSAGE_H_ -#define DEVICEHANDLERMESSAGE_H_ +#ifndef FSFW_DEVICEHANDLERS_DEVICEHANDLERMESSAGE_H_ +#define FSFW_DEVICEHANDLERS_DEVICEHANDLERMESSAGE_H_ #include "../action/ActionMessage.h" #include "../ipc/CommandMessage.h" #include "../objectmanager/SystemObjectIF.h" #include "../storagemanager/StorageManagerIF.h" -//SHOULDDO: rework the static constructors to name the type of command they are building, maybe even hide setting the commandID. +// SHOULDDO: rework the static constructors to name the type of command +// they are building, maybe even hide setting the commandID. + /** - * This is used to uniquely identify commands that are sent to a device - * - * The values are defined in the device-specific implementations - */ -typedef uint32_t DeviceCommandId_t; - -/** - * The DeviceHandlerMessage is used to send Commands to a DeviceHandlerIF + * @brief The DeviceHandlerMessage is used to send commands to classes + * implementing DeviceHandlerIF */ class DeviceHandlerMessage { -private: - DeviceHandlerMessage(); public: + /** + * Instantiation forbidden. Instead, use static functions to operate + * on messages. + */ + DeviceHandlerMessage() = delete; + virtual ~DeviceHandlerMessage() {} /** * These are the commands that can be sent to a DeviceHandlerBase */ static const uint8_t MESSAGE_ID = messagetypes::DEVICE_HANDLER_COMMAND; - static const Command_t CMD_RAW = MAKE_COMMAND_ID( 1 ); //!< Sends a raw command, setParameter is a ::store_id_t containing the raw packet to send -// static const Command_t CMD_DIRECT = MAKE_COMMAND_ID( 2 ); //!< Sends a direct command, setParameter is a ::DeviceCommandId_t, setParameter2 is a ::store_id_t containing the data needed for the command - static const Command_t CMD_SWITCH_IOBOARD = MAKE_COMMAND_ID( 3 ); //!< Requests a IO-Board switch, setParameter() is the IO-Board identifier - static const Command_t CMD_WIRETAPPING = MAKE_COMMAND_ID( 4 ); //!< (De)Activates the monitoring of all raw traffic in DeviceHandlers, setParameter is 0 to deactivate, 1 to activate + //! Sends a raw command, setParameter is a storeId containing the + //! raw packet to send + static const Command_t CMD_RAW = MAKE_COMMAND_ID(1); + //! Requests a IO-Board switch, setParameter() is the IO-Board identifier + static const Command_t CMD_SWITCH_ADDRESS = MAKE_COMMAND_ID(3); + //! (De)Activates the monitoring of all raw traffic in DeviceHandlers, + //! setParameter is 0 to deactivate, 1 to activate + static const Command_t CMD_WIRETAPPING = MAKE_COMMAND_ID(4); - /*static const Command_t REPLY_SWITCHED_IOBOARD = MAKE_COMMAND_ID(1 );//!< Reply to a @c CMD_SWITCH_IOBOARD, indicates switch was successful, getParameter() contains the board switched to (0: nominal, 1: redundant) - static const Command_t REPLY_CANT_SWITCH_IOBOARD = MAKE_COMMAND_ID( 2); //!< Reply to a @c CMD_SWITCH_IOBOARD, indicating the switch could not be performed, getParameter() contains the error message - static const Command_t REPLY_WIRETAPPING = MAKE_COMMAND_ID( 3); //!< Reply to a @c CMD_WIRETAPPING, getParameter() is the current state, 1 enabled, 0 disabled - - static const Command_t REPLY_COMMAND_WAS_SENT = MAKE_COMMAND_ID(4 );//!< Reply to a @c CMD_RAW or @c CMD_DIRECT, indicates the command was successfully sent to the device, getParameter() contains the ::DeviceCommandId_t - static const Command_t REPLY_COMMAND_NOT_SUPPORTED = MAKE_COMMAND_ID(5 );//!< Reply to a @c CMD_DIRECT, the requested ::DeviceCommand_t is not supported, getParameter() contains the requested ::DeviceCommand_t, getParameter2() contains the ::DeviceCommandId_t - static const Command_t REPLY_COMMAND_WAS_NOT_SENT = MAKE_COMMAND_ID(6 );//!< Reply to a @c CMD_RAW or @c CMD_DIRECT, indicates the command was not sent, getParameter contains the RMAP Return code (@see rmap.h), getParameter2() contains the ::DeviceCommandId_t - - static const Command_t REPLY_COMMAND_ALREADY_SENT = MAKE_COMMAND_ID(7 );//!< Reply to a @c CMD_DIRECT, the requested ::DeviceCommand_t has already been sent to the device and not ye been answered - static const Command_t REPLY_WRONG_MODE_FOR_CMD = MAKE_COMMAND_ID(8 );//!< Reply to a @c CMD_RAW or @c CMD_DIRECT, indicates that the requested command can not be sent in the curent mode, getParameter() contains the DeviceHandlerCommand_t - static const Command_t REPLY_NO_DATA = MAKE_COMMAND_ID(9 ); //!< Reply to a CMD_RAW or @c CMD_DIRECT, indicates that the ::store_id_t was invalid, getParameter() contains the ::DeviceCommandId_t, getPrameter2() contains the error code - */ - static const Command_t REPLY_DIRECT_COMMAND_SENT = ActionMessage::STEP_SUCCESS; //!< Signals that a direct command was sent - static const Command_t REPLY_RAW_COMMAND = MAKE_COMMAND_ID(0x11 ); //!< Contains a raw command sent to the Device - static const Command_t REPLY_RAW_REPLY = MAKE_COMMAND_ID( 0x12); //!< Contains a raw reply from the Device, getParameter() is the ObjcetId of the sender, getParameter2() is a ::store_id_t containing the raw packet received + //! Signals that a direct command was sent + static const Command_t REPLY_DIRECT_COMMAND_SENT = ActionMessage::STEP_SUCCESS; + //! Contains a raw command sent to the Device + static const Command_t REPLY_RAW_COMMAND = MAKE_COMMAND_ID(0x11); + //! Contains a raw reply from the Device, getParameter() is the ObjcetId + //! of the sender, getParameter2() is a ::store_id_t containing the + //! raw packet received + static const Command_t REPLY_RAW_REPLY = MAKE_COMMAND_ID(0x12); static const Command_t REPLY_DIRECT_COMMAND_DATA = ActionMessage::DATA_REPLY; - /** - * Default Destructor - */ - virtual ~DeviceHandlerMessage() { - } - static store_address_t getStoreAddress(const CommandMessage* message); static uint32_t getDeviceCommandId(const CommandMessage* message); static object_id_t getDeviceObjectId(const CommandMessage *message); static object_id_t getIoBoardObjectId(const CommandMessage* message); static uint8_t getWiretappingMode(const CommandMessage* message); -// static void setDeviceHandlerDirectCommandMessage(CommandMessage* message, -// DeviceCommandId_t deviceCommand, -// store_address_t commandParametersStoreId); - static void setDeviceHandlerDirectCommandReply(CommandMessage* message, object_id_t deviceObjectid, store_address_t commandParametersStoreId); @@ -75,11 +62,6 @@ public: object_id_t deviceObjectid, store_address_t rawPacketStoreId, bool isCommand); -// static void setDeviceHandlerMessage(CommandMessage* message, -// Command_t command, DeviceCommandId_t deviceCommand, -// store_address_t commandParametersStoreId); -// static void setDeviceHandlerMessage(CommandMessage* message, -// Command_t command, store_address_t rawPacketStoreId); static void setDeviceHandlerWiretappingMessage(CommandMessage* message, uint8_t wiretappingMode); static void setDeviceHandlerSwitchIoBoardMessage(CommandMessage* message, @@ -88,4 +70,4 @@ public: static void clear(CommandMessage* message); }; -#endif /* DEVICEHANDLERMESSAGE_H_ */ +#endif /* FSFW_DEVICEHANDLERS_DEVICEHANDLERMESSAGE_H_ */ From 7c3f99ed2d4beba650722e596a48abb9edb837c4 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 1 Oct 2020 11:06:46 +0200 Subject: [PATCH 096/101] Revert "DH IF and DH message form improved" This reverts commit adf528fce91412c43daf349c02cee9710bf54363. --- devicehandlers/DeviceHandlerIF.h | 20 ++----- devicehandlers/DeviceHandlerMessage.cpp | 19 +++++- devicehandlers/DeviceHandlerMessage.h | 78 +++++++++++++++---------- 3 files changed, 69 insertions(+), 48 deletions(-) diff --git a/devicehandlers/DeviceHandlerIF.h b/devicehandlers/DeviceHandlerIF.h index 9c8eb098..52a3be4d 100644 --- a/devicehandlers/DeviceHandlerIF.h +++ b/devicehandlers/DeviceHandlerIF.h @@ -1,19 +1,12 @@ -#ifndef FSFW_DEVICEHANDLERS_DEVICEHANDLERIF_H_ -#define FSFW_DEVICEHANDLERS_DEVICEHANDLERIF_H_ - -#include "DeviceHandlerMessage.h" +#ifndef DEVICEHANDLERIF_H_ +#define DEVICEHANDLERIF_H_ #include "../action/HasActionsIF.h" +#include "DeviceHandlerMessage.h" #include "../events/Event.h" #include "../modes/HasModesIF.h" #include "../ipc/MessageQueueSenderIF.h" -/** - * This is used to uniquely identify commands that are sent to a device - * The values are defined in the device-specific implementations - */ -using DeviceCommandId_t = uint32_t; - /** * @brief This is the Interface used to communicate with a device handler. * @details Includes all expected return values, events and modes. @@ -22,7 +15,6 @@ using DeviceCommandId_t = uint32_t; class DeviceHandlerIF { public: - static const uint8_t TRANSITION_MODE_CHILD_ACTION_MASK = 0x20; static const uint8_t TRANSITION_MODE_BASE_ACTION_MASK = 0x10; @@ -55,8 +47,6 @@ public: //! 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. @@ -106,7 +96,7 @@ public: static const uint8_t INTERFACE_ID = CLASS_ID::DEVICE_HANDLER_IF; // Standard codes used when building commands. - static const ReturnValue_t NO_COMMAND_DATA = MAKE_RETURN_CODE(0xA0); //!< If no command data was given when expected. + static const ReturnValue_t NO_COMMAND_DATA = MAKE_RETURN_CODE(0xA0); //!< If the command size is 0. Checked in DHB static const ReturnValue_t COMMAND_NOT_SUPPORTED = MAKE_RETURN_CODE(0xA1); //!< Command ID not in commandMap. Checked in DHB static const ReturnValue_t COMMAND_ALREADY_SENT = MAKE_RETURN_CODE(0xA2); //!< Command was already executed. Checked in DHB static const ReturnValue_t COMMAND_WAS_NOT_SENT = MAKE_RETURN_CODE(0xA3); @@ -160,4 +150,4 @@ public: }; -#endif /* FSFW_DEVICEHANDLERS_DEVICEHANDLERIF_H_ */ +#endif /* DEVICEHANDLERIF_H_ */ diff --git a/devicehandlers/DeviceHandlerMessage.cpp b/devicehandlers/DeviceHandlerMessage.cpp index cb9043db..564fae21 100644 --- a/devicehandlers/DeviceHandlerMessage.cpp +++ b/devicehandlers/DeviceHandlerMessage.cpp @@ -1,6 +1,10 @@ +#include "../objectmanager/ObjectManagerIF.h" #include "DeviceHandlerMessage.h" #include "../objectmanager/ObjectManagerIF.h" +DeviceHandlerMessage::DeviceHandlerMessage() { +} + store_address_t DeviceHandlerMessage::getStoreAddress( const CommandMessage* message) { return store_address_t(message->getParameter2()); @@ -21,6 +25,14 @@ uint8_t DeviceHandlerMessage::getWiretappingMode( return message->getParameter(); } +//void DeviceHandlerMessage::setDeviceHandlerDirectCommandMessage( +// CommandMessage* message, DeviceCommandId_t deviceCommand, +// store_address_t commandParametersStoreId) { +// message->setCommand(CMD_DIRECT); +// message->setParameter(deviceCommand); +// message->setParameter2(commandParametersStoreId.raw); +//} + void DeviceHandlerMessage::setDeviceHandlerRawCommandMessage( CommandMessage* message, store_address_t rawPacketStoreId) { message->setCommand(CMD_RAW); @@ -35,7 +47,7 @@ void DeviceHandlerMessage::setDeviceHandlerWiretappingMessage( void DeviceHandlerMessage::setDeviceHandlerSwitchIoBoardMessage( CommandMessage* message, uint32_t ioBoardIdentifier) { - message->setCommand(CMD_SWITCH_ADDRESS); + message->setCommand(CMD_SWITCH_IOBOARD); message->setParameter(ioBoardIdentifier); } @@ -67,17 +79,18 @@ void DeviceHandlerMessage::setDeviceHandlerDirectCommandReply( void DeviceHandlerMessage::clear(CommandMessage* message) { switch (message->getCommand()) { case CMD_RAW: +// case CMD_DIRECT: case REPLY_RAW_COMMAND: case REPLY_RAW_REPLY: case REPLY_DIRECT_COMMAND_DATA: { StorageManagerIF *ipcStore = objectManager->get( objects::IPC_STORE); - if (ipcStore != nullptr) { + if (ipcStore != NULL) { ipcStore->deleteData(getStoreAddress(message)); } } /* NO BREAK falls through*/ - case CMD_SWITCH_ADDRESS: + case CMD_SWITCH_IOBOARD: case CMD_WIRETAPPING: message->setCommand(CommandMessage::CMD_NONE); message->setParameter(0); diff --git a/devicehandlers/DeviceHandlerMessage.h b/devicehandlers/DeviceHandlerMessage.h index e5da01c8..8d1c94f4 100644 --- a/devicehandlers/DeviceHandlerMessage.h +++ b/devicehandlers/DeviceHandlerMessage.h @@ -1,56 +1,69 @@ -#ifndef FSFW_DEVICEHANDLERS_DEVICEHANDLERMESSAGE_H_ -#define FSFW_DEVICEHANDLERS_DEVICEHANDLERMESSAGE_H_ +#ifndef DEVICEHANDLERMESSAGE_H_ +#define DEVICEHANDLERMESSAGE_H_ #include "../action/ActionMessage.h" #include "../ipc/CommandMessage.h" #include "../objectmanager/SystemObjectIF.h" #include "../storagemanager/StorageManagerIF.h" -// SHOULDDO: rework the static constructors to name the type of command -// they are building, maybe even hide setting the commandID. - +//SHOULDDO: rework the static constructors to name the type of command they are building, maybe even hide setting the commandID. /** - * @brief The DeviceHandlerMessage is used to send commands to classes - * implementing DeviceHandlerIF + * This is used to uniquely identify commands that are sent to a device + * + * The values are defined in the device-specific implementations + */ +typedef uint32_t DeviceCommandId_t; + +/** + * The DeviceHandlerMessage is used to send Commands to a DeviceHandlerIF */ class DeviceHandlerMessage { +private: + DeviceHandlerMessage(); public: - /** - * Instantiation forbidden. Instead, use static functions to operate - * on messages. - */ - DeviceHandlerMessage() = delete; - virtual ~DeviceHandlerMessage() {} /** * These are the commands that can be sent to a DeviceHandlerBase */ static const uint8_t MESSAGE_ID = messagetypes::DEVICE_HANDLER_COMMAND; - //! Sends a raw command, setParameter is a storeId containing the - //! raw packet to send - static const Command_t CMD_RAW = MAKE_COMMAND_ID(1); - //! Requests a IO-Board switch, setParameter() is the IO-Board identifier - static const Command_t CMD_SWITCH_ADDRESS = MAKE_COMMAND_ID(3); - //! (De)Activates the monitoring of all raw traffic in DeviceHandlers, - //! setParameter is 0 to deactivate, 1 to activate - static const Command_t CMD_WIRETAPPING = MAKE_COMMAND_ID(4); + static const Command_t CMD_RAW = MAKE_COMMAND_ID( 1 ); //!< Sends a raw command, setParameter is a ::store_id_t containing the raw packet to send +// static const Command_t CMD_DIRECT = MAKE_COMMAND_ID( 2 ); //!< Sends a direct command, setParameter is a ::DeviceCommandId_t, setParameter2 is a ::store_id_t containing the data needed for the command + static const Command_t CMD_SWITCH_IOBOARD = MAKE_COMMAND_ID( 3 ); //!< Requests a IO-Board switch, setParameter() is the IO-Board identifier + static const Command_t CMD_WIRETAPPING = MAKE_COMMAND_ID( 4 ); //!< (De)Activates the monitoring of all raw traffic in DeviceHandlers, setParameter is 0 to deactivate, 1 to activate - //! Signals that a direct command was sent - static const Command_t REPLY_DIRECT_COMMAND_SENT = ActionMessage::STEP_SUCCESS; - //! Contains a raw command sent to the Device - static const Command_t REPLY_RAW_COMMAND = MAKE_COMMAND_ID(0x11); - //! Contains a raw reply from the Device, getParameter() is the ObjcetId - //! of the sender, getParameter2() is a ::store_id_t containing the - //! raw packet received - static const Command_t REPLY_RAW_REPLY = MAKE_COMMAND_ID(0x12); + /*static const Command_t REPLY_SWITCHED_IOBOARD = MAKE_COMMAND_ID(1 );//!< Reply to a @c CMD_SWITCH_IOBOARD, indicates switch was successful, getParameter() contains the board switched to (0: nominal, 1: redundant) + static const Command_t REPLY_CANT_SWITCH_IOBOARD = MAKE_COMMAND_ID( 2); //!< Reply to a @c CMD_SWITCH_IOBOARD, indicating the switch could not be performed, getParameter() contains the error message + static const Command_t REPLY_WIRETAPPING = MAKE_COMMAND_ID( 3); //!< Reply to a @c CMD_WIRETAPPING, getParameter() is the current state, 1 enabled, 0 disabled + + static const Command_t REPLY_COMMAND_WAS_SENT = MAKE_COMMAND_ID(4 );//!< Reply to a @c CMD_RAW or @c CMD_DIRECT, indicates the command was successfully sent to the device, getParameter() contains the ::DeviceCommandId_t + static const Command_t REPLY_COMMAND_NOT_SUPPORTED = MAKE_COMMAND_ID(5 );//!< Reply to a @c CMD_DIRECT, the requested ::DeviceCommand_t is not supported, getParameter() contains the requested ::DeviceCommand_t, getParameter2() contains the ::DeviceCommandId_t + static const Command_t REPLY_COMMAND_WAS_NOT_SENT = MAKE_COMMAND_ID(6 );//!< Reply to a @c CMD_RAW or @c CMD_DIRECT, indicates the command was not sent, getParameter contains the RMAP Return code (@see rmap.h), getParameter2() contains the ::DeviceCommandId_t + + static const Command_t REPLY_COMMAND_ALREADY_SENT = MAKE_COMMAND_ID(7 );//!< Reply to a @c CMD_DIRECT, the requested ::DeviceCommand_t has already been sent to the device and not ye been answered + static const Command_t REPLY_WRONG_MODE_FOR_CMD = MAKE_COMMAND_ID(8 );//!< Reply to a @c CMD_RAW or @c CMD_DIRECT, indicates that the requested command can not be sent in the curent mode, getParameter() contains the DeviceHandlerCommand_t + static const Command_t REPLY_NO_DATA = MAKE_COMMAND_ID(9 ); //!< Reply to a CMD_RAW or @c CMD_DIRECT, indicates that the ::store_id_t was invalid, getParameter() contains the ::DeviceCommandId_t, getPrameter2() contains the error code + */ + static const Command_t REPLY_DIRECT_COMMAND_SENT = ActionMessage::STEP_SUCCESS; //!< Signals that a direct command was sent + static const Command_t REPLY_RAW_COMMAND = MAKE_COMMAND_ID(0x11 ); //!< Contains a raw command sent to the Device + static const Command_t REPLY_RAW_REPLY = MAKE_COMMAND_ID( 0x12); //!< Contains a raw reply from the Device, getParameter() is the ObjcetId of the sender, getParameter2() is a ::store_id_t containing the raw packet received static const Command_t REPLY_DIRECT_COMMAND_DATA = ActionMessage::DATA_REPLY; + /** + * Default Destructor + */ + virtual ~DeviceHandlerMessage() { + } + static store_address_t getStoreAddress(const CommandMessage* message); static uint32_t getDeviceCommandId(const CommandMessage* message); static object_id_t getDeviceObjectId(const CommandMessage *message); static object_id_t getIoBoardObjectId(const CommandMessage* message); static uint8_t getWiretappingMode(const CommandMessage* message); +// static void setDeviceHandlerDirectCommandMessage(CommandMessage* message, +// DeviceCommandId_t deviceCommand, +// store_address_t commandParametersStoreId); + static void setDeviceHandlerDirectCommandReply(CommandMessage* message, object_id_t deviceObjectid, store_address_t commandParametersStoreId); @@ -62,6 +75,11 @@ public: object_id_t deviceObjectid, store_address_t rawPacketStoreId, bool isCommand); +// static void setDeviceHandlerMessage(CommandMessage* message, +// Command_t command, DeviceCommandId_t deviceCommand, +// store_address_t commandParametersStoreId); +// static void setDeviceHandlerMessage(CommandMessage* message, +// Command_t command, store_address_t rawPacketStoreId); static void setDeviceHandlerWiretappingMessage(CommandMessage* message, uint8_t wiretappingMode); static void setDeviceHandlerSwitchIoBoardMessage(CommandMessage* message, @@ -70,4 +88,4 @@ public: static void clear(CommandMessage* message); }; -#endif /* FSFW_DEVICEHANDLERS_DEVICEHANDLERMESSAGE_H_ */ +#endif /* DEVICEHANDLERMESSAGE_H_ */ From 1f3a10b37554c1b8872a2dd82e0ebb4673e270f7 Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Thu, 1 Oct 2020 13:30:28 +0200 Subject: [PATCH 097/101] Fixes and comments in FixedOrderedMultimap --- container/FixedOrderedMultimap.h | 208 +++++++++++++++++++++++-------- 1 file changed, 159 insertions(+), 49 deletions(-) diff --git a/container/FixedOrderedMultimap.h b/container/FixedOrderedMultimap.h index 717575d7..a9f093d6 100644 --- a/container/FixedOrderedMultimap.h +++ b/container/FixedOrderedMultimap.h @@ -5,6 +5,24 @@ #include #include /** + * @brief A "Map" which allows multiple entries of the same key. + * @details + * Same keys are ordered by KEY_COMPARE function which is std::less > by default. + * + * It uses the ArrayList, so technically this is not a real map, it is an array of pairs + * of type key_t, T. It is ordered by key_t as FixedMap but allows same keys. + * + * Its of fixed size so no allocations are performed after the construction. + * + * The maximum size is given as first parameter of the constructor. + * + * It provides an iterator to do list iterations. + * + * The type T must have a copy constructor if it is not trivial copy-able. + * + * @warning Iterators return a non-const key_t in the pair. + * @warning A User is not allowed to change the key, otherwise the map is corrupted. + * * \ingroup container */ template> @@ -14,78 +32,84 @@ public: static const ReturnValue_t MAP_FULL = MAKE_RETURN_CODE(0x01); static const ReturnValue_t KEY_DOES_NOT_EXIST = MAKE_RETURN_CODE(0x02); -private: - typedef KEY_COMPARE compare; - compare myComp; - ArrayList, uint32_t> theMap; - uint32_t _size; - - uint32_t findFirstIndex(key_t key, uint32_t startAt = 0) const { - if (startAt >= _size) { - return startAt + 1; - } - uint32_t i = startAt; - for (i = startAt; i < _size; ++i) { - if (theMap[i].first == key) { - return i; - } - } - return i; - } - - uint32_t findNicePlace(key_t key) const { - uint32_t i = 0; - for (i = 0; i < _size; ++i) { - if (myComp(key, theMap[i].first)) { - return i; - } - } - return i; - } - - void removeFromPosition(uint32_t position) { - if (_size <= position) { - return; - } - memmove(static_cast(&theMap[position]), static_cast(&theMap[position + 1]), - (_size - position - 1) * sizeof(std::pair)); - --_size; - } -public: - FixedOrderedMultimap(uint32_t maxSize) : - theMap(maxSize), _size(0) { + /*** + * Constructor which needs a size_t for the maximum allowed size + * + * Can not be resized during runtime + * + * Allocates memory at construction + * @param maxSize size_t of Maximum allowed size + */ + FixedOrderedMultimap(size_t maxSize) : + theMap(maxSize), _size(0) { } + /*** + * Virtual destructor frees Memory by deleting its member + */ virtual ~FixedOrderedMultimap() { } - class Iterator: public ArrayList, uint32_t>::Iterator { + /*** + * Special iterator for FixedOrderedMultimap + */ + class Iterator: public ArrayList, size_t>::Iterator { public: Iterator() : - ArrayList, uint32_t>::Iterator() { + ArrayList, size_t>::Iterator() { } Iterator(std::pair *pair) : - ArrayList, uint32_t>::Iterator(pair) { + ArrayList, size_t>::Iterator(pair) { } }; + friend bool operator==(const typename FixedOrderedMultimap::Iterator& lhs, + const typename FixedOrderedMultimap::Iterator& rhs) { + return (lhs.value == rhs.value); + } + + friend bool operator!=(const typename FixedOrderedMultimap::Iterator& lhs, + const typename FixedOrderedMultimap::Iterator& rhs) { + return not (lhs.value == rhs.value); + } + + /*** + * Returns an iterator on the first element + * @return Iterator pointing to first element + */ Iterator begin() const { return Iterator(&theMap[0]); } + /** + * Returns an iterator pointing to one element past the end + * @return Iterator pointing to one element past the end + */ Iterator end() const { return Iterator(&theMap[_size]); } - uint32_t size() const { + /*** + * Returns the current size of the map (not maximum size!) + * @return Current size + */ + size_t size() const { return _size; } + /*** + * Used to insert a key and value separately. + * + * @param[in] key Key of the new element + * @param[in] value Value of the new element + * @param[in/out] (optional) storedValue On success this points to the new value, otherwise a nullptr + * @return RETURN_OK if insert was successful, MAP_FULL if no space is available + */ ReturnValue_t insert(key_t key, T value, Iterator *storedValue = nullptr) { if (_size == theMap.maxSize()) { return MAP_FULL; } - uint32_t position = findNicePlace(key); + size_t position = findNicePlace(key); memmove(static_cast(&theMap[position + 1]),static_cast(&theMap[position]), (_size - position) * sizeof(std::pair)); theMap[position].first = key; @@ -97,10 +121,21 @@ public: return HasReturnvaluesIF::RETURN_OK; } + /*** + * Used to insert new pair instead of single values + * + * @param pair Pair to be inserted + * @return RETURN_OK if insert was successful, MAP_FULL if no space is available + */ ReturnValue_t insert(std::pair pair) { return insert(pair.first, pair.second); } + /*** + * Can be used to check if a certain key is in the map + * @param key Key to be checked + * @return RETURN_OK if the key exists KEY_DOES_NOT_EXIST otherwise + */ ReturnValue_t exists(key_t key) const { ReturnValue_t result = KEY_DOES_NOT_EXIST; if (findFirstIndex(key) < _size) { @@ -109,8 +144,18 @@ public: return result; } + /*** + * Used to delete the element in the iterator + * + * The iterator will point to the element before or begin(), + * but never to one element in front of the map. + * + * @warning The iterator needs to be valid and dereferenceable + * @param[in/out] iter Pointer to iterator to the element that needs to be ereased + * @return RETURN_OK if erased, KEY_DOES_NOT_EXIST if the there is no element like this + */ ReturnValue_t erase(Iterator *iter) { - uint32_t i; + size_t i; if ((i = findFirstIndex((*iter).value->first)) >= _size) { return KEY_DOES_NOT_EXIST; } @@ -123,8 +168,13 @@ public: return HasReturnvaluesIF::RETURN_OK; } + /*** + * Used to erase by key + * @param key Key to be erased + * @return RETURN_OK if erased, KEY_DOES_NOT_EXIST if the there is no element like this + */ ReturnValue_t erase(key_t key) { - uint32_t i; + size_t i; if ((i = findFirstIndex(key)) >= _size) { return KEY_DOES_NOT_EXIST; } @@ -135,6 +185,14 @@ public: return HasReturnvaluesIF::RETURN_OK; } + /*** + * Find returns the first appearance of the key + * + * If the key does not exist, it points to end() + * + * @param key Key to search for + * @return Iterator pointing to the first entry of key + */ Iterator find(key_t key) const { ReturnValue_t result = exists(key); if (result != HasReturnvaluesIF::RETURN_OK) { @@ -143,6 +201,15 @@ public: return Iterator(&theMap[findFirstIndex(key)]); } + /*** + * Finds first entry of the given key and returns a + * pointer to the value + * + * @param key Key to search for + * @param value Found value + * @return RETURN_OK if it points to the value, + * KEY_DOES_NOT_EXIST if the key is not in the map + */ ReturnValue_t find(key_t key, T **value) const { ReturnValue_t result = exists(key); if (result != HasReturnvaluesIF::RETURN_OK) { @@ -151,15 +218,58 @@ public: *value = &theMap[findFirstIndex(key)].second; return HasReturnvaluesIF::RETURN_OK; } - + /** + * Clears the map, does not deallocate any memory + */ void clear() { _size = 0; } - uint32_t maxSize() const { + /** + * Returns the maximum size of the map + * @return Maximum size of the map + */ + size_t maxSize() const { return theMap.maxSize(); } +private: + typedef KEY_COMPARE compare; + compare myComp; + ArrayList, size_t> theMap; + size_t _size; + + size_t findFirstIndex(key_t key, size_t startAt = 0) const { + if (startAt >= _size) { + return startAt + 1; + } + size_t i = startAt; + for (i = startAt; i < _size; ++i) { + if (theMap[i].first == key) { + return i; + } + } + return i; + } + + size_t findNicePlace(key_t key) const { + size_t i = 0; + for (i = 0; i < _size; ++i) { + if (myComp(key, theMap[i].first)) { + return i; + } + } + return i; + } + + void removeFromPosition(size_t position) { + if (_size <= position) { + return; + } + memmove(static_cast(&theMap[position]), static_cast(&theMap[position + 1]), + (_size - position - 1) * sizeof(std::pair)); + --_size; + } }; #endif /* FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_H_ */ From c86d654fdfedfb3319e9ace45dc83874ce8d5c6a Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 1 Oct 2020 13:58:20 +0200 Subject: [PATCH 098/101] tpp file added --- container/FixedOrderedMultimap.h | 197 ++++++++++++----------------- container/FixedOrderedMultimap.tpp | 143 +++++++++++++++++++++ 2 files changed, 222 insertions(+), 118 deletions(-) create mode 100644 container/FixedOrderedMultimap.tpp diff --git a/container/FixedOrderedMultimap.h b/container/FixedOrderedMultimap.h index 717575d7..cb8ab10f 100644 --- a/container/FixedOrderedMultimap.h +++ b/container/FixedOrderedMultimap.h @@ -1,24 +1,91 @@ -#ifndef FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_H_ -#define FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_H_ +#ifndef FSFW_CONTAINER_FIXEDORDEREDMULTIMAP_H_ +#define FSFW_CONTAINER_FIXEDORDEREDMULTIMAP_H_ #include "ArrayList.h" #include -#include + /** - * \ingroup container + * @brief Map implementation which allows entries with identical keys + * @details + * Performs no dynamic memory allocation except on initialization. + * Uses an ArrayList as the underlying container and thus has a linear + * complexity O(n). As long as the number of entries remains low, this + * should not be an issue. + * The number of insertion and deletion operation should be minimized + * as those incur exensive memory move operations (the underlying container + * is not node based). + * @ingroup container */ template> class FixedOrderedMultimap { public: static const uint8_t INTERFACE_ID = CLASS_ID::FIXED_MULTIMAP; - static const ReturnValue_t MAP_FULL = MAKE_RETURN_CODE(0x01); - static const ReturnValue_t KEY_DOES_NOT_EXIST = MAKE_RETURN_CODE(0x02); + static const ReturnValue_t KEY_ALREADY_EXISTS = MAKE_RETURN_CODE(0x01); + static const ReturnValue_t MAP_FULL = MAKE_RETURN_CODE(0x02); + static const ReturnValue_t KEY_DOES_NOT_EXIST = MAKE_RETURN_CODE(0x03); + + /** + * Initializes the ordered multimap with a fixed maximum size. + * @param maxSize + */ + FixedOrderedMultimap(size_t maxSize); + + virtual ~FixedOrderedMultimap() {} + + class Iterator: public ArrayList, uint32_t>::Iterator { + public: + /** Returns an iterator to nullptr */ + Iterator(); + /** Initializes iterator to given entry */ + Iterator(std::pair *pair); + }; + + /** Iterator to start of map */ + Iterator begin() const; + /** Iterator to end of map */ + Iterator end() const; + /** Current (variable) size of the map */ + size_t size() const; + + /** + * Insert a key/value pair inside the map. An iterator to the stored + * value might be returned optionally. + * @param key + * @param value + * @param storedValue + * @return + */ + ReturnValue_t insert(key_t key, T value, Iterator *storedValue = nullptr); + /** + * Insert a given std::pair + * @param pair + * @return + */ + ReturnValue_t insert(std::pair pair); + /** + * Checks existence of key in map. + * @param key + * @return + * - @c KEY_DOES_NOT_EXIST if key does not exists. + * - @c RETURN_OK otherwise. + */ + ReturnValue_t exists(key_t key) const; + + ReturnValue_t erase(Iterator *iter); + ReturnValue_t erase(key_t key); + + Iterator find(key_t key) const; + ReturnValue_t find(key_t key, T **value) const; + + void clear(); + + size_t maxSize() const; private: typedef KEY_COMPARE compare; compare myComp; ArrayList, uint32_t> theMap; - uint32_t _size; + size_t _size; uint32_t findFirstIndex(key_t key, uint32_t startAt = 0) const { if (startAt >= _size) { @@ -47,119 +114,13 @@ private: if (_size <= position) { return; } - memmove(static_cast(&theMap[position]), static_cast(&theMap[position + 1]), + std::memmove(static_cast(&theMap[position]), + static_cast(&theMap[position + 1]), (_size - position - 1) * sizeof(std::pair)); --_size; } -public: - FixedOrderedMultimap(uint32_t maxSize) : - theMap(maxSize), _size(0) { - } - virtual ~FixedOrderedMultimap() { - } - - class Iterator: public ArrayList, uint32_t>::Iterator { - public: - Iterator() : - ArrayList, uint32_t>::Iterator() { - } - - Iterator(std::pair *pair) : - ArrayList, uint32_t>::Iterator(pair) { - } - }; - - Iterator begin() const { - return Iterator(&theMap[0]); - } - - Iterator end() const { - return Iterator(&theMap[_size]); - } - - uint32_t size() const { - return _size; - } - - ReturnValue_t insert(key_t key, T value, Iterator *storedValue = nullptr) { - if (_size == theMap.maxSize()) { - return MAP_FULL; - } - uint32_t position = findNicePlace(key); - memmove(static_cast(&theMap[position + 1]),static_cast(&theMap[position]), - (_size - position) * sizeof(std::pair)); - theMap[position].first = key; - theMap[position].second = value; - ++_size; - if (storedValue != nullptr) { - *storedValue = Iterator(&theMap[position]); - } - return HasReturnvaluesIF::RETURN_OK; - } - - ReturnValue_t insert(std::pair pair) { - return insert(pair.first, pair.second); - } - - ReturnValue_t exists(key_t key) const { - ReturnValue_t result = KEY_DOES_NOT_EXIST; - if (findFirstIndex(key) < _size) { - result = HasReturnvaluesIF::RETURN_OK; - } - return result; - } - - ReturnValue_t erase(Iterator *iter) { - uint32_t i; - if ((i = findFirstIndex((*iter).value->first)) >= _size) { - return KEY_DOES_NOT_EXIST; - } - removeFromPosition(i); - if (*iter != begin()) { - (*iter)--; - } else { - *iter = begin(); - } - return HasReturnvaluesIF::RETURN_OK; - } - - ReturnValue_t erase(key_t key) { - uint32_t i; - if ((i = findFirstIndex(key)) >= _size) { - return KEY_DOES_NOT_EXIST; - } - do { - removeFromPosition(i); - i = findFirstIndex(key, i); - } while (i < _size); - return HasReturnvaluesIF::RETURN_OK; - } - - Iterator find(key_t key) const { - ReturnValue_t result = exists(key); - if (result != HasReturnvaluesIF::RETURN_OK) { - return end(); - } - return Iterator(&theMap[findFirstIndex(key)]); - } - - ReturnValue_t find(key_t key, T **value) const { - ReturnValue_t result = exists(key); - if (result != HasReturnvaluesIF::RETURN_OK) { - return result; - } - *value = &theMap[findFirstIndex(key)].second; - return HasReturnvaluesIF::RETURN_OK; - } - - void clear() { - _size = 0; - } - - uint32_t maxSize() const { - return theMap.maxSize(); - } - }; -#endif /* FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_H_ */ +#include "FixedOrderedMultimap.tpp" + +#endif /* FSFW_CONTAINER_FIXEDORDEREDMULTIMAP_H_ */ diff --git a/container/FixedOrderedMultimap.tpp b/container/FixedOrderedMultimap.tpp new file mode 100644 index 00000000..bc76c594 --- /dev/null +++ b/container/FixedOrderedMultimap.tpp @@ -0,0 +1,143 @@ +#ifndef FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_TPP_ +#define FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_TPP_ + +template +inline FixedOrderedMultimap::Iterator::Iterator(): + ArrayList, uint32_t>::Iterator(){} + +template +inline FixedOrderedMultimap::Iterator::Iterator( + std::pair *pair): + ArrayList, uint32_t>::Iterator(pair){} + +template +inline typename FixedOrderedMultimap::Iterator +FixedOrderedMultimap::begin() const { + return Iterator(&theMap[0]); +} + +template +inline typename FixedOrderedMultimap::Iterator +FixedOrderedMultimap::end() const { + return Iterator(&theMap[_size]); +} + + +template +inline size_t FixedOrderedMultimap::size() const { + return _size; +} + +template +inline FixedOrderedMultimap::FixedOrderedMultimap( + size_t maxSize): theMap(maxSize), _size(0) {} + + +template +inline ReturnValue_t FixedOrderedMultimap::insert( + key_t key, T value, Iterator *storedValue) { + if (_size == theMap.maxSize()) { + return MAP_FULL; + } + uint32_t position = findNicePlace(key); + // Compiler might emitt warning because std::pair is not a POD type (yet..) + // See: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2342.htm#std::pair-example + // Circumvent warning by casting to void* + std::memmove(static_cast(&theMap[position + 1]), + static_cast(&theMap[position]), + (_size - position) * sizeof(std::pair)); + theMap[position].first = key; + theMap[position].second = value; + ++_size; + if (storedValue != nullptr) { + *storedValue = Iterator(&theMap[position]); + } + return HasReturnvaluesIF::RETURN_OK; +} + +template +inline ReturnValue_t FixedOrderedMultimap::insert( + std::pair pair) { + return insert(pair.fist, pair.second); +} + +template +inline ReturnValue_t FixedOrderedMultimap::exists( + key_t key) const { + ReturnValue_t result = KEY_DOES_NOT_EXIST; + if (findFirstIndex(key) < _size) { + result = HasReturnvaluesIF::RETURN_OK; + } + return result; +} + +template +inline ReturnValue_t FixedOrderedMultimap::erase( + Iterator *iter) +{ + uint32_t i; + if ((i = findFirstIndex((*iter).value->first)) >= _size) { + return KEY_DOES_NOT_EXIST; + } + removeFromPosition(i); + if (*iter != begin()) { + (*iter)--; + } else { + *iter = begin(); + } + return HasReturnvaluesIF::RETURN_OK; +} + +template +inline ReturnValue_t FixedOrderedMultimap::erase( + key_t key) +{ + uint32_t i; + if ((i = findFirstIndex(key)) >= _size) { + return KEY_DOES_NOT_EXIST; + } + do { + removeFromPosition(i); + i = findFirstIndex(key, i); + } while (i < _size); + return HasReturnvaluesIF::RETURN_OK; +} + +template +inline ReturnValue_t FixedOrderedMultimap::find( + key_t key, T **value) const +{ + ReturnValue_t result = exists(key); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + *value = &theMap[findFirstIndex(key)].second; + return HasReturnvaluesIF::RETURN_OK; +} + +template +inline typename FixedOrderedMultimap::Iterator +FixedOrderedMultimap::find( + key_t key) const +{ + ReturnValue_t result = exists(key); + if (result != HasReturnvaluesIF::RETURN_OK) { + return end(); + } + return Iterator(&theMap[findFirstIndex(key)]); +} + +template +inline void FixedOrderedMultimap::clear() +{ + _size = 0; +} + +template +inline size_t FixedOrderedMultimap::maxSize() const +{ + return theMap.maxSize(); +} + + +#endif /* FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_TPP_ */ From 587f87d270b282726363f348467f130370d61f96 Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Thu, 1 Oct 2020 17:27:24 +0200 Subject: [PATCH 099/101] Feedback from Robin --- container/FixedOrderedMultimap.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/container/FixedOrderedMultimap.h b/container/FixedOrderedMultimap.h index 4bbea302..82d388c9 100644 --- a/container/FixedOrderedMultimap.h +++ b/container/FixedOrderedMultimap.h @@ -5,7 +5,7 @@ #include /** - * @brief A "Map" which allows multiple entries of the same key. + * @brief An associative container which allows multiple entries of the same key. * @details * Same keys are ordered by KEY_COMPARE function which is std::less > by default. * From f1bc9972f3217981b895a6e48e9aca816340512c Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Thu, 1 Oct 2020 17:36:46 +0200 Subject: [PATCH 100/101] Fixed bugs --- container/FixedOrderedMultimap.tpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/container/FixedOrderedMultimap.tpp b/container/FixedOrderedMultimap.tpp index 715bf474..16a7124b 100644 --- a/container/FixedOrderedMultimap.tpp +++ b/container/FixedOrderedMultimap.tpp @@ -2,8 +2,8 @@ #define FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_TPP_ -template> -ReturnValue_t FixedOrderedMultimap::insert(key_t key, T value, Iterator *storedValue = nullptr) { +template +ReturnValue_t FixedOrderedMultimap::insert(key_t key, T value, Iterator *storedValue) { if (_size == theMap.maxSize()) { return MAP_FULL; } @@ -18,12 +18,12 @@ ReturnValue_t FixedOrderedMultimap::insert(key_t key, T v } return HasReturnvaluesIF::RETURN_OK; } -template> +template ReturnValue_t FixedOrderedMultimap::insert(std::pair pair) { return insert(pair.first, pair.second); } -template> +template ReturnValue_t FixedOrderedMultimap::exists(key_t key) const { ReturnValue_t result = KEY_DOES_NOT_EXIST; if (findFirstIndex(key) < _size) { @@ -32,7 +32,7 @@ ReturnValue_t FixedOrderedMultimap::exists(key_t key) con return result; } -template> +template ReturnValue_t FixedOrderedMultimap::erase(Iterator *iter) { size_t i; if ((i = findFirstIndex((*iter).value->first)) >= _size) { @@ -47,7 +47,7 @@ ReturnValue_t FixedOrderedMultimap::erase(Iterator *iter) return HasReturnvaluesIF::RETURN_OK; } -template> +template ReturnValue_t FixedOrderedMultimap::erase(key_t key) { size_t i; if ((i = findFirstIndex(key)) >= _size) { @@ -60,7 +60,7 @@ ReturnValue_t FixedOrderedMultimap::erase(key_t key) { return HasReturnvaluesIF::RETURN_OK; } -template> +template FixedOrderedMultimap::Iterator FixedOrderedMultimap::find(key_t key) const { ReturnValue_t result = exists(key); if (result != HasReturnvaluesIF::RETURN_OK) { @@ -69,7 +69,7 @@ FixedOrderedMultimap::Iterator FixedOrderedMultimap> +template ReturnValue_t FixedOrderedMultimap::find(key_t key, T **value) const { ReturnValue_t result = exists(key); if (result != HasReturnvaluesIF::RETURN_OK) { @@ -79,8 +79,8 @@ ReturnValue_t FixedOrderedMultimap::find(key_t key, T **v return HasReturnvaluesIF::RETURN_OK; } -template> -size_t FixedOrderedMultimap::findFirstIndex(key_t key, size_t startAt = 0) const { +template +size_t FixedOrderedMultimap::findFirstIndex(key_t key, size_t startAt) const { if (startAt >= _size) { return startAt + 1; } @@ -93,7 +93,7 @@ size_t FixedOrderedMultimap::findFirstIndex(key_t key, si return i; } -template> +template size_t FixedOrderedMultimap::findNicePlace(key_t key) const { size_t i = 0; for (i = 0; i < _size; ++i) { @@ -104,7 +104,7 @@ size_t FixedOrderedMultimap::findNicePlace(key_t key) con return i; } -template> +template void FixedOrderedMultimap::removeFromPosition(size_t position) { if (_size <= position) { return; From 6776ca86eb0df44f2580139c48f6f394b5e6a727 Mon Sep 17 00:00:00 2001 From: Steffen Gaisser Date: Thu, 1 Oct 2020 17:44:23 +0200 Subject: [PATCH 101/101] Made tpp file less cluttered and added inline qualifier --- container/FixedOrderedMultimap.h | 8 +++++++- container/FixedOrderedMultimap.tpp | 27 +++++++++------------------ 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/container/FixedOrderedMultimap.h b/container/FixedOrderedMultimap.h index 82d388c9..96bc0073 100644 --- a/container/FixedOrderedMultimap.h +++ b/container/FixedOrderedMultimap.h @@ -159,7 +159,13 @@ public: * @param key Key to search for * @return Iterator pointing to the first entry of key */ - Iterator find(key_t key) const; + Iterator find(key_t key) const{ + ReturnValue_t result = exists(key); + if (result != HasReturnvaluesIF::RETURN_OK) { + return end(); + } + return Iterator(&theMap[findFirstIndex(key)]); + }; /*** * Finds first entry of the given key and returns a diff --git a/container/FixedOrderedMultimap.tpp b/container/FixedOrderedMultimap.tpp index 16a7124b..4aa85e97 100644 --- a/container/FixedOrderedMultimap.tpp +++ b/container/FixedOrderedMultimap.tpp @@ -3,7 +3,7 @@ template -ReturnValue_t FixedOrderedMultimap::insert(key_t key, T value, Iterator *storedValue) { +inline ReturnValue_t FixedOrderedMultimap::insert(key_t key, T value, Iterator *storedValue) { if (_size == theMap.maxSize()) { return MAP_FULL; } @@ -19,12 +19,12 @@ ReturnValue_t FixedOrderedMultimap::insert(key_t key, T v return HasReturnvaluesIF::RETURN_OK; } template -ReturnValue_t FixedOrderedMultimap::insert(std::pair pair) { +inline ReturnValue_t FixedOrderedMultimap::insert(std::pair pair) { return insert(pair.first, pair.second); } template -ReturnValue_t FixedOrderedMultimap::exists(key_t key) const { +inline ReturnValue_t FixedOrderedMultimap::exists(key_t key) const { ReturnValue_t result = KEY_DOES_NOT_EXIST; if (findFirstIndex(key) < _size) { result = HasReturnvaluesIF::RETURN_OK; @@ -33,7 +33,7 @@ ReturnValue_t FixedOrderedMultimap::exists(key_t key) con } template -ReturnValue_t FixedOrderedMultimap::erase(Iterator *iter) { +inline ReturnValue_t FixedOrderedMultimap::erase(Iterator *iter) { size_t i; if ((i = findFirstIndex((*iter).value->first)) >= _size) { return KEY_DOES_NOT_EXIST; @@ -48,7 +48,7 @@ ReturnValue_t FixedOrderedMultimap::erase(Iterator *iter) } template -ReturnValue_t FixedOrderedMultimap::erase(key_t key) { +inline ReturnValue_t FixedOrderedMultimap::erase(key_t key) { size_t i; if ((i = findFirstIndex(key)) >= _size) { return KEY_DOES_NOT_EXIST; @@ -61,16 +61,7 @@ ReturnValue_t FixedOrderedMultimap::erase(key_t key) { } template -FixedOrderedMultimap::Iterator FixedOrderedMultimap::find(key_t key) const { - ReturnValue_t result = exists(key); - if (result != HasReturnvaluesIF::RETURN_OK) { - return end(); - } - return Iterator(&theMap[findFirstIndex(key)]); -} - -template -ReturnValue_t FixedOrderedMultimap::find(key_t key, T **value) const { +inline ReturnValue_t FixedOrderedMultimap::find(key_t key, T **value) const { ReturnValue_t result = exists(key); if (result != HasReturnvaluesIF::RETURN_OK) { return result; @@ -80,7 +71,7 @@ ReturnValue_t FixedOrderedMultimap::find(key_t key, T **v } template -size_t FixedOrderedMultimap::findFirstIndex(key_t key, size_t startAt) const { +inline size_t FixedOrderedMultimap::findFirstIndex(key_t key, size_t startAt) const { if (startAt >= _size) { return startAt + 1; } @@ -94,7 +85,7 @@ size_t FixedOrderedMultimap::findFirstIndex(key_t key, si } template -size_t FixedOrderedMultimap::findNicePlace(key_t key) const { +inline size_t FixedOrderedMultimap::findNicePlace(key_t key) const { size_t i = 0; for (i = 0; i < _size; ++i) { if (myComp(key, theMap[i].first)) { @@ -105,7 +96,7 @@ size_t FixedOrderedMultimap::findNicePlace(key_t key) con } template -void FixedOrderedMultimap::removeFromPosition(size_t position) { +inline void FixedOrderedMultimap::removeFromPosition(size_t position) { if (_size <= position) { return; }