diff --git a/osal/FreeRTOS/BinSemaphUsingTask.cpp b/osal/FreeRTOS/BinSemaphUsingTask.cpp new file mode 100644 index 000000000..0d7320545 --- /dev/null +++ b/osal/FreeRTOS/BinSemaphUsingTask.cpp @@ -0,0 +1,95 @@ +#include +#include + + +BinarySemaphoreUsingTask::BinarySemaphoreUsingTask() { + handle = TaskManagement::getCurrentTaskHandle(); +} + +ReturnValue_t BinarySemaphoreUsingTask::acquire(uint32_t timeoutMs) { + return takeBinarySemaphore(timeoutMs); +} + +ReturnValue_t BinarySemaphoreUsingTask::release() { + return giveBinarySemaphore(); +} + +ReturnValue_t BinarySemaphoreUsingTask::takeBinarySemaphore(uint32_t timeoutMs) { + TickType_t timeout = SemaphoreIF::NO_TIMEOUT; + if(timeoutMs == SemaphoreIF::MAX_TIMEOUT) { + timeout = SemaphoreIF::MAX_TIMEOUT; + } + else if(timeoutMs > BinarySemaphoreUsingTask::NO_TIMEOUT){ + timeout = pdMS_TO_TICKS(timeoutMs); + } + + BaseType_t returncode = ulTaskNotifyTake(pdTRUE, timeout); + if (returncode == pdPASS) { + return HasReturnvaluesIF::RETURN_OK; + } + else { + return SemaphoreIF::SEMAPHORE_TIMEOUT; + } +} + +ReturnValue_t BinarySemaphoreUsingTask::takeBinarySemaphoreTickTimeout( + TickType_t timeoutTicks) { + BaseType_t returncode = ulTaskNotifyTake(pdTRUE, timeoutTicks); + if (returncode == pdPASS) { + return HasReturnvaluesIF::RETURN_OK; + } else { + return SEMAPHORE_TIMEOUT; + } +} + +ReturnValue_t BinarySemaphoreUsingTask::giveBinarySemaphore() { + BaseType_t returncode = xTaskNotifyGive(handle); + if (returncode == pdPASS) { + return HasReturnvaluesIF::RETURN_OK; + } else { + return SEMAPHORE_NOT_OWNED; + } +} + +TaskHandle_t BinarySemaphoreUsingTask::getTaskHandle() { + return handle; +} + +uint8_t BinarySemaphoreUsingTask::getSemaphoreCounter() { + uint32_t notificationValue; + xTaskNotifyAndQuery(handle, 0, eNoAction, ¬ificationValue); + return notificationValue; +} + +uint8_t BinarySemaphoreUsingTask::getSemaphoreCounterFromISR(TaskHandle_t taskHandle) { + uint32_t notificationValue; + BaseType_t higherPriorityTaskWoken; + xTaskNotifyAndQueryFromISR(taskHandle, 0, eNoAction, ¬ificationValue, + &higherPriorityTaskWoken); + if(higherPriorityTaskWoken) { + TaskManagement::requestContextSwitch(CallContext::isr); + } + return notificationValue; +} + + +ReturnValue_t BinarySemaphoreUsingTask::giveBinarySemaphore(TaskHandle_t taskHandle) { + BaseType_t returncode = xTaskNotifyGive(taskHandle); + if (returncode == pdPASS) { + return HasReturnvaluesIF::RETURN_OK; + } else { + return SEMAPHORE_NOT_OWNED; + } +} + +// Be careful with the stack size here. This is called from an ISR! +ReturnValue_t BinarySemaphoreUsingTask::giveBinarySemaphoreFromISR( + TaskHandle_t taskHandle, BaseType_t * higherPriorityTaskWoken) { + vTaskNotifyGiveFromISR(taskHandle, higherPriorityTaskWoken); + if(*higherPriorityTaskWoken == pdPASS) { + // Request context switch because unblocking the semaphore + // caused a high priority task unblock. + TaskManagement::requestContextSwitch(CallContext::isr); + } + return HasReturnvaluesIF::RETURN_OK; +} diff --git a/osal/FreeRTOS/BinSemaphUsingTask.h b/osal/FreeRTOS/BinSemaphUsingTask.h new file mode 100644 index 000000000..2736b1db6 --- /dev/null +++ b/osal/FreeRTOS/BinSemaphUsingTask.h @@ -0,0 +1,86 @@ +#ifndef FRAMEWORK_OSAL_FREERTOS_BINSEMAPHUSINGTASK_H_ +#define FRAMEWORK_OSAL_FREERTOS_BINSEMAPHUSINGTASK_H_ + +#include +#include + +extern "C" { +#include +#include +} + +class BinarySemaphoreUsingTask: public SemaphoreIF, + public HasReturnvaluesIF { +public: + static const uint8_t INTERFACE_ID = CLASS_ID::SEMAPHORE_IF; + + //! @brief Default ctor + BinarySemaphoreUsingTask(); + + ReturnValue_t acquire(uint32_t timeoutMs = + SemaphoreIF::NO_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 + * 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 = + SemaphoreIF::NO_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 = + SemaphoreIF::NO_TIMEOUT); + + /** + * Give back the binary semaphore + * @return - @c RETURN_OK on success + * - @c RETURN_FAILED on failure + */ + ReturnValue_t giveBinarySemaphore(); + + /** + * Get handle to the task related to the semaphore. + * @return + */ + TaskHandle_t getTaskHandle(); + + /** + * Wrapper function to give back semaphore from handle + * @param semaphore + * @return - @c RETURN_OK on success + * - @c RETURN_FAILED on failure + */ + static ReturnValue_t giveBinarySemaphore(TaskHandle_t taskToNotify); + + /** + * Wrapper function to give back semaphore from handle when called from an ISR + * @param semaphore + * @param higherPriorityTaskWoken This will be set to pdPASS if a task with a higher priority + * was unblocked + * @return - @c RETURN_OK on success + * - @c RETURN_FAILED on failure + */ + static ReturnValue_t giveBinarySemaphoreFromISR(TaskHandle_t taskToNotify, + BaseType_t * higherPriorityTaskWoken); + + static uint8_t getSemaphoreCounterFromISR(TaskHandle_t taskHandle); + +protected: + TaskHandle_t handle; +}; + + + +#endif /* FRAMEWORK_OSAL_FREERTOS_BINSEMAPHUSINGTASK_H_ */ diff --git a/osal/FreeRTOS/BinarySemaphore.cpp b/osal/FreeRTOS/BinarySemaphore.cpp index 150f8c993..d56be763d 100644 --- a/osal/FreeRTOS/BinarySemaphore.cpp +++ b/osal/FreeRTOS/BinarySemaphore.cpp @@ -2,8 +2,6 @@ #include #include -#if ( configUSE_TASK_NOTIFICATIONS == 0 ) - BinarySemaphore::BinarySemaphore() { handle = xSemaphoreCreateBinary(); if(handle == nullptr) { @@ -129,100 +127,3 @@ ReturnValue_t BinarySemaphore::giveBinarySemaphoreFromISR(SemaphoreHandle_t sema return SEMAPHORE_NOT_OWNED; } } - - -#else - -BinarySemaphore::BinarySemaphore() { - handle = TaskManagement::getCurrentTaskHandle(); -} - -ReturnValue_t BinarySemaphore::acquire(uint32_t timeoutMs) { - return takeBinarySemaphore(timeoutMs); -} - -ReturnValue_t BinarySemaphore::release() { - return giveBinarySemaphore(); -} - -ReturnValue_t BinarySemaphore::takeBinarySemaphore(uint32_t timeoutMs) { - TickType_t timeout = SemaphoreIF::NO_TIMEOUT; - if(timeoutMs == SemaphoreIF::MAX_TIMEOUT) { - timeout = SemaphoreIF::MAX_TIMEOUT; - } - else if(timeoutMs > BinarySemaphore::NO_TIMEOUT){ - timeout = pdMS_TO_TICKS(timeoutMs); - } - - BaseType_t returncode = ulTaskNotifyTake(pdTRUE, timeout); - if (returncode == pdPASS) { - return HasReturnvaluesIF::RETURN_OK; - } - else { - return SemaphoreIF::SEMAPHORE_TIMEOUT; - } -} - -ReturnValue_t BinarySemaphore::takeBinarySemaphoreTickTimeout( - TickType_t timeoutTicks) { - BaseType_t returncode = ulTaskNotifyTake(pdTRUE, timeoutTicks); - if (returncode == pdPASS) { - return HasReturnvaluesIF::RETURN_OK; - } else { - return SEMAPHORE_TIMEOUT; - } -} - -ReturnValue_t BinarySemaphore::giveBinarySemaphore() { - BaseType_t returncode = xTaskNotifyGive(handle); - if (returncode == pdPASS) { - return HasReturnvaluesIF::RETURN_OK; - } else { - return SEMAPHORE_NOT_OWNED; - } -} - -TaskHandle_t BinarySemaphore::getTaskHandle() { - return handle; -} - -uint8_t BinarySemaphore::getSemaphoreCounter() { - uint32_t notificationValue; - xTaskNotifyAndQuery(handle, 0, eNoAction, ¬ificationValue); - return notificationValue; -} - -uint8_t BinarySemaphore::getSemaphoreCounterFromISR(TaskHandle_t taskHandle) { - uint32_t notificationValue; - BaseType_t higherPriorityTaskWoken; - xTaskNotifyAndQueryFromISR(taskHandle, 0, eNoAction, ¬ificationValue, - &higherPriorityTaskWoken); - if(higherPriorityTaskWoken) { - TaskManagement::requestContextSwitch(CallContext::isr); - } - return notificationValue; -} - - -ReturnValue_t BinarySemaphore::giveBinarySemaphore(TaskHandle_t taskHandle) { - BaseType_t returncode = xTaskNotifyGive(taskHandle); - if (returncode == pdPASS) { - return HasReturnvaluesIF::RETURN_OK; - } else { - return SEMAPHORE_NOT_OWNED; - } -} - -// Be careful with the stack size here. This is called from an ISR! -ReturnValue_t BinarySemaphore::giveBinarySemaphoreFromISR( - TaskHandle_t taskHandle, BaseType_t * higherPriorityTaskWoken) { - vTaskNotifyGiveFromISR(taskHandle, higherPriorityTaskWoken); - if(*higherPriorityTaskWoken == pdPASS) { - // Request context switch because unblocking the semaphore - // caused a high priority task unblock. - TaskManagement::requestContextSwitch(CallContext::isr); - } - return HasReturnvaluesIF::RETURN_OK; -} - -#endif diff --git a/osal/FreeRTOS/BinarySemaphore.h b/osal/FreeRTOS/BinarySemaphore.h index 2ee102267..e5c0ce4b5 100644 --- a/osal/FreeRTOS/BinarySemaphore.h +++ b/osal/FreeRTOS/BinarySemaphore.h @@ -6,18 +6,9 @@ extern "C" { #include -#if ( configUSE_TASK_NOTIFICATIONS == 0 ) #include -#else -#include -#endif } -// TODO: Implement the new (better) task notifications. -// However, those 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. The default semaphore implementation creates a @@ -25,11 +16,15 @@ extern "C" { * @details * Documentation: https://www.freertos.org/Embedded-RTOS-Binary-Semaphores.html * + * Please note that if the semaphore implementation is only related to + * the synchronization of one task, the new task notifications can be used, + * also see the BinSemaphUsingTask and CountingSemaphUsingTask classes. + * These use the task notification value instead of a queue and are + * faster and more efficient. + * * @author R. Mueller * @ingroup osal */ -#if ( configUSE_TASK_NOTIFICATIONS == 0 ) - class BinarySemaphore: public SemaphoreIF, public HasReturnvaluesIF { public: @@ -110,80 +105,4 @@ protected: SemaphoreHandle_t handle; }; - -#else - -class BinarySemaphore: public SemaphoreIF, - public HasReturnvaluesIF { -public: - static const uint8_t INTERFACE_ID = CLASS_ID::SEMAPHORE_IF; - - //! @brief Default ctor - BinarySemaphore(); - - ReturnValue_t acquire(uint32_t timeoutMs = - SemaphoreIF::NO_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 - * 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 = - SemaphoreIF::NO_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_TIMEOUT); - - /** - * Give back the binary semaphore - * @return - @c RETURN_OK on success - * - @c RETURN_FAILED on failure - */ - ReturnValue_t giveBinarySemaphore(); - - /** - * Get handle to the task related to the semaphore. - * @return - */ - TaskHandle_t getTaskHandle(); - - /** - * Wrapper function to give back semaphore from handle - * @param semaphore - * @return - @c RETURN_OK on success - * - @c RETURN_FAILED on failure - */ - static ReturnValue_t giveBinarySemaphore(TaskHandle_t taskToNotify); - - /** - * Wrapper function to give back semaphore from handle when called from an ISR - * @param semaphore - * @param higherPriorityTaskWoken This will be set to pdPASS if a task with a higher priority - * was unblocked - * @return - @c RETURN_OK on success - * - @c RETURN_FAILED on failure - */ - static ReturnValue_t giveBinarySemaphoreFromISR(TaskHandle_t taskToNotify, - BaseType_t * higherPriorityTaskWoken); - - static uint8_t getSemaphoreCounterFromISR(TaskHandle_t taskHandle); - -protected: - TaskHandle_t handle; -}; -#endif - #endif /* FRAMEWORK_OSAL_FREERTOS_BINARYSEMPAHORE_H_ */ diff --git a/osal/FreeRTOS/CountingSemaphUsingTask.cpp b/osal/FreeRTOS/CountingSemaphUsingTask.cpp new file mode 100644 index 000000000..6c5d45c7c --- /dev/null +++ b/osal/FreeRTOS/CountingSemaphUsingTask.cpp @@ -0,0 +1,8 @@ +#include +#include + +CountingSemaphoreUsingTask::CountingSemaphoreUsingTask(uint8_t count, + uint8_t initCount): + count(count), initCount(initCount) { + handle = TaskManagement::getCurrentTaskHandle(); +} diff --git a/osal/FreeRTOS/CountingSemaphUsingTask.h b/osal/FreeRTOS/CountingSemaphUsingTask.h new file mode 100644 index 000000000..c4bfb61ab --- /dev/null +++ b/osal/FreeRTOS/CountingSemaphUsingTask.h @@ -0,0 +1,25 @@ +#ifndef FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHUSINGTASK_H_ +#define FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHUSINGTASK_H_ + +#include +#include + +extern "C" { +#include +#include +} + +class CountingSemaphoreUsingTask: public SemaphoreIF { +public: + CountingSemaphoreUsingTask(uint8_t count, uint8_t initCount); + + ReturnValue_t acquire(uint32_t timeoutMs); + ReturnValue_t release(); + +private: + TaskHandle_t handle; + uint8_t count = 0; + uint8_t initCount = 0; +}; + +#endif /* FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHUSINGTASK_H_ */ diff --git a/osal/FreeRTOS/CountingSemaphore.cpp b/osal/FreeRTOS/CountingSemaphore.cpp index e04d3defd..2f0dfd764 100644 --- a/osal/FreeRTOS/CountingSemaphore.cpp +++ b/osal/FreeRTOS/CountingSemaphore.cpp @@ -1,5 +1,6 @@ #include #include +#include extern "C" { #include @@ -30,3 +31,4 @@ CountingSemaphore& CountingSemaphore::operator =( } return * this; } + diff --git a/osal/FreeRTOS/SemaphoreFactory.cpp b/osal/FreeRTOS/SemaphoreFactory.cpp index 7bd71dd7a..1eee1bacc 100644 --- a/osal/FreeRTOS/SemaphoreFactory.cpp +++ b/osal/FreeRTOS/SemaphoreFactory.cpp @@ -21,15 +21,15 @@ SemaphoreFactory* SemaphoreFactory::instance() { return SemaphoreFactory::factoryInstance; } -SemaphoreIF* SemaphoreFactory::createBinarySemaphore() { +SemaphoreIF* SemaphoreFactory::createBinarySemaphore(uint32_t argument) { return new BinarySemaphore(); } SemaphoreIF* SemaphoreFactory::createCountingSemaphore(uint8_t count, - uint8_t initCount) { + uint8_t initCount, uint32_t argument) { return new CountingSemaphore(count, initCount); } -void SemaphoreFactory::deleteMutex(SemaphoreIF* semaphore) { +void SemaphoreFactory::deleteSemaphore(SemaphoreIF* semaphore) { delete semaphore; } diff --git a/tasks/SemaphoreFactory.h b/tasks/SemaphoreFactory.h index fa95399a1..971e97fa3 100644 --- a/tasks/SemaphoreFactory.h +++ b/tasks/SemaphoreFactory.h @@ -20,19 +20,23 @@ public: /** * Create a binary semaphore. * Creator function for a binary semaphore which may only be acquired once + * @param argument Can be used to pass implementation specific information. * @return Pointer to newly created semaphore class instance. */ - SemaphoreIF* createBinarySemaphore(); + SemaphoreIF* createBinarySemaphore(uint32_t argument = 0); /** * Create a counting semaphore. * Creator functons for a counting semaphore which may be acquired multiple * times. * @param count Semaphore can be taken count times. * @param initCount Initial count value. + * @param argument Can be used to pass implementation specific information. * @return */ - SemaphoreIF* createCountingSemaphore(uint8_t count, uint8_t initCount); - void deleteMutex(SemaphoreIF* mutex); + SemaphoreIF* createCountingSemaphore(uint8_t count, uint8_t initCount, + uint32_t argument = 0); + + void deleteSemaphore(SemaphoreIF* mutex); private: /**