Merge remote-tracking branch 'upstream/master' into mueller/MQM_IF_UpdateLinux

This commit is contained in:
Robin Müller 2020-09-29 15:20:32 +02:00
commit 4010d8d960
24 changed files with 752 additions and 250 deletions

View File

@ -97,8 +97,7 @@ public:
bool operator!=(const typename ArrayList<T, count_t>::Iterator& other) const { bool operator!=(const typename ArrayList<T, count_t>::Iterator& other) const {
return !(*this == other); return !(*this == other);
} }
} };
;
/** /**
* Number of Elements stored in this List * Number of Elements stored in this List

View File

@ -10,10 +10,9 @@
template<typename key_t, typename T, typename KEY_COMPARE = std::less<key_t>> template<typename key_t, typename T, typename KEY_COMPARE = std::less<key_t>>
class FixedOrderedMultimap { class FixedOrderedMultimap {
public: public:
static const uint8_t INTERFACE_ID = CLASS_ID::FIXED_MAP; static const uint8_t INTERFACE_ID = CLASS_ID::FIXED_MULTIMAP;
static const ReturnValue_t KEY_ALREADY_EXISTS = MAKE_RETURN_CODE(0x01); static const ReturnValue_t MAP_FULL = 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(0x02);
static const ReturnValue_t KEY_DOES_NOT_EXIST = MAKE_RETURN_CODE(0x03);
private: private:
typedef KEY_COMPARE compare; typedef KEY_COMPARE compare;

View File

@ -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 <cstddef>
FixedSequenceSlot::FixedSequenceSlot(object_id_t handlerId, uint32_t setTime,
int8_t setSequenceId, PeriodicTaskIF* executingTask) :
handler(NULL), pollingTimeMs(setTime), opcode(setSequenceId) {
handler = objectManager->get<ExecutableObjectIF>(handlerId);
handler->setTaskIF(executingTask);
}
FixedSequenceSlot::~FixedSequenceSlot() {}

View File

@ -2,6 +2,7 @@
#define FSFW_IPC_COMMANDMESSAGE_H_ #define FSFW_IPC_COMMANDMESSAGE_H_
#include "CommandMessageIF.h" #include "CommandMessageIF.h"
#include "MessageQueueMessage.h" #include "MessageQueueMessage.h"
#include "FwMessageTypes.h" #include "FwMessageTypes.h"

View File

@ -15,5 +15,4 @@
*/ */
using MessageQueueId_t = uint32_t; using MessageQueueId_t = uint32_t;
#endif /* FSFW_IPC_MESSAGEQUEUEDEFINITIONS_H_ */ #endif /* FSFW_IPC_MESSAGEQUEUEDEFINITIONS_H_ */

View File

