From e26f0d54b2828e786c4d91ef38345a7e68d1fbcf Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Wed, 22 Apr 2020 19:44:03 +0200 Subject: [PATCH 01/34] binary semaphore init --- osal/FreeRTOS/BinarySemaphore.cpp | 152 ++++++++++++++++++++++++++++++ osal/FreeRTOS/BinarySemaphore.h | 130 +++++++++++++++++++++++++ 2 files changed, 282 insertions(+) create mode 100644 osal/FreeRTOS/BinarySemaphore.cpp create mode 100644 osal/FreeRTOS/BinarySemaphore.h diff --git a/osal/FreeRTOS/BinarySemaphore.cpp b/osal/FreeRTOS/BinarySemaphore.cpp new file mode 100644 index 00000000..b5f8e6c6 --- /dev/null +++ b/osal/FreeRTOS/BinarySemaphore.cpp @@ -0,0 +1,152 @@ +/** + * @file BinarySemaphore.cpp + * + * @date 25.02.2020 + */ +#include +#include + +#include + +extern "C" { +#include "portmacro.h" +#include "task.h" +} + +BinarySemaphore::BinarySemaphore() { + xSemaphoreCreateBinary(handle); + if(handle == nullptr) { + error << "Binary semaphore creation failure" << std::endl; + } +} + +BinarySemaphore::~BinarySemaphore() { + vSemaphoreDelete(handle); +} + +// This copy ctor is important as it prevents the assignment to a ressource +// (other.handle) variable which is later deleted! +BinarySemaphore::BinarySemaphore(const BinarySemaphore& other) { + xSemaphoreCreateBinary(handle); + if(handle == nullptr) { + error << "Binary semaphore creation failure" << std::endl; + } +} + +BinarySemaphore& BinarySemaphore::operator =(const BinarySemaphore& s) { + if(this != &s) { + xSemaphoreCreateBinary(handle); + if(handle == nullptr) { + error << "Binary semaphore creation failure" << std::endl; + } + } + return *this; +} + +BinarySemaphore::BinarySemaphore(BinarySemaphore&& s) { + xSemaphoreCreateBinary(handle); + if(handle == nullptr) { + error << "Binary semaphore creation failure" << std::endl; + } +} + +BinarySemaphore& BinarySemaphore::operator =( + BinarySemaphore&& s) { + if(&s != this) { + xSemaphoreCreateBinary(handle); + if(handle == nullptr) { + error << "Binary semaphore creation failure" << std::endl; + } + } + return *this; +} + +ReturnValue_t BinarySemaphore::takeBinarySemaphore(uint32_t timeoutMs) { + if(handle == nullptr) { + return SEMAPHORE_NULLPOINTER; + } + TickType_t timeout = BinarySemaphore::NO_BLOCK_TICKS; + if(timeoutMs == BinarySemaphore::BLOCK_TIMEOUT) { + timeout = BinarySemaphore::BLOCK_TIMEOUT_TICKS; + } + else if(timeoutMs > BinarySemaphore::NO_BLOCK_TIMEOUT){ + timeout = pdMS_TO_TICKS(timeoutMs); + } + + BaseType_t returncode = xSemaphoreTake(handle, timeout); + if (returncode == pdPASS) { + return HasReturnvaluesIF::RETURN_OK; + } + else { + return SEMAPHORE_TIMEOUT; + } +} + +ReturnValue_t BinarySemaphore::takeBinarySemaphoreTickTimeout( + TickType_t timeoutTicks) { + if(handle == nullptr) { + return SEMAPHORE_NULLPOINTER; + } + + BaseType_t returncode = xSemaphoreTake(handle, timeoutTicks); + if (returncode == pdPASS) { + return HasReturnvaluesIF::RETURN_OK; + } else { + return SEMAPHORE_TIMEOUT; + } +} + +ReturnValue_t BinarySemaphore::giveBinarySemaphore() { + if (handle == nullptr) { + return SEMAPHORE_NULLPOINTER; + } + BaseType_t returncode = xSemaphoreGive(handle); + if (returncode == pdPASS) { + return HasReturnvaluesIF::RETURN_OK; + } else { + return SEMAPHORE_NOT_OWNED; + } +} + +SemaphoreHandle_t BinarySemaphore::getSemaphore() { + return handle; +} + +ReturnValue_t BinarySemaphore::giveBinarySemaphore(SemaphoreHandle_t semaphore) { + if (semaphore == nullptr) { + return SEMAPHORE_NULLPOINTER; + } + BaseType_t returncode = xSemaphoreGive(semaphore); + if (returncode == pdPASS) { + return HasReturnvaluesIF::RETURN_OK; + } else { + return HasReturnvaluesIF::RETURN_FAILED; + } +} + +void BinarySemaphore::resetSemaphore() { + if(handle != nullptr) { + vSemaphoreDelete(handle); + xSemaphoreCreateBinary(handle); + } +} + + +// Be careful with the stack size here. This is called from an ISR! +ReturnValue_t BinarySemaphore::giveBinarySemaphoreFromISR(SemaphoreHandle_t semaphore, + BaseType_t * higherPriorityTaskWoken) { + if (semaphore == nullptr) { + return SEMAPHORE_NULLPOINTER; + } + BaseType_t returncode = xSemaphoreGiveFromISR(semaphore, higherPriorityTaskWoken); + if (returncode == pdPASS) { + if(*higherPriorityTaskWoken == pdPASS) { + // Request context switch because unblocking the semaphore + // caused a high priority task unblock. + TaskManagement::requestContextSwitch(CallContext::isr); + } + return HasReturnvaluesIF::RETURN_OK; + } else { + return SEMAPHORE_NOT_OWNED; + } +} diff --git a/osal/FreeRTOS/BinarySemaphore.h b/osal/FreeRTOS/BinarySemaphore.h new file mode 100644 index 00000000..2203c923 --- /dev/null +++ b/osal/FreeRTOS/BinarySemaphore.h @@ -0,0 +1,130 @@ +/** + * @file BinarySempahore.h + * + * @date 25.02.2020 + */ +#ifndef FRAMEWORK_OSAL_FREERTOS_BINARYSEMPAHORE_H_ +#define FRAMEWORK_OSAL_FREERTOS_BINARYSEMPAHORE_H_ + +#include + +extern "C" { +#include "FreeRTOS.h" +#include "semphr.h" +} + + +/** + * @brief OS Tool to achieve synchronization of between tasks or between task and ISR + * @details + * Documentation: https://www.freertos.org/Embedded-RTOS-Binary-Semaphores.html + * @ingroup osal + */ +class BinarySemaphore: public HasReturnvaluesIF { +public: + static const uint8_t INTERFACE_ID = CLASS_ID::SEMAPHORE_IF; + + //! No block time, poll the semaphore. Can also be used as tick type. + //! Can be passed as tick type and ms value. + static constexpr uint32_t NO_BLOCK_TIMEOUT = 0; + static constexpr TickType_t NO_BLOCK_TICKS = 0; + //! No block time, poll the semaphore. + //! Can be passed as tick type and ms value. + static constexpr TickType_t BLOCK_TIMEOUT_TICKS = portMAX_DELAY; + static constexpr uint32_t BLOCK_TIMEOUT = portMAX_DELAY; + + //! 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_NULLPOINTER = MAKE_RETURN_CODE(3); + + BinarySemaphore(); + + /** + * @brief Copy ctor + */ + BinarySemaphore(const BinarySemaphore&); + + /** + * @brief Copy assignment + */ + BinarySemaphore& operator=(const BinarySemaphore&); + + /** + * @brief Move constructor + */ + BinarySemaphore (BinarySemaphore &&); + + /** + * Move assignment + */ + BinarySemaphore & operator=(BinarySemaphore &&); + + /** + * Delete the binary semaphore to prevent a memory leak + */ + virtual ~BinarySemaphore(); + + /** + * 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 RETURN_FAILED on failure + */ + ReturnValue_t takeBinarySemaphore(uint32_t timeoutMs = + BinarySemaphore::NO_BLOCK_TIMEOUT); + + /** + * Same as lockBinarySemaphore() with timeout in FreeRTOS ticks. + * @param timeoutTicks + * @return - @c RETURN_OK on success + * - @c RETURN_FAILED on failure + */ + ReturnValue_t takeBinarySemaphoreTickTimeout(TickType_t timeoutTicks = + BinarySemaphore::NO_BLOCK_TICKS); + + /** + * Give back the binary semaphore + * @return - @c RETURN_OK on success + * - @c RETURN_FAILED on failure + */ + ReturnValue_t giveBinarySemaphore(); + + /** + * Get Handle to the semaphore. + * @return + */ + SemaphoreHandle_t getSemaphore(); + + /** + * Reset the semaphore. + */ + void resetSemaphore(); + + /** + * Wrapper function to give back semaphore from handle + * @param semaphore + * @return - @c RETURN_OK on success + * - @c RETURN_FAILED on failure + */ + static ReturnValue_t giveBinarySemaphore(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 + * @return - @c RETURN_OK on success + * - @c RETURN_FAILED on failure + */ + static ReturnValue_t giveBinarySemaphoreFromISR(SemaphoreHandle_t semaphore, + BaseType_t * higherPriorityTaskWoken); +private: + SemaphoreHandle_t handle; +}; + +#endif /* FRAMEWORK_OSAL_FREERTOS_BINARYSEMPAHORE_H_ */ From 6eda5a08381891907d67e3b23a93e80808585b07 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Wed, 22 Apr 2020 19:46:49 +0200 Subject: [PATCH 02/34] task management header added --- osal/FreeRTOS/TaskManagement.h | 38 ++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 osal/FreeRTOS/TaskManagement.h diff --git a/osal/FreeRTOS/TaskManagement.h b/osal/FreeRTOS/TaskManagement.h new file mode 100644 index 00000000..fd2bfc0b --- /dev/null +++ b/osal/FreeRTOS/TaskManagement.h @@ -0,0 +1,38 @@ +/** + * @file TaskManagement.h + * + * @date 26.02.2020 + */ + +#ifndef FRAMEWORK_OSAL_FREERTOS_TASKMANAGEMENT_H_ +#define FRAMEWORK_OSAL_FREERTOS_TASKMANAGEMENT_H_ + +/*! + * 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 CallContext { + task = 0x00,//!< task_context + isr = 0xFF //!< isr_context +}; + +class TaskManagement { +public: + /** + * 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 requestContextSwitchFromTask(void); +}; + +#endif /* FRAMEWORK_OSAL_FREERTOS_TASKMANAGEMENT_H_ */ From 1b5127dc85f236d7e02cdb22c722bea4976d531b Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Wed, 22 Apr 2020 19:50:07 +0200 Subject: [PATCH 03/34] added task management implementation --- osal/FreeRTOS/TaskManagement.cpp | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 osal/FreeRTOS/TaskManagement.cpp diff --git a/osal/FreeRTOS/TaskManagement.cpp b/osal/FreeRTOS/TaskManagement.cpp new file mode 100644 index 00000000..9946833d --- /dev/null +++ b/osal/FreeRTOS/TaskManagement.cpp @@ -0,0 +1,32 @@ +/** + * @file TaskManagement.cpp + * + * @date 26.02.2020 + * + */ +#include +#include +#include "portmacro.h" +#include "task.h" + +/** + * TODO: This stuff is hardware and architecture and mission dependant... + * Some FreeRTOS implementations might be able to determine their own task context for example. + * If not ISRs are used, or task preemption is enabled, some of this stuff might + * not be necessary anyway. Maybe there is a better solution? + */ +void TaskManagement::requestContextSwitchFromTask() { + 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 + portYIELD_FROM_ISR(); + } else { + requestContextSwitchFromTask(); + } +} + + + From 0e6f8d3f821d3fa6907de2310e9102a33d30afb2 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Wed, 22 Apr 2020 19:53:06 +0200 Subject: [PATCH 04/34] comment adapted --- osal/FreeRTOS/TaskManagement.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/osal/FreeRTOS/TaskManagement.cpp b/osal/FreeRTOS/TaskManagement.cpp index 9946833d..0c96c62f 100644 --- a/osal/FreeRTOS/TaskManagement.cpp +++ b/osal/FreeRTOS/TaskManagement.cpp @@ -5,15 +5,17 @@ * */ #include -#include + +extern "C" { +#include "FreeRTOS.h" #include "portmacro.h" #include "task.h" +} /** * TODO: This stuff is hardware and architecture and mission dependant... - * Some FreeRTOS implementations might be able to determine their own task context for example. - * If not ISRs are used, or task preemption is enabled, some of this stuff might - * not be necessary anyway. Maybe there is a better solution? + * Maybe there is a better solution? The request ContextSwitch function + * could be declared external for example. */ void TaskManagement::requestContextSwitchFromTask() { vTaskDelay(0); From 328737d0ad5d6efb098963fdf0e5088776f50f64 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 23 Apr 2020 18:12:02 +0200 Subject: [PATCH 05/34] newer non-deprecated semaphore call used --- osal/FreeRTOS/BinarySemaphore.cpp | 24 +++++++++++++----------- osal/FreeRTOS/BinarySemaphore.h | 8 ++++++-- 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/osal/FreeRTOS/BinarySemaphore.cpp b/osal/FreeRTOS/BinarySemaphore.cpp index b5f8e6c6..a6a923aa 100644 --- a/osal/FreeRTOS/BinarySemaphore.cpp +++ b/osal/FreeRTOS/BinarySemaphore.cpp @@ -8,16 +8,13 @@ #include -extern "C" { -#include "portmacro.h" -#include "task.h" -} - BinarySemaphore::BinarySemaphore() { - xSemaphoreCreateBinary(handle); + handle = xSemaphoreCreateBinary(); if(handle == nullptr) { + error << "Binary semaphore creation failure" << std::endl; } + xSemaphoreGive(handle); } BinarySemaphore::~BinarySemaphore() { @@ -27,36 +24,40 @@ BinarySemaphore::~BinarySemaphore() { // This copy ctor is important as it prevents the assignment to a ressource // (other.handle) variable which is later deleted! BinarySemaphore::BinarySemaphore(const BinarySemaphore& other) { - xSemaphoreCreateBinary(handle); + handle = xSemaphoreCreateBinary(); if(handle == nullptr) { error << "Binary semaphore creation failure" << std::endl; } + xSemaphoreGive(handle); } BinarySemaphore& BinarySemaphore::operator =(const BinarySemaphore& s) { if(this != &s) { - xSemaphoreCreateBinary(handle); + handle = xSemaphoreCreateBinary(); if(handle == nullptr) { error << "Binary semaphore creation failure" << std::endl; } + xSemaphoreGive(handle); } return *this; } BinarySemaphore::BinarySemaphore(BinarySemaphore&& s) { - xSemaphoreCreateBinary(handle); + handle = xSemaphoreCreateBinary(); if(handle == nullptr) { error << "Binary semaphore creation failure" << std::endl; } + xSemaphoreGive(handle); } BinarySemaphore& BinarySemaphore::operator =( BinarySemaphore&& s) { if(&s != this) { - xSemaphoreCreateBinary(handle); + handle = xSemaphoreCreateBinary(); if(handle == nullptr) { error << "Binary semaphore creation failure" << std::endl; } + xSemaphoreGive(handle); } return *this; } @@ -127,7 +128,8 @@ ReturnValue_t BinarySemaphore::giveBinarySemaphore(SemaphoreHandle_t semaphore) void BinarySemaphore::resetSemaphore() { if(handle != nullptr) { vSemaphoreDelete(handle); - xSemaphoreCreateBinary(handle); + handle = xSemaphoreCreateBinary(); + xSemaphoreGive(handle); } } diff --git a/osal/FreeRTOS/BinarySemaphore.h b/osal/FreeRTOS/BinarySemaphore.h index 2203c923..0ab9cdea 100644 --- a/osal/FreeRTOS/BinarySemaphore.h +++ b/osal/FreeRTOS/BinarySemaphore.h @@ -18,6 +18,10 @@ extern "C" { * @brief OS Tool to achieve synchronization of between tasks or between task and ISR * @details * Documentation: https://www.freertos.org/Embedded-RTOS-Binary-Semaphores.html + * + * SHOULDDO: check freeRTOS version and use new task notifications, + * if non-ancient freeRTOS version is used. + * * @ingroup osal */ class BinarySemaphore: public HasReturnvaluesIF { @@ -68,8 +72,8 @@ public: /** * 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, + * 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 From fc4199c3b12dfc6f7996d75c035fb0767c21a004 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Thu, 23 Apr 2020 18:13:14 +0200 Subject: [PATCH 06/34] architecture dependant call delcared external --- osal/FreeRTOS/TaskManagement.cpp | 8 +------- osal/FreeRTOS/TaskManagement.h | 7 +++++++ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/osal/FreeRTOS/TaskManagement.cpp b/osal/FreeRTOS/TaskManagement.cpp index 0c96c62f..d7ddaf38 100644 --- a/osal/FreeRTOS/TaskManagement.cpp +++ b/osal/FreeRTOS/TaskManagement.cpp @@ -8,15 +8,9 @@ extern "C" { #include "FreeRTOS.h" -#include "portmacro.h" #include "task.h" } -/** - * TODO: This stuff is hardware and architecture and mission dependant... - * Maybe there is a better solution? The request ContextSwitch function - * could be declared external for example. - */ void TaskManagement::requestContextSwitchFromTask() { vTaskDelay(0); } @@ -24,7 +18,7 @@ void TaskManagement::requestContextSwitchFromTask() { void TaskManagement::requestContextSwitch(CallContext callContext = CallContext::task) { if(callContext == CallContext::isr) { // This function depends on the partmacro.h definition for the specific device - portYIELD_FROM_ISR(); + requestContextSwitchFromISR(); } else { requestContextSwitchFromTask(); } diff --git a/osal/FreeRTOS/TaskManagement.h b/osal/FreeRTOS/TaskManagement.h index fd2bfc0b..c122e0fb 100644 --- a/osal/FreeRTOS/TaskManagement.h +++ b/osal/FreeRTOS/TaskManagement.h @@ -7,6 +7,12 @@ #ifndef FRAMEWORK_OSAL_FREERTOS_TASKMANAGEMENT_H_ #define FRAMEWORK_OSAL_FREERTOS_TASKMANAGEMENT_H_ +/** + * Architecture dependant portmacro.h function call. + * Should be implemented in bsp. + */ +extern "C" void requestContextSwitchFromISR(); + /*! * Used by functions to tell if they are being called from * within an ISR or from a regular task. This is required because FreeRTOS @@ -18,6 +24,7 @@ enum CallContext { isr = 0xFF //!< isr_context }; + class TaskManagement { public: /** From d44a06fafc1a63ec38354438910b556e0f1c6b81 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Sun, 10 May 2020 12:48:22 +0200 Subject: [PATCH 07/34] removed cfg include --- objectmanager/ObjectManagerIF.h | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/objectmanager/ObjectManagerIF.h b/objectmanager/ObjectManagerIF.h index 1d7674c6..3575fc16 100644 --- a/objectmanager/ObjectManagerIF.h +++ b/objectmanager/ObjectManagerIF.h @@ -9,9 +9,9 @@ #define OBJECTMANAGERIF_H_ #include -#include #include #include +#include /** * @brief This class provides an interface to the global object manager. @@ -24,9 +24,12 @@ */ 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 @@ -79,16 +82,21 @@ public: }; -/*Documentation can be found in the class method declaration above.*/ -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 ebcc4742a92c6aa2152aa7cc8953a587f05fec5b Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 15 May 2020 21:14:21 +0200 Subject: [PATCH 08/34] removed conflict markers --- osal/FreeRTOS/FixedTimeslotTask.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/osal/FreeRTOS/FixedTimeslotTask.cpp b/osal/FreeRTOS/FixedTimeslotTask.cpp index 932bbe8a..18ec1092 100644 --- a/osal/FreeRTOS/FixedTimeslotTask.cpp +++ b/osal/FreeRTOS/FixedTimeslotTask.cpp @@ -57,10 +57,6 @@ ReturnValue_t FixedTimeslotTask::startTask() { ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId, uint32_t slotTimeMs, int8_t executionStep) { -<<<<<<< HEAD -======= - ->>>>>>> mueller_framework if (objectManager->get(componentId) != nullptr) { if(slotTimeMs == 0) { // FreeRTOS throws a sanity error for zero values, so we set From 7e04c055b353b1cfe6817a2cc2e0fbbca4db631e Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 18 May 2020 16:13:46 +0200 Subject: [PATCH 09/34] tc packet stored formatting --- tmtcpacket/pus/TcPacketStored.cpp | 10 +++++----- tmtcpacket/pus/TcPacketStored.h | 4 +++- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/tmtcpacket/pus/TcPacketStored.cpp b/tmtcpacket/pus/TcPacketStored.cpp index 0187b08f..6a4d03be 100644 --- a/tmtcpacket/pus/TcPacketStored.cpp +++ b/tmtcpacket/pus/TcPacketStored.cpp @@ -1,22 +1,22 @@ #include #include #include -#include +#include TcPacketStored::TcPacketStored(store_address_t setAddress) : - TcPacketBase(NULL), storeAddress(setAddress) { + TcPacketBase(nullptr), storeAddress(setAddress) { this->setStoreAddress(this->storeAddress); } TcPacketStored::TcPacketStored(uint16_t apid, uint8_t ack, uint8_t service, uint8_t subservice, uint8_t sequence_count, const uint8_t* data, - uint32_t size) : - TcPacketBase(NULL) { + size_t size) : + TcPacketBase(nullptr) { this->storeAddress.raw = StorageManagerIF::INVALID_ADDRESS; if (!this->checkAndSetStore()) { return; } - uint8_t* p_data = NULL; + uint8_t* p_data = nullptr; ReturnValue_t returnValue = this->store->getFreeElement(&this->storeAddress, (TC_PACKET_MIN_SIZE + size), &p_data); if (returnValue != this->store->RETURN_OK) { diff --git a/tmtcpacket/pus/TcPacketStored.h b/tmtcpacket/pus/TcPacketStored.h index c57f0e0f..50639788 100644 --- a/tmtcpacket/pus/TcPacketStored.h +++ b/tmtcpacket/pus/TcPacketStored.h @@ -64,7 +64,9 @@ public: * @param data The data to be copied to the Application Data Field. * @param size The amount of data to be copied. */ - TcPacketStored( uint16_t apid, uint8_t ack, uint8_t service, uint8_t subservice, uint8_t sequence_count = 0, const uint8_t* data = NULL, uint32_t size = 0 ); + TcPacketStored( uint16_t apid, uint8_t ack, uint8_t service, + uint8_t subservice, uint8_t sequence_count = 0, + const uint8_t* data = nullptr, size_t size = 0 ); /** * Another constructor to create a TcPacket from a raw packet stream. * Takes the data and adds it unchecked to the TcStore. From b12bace3857588cfca51e0b0c8df37fec0d6c31a Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 18 May 2020 16:40:11 +0200 Subject: [PATCH 10/34] changed order of input arguments (relevance) default argument for ACK --- tmtcpacket/pus/TcPacketStored.cpp | 6 +++--- tmtcpacket/pus/TcPacketStored.h | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tmtcpacket/pus/TcPacketStored.cpp b/tmtcpacket/pus/TcPacketStored.cpp index 6a4d03be..57b90bcc 100644 --- a/tmtcpacket/pus/TcPacketStored.cpp +++ b/tmtcpacket/pus/TcPacketStored.cpp @@ -8,9 +8,9 @@ TcPacketStored::TcPacketStored(store_address_t setAddress) : this->setStoreAddress(this->storeAddress); } -TcPacketStored::TcPacketStored(uint16_t apid, uint8_t ack, uint8_t service, - uint8_t subservice, uint8_t sequence_count, const uint8_t* data, - size_t size) : +TcPacketStored::TcPacketStored(uint8_t service, uint8_t subservice, + uint16_t apid, uint8_t sequence_count, const uint8_t* data, + size_t size, uint8_t ack ) : TcPacketBase(nullptr) { this->storeAddress.raw = StorageManagerIF::INVALID_ADDRESS; if (!this->checkAndSetStore()) { diff --git a/tmtcpacket/pus/TcPacketStored.h b/tmtcpacket/pus/TcPacketStored.h index 50639788..a9c49c2e 100644 --- a/tmtcpacket/pus/TcPacketStored.h +++ b/tmtcpacket/pus/TcPacketStored.h @@ -64,9 +64,9 @@ public: * @param data The data to be copied to the Application Data Field. * @param size The amount of data to be copied. */ - TcPacketStored( uint16_t apid, uint8_t ack, uint8_t service, - uint8_t subservice, uint8_t sequence_count = 0, - const uint8_t* data = nullptr, size_t size = 0 ); + TcPacketStored( uint8_t service, uint8_t subservice, uint16_t apid, + uint8_t sequence_count = 0, const uint8_t* data = nullptr, + size_t size = 0, uint8_t ack = TcPacketBase::ACK_ALL ); /** * Another constructor to create a TcPacket from a raw packet stream. * Takes the data and adds it unchecked to the TcStore. From 1d4d01d1906d1300eb7fe4e65d259afe64210a81 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 18 May 2020 17:22:10 +0200 Subject: [PATCH 11/34] Added ISR calls for MQ and task mgmt The task management defines an external function which implements a context switch call from an ISR --- osal/FreeRTOS/MessageQueue.cpp | 95 ++++++++++++++++++++------------ osal/FreeRTOS/MessageQueue.h | 75 +++++++++++++++++-------- osal/FreeRTOS/TaskManagement.cpp | 24 ++++++++ osal/FreeRTOS/TaskManagement.h | 63 +++++++++++++++++++++ 4 files changed, 199 insertions(+), 58 deletions(-) create mode 100644 osal/FreeRTOS/TaskManagement.cpp create mode 100644 osal/FreeRTOS/TaskManagement.h diff --git a/osal/FreeRTOS/MessageQueue.cpp b/osal/FreeRTOS/MessageQueue.cpp index e5da0442..38f425a4 100644 --- a/osal/FreeRTOS/MessageQueue.cpp +++ b/osal/FreeRTOS/MessageQueue.cpp @@ -2,11 +2,14 @@ #include -// 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 - -MessageQueue::MessageQueue(size_t message_depth, size_t max_message_size) : -defaultDestination(0),lastPartner(0) { - handle = xQueueCreate(message_depth, max_message_size); +// 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 +// As a first step towards this, introduces system context variable which needs +// to be switched manually +// Haven't found function to find system context. +MessageQueue::MessageQueue(size_t messageDepth, size_t maxMessageSize) : +defaultDestination(0),lastPartner(0), callContext(CallContext::task) { + handle = xQueueCreate(messageDepth, maxMessageSize); if (handle == NULL) { sif::error << "MessageQueue creation failed" << std::endl; } @@ -18,6 +21,10 @@ MessageQueue::~MessageQueue() { } } +void MessageQueue::switchSystemContext(CallContext callContext) { + this->callContext = callContext; +} + ReturnValue_t MessageQueue::sendMessage(MessageQueueId_t sendTo, MessageQueueMessage* message, bool ignoreFault) { return sendMessageFrom(sendTo, message, this->getId(), ignoreFault); @@ -27,6 +34,11 @@ ReturnValue_t MessageQueue::sendToDefault(MessageQueueMessage* message) { return sendToDefaultFrom(message, this->getId()); } +ReturnValue_t MessageQueue::sendToDefaultFrom(MessageQueueMessage* message, + MessageQueueId_t sentFrom, bool ignoreFault) { + return sendMessageFrom(defaultDestination,message,sentFrom,ignoreFault); +} + ReturnValue_t MessageQueue::reply(MessageQueueMessage* message) { if (this->lastPartner != 0) { return sendMessageFrom(this->lastPartner, message, this->getId()); @@ -35,6 +47,27 @@ ReturnValue_t MessageQueue::reply(MessageQueueMessage* message) { } } +ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo, + MessageQueueMessage* message, MessageQueueId_t sentFrom, + bool ignoreFault) { + return sendMessageFromMessageQueue(sendTo,message,sentFrom,ignoreFault, callContext); +} + + +ReturnValue_t MessageQueue::handleSendResult(BaseType_t result, bool ignoreFault) { + if (result != pdPASS) { + if (!ignoreFault) { + InternalErrorReporterIF* internalErrorReporter = objectManager->get( + objects::INTERNAL_ERROR_REPORTER); + if (internalErrorReporter != NULL) { + internalErrorReporter->queueMessageNotSent(); + } + } + return MessageQueueIF::FULL; + } + return HasReturnvaluesIF::RETURN_OK; +} + ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessage* message, MessageQueueId_t* receivedFrom) { ReturnValue_t status = this->receiveMessage(message); @@ -73,17 +106,6 @@ void MessageQueue::setDefaultDestination(MessageQueueId_t defaultDestination) { this->defaultDestination = defaultDestination; } -ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo, - MessageQueueMessage* message, MessageQueueId_t sentFrom, - bool ignoreFault) { - return sendMessageFromMessageQueue(sendTo,message,sentFrom,ignoreFault); -} - -ReturnValue_t MessageQueue::sendToDefaultFrom(MessageQueueMessage* message, - MessageQueueId_t sentFrom, bool ignoreFault) { - return sendMessageFrom(defaultDestination,message,sentFrom,ignoreFault); -} - MessageQueueId_t MessageQueue::getDefaultDestination() const { return defaultDestination; } @@ -92,23 +114,28 @@ bool MessageQueue::isDefaultDestinationSet() const { return 0; } + +// static core function to send messages. ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo, - MessageQueueMessage *message, MessageQueueId_t sentFrom, - bool ignoreFault) { - message->setSender(sentFrom); - - BaseType_t result = xQueueSendToBack(reinterpret_cast(sendTo),reinterpret_cast(message->getBuffer()), 0); - if (result != pdPASS) { - if (!ignoreFault) { - InternalErrorReporterIF* internalErrorReporter = objectManager->get( - objects::INTERNAL_ERROR_REPORTER); - if (internalErrorReporter != NULL) { - internalErrorReporter->queueMessageNotSent(); - } - } - return MessageQueueIF::FULL; - } - return HasReturnvaluesIF::RETURN_OK; - + MessageQueueMessage *message, MessageQueueId_t sentFrom, + bool ignoreFault, CallContext callContext) { + message->setSender(sentFrom); + BaseType_t result; + if(callContext == CallContext::task) { + result = xQueueSendToBack(reinterpret_cast(sendTo), + static_cast(message->getBuffer()), 0); + } + else { + // If the call context is from an interrupt, + // request a context switch if a higher priority task + // was blocked by the interrupt. + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + result = xQueueSendFromISR(reinterpret_cast(sendTo), + static_cast(message->getBuffer()), + &xHigherPriorityTaskWoken); + if(xHigherPriorityTaskWoken == pdTRUE) { + TaskManagement::requestContextSwitch(callContext); + } + } + return handleSendResult(result, ignoreFault); } - diff --git a/osal/FreeRTOS/MessageQueue.h b/osal/FreeRTOS/MessageQueue.h index 32f41b44..ce6ed46b 100644 --- a/osal/FreeRTOS/MessageQueue.h +++ b/osal/FreeRTOS/MessageQueue.h @@ -4,9 +4,14 @@ #include #include #include +#include + +extern "C" { +#include +#include +} + -#include -#include //TODO this class assumes that MessageQueueId_t is the same size as void* (the FreeRTOS handle type), compiler will catch this but it might be nice to have something checking or even an always working solution // https://scaryreasoner.wordpress.com/2009/02/28/checking-sizeof-at-compile-time/ @@ -21,11 +26,17 @@ * methods to send a message to a user-defined or a default destination. In addition * it also provides a reply method to answer to the queue it received its last message * from. + * * The MessageQueue should be used as "post box" for a single owning object. So all * message queue communication is "n-to-one". * For creating the queue, as well as sending and receiving messages, the class makes * use of the operating system calls provided. - * \ingroup message_queue + * + * Please keep in mind that FreeRTOS offers + * different calls for message queue operations if called from an ISR. + * For now, the system context needs to be switched manually. + * @ingroup osal + * @ingroup message_queue */ class MessageQueue : public MessageQueueIF { friend class MessageQueueSenderIF; @@ -43,11 +54,15 @@ public: * This should be left default. */ MessageQueue( size_t message_depth = 3, size_t max_message_size = MessageQueueMessage::MAX_MESSAGE_SIZE ); + /** * @brief The destructor deletes the formerly created message queue. * @details This is accomplished by using the delete call provided by the operating system. */ virtual ~MessageQueue(); + + void switchSystemContext(CallContext callContext); + /** * @brief This operation sends a message to the given destination. * @details It directly uses the sendMessage call of the MessageQueueSender parent, but passes its @@ -74,6 +89,29 @@ public: */ ReturnValue_t reply( MessageQueueMessage* message ); + /** + * \brief With the sendMessage call, a queue message is sent to a receiving queue. + * \details This method takes the message provided, adds the sentFrom information and passes + * it on to the destination provided with an operating system call. The OS's return + * value is returned. + * \param sendTo This parameter specifies the message queue id to send the message to. + * \param message This is a pointer to a previously created message, which is sent. + * \param sentFrom The sentFrom information can be set to inject the sender's queue id into the message. + * This variable is set to zero by default. + * \param ignoreFault If set to true, the internal software fault counter is not incremented if queue is full. + */ + virtual ReturnValue_t sendMessageFrom( MessageQueueId_t sendTo, MessageQueueMessage* message, + MessageQueueId_t sentFrom = NO_QUEUE, bool ignoreFault = false ); + + /** + * \brief The sendToDefault method sends a queue message to the default destination. + * \details In all other aspects, it works identical to the sendMessage method. + * \param message This is a pointer to a previously created message, which is sent. + * \param sentFrom The sentFrom information can be set to inject the sender's queue id into the message. + * This variable is set to zero by default. + */ + virtual ReturnValue_t sendToDefaultFrom( MessageQueueMessage* message, MessageQueueId_t sentFrom = NO_QUEUE, bool ignoreFault = false ); + /** * @brief This function reads available messages from the message queue and returns the sender. * @details It works identically to the other receiveMessage call, but in addition returns the @@ -107,26 +145,7 @@ public: * @brief This method returns the message queue id of this class's message queue. */ MessageQueueId_t getId() const; - /** - * \brief With the sendMessage call, a queue message is sent to a receiving queue. - * \details This method takes the message provided, adds the sentFrom information and passes - * it on to the destination provided with an operating system call. The OS's return - * value is returned. - * \param sendTo This parameter specifies the message queue id to send the message to. - * \param message This is a pointer to a previously created message, which is sent. - * \param sentFrom The sentFrom information can be set to inject the sender's queue id into the message. - * This variable is set to zero by default. - * \param ignoreFault If set to true, the internal software fault counter is not incremented if queue is full. - */ - virtual ReturnValue_t sendMessageFrom( MessageQueueId_t sendTo, MessageQueueMessage* message, MessageQueueId_t sentFrom = NO_QUEUE, bool ignoreFault = false ); - /** - * \brief The sendToDefault method sends a queue message to the default destination. - * \details In all other aspects, it works identical to the sendMessage method. - * \param message This is a pointer to a previously created message, which is sent. - * \param sentFrom The sentFrom information can be set to inject the sender's queue id into the message. - * This variable is set to zero by default. - */ - virtual ReturnValue_t sendToDefaultFrom( MessageQueueMessage* message, MessageQueueId_t sentFrom = NO_QUEUE, bool ignoreFault = false ); + /** * \brief This method is a simple setter for the default destination. */ @@ -148,12 +167,20 @@ protected: * \param sentFrom The sentFrom information can be set to inject the sender's queue id into the message. * This variable is set to zero by default. * \param ignoreFault If set to true, the internal software fault counter is not incremented if queue is full. + * \param context */ - static ReturnValue_t sendMessageFromMessageQueue(MessageQueueId_t sendTo,MessageQueueMessage* message, MessageQueueId_t sentFrom = NO_QUEUE,bool ignoreFault=false); + static ReturnValue_t sendMessageFromMessageQueue(MessageQueueId_t sendTo, + MessageQueueMessage* message, MessageQueueId_t sentFrom = NO_QUEUE, + bool ignoreFault=false, CallContext callContext = CallContext::task); + + static ReturnValue_t handleSendResult(BaseType_t result, bool ignoreFault); + + private: QueueHandle_t handle; MessageQueueId_t defaultDestination; MessageQueueId_t lastPartner; + CallContext callContext; //!< Stores the current system context }; #endif /* MESSAGEQUEUE_H_ */ diff --git a/osal/FreeRTOS/TaskManagement.cpp b/osal/FreeRTOS/TaskManagement.cpp new file mode 100644 index 00000000..52222531 --- /dev/null +++ b/osal/FreeRTOS/TaskManagement.cpp @@ -0,0 +1,24 @@ +#include + +void TaskManagement::requestContextSwitchFromTask() { + 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 + requestContextSwitchFromISR(); + } else { + requestContextSwitchFromTask(); + } +} + +TaskHandle_t TaskManagement::getCurrentTaskHandle() { + return xTaskGetCurrentTaskHandle(); +} + +configSTACK_DEPTH_TYPE TaskManagement::getTaskStackHighWatermark() { + return uxTaskGetStackHighWaterMark(TaskManagement::getCurrentTaskHandle()); +} + + diff --git a/osal/FreeRTOS/TaskManagement.h b/osal/FreeRTOS/TaskManagement.h new file mode 100644 index 00000000..eaaf97e2 --- /dev/null +++ b/osal/FreeRTOS/TaskManagement.h @@ -0,0 +1,63 @@ +#ifndef FRAMEWORK_OSAL_FREERTOS_TASKMANAGEMENT_H_ +#define FRAMEWORK_OSAL_FREERTOS_TASKMANAGEMENT_H_ + +#include + +extern "C" { +#include +#include +} +#include + +/** + * Architecture dependant portmacro.h function call. + * Should be implemented in bsp. + */ +extern "C" void requestContextSwitchFromISR(); + +/*! + * 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 CallContext { + task = 0x00,//!< task_context + isr = 0xFF //!< isr_context +}; + + +class TaskManagement { +public: + /** + * 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 requestContextSwitchFromTask(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 configSTACK_DEPTH_TYPE getTaskStackHighWatermark(); +}; + +#endif /* FRAMEWORK_OSAL_FREERTOS_TASKMANAGEMENT_H_ */ From d1500a78685d18e05b94419be69f9cb09056c127 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 18 May 2020 17:31:05 +0200 Subject: [PATCH 12/34] mq doc improvements --- osal/FreeRTOS/MessageQueue.cpp | 9 ++- osal/FreeRTOS/MessageQueue.h | 120 ++++++++++++++++++--------------- 2 files changed, 72 insertions(+), 57 deletions(-) diff --git a/osal/FreeRTOS/MessageQueue.cpp b/osal/FreeRTOS/MessageQueue.cpp index 38f425a4..12a3173a 100644 --- a/osal/FreeRTOS/MessageQueue.cpp +++ b/osal/FreeRTOS/MessageQueue.cpp @@ -50,14 +50,16 @@ ReturnValue_t MessageQueue::reply(MessageQueueMessage* message) { ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessage* message, MessageQueueId_t sentFrom, bool ignoreFault) { - return sendMessageFromMessageQueue(sendTo,message,sentFrom,ignoreFault, callContext); + return sendMessageFromMessageQueue(sendTo, message, sentFrom, + ignoreFault, callContext); } ReturnValue_t MessageQueue::handleSendResult(BaseType_t result, bool ignoreFault) { if (result != pdPASS) { if (!ignoreFault) { - InternalErrorReporterIF* internalErrorReporter = objectManager->get( + InternalErrorReporterIF* internalErrorReporter = + objectManager->get( objects::INTERNAL_ERROR_REPORTER); if (internalErrorReporter != NULL) { internalErrorReporter->queueMessageNotSent(); @@ -78,7 +80,8 @@ ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessage* message, } ReturnValue_t MessageQueue::receiveMessage(MessageQueueMessage* message) { - BaseType_t result = xQueueReceive(handle,reinterpret_cast(message->getBuffer()), 0); + BaseType_t result = xQueueReceive(handle,reinterpret_cast( + message->getBuffer()), 0); if (result == pdPASS){ this->lastPartner = message->getSender(); return HasReturnvaluesIF::RETURN_OK; diff --git a/osal/FreeRTOS/MessageQueue.h b/osal/FreeRTOS/MessageQueue.h index ce6ed46b..c278e329 100644 --- a/osal/FreeRTOS/MessageQueue.h +++ b/osal/FreeRTOS/MessageQueue.h @@ -12,52 +12,57 @@ extern "C" { } - //TODO this class assumes that MessageQueueId_t is the same size as void* (the FreeRTOS handle type), compiler will catch this but it might be nice to have something checking or even an always working solution // https://scaryreasoner.wordpress.com/2009/02/28/checking-sizeof-at-compile-time/ /** - * @brief This class manages sending and receiving of message queue messages. + * @brief This class manages sending and receiving of + * message queue messages. + * @details + * Message queues are used to pass asynchronous messages between processes. + * They work like post boxes, where all incoming messages are stored in FIFO + * order. This class creates a new receiving queue and provides methods to fetch + * received messages. Being a child of MessageQueueSender, this class also + * provides methods to send a message to a user-defined or a default destination. + * In addition it also provides a reply method to answer to the queue it + * received its last message from. * - * @details Message queues are used to pass asynchronous messages between processes. - * They work like post boxes, where all incoming messages are stored in FIFO - * order. This class creates a new receiving queue and provides methods to fetch - * received messages. Being a child of MessageQueueSender, this class also provides - * methods to send a message to a user-defined or a default destination. In addition - * it also provides a reply method to answer to the queue it received its last message - * from. + * The MessageQueue should be used as "post box" for a single owning object. + * So all message queue communication is "n-to-one". + * For creating the queue, as well as sending and receiving messages, the class + * makes use of the operating system calls provided. * - * The MessageQueue should be used as "post box" for a single owning object. So all - * message queue communication is "n-to-one". - * For creating the queue, as well as sending and receiving messages, the class makes - * use of the operating system calls provided. - * - * Please keep in mind that FreeRTOS offers - * different calls for message queue operations if called from an ISR. - * For now, the system context needs to be switched manually. - * @ingroup osal - * @ingroup message_queue + * Please keep in mind that FreeRTOS offers different calls for message queue + * operations if called from an ISR. + * For now, the system context needs to be switched manually. + * @ingroup osal + * @ingroup message_queue */ class MessageQueue : public MessageQueueIF { friend class MessageQueueSenderIF; public: /** * @brief The constructor initializes and configures the message queue. - * @details By making use of the according operating system call, a message queue is created - * and initialized. The message depth - the maximum number of messages to be - * buffered - may be set with the help of a parameter, whereas the message size is - * automatically set to the maximum message queue message size. The operating system - * sets the message queue id, or i case of failure, it is set to zero. - * @param message_depth The number of messages to be buffered before passing an error to the - * sender. Default is three. - * @param max_message_size With this parameter, the maximum message size can be adjusted. - * This should be left default. + * @details + * By making use of the according operating system call, a message queue is created + * and initialized. The message depth - the maximum number of messages to be + * buffered - may be set with the help of a parameter, whereas the message size is + * automatically set to the maximum message queue message size. The operating system + * sets the message queue id, or i case of failure, it is set to zero. + * @param message_depth + * The number of messages to be buffered before passing an error to the + * sender. Default is three. + * @param max_message_size + * With this parameter, the maximum message size can be adjusted. + * This should be left default. */ - MessageQueue( size_t message_depth = 3, size_t max_message_size = MessageQueueMessage::MAX_MESSAGE_SIZE ); + MessageQueue( size_t message_depth = 3, + size_t max_message_size = MessageQueueMessage::MAX_MESSAGE_SIZE ); /** * @brief The destructor deletes the formerly created message queue. - * @details This is accomplished by using the delete call provided by the operating system. + * @details This is accomplished by using the delete call provided + * by the operating system. */ virtual ~MessageQueue(); @@ -90,27 +95,28 @@ public: ReturnValue_t reply( MessageQueueMessage* message ); /** - * \brief With the sendMessage call, a queue message is sent to a receiving queue. - * \details This method takes the message provided, adds the sentFrom information and passes + * @brief With the sendMessage call, a queue message is sent to a receiving queue. + * @details This method takes the message provided, adds the sentFrom information and passes * it on to the destination provided with an operating system call. The OS's return * value is returned. - * \param sendTo This parameter specifies the message queue id to send the message to. - * \param message This is a pointer to a previously created message, which is sent. - * \param sentFrom The sentFrom information can be set to inject the sender's queue id into the message. + * @param sendTo This parameter specifies the message queue id to send the message to. + * @param message This is a pointer to a previously created message, which is sent. + * @param sentFrom The sentFrom information can be set to inject the sender's queue id into the message. * This variable is set to zero by default. - * \param ignoreFault If set to true, the internal software fault counter is not incremented if queue is full. + * @param ignoreFault If set to true, the internal software fault counter is not incremented if queue is full. */ virtual ReturnValue_t sendMessageFrom( MessageQueueId_t sendTo, MessageQueueMessage* message, MessageQueueId_t sentFrom = NO_QUEUE, bool ignoreFault = false ); /** - * \brief The sendToDefault method sends a queue message to the default destination. - * \details In all other aspects, it works identical to the sendMessage method. - * \param message This is a pointer to a previously created message, which is sent. - * \param sentFrom The sentFrom information can be set to inject the sender's queue id into the message. + * @brief The sendToDefault method sends a queue message to the default destination. + * @details In all other aspects, it works identical to the sendMessage method. + * @param message This is a pointer to a previously created message, which is sent. + * @param sentFrom The sentFrom information can be set to inject the sender's queue id into the message. * This variable is set to zero by default. */ - virtual ReturnValue_t sendToDefaultFrom( MessageQueueMessage* message, MessageQueueId_t sentFrom = NO_QUEUE, bool ignoreFault = false ); + virtual ReturnValue_t sendToDefaultFrom( MessageQueueMessage* message, + MessageQueueId_t sentFrom = NO_QUEUE, bool ignoreFault = false ); /** * @brief This function reads available messages from the message queue and returns the sender. @@ -147,27 +153,34 @@ public: MessageQueueId_t getId() const; /** - * \brief This method is a simple setter for the default destination. + * @brief This method is a simple setter for the default destination. */ void setDefaultDestination(MessageQueueId_t defaultDestination); /** - * \brief This method is a simple getter for the default destination. + * @brief This method is a simple getter for the default destination. */ MessageQueueId_t getDefaultDestination() const; bool isDefaultDestinationSet() const; protected: /** - * Implementation to be called from any send Call within MessageQueue and MessageQueueSenderIF - * \details This method takes the message provided, adds the sentFrom information and passes - * it on to the destination provided with an operating system call. The OS's return - * value is returned. - * \param sendTo This parameter specifies the message queue id to send the message to. - * \param message This is a pointer to a previously created message, which is sent. - * \param sentFrom The sentFrom information can be set to inject the sender's queue id into the message. - * This variable is set to zero by default. - * \param ignoreFault If set to true, the internal software fault counter is not incremented if queue is full. - * \param context + * @brief Implementation to be called from any send Call within + * MessageQueue and MessageQueueSenderIF. + * @details + * This method takes the message provided, adds the sentFrom information and + * passes it on to the destination provided with an operating system call. + * The OS's return value is returned. + * @param sendTo + * This parameter specifies the message queue id to send the message to. + * @param message + * This is a pointer to a previously created message, which is sent. + * @param sentFrom + * The sentFrom information can be set to inject the sender's queue id into + * the message. This variable is set to zero by default. + * @param ignoreFault + * If set to true, the internal software fault counter is not incremented + * if queue is full. + * @param context Specify whether call is made from task or from an ISR. */ static ReturnValue_t sendMessageFromMessageQueue(MessageQueueId_t sendTo, MessageQueueMessage* message, MessageQueueId_t sentFrom = NO_QUEUE, @@ -175,7 +188,6 @@ protected: static ReturnValue_t handleSendResult(BaseType_t result, bool ignoreFault); - private: QueueHandle_t handle; MessageQueueId_t defaultDestination; From f8614e23a867d21d64922329164920c41ab55c38 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 18 May 2020 17:38:19 +0200 Subject: [PATCH 13/34] deleted copy ans assignment ctor --- osal/FreeRTOS/MessageQueue.cpp | 18 +++++++++--------- osal/FreeRTOS/MessageQueue.h | 16 +++++++++++----- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/osal/FreeRTOS/MessageQueue.cpp b/osal/FreeRTOS/MessageQueue.cpp index 12a3173a..9e4b581b 100644 --- a/osal/FreeRTOS/MessageQueue.cpp +++ b/osal/FreeRTOS/MessageQueue.cpp @@ -7,11 +7,10 @@ // As a first step towards this, introduces system context variable which needs // to be switched manually // Haven't found function to find system context. -MessageQueue::MessageQueue(size_t messageDepth, size_t maxMessageSize) : -defaultDestination(0),lastPartner(0), callContext(CallContext::task) { +MessageQueue::MessageQueue(size_t messageDepth, size_t maxMessageSize) { handle = xQueueCreate(messageDepth, maxMessageSize); if (handle == NULL) { - sif::error << "MessageQueue creation failed" << std::endl; + sif::error << "MessageQueue: Creation failed" << std::endl; } } @@ -57,11 +56,11 @@ ReturnValue_t MessageQueue::sendMessageFrom(MessageQueueId_t sendTo, ReturnValue_t MessageQueue::handleSendResult(BaseType_t result, bool ignoreFault) { if (result != pdPASS) { - if (!ignoreFault) { + if (not ignoreFault) { InternalErrorReporterIF* internalErrorReporter = objectManager->get( objects::INTERNAL_ERROR_REPORTER); - if (internalErrorReporter != NULL) { + if (internalErrorReporter != nullptr) { internalErrorReporter->queueMessageNotSent(); } } @@ -106,6 +105,7 @@ MessageQueueId_t MessageQueue::getId() const { } void MessageQueue::setDefaultDestination(MessageQueueId_t defaultDestination) { + defaultDestinationSet = true; this->defaultDestination = defaultDestination; } @@ -114,7 +114,7 @@ MessageQueueId_t MessageQueue::getDefaultDestination() const { } bool MessageQueue::isDefaultDestinationSet() const { - return 0; + return defaultDestinationSet; } @@ -129,9 +129,9 @@ ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo, static_cast(message->getBuffer()), 0); } else { - // If the call context is from an interrupt, - // request a context switch if a higher priority task - // was blocked by the interrupt. + /* If the call context is from an interrupt, + * request a context switch if a higher priority task + * was blocked by the interrupt. */ BaseType_t xHigherPriorityTaskWoken = pdFALSE; result = xQueueSendFromISR(reinterpret_cast(sendTo), static_cast(message->getBuffer()), diff --git a/osal/FreeRTOS/MessageQueue.h b/osal/FreeRTOS/MessageQueue.h index c278e329..e88bbcec 100644 --- a/osal/FreeRTOS/MessageQueue.h +++ b/osal/FreeRTOS/MessageQueue.h @@ -56,8 +56,12 @@ public: * With this parameter, the maximum message size can be adjusted. * This should be left default. */ - MessageQueue( size_t message_depth = 3, - size_t max_message_size = MessageQueueMessage::MAX_MESSAGE_SIZE ); + MessageQueue( size_t messageDepth = 3, + size_t maxMessageSize = MessageQueueMessage::MAX_MESSAGE_SIZE ); + + /** Copying message queues forbidden */ + MessageQueue(const MessageQueue&) = delete; + MessageQueue& operator=(const MessageQueue&) = delete; /** * @brief The destructor deletes the formerly created message queue. @@ -189,10 +193,12 @@ protected: static ReturnValue_t handleSendResult(BaseType_t result, bool ignoreFault); private: + bool defaultDestinationSet = false; QueueHandle_t handle; - MessageQueueId_t defaultDestination; - MessageQueueId_t lastPartner; - CallContext callContext; //!< Stores the current system context + MessageQueueId_t defaultDestination = 0; + MessageQueueId_t lastPartner = 0; + //!< Stores the current system context + CallContext callContext = CallContext::task; }; #endif /* MESSAGEQUEUE_H_ */ From 41c0ca6c52a728ffaf359805efb0df0319b9dcc3 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 18 May 2020 17:39:10 +0200 Subject: [PATCH 14/34] added doc for switchSystemContext --- osal/FreeRTOS/MessageQueue.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/osal/FreeRTOS/MessageQueue.h b/osal/FreeRTOS/MessageQueue.h index e88bbcec..07e95ddf 100644 --- a/osal/FreeRTOS/MessageQueue.h +++ b/osal/FreeRTOS/MessageQueue.h @@ -70,6 +70,11 @@ public: */ virtual ~MessageQueue(); + /** + * This function is used to switch the call context. This has to be called + * if a message is sent or received from an ISR! + * @param callContext + */ void switchSystemContext(CallContext callContext); /** From b23728731548d900b97a70e3d32565ebcfcc50e7 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 18 May 2020 17:48:16 +0200 Subject: [PATCH 15/34] bin semaph sif replacements --- osal/FreeRTOS/BinarySemaphore.cpp | 11 +++++------ returnvalues/FwClassIds.h | 2 ++ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/osal/FreeRTOS/BinarySemaphore.cpp b/osal/FreeRTOS/BinarySemaphore.cpp index a6a923aa..acfc53bd 100644 --- a/osal/FreeRTOS/BinarySemaphore.cpp +++ b/osal/FreeRTOS/BinarySemaphore.cpp @@ -11,8 +11,7 @@ BinarySemaphore::BinarySemaphore() { handle = xSemaphoreCreateBinary(); if(handle == nullptr) { - - error << "Binary semaphore creation failure" << std::endl; + sif::error << "Binary semaphore creation failure" << std::endl; } xSemaphoreGive(handle); } @@ -26,7 +25,7 @@ BinarySemaphore::~BinarySemaphore() { BinarySemaphore::BinarySemaphore(const BinarySemaphore& other) { handle = xSemaphoreCreateBinary(); if(handle == nullptr) { - error << "Binary semaphore creation failure" << std::endl; + sif::error << "Binary semaphore creation failure" << std::endl; } xSemaphoreGive(handle); } @@ -35,7 +34,7 @@ BinarySemaphore& BinarySemaphore::operator =(const BinarySemaphore& s) { if(this != &s) { handle = xSemaphoreCreateBinary(); if(handle == nullptr) { - error << "Binary semaphore creation failure" << std::endl; + sif::error << "Binary semaphore creation failure" << std::endl; } xSemaphoreGive(handle); } @@ -45,7 +44,7 @@ BinarySemaphore& BinarySemaphore::operator =(const BinarySemaphore& s) { BinarySemaphore::BinarySemaphore(BinarySemaphore&& s) { handle = xSemaphoreCreateBinary(); if(handle == nullptr) { - error << "Binary semaphore creation failure" << std::endl; + sif::error << "Binary semaphore creation failure" << std::endl; } xSemaphoreGive(handle); } @@ -55,7 +54,7 @@ BinarySemaphore& BinarySemaphore::operator =( if(&s != this) { handle = xSemaphoreCreateBinary(); if(handle == nullptr) { - error << "Binary semaphore creation failure" << std::endl; + sif::error << "Binary semaphore creation failure" << std::endl; } xSemaphoreGive(handle); } diff --git a/returnvalues/FwClassIds.h b/returnvalues/FwClassIds.h index d21861c0..120d8b8c 100644 --- a/returnvalues/FwClassIds.h +++ b/returnvalues/FwClassIds.h @@ -24,6 +24,7 @@ enum { MEMORY_HELPER, //MH SERIALIZE_IF, //SE FIXED_MAP, //FM + FIXED_MULTIMAP, //FMM HAS_HEALTH_IF, //HHI FIFO_CLASS, //FF MESSAGE_PROXY, //MQP @@ -59,6 +60,7 @@ enum { SGP4PROPAGATOR_CLASS, //SGP4 53 MUTEX_IF, //MUX 54 MESSAGE_QUEUE_IF,//MQI 55 + SEMAPHORE_IF, //SPH 56 FW_CLASS_ID_COUNT //is actually count + 1 ! }; From 45b0193ef38b70a4f1d5be76564258bc6ab5c928 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 18 May 2020 18:06:40 +0200 Subject: [PATCH 16/34] bin semaph todo --- osal/FreeRTOS/BinarySemaphore.h | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/osal/FreeRTOS/BinarySemaphore.h b/osal/FreeRTOS/BinarySemaphore.h index 0ab9cdea..865da8a6 100644 --- a/osal/FreeRTOS/BinarySemaphore.h +++ b/osal/FreeRTOS/BinarySemaphore.h @@ -1,27 +1,24 @@ -/** - * @file BinarySempahore.h - * - * @date 25.02.2020 - */ #ifndef FRAMEWORK_OSAL_FREERTOS_BINARYSEMPAHORE_H_ #define FRAMEWORK_OSAL_FREERTOS_BINARYSEMPAHORE_H_ #include extern "C" { -#include "FreeRTOS.h" -#include "semphr.h" +#include +#include } - +// TODO: Counting semaphores and implement the new (better) +// task notifications. However, those use task notifications require +// the task handle. Maybe it would be better to make a separate class +// and switch between the classes with #ifdefs. +// Task Notifications require FreeRTOS V8.2 something.. /** * @brief OS Tool to achieve synchronization of between tasks or between task and ISR * @details * Documentation: https://www.freertos.org/Embedded-RTOS-Binary-Semaphores.html * - * SHOULDDO: check freeRTOS version and use new task notifications, - * if non-ancient freeRTOS version is used. - * + * @author R. Mueller * @ingroup osal */ class BinarySemaphore: public HasReturnvaluesIF { From 87bf843beffe92f7f535609cb83fcb4378f952be Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 18 May 2020 19:19:50 +0200 Subject: [PATCH 17/34] binary semaphore IF init --- tasks/SemaphoreIF.h | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 tasks/SemaphoreIF.h diff --git a/tasks/SemaphoreIF.h b/tasks/SemaphoreIF.h new file mode 100644 index 00000000..babac05a --- /dev/null +++ b/tasks/SemaphoreIF.h @@ -0,0 +1,8 @@ +#ifndef FRAMEWORK_TASKS_SEMAPHOREIF_H_ +#define FRAMEWORK_TASKS_SEMAPHOREIF_H_ + + + + + +#endif /* FRAMEWORK_TASKS_SEMAPHOREIF_H_ */ From 9ba21b1e288ba9f8e20fae9c4cc7ea6923b2651f Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 18 May 2020 19:30:50 +0200 Subject: [PATCH 18/34] semaphore if continued --- tasks/SemaphoreIF.h | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/tasks/SemaphoreIF.h b/tasks/SemaphoreIF.h index babac05a..cf56f6f9 100644 --- a/tasks/SemaphoreIF.h +++ b/tasks/SemaphoreIF.h @@ -1,8 +1,49 @@ #ifndef FRAMEWORK_TASKS_SEMAPHOREIF_H_ #define FRAMEWORK_TASKS_SEMAPHOREIF_H_ +#include +#include +#include +/** + * @brief Generic interface for semaphores, which can be used to achieve + * task synchronization. + */ +class SemaphoreIF { + //!< Needs to be defined in implementation. + static const uint32_t NO_TIMEOUT; + 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_NULLPOINTER = 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 + */ + ReturnValue_t acquire(uint32_t timeoutMs) = 0; + /** + * Corrensponding call to release a semaphore. + * @return + */ + 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. + * @return + */ + uint8_t getSemaphoreCounter() = 0; +}; #endif /* FRAMEWORK_TASKS_SEMAPHOREIF_H_ */ From 4dd6594845deb381b80fcb2ba8e0ec27acec27e1 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 18 May 2020 19:38:02 +0200 Subject: [PATCH 19/34] integrated interface into bin semaphore --- osal/FreeRTOS/BinarySemaphore.cpp | 11 +++++++++++ osal/FreeRTOS/BinarySemaphore.h | 11 +++++++++-- tasks/SemaphoreIF.h | 14 +++++++------- 3 files changed, 27 insertions(+), 9 deletions(-) diff --git a/osal/FreeRTOS/BinarySemaphore.cpp b/osal/FreeRTOS/BinarySemaphore.cpp index acfc53bd..c0300b81 100644 --- a/osal/FreeRTOS/BinarySemaphore.cpp +++ b/osal/FreeRTOS/BinarySemaphore.cpp @@ -132,6 +132,17 @@ void BinarySemaphore::resetSemaphore() { } } +ReturnValue_t BinarySemaphore::acquire(uint32_t timeoutMs) { + return takeBinarySemaphore(timeoutMs); +} + +ReturnValue_t BinarySemaphore::release() { + return giveBinarySemaphore(); +} + +uint8_t BinarySemaphore::getSemaphoreCounter() { + return uxSemaphoreGetCount(handle); +} // Be careful with the stack size here. This is called from an ISR! ReturnValue_t BinarySemaphore::giveBinarySemaphoreFromISR(SemaphoreHandle_t semaphore, diff --git a/osal/FreeRTOS/BinarySemaphore.h b/osal/FreeRTOS/BinarySemaphore.h index 865da8a6..8271d9d0 100644 --- a/osal/FreeRTOS/BinarySemaphore.h +++ b/osal/FreeRTOS/BinarySemaphore.h @@ -2,7 +2,7 @@ #define FRAMEWORK_OSAL_FREERTOS_BINARYSEMPAHORE_H_ #include - +#include extern "C" { #include #include @@ -21,7 +21,8 @@ extern "C" { * @author R. Mueller * @ingroup osal */ -class BinarySemaphore: public HasReturnvaluesIF { +class BinarySemaphore: public SemaphoreIF, + public HasReturnvaluesIF { public: static const uint8_t INTERFACE_ID = CLASS_ID::SEMAPHORE_IF; @@ -67,6 +68,12 @@ public: */ virtual ~BinarySemaphore(); + ReturnValue_t acquire(uint32_t timeoutMs = + BinarySemaphore::NO_BLOCK_TIMEOUT) override; + ReturnValue_t release() override; + + uint8_t getSemaphoreCounter() override; + /** * Take the binary semaphore. * If the semaphore has already been taken, the task will be blocked diff --git a/tasks/SemaphoreIF.h b/tasks/SemaphoreIF.h index cf56f6f9..616b992d 100644 --- a/tasks/SemaphoreIF.h +++ b/tasks/SemaphoreIF.h @@ -9,10 +9,11 @@ * task synchronization. */ class SemaphoreIF { +public: + virtual~ SemaphoreIF() {}; //!< Needs to be defined in implementation. static const uint32_t NO_TIMEOUT; 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 @@ -26,24 +27,23 @@ class SemaphoreIF { * for a maximum of timeoutMs while trying to acquire the semaphore. * This can be used to achieve task synchrnization. * @param timeoutMs - * @return + * @return - c RETURN_OK for successfull acquisition */ - ReturnValue_t acquire(uint32_t timeoutMs) = 0; + virtual ReturnValue_t acquire(uint32_t timeoutMs) = 0; /** * Corrensponding call to release a semaphore. - * @return + * @return -@c RETURN_OK for successfull release */ - ReturnValue_t release() = 0; + 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. - * @return */ - uint8_t getSemaphoreCounter() = 0; + virtual uint8_t getSemaphoreCounter() = 0; }; #endif /* FRAMEWORK_TASKS_SEMAPHOREIF_H_ */ From b1d9d55f50a0e242ec57604934659c7fff50eb01 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 18 May 2020 19:42:05 +0200 Subject: [PATCH 20/34] improved documentation --- tasks/SemaphoreIF.h | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tasks/SemaphoreIF.h b/tasks/SemaphoreIF.h index 616b992d..7dde27f4 100644 --- a/tasks/SemaphoreIF.h +++ b/tasks/SemaphoreIF.h @@ -6,7 +6,16 @@ /** * @brief Generic interface for semaphores, which can be used to achieve - * task synchronization. + * 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. + * + * 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: From 067cd9573100952c1398b956a8b7d2cbeab93a3a Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 18 May 2020 19:42:45 +0200 Subject: [PATCH 21/34] removed file header --- osal/FreeRTOS/BinarySemaphore.cpp | 5 ----- osal/FreeRTOS/BinarySemaphore.h | 1 - 2 files changed, 6 deletions(-) diff --git a/osal/FreeRTOS/BinarySemaphore.cpp b/osal/FreeRTOS/BinarySemaphore.cpp index c0300b81..e4850702 100644 --- a/osal/FreeRTOS/BinarySemaphore.cpp +++ b/osal/FreeRTOS/BinarySemaphore.cpp @@ -1,8 +1,3 @@ -/** - * @file BinarySemaphore.cpp - * - * @date 25.02.2020 - */ #include #include diff --git a/osal/FreeRTOS/BinarySemaphore.h b/osal/FreeRTOS/BinarySemaphore.h index 8271d9d0..854cbba4 100644 --- a/osal/FreeRTOS/BinarySemaphore.h +++ b/osal/FreeRTOS/BinarySemaphore.h @@ -71,7 +71,6 @@ public: ReturnValue_t acquire(uint32_t timeoutMs = BinarySemaphore::NO_BLOCK_TIMEOUT) override; ReturnValue_t release() override; - uint8_t getSemaphoreCounter() override; /** From 7227c3a8667a1ead8c4160b8372d350e79617de4 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 18 May 2020 20:35:13 +0200 Subject: [PATCH 22/34] implemented semaph factory --- osal/FreeRTOS/BinarySemaphore.cpp | 45 +++++++++++++------------ osal/FreeRTOS/BinarySemaphore.h | 52 +++++++++++------------------ osal/FreeRTOS/CountingSemaphore.cpp | 26 +++++++++++++++ osal/FreeRTOS/CountingSemaphore.h | 21 ++++++++++++ osal/FreeRTOS/Mutex.h | 8 ++--- osal/FreeRTOS/MutexFactory.cpp | 9 ++--- osal/FreeRTOS/SemaphoreFactory.cpp | 33 ++++++++++++++++++ tasks/SemaphoreFactory.h | 45 +++++++++++++++++++++++++ 8 files changed, 177 insertions(+), 62 deletions(-) create mode 100644 osal/FreeRTOS/CountingSemaphore.cpp create mode 100644 osal/FreeRTOS/CountingSemaphore.h create mode 100644 osal/FreeRTOS/SemaphoreFactory.cpp create mode 100644 tasks/SemaphoreFactory.h diff --git a/osal/FreeRTOS/BinarySemaphore.cpp b/osal/FreeRTOS/BinarySemaphore.cpp index e4850702..11e48153 100644 --- a/osal/FreeRTOS/BinarySemaphore.cpp +++ b/osal/FreeRTOS/BinarySemaphore.cpp @@ -3,21 +3,21 @@ #include -BinarySemaphore::BinarySemaphore() { +Semaphore::Semaphore() { handle = xSemaphoreCreateBinary(); if(handle == nullptr) { - sif::error << "Binary semaphore creation failure" << std::endl; + sif::error << "Semaphore: Binary semaph creation failure" << std::endl; } xSemaphoreGive(handle); } -BinarySemaphore::~BinarySemaphore() { +Semaphore::~Semaphore() { vSemaphoreDelete(handle); } // This copy ctor is important as it prevents the assignment to a ressource // (other.handle) variable which is later deleted! -BinarySemaphore::BinarySemaphore(const BinarySemaphore& other) { +Semaphore::Semaphore(const Semaphore& other) { handle = xSemaphoreCreateBinary(); if(handle == nullptr) { sif::error << "Binary semaphore creation failure" << std::endl; @@ -25,7 +25,7 @@ BinarySemaphore::BinarySemaphore(const BinarySemaphore& other) { xSemaphoreGive(handle); } -BinarySemaphore& BinarySemaphore::operator =(const BinarySemaphore& s) { +Semaphore& Semaphore::operator =(const Semaphore& s) { if(this != &s) { handle = xSemaphoreCreateBinary(); if(handle == nullptr) { @@ -36,7 +36,7 @@ BinarySemaphore& BinarySemaphore::operator =(const BinarySemaphore& s) { return *this; } -BinarySemaphore::BinarySemaphore(BinarySemaphore&& s) { +Semaphore::Semaphore(Semaphore&& s) { handle = xSemaphoreCreateBinary(); if(handle == nullptr) { sif::error << "Binary semaphore creation failure" << std::endl; @@ -44,8 +44,8 @@ BinarySemaphore::BinarySemaphore(BinarySemaphore&& s) { xSemaphoreGive(handle); } -BinarySemaphore& BinarySemaphore::operator =( - BinarySemaphore&& s) { +Semaphore& Semaphore::operator =( + Semaphore&& s) { if(&s != this) { handle = xSemaphoreCreateBinary(); if(handle == nullptr) { @@ -56,15 +56,15 @@ BinarySemaphore& BinarySemaphore::operator =( return *this; } -ReturnValue_t BinarySemaphore::takeBinarySemaphore(uint32_t timeoutMs) { +ReturnValue_t Semaphore::takeBinarySemaphore(uint32_t timeoutMs) { if(handle == nullptr) { return SEMAPHORE_NULLPOINTER; } - TickType_t timeout = BinarySemaphore::NO_BLOCK_TICKS; - if(timeoutMs == BinarySemaphore::BLOCK_TIMEOUT) { - timeout = BinarySemaphore::BLOCK_TIMEOUT_TICKS; + TickType_t timeout = Semaphore::NO_BLOCK_TICKS; + if(timeoutMs == Semaphore::BLOCK_TIMEOUT) { + timeout = Semaphore::BLOCK_TIMEOUT_TICKS; } - else if(timeoutMs > BinarySemaphore::NO_BLOCK_TIMEOUT){ + else if(timeoutMs > Semaphore::NO_BLOCK_TIMEOUT){ timeout = pdMS_TO_TICKS(timeoutMs); } @@ -77,7 +77,7 @@ ReturnValue_t BinarySemaphore::takeBinarySemaphore(uint32_t timeoutMs) { } } -ReturnValue_t BinarySemaphore::takeBinarySemaphoreTickTimeout( +ReturnValue_t Semaphore::takeBinarySemaphoreTickTimeout( TickType_t timeoutTicks) { if(handle == nullptr) { return SEMAPHORE_NULLPOINTER; @@ -91,7 +91,7 @@ ReturnValue_t BinarySemaphore::takeBinarySemaphoreTickTimeout( } } -ReturnValue_t BinarySemaphore::giveBinarySemaphore() { +ReturnValue_t Semaphore::giveBinarySemaphore() { if (handle == nullptr) { return SEMAPHORE_NULLPOINTER; } @@ -103,11 +103,11 @@ ReturnValue_t BinarySemaphore::giveBinarySemaphore() { } } -SemaphoreHandle_t BinarySemaphore::getSemaphore() { +SemaphoreHandle_t Semaphore::getSemaphore() { return handle; } -ReturnValue_t BinarySemaphore::giveBinarySemaphore(SemaphoreHandle_t semaphore) { +ReturnValue_t Semaphore::giveBinarySemaphore(SemaphoreHandle_t semaphore) { if (semaphore == nullptr) { return SEMAPHORE_NULLPOINTER; } @@ -119,7 +119,7 @@ ReturnValue_t BinarySemaphore::giveBinarySemaphore(SemaphoreHandle_t semaphore) } } -void BinarySemaphore::resetSemaphore() { +void Semaphore::resetSemaphore() { if(handle != nullptr) { vSemaphoreDelete(handle); handle = xSemaphoreCreateBinary(); @@ -127,20 +127,20 @@ void BinarySemaphore::resetSemaphore() { } } -ReturnValue_t BinarySemaphore::acquire(uint32_t timeoutMs) { +ReturnValue_t Semaphore::acquire(uint32_t timeoutMs) { return takeBinarySemaphore(timeoutMs); } -ReturnValue_t BinarySemaphore::release() { +ReturnValue_t Semaphore::release() { return giveBinarySemaphore(); } -uint8_t BinarySemaphore::getSemaphoreCounter() { +uint8_t Semaphore::getSemaphoreCounter() { return uxSemaphoreGetCount(handle); } // Be careful with the stack size here. This is called from an ISR! -ReturnValue_t BinarySemaphore::giveBinarySemaphoreFromISR(SemaphoreHandle_t semaphore, +ReturnValue_t Semaphore::giveBinarySemaphoreFromISR(SemaphoreHandle_t semaphore, BaseType_t * higherPriorityTaskWoken) { if (semaphore == nullptr) { return SEMAPHORE_NULLPOINTER; @@ -157,3 +157,4 @@ ReturnValue_t BinarySemaphore::giveBinarySemaphoreFromISR(SemaphoreHandle_t sema return SEMAPHORE_NOT_OWNED; } } + diff --git a/osal/FreeRTOS/BinarySemaphore.h b/osal/FreeRTOS/BinarySemaphore.h index 854cbba4..6383432f 100644 --- a/osal/FreeRTOS/BinarySemaphore.h +++ b/osal/FreeRTOS/BinarySemaphore.h @@ -14,14 +14,16 @@ extern "C" { // and switch between the classes with #ifdefs. // Task Notifications require FreeRTOS V8.2 something.. /** - * @brief OS Tool to achieve synchronization of between tasks or between task and ISR + * @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 * * @author R. Mueller * @ingroup osal */ -class BinarySemaphore: public SemaphoreIF, +class Semaphore: public SemaphoreIF, public HasReturnvaluesIF { public: static const uint8_t INTERFACE_ID = CLASS_ID::SEMAPHORE_IF; @@ -41,35 +43,21 @@ public: static constexpr ReturnValue_t SEMAPHORE_NOT_OWNED = MAKE_RETURN_CODE(2); static constexpr ReturnValue_t SEMAPHORE_NULLPOINTER = MAKE_RETURN_CODE(3); - BinarySemaphore(); - - /** - * @brief Copy ctor - */ - BinarySemaphore(const BinarySemaphore&); - - /** - * @brief Copy assignment - */ - BinarySemaphore& operator=(const BinarySemaphore&); - - /** - * @brief Move constructor - */ - BinarySemaphore (BinarySemaphore &&); - - /** - * Move assignment - */ - BinarySemaphore & operator=(BinarySemaphore &&); - - /** - * Delete the binary semaphore to prevent a memory leak - */ - virtual ~BinarySemaphore(); + //! @brief Default ctor + Semaphore(); + //! @brief Copy ctor + Semaphore(const Semaphore&); + //! @brief Copy assignment + Semaphore& operator=(const Semaphore&); + //! @brief Move ctor + Semaphore (Semaphore &&); + //! @brief Move assignment + Semaphore & operator=(Semaphore &&); + //! @brief Destructor + virtual ~Semaphore(); ReturnValue_t acquire(uint32_t timeoutMs = - BinarySemaphore::NO_BLOCK_TIMEOUT) override; + Semaphore::NO_BLOCK_TIMEOUT) override; ReturnValue_t release() override; uint8_t getSemaphoreCounter() override; @@ -83,7 +71,7 @@ public: * -@c RETURN_FAILED on failure */ ReturnValue_t takeBinarySemaphore(uint32_t timeoutMs = - BinarySemaphore::NO_BLOCK_TIMEOUT); + Semaphore::NO_BLOCK_TIMEOUT); /** * Same as lockBinarySemaphore() with timeout in FreeRTOS ticks. @@ -92,7 +80,7 @@ public: * - @c RETURN_FAILED on failure */ ReturnValue_t takeBinarySemaphoreTickTimeout(TickType_t timeoutTicks = - BinarySemaphore::NO_BLOCK_TICKS); + Semaphore::NO_BLOCK_TICKS); /** * Give back the binary semaphore @@ -130,7 +118,7 @@ public: */ static ReturnValue_t giveBinarySemaphoreFromISR(SemaphoreHandle_t semaphore, BaseType_t * higherPriorityTaskWoken); -private: +protected: SemaphoreHandle_t handle; }; diff --git a/osal/FreeRTOS/CountingSemaphore.cpp b/osal/FreeRTOS/CountingSemaphore.cpp new file mode 100644 index 00000000..adf3f23c --- /dev/null +++ b/osal/FreeRTOS/CountingSemaphore.cpp @@ -0,0 +1,26 @@ +#include +#include + +CountingSemaphore::CountingSemaphore(uint8_t count, uint8_t initCount): + count(count), initCount(initCount) { + handle = xSemaphoreCreateCounting(count, initCount); + if(handle == nullptr) { + sif::error << "CountingSemaphore: Creation failure" << std::endl; + } +} + +CountingSemaphore::CountingSemaphore(CountingSemaphore&& other) { + handle = xSemaphoreCreateCounting(other.count, other.initCount); + if(handle == nullptr) { + sif::error << "CountingSemaphore: Creation failure" << std::endl; + } +} + +CountingSemaphore& CountingSemaphore::operator =( + CountingSemaphore&& other) { + handle = xSemaphoreCreateCounting(other.count, other.initCount); + if(handle == nullptr) { + sif::error << "CountingSemaphore: Creation failure" << std::endl; + } + return * this; +} diff --git a/osal/FreeRTOS/CountingSemaphore.h b/osal/FreeRTOS/CountingSemaphore.h new file mode 100644 index 00000000..8c059af5 --- /dev/null +++ b/osal/FreeRTOS/CountingSemaphore.h @@ -0,0 +1,21 @@ +#ifndef FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHORE_H_ +#define FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHORE_H_ +#include + +class CountingSemaphore: public Semaphore { +public: + CountingSemaphore(uint8_t count, 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 &&); +private: + uint8_t count = 0; + uint8_t initCount = 0; +}; + +#endif /* FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHORE_H_ */ diff --git a/osal/FreeRTOS/Mutex.h b/osal/FreeRTOS/Mutex.h index 91f29585..ccbcad26 100644 --- a/osal/FreeRTOS/Mutex.h +++ b/osal/FreeRTOS/Mutex.h @@ -3,10 +3,10 @@ #include - -#include -#include "semphr.h" - +extern "C" { +#include +#include +} class Mutex : public MutexIF { diff --git a/osal/FreeRTOS/MutexFactory.cpp b/osal/FreeRTOS/MutexFactory.cpp index cadb54fb..08cd68c8 100644 --- a/osal/FreeRTOS/MutexFactory.cpp +++ b/osal/FreeRTOS/MutexFactory.cpp @@ -1,10 +1,11 @@ #include -#include "../FreeRTOS/Mutex.h" +#include -//TODO: Different variant than the lazy loading in QueueFactory. What's better and why? -> one is on heap the other on bss/data +//TODO: Different variant than the lazy loading in QueueFactory. +//What's better and why? -> one is on heap the other on bss/data //MutexFactory* MutexFactory::factoryInstance = new MutexFactory(); -MutexFactory* MutexFactory::factoryInstance = NULL; +MutexFactory* MutexFactory::factoryInstance = nullptr; MutexFactory::MutexFactory() { } @@ -13,7 +14,7 @@ MutexFactory::~MutexFactory() { } MutexFactory* MutexFactory::instance() { - if (factoryInstance == NULL){ + if (factoryInstance == nullptr){ factoryInstance = new MutexFactory(); } return MutexFactory::factoryInstance; diff --git a/osal/FreeRTOS/SemaphoreFactory.cpp b/osal/FreeRTOS/SemaphoreFactory.cpp new file mode 100644 index 00000000..dd319025 --- /dev/null +++ b/osal/FreeRTOS/SemaphoreFactory.cpp @@ -0,0 +1,33 @@ +#include +#include +#include +#include + +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() { + return new Semaphore(); +} + +SemaphoreIF* SemaphoreFactory::createCountingSemaphore(uint8_t count, + uint8_t initCount) { + return new CountingSemaphore(count, initCount); +} + +void SemaphoreFactory::deleteMutex(SemaphoreIF* semaphore) { + delete semaphore; +} diff --git a/tasks/SemaphoreFactory.h b/tasks/SemaphoreFactory.h new file mode 100644 index 00000000..fa95399a --- /dev/null +++ b/tasks/SemaphoreFactory.h @@ -0,0 +1,45 @@ +#ifndef FRAMEWORK_TASKS_SEMAPHOREFACTORY_H_ +#define FRAMEWORK_TASKS_SEMAPHOREFACTORY_H_ +#include + +/** + * 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 + * @return Pointer to newly created semaphore class instance. + */ + SemaphoreIF* createBinarySemaphore(); + /** + * 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. + * @return + */ + SemaphoreIF* createCountingSemaphore(uint8_t count, uint8_t initCount); + void deleteMutex(SemaphoreIF* mutex); + +private: + /** + * External instantiation is not allowed. + */ + SemaphoreFactory(); + static SemaphoreFactory* factoryInstance; +}; + +#endif /* FRAMEWORK_TASKS_SEMAPHOREFACTORY_H_ */ From 066930b110730c8c781f0b680e1f7b99f1dbe920 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 18 May 2020 20:39:48 +0200 Subject: [PATCH 23/34] improvements --- osal/FreeRTOS/BinarySemaphore.cpp | 42 +++++++++++++++--------------- osal/FreeRTOS/BinarySemaphore.h | 20 +++++++------- osal/FreeRTOS/CountingSemaphore.h | 10 ++++++- osal/FreeRTOS/SemaphoreFactory.cpp | 2 +- 4 files changed, 41 insertions(+), 33 deletions(-) diff --git a/osal/FreeRTOS/BinarySemaphore.cpp b/osal/FreeRTOS/BinarySemaphore.cpp index 11e48153..f08e3b81 100644 --- a/osal/FreeRTOS/BinarySemaphore.cpp +++ b/osal/FreeRTOS/BinarySemaphore.cpp @@ -3,7 +3,7 @@ #include -Semaphore::Semaphore() { +BinarySemaphore::BinarySemaphore() { handle = xSemaphoreCreateBinary(); if(handle == nullptr) { sif::error << "Semaphore: Binary semaph creation failure" << std::endl; @@ -11,13 +11,13 @@ Semaphore::Semaphore() { xSemaphoreGive(handle); } -Semaphore::~Semaphore() { +BinarySemaphore::~BinarySemaphore() { vSemaphoreDelete(handle); } // This copy ctor is important as it prevents the assignment to a ressource // (other.handle) variable which is later deleted! -Semaphore::Semaphore(const Semaphore& other) { +BinarySemaphore::BinarySemaphore(const BinarySemaphore& other) { handle = xSemaphoreCreateBinary(); if(handle == nullptr) { sif::error << "Binary semaphore creation failure" << std::endl; @@ -25,7 +25,7 @@ Semaphore::Semaphore(const Semaphore& other) { xSemaphoreGive(handle); } -Semaphore& Semaphore::operator =(const Semaphore& s) { +BinarySemaphore& BinarySemaphore::operator =(const BinarySemaphore& s) { if(this != &s) { handle = xSemaphoreCreateBinary(); if(handle == nullptr) { @@ -36,7 +36,7 @@ Semaphore& Semaphore::operator =(const Semaphore& s) { return *this; } -Semaphore::Semaphore(Semaphore&& s) { +BinarySemaphore::BinarySemaphore(BinarySemaphore&& s) { handle = xSemaphoreCreateBinary(); if(handle == nullptr) { sif::error << "Binary semaphore creation failure" << std::endl; @@ -44,8 +44,8 @@ Semaphore::Semaphore(Semaphore&& s) { xSemaphoreGive(handle); } -Semaphore& Semaphore::operator =( - Semaphore&& s) { +BinarySemaphore& BinarySemaphore::operator =( + BinarySemaphore&& s) { if(&s != this) { handle = xSemaphoreCreateBinary(); if(handle == nullptr) { @@ -56,15 +56,15 @@ Semaphore& Semaphore::operator =( return *this; } -ReturnValue_t Semaphore::takeBinarySemaphore(uint32_t timeoutMs) { +ReturnValue_t BinarySemaphore::takeBinarySemaphore(uint32_t timeoutMs) { if(handle == nullptr) { return SEMAPHORE_NULLPOINTER; } - TickType_t timeout = Semaphore::NO_BLOCK_TICKS; - if(timeoutMs == Semaphore::BLOCK_TIMEOUT) { - timeout = Semaphore::BLOCK_TIMEOUT_TICKS; + TickType_t timeout = BinarySemaphore::NO_BLOCK_TICKS; + if(timeoutMs == BinarySemaphore::BLOCK_TIMEOUT) { + timeout = BinarySemaphore::BLOCK_TIMEOUT_TICKS; } - else if(timeoutMs > Semaphore::NO_BLOCK_TIMEOUT){ + else if(timeoutMs > BinarySemaphore::NO_BLOCK_TIMEOUT){ timeout = pdMS_TO_TICKS(timeoutMs); } @@ -77,7 +77,7 @@ ReturnValue_t Semaphore::takeBinarySemaphore(uint32_t timeoutMs) { } } -ReturnValue_t Semaphore::takeBinarySemaphoreTickTimeout( +ReturnValue_t BinarySemaphore::takeBinarySemaphoreTickTimeout( TickType_t timeoutTicks) { if(handle == nullptr) { return SEMAPHORE_NULLPOINTER; @@ -91,7 +91,7 @@ ReturnValue_t Semaphore::takeBinarySemaphoreTickTimeout( } } -ReturnValue_t Semaphore::giveBinarySemaphore() { +ReturnValue_t BinarySemaphore::giveBinarySemaphore() { if (handle == nullptr) { return SEMAPHORE_NULLPOINTER; } @@ -103,11 +103,11 @@ ReturnValue_t Semaphore::giveBinarySemaphore() { } } -SemaphoreHandle_t Semaphore::getSemaphore() { +SemaphoreHandle_t BinarySemaphore::getSemaphore() { return handle; } -ReturnValue_t Semaphore::giveBinarySemaphore(SemaphoreHandle_t semaphore) { +ReturnValue_t BinarySemaphore::giveBinarySemaphore(SemaphoreHandle_t semaphore) { if (semaphore == nullptr) { return SEMAPHORE_NULLPOINTER; } @@ -119,7 +119,7 @@ ReturnValue_t Semaphore::giveBinarySemaphore(SemaphoreHandle_t semaphore) { } } -void Semaphore::resetSemaphore() { +void BinarySemaphore::resetSemaphore() { if(handle != nullptr) { vSemaphoreDelete(handle); handle = xSemaphoreCreateBinary(); @@ -127,20 +127,20 @@ void Semaphore::resetSemaphore() { } } -ReturnValue_t Semaphore::acquire(uint32_t timeoutMs) { +ReturnValue_t BinarySemaphore::acquire(uint32_t timeoutMs) { return takeBinarySemaphore(timeoutMs); } -ReturnValue_t Semaphore::release() { +ReturnValue_t BinarySemaphore::release() { return giveBinarySemaphore(); } -uint8_t Semaphore::getSemaphoreCounter() { +uint8_t BinarySemaphore::getSemaphoreCounter() { return uxSemaphoreGetCount(handle); } // Be careful with the stack size here. This is called from an ISR! -ReturnValue_t Semaphore::giveBinarySemaphoreFromISR(SemaphoreHandle_t semaphore, +ReturnValue_t BinarySemaphore::giveBinarySemaphoreFromISR(SemaphoreHandle_t semaphore, BaseType_t * higherPriorityTaskWoken) { if (semaphore == nullptr) { return SEMAPHORE_NULLPOINTER; diff --git a/osal/FreeRTOS/BinarySemaphore.h b/osal/FreeRTOS/BinarySemaphore.h index 6383432f..bd4ddb95 100644 --- a/osal/FreeRTOS/BinarySemaphore.h +++ b/osal/FreeRTOS/BinarySemaphore.h @@ -23,7 +23,7 @@ extern "C" { * @author R. Mueller * @ingroup osal */ -class Semaphore: public SemaphoreIF, +class BinarySemaphore: public SemaphoreIF, public HasReturnvaluesIF { public: static const uint8_t INTERFACE_ID = CLASS_ID::SEMAPHORE_IF; @@ -44,20 +44,20 @@ public: static constexpr ReturnValue_t SEMAPHORE_NULLPOINTER = MAKE_RETURN_CODE(3); //! @brief Default ctor - Semaphore(); + BinarySemaphore(); //! @brief Copy ctor - Semaphore(const Semaphore&); + BinarySemaphore(const BinarySemaphore&); //! @brief Copy assignment - Semaphore& operator=(const Semaphore&); + BinarySemaphore& operator=(const BinarySemaphore&); //! @brief Move ctor - Semaphore (Semaphore &&); + BinarySemaphore (BinarySemaphore &&); //! @brief Move assignment - Semaphore & operator=(Semaphore &&); + BinarySemaphore & operator=(BinarySemaphore &&); //! @brief Destructor - virtual ~Semaphore(); + virtual ~BinarySemaphore(); ReturnValue_t acquire(uint32_t timeoutMs = - Semaphore::NO_BLOCK_TIMEOUT) override; + BinarySemaphore::NO_BLOCK_TIMEOUT) override; ReturnValue_t release() override; uint8_t getSemaphoreCounter() override; @@ -71,7 +71,7 @@ public: * -@c RETURN_FAILED on failure */ ReturnValue_t takeBinarySemaphore(uint32_t timeoutMs = - Semaphore::NO_BLOCK_TIMEOUT); + BinarySemaphore::NO_BLOCK_TIMEOUT); /** * Same as lockBinarySemaphore() with timeout in FreeRTOS ticks. @@ -80,7 +80,7 @@ public: * - @c RETURN_FAILED on failure */ ReturnValue_t takeBinarySemaphoreTickTimeout(TickType_t timeoutTicks = - Semaphore::NO_BLOCK_TICKS); + BinarySemaphore::NO_BLOCK_TICKS); /** * Give back the binary semaphore diff --git a/osal/FreeRTOS/CountingSemaphore.h b/osal/FreeRTOS/CountingSemaphore.h index 8c059af5..a33a0fa5 100644 --- a/osal/FreeRTOS/CountingSemaphore.h +++ b/osal/FreeRTOS/CountingSemaphore.h @@ -2,7 +2,15 @@ #define FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHORE_H_ #include -class CountingSemaphore: public Semaphore { +/** + * @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(uint8_t count, uint8_t initCount); //! @brief Copy ctor, disabled diff --git a/osal/FreeRTOS/SemaphoreFactory.cpp b/osal/FreeRTOS/SemaphoreFactory.cpp index dd319025..9a355891 100644 --- a/osal/FreeRTOS/SemaphoreFactory.cpp +++ b/osal/FreeRTOS/SemaphoreFactory.cpp @@ -20,7 +20,7 @@ SemaphoreFactory* SemaphoreFactory::instance() { } SemaphoreIF* SemaphoreFactory::createBinarySemaphore() { - return new Semaphore(); + return new BinarySemaphore(); } SemaphoreIF* SemaphoreFactory::createCountingSemaphore(uint8_t count, From 2790a40d6c35d27bb8e86121e02c6ca9f0ddf4ef Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 19 May 2020 18:55:13 +0200 Subject: [PATCH 24/34] some renamings --- tmtcpacket/pus/TcPacketBase.cpp | 30 +++++++++++++++--------------- tmtcpacket/pus/TcPacketBase.h | 4 ++-- tmtcpacket/pus/TcPacketStored.cpp | 2 +- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/tmtcpacket/pus/TcPacketBase.cpp b/tmtcpacket/pus/TcPacketBase.cpp index 0972ffff..32caf5bb 100644 --- a/tmtcpacket/pus/TcPacketBase.cpp +++ b/tmtcpacket/pus/TcPacketBase.cpp @@ -13,28 +13,28 @@ TcPacketBase::~TcPacketBase() { } uint8_t TcPacketBase::getService() { - return tcData->data_field.service_type; + return tcData->dataField.service_type; } uint8_t TcPacketBase::getSubService() { - return tcData->data_field.service_subtype; + return tcData->dataField.service_subtype; } uint8_t TcPacketBase::getAcknowledgeFlags() { - return tcData->data_field.version_type_ack & 0b00001111; + return tcData->dataField.version_type_ack & 0b00001111; } const uint8_t* TcPacketBase::getApplicationData() const { - return &tcData->data; + return &tcData->appData; } uint16_t TcPacketBase::getApplicationDataSize() { - return getPacketDataLength() - sizeof(tcData->data_field) - CRC_SIZE + 1; + return getPacketDataLength() - sizeof(tcData->dataField) - CRC_SIZE + 1; } uint16_t TcPacketBase::getErrorControl() { uint16_t size = getApplicationDataSize() + CRC_SIZE; - uint8_t* p_to_buffer = &tcData->data; + uint8_t* p_to_buffer = &tcData->appData; return (p_to_buffer[size - 2] << 8) + p_to_buffer[size - 1]; } @@ -42,8 +42,8 @@ void TcPacketBase::setErrorControl() { uint32_t full_size = getFullSize(); uint16_t crc = CRC::crc16ccitt(getWholeData(), full_size - CRC_SIZE); uint32_t size = getApplicationDataSize(); - (&tcData->data)[size] = (crc & 0XFF00) >> 8; // CRCH - (&tcData->data)[size + 1] = (crc) & 0X00FF; // CRCL + (&tcData->appData)[size] = (crc & 0XFF00) >> 8; // CRCH + (&tcData->appData)[size + 1] = (crc) & 0X00FF; // CRCL } void TcPacketBase::setData(const uint8_t* pData) { @@ -59,11 +59,11 @@ void TcPacketBase::setApplicationData(const uint8_t * pData, uint16_t dataLen) { } uint8_t TcPacketBase::getSecondaryHeaderFlag() { - return (tcData->data_field.version_type_ack & 0b10000000) >> 7; + return (tcData->dataField.version_type_ack & 0b10000000) >> 7; } uint8_t TcPacketBase::getPusVersionNumber() { - return (tcData->data_field.version_type_ack & 0b01110000) >> 4; + return (tcData->dataField.version_type_ack & 0b01110000) >> 4; } void TcPacketBase::print() { @@ -78,14 +78,14 @@ void TcPacketBase::print() { void TcPacketBase::initializeTcPacket(uint16_t apid, uint16_t sequenceCount, uint8_t ack, uint8_t service, uint8_t subservice) { initSpacePacketHeader(true, true, apid, sequenceCount); - memset(&tcData->data_field, 0, sizeof(tcData->data_field)); + memset(&tcData->dataField, 0, sizeof(tcData->dataField)); setPacketDataLength(sizeof(PUSTcDataFieldHeader) + CRC_SIZE - 1); //Data Field Header: //Set CCSDS_secondary_header_flag to 0, version number to 001 and ack to 0000 - tcData->data_field.version_type_ack = 0b00010000; - tcData->data_field.version_type_ack |= (ack & 0x0F); - tcData->data_field.service_type = service; - tcData->data_field.service_subtype = subservice; + tcData->dataField.version_type_ack = 0b00010000; + tcData->dataField.version_type_ack |= (ack & 0x0F); + tcData->dataField.service_type = service; + tcData->dataField.service_subtype = subservice; } size_t TcPacketBase::calculateFullPacketLength(size_t appDataLen) { diff --git a/tmtcpacket/pus/TcPacketBase.h b/tmtcpacket/pus/TcPacketBase.h index 136aaa0b..9b858bd9 100644 --- a/tmtcpacket/pus/TcPacketBase.h +++ b/tmtcpacket/pus/TcPacketBase.h @@ -24,8 +24,8 @@ struct PUSTcDataFieldHeader { */ struct TcPacketPointer { CCSDSPrimaryHeader primary; - PUSTcDataFieldHeader data_field; - uint8_t data; + PUSTcDataFieldHeader dataField; + uint8_t appData; }; /** diff --git a/tmtcpacket/pus/TcPacketStored.cpp b/tmtcpacket/pus/TcPacketStored.cpp index 57b90bcc..47cf2ecd 100644 --- a/tmtcpacket/pus/TcPacketStored.cpp +++ b/tmtcpacket/pus/TcPacketStored.cpp @@ -24,7 +24,7 @@ TcPacketStored::TcPacketStored(uint8_t service, uint8_t subservice, } this->setData(p_data); initializeTcPacket(apid, sequence_count, ack, service, subservice); - memcpy(&tcData->data, data, size); + memcpy(&tcData->appData, data, size); this->setPacketDataLength( size + sizeof(PUSTcDataFieldHeader) + CRC_SIZE - 1); this->setErrorControl(); From f612b095c1c508466098576866827dc065dc9809 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 19 May 2020 19:39:19 +0200 Subject: [PATCH 25/34] updated tmtc packet base --- tmtcpacket/pus/TcPacketBase.cpp | 7 +++---- tmtcpacket/pus/TcPacketBase.h | 15 +++++++++------ tmtcpacket/pus/TmPacketBase.cpp | 5 +++++ tmtcpacket/pus/TmPacketBase.h | 7 +++++++ 4 files changed, 24 insertions(+), 10 deletions(-) diff --git a/tmtcpacket/pus/TcPacketBase.cpp b/tmtcpacket/pus/TcPacketBase.cpp index 32caf5bb..733c36df 100644 --- a/tmtcpacket/pus/TcPacketBase.cpp +++ b/tmtcpacket/pus/TcPacketBase.cpp @@ -51,11 +51,10 @@ void TcPacketBase::setData(const uint8_t* pData) { tcData = (TcPacketPointer*) pData; } -void TcPacketBase::setApplicationData(const uint8_t * pData, uint16_t dataLen) { - setData(pData); - // packet data length is actual size of data field minus 1 +void TcPacketBase::setAppData(uint8_t * appData, uint16_t dataLen) { + memcpy(&tcData->appData, appData, dataLen); SpacePacketBase::setPacketDataLength(dataLen + - sizeof(PUSTcDataFieldHeader) + TcPacketBase::CRC_SIZE - 1); + sizeof(PUSTcDataFieldHeader) + TcPacketBase::CRC_SIZE - 1); } uint8_t TcPacketBase::getSecondaryHeaderFlag() { diff --git a/tmtcpacket/pus/TcPacketBase.h b/tmtcpacket/pus/TcPacketBase.h index 9b858bd9..73076176 100644 --- a/tmtcpacket/pus/TcPacketBase.h +++ b/tmtcpacket/pus/TcPacketBase.h @@ -168,6 +168,14 @@ public: * current content of the packet. */ void setErrorControl(); + + /** + * Copies the supplied data to the internal TC application data field. + * @param pData + * @param dataLen + */ + void setAppData(uint8_t * appData, uint16_t dataLen); + /** * With this method, the packet data pointer can be redirected to another * location. @@ -178,12 +186,7 @@ public: * @param p_data A pointer to another PUS Telecommand Packet. */ void setData( const uint8_t* pData ); - /** - * Set application data and corresponding length field. - * @param pData - * @param dataLen - */ - void setApplicationData(const uint8_t * pData, uint16_t dataLen); + /** * This is a debugging helper method that prints the whole packet content * to the screen. diff --git a/tmtcpacket/pus/TmPacketBase.cpp b/tmtcpacket/pus/TmPacketBase.cpp index a7bda5af..a2c27ce1 100644 --- a/tmtcpacket/pus/TmPacketBase.cpp +++ b/tmtcpacket/pus/TmPacketBase.cpp @@ -102,6 +102,11 @@ void TmPacketBase::initializeTmPacket(uint16_t apid, uint8_t service, uint8_t su } } +void TmPacketBase::setSourceData(uint8_t* sourceData, size_t sourceSize) { + memcpy(getSourceData(), sourceData, sourceSize); + setSourceDataSize(sourceSize); +} + void TmPacketBase::setSourceDataSize(uint16_t size) { setPacketDataLength(size + sizeof(PUSTmDataFieldHeader) + CRC_SIZE - 1); } diff --git a/tmtcpacket/pus/TmPacketBase.h b/tmtcpacket/pus/TmPacketBase.h index d03beba5..6f3c4b59 100644 --- a/tmtcpacket/pus/TmPacketBase.h +++ b/tmtcpacket/pus/TmPacketBase.h @@ -125,6 +125,13 @@ public: * current content of the packet. */ void setErrorControl(); + /** + * This sets the source data. It copies the provided data to + * the internal TmPacketPointer source data location. + * @param sourceData + * @param sourceSize + */ + void setSourceData(uint8_t* sourceData, size_t sourceSize); /** * With this method, the packet data pointer can be redirected to another * location. From e2418d61a6263f67f2db96ac265f0e271766a28c Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 19 May 2020 19:53:10 +0200 Subject: [PATCH 26/34] improved printer --- globalfunctions/printer.cpp | 24 +++++++++++++++++------- globalfunctions/printer.h | 7 ++++--- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/globalfunctions/printer.cpp b/globalfunctions/printer.cpp index bf4c5848..01ec532c 100644 --- a/globalfunctions/printer.cpp +++ b/globalfunctions/printer.cpp @@ -1,36 +1,46 @@ #include #include -void printer::print(uint8_t *data, size_t size, OutputType type) { - sif::info << "Printing data with size " << size << ": ["; +void printer::print(uint8_t *data, size_t size, OutputType type, bool printInfo, + size_t maxCharPerLine) { + if(printInfo) { + sif::info << "Printing data with size " << size << ": "; + } + sif::info << "["; if(type == OutputType::HEX) { - printer::printHex(data, size); + printer::printHex(data, size, maxCharPerLine); } else { - printer::printDec(data, size); + printer::printDec(data, size, maxCharPerLine); } } -void printer::printHex(uint8_t *data, size_t size) { +void printer::printHex(uint8_t *data, size_t size, size_t maxCharPerLine) { sif::info << std::hex; for(size_t i = 0; i < size; i++) { sif::info << "0x" << static_cast(data[i]); if(i < size - 1){ sif::info << " , "; + if(i > 0 and i % maxCharPerLine == 0) { + sif::info << std::endl; + } } + } sif::info << std::dec; sif::info << "]" << std::endl; } -void printer::printDec(uint8_t *data, size_t size) { +void printer::printDec(uint8_t *data, size_t size, size_t maxCharPerLine) { sif::info << std::dec; for(size_t i = 0; i < size; i++) { sif::info << "0x" << static_cast(data[i]); if(i < size - 1){ sif::info << " , "; + if(i > 0 and i % maxCharPerLine == 0) { + sif::info << std::endl; + } } } sif::info << "]" << std::endl; } - diff --git a/globalfunctions/printer.h b/globalfunctions/printer.h index 3c9d6aa0..db9f343f 100644 --- a/globalfunctions/printer.h +++ b/globalfunctions/printer.h @@ -10,9 +10,10 @@ enum class OutputType { HEX }; -void print(uint8_t* data, size_t size, OutputType type = OutputType::HEX); -void printHex(uint8_t* data, size_t size); -void printDec(uint8_t* data, size_t size); +void print(uint8_t* data, size_t size, OutputType type = OutputType::HEX, + bool printInfo = true, size_t maxCharPerLine = 12); +void printHex(uint8_t* data, size_t size, size_t maxCharPerLine = 12); +void printDec(uint8_t* data, size_t size, size_t maxCharPerLine = 12); } #endif /* FRAMEWORK_GLOBALFUNCTIONS_PRINTER_H_ */ From 1aef000eff336b97917ac4c178d95749ec9cd5dc Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 19 May 2020 20:24:58 +0200 Subject: [PATCH 27/34] printer improvements and fixes tc packet stored getter function --- globalfunctions/printer.cpp | 10 +++++----- globalfunctions/printer.h | 6 +++--- tmtcpacket/pus/TcPacketStored.cpp | 12 ++++++++++++ tmtcpacket/pus/TcPacketStored.h | 3 +++ 4 files changed, 23 insertions(+), 8 deletions(-) diff --git a/globalfunctions/printer.cpp b/globalfunctions/printer.cpp index 01ec532c..f099113c 100644 --- a/globalfunctions/printer.cpp +++ b/globalfunctions/printer.cpp @@ -1,8 +1,8 @@ #include #include -void printer::print(uint8_t *data, size_t size, OutputType type, bool printInfo, - size_t maxCharPerLine) { +void printer::print(const uint8_t *data, size_t size, OutputType type, + bool printInfo, size_t maxCharPerLine) { if(printInfo) { sif::info << "Printing data with size " << size << ": "; } @@ -15,7 +15,7 @@ void printer::print(uint8_t *data, size_t size, OutputType type, bool printInfo, } } -void printer::printHex(uint8_t *data, size_t size, size_t maxCharPerLine) { +void printer::printHex(const uint8_t *data, size_t size, size_t maxCharPerLine) { sif::info << std::hex; for(size_t i = 0; i < size; i++) { sif::info << "0x" << static_cast(data[i]); @@ -31,10 +31,10 @@ void printer::printHex(uint8_t *data, size_t size, size_t maxCharPerLine) { sif::info << "]" << std::endl; } -void printer::printDec(uint8_t *data, size_t size, size_t maxCharPerLine) { +void printer::printDec(const uint8_t *data, size_t size, size_t maxCharPerLine) { sif::info << std::dec; for(size_t i = 0; i < size; i++) { - sif::info << "0x" << static_cast(data[i]); + sif::info << static_cast(data[i]); if(i < size - 1){ sif::info << " , "; if(i > 0 and i % maxCharPerLine == 0) { diff --git a/globalfunctions/printer.h b/globalfunctions/printer.h index db9f343f..76d28e5f 100644 --- a/globalfunctions/printer.h +++ b/globalfunctions/printer.h @@ -10,10 +10,10 @@ enum class OutputType { HEX }; -void print(uint8_t* data, size_t size, OutputType type = OutputType::HEX, +void print(const uint8_t* data, size_t size, OutputType type = OutputType::HEX, bool printInfo = true, size_t maxCharPerLine = 12); -void printHex(uint8_t* data, size_t size, size_t maxCharPerLine = 12); -void printDec(uint8_t* data, size_t size, size_t maxCharPerLine = 12); +void printHex(const uint8_t* data, size_t size, size_t maxCharPerLine = 12); +void printDec(const uint8_t* data, size_t size, size_t maxCharPerLine = 12); } #endif /* FRAMEWORK_GLOBALFUNCTIONS_PRINTER_H_ */ diff --git a/tmtcpacket/pus/TcPacketStored.cpp b/tmtcpacket/pus/TcPacketStored.cpp index 47cf2ecd..64aa74dc 100644 --- a/tmtcpacket/pus/TcPacketStored.cpp +++ b/tmtcpacket/pus/TcPacketStored.cpp @@ -1,6 +1,7 @@ #include #include #include + #include TcPacketStored::TcPacketStored(store_address_t setAddress) : @@ -20,6 +21,8 @@ TcPacketStored::TcPacketStored(uint8_t service, uint8_t subservice, ReturnValue_t returnValue = this->store->getFreeElement(&this->storeAddress, (TC_PACKET_MIN_SIZE + size), &p_data); if (returnValue != this->store->RETURN_OK) { + sif::warning << "TcPacketStored: Could not get free element from store!" + << std::endl; return; } this->setData(p_data); @@ -30,6 +33,15 @@ TcPacketStored::TcPacketStored(uint8_t service, uint8_t subservice, this->setErrorControl(); } +ReturnValue_t TcPacketStored::getData(const uint8_t ** dataPtr, + size_t* dataSize) { + auto result = this->store->getData(storeAddress, dataPtr, dataSize); + if(result != HasReturnvaluesIF::RETURN_OK) { + sif::warning << "TcPacketStored: Could not get data!" << std::endl; + } + return result; +} + TcPacketStored::TcPacketStored() : TcPacketBase(NULL) { this->storeAddress.raw = StorageManagerIF::INVALID_ADDRESS; diff --git a/tmtcpacket/pus/TcPacketStored.h b/tmtcpacket/pus/TcPacketStored.h index a9c49c2e..de3eb85f 100644 --- a/tmtcpacket/pus/TcPacketStored.h +++ b/tmtcpacket/pus/TcPacketStored.h @@ -74,6 +74,9 @@ public: * @param Size size of the packet. */ TcPacketStored( const uint8_t* data, uint32_t size); + + ReturnValue_t getData(const uint8_t ** dataPtr, + size_t* dataSize); /** * This is a getter for the current store address of the packet. * @return The current store address. The (raw) value is \c StorageManagerIF::INVALID_ADDRESS if From 7afaa752f37422254f962982a41038afb0fbe8da Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 19 May 2020 20:25:54 +0200 Subject: [PATCH 28/34] form improvement --- globalfunctions/printer.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/globalfunctions/printer.cpp b/globalfunctions/printer.cpp index f099113c..b71d70b8 100644 --- a/globalfunctions/printer.cpp +++ b/globalfunctions/printer.cpp @@ -15,7 +15,8 @@ void printer::print(const uint8_t *data, size_t size, OutputType type, } } -void printer::printHex(const uint8_t *data, size_t size, size_t maxCharPerLine) { +void printer::printHex(const uint8_t *data, size_t size, + size_t maxCharPerLine) { sif::info << std::hex; for(size_t i = 0; i < size; i++) { sif::info << "0x" << static_cast(data[i]); @@ -31,7 +32,8 @@ void printer::printHex(const uint8_t *data, size_t size, size_t maxCharPerLine) sif::info << "]" << std::endl; } -void printer::printDec(const uint8_t *data, size_t size, size_t maxCharPerLine) { +void printer::printDec(const uint8_t *data, size_t size, + size_t maxCharPerLine) { sif::info << std::dec; for(size_t i = 0; i < size; i++) { sif::info << static_cast(data[i]); From 9b53e2b64fe9327f55eb12b393a91c666b836dde Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 19 May 2020 22:45:48 +0200 Subject: [PATCH 29/34] added informative comment for counting semaphore --- osal/FreeRTOS/CountingSemaphore.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/osal/FreeRTOS/CountingSemaphore.cpp b/osal/FreeRTOS/CountingSemaphore.cpp index adf3f23c..2b81848a 100644 --- a/osal/FreeRTOS/CountingSemaphore.cpp +++ b/osal/FreeRTOS/CountingSemaphore.cpp @@ -1,6 +1,8 @@ #include #include +// Make sure #define configUSE_COUNTING_SEMAPHORES 1 is set in +// free FreeRTOSConfig.h file. CountingSemaphore::CountingSemaphore(uint8_t count, uint8_t initCount): count(count), initCount(initCount) { handle = xSemaphoreCreateCounting(count, initCount); From 338651af2f7a67422cda787b56b513f020325df4 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Tue, 19 May 2020 23:07:28 +0200 Subject: [PATCH 30/34] binary printer added --- globalfunctions/printer.cpp | 15 ++++++++++++++- globalfunctions/printer.h | 4 +++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/globalfunctions/printer.cpp b/globalfunctions/printer.cpp index b71d70b8..a68a91ee 100644 --- a/globalfunctions/printer.cpp +++ b/globalfunctions/printer.cpp @@ -1,5 +1,6 @@ #include #include +#include void printer::print(const uint8_t *data, size_t size, OutputType type, bool printInfo, size_t maxCharPerLine) { @@ -10,9 +11,12 @@ void printer::print(const uint8_t *data, size_t size, OutputType type, if(type == OutputType::HEX) { printer::printHex(data, size, maxCharPerLine); } - else { + else if (type == OutputType::DEC) { printer::printDec(data, size, maxCharPerLine); } + else if(type == OutputType::BIN) { + printer::printBin(data, size); + } } void printer::printHex(const uint8_t *data, size_t size, @@ -46,3 +50,12 @@ void printer::printDec(const uint8_t *data, size_t size, } sif::info << "]" << std::endl; } + +void printer::printBin(const uint8_t *data, size_t size) { + sif::info << "\n" << std::flush; + for(size_t i = 0; i < size; i++) { + sif::info << "Byte " << i + 1 << ": 0b"<< + std::bitset<8>(data[i]) << ",\n" << std::flush; + } + sif::info << "]" << std::endl; +} diff --git a/globalfunctions/printer.h b/globalfunctions/printer.h index 76d28e5f..33a382ec 100644 --- a/globalfunctions/printer.h +++ b/globalfunctions/printer.h @@ -7,13 +7,15 @@ namespace printer { enum class OutputType { DEC, - HEX + HEX, + BIN }; void print(const uint8_t* data, size_t size, OutputType type = OutputType::HEX, bool printInfo = true, size_t maxCharPerLine = 12); void printHex(const uint8_t* data, size_t size, size_t maxCharPerLine = 12); void printDec(const uint8_t* data, size_t size, size_t maxCharPerLine = 12); +void printBin(const uint8_t* data, size_t size); } #endif /* FRAMEWORK_GLOBALFUNCTIONS_PRINTER_H_ */ From f6b17d6e2ea6156d06214937c70bee305707a836 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Wed, 20 May 2020 12:50:56 +0200 Subject: [PATCH 31/34] deleted copyctor and copy assignment --- osal/FreeRTOS/BinarySemaphore.cpp | 21 --------------------- osal/FreeRTOS/BinarySemaphore.h | 8 ++++---- 2 files changed, 4 insertions(+), 25 deletions(-) diff --git a/osal/FreeRTOS/BinarySemaphore.cpp b/osal/FreeRTOS/BinarySemaphore.cpp index c4a363b4..026704d6 100644 --- a/osal/FreeRTOS/BinarySemaphore.cpp +++ b/osal/FreeRTOS/BinarySemaphore.cpp @@ -15,27 +15,6 @@ BinarySemaphore::~BinarySemaphore() { vSemaphoreDelete(handle); } -// This copy ctor is important as it prevents the assignment to a ressource -// (other.handle) variable which is later deleted! -BinarySemaphore::BinarySemaphore(const BinarySemaphore& other) { - handle = xSemaphoreCreateBinary(); - if(handle == nullptr) { - sif::error << "Binary semaphore creation failure" << std::endl; - } - xSemaphoreGive(handle); -} - -BinarySemaphore& BinarySemaphore::operator =(const BinarySemaphore& s) { - if(this != &s) { - handle = xSemaphoreCreateBinary(); - if(handle == nullptr) { - sif::error << "Binary semaphore creation failure" << std::endl; - } - xSemaphoreGive(handle); - } - return *this; -} - BinarySemaphore::BinarySemaphore(BinarySemaphore&& s) { handle = xSemaphoreCreateBinary(); if(handle == nullptr) { diff --git a/osal/FreeRTOS/BinarySemaphore.h b/osal/FreeRTOS/BinarySemaphore.h index 0c9c0992..5f69dc90 100644 --- a/osal/FreeRTOS/BinarySemaphore.h +++ b/osal/FreeRTOS/BinarySemaphore.h @@ -39,10 +39,10 @@ public: //! @brief Default ctor BinarySemaphore(); - //! @brief Copy ctor - BinarySemaphore(const BinarySemaphore&); - //! @brief Copy assignment - BinarySemaphore& operator=(const 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 From d2d1ef9a854727a0381ccab719d2a8cba8a4acf0 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 22 May 2020 00:58:30 +0200 Subject: [PATCH 32/34] better include guards --- storagemanager/LocalPool.tpp | 4 ++-- storagemanager/PoolManager.h | 4 ++-- storagemanager/PoolManager.tpp | 4 ++-- storagemanager/StorageAccessor.h | 25 +++++++++++-------------- 4 files changed, 17 insertions(+), 20 deletions(-) diff --git a/storagemanager/LocalPool.tpp b/storagemanager/LocalPool.tpp index 59d06ab8..32724bd8 100644 --- a/storagemanager/LocalPool.tpp +++ b/storagemanager/LocalPool.tpp @@ -1,5 +1,5 @@ -#ifndef LOCALPOOL_TPP -#define LOCALPOOL_TPP +#ifndef FRAMEWORK_STORAGEMANAGER_LOCALPOOL_TPP_ +#define FRAMEWORK_STORAGEMANAGER_LOCALPOOL_TPP_ template inline LocalPool::LocalPool(object_id_t setObjectId, diff --git a/storagemanager/PoolManager.h b/storagemanager/PoolManager.h index 87670a82..6e353de2 100644 --- a/storagemanager/PoolManager.h +++ b/storagemanager/PoolManager.h @@ -1,5 +1,5 @@ -#ifndef POOLMANAGER_H_ -#define POOLMANAGER_H_ +#ifndef FRAMEWORK_STORAGEMANAGER_POOLMANAGER_H_ +#define FRAMEWORK_STORAGEMANAGER_POOLMANAGER_H_ #include #include diff --git a/storagemanager/PoolManager.tpp b/storagemanager/PoolManager.tpp index 7025d795..854e22da 100644 --- a/storagemanager/PoolManager.tpp +++ b/storagemanager/PoolManager.tpp @@ -1,5 +1,5 @@ -#ifndef POOLMANAGER_TPP_ -#define POOLMANAGER_TPP_ +#ifndef FRAMEWORK_STORAGEMANAGER_POOLMANAGER_TPP_ +#define FRAMEWORK_STORAGEMANAGER_POOLMANAGER_TPP_ template inline PoolManager::PoolManager(object_id_t setObjectId, diff --git a/storagemanager/StorageAccessor.h b/storagemanager/StorageAccessor.h index 8949642c..f6964b93 100644 --- a/storagemanager/StorageAccessor.h +++ b/storagemanager/StorageAccessor.h @@ -1,22 +1,19 @@ -/** - * @brief Helper classes to facilitate safe access to storages which is also - * conforming to RAII principles - * @details 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. - */ -#ifndef TEST_PROTOTYPES_STORAGEACCESSOR_H_ -#define TEST_PROTOTYPES_STORAGEACCESSOR_H_ +#ifndef FRAMEWORK_STORAGEMANAGER_STORAGEACCESSOR_H_ +#define FRAMEWORK_STORAGEMANAGER_STORAGEACCESSOR_H_ #include #include -#include /** - * @brief Accessor class which can be returned by pool managers - * or passed and set by pool managers to have safe access to the pool - * resources. + * @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. From d4abfacd27b09c17f898e80c62f969610a5d6367 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Fri, 22 May 2020 01:15:02 +0200 Subject: [PATCH 33/34] found solution for circ dependency had to put store_address_t in own file though --- storagemanager/StorageAccessor.cpp | 1 + storagemanager/StorageAccessor.h | 4 ++- storagemanager/StorageManagerIF.h | 56 ++---------------------------- storagemanager/storeAddress.h | 54 ++++++++++++++++++++++++++++ 4 files changed, 61 insertions(+), 54 deletions(-) create mode 100644 storagemanager/storeAddress.h diff --git a/storagemanager/StorageAccessor.cpp b/storagemanager/StorageAccessor.cpp index cc292d6c..c0c8126b 100644 --- a/storagemanager/StorageAccessor.cpp +++ b/storagemanager/StorageAccessor.cpp @@ -1,4 +1,5 @@ #include +#include ConstStorageAccessor::ConstStorageAccessor(store_address_t storeId): storeId(storeId) {} diff --git a/storagemanager/StorageAccessor.h b/storagemanager/StorageAccessor.h index f6964b93..57c9369c 100644 --- a/storagemanager/StorageAccessor.h +++ b/storagemanager/StorageAccessor.h @@ -2,7 +2,9 @@ #define FRAMEWORK_STORAGEMANAGER_STORAGEACCESSOR_H_ #include -#include +#include + +class StorageManagerIF; /** * @brief Helper classes to facilitate safe access to storages which is also diff --git a/storagemanager/StorageManagerIF.h b/storagemanager/StorageManagerIF.h index 559c4b9a..af5aeb73 100644 --- a/storagemanager/StorageManagerIF.h +++ b/storagemanager/StorageManagerIF.h @@ -3,64 +3,14 @@ #include #include -#include +#include +#include #include - -class StorageAccessor; -class ConstStorageAccessor; +#include using AccessorPair = std::pair; using ConstAccessorPair = std::pair; -/** - * 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; - } -}; - /** * @brief This class provides an interface for intermediate data storage. * @details The Storage manager classes shall be used to store larger chunks of 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 723e715022e6d5ada2dfdee9da5a6f3d7450faa9 Mon Sep 17 00:00:00 2001 From: "Robin.Mueller" Date: Mon, 25 May 2020 14:01:35 +0200 Subject: [PATCH 34/34] consistency fix --- storagemanager/LocalPool.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storagemanager/LocalPool.h b/storagemanager/LocalPool.h index 6892b881..c155f918 100644 --- a/storagemanager/LocalPool.h +++ b/storagemanager/LocalPool.h @@ -12,7 +12,7 @@ /** * @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.