Merge branch 'mueller_framework' into front_branch

This commit is contained in:
Robin Müller 2020-05-29 17:56:06 +02:00
commit c34c6238c6
37 changed files with 935 additions and 233 deletions

View File

@ -13,7 +13,7 @@
class MutexIF { class MutexIF {
public: public:
static const uint32_t NO_TIMEOUT; //!< Needs to be defined in implementation. static const uint32_t NO_TIMEOUT; //!< Needs to be defined in implementation.
static const uint32_t MAX_TIMEOUT;
static const uint8_t INTERFACE_ID = CLASS_ID::MUTEX_IF; static const uint8_t INTERFACE_ID = CLASS_ID::MUTEX_IF;
/** /**
* The system lacked the necessary resources (other than memory) to initialize another mutex. * The system lacked the necessary resources (other than memory) to initialize another mutex.

View File

@ -0,0 +1,91 @@
#include <framework/osal/FreeRTOS/BinSemaphUsingTask.h>
#include <framework/osal/FreeRTOS/TaskManagement.h>
#include <framework/serviceinterface/ServiceInterfaceStream.h>
BinarySemaphoreUsingTask::BinarySemaphoreUsingTask() {
handle = TaskManagement::getCurrentTaskHandle();
if(handle == nullptr) {
sif::error << "Could not retrieve task handle. Please ensure the"
"constructor was called inside a task." << std::endl;
}
xTaskNotifyGive(handle);
}
BinarySemaphoreUsingTask::~BinarySemaphoreUsingTask() {
// Clear notification value on destruction.
xTaskNotifyAndQuery(handle, 0, eSetValueWithOverwrite, nullptr);
}
ReturnValue_t BinarySemaphoreUsingTask::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 BinarySemaphoreUsingTask::acquireWithTickTimeout(
TickType_t timeoutTicks) {
BaseType_t returncode = ulTaskNotifyTake(pdTRUE, timeoutTicks);
if (returncode == pdPASS) {
return HasReturnvaluesIF::RETURN_OK;
}
else {
return SemaphoreIF::SEMAPHORE_TIMEOUT;
}
}
ReturnValue_t BinarySemaphoreUsingTask::release() {
return release(this->handle);
}
ReturnValue_t BinarySemaphoreUsingTask::release(
TaskHandle_t taskHandle) {
if(getSemaphoreCounter(taskHandle) == 1) {
return SemaphoreIF::SEMAPHORE_NOT_OWNED;
}
BaseType_t returncode = xTaskNotifyGive(taskHandle);
if (returncode == pdPASS) {
return HasReturnvaluesIF::RETURN_OK;
}
else {
// This should never happen.
return HasReturnvaluesIF::RETURN_FAILED;
}
}
TaskHandle_t BinarySemaphoreUsingTask::getTaskHandle() {
return handle;
}
uint8_t BinarySemaphoreUsingTask::getSemaphoreCounter() const {
return getSemaphoreCounter(this->handle);
}
uint8_t BinarySemaphoreUsingTask::getSemaphoreCounter(
TaskHandle_t taskHandle) {
uint32_t notificationValue;
xTaskNotifyAndQuery(taskHandle, 0, eNoAction, &notificationValue);
return notificationValue;
}
// Be careful with the stack size here. This is called from an ISR!
ReturnValue_t BinarySemaphoreUsingTask::releaseFromISR(
TaskHandle_t taskHandle, BaseType_t * higherPriorityTaskWoken) {
if(getSemaphoreCounterFromISR(taskHandle, higherPriorityTaskWoken) == 1) {
return SemaphoreIF::SEMAPHORE_NOT_OWNED;
}
vTaskNotifyGiveFromISR(taskHandle, higherPriorityTaskWoken);
return HasReturnvaluesIF::RETURN_OK;
}
uint8_t BinarySemaphoreUsingTask::getSemaphoreCounterFromISR(
TaskHandle_t taskHandle, BaseType_t* higherPriorityTaskWoken) {
uint32_t notificationValue = 0;
xTaskNotifyAndQueryFromISR(taskHandle, 0, eNoAction, &notificationValue,
higherPriorityTaskWoken);
return notificationValue;
}

View File

@ -0,0 +1,75 @@
#ifndef FRAMEWORK_OSAL_FREERTOS_BINSEMAPHUSINGTASK_H_
#define FRAMEWORK_OSAL_FREERTOS_BINSEMAPHUSINGTASK_H_
#include <framework/returnvalues/HasReturnvaluesIF.h>
#include <framework/tasks/SemaphoreIF.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
/**
* @brief Binary Semaphore implementation using the task notification value.
* The notification value should therefore not be used
* for other purposes.
* @details
* Additional information: https://www.freertos.org/RTOS-task-notifications.html
* and general semaphore documentation.
*/
class BinarySemaphoreUsingTask: public SemaphoreIF,
public HasReturnvaluesIF {
public:
static const uint8_t INTERFACE_ID = CLASS_ID::SEMAPHORE_IF;
//! @brief Default ctor
BinarySemaphoreUsingTask();
//! @brief Default dtor
virtual~ BinarySemaphoreUsingTask();
ReturnValue_t acquire(uint32_t timeoutMs =
SemaphoreIF::NO_TIMEOUT) override;
ReturnValue_t release() override;
uint8_t getSemaphoreCounter() const override;
static uint8_t getSemaphoreCounter(TaskHandle_t taskHandle);
static uint8_t getSemaphoreCounterFromISR(TaskHandle_t taskHandle,
BaseType_t* higherPriorityTaskWoken);
/**
* Same as acquire() with timeout in FreeRTOS ticks.
* @param timeoutTicks
* @return - @c RETURN_OK on success
* - @c RETURN_FAILED on failure
*/
ReturnValue_t acquireWithTickTimeout(TickType_t timeoutTicks =
SemaphoreIF::NO_TIMEOUT);
/**
* 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 release(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. A context switch should be requested
* from an ISR if this is the case (see TaskManagement functions)
* @return - @c RETURN_OK on success
* - @c RETURN_FAILED on failure
*/
static ReturnValue_t releaseFromISR(TaskHandle_t taskToNotify,
BaseType_t * higherPriorityTaskWoken);
protected:
TaskHandle_t handle;
};
#endif /* FRAMEWORK_OSAL_FREERTOS_BINSEMAPHUSINGTASK_H_ */

View File

@ -1,6 +1,5 @@
#include <framework/osal/FreeRTOS/BinarySemaphore.h> #include <framework/osal/FreeRTOS/BinarySemaphore.h>
#include <framework/osal/FreeRTOS/TaskManagement.h> #include <framework/osal/FreeRTOS/TaskManagement.h>
#include <framework/serviceinterface/ServiceInterfaceStream.h> #include <framework/serviceinterface/ServiceInterfaceStream.h>
BinarySemaphore::BinarySemaphore() { BinarySemaphore::BinarySemaphore() {
@ -8,6 +7,7 @@ BinarySemaphore::BinarySemaphore() {
if(handle == nullptr) { if(handle == nullptr) {
sif::error << "Semaphore: Binary semaph creation failure" << std::endl; sif::error << "Semaphore: Binary semaph creation failure" << std::endl;
} }
// Initiated semaphore must be given before it can be taken.
xSemaphoreGive(handle); xSemaphoreGive(handle);
} }
@ -35,104 +35,69 @@ BinarySemaphore& BinarySemaphore::operator =(
return *this; return *this;
} }
ReturnValue_t BinarySemaphore::takeBinarySemaphore(uint32_t timeoutMs) { ReturnValue_t BinarySemaphore::acquire(uint32_t timeoutMs) {
if(handle == nullptr) { TickType_t timeout = SemaphoreIF::NO_TIMEOUT;
return SEMAPHORE_NULLPOINTER; if(timeoutMs == SemaphoreIF::MAX_TIMEOUT) {
timeout = SemaphoreIF::MAX_TIMEOUT;
} }
TickType_t timeout = BinarySemaphore::NO_BLOCK_TICKS; else if(timeoutMs > SemaphoreIF::NO_TIMEOUT){
if(timeoutMs == BinarySemaphore::BLOCK_TIMEOUT) {
timeout = BinarySemaphore::BLOCK_TIMEOUT_TICKS;
}
else if(timeoutMs > BinarySemaphore::NO_BLOCK_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 SEMAPHORE_TIMEOUT;
}
} }
ReturnValue_t BinarySemaphore::takeBinarySemaphoreTickTimeout( ReturnValue_t BinarySemaphore::acquireWithTickTimeout(TickType_t timeoutTicks) {
TickType_t timeoutTicks) {
if(handle == nullptr) { if(handle == nullptr) {
return SEMAPHORE_NULLPOINTER; return SemaphoreIF::SEMAPHORE_INVALID;
} }
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 { }
return SEMAPHORE_TIMEOUT; else {
return SemaphoreIF::SEMAPHORE_TIMEOUT;
} }
} }
ReturnValue_t BinarySemaphore::giveBinarySemaphore() { ReturnValue_t BinarySemaphore::release() {
if (handle == nullptr) { return release(handle);
return SEMAPHORE_NULLPOINTER;
} }
BaseType_t returncode = xSemaphoreGive(handle);
ReturnValue_t BinarySemaphore::release(SemaphoreHandle_t semaphore) {
if (semaphore == nullptr) {
return SemaphoreIF::SEMAPHORE_INVALID;
}
BaseType_t returncode = xSemaphoreGive(semaphore);
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;
}
}
uint8_t BinarySemaphore::getSemaphoreCounter() const {
return uxSemaphoreGetCount(handle);
} }
SemaphoreHandle_t BinarySemaphore::getSemaphore() { SemaphoreHandle_t BinarySemaphore::getSemaphore() {
return handle; 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);
handle = xSemaphoreCreateBinary();
xSemaphoreGive(handle);
}
}
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! // Be careful with the stack size here. This is called from an ISR!
ReturnValue_t BinarySemaphore::giveBinarySemaphoreFromISR(SemaphoreHandle_t semaphore, ReturnValue_t BinarySemaphore::releaseFromISR(
BaseType_t * higherPriorityTaskWoken) { SemaphoreHandle_t semaphore, BaseType_t * higherPriorityTaskWoken) {
if (semaphore == nullptr) { if (semaphore == nullptr) {
return SEMAPHORE_NULLPOINTER; return SemaphoreIF::SEMAPHORE_INVALID;
} }
BaseType_t returncode = xSemaphoreGiveFromISR(semaphore, higherPriorityTaskWoken); BaseType_t returncode = xSemaphoreGiveFromISR(semaphore,
higherPriorityTaskWoken);
if (returncode == pdPASS) { 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; return HasReturnvaluesIF::RETURN_OK;
} else { }
return SEMAPHORE_NOT_OWNED; else {
return SemaphoreIF::SEMAPHORE_NOT_OWNED;
} }
} }