@ -8,7 +8,7 @@ const size_t PeriodicTaskIF::MINIMUM_STACK_SIZE = configMINIMAL_STACK_SIZE;
FixedTimeslotTask::FixedTimeslotTask(TaskName name, TaskPriority setPriority, FixedTimeslotTask::FixedTimeslotTask(TaskName name, TaskPriority setPriority,
TaskStackSize setStack, TaskPeriod overallPeriod, TaskStackSize setStack, TaskPeriod overallPeriod,
void (*setDeadlineMissedFunc)()) : void (*setDeadlineMissedFunc)()) :
started(false), handle(NULL), pst(overallPeriod * 1000) { started(false), handle(nullptr), pst(overallPeriod * 1000) {
configSTACK_DEPTH_TYPE stackSize = setStack / sizeof(configSTACK_DEPTH_TYPE); configSTACK_DEPTH_TYPE stackSize = setStack / sizeof(configSTACK_DEPTH_TYPE);
xTaskCreate(taskEntryPoint, name, stackSize, this, setPriority, &handle); xTaskCreate(taskEntryPoint, name, stackSize, this, setPriority, &handle);
// All additional attributes are applied to the object. // All additional attributes are applied to the object.
@ -62,8 +62,10 @@ ReturnValue_t FixedTimeslotTask::startTask() {
ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId, ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId,
uint32_t slotTimeMs, int8_t executionStep) { uint32_t slotTimeMs, int8_t executionStep) {
if (objectManager->get<ExecutableObjectIF>(componentId) != nullptr) { ExecutableObjectIF* handler =
pst.addSlot(componentId, slotTimeMs, executionStep, this); objectManager->get<ExecutableObjectIF>(componentId);
if (handler != nullptr) {
pst.addSlot(componentId, slotTimeMs, executionStep, handler, this);
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
@ -85,6 +87,8 @@ void FixedTimeslotTask::taskFunctionality() {
// start time for the first entry. // start time for the first entry.
auto slotListIter = pst.current; auto slotListIter = pst.current;
pst.intializeSequenceAfterTaskCreation();
//The start time for the first entry is read. //The start time for the first entry is read.
uint32_t intervalMs = slotListIter->pollingTimeMs; uint32_t intervalMs = slotListIter->pollingTimeMs;
TickType_t interval = pdMS_TO_TICKS(intervalMs); TickType_t interval = pdMS_TO_TICKS(intervalMs);
@ -143,10 +147,6 @@ void FixedTimeslotTask::checkMissedDeadline(const TickType_t xLastWakeTime,
} }
void FixedTimeslotTask::handleMissedDeadline() { void FixedTimeslotTask::handleMissedDeadline() {
#ifdef DEBUG
sif::warning << "FixedTimeslotTask: " << pcTaskGetName(NULL) <<
" missed deadline!\n" << std::flush;
#endif
if(deadlineMissedFunc != nullptr) { if(deadlineMissedFunc != nullptr) {
this->deadlineMissedFunc(); this->deadlineMissedFunc();
} }

View File

@ -1,12 +1,11 @@
#ifndef FRAMEWORK_OSAL_FREERTOS_FIXEDTIMESLOTTASK_H_ #ifndef FSFW_OSAL_FREERTOS_FIXEDTIMESLOTTASK_H_
#define FRAMEWORK_OSAL_FREERTOS_FIXEDTIMESLOTTASK_H_ #define FSFW_OSAL_FREERTOS_FIXEDTIMESLOTTASK_H_
#include "FreeRTOSTaskIF.h" #include "FreeRTOSTaskIF.h"
#include "../../devicehandlers/FixedSlotSequence.h" #include "../../tasks/FixedSlotSequence.h"
#include "../../tasks/FixedTimeslotTaskIF.h" #include "../../tasks/FixedTimeslotTaskIF.h"
#include "../../tasks/Typedef.h" #include "../../tasks/Typedef.h"
#include <freertos/FreeRTOS.h> #include <freertos/FreeRTOS.h>
#include <freertos/task.h> #include <freertos/task.h>
@ -99,4 +98,4 @@ protected:
void handleMissedDeadline(); void handleMissedDeadline();
}; };
#endif /* FRAMEWORK_OSAL_FREERTOS_FIXEDTIMESLOTTASK_H_ */ #endif /* FSFW_OSAL_FREERTOS_FIXEDTIMESLOTTASK_H_ */

View File

@ -133,10 +133,6 @@ TaskHandle_t PeriodicTask::getTaskHandle() {
} }
void PeriodicTask::handleMissedDeadline() { void PeriodicTask::handleMissedDeadline() {
#ifdef DEBUG
sif::warning << "PeriodicTask: " << pcTaskGetName(NULL) <<
" missed deadline!\n" << std::flush;
#endif
if(deadlineMissedFunc != nullptr) { if(deadlineMissedFunc != nullptr) {
this->deadlineMissedFunc(); this->deadlineMissedFunc();
} }

View File

@ -1,5 +1,5 @@
#include "../../serviceinterface/ServiceInterfaceStream.h"
#include "FixedTimeslotTask.h" #include "FixedTimeslotTask.h"
#include "../../serviceinterface/ServiceInterfaceStream.h"
#include <limits.h> #include <limits.h>
@ -39,13 +39,16 @@ uint32_t FixedTimeslotTask::getPeriodMs() const {
ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId, ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId,
uint32_t slotTimeMs, int8_t executionStep) { uint32_t slotTimeMs, int8_t executionStep) {
if (objectManager->get<ExecutableObjectIF>(componentId) != nullptr) { ExecutableObjectIF* executableObject =
pst.addSlot(componentId, slotTimeMs, executionStep, this); objectManager->get<ExecutableObjectIF>(componentId);
if (executableObject != nullptr) {
pst.addSlot(componentId, slotTimeMs, executionStep,
executableObject,this);
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
sif::error << "Component " << std::hex << componentId << 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; return HasReturnvaluesIF::RETURN_FAILED;
} }
@ -58,6 +61,9 @@ void FixedTimeslotTask::taskFunctionality() {
if (!started) { if (!started) {
suspend(); suspend();
} }
pst.intializeSequenceAfterTaskCreation();
//The start time for the first entry is read. //The start time for the first entry is read.
uint64_t lastWakeTime = getCurrentMonotonicTimeMs(); uint64_t lastWakeTime = getCurrentMonotonicTimeMs();
uint64_t interval = pst.getIntervalToNextSlotMs(); uint64_t interval = pst.getIntervalToNextSlotMs();

View File

@ -1,9 +1,9 @@
#ifndef FRAMEWORK_OSAL_LINUX_FIXEDTIMESLOTTASK_H_ #ifndef FSFW_OSAL_LINUX_FIXEDTIMESLOTTASK_H_
#define FRAMEWORK_OSAL_LINUX_FIXEDTIMESLOTTASK_H_ #define FSFW_OSAL_LINUX_FIXEDTIMESLOTTASK_H_
#include "../../tasks/FixedTimeslotTaskIF.h"
#include "../../devicehandlers/FixedSlotSequence.h"
#include "PosixThread.h" #include "PosixThread.h"
#include "../../tasks/FixedTimeslotTaskIF.h"
#include "../../tasks/FixedSlotSequence.h"
#include <pthread.h> #include <pthread.h>
class FixedTimeslotTask: public FixedTimeslotTaskIF, public PosixThread { class FixedTimeslotTask: public FixedTimeslotTaskIF, public PosixThread {
@ -74,4 +74,4 @@ private:
bool started; bool started;
}; };
#endif /* FRAMEWORK_OSAL_LINUX_FIXEDTIMESLOTTASK_H_ */ #endif /* FSFW_OSAL_LINUX_FIXEDTIMESLOTTASK_H_ */

View File

@ -0,0 +1,88 @@
#include "ConstStorageAccessor.h"
#include "StorageManagerIF.h"
#include "../serviceinterface/ServiceInterfaceStream.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) {
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;
}

View File

@ -0,0 +1,116 @@
#ifndef FSFW_STORAGEMANAGER_CONSTSTORAGEACCESSOR_H_
#define FSFW_STORAGEMANAGER_CONSTSTORAGEACCESSOR_H_
#include "storeAddress.h"
#include "../returnvalues/HasReturnvaluesIF.h"
#include <cstddef>
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<uint8_t NUMBER_OF_POOLS>
friend class PoolManager;
template<uint8_t NUMBER_OF_POOLS>
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 /* FSFW_STORAGEMANAGER_CONSTSTORAGEACCESSOR_H_ */

View File

@ -1,18 +1,14 @@
/** #ifndef FSFW_STORAGEMANAGER_LOCALPOOL_H_
* @file LocalPool #define FSFW_STORAGEMANAGER_LOCALPOOL_H_
* @date 02.02.2012
* @author Bastian Baetz
* @brief This file contains the definition of the LocalPool class.
*/
#ifndef FRAMEWORK_STORAGEMANAGER_LOCALPOOL_H_
#define FRAMEWORK_STORAGEMANAGER_LOCALPOOL_H_
#include "../objectmanager/SystemObject.h"
#include "../serviceinterface/ServiceInterfaceStream.h"
#include "StorageManagerIF.h" #include "StorageManagerIF.h"
#include "../objectmanager/SystemObject.h"
#include "../objectmanager/ObjectManagerIF.h" #include "../objectmanager/ObjectManagerIF.h"
#include "../serviceinterface/ServiceInterfaceStream.h"
#include "../internalError/InternalErrorReporterIF.h" #include "../internalError/InternalErrorReporterIF.h"
#include <string.h> #include "../storagemanager/StorageAccessor.h"
#include <cstring>
/** /**
* @brief The LocalPool class provides an intermediate data storage with * @brief The LocalPool class provides an intermediate data storage with
@ -27,6 +23,7 @@
* 0xFFFF-1 bytes. * 0xFFFF-1 bytes.
* It is possible to store empty packets in the pool. * It is possible to store empty packets in the pool.
* The local pool is NOT thread-safe. * The local pool is NOT thread-safe.
* @author Bastian Baetz
*/ */
template<uint8_t NUMBER_OF_POOLS = 5> template<uint8_t NUMBER_OF_POOLS = 5>
class LocalPool: public SystemObject, public StorageManagerIF { class LocalPool: public SystemObject, public StorageManagerIF {
@ -39,7 +36,7 @@ public:
/** /**
* @brief This is the default constructor for a pool manager instance. * @brief This is the default constructor for a pool manager instance.
* @details By passing two arrays of size NUMBER_OF_POOLS, the constructor * @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. * regions are all set to zero on start up.
* @param setObjectId The object identifier to be set. This allows for * @param setObjectId The object identifier to be set. This allows for
* multiple instances of LocalPool in the system. * multiple instances of LocalPool in the system.
@ -73,10 +70,17 @@ public:
size_t size, bool ignoreFault = false) override; size_t size, bool ignoreFault = false) override;
ReturnValue_t getFreeElement(store_address_t* storageId,const size_t size, ReturnValue_t getFreeElement(store_address_t* storageId,const size_t size,
uint8_t** p_data, bool ignoreFault = false) override; 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, ReturnValue_t getData(store_address_t packet_id, const uint8_t** packet_ptr,
size_t * size) override; 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, ReturnValue_t modifyData(store_address_t packet_id, uint8_t** packet_ptr,
size_t * size) override; size_t * size) override;
virtual ReturnValue_t deleteData(store_address_t) override; virtual ReturnValue_t deleteData(store_address_t) override;
virtual ReturnValue_t deleteData(uint8_t* ptr, size_t size, virtual ReturnValue_t deleteData(uint8_t* ptr, size_t size,
store_address_t* storeId = NULL) override; store_address_t* storeId = NULL) override;
@ -84,7 +88,7 @@ public:
ReturnValue_t initialize() override; ReturnValue_t initialize() override;
protected: 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 size The minimum packet size that shall be reserved.
* @param[out] address Storage ID of the reserved data. * @param[out] address Storage ID of the reserved data.
* @return - #RETURN_OK on success, * @return - #RETURN_OK on success,
@ -97,7 +101,8 @@ protected:
private: private:
/** /**
* Indicates that this element is free. * 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; static const uint32_t STORAGE_FREE = 0xFFFFFFFF;
/** /**
@ -123,7 +128,9 @@ private:
* is also dynamically allocated there. * is also dynamically allocated there.
*/ */
uint32_t* size_list[NUMBER_OF_POOLS]; 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. * @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 * @details It also sets the size in size_list. The method does not perform
@ -180,4 +187,4 @@ private:
#include "LocalPool.tpp" #include "LocalPool.tpp"
#endif /* FRAMEWORK_STORAGEMANAGER_LOCALPOOL_H_ */ #endif /* FSFW_STORAGEMANAGER_LOCALPOOL_H_ */

View File

@ -1,5 +1,9 @@
#ifndef FRAMEWORK_STORAGEMANAGER_LOCALPOOL_TPP_ #ifndef FSFW_STORAGEMANAGER_LOCALPOOL_TPP_
#define FRAMEWORK_STORAGEMANAGER_LOCALPOOL_TPP_ #define FSFW_STORAGEMANAGER_LOCALPOOL_TPP_
#ifndef FSFW_STORAGEMANAGER_LOCALPOOL_H_
#error Include LocalPool.h before LocalPool.tpp!
#endif
template<uint8_t NUMBER_OF_POOLS> template<uint8_t NUMBER_OF_POOLS>
inline LocalPool<NUMBER_OF_POOLS>::LocalPool(object_id_t setObjectId, inline LocalPool<NUMBER_OF_POOLS>::LocalPool(object_id_t setObjectId,
@ -122,8 +126,9 @@ inline LocalPool<NUMBER_OF_POOLS>::~LocalPool(void) {
} }
template<uint8_t NUMBER_OF_POOLS> template<uint8_t NUMBER_OF_POOLS>
inline ReturnValue_t LocalPool<NUMBER_OF_POOLS>::addData(store_address_t* storageId, inline ReturnValue_t LocalPool<NUMBER_OF_POOLS>::addData(
const uint8_t* data, size_t size, bool ignoreFault) { store_address_t* storageId, const uint8_t* data, size_t size,
bool ignoreFault) {
ReturnValue_t status = reserveSpace(size, storageId, ignoreFault); ReturnValue_t status = reserveSpace(size, storageId, ignoreFault);
if (status == RETURN_OK) { if (status == RETURN_OK) {
write(*storageId, data, size); write(*storageId, data, size);
@ -144,15 +149,55 @@ inline ReturnValue_t LocalPool<NUMBER_OF_POOLS>::getFreeElement(
return status; return status;
} }
template<uint8_t NUMBER_OF_POOLS>
inline ConstAccessorPair LocalPool<NUMBER_OF_POOLS>::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<uint8_t NUMBER_OF_POOLS>
inline ReturnValue_t LocalPool<NUMBER_OF_POOLS>::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<uint8_t NUMBER_OF_POOLS> template<uint8_t NUMBER_OF_POOLS>
inline ReturnValue_t LocalPool<NUMBER_OF_POOLS>::getData( inline ReturnValue_t LocalPool<NUMBER_OF_POOLS>::getData(
store_address_t packet_id, const uint8_t** packet_ptr, size_t* size) { 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); ReturnValue_t status = modifyData(packet_id, &tempData, size);
*packet_ptr = tempData; *packet_ptr = tempData;
return status; return status;
} }
template<uint8_t NUMBER_OF_POOLS>
inline AccessorPair LocalPool<NUMBER_OF_POOLS>::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<uint8_t NUMBER_OF_POOLS>
inline ReturnValue_t LocalPool<NUMBER_OF_POOLS>::modifyData(
store_address_t storeId, StorageAccessor& storeAccessor) {
storeAccessor.assignStore(this);
ReturnValue_t status = modifyData(storeId, &storeAccessor.dataPointer,
&storeAccessor.size_);
storeAccessor.assignConstPointer();
return status;
}
template<uint8_t NUMBER_OF_POOLS> template<uint8_t NUMBER_OF_POOLS>
inline ReturnValue_t LocalPool<NUMBER_OF_POOLS>::modifyData( inline ReturnValue_t LocalPool<NUMBER_OF_POOLS>::modifyData(
store_address_t packet_id, uint8_t** packet_ptr, size_t* size) { store_address_t packet_id, uint8_t** packet_ptr, size_t* size) {
@ -242,8 +287,8 @@ inline ReturnValue_t LocalPool<NUMBER_OF_POOLS>::initialize() {
} }
internalErrorReporter = objectManager->get<InternalErrorReporterIF>( internalErrorReporter = objectManager->get<InternalErrorReporterIF>(
objects::INTERNAL_ERROR_REPORTER); objects::INTERNAL_ERROR_REPORTER);
if (internalErrorReporter == NULL){ if (internalErrorReporter == nullptr){
return RETURN_FAILED; return ObjectManagerIF::INTERNAL_ERR_REPORTER_UNINIT;
} }
//Check if any pool size is large than the maximum allowed. //Check if any pool size is large than the maximum allowed.
@ -251,10 +296,10 @@ inline ReturnValue_t LocalPool<NUMBER_OF_POOLS>::initialize() {
if (element_sizes[count] >= STORAGE_FREE) { if (element_sizes[count] >= STORAGE_FREE) {
sif::error << "LocalPool::initialize: Pool is too large! " sif::error << "LocalPool::initialize: Pool is too large! "
"Max. allowed size is: " << (STORAGE_FREE - 1) << std::endl; "Max. allowed size is: " << (STORAGE_FREE - 1) << std::endl;
return RETURN_FAILED; return StorageManagerIF::POOL_TOO_LARGE;
} }
} }
return RETURN_OK; return RETURN_OK;
} }
#endif #endif /* FSFW_STORAGEMANAGER_LOCALPOOL_TPP_ */

View File

@ -1,17 +1,18 @@
#ifndef POOLMANAGER_H_ #ifndef FSFW_STORAGEMANAGER_POOLMANAGER_H_
#define POOLMANAGER_H_ #define FSFW_STORAGEMANAGER_POOLMANAGER_H_
#include "LocalPool.h" #include "LocalPool.h"
#include "StorageAccessor.h"
#include "../ipc/MutexHelper.h" #include "../ipc/MutexHelper.h"
/** /**
* @brief The PoolManager class provides an intermediate data storage with * @brief The PoolManager class provides an intermediate data storage with
* a fixed pool size policy for inter-process communication. * a fixed pool size policy for inter-process communication.
* @details Uses local pool calls but is thread safe by protecting the call * @details Uses local pool calls but is thread safe by protecting the call
* with a lock. * with a lock.
* @author Bastian Baetz
*/ */
template <uint8_t NUMBER_OF_POOLS = 5> template <uint8_t NUMBER_OF_POOLS = 5>
class PoolManager : public LocalPool<NUMBER_OF_POOLS> { class PoolManager : public LocalPool<NUMBER_OF_POOLS> {
public: public:
@ -19,16 +20,25 @@ public:
const uint16_t element_sizes[NUMBER_OF_POOLS], const uint16_t element_sizes[NUMBER_OF_POOLS],
const uint16_t n_elements[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(); virtual ~PoolManager();
//! @brief LocalPool overrides for thread-safety. /**
* @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(store_address_t) override;
ReturnValue_t deleteData(uint8_t* buffer, size_t size, ReturnValue_t deleteData(uint8_t* buffer, size_t size,
store_address_t* storeId = NULL) override; store_address_t* storeId = nullptr) override;
ReturnValue_t modifyData(store_address_t packet_id, uint8_t** packet_ptr,
size_t* size) override; void setMutexTimeout(uint32_t mutexTimeoutMs);
protected: protected:
//! Default mutex timeout value to prevent permanent blocking.
uint32_t mutexTimeoutMs = 20;
ReturnValue_t reserveSpace(const uint32_t size, store_address_t* address, ReturnValue_t reserveSpace(const uint32_t size, store_address_t* address,
bool ignoreFault) override; bool ignoreFault) override;
@ -43,4 +53,4 @@ protected:
#include "PoolManager.tpp" #include "PoolManager.tpp"
#endif /* POOLMANAGER_H_ */ #endif /* FSFW_STORAGEMANAGER_POOLMANAGER_H_ */

View File

@ -1,6 +1,10 @@
#ifndef FRAMEWORK_STORAGEMANAGER_POOLMANAGER_TPP_ #ifndef FRAMEWORK_STORAGEMANAGER_POOLMANAGER_TPP_
#define FRAMEWORK_STORAGEMANAGER_POOLMANAGER_TPP_ #define FRAMEWORK_STORAGEMANAGER_POOLMANAGER_TPP_
#ifndef FSFW_STORAGEMANAGER_POOLMANAGER_H_
#error Include PoolManager.h before PoolManager.tpp!
#endif
template<uint8_t NUMBER_OF_POOLS> template<uint8_t NUMBER_OF_POOLS>
inline PoolManager<NUMBER_OF_POOLS>::PoolManager(object_id_t setObjectId, inline PoolManager<NUMBER_OF_POOLS>::PoolManager(object_id_t setObjectId,
const uint16_t element_sizes[NUMBER_OF_POOLS], const uint16_t element_sizes[NUMBER_OF_POOLS],
@ -17,7 +21,7 @@ inline PoolManager<NUMBER_OF_POOLS>::~PoolManager(void) {
template<uint8_t NUMBER_OF_POOLS> template<uint8_t NUMBER_OF_POOLS>
inline ReturnValue_t PoolManager<NUMBER_OF_POOLS>::reserveSpace( inline ReturnValue_t PoolManager<NUMBER_OF_POOLS>::reserveSpace(
const uint32_t size, store_address_t* address, bool ignoreFault) { 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<NUMBER_OF_POOLS>::reserveSpace(size, ReturnValue_t status = LocalPool<NUMBER_OF_POOLS>::reserveSpace(size,
address,ignoreFault); address,ignoreFault);
return status; return status;
@ -29,7 +33,7 @@ inline ReturnValue_t PoolManager<NUMBER_OF_POOLS>::deleteData(
// debug << "PoolManager( " << translateObject(getObjectId()) << // debug << "PoolManager( " << translateObject(getObjectId()) <<
// " )::deleteData from store " << packet_id.pool_index << // " )::deleteData from store " << packet_id.pool_index <<
// ". id is "<< packet_id.packet_index << std::endl; // ". id is "<< packet_id.packet_index << std::endl;
MutexHelper mutexHelper(mutex,MutexIF::BLOCKING); MutexHelper mutexHelper(mutex,MutexIF::WAITING, mutexTimeoutMs);
ReturnValue_t status = LocalPool<NUMBER_OF_POOLS>::deleteData(packet_id); ReturnValue_t status = LocalPool<NUMBER_OF_POOLS>::deleteData(packet_id);
return status; return status;
} }
@ -37,19 +41,16 @@ inline ReturnValue_t PoolManager<NUMBER_OF_POOLS>::deleteData(
template<uint8_t NUMBER_OF_POOLS> template<uint8_t NUMBER_OF_POOLS>
inline ReturnValue_t PoolManager<NUMBER_OF_POOLS>::deleteData(uint8_t* buffer, inline ReturnValue_t PoolManager<NUMBER_OF_POOLS>::deleteData(uint8_t* buffer,
size_t size, store_address_t* storeId) { size_t size, store_address_t* storeId) {
MutexHelper mutexHelper(mutex,MutexIF::BLOCKING); MutexHelper mutexHelper(mutex,MutexIF::WAITING, mutexTimeoutMs);
ReturnValue_t status = LocalPool<NUMBER_OF_POOLS>::deleteData(buffer, ReturnValue_t status = LocalPool<NUMBER_OF_POOLS>::deleteData(buffer,
size, storeId); size, storeId);
return status; return status;
} }
template<uint8_t NUMBER_OF_POOLS> template<uint8_t NUMBER_OF_POOLS>
inline ReturnValue_t PoolManager<NUMBER_OF_POOLS>::modifyData( inline void PoolManager<NUMBER_OF_POOLS>::setMutexTimeout(
store_address_t packet_id, uint8_t** packet_ptr, size_t* size) { uint32_t mutexTimeoutMs) {
MutexHelper mutexHelper(mutex,MutexIF::BLOCKING); this->mutexTimeout = mutexTimeoutMs;
ReturnValue_t status = LocalPool<NUMBER_OF_POOLS>::modifyData(packet_id,
packet_ptr, size);
return status;
} }
#endif #endif /* FRAMEWORK_STORAGEMANAGER_POOLMANAGER_TPP_ */

View File

@ -0,0 +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;
}

View File

@ -0,0 +1,45 @@
#ifndef FSFW_STORAGEMANAGER_STORAGEACCESSOR_H_
#define FSFW_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<uint8_t NUMBER_OF_POOLS>
friend class PoolManager;
template<uint8_t NUMBER_OF_POOLS>
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 /* FSFW_STORAGEMANAGER_STORAGEACCESSOR_H_ */

View File

@ -1,60 +1,17 @@
#ifndef STORAGEMANAGERIF_H_H #ifndef FSFW_STORAGEMANAGER_STORAGEMANAGERIF_H_
#define STORAGEMANAGERIF_H_H #define FSFW_STORAGEMANAGER_STORAGEMANAGERIF_H_
#include "StorageAccessor.h"
#include "storeAddress.h"
#include "../events/Event.h" #include "../events/Event.h"
#include "../returnvalues/HasReturnvaluesIF.h" #include "../returnvalues/HasReturnvaluesIF.h"
#include <stddef.h>
/** #include <utility>
* @brief This union defines the type that identifies where a data packet is #include <cstddef>
* stored in the store.
* It consists 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){}
/** using AccessorPair = std::pair<ReturnValue_t, StorageAccessor>;
* Constructor to create an address object using the raw address using ConstAccessorPair = std::pair<ReturnValue_t, ConstStorageAccessor>;
* @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;
}
};
/** /**
* @brief This class provides an interface for intermediate data storage. * @brief This class provides an interface for intermediate data storage.
@ -77,6 +34,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 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 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 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 uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::OBSW;
static const Event GET_DATA_FAILED = MAKE_EVENT(0, SEVERITY::LOW); static const Event GET_DATA_FAILED = MAKE_EVENT(0, SEVERITY::LOW);
@ -122,6 +80,29 @@ public:
*/ */
virtual ReturnValue_t deleteData(uint8_t* buffer, size_t size, virtual ReturnValue_t deleteData(uint8_t* buffer, size_t size,
store_address_t* storeId = nullptr) = 0; 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 * @brief getData returns an address to data and the size of the data
* for a given packet_id. * for a given packet_id.
@ -135,8 +116,30 @@ public:
*/ */
virtual ReturnValue_t getData(store_address_t packet_id, virtual ReturnValue_t getData(store_address_t packet_id,
const uint8_t** packet_ptr, size_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, virtual ReturnValue_t modifyData(store_address_t packet_id,
uint8_t** packet_ptr, size_t* size) = 0; uint8_t** packet_ptr, size_t* size) = 0;
@ -155,6 +158,7 @@ public:
*/ */
virtual ReturnValue_t getFreeElement(store_address_t* storageId, virtual ReturnValue_t getFreeElement(store_address_t* storageId,
const size_t size, uint8_t** p_data, bool ignoreFault = false ) = 0; const size_t size, uint8_t** p_data, bool ignoreFault = false ) = 0;
/** /**
* Clears the whole store. * Clears the whole store.
* Use with care! * Use with care!
@ -162,4 +166,4 @@ public:
virtual void clearStore() = 0; virtual void clearStore() = 0;
}; };
#endif /* STORAGEMANAGERIF_H_ */ #endif /* FSFW_STORAGEMANAGER_STORAGEMANAGERIF_H_ */

View File

@ -0,0 +1,55 @@
#ifndef FSFW_STORAGEMANAGER_STOREADDRESS_H_
#define FSFW_STORAGEMANAGER_STOREADDRESS_H_
#include <cstdint>
/**
* 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 /* FSFW_STORAGEMANAGER_STOREADDRESS_H_ */

View File

@ -0,0 +1,17 @@
#include "FixedSequenceSlot.h"
#include "PeriodicTaskIF.h"
#include <cstddef>
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() {}

View File

@ -1,39 +1,39 @@
/** #ifndef FSFW_TASKS_FIXEDSEQUENCESLOT_H_
* @file FixedSequenceSlot.h #define FSFW_TASKS_FIXEDSEQUENCESLOT_H_
* @brief This file defines the PollingSlot class.
* @date 19.12.2012
* @author baetz
*/
#ifndef FIXEDSEQUENCESLOT_H_
#define FIXEDSEQUENCESLOT_H_
#include "ExecutableObjectIF.h"
#include "../objectmanager/ObjectManagerIF.h" #include "../objectmanager/ObjectManagerIF.h"
#include "../tasks/ExecutableObjectIF.h"
class PeriodicTaskIF; class PeriodicTaskIF;
/** /**
* @brief This class is the representation of a single polling sequence table entry. * @brief This class is the representation of a single polling sequence
* * table entry.
* @details The PollingSlot class is the representation of a single polling * @details
* The PollingSlot class is the representation of a single polling
* sequence table entry. * sequence table entry.
* @author baetz
*/ */
class FixedSequenceSlot { class FixedSequenceSlot {
public: public:
FixedSequenceSlot( object_id_t handlerId, uint32_t setTimeMs, FixedSequenceSlot( object_id_t handlerId, uint32_t setTimeMs,
int8_t setSequenceId, PeriodicTaskIF* executingTask ); int8_t setSequenceId, ExecutableObjectIF* executableObject,
PeriodicTaskIF* executingTask);
virtual ~FixedSequenceSlot(); virtual ~FixedSequenceSlot();
object_id_t handlerId;
/** /**
* @brief Handler identifies which device handler object is executed in this slot. * @brief Handler identifies which object is executed in this slot.
*/ */
ExecutableObjectIF* handler; ExecutableObjectIF* executableObject = nullptr;
/** /**
* @brief This attribute defines when a device handler object is executed. * @brief This attribute defines when a device handler object is executed.
* * @details
* @details The pollingTime attribute identifies the time the handler is executed in ms. * The pollingTime attribute identifies the time the handler is
* It must be smaller than the period length of the polling sequence. * executed in ms. It must be smaller than the period length of the
* polling sequence.
*/ */
uint32_t pollingTimeMs; uint32_t pollingTimeMs;
@ -57,4 +57,4 @@ public:
}; };
#endif /* FIXEDSEQUENCESLOT_H_ */ #endif /* FSFW_TASKS_FIXEDSEQUENCESLOT_H_ */

View File

@ -1,5 +1,6 @@
#include "FixedSlotSequence.h" #include "FixedSlotSequence.h"
#include "../serviceinterface/ServiceInterfaceStream.h" #include "../serviceinterface/ServiceInterfaceStream.h"
#include <cstdlib>
FixedSlotSequence::FixedSlotSequence(uint32_t setLengthMs) : FixedSlotSequence::FixedSlotSequence(uint32_t setLengthMs) :
lengthMs(setLengthMs) { lengthMs(setLengthMs) {
@ -12,7 +13,7 @@ FixedSlotSequence::~FixedSlotSequence() {
} }
void FixedSlotSequence::executeAndAdvance() { void FixedSlotSequence::executeAndAdvance() {
current->handler->performOperation(current->opcode); current->executableObject->performOperation(current->opcode);
// if (returnValue != RETURN_OK) { // if (returnValue != RETURN_OK) {
// this->sendErrorMessage( returnValue ); // this->sendErrorMessage( returnValue );
// } // }
@ -80,44 +81,82 @@ uint32_t FixedSlotSequence::getLengthMs() const {
return this->lengthMs; 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 { ReturnValue_t FixedSlotSequence::checkSequence() const {
if(slotList.empty()) { 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; return HasReturnvaluesIF::RETURN_FAILED;
} }
auto slotIt = slotList.begin(); if(customCheckFunction != nullptr) {
uint32_t count = 0; 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; uint32_t time = 0;
while (slotIt != slotList.end()) { for(const auto& slot: slotList) {
if (slotIt->handler == nullptr) { if (slot.executableObject == nullptr) {
sif::error << "FixedSlotSequene::initialize: ObjectId does not exist!" errorCount++;
<< std::endl; }
count++; else if (slot.pollingTimeMs < time) {
} else if (slotIt->pollingTimeMs < time) { sif::error << "FixedSlotSequence::checkSequence: Time: "
sif::error << "FixedSlotSequence::initialize: Time: " << slot.pollingTimeMs << " is smaller than previous with "
<< slotIt->pollingTimeMs << time << std::endl;
<< " is smaller than previous with " << time << std::endl; errorCount++;
count++; }
} else { else {
// All ok, print slot. // All ok, print slot.
//info << "Current slot polling time: " << std::endl; //sif::info << "Current slot polling time: " << std::endl;
//info << std::dec << slotIt->pollingTimeMs << std::endl; //sif::info << std::dec << slotIt->pollingTimeMs << std::endl;
} }
time = slotIt->pollingTimeMs; time = slot.pollingTimeMs;
slotIt++;
} }
//info << "Number of elements in slot list: " //sif::info << "Number of elements in slot list: "
// << slotList.size() << std::endl; // << slotList.size() << std::endl;
if (count > 0) { if (errorCount > 0) {
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
void FixedSlotSequence::addSlot(object_id_t componentId, uint32_t slotTimeMs,
int8_t executionStep, PeriodicTaskIF* executingTask) { ReturnValue_t FixedSlotSequence::intializeSequenceAfterTaskCreation() const {
this->slotList.insert(FixedSequenceSlot(componentId, slotTimeMs, executionStep, std::set<ExecutableObjectIF*> uniqueObjects;
executingTask)); uint32_t count = 0;
this->current = slotList.begin(); 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;
}
void FixedSlotSequence::addCustomCheck(ReturnValue_t
(*customCheckFunction)(const SlotList&)) {
this->customCheckFunction = customCheckFunction;
} }

View File

@ -1,26 +1,30 @@
#ifndef FRAMEWORK_DEVICEHANDLERS_FIXEDSLOTSEQUENCE_H_ #ifndef FSFW_TASKS_FIXEDSLOTSEQUENCE_H_
#define FRAMEWORK_DEVICEHANDLERS_FIXEDSLOTSEQUENCE_H_ #define FSFW_TASKS_FIXEDSLOTSEQUENCE_H_
#include "FixedSequenceSlot.h" #include "FixedSequenceSlot.h"
#include "../objectmanager/SystemObject.h" #include "../objectmanager/SystemObject.h"
#include <set> #include <set>
/** /**
* @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 * @details
* The FixedSlotSequence object maintains the dynamic execution of * 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 * The main idea is to create a list of executable objects (for example
* handlers to thepolling sequence and to maintain a list of * device handlers), to announce all handlers to the polling sequence and to
* polling slot objects. This slot list represents the Polling Sequence Table * maintain a list of polling slot objects.
* in software. * This slot list represents the Polling Sequence Table in software.
* *
* Each polling slot contains information to indicate when and * Each polling slot contains information to indicate when and
* which device handler shall be executed within a given polling period. * which executable object shall be executed within a given polling period.
* The sequence is then executed by iterating through this slot list. * When adding a slot, a pointer to the executing task, a pointer to the
* Handlers are invoking by calling a certain function stored in the handler list. * 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 { class FixedSlotSequence {
public: public:
@ -29,41 +33,44 @@ public:
/** /**
* @brief The constructor of the FixedSlotSequence object. * @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. * @param setLength The period length, expressed in ms.
*/ */
FixedSlotSequence(uint32_t setLengthMs); FixedSlotSequence(uint32_t setLengthMs);
/** /**
* @brief The destructor of the FixedSlotSequence object. * @brief The destructor of the FixedSlotSequence object.
* * @details
* @details The destructor frees all allocated memory by iterating through the slotList * The destructor frees all allocated memory by iterating through the
* and deleting all allocated resources. * slotList and deleting all allocated resources.
*/ */
virtual ~FixedSlotSequence(); virtual ~FixedSlotSequence();
/** /**
* @brief This is a method to add an PollingSlot object to slotList. * @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 * @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. * to the end of the list. The list is currently NOT reordered.
* Afterwards, the iterator current is set to the beginning of the list. * Afterwards, the iterator current is set to the beginning of the list.
* @param Object ID of the object to add * @param handlerId ID of the object to add
* @param setTime Value between (0 to 1) * slotLengthMs, when a FixedTimeslotTask * @param setTime
* Value between (0 to 1) * slotLengthMs, when a FixedTimeslotTask
* will be called inside the slot period. * will be called inside the slot period.
* @param setSequenceId ID which can be used to distinguish * @param setSequenceId
* different task operations * ID which can be used to distinguish different task operations. This
* value will be passed to the executable function.
* @param * @param
* @param * @param
*/ */
void addSlot(object_id_t handlerId, uint32_t setTime, int8_t setSequenceId, void addSlot(object_id_t handlerId, uint32_t setTime, int8_t setSequenceId,
ExecutableObjectIF* executableObject,
PeriodicTaskIF* executingTask); PeriodicTaskIF* executingTask);
/** /**
* Checks if the current slot shall be executed immediately after the one before. * @brief Checks if the current slot shall be executed immediately
* This allows to distinguish between grouped and not grouped handlers. * 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 * @return - @c true if the slot has the same polling time as the previous
* - @c false else * - @c false else
*/ */
@ -125,12 +132,32 @@ public:
SlotListIter current; SlotListIter current;
/** /**
* Iterate through slotList and check successful creation. * @brief Check and initialize slot list.
* @details
* Checks if timing is ok (must be ascending) and if all handlers were found. * Checks if timing is ok (must be ascending) and if all handlers were found.
* @return * @return
*/ */
ReturnValue_t checkSequence() const; 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 &));
/**
* @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: protected:
/** /**
@ -146,7 +173,9 @@ protected:
*/ */
SlotList slotList; SlotList slotList;
ReturnValue_t (*customCheckFunction)(const SlotList&) = nullptr;
uint32_t lengthMs; uint32_t lengthMs;
}; };
#endif /* FIXEDSLOTSEQUENCE_H_ */ #endif /* FSFW_TASKS_FIXEDSLOTSEQUENCE_H_ */