counting semaph implementation finished

This commit is contained in:
Robin Müller 2020-05-27 22:12:52 +02:00
parent 95bf5c1071
commit 63dbf99592
8 changed files with 154 additions and 87 deletions

View File

@ -1,7 +1,6 @@
#include <framework/osal/FreeRTOS/BinSemaphUsingTask.h> #include <framework/osal/FreeRTOS/BinSemaphUsingTask.h>
#include <framework/osal/FreeRTOS/TaskManagement.h> #include <framework/osal/FreeRTOS/TaskManagement.h>
BinarySemaphoreUsingTask::BinarySemaphoreUsingTask() { BinarySemaphoreUsingTask::BinarySemaphoreUsingTask() {
handle = TaskManagement::getCurrentTaskHandle(); handle = TaskManagement::getCurrentTaskHandle();
xTaskNotifyGive(handle); xTaskNotifyGive(handle);
@ -9,44 +8,29 @@ BinarySemaphoreUsingTask::BinarySemaphoreUsingTask() {
} }
ReturnValue_t BinarySemaphoreUsingTask::acquire(uint32_t timeoutMs) { 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; TickType_t timeout = SemaphoreIF::NO_TIMEOUT;
if(timeoutMs == SemaphoreIF::MAX_TIMEOUT) { if(timeoutMs == SemaphoreIF::MAX_TIMEOUT) {
timeout = SemaphoreIF::MAX_TIMEOUT; timeout = SemaphoreIF::MAX_TIMEOUT;
} }
else if(timeoutMs > SemaphoreIF::NO_TIMEOUT){ else if(timeoutMs > SemaphoreIF::NO_TIMEOUT){
timeout = pdMS_TO_TICKS(timeoutMs); timeout = pdMS_TO_TICKS(timeoutMs);
}
BaseType_t returncode = ulTaskNotifyTake(pdTRUE, timeout);
if (returncode == pdPASS) {
locked = true;
return HasReturnvaluesIF::RETURN_OK;
}
else {
return SemaphoreIF::SEMAPHORE_TIMEOUT;
} }
return acquireWithTickTimeout(timeout);
} }
ReturnValue_t BinarySemaphoreUsingTask::takeBinarySemaphoreTickTimeout( ReturnValue_t BinarySemaphoreUsingTask::acquireWithTickTimeout(
TickType_t timeoutTicks) { TickType_t timeoutTicks) {
BaseType_t returncode = ulTaskNotifyTake(pdTRUE, timeoutTicks); BaseType_t returncode = ulTaskNotifyTake(pdTRUE, timeoutTicks);
if (returncode == pdPASS) { if (returncode == pdPASS) {
locked = true; locked = true;
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} else { }
return SEMAPHORE_TIMEOUT; else {
return SemaphoreIF::SEMAPHORE_TIMEOUT;
} }
} }
ReturnValue_t BinarySemaphoreUsingTask::giveBinarySemaphore() { ReturnValue_t BinarySemaphoreUsingTask::release() {
if(not locked) { if(not locked) {
return SemaphoreIF::SEMAPHORE_NOT_OWNED; return SemaphoreIF::SEMAPHORE_NOT_OWNED;
} }
@ -69,7 +53,9 @@ uint8_t BinarySemaphoreUsingTask::getSemaphoreCounter() const {
return notificationValue; return notificationValue;
} }
uint8_t BinarySemaphoreUsingTask::getSemaphoreCounterFromISR(TaskHandle_t taskHandle) {
uint8_t BinarySemaphoreUsingTask::getSemaphoreCounterFromISR(
TaskHandle_t taskHandle) {
uint32_t notificationValue; uint32_t notificationValue;
BaseType_t higherPriorityTaskWoken; BaseType_t higherPriorityTaskWoken;
xTaskNotifyAndQueryFromISR(taskHandle, 0, eNoAction, &notificationValue, xTaskNotifyAndQueryFromISR(taskHandle, 0, eNoAction, &notificationValue,
@ -80,8 +66,8 @@ uint8_t BinarySemaphoreUsingTask::getSemaphoreCounterFromISR(TaskHandle_t taskHa
return notificationValue; return notificationValue;
} }
ReturnValue_t BinarySemaphoreUsingTask::release(
ReturnValue_t BinarySemaphoreUsingTask::giveBinarySemaphore(TaskHandle_t taskHandle) { TaskHandle_t taskHandle) {
BaseType_t returncode = xTaskNotifyGive(taskHandle); BaseType_t returncode = xTaskNotifyGive(taskHandle);
if (returncode == pdPASS) { if (returncode == pdPASS) {
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
@ -93,7 +79,7 @@ ReturnValue_t BinarySemaphoreUsingTask::giveBinarySemaphore(TaskHandle_t taskHan
} }
// Be careful with the stack size here. This is called from an ISR! // Be careful with the stack size here. This is called from an ISR!
ReturnValue_t BinarySemaphoreUsingTask::giveBinarySemaphoreFromISR( ReturnValue_t BinarySemaphoreUsingTask::releaseFromISR(
TaskHandle_t taskHandle, BaseType_t * higherPriorityTaskWoken) { TaskHandle_t taskHandle, BaseType_t * higherPriorityTaskWoken) {
vTaskNotifyGiveFromISR(taskHandle, higherPriorityTaskWoken); vTaskNotifyGiveFromISR(taskHandle, higherPriorityTaskWoken);
if(*higherPriorityTaskWoken == pdPASS) { if(*higherPriorityTaskWoken == pdPASS) {

View File

@ -27,35 +27,17 @@ public:
SemaphoreIF::NO_TIMEOUT) override; SemaphoreIF::NO_TIMEOUT) override;
ReturnValue_t release() override; ReturnValue_t release() override;
uint8_t getSemaphoreCounter() const override; uint8_t getSemaphoreCounter() const override;
static uint8_t getSemaphoreCounterFromISR(TaskHandle_t taskHandle);
/** /**
* Take the binary semaphore. * Same as acquire() with timeout in FreeRTOS ticks.
* 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 * @param timeoutTicks
* @return - @c RETURN_OK on success * @return - @c RETURN_OK on success
* - @c RETURN_FAILED on failure * - @c RETURN_FAILED on failure
*/ */
ReturnValue_t takeBinarySemaphoreTickTimeout(TickType_t timeoutTicks = ReturnValue_t acquireWithTickTimeout(TickType_t timeoutTicks =
SemaphoreIF::NO_TIMEOUT); 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. * Get handle to the task related to the semaphore.
* @return * @return
@ -68,7 +50,7 @@ public:
* @return - @c RETURN_OK on success * @return - @c RETURN_OK on success
* - @c RETURN_FAILED on failure * - @c RETURN_FAILED on failure
*/ */
static ReturnValue_t giveBinarySemaphore(TaskHandle_t taskToNotify); static ReturnValue_t release(TaskHandle_t taskToNotify);
/** /**
* Wrapper function to give back semaphore from handle when called from an ISR * Wrapper function to give back semaphore from handle when called from an ISR
@ -78,11 +60,9 @@ public:
* @return - @c RETURN_OK on success * @return - @c RETURN_OK on success
* - @c RETURN_FAILED on failure * - @c RETURN_FAILED on failure
*/ */
static ReturnValue_t giveBinarySemaphoreFromISR(TaskHandle_t taskToNotify, static ReturnValue_t releaseFromISR(TaskHandle_t taskToNotify,
BaseType_t * higherPriorityTaskWoken); BaseType_t * higherPriorityTaskWoken);
static uint8_t getSemaphoreCounterFromISR(TaskHandle_t taskHandle);
protected: protected:
TaskHandle_t handle; TaskHandle_t handle;
// This boolean is required to track whether the semaphore is locked // This boolean is required to track whether the semaphore is locked
@ -90,6 +70,4 @@ protected:
bool locked; bool locked;
}; };
#endif /* FRAMEWORK_OSAL_FREERTOS_BINSEMAPHUSINGTASK_H_ */ #endif /* FRAMEWORK_OSAL_FREERTOS_BINSEMAPHUSINGTASK_H_ */

View File

@ -43,21 +43,13 @@ ReturnValue_t BinarySemaphore::acquire(uint32_t timeoutMs) {
if(timeoutMs == SemaphoreIF::MAX_TIMEOUT) { if(timeoutMs == SemaphoreIF::MAX_TIMEOUT) {
timeout = SemaphoreIF::MAX_TIMEOUT; timeout = SemaphoreIF::MAX_TIMEOUT;
} }
else if(timeoutMs > BinarySemaphore::NO_TIMEOUT){ else if(timeoutMs > SemaphoreIF::NO_TIMEOUT){
timeout = pdMS_TO_TICKS(timeoutMs); timeout = pdMS_TO_TICKS(timeoutMs);
} }
return acquireWithTickTimeout(timeout);
BaseType_t returncode = xSemaphoreTake(handle, timeout);
if (returncode == pdPASS) {
return HasReturnvaluesIF::RETURN_OK;
}
else {
return SemaphoreIF::SEMAPHORE_TIMEOUT;
}
} }
ReturnValue_t BinarySemaphore::acquireWithTickTimeout( ReturnValue_t BinarySemaphore::acquireWithTickTimeout(TickType_t timeoutTicks) {
TickType_t timeoutTicks) {
if(handle == nullptr) { if(handle == nullptr) {
return SemaphoreIF::SEMAPHORE_NULLPOINTER; return SemaphoreIF::SEMAPHORE_NULLPOINTER;
} }
@ -65,20 +57,22 @@ ReturnValue_t BinarySemaphore::acquireWithTickTimeout(
BaseType_t returncode = xSemaphoreTake(handle, timeoutTicks); BaseType_t returncode = xSemaphoreTake(handle, timeoutTicks);
if (returncode == pdPASS) { if (returncode == pdPASS) {
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} else { }
else {
return SemaphoreIF::SEMAPHORE_TIMEOUT; return SemaphoreIF::SEMAPHORE_TIMEOUT;
} }
} }
ReturnValue_t BinarySemaphore::release() { ReturnValue_t BinarySemaphore::release() {
if (handle == nullptr) { if (handle == nullptr) {
return SEMAPHORE_NULLPOINTER; return SemaphoreIF::SEMAPHORE_NULLPOINTER;
} }
BaseType_t returncode = xSemaphoreGive(handle); BaseType_t returncode = xSemaphoreGive(handle);
if (returncode == pdPASS) { if (returncode == pdPASS) {
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} else { }
return SEMAPHORE_NOT_OWNED; else {
return SemaphoreIF::SEMAPHORE_NOT_OWNED;
} }
} }

View File

@ -2,7 +2,7 @@
#include <framework/osal/FreeRTOS/TaskManagement.h> #include <framework/osal/FreeRTOS/TaskManagement.h>
#include <framework/serviceinterface/ServiceInterfaceStream.h> #include <framework/serviceinterface/ServiceInterfaceStream.h>
CountingSemaphoreUsingTask::CountingSemaphoreUsingTask(uint8_t maxCount, CountingSemaphoreUsingTask::CountingSemaphoreUsingTask(const uint8_t maxCount,
uint8_t initCount): maxCount(maxCount) { uint8_t initCount): maxCount(maxCount) {
if(initCount > maxCount) { if(initCount > maxCount) {
sif::error << "CountingSemaphoreUsingTask: Max count bigger than " sif::error << "CountingSemaphoreUsingTask: Max count bigger than "
@ -17,13 +17,93 @@ CountingSemaphoreUsingTask::CountingSemaphoreUsingTask(uint8_t maxCount,
} }
ReturnValue_t CountingSemaphoreUsingTask::acquire(uint32_t timeoutMs) { ReturnValue_t CountingSemaphoreUsingTask::acquire(uint32_t timeoutMs) {
return HasReturnvaluesIF::RETURN_OK; TickType_t timeout = SemaphoreIF::NO_TIMEOUT;
if(timeoutMs == SemaphoreIF::MAX_TIMEOUT) {
timeout = SemaphoreIF::MAX_TIMEOUT;
}
else if(timeoutMs > SemaphoreIF::NO_TIMEOUT){
timeout = pdMS_TO_TICKS(timeoutMs);
}
BaseType_t returncode = ulTaskNotifyTake(pdFALSE, timeout);
if (returncode == pdPASS) {
currentCount--;
return HasReturnvaluesIF::RETURN_OK;
}
else {
return SemaphoreIF::SEMAPHORE_TIMEOUT;
}
}
ReturnValue_t CountingSemaphoreUsingTask::acquireWithTickTimeout(
TickType_t timeoutTicks) {
BaseType_t returncode = ulTaskNotifyTake(pdFALSE, timeoutTicks);
if (returncode == pdPASS) {
currentCount--;
return HasReturnvaluesIF::RETURN_OK;
}
else {
return SemaphoreIF::SEMAPHORE_TIMEOUT;
}
} }
ReturnValue_t CountingSemaphoreUsingTask::release() { ReturnValue_t CountingSemaphoreUsingTask::release() {
return HasReturnvaluesIF::RETURN_OK; if(currentCount == maxCount) {
return SemaphoreIF::SEMAPHORE_NOT_OWNED;
}
BaseType_t returncode = xTaskNotifyGive(handle);
if (returncode == pdPASS) {
currentCount++;
return HasReturnvaluesIF::RETURN_OK;
}
else {
// This should never happen
return HasReturnvaluesIF::RETURN_FAILED;
}
} }
uint8_t CountingSemaphoreUsingTask::getSemaphoreCounter() const { uint8_t CountingSemaphoreUsingTask::getSemaphoreCounter() const {
return 0; uint32_t notificationValue;
xTaskNotifyAndQuery(handle, 0, eNoAction, &notificationValue);
return notificationValue;
}
TaskHandle_t CountingSemaphoreUsingTask::getTaskHandle() {
return handle;
}
uint8_t CountingSemaphoreUsingTask::getSemaphoreCounterFromISR(
TaskHandle_t task) {
uint32_t notificationValue;
BaseType_t higherPriorityTaskWoken = 0;
xTaskNotifyAndQueryFromISR(task, 0, eNoAction, &notificationValue,
&higherPriorityTaskWoken);
if(higherPriorityTaskWoken == pdTRUE) {
TaskManagement::requestContextSwitch(CallContext::isr);
}
return notificationValue;
}
ReturnValue_t CountingSemaphoreUsingTask::release(
TaskHandle_t taskToNotify) {
BaseType_t returncode = xTaskNotifyGive(taskToNotify);
if (returncode == pdPASS) {
return HasReturnvaluesIF::RETURN_OK;
}
else {
// This should never happen.
return HasReturnvaluesIF::RETURN_FAILED;
}
}
ReturnValue_t CountingSemaphoreUsingTask::releaseFromISR(
TaskHandle_t taskToNotify, BaseType_t* higherPriorityTaskWoken) {
vTaskNotifyGiveFromISR(taskToNotify, 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;
} }

View File

@ -11,11 +11,39 @@ extern "C" {
class CountingSemaphoreUsingTask: public SemaphoreIF { class CountingSemaphoreUsingTask: public SemaphoreIF {
public: public:
CountingSemaphoreUsingTask(uint8_t maxCount, uint8_t initCount); CountingSemaphoreUsingTask(const uint8_t maxCount, uint8_t initCount);
ReturnValue_t acquire(uint32_t timeoutMs) override; ReturnValue_t acquire(uint32_t timeoutMs = SemaphoreIF::NO_TIMEOUT) override;
ReturnValue_t release() override; ReturnValue_t release() override;
uint8_t getSemaphoreCounter() const override; uint8_t getSemaphoreCounter() const override;
static uint8_t getSemaphoreCounterFromISR(TaskHandle_t task);
/**
* Acquire, using a timeout value in ticks
* @param timeoutTicks
* @return
*/
ReturnValue_t acquireWithTickTimeout(
TickType_t timeoutTicks= SemaphoreIF::NO_TIMEOUT);
/**
* Get handle to the task related to the semaphore.
* @return
*/
TaskHandle_t getTaskHandle();
/**
* Release semaphore of task by supplying task handle
* @param taskToNotify
* @return
*/
static ReturnValue_t release(TaskHandle_t taskToNotify);
/**
* Release seamphore of a task from an ISR.
* @param taskToNotify
* @return
*/
static ReturnValue_t releaseFromISR(TaskHandle_t taskToNotify,
BaseType_t* higherPriorityTaskWoken);
private: private:
TaskHandle_t handle; TaskHandle_t handle;

View File

@ -8,16 +8,17 @@ extern "C" {
// Make sure #define configUSE_COUNTING_SEMAPHORES 1 is set in // Make sure #define configUSE_COUNTING_SEMAPHORES 1 is set in
// free FreeRTOSConfig.h file. // free FreeRTOSConfig.h file.
CountingSemaphore::CountingSemaphore(uint8_t count, uint8_t initCount): CountingSemaphore::CountingSemaphore(const uint8_t maxCount, uint8_t initCount):
count(count), initCount(initCount) { maxCount(maxCount), initCount(initCount) {
handle = xSemaphoreCreateCounting(count, initCount); handle = xSemaphoreCreateCounting(maxCount, initCount);
if(handle == nullptr) { if(handle == nullptr) {
sif::error << "CountingSemaphore: Creation failure" << std::endl; sif::error << "CountingSemaphore: Creation failure" << std::endl;
} }
} }
CountingSemaphore::CountingSemaphore(CountingSemaphore&& other) { CountingSemaphore::CountingSemaphore(CountingSemaphore&& other):
handle = xSemaphoreCreateCounting(other.count, other.initCount); maxCount(other.maxCount), initCount(other.initCount) {
handle = xSemaphoreCreateCounting(other.maxCount, other.initCount);
if(handle == nullptr) { if(handle == nullptr) {
sif::error << "CountingSemaphore: Creation failure" << std::endl; sif::error << "CountingSemaphore: Creation failure" << std::endl;
} }
@ -25,7 +26,7 @@ CountingSemaphore::CountingSemaphore(CountingSemaphore&& other) {
CountingSemaphore& CountingSemaphore::operator =( CountingSemaphore& CountingSemaphore::operator =(
CountingSemaphore&& other) { CountingSemaphore&& other) {
handle = xSemaphoreCreateCounting(other.count, other.initCount); handle = xSemaphoreCreateCounting(other.maxCount, other.initCount);
if(handle == nullptr) { if(handle == nullptr) {
sif::error << "CountingSemaphore: Creation failure" << std::endl; sif::error << "CountingSemaphore: Creation failure" << std::endl;
} }

View File

@ -12,7 +12,7 @@
*/ */
class CountingSemaphore: public BinarySemaphore { class CountingSemaphore: public BinarySemaphore {
public: public:
CountingSemaphore(uint8_t count, uint8_t initCount); CountingSemaphore(const uint8_t maxCount, uint8_t initCount);
//! @brief Copy ctor, disabled //! @brief Copy ctor, disabled
CountingSemaphore(const CountingSemaphore&) = delete; CountingSemaphore(const CountingSemaphore&) = delete;
//! @brief Copy assignment, disabled //! @brief Copy assignment, disabled
@ -22,7 +22,7 @@ public:
//! @brief Move assignment //! @brief Move assignment
CountingSemaphore & operator=(CountingSemaphore &&); CountingSemaphore & operator=(CountingSemaphore &&);
private: private:
uint8_t count = 0; const uint8_t maxCount;
uint8_t initCount = 0; uint8_t initCount = 0;
}; };

View File

@ -23,7 +23,7 @@ public:
* @param argument Can be used to pass implementation specific information. * @param argument Can be used to pass implementation specific information.
* @return Pointer to newly created semaphore class instance. * @return Pointer to newly created semaphore class instance.
*/ */
SemaphoreIF* createBinarySemaphore(uint32_t argument = 0); SemaphoreIF* createBinarySemaphore(uint32_t arguments = 0);
/** /**
* Create a counting semaphore. * Create a counting semaphore.
* Creator functons for a counting semaphore which may be acquired multiple * Creator functons for a counting semaphore which may be acquired multiple
@ -33,8 +33,8 @@ public:
* @param argument Can be used to pass implementation specific information. * @param argument Can be used to pass implementation specific information.
* @return * @return
*/ */
SemaphoreIF* createCountingSemaphore(uint8_t maxCount, uint8_t initCount, SemaphoreIF* createCountingSemaphore(const uint8_t maxCount,
uint32_t argument = 0); uint8_t initCount, uint32_t arguments = 0);
void deleteSemaphore(SemaphoreIF* mutex); void deleteSemaphore(SemaphoreIF* mutex);