View File

@ -3,16 +3,10 @@
#include <framework/returnvalues/HasReturnvaluesIF.h> #include <framework/returnvalues/HasReturnvaluesIF.h>
#include <framework/tasks/SemaphoreIF.h> #include <framework/tasks/SemaphoreIF.h>
extern "C" {
#include <freertos/FreeRTOS.h> #include <freertos/FreeRTOS.h>
#include <freertos/semphr.h> #include <freertos/semphr.h>
}
// 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 * @brief OS Tool to achieve synchronization of between tasks or between
* task and ISR. The default semaphore implementation creates a * task and ISR. The default semaphore implementation creates a
@ -20,6 +14,12 @@ extern "C" {
* @details * @details
* Documentation: https://www.freertos.org/Embedded-RTOS-Binary-Semaphores.html * 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 * @author R. Mueller
* @ingroup osal * @ingroup osal
*/ */
@ -28,15 +28,6 @@ class BinarySemaphore: public SemaphoreIF,
public: public:
static const uint8_t INTERFACE_ID = CLASS_ID::SEMAPHORE_IF; 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;
//! @brief Default ctor //! @brief Default ctor
BinarySemaphore(); BinarySemaphore();
//! @brief Copy ctor, deleted explicitely. //! @brief Copy ctor, deleted explicitely.
@ -50,10 +41,7 @@ public:
//! @brief Destructor //! @brief Destructor
virtual ~BinarySemaphore(); virtual ~BinarySemaphore();
ReturnValue_t acquire(uint32_t timeoutMs = uint8_t getSemaphoreCounter() const override;
BinarySemaphore::NO_BLOCK_TIMEOUT) override;
ReturnValue_t release() override;
uint8_t getSemaphoreCounter() override;
/** /**
* Take the binary semaphore. * Take the binary semaphore.
@ -62,26 +50,27 @@ public:
* for example by an ISR or another task. * for example by an ISR or another task.
* @param timeoutMs * @param timeoutMs
* @return -@c RETURN_OK on success * @return -@c RETURN_OK on success
* -@c RETURN_FAILED on failure * -@c SemaphoreIF::SEMAPHORE_TIMEOUT on timeout
*/ */
ReturnValue_t takeBinarySemaphore(uint32_t timeoutMs = ReturnValue_t acquire(uint32_t timeoutMs =
BinarySemaphore::NO_BLOCK_TIMEOUT); SemaphoreIF::NO_TIMEOUT) override;
/** /**
* Same as lockBinarySemaphore() with timeout in FreeRTOS ticks. * 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 SemaphoreIF::SEMAPHORE_TIMEOUT on timeout
*/ */
ReturnValue_t takeBinarySemaphoreTickTimeout(TickType_t timeoutTicks = ReturnValue_t acquireWithTickTimeout(TickType_t timeoutTicks =
BinarySemaphore::NO_BLOCK_TICKS); BinarySemaphore::NO_TIMEOUT);
/** /**
* Give back the binary semaphore * Release the binary semaphore.
* @return -@c RETURN_OK on success * @return -@c RETURN_OK on success
* - @c RETURN_FAILED on failure * -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if the semaphores is
* already available.
*/ */
ReturnValue_t giveBinarySemaphore(); ReturnValue_t release() override;
/** /**
* Get Handle to the semaphore. * Get Handle to the semaphore.
@ -89,28 +78,26 @@ public:
*/ */
SemaphoreHandle_t getSemaphore(); SemaphoreHandle_t getSemaphore();
/**
* Reset the semaphore.
*/
void resetSemaphore();
/** /**
* Wrapper function to give back semaphore from handle * Wrapper function to give back semaphore from handle
* @param semaphore * @param semaphore
* @return -@c RETURN_OK on success * @return -@c RETURN_OK on success
* - @c RETURN_FAILED on failure * -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if the semaphores is
* already available.
*/ */
static ReturnValue_t giveBinarySemaphore(SemaphoreHandle_t semaphore); static ReturnValue_t release(SemaphoreHandle_t semaphore);
/** /**
* 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
* @param semaphore * @param semaphore
* @param higherPriorityTaskWoken This will be set to pdPASS if a task with a higher priority * @param higherPriorityTaskWoken This will be set to pdPASS if a task with
* was unblocked * a higher priority was unblocked. A context switch from an ISR should
* then be requested (see TaskManagement functions)
* @return -@c RETURN_OK on success * @return -@c RETURN_OK on success
* - @c RETURN_FAILED on failure * -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if the semaphores is
* already available.
*/ */
static ReturnValue_t giveBinarySemaphoreFromISR(SemaphoreHandle_t semaphore, static ReturnValue_t releaseFromISR(SemaphoreHandle_t semaphore,
BaseType_t * higherPriorityTaskWoken); BaseType_t * higherPriorityTaskWoken);
protected: protected:

View File

@ -1,19 +1,18 @@
#include <framework/timemanager/Clock.h> #include <framework/timemanager/Clock.h>
#include <framework/globalfunctions/timevalOperations.h> #include <framework/globalfunctions/timevalOperations.h>
#include <framework/osal/FreeRTOS/Timekeeper.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <stdlib.h> #include <stdlib.h>
#include "Timekeeper.h" #include <time.h>
extern "C" {
#include <FreeRTOS.h>
#include <task.h>
}
//TODO sanitize input? //TODO sanitize input?
//TODO much of this code can be reused for tick-only systems //TODO much of this code can be reused for tick-only systems
uint16_t Clock::leapSeconds = 0; uint16_t Clock::leapSeconds = 0;
MutexIF* Clock::timeMutex = NULL; MutexIF* Clock::timeMutex = nullptr;
uint32_t Clock::getTicksPerSecond(void) { uint32_t Clock::getTicksPerSecond(void) {
return 1000; return 1000;
@ -130,7 +129,7 @@ ReturnValue_t Clock::convertTimevalToJD2000(timeval time, double* JD2000) {
ReturnValue_t Clock::convertUTCToTT(timeval utc, timeval* tt) { ReturnValue_t Clock::convertUTCToTT(timeval utc, timeval* tt) {
//SHOULDDO: works not for dates in the past (might have less leap seconds) //SHOULDDO: works not for dates in the past (might have less leap seconds)
if (timeMutex == NULL) { if (timeMutex == nullptr) {
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }

View File

@ -0,0 +1,110 @@
#include <framework/osal/FreeRTOS/CountingSemaphUsingTask.h>
#include <framework/osal/FreeRTOS/TaskManagement.h>
#include <framework/serviceinterface/ServiceInterfaceStream.h>
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, &notificationValue);
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, &notificationValue,
higherPriorityTaskWoken);
return notificationValue;
}
uint8_t CountingSemaphoreUsingTask::getMaxCount() const {
return maxCount;
}

View File

@ -0,0 +1,100 @@
#ifndef FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHUSINGTASK_H_
#define FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHUSINGTASK_H_
#include <framework/osal/FreeRTOS/CountingSemaphUsingTask.h>
#include <framework/tasks/SemaphoreIF.h>
extern "C" {
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
}
/**
* @brief Couting Semaphore implementation which uses the notification value
* of the task. The notification value should therefore not be used
* for other purposes.
* @details
* Additional information: https://www.freertos.org/RTOS-task-notifications.html
* and general semaphore documentation.
*/
class CountingSemaphoreUsingTask: public SemaphoreIF {
public:
CountingSemaphoreUsingTask(const uint8_t maxCount, uint8_t initCount);
virtual ~CountingSemaphoreUsingTask();
/**
* Acquire the counting semaphore.
* If no semaphores are available, the task will be blocked
* for a maximum of #timeoutMs or until one is given back,
* for example by an ISR or another task.
* @param timeoutMs
* @return -@c RETURN_OK on success
* -@c SemaphoreIF::SEMAPHORE_TIMEOUT on timeout
*/
ReturnValue_t acquire(uint32_t timeoutMs = SemaphoreIF::NO_TIMEOUT) override;
/**
* Release a semaphore, increasing the number of available counting
* semaphores up to the #maxCount value.
* @return -@c RETURN_OK on success
* -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if #maxCount semaphores are
* already available.
*/
ReturnValue_t release() override;
uint8_t getSemaphoreCounter() const override;
/**
* Get the semaphore counter from an ISR.
* @param task
* @param higherPriorityTaskWoken This will be set to pdPASS if a task with
* a higher priority was unblocked. A context switch should be requested
* from an ISR if this is the case (see TaskManagement functions)
* @return
*/
static uint8_t getSemaphoreCounterFromISR(TaskHandle_t task,
BaseType_t* higherPriorityTaskWoken);
/**
* Acquire with a timeout value in ticks
* @param timeoutTicks
* @return -@c RETURN_OK on success
* -@c SemaphoreIF::SEMAPHORE_TIMEOUT on timeout
*/
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 -@c RETURN_OK on success
* -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if #maxCount semaphores are
* already available.
*/
static ReturnValue_t release(TaskHandle_t taskToNotify);
/**
* Release seamphore of a task from an ISR.
* @param taskToNotify
* @param higherPriorityTaskWoken This will be set to pdPASS if a task with
* a higher priority was unblocked. A context switch should be requested
* from an ISR if this is the case (see TaskManagement functions)
* @return -@c RETURN_OK on success
* -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if #maxCount semaphores are
* already available.
*/
static ReturnValue_t releaseFromISR(TaskHandle_t taskToNotify,
BaseType_t* higherPriorityTaskWoken);
uint8_t getMaxCount() const;
private:
TaskHandle_t handle;
const uint8_t maxCount;
};
#endif /* FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHUSINGTASK_H_ */

View File

@ -1,18 +1,28 @@
#include <framework/osal/FreeRTOS/CountingSemaphore.h> #include <framework/osal/FreeRTOS/CountingSemaphore.h>
#include <framework/serviceinterface/ServiceInterfaceStream.h> #include <framework/serviceinterface/ServiceInterfaceStream.h>
#include <framework/osal/FreeRTOS/TaskManagement.h>
#include <freertos/semphr.h>
// 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); if(initCount > maxCount) {
sif::error << "CountingSemaphoreUsingTask: Max count bigger than "
"intial cout. Setting initial count to max count." << std::endl;
initCount = maxCount;
}
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;
} }
@ -20,9 +30,14 @@ 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;
} }
return * this; return * this;
} }
uint8_t CountingSemaphore::getMaxCount() const {
return maxCount;
}

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
@ -21,8 +21,13 @@ public:
CountingSemaphore (CountingSemaphore &&); CountingSemaphore (CountingSemaphore &&);
//! @brief Move assignment //! @brief Move assignment
CountingSemaphore & operator=(CountingSemaphore &&); CountingSemaphore & operator=(CountingSemaphore &&);
/* Same API as binary semaphore otherwise. acquire() can be called
* until there are not semaphores left and release() can be called
* until maxCount is reached. */
uint8_t getMaxCount() const;
private: private:
uint8_t count = 0; const uint8_t maxCount;
uint8_t initCount = 0; uint8_t initCount = 0;
}; };

