#include #include #include CountingSemaphoreUsingTask::CountingSemaphoreUsingTask(const uint8_t maxCount, uint8_t initCount): maxCount(maxCount) { if(initCount > maxCount) { sif::error << "CountingSemaphoreUsingTask: Max count bigger than " "intial cout. Setting initial count to max count." << std::endl; initCount = maxCount; } handle = TaskManagement::getCurrentTaskHandle(); if(handle == nullptr) { sif::error << "CountingSemaphoreUsingTask: Could not retrieve task " "handle. Please ensure the constructor was called inside a " "task." << std::endl; } uint32_t oldNotificationValue; xTaskNotifyAndQuery(handle, 0, eSetValueWithOverwrite, &oldNotificationValue); if(oldNotificationValue != 0) { sif::warning << "CountinSemaphoreUsingTask: Semaphore initiated but " "current notification value is not 0. Please ensure the " "notification value is not used for other purposes!" << std::endl; } for(int i = 0; i < initCount; i++) { xTaskNotifyGive(handle); } } CountingSemaphoreUsingTask::~CountingSemaphoreUsingTask() { // Clear notification value on destruction. // If this is not desired, don't call the destructor // (or implement a boolean which disables the reset) xTaskNotifyAndQuery(handle, 0, eSetValueWithOverwrite, nullptr); } ReturnValue_t CountingSemaphoreUsingTask::acquire(uint32_t timeoutMs) { 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); } return acquireWithTickTimeout(timeout); } ReturnValue_t CountingSemaphoreUsingTask::acquireWithTickTimeout( TickType_t timeoutTicks) { // Decrement notfication value without resetting it. BaseType_t oldCount = ulTaskNotifyTake(pdFALSE, timeoutTicks); if (getSemaphoreCounter() == oldCount - 1) { return HasReturnvaluesIF::RETURN_OK; } else { return SemaphoreIF::SEMAPHORE_TIMEOUT; } } ReturnValue_t CountingSemaphoreUsingTask::release() { if(getSemaphoreCounter() == maxCount) { return SemaphoreIF::SEMAPHORE_NOT_OWNED; } return release(handle); } ReturnValue_t CountingSemaphoreUsingTask::release( TaskHandle_t taskToNotify) { BaseType_t returncode = xTaskNotifyGive(taskToNotify); if (returncode == pdPASS) { return HasReturnvaluesIF::RETURN_OK; } else { // This should never happen. return HasReturnvaluesIF::RETURN_FAILED; } } uint8_t CountingSemaphoreUsingTask::getSemaphoreCounter() const { uint32_t notificationValue = 0; xTaskNotifyAndQuery(handle, 0, eNoAction, ¬ificationValue); return notificationValue; } TaskHandle_t CountingSemaphoreUsingTask::getTaskHandle() { return handle; } ReturnValue_t CountingSemaphoreUsingTask::releaseFromISR( TaskHandle_t taskToNotify, BaseType_t* higherPriorityTaskWoken) { vTaskNotifyGiveFromISR(taskToNotify, higherPriorityTaskWoken); return HasReturnvaluesIF::RETURN_OK; } uint8_t CountingSemaphoreUsingTask::getSemaphoreCounterFromISR( TaskHandle_t task, BaseType_t* higherPriorityTaskWoken) { uint32_t notificationValue; xTaskNotifyAndQueryFromISR(task, 0, eNoAction, ¬ificationValue, higherPriorityTaskWoken); return notificationValue; } uint8_t CountingSemaphoreUsingTask::getMaxCount() const { return maxCount; }