View File

@ -1,4 +1,4 @@
#include "MessageQueue.h" #include <framework/osal/FreeRTOS/MessageQueue.h>
#include <framework/serviceinterface/ServiceInterfaceStream.h> #include <framework/serviceinterface/ServiceInterfaceStream.h>
@ -124,7 +124,7 @@ ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo,
bool ignoreFault, CallContext callContext) { bool ignoreFault, CallContext callContext) {
message->setSender(sentFrom); message->setSender(sentFrom);
BaseType_t result; BaseType_t result;
if(callContext == CallContext::task) { if(callContext == CallContext::TASK) {
result = xQueueSendToBack(reinterpret_cast<QueueHandle_t>(sendTo), result = xQueueSendToBack(reinterpret_cast<QueueHandle_t>(sendTo),
static_cast<const void*>(message->getBuffer()), 0); static_cast<const void*>(message->getBuffer()), 0);
} }

View File

@ -6,11 +6,8 @@
#include <framework/ipc/MessageQueueMessage.h> #include <framework/ipc/MessageQueueMessage.h>
#include <framework/osal/FreeRTOS/TaskManagement.h> #include <framework/osal/FreeRTOS/TaskManagement.h>
extern "C" {
#include <freertos/FreeRTOS.h> #include <freertos/FreeRTOS.h>
#include <freertos/queue.h> #include <freertos/queue.h>
}
// TODO: this class assumes that MessageQueueId_t is the same size as void* // 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 // (the FreeRTOS handle type), compiler will catch this but it might be nice
@ -164,11 +161,7 @@ public:
MessageQueueId_t getId() const; MessageQueueId_t getId() const;
/** /**
<<<<<<< HEAD
* \brief This method is a simple setter for the default destination.
=======
* @brief This method is a simple setter for the default destination. * @brief This method is a simple setter for the default destination.
>>>>>>> mueller_BinSempahInterface
*/ */
void setDefaultDestination(MessageQueueId_t defaultDestination); void setDefaultDestination(MessageQueueId_t defaultDestination);
/** /**
@ -199,7 +192,7 @@ protected:
*/ */
static ReturnValue_t sendMessageFromMessageQueue(MessageQueueId_t sendTo, static ReturnValue_t sendMessageFromMessageQueue(MessageQueueId_t sendTo,
MessageQueueMessage* message, MessageQueueId_t sentFrom = NO_QUEUE, MessageQueueMessage* message, MessageQueueId_t sentFrom = NO_QUEUE,
bool ignoreFault=false, CallContext callContext = CallContext::task); bool ignoreFault=false, CallContext callContext = CallContext::TASK);
static ReturnValue_t handleSendResult(BaseType_t result, bool ignoreFault); static ReturnValue_t handleSendResult(BaseType_t result, bool ignoreFault);
@ -209,7 +202,7 @@ private:
MessageQueueId_t defaultDestination = 0; MessageQueueId_t defaultDestination = 0;
MessageQueueId_t lastPartner = 0; MessageQueueId_t lastPartner = 0;
//!< Stores the current system context //!< Stores the current system context
CallContext callContext = CallContext::task; CallContext callContext = CallContext::TASK;
}; };
#endif /* MESSAGEQUEUE_H_ */ #endif /* MESSAGEQUEUE_H_ */

View File

@ -1,29 +1,33 @@
#include "Mutex.h" #include <framework/osal/FreeRTOS/Mutex.h>
#include <framework/serviceinterface/ServiceInterfaceStream.h> #include <framework/serviceinterface/ServiceInterfaceStream.h>
const uint32_t MutexIF::NO_TIMEOUT = 0; const uint32_t MutexIF::NO_TIMEOUT = 0;
const uint32_t MutexIF::MAX_TIMEOUT = portMAX_DELAY;
Mutex::Mutex() { Mutex::Mutex() {
handle = xSemaphoreCreateMutex(); handle = xSemaphoreCreateMutex();
if(handle == NULL) { if(handle == nullptr) {
sif::error << "Mutex creation failure" << std::endl; sif::error << "Mutex: Creation failure" << std::endl;
} }
} }
Mutex::~Mutex() { Mutex::~Mutex() {
if (handle != 0) { if (handle != nullptr) {
vSemaphoreDelete(handle); vSemaphoreDelete(handle);
} }
} }
ReturnValue_t Mutex::lockMutex(uint32_t timeoutMs) { ReturnValue_t Mutex::lockMutex(uint32_t timeoutMs) {
if (handle == 0) { if (handle == nullptr) {
return MutexIF::MUTEX_NOT_FOUND; return MutexIF::MUTEX_NOT_FOUND;
} }
TickType_t timeout = portMAX_DELAY; TickType_t timeout = MutexIF::NO_TIMEOUT;
if (timeoutMs != NO_TIMEOUT) { if(timeoutMs == MutexIF::MAX_TIMEOUT) {
timeout = MutexIF::MAX_TIMEOUT;
}
else if(timeoutMs > MutexIF::NO_TIMEOUT){
timeout = pdMS_TO_TICKS(timeoutMs); timeout = pdMS_TO_TICKS(timeoutMs);
} }
@ -36,7 +40,7 @@ ReturnValue_t Mutex::lockMutex(uint32_t timeoutMs) {
} }
ReturnValue_t Mutex::unlockMutex() { ReturnValue_t Mutex::unlockMutex() {
if (handle == 0) { if (handle == nullptr) {
return MutexIF::MUTEX_NOT_FOUND; return MutexIF::MUTEX_NOT_FOUND;
} }
BaseType_t returncode = xSemaphoreGive(handle); BaseType_t returncode = xSemaphoreGive(handle);

View File

@ -3,11 +3,8 @@
#include <framework/ipc/MutexIF.h> #include <framework/ipc/MutexIF.h>
extern "C" {
#include <freertos/FreeRTOS.h> #include <freertos/FreeRTOS.h>
#include <freertos/semphr.h> #include <freertos/semphr.h>
}
/** /**
* @brief OS component to implement MUTual EXclusion * @brief OS component to implement MUTual EXclusion
@ -21,7 +18,7 @@ class Mutex : public MutexIF {
public: public:
Mutex(); Mutex();
~Mutex(); ~Mutex();
ReturnValue_t lockMutex(uint32_t timeoutMs) override; ReturnValue_t lockMutex(uint32_t timeoutMs = MutexIF::MAX_TIMEOUT) override;
ReturnValue_t unlockMutex() override; ReturnValue_t unlockMutex() override;
private: private:
SemaphoreHandle_t handle; SemaphoreHandle_t handle;

View File

@ -1,5 +1,7 @@
#include <framework/osal/FreeRTOS/BinarySemaphore.h> #include <framework/osal/FreeRTOS/BinarySemaphore.h>
#include <framework/osal/FreeRTOS/BinSemaphUsingTask.h>
#include <framework/osal/FreeRTOS/CountingSemaphore.h> #include <framework/osal/FreeRTOS/CountingSemaphore.h>
#include <framework/osal/FreeRTOS/CountingSemaphUsingTask.h>
#include <framework/tasks/SemaphoreFactory.h> #include <framework/tasks/SemaphoreFactory.h>
#include <framework/serviceinterface/ServiceInterfaceStream.h> #include <framework/serviceinterface/ServiceInterfaceStream.h>
@ -7,6 +9,9 @@ SemaphoreFactory* SemaphoreFactory::factoryInstance = nullptr;
const uint32_t SemaphoreIF::NO_TIMEOUT = 0; const uint32_t SemaphoreIF::NO_TIMEOUT = 0;
const uint32_t SemaphoreIF::MAX_TIMEOUT = portMAX_DELAY; const uint32_t SemaphoreIF::MAX_TIMEOUT = portMAX_DELAY;
static const uint32_t USE_REGULAR_SEMAPHORES = 0;
static const uint32_t USE_TASK_NOTIFICATIONS = 1;
SemaphoreFactory::SemaphoreFactory() { SemaphoreFactory::SemaphoreFactory() {
} }
@ -21,15 +26,36 @@ SemaphoreFactory* SemaphoreFactory::instance() {
return SemaphoreFactory::factoryInstance; return SemaphoreFactory::factoryInstance;
} }
SemaphoreIF* SemaphoreFactory::createBinarySemaphore() { SemaphoreIF* SemaphoreFactory::createBinarySemaphore(uint32_t argument) {
if(argument == USE_REGULAR_SEMAPHORES) {
return new BinarySemaphore();
}
else if(argument == USE_TASK_NOTIFICATIONS) {
return new BinarySemaphoreUsingTask();
}
else {
sif::warning << "SemaphoreFactory: Invalid argument, return regular"
"binary semaphore" << std::endl;
return new BinarySemaphore(); return new BinarySemaphore();
} }
SemaphoreIF* SemaphoreFactory::createCountingSemaphore(uint8_t count,
uint8_t initCount) {
return new CountingSemaphore(count, initCount);
} }
void SemaphoreFactory::deleteMutex(SemaphoreIF* semaphore) { SemaphoreIF* SemaphoreFactory::createCountingSemaphore(uint8_t maxCount,
uint8_t initCount, uint32_t argument) {
if(argument == USE_REGULAR_SEMAPHORES) {
return new CountingSemaphore(maxCount, initCount);
}
else if(argument == USE_TASK_NOTIFICATIONS) {
return new CountingSemaphoreUsingTask(maxCount, initCount);
}
else {
sif::warning << "SemaphoreFactory: Invalid argument, return regular"
"binary semaphore" << std::endl;
return new CountingSemaphore(maxCount, initCount);
}
}
void SemaphoreFactory::deleteSemaphore(SemaphoreIF* semaphore) {
delete semaphore; delete semaphore;
} }

View File

@ -5,8 +5,8 @@ void TaskManagement::requestContextSwitchFromTask() {
} }
void TaskManagement::requestContextSwitch( void TaskManagement::requestContextSwitch(
CallContext callContext = CallContext::task) { CallContext callContext = CallContext::TASK) {
if(callContext == CallContext::isr) { if(callContext == CallContext::ISR) {
// This function depends on the partmacro.h definition for the specific device // This function depends on the partmacro.h definition for the specific device
requestContextSwitchFromISR(); requestContextSwitchFromISR();
} else { } else {

View File

@ -21,9 +21,9 @@ extern "C" void requestContextSwitchFromISR();
* has different functions for handling semaphores and messages from within * has different functions for handling semaphores and messages from within
* an ISR and task. * an ISR and task.
*/ */
enum CallContext { enum class CallContext {
task = 0x00,//!< task_context TASK = 0x00,//!< task_context
isr = 0xFF //!< isr_context ISR = 0xFF //!< isr_context
}; };

View File

@ -1,18 +1,13 @@
/**
* @file Timekeeper.cpp
* @date
*/
#include <framework/osal/FreeRTOS/Timekeeper.h> #include <framework/osal/FreeRTOS/Timekeeper.h>
extern "C" { #include "FreeRTOSConfig.h"
#include <task.h>
}
Timekeeper * Timekeeper::myinstance = nullptr; Timekeeper * Timekeeper::myinstance = nullptr;
Timekeeper::Timekeeper() : offset( { 0, 0 } ) {} Timekeeper::Timekeeper() : offset( { 0, 0 } ) {}
Timekeeper::~Timekeeper() {}
const timeval& Timekeeper::getOffset() const { const timeval& Timekeeper::getOffset() const {
return offset; return offset;
} }
@ -28,8 +23,6 @@ void Timekeeper::setOffset(const timeval& offset) {
this->offset = offset; this->offset = offset;
} }
Timekeeper::~Timekeeper() {}
timeval Timekeeper::ticksToTimeval(TickType_t ticks) { timeval Timekeeper::ticksToTimeval(TickType_t ticks) {
timeval uptime; timeval uptime;
uptime.tv_sec = ticks / configTICK_RATE_HZ; uptime.tv_sec = ticks / configTICK_RATE_HZ;

View File

@ -2,9 +2,9 @@
#define FRAMEWORK_OSAL_FREERTOS_TIMEKEEPER_H_ #define FRAMEWORK_OSAL_FREERTOS_TIMEKEEPER_H_
#include <framework/timemanager/Clock.h> #include <framework/timemanager/Clock.h>
extern "C" {
#include <FreeRTOS.h> #include <freertos/FreeRTOS.h>
} #include <freertos/task.h>
/** /**

View File

@ -0,0 +1,148 @@
#include <framework/osal/linux/BinarySemaphore.h>
#include <framework/serviceinterface/ServiceInterfaceStream.h>
extern "C" {
#include <errno.h>
#include <string.h>
}
BinarySemaphore::BinarySemaphore() {
// Using unnamed semaphores for now
initSemaphore();
}
BinarySemaphore::~BinarySemaphore() {
sem_destroy(&handle);
}
BinarySemaphore::BinarySemaphore(BinarySemaphore&& s) {
initSemaphore();
}
BinarySemaphore& BinarySemaphore::operator =(
BinarySemaphore&& s) {
initSemaphore();
return * this;
}
ReturnValue_t BinarySemaphore::acquire(uint32_t timeoutMs) {
int result = 0;
if(timeoutMs == SemaphoreIF::NO_TIMEOUT) {
result = sem_trywait(&handle);
}
else if(timeoutMs == SemaphoreIF::MAX_TIMEOUT) {
result = sem_wait(&handle);
}
else if(timeoutMs > SemaphoreIF::NO_TIMEOUT){
timespec timeOut;
clock_gettime(CLOCK_REALTIME, &timeOut);
uint64_t nseconds = timeOut.tv_sec * 1000000000 + timeOut.tv_nsec;
nseconds += timeoutMs * 1000000;
timeOut.tv_sec = nseconds / 1000000000;
timeOut.tv_nsec = nseconds - timeOut.tv_sec * 1000000000;
result = sem_timedwait(&handle, &timeOut);
if(result != 0 and errno == EINVAL) {
sif::debug << "BinarySemaphore::acquire: Invalid time value possible"
<< std::endl;
}
}
if(result == 0) {
return HasReturnvaluesIF::RETURN_OK;
}
switch(errno) {
case(EAGAIN):
// Operation could not be performed without blocking (for sem_trywait)
case(ETIMEDOUT):
// Semaphore is 0
return SemaphoreIF::SEMAPHORE_TIMEOUT;
case(EINVAL):
// Semaphore invalid
return SemaphoreIF::SEMAPHORE_INVALID;
case(EINTR):
// Call was interrupted by signal handler
sif::debug << "BinarySemaphore::acquire: Signal handler interrupted."
"Code " << strerror(errno) << std::endl;
/* No break */
default:
return HasReturnvaluesIF::RETURN_FAILED;
}
}
ReturnValue_t BinarySemaphore::release() {
return BinarySemaphore::release(&this->handle);
}
ReturnValue_t BinarySemaphore::release(sem_t *handle) {
ReturnValue_t countResult = checkCount(handle, 1);
if(countResult != HasReturnvaluesIF::RETURN_OK) {
return countResult;
}
int result = sem_post(handle);
if(result == 0) {
return HasReturnvaluesIF::RETURN_OK;
}
switch(errno) {
case(EINVAL):
// Semaphore invalid
return SemaphoreIF::SEMAPHORE_INVALID;
case(EOVERFLOW):
// SEM_MAX_VALUE overflow. This should never happen
default:
return HasReturnvaluesIF::RETURN_FAILED;
}
}
uint8_t BinarySemaphore::getSemaphoreCounter() const {
// And another ugly cast :-D
return getSemaphoreCounter(const_cast<sem_t*>(&this->handle));
}
uint8_t BinarySemaphore::getSemaphoreCounter(sem_t *handle) {
int value = 0;
int result = sem_getvalue(handle, &value);
if (result == 0) {
return value;
}
else if(result != 0 and errno == EINVAL) {
// Could be called from interrupt, use lightweight printf
printf("BinarySemaphore::getSemaphoreCounter: Invalid semaphore\n");
return 0;
}
else {
// This should never happen.
return 0;
}
}
void BinarySemaphore::initSemaphore(uint8_t initCount) {
auto result = sem_init(&handle, true, initCount);
if(result == -1) {
switch(errno) {
case(EINVAL):
// Value exceeds SEM_VALUE_MAX
case(ENOSYS):
// System does not support process-shared semaphores
sif::error << "BinarySemaphore: Init failed with" << strerror(errno)
<< std::endl;
}
}
}
ReturnValue_t BinarySemaphore::checkCount(sem_t* handle, uint8_t maxCount) {
int value = getSemaphoreCounter(handle);
if(value >= maxCount) {
if(maxCount == 1 and value > 1) {
// Binary Semaphore special case.
// This is a config error use lightweight printf is this is called
// from an interrupt
printf("BinarySemaphore::release: Value of binary semaphore greater"
" than 1!\n");
return HasReturnvaluesIF::RETURN_FAILED;
}
return SemaphoreIF::SEMAPHORE_NOT_OWNED;
}
return HasReturnvaluesIF::RETURN_OK;
}

View File

@ -0,0 +1,81 @@
#ifndef FRAMEWORK_OSAL_LINUX_BINARYSEMPAHORE_H_
#define FRAMEWORK_OSAL_LINUX_BINARYSEMPAHORE_H_
#include <framework/returnvalues/HasReturnvaluesIF.h>
#include <framework/tasks/SemaphoreIF.h>
extern "C" {
#include <semaphore.h>
}
/**
* @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
* See: http://www.man7.org/linux/man-pages/man7/sem_overview.7.html
* @author R. Mueller
* @ingroup osal
*/
class BinarySemaphore: public SemaphoreIF,
public HasReturnvaluesIF {
public:
static const uint8_t INTERFACE_ID = CLASS_ID::SEMAPHORE_IF;
//! @brief Default ctor
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
BinarySemaphore & operator=(BinarySemaphore &&);
//! @brief Destructor
virtual ~BinarySemaphore();
void initSemaphore(uint8_t initCount = 1);
uint8_t getSemaphoreCounter() const override;
static uint8_t getSemaphoreCounter(sem_t* handle);
/**
* 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 SemaphoreIF::SEMAPHORE_TIMEOUT on timeout
*/
ReturnValue_t acquire(uint32_t timeoutMs =
SemaphoreIF::NO_TIMEOUT) override;
/**
* Release the binary semaphore.
* @return -@c RETURN_OK on success
* -@c SemaphoreIF::SEMAPHORE_NOT_OWNED if the semaphores is
* already available.
*/
virtual ReturnValue_t release() override;
/**
* This static function can be used to release a semaphore by providing
* its handle.
* @param handle
* @return
*/
static ReturnValue_t release(sem_t* handle);
/** Checks the validity of the semaphore count against a specified
* known maxCount
* @param handle
* @param maxCount
* @return
*/
static ReturnValue_t checkCount(sem_t* handle, uint8_t maxCount);
protected:
sem_t handle;
};
#endif /* FRAMEWORK_OSAL_FREERTOS_BINARYSEMPAHORE_H_ */

View File

@ -1,10 +1,10 @@
#include <sys/time.h> #include <framework/serviceinterface/ServiceInterfaceStream.h>
#include <time.h>
#include <framework/timemanager/Clock.h> #include <framework/timemanager/Clock.h>
#include <sys/time.h>
#include <sys/sysinfo.h> #include <sys/sysinfo.h>
#include <linux/sysinfo.h> #include <linux/sysinfo.h>
#include <time.h>
#include <unistd.h> #include <unistd.h>
//#include <fstream> //#include <fstream>
@ -65,6 +65,15 @@ ReturnValue_t Clock::getClock_usecs(uint64_t* time) {
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
timeval Clock::getUptime() {
timeval uptime;
auto result = getUptime(&uptime);
if(result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "Clock::getUptime: Error getting uptime" << std::endl;
}
return uptime;
}
ReturnValue_t Clock::getUptime(timeval* uptime) { ReturnValue_t Clock::getUptime(timeval* uptime) {
//TODO This is not posix compatible and delivers only seconds precision //TODO This is not posix compatible and delivers only seconds precision
struct sysinfo sysInfo; struct sysinfo sysInfo;

View File

@ -0,0 +1,54 @@
#include <framework/osal/linux/CountingSemaphore.h>
#include <framework/serviceinterface/ServiceInterfaceStream.h>
CountingSemaphore::CountingSemaphore(const uint8_t maxCount, uint8_t initCount):
maxCount(maxCount), initCount(initCount) {
if(initCount > maxCount) {
sif::error << "CountingSemaphoreUsingTask: Max count bigger than "
"intial cout. Setting initial count to max count." << std::endl;
initCount = maxCount;
}
initSemaphore(initCount);
}
CountingSemaphore::CountingSemaphore(CountingSemaphore&& other):
maxCount(other.maxCount), initCount(other.initCount) {
initSemaphore(initCount);
}
CountingSemaphore& CountingSemaphore::operator =(
CountingSemaphore&& other) {
initSemaphore(other.initCount);
return * this;
}
ReturnValue_t CountingSemaphore::release() {
ReturnValue_t result = checkCount(&handle, maxCount);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
return CountingSemaphore::release(&this->handle);
}
ReturnValue_t CountingSemaphore::release(sem_t* handle) {
int result = sem_post(handle);
if(result == 0) {
return HasReturnvaluesIF::RETURN_OK;
}
switch(errno) {
case(EINVAL):
// Semaphore invalid
return SemaphoreIF::SEMAPHORE_INVALID;
case(EOVERFLOW):
// SEM_MAX_VALUE overflow. This should never happen
default:
return HasReturnvaluesIF::RETURN_FAILED;
}
}
uint8_t CountingSemaphore::getMaxCount() const {
return maxCount;
}

View File

@ -0,0 +1,37 @@
#ifndef FRAMEWORK_OSAL_LINUX_COUNTINGSEMAPHORE_H_
#define FRAMEWORK_OSAL_LINUX_COUNTINGSEMAPHORE_H_
#include <framework/osal/linux/BinarySemaphore.h>
/**
* @brief Counting semaphores, which can be acquired 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(const uint8_t maxCount, 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 &&);
ReturnValue_t release() override;
static ReturnValue_t release(sem_t* sem);
/* Same API as binary semaphore otherwise. acquire() can be called
* until there are not semaphores left and release() can be called
* until maxCount is reached. */
uint8_t getMaxCount() const;
private:
const uint8_t maxCount;
uint8_t initCount = 0;
};
#endif /* FRAMEWORK_OSAL_FREERTOS_COUNTINGSEMAPHORE_H_ */

View File

@ -1,5 +1,5 @@
#ifndef OS_RTEMS_MUTEX_H_ #ifndef OS_LINUX_MUTEX_H_
#define OS_RTEMS_MUTEX_H_ #define OS_LINUX_MUTEX_H_
#include <framework/ipc/MutexIF.h> #include <framework/ipc/MutexIF.h>

View File

@ -57,9 +57,11 @@ void PeriodicPosixTask::taskFunctionality(void){
char name[20] = {0}; char name[20] = {0};
int status = pthread_getname_np(pthread_self(),name,sizeof(name)); int status = pthread_getname_np(pthread_self(),name,sizeof(name));
if(status==0){ if(status==0){
sif::error << "ObjectTask: " << name << " Deadline missed." << std::endl; sif::error << "PeriodicPosixTask " << name << ": Deadline "
"missed." << std::endl;
}else{ }else{
sif::error << "ObjectTask: X Deadline missed. " << status << std::endl; sif::error << "PeriodicPosixTask X: Deadline missed. " <<
status << std::endl;
} }
if (this->deadlineMissedFunc != NULL) { if (this->deadlineMissedFunc != NULL) {
this->deadlineMissedFunc(); this->deadlineMissedFunc();

View File

@ -1,4 +1,6 @@
#include <framework/tasks/SemaphoreFactory.h> #include <framework/tasks/SemaphoreFactory.h>
#include <framework/osal/linux/BinarySemaphore.h>
#include <framework/osal/linux/CountingSemaphore.h>
#include <framework/serviceinterface/ServiceInterfaceStream.h> #include <framework/serviceinterface/ServiceInterfaceStream.h>
const uint32_t SemaphoreIF::NO_TIMEOUT = 0; const uint32_t SemaphoreIF::NO_TIMEOUT = 0;
@ -20,18 +22,15 @@ SemaphoreFactory* SemaphoreFactory::instance() {
return SemaphoreFactory::factoryInstance; return SemaphoreFactory::factoryInstance;
} }
SemaphoreIF* SemaphoreFactory::createBinarySemaphore() { SemaphoreIF* SemaphoreFactory::createBinarySemaphore(uint32_t arguments) {
sif::error << "Semaphore not implemented for Linux yet" << std::endl; return new BinarySemaphore();
return nullptr;
} }
SemaphoreIF* SemaphoreFactory::createCountingSemaphore(uint8_t count, SemaphoreIF* SemaphoreFactory::createCountingSemaphore(const uint8_t maxCount,
uint8_t initCount) { uint8_t initCount, uint32_t arguments) {
sif::error << "Counting Semaphore not implemented for " return new CountingSemaphore(maxCount, initCount);
"Linux yet" << std::endl;
return nullptr;
} }
void SemaphoreFactory::deleteMutex(SemaphoreIF* semaphore) { void SemaphoreFactory::deleteSemaphore(SemaphoreIF* semaphore) {
delete semaphore; delete semaphore;
} }

View File

@ -22,6 +22,7 @@
* 0xFFFF-1 bytes. * 0xFFFF-1 bytes.
* It is possible to store empty packets in the pool. * It is possible to store empty packets in the pool.
* The local pool is NOT thread-safe. * The local pool is NOT thread-safe.
* @author Bastian Baetz
*/ */
template<uint8_t NUMBER_OF_POOLS = 5> template<uint8_t NUMBER_OF_POOLS = 5>

View File

@ -1,6 +1,10 @@
#ifndef FRAMEWORK_STORAGEMANAGER_LOCALPOOL_TPP_ #ifndef FRAMEWORK_STORAGEMANAGER_LOCALPOOL_TPP_
#define FRAMEWORK_STORAGEMANAGER_LOCALPOOL_TPP_ #define FRAMEWORK_STORAGEMANAGER_LOCALPOOL_TPP_
#ifndef FRAMEWORK_STORAGEMANAGER_LOCALPOOL_H_
#error Include LocalPool.h before LocalPool.tpp!
#endif
template<uint8_t NUMBER_OF_POOLS> template<uint8_t NUMBER_OF_POOLS>
inline LocalPool<NUMBER_OF_POOLS>::LocalPool(object_id_t setObjectId, inline LocalPool<NUMBER_OF_POOLS>::LocalPool(object_id_t setObjectId,
const uint16_t element_sizes[NUMBER_OF_POOLS], const uint16_t element_sizes[NUMBER_OF_POOLS],

View File

@ -10,6 +10,7 @@
* a fixed pool size policy for inter-process communication. * a fixed pool size policy for inter-process communication.
* @details Uses local pool calls but is thread safe by protecting the call * @details Uses local pool calls but is thread safe by protecting the call
* with a lock. * with a lock.
* @author Bastian Baetz
*/ */
template <uint8_t NUMBER_OF_POOLS> template <uint8_t NUMBER_OF_POOLS>
class PoolManager : public LocalPool<NUMBER_OF_POOLS> { class PoolManager : public LocalPool<NUMBER_OF_POOLS> {

View File

@ -1,6 +1,10 @@
#ifndef FRAMEWORK_STORAGEMANAGER_POOLMANAGER_TPP_ #ifndef FRAMEWORK_STORAGEMANAGER_POOLMANAGER_TPP_
#define FRAMEWORK_STORAGEMANAGER_POOLMANAGER_TPP_ #define FRAMEWORK_STORAGEMANAGER_POOLMANAGER_TPP_
#ifndef FRAMEWORK_STORAGEMANAGER_POOLMANAGER_H_
#error Include PoolManager.h before PoolManager.tpp!
#endif
template<uint8_t NUMBER_OF_POOLS> template<uint8_t NUMBER_OF_POOLS>
inline PoolManager<NUMBER_OF_POOLS>::PoolManager(object_id_t setObjectId, inline PoolManager<NUMBER_OF_POOLS>::PoolManager(object_id_t setObjectId,
const uint16_t element_sizes[NUMBER_OF_POOLS], const uint16_t element_sizes[NUMBER_OF_POOLS],

View File

@ -20,19 +20,23 @@ public:
/** /**
* Create a binary semaphore. * Create a binary semaphore.
* Creator function for a binary semaphore which may only be acquired once * 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. * @return Pointer to newly created semaphore class instance.
*/ */
SemaphoreIF* createBinarySemaphore(); 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
* times. * times.
* @param count Semaphore can be taken count times. * @param count Semaphore can be taken count times.
* @param initCount Initial count value. * @param initCount Initial count value.
* @param argument Can be used to pass implementation specific information.
* @return * @return
*/ */
SemaphoreIF* createCountingSemaphore(uint8_t count, uint8_t initCount); SemaphoreIF* createCountingSemaphore(const uint8_t maxCount,
void deleteMutex(SemaphoreIF* mutex); uint8_t initCount, uint32_t arguments = 0);
void deleteSemaphore(SemaphoreIF* semaphore);
private: private:
/** /**

View File

@ -12,7 +12,8 @@
* A semaphore is a synchronization primitive. * A semaphore is a synchronization primitive.
* See: https://en.wikipedia.org/wiki/Semaphore_(programming) * See: https://en.wikipedia.org/wiki/Semaphore_(programming)
* A semaphore can be used to achieve task synchonization and track the * A semaphore can be used to achieve task synchonization and track the
* availability of resources. * availability of resources by using either the binary or the counting
* semaphore types.
* *
* If mutual exlcusion of a resource is desired, a mutex should be used, * 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. * which is a special form of a semaphore and has an own interface.
@ -29,7 +30,7 @@ public:
static constexpr ReturnValue_t SEMAPHORE_TIMEOUT = MAKE_RETURN_CODE(1); static constexpr ReturnValue_t SEMAPHORE_TIMEOUT = MAKE_RETURN_CODE(1);
//! The current semaphore can not be given, because it is not owned //! 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_NOT_OWNED = MAKE_RETURN_CODE(2);
static constexpr ReturnValue_t SEMAPHORE_NULLPOINTER = MAKE_RETURN_CODE(3); static constexpr ReturnValue_t SEMAPHORE_INVALID = MAKE_RETURN_CODE(3);
/** /**
* Generic call to acquire a semaphore. * Generic call to acquire a semaphore.
@ -54,7 +55,7 @@ public:
* is returned if the semaphore is available, and 0 is returned if the * is returned if the semaphore is available, and 0 is returned if the
* semaphore is not available. * semaphore is not available.
*/ */
virtual uint8_t getSemaphoreCounter() = 0; virtual uint8_t getSemaphoreCounter() const = 0;
}; };
#endif /* FRAMEWORK_TASKS_SEMAPHOREIF_H_ */ #endif /* FRAMEWORK_TASKS_SEMAPHOREIF_H_ */

View File

@ -2,13 +2,14 @@
#define FRAMEWORK_TIMEMANAGER_CLOCK_H_ #define FRAMEWORK_TIMEMANAGER_CLOCK_H_
#include <framework/returnvalues/HasReturnvaluesIF.h> #include <framework/returnvalues/HasReturnvaluesIF.h>
#include <stdint.h>
#include <sys/time.h>
#include <framework/ipc/MutexFactory.h> #include <framework/ipc/MutexFactory.h>
#include <framework/globalfunctions/timevalOperations.h> #include <framework/globalfunctions/timevalOperations.h>
#include <cstdint>
#include <sys/time.h>
typedef uint32_t millis_t; typedef uint32_t millis_t;
typedef float seconds_t; typedef double seconds_t;
class Clock { class Clock {
public: public:
@ -22,7 +23,7 @@ public:
uint32_t usecond; //!< Microseconds, 0 .. 999999 uint32_t usecond; //!< Microseconds, 0 .. 999999
} TimeOfDay_t; } TimeOfDay_t;
/**static Clock* TimeOfDay_t(); /**
* This method returns the number of clock ticks per second. * This method returns the number of clock ticks per second.
* In RTEMS, this is typically 1000. * In RTEMS, this is typically 1000.
* @return The number of ticks. * @return The number of ticks.
@ -34,22 +35,23 @@ public:
* This system call sets the system time. * This system call sets the system time.
* To set the time, it uses a TimeOfDay_t struct. * To set the time, it uses a TimeOfDay_t struct.
* @param time The struct with the time settings to set. * @param time The struct with the time settings to set.
* @return \c RETURN_OK on success. Otherwise, the OS failure code is returned. * @return -@c RETURN_OK on success. Otherwise, the OS failure code
* is returned.
*/ */
static ReturnValue_t setClock(const TimeOfDay_t* time); static ReturnValue_t setClock(const TimeOfDay_t* time);
/** /**
* This system call sets the system time. * This system call sets the system time.
* To set the time, it uses a timeval struct. * To set the time, it uses a timeval struct.
* @param time The struct with the time settings to set. * @param time The struct with the time settings to set.
* @return \c RETURN_OK on success. Otherwise, the OS failure code is returned. * @return -@c RETURN_OK on success. Otherwise, the OS failure code is returned.
*/ */
static ReturnValue_t setClock(const timeval* time); static ReturnValue_t setClock(const timeval* time);
/** /**
* This system call returns the current system clock in timeval format. * This system call returns the current system clock in timeval format.
* The timval format has the fields \c tv_sec with seconds and \c tv_usec with * The timval format has the fields @c tv_sec with seconds and @c tv_usec with
* microseconds since an OS-defined epoch. * microseconds since an OS-defined epoch.
* @param time A pointer to a timeval struct where the current time is stored. * @param time A pointer to a timeval struct where the current time is stored.
* @return \c RETURN_OK on success. Otherwise, the OS failure code is returned. * @return @c RETURN_OK on success. Otherwise, the OS failure code is returned.
*/ */
static ReturnValue_t getClock_timeval(timeval* time); static ReturnValue_t getClock_timeval(timeval* time);
@ -57,7 +59,7 @@ public:
* Get the time since boot in a timeval struct * Get the time since boot in a timeval struct
* *
* @param[out] time A pointer to a timeval struct where the uptime is stored. * @param[out] time A pointer to a timeval struct where the uptime is stored.
* @return\c RETURN_OK on success. Otherwise, the OS failure code is returned. * @return @c RETURN_OK on success. Otherwise, the OS failure code is returned.
* *
* @deprecated, I do not think this should be able to fail, use timeval getUptime() * @deprecated, I do not think this should be able to fail, use timeval getUptime()
*/ */

View File

@ -1,9 +1,3 @@
/**
* @file Stopwatch.cpp
*
* @date 08.04.2020
*/
#include <framework/timemanager/Stopwatch.h> #include <framework/timemanager/Stopwatch.h>
#include <framework/serviceinterface/ServiceInterfaceStream.h> #include <framework/serviceinterface/ServiceInterfaceStream.h>
#include <iomanip> #include <iomanip>
@ -12,11 +6,11 @@ Stopwatch::Stopwatch(bool displayOnDestruction,
StopwatchDisplayMode displayMode): displayOnDestruction( StopwatchDisplayMode displayMode): displayOnDestruction(
displayOnDestruction), displayMode(displayMode) { displayOnDestruction), displayMode(displayMode) {
// Measures start time on initialization. // Measures start time on initialization.
startTime = Clock::getUptime(); Clock::getClock_timeval(&startTime);
} }
void Stopwatch::start() { void Stopwatch::start() {
startTime = Clock::getUptime(); Clock::getClock_timeval(&startTime);
} }
millis_t Stopwatch::stop() { millis_t Stopwatch::stop() {
@ -57,5 +51,7 @@ StopwatchDisplayMode Stopwatch::getDisplayMode() const {
} }
void Stopwatch::stopInternal() { void Stopwatch::stopInternal() {
elapsedTime = Clock::getUptime() - startTime; timeval endTime;
Clock::getClock_timeval(&endTime);
elapsedTime = endTime - startTime;
} }

View File

@ -1,9 +1,3 @@
/**
* @file Stopwatch.h
*
* @date 08.04.2020
*/
#ifndef FRAMEWORK_TIMEMANAGER_STOPWATCH_H_ #ifndef FRAMEWORK_TIMEMANAGER_STOPWATCH_H_
#define FRAMEWORK_TIMEMANAGER_STOPWATCH_H_ #define FRAMEWORK_TIMEMANAGER_STOPWATCH_H_
#include <framework/timemanager/Clock.h> #include <framework/timemanager/Clock.h>
@ -19,7 +13,8 @@ enum class StopwatchDisplayMode {
* This class can be used to measure elapsed times. It also displays elapsed * This class can be used to measure elapsed times. It also displays elapsed
* times automatically on destruction if not explicitely deactivated in the * times automatically on destruction if not explicitely deactivated in the
* constructor. The default time format is the elapsed time in miliseconds * constructor. The default time format is the elapsed time in miliseconds
* as a float. * in seconds as a double.
* @author R. Mueller
*/ */
class Stopwatch { class Stopwatch {
public: public:
@ -46,6 +41,10 @@ public:
* @return elapsed time in milliseconds (rounded) * @return elapsed time in milliseconds (rounded)
*/ */
millis_t stop(); millis_t stop();
/**
* Calculates the elapsed time since start and returns it
* @return elapsed time in seconds (double precision)
*/
seconds_t stopSeconds(); seconds_t stopSeconds();
/** /**