diff --git a/ipc/MutexIF.h b/ipc/MutexIF.h index 35786d6a..a4aff1cd 100644 --- a/ipc/MutexIF.h +++ b/ipc/MutexIF.h @@ -3,6 +3,13 @@ #include +/** + * @brief Common interface for OS Mutex objects which provide MUTual EXclusion. + * + * @details https://en.wikipedia.org/wiki/Lock_(computer_science) + * @ingroup osal + * @ingroup interface + */ class MutexIF { public: static const uint32_t NO_TIMEOUT; //!< Needs to be defined in implementation. diff --git a/osal/FreeRTOS/BinarySemaphore.cpp b/osal/FreeRTOS/BinarySemaphore.cpp index 0422f105..dd73c5b0 100644 --- a/osal/FreeRTOS/BinarySemaphore.cpp +++ b/osal/FreeRTOS/BinarySemaphore.cpp @@ -3,7 +3,93 @@ * * @date 25.02.2020 */ +#include +#include +#include "portmacro.h" +#include "task.h" +BinarySemaphore::BinarySemaphore() { + vSemaphoreCreateBinary(handle); + if(handle == NULL) { + error << "Binary semaphore creation failure" << std::endl; + } +} +BinarySemaphore::~BinarySemaphore() { + vSemaphoreDelete(handle); +} +ReturnValue_t BinarySemaphore::takeBinarySemaphore(uint32_t timeoutMs) { + if(handle == NULL) { + return HasReturnvaluesIF::RETURN_FAILED; + } + TickType_t timeout = portMAX_DELAY; + if(timeoutMs != 0) { + timeout = pdMS_TO_TICKS(timeoutMs); + } + BaseType_t returncode = xSemaphoreTake(handle, timeout); + if (returncode == pdPASS) { + return HasReturnvaluesIF::RETURN_OK; + } else { + return SEMAPHORE_NOT_FOUND; + } +} + +ReturnValue_t BinarySemaphore::takeBinarySemaphoreTickTimeout(TickType_t timeoutTicks) { + if(handle == NULL) { + return SEMAPHORE_NOT_FOUND; + } + + BaseType_t returncode = xSemaphoreTake(handle, timeoutTicks); + if (returncode == pdPASS) { + return HasReturnvaluesIF::RETURN_OK; + } else { + return SEMAPHORE_TIMEOUT; + } +} + +ReturnValue_t BinarySemaphore::giveBinarySemaphore() { + if (handle == NULL) { + return HasReturnvaluesIF::RETURN_FAILED; + } + BaseType_t returncode = xSemaphoreGive(handle); + if (returncode == pdPASS) { + return HasReturnvaluesIF::RETURN_OK; + } else { + return SEMAPHORE_NOT_OWNED; + } +} + +SemaphoreHandle_t BinarySemaphore::getSemaphore() { + return handle; +} + +ReturnValue_t giveBinarySemaphore(SemaphoreHandle_t semaphore) { + if (semaphore == NULL) { + return HasReturnvaluesIF::RETURN_FAILED; + } + BaseType_t returncode = xSemaphoreGive(semaphore); + if (returncode == pdPASS) { + return HasReturnvaluesIF::RETURN_OK; + } else { + return HasReturnvaluesIF::RETURN_FAILED; + } +} + +ReturnValue_t giveBinarySemaphoreFromISR(SemaphoreHandle_t semaphore, + BaseType_t * higherPriorityTaskWoken) { + if (semaphore == NULL) { + return HasReturnvaluesIF::RETURN_FAILED; + } + BaseType_t returncode = xSemaphoreGiveFromISR(semaphore, higherPriorityTaskWoken); + if (returncode == pdPASS) { + if(*higherPriorityTaskWoken == pdPASS) { + // Request context switch + portYIELD_FROM_ISR(); + } + return HasReturnvaluesIF::RETURN_OK; + } else { + return HasReturnvaluesIF::RETURN_FAILED; + } +} diff --git a/osal/FreeRTOS/BinarySemaphore.h b/osal/FreeRTOS/BinarySemaphore.h new file mode 100644 index 00000000..afc01adf --- /dev/null +++ b/osal/FreeRTOS/BinarySemaphore.h @@ -0,0 +1,94 @@ +/** + * @file BinarySempahore.h + * + * @date 25.02.2020 + */ +#ifndef FRAMEWORK_OSAL_FREERTOS_BINARYSEMPAHORE_H_ +#define FRAMEWORK_OSAL_FREERTOS_BINARYSEMPAHORE_H_ + +#include +#include +#include "semphr.h" + +/** + * @brief OS Tool to achieve synchronization of between tasks or between task and ISR + * @details + * Documentation: https://www.freertos.org/Embedded-RTOS-Binary-Semaphores.html + * @ingroup osal + */ +class BinarySemaphore: public HasReturnvaluesIF { +public: + static const uint8_t INTERFACE_ID = CLASS_ID::SEMAPHORE_IF; + + /** Semaphore object not found */ + static const ReturnValue_t SEMAPHORE_NOT_FOUND = MAKE_RETURN_CODE(1); + /** Semaphore timeout */ + static const ReturnValue_t SEMAPHORE_TIMEOUT = MAKE_RETURN_CODE(2); + /** The current semaphore can not be given, because it is not owned */ + static const ReturnValue_t SEMAPHORE_NOT_OWNED = MAKE_RETURN_CODE(3); + + /** + * Create a binary semaphore + */ + BinarySemaphore(); + + /** + * Delete the binary semaphore to prevent a memory leak + */ + ~BinarySemaphore(); + + /** + * Take the binary semaphore. + * If the semaphore has already been taken, the task will be blocked for a maximum + * of #timeoutMs or until the semaphore is given back, + * for example by an ISR or another task. + * @param timeoutMs + * @return -@c RETURN_OK on success + * -@c RETURN_FAILED on failure + */ + ReturnValue_t takeBinarySemaphore(uint32_t timeoutMs); + + /** + * 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); + + /** + * Give back the binary semaphore + * @return -@c RETURN_OK on success + * -@c RETURN_FAILED on failure + */ + ReturnValue_t giveBinarySemaphore(); + + /** + * Get Handle to the semaphore. + * @return + */ + SemaphoreHandle_t getSemaphore(); +private: + SemaphoreHandle_t handle; +}; + +/** + * Wrapper function to give back semaphore from handle + * @param semaphore + * @return -@c RETURN_OK on success + * -@c RETURN_FAILED on failure + */ +ReturnValue_t giveBinarySemaphore(SemaphoreHandle_t semaphore); + +/** + * Wrapper function to give back semaphore from handle when called from an ISR + * @param semaphore + * @param higherPriorityTaskWoken This will be set to pdPASS if a task with a higher priority + * was unblocked + * @return -@c RETURN_OK on success + * -@c RETURN_FAILED on failure + */ +ReturnValue_t giveBinarySemaphoreFromISR(SemaphoreHandle_t semaphore, + BaseType_t * higherPriorityTaskWoken); + +#endif /* FRAMEWORK_OSAL_FREERTOS_BINARYSEMPAHORE_H_ */ diff --git a/osal/FreeRTOS/BinarySempahore.h b/osal/FreeRTOS/BinarySempahore.h deleted file mode 100644 index ab32d7b7..00000000 --- a/osal/FreeRTOS/BinarySempahore.h +++ /dev/null @@ -1,14 +0,0 @@ -/** - * @file BinarySempahore.h - * - * @date 25.02.2020 - */ - -#ifndef FRAMEWORK_OSAL_FREERTOS_BINARYSEMPAHORE_H_ -#define FRAMEWORK_OSAL_FREERTOS_BINARYSEMPAHORE_H_ - - - - - -#endif /* FRAMEWORK_OSAL_FREERTOS_BINARYSEMPAHORE_H_ */ diff --git a/osal/FreeRTOS/MessageQueue.cpp b/osal/FreeRTOS/MessageQueue.cpp index 883cf261..fdca80c7 100644 --- a/osal/FreeRTOS/MessageQueue.cpp +++ b/osal/FreeRTOS/MessageQueue.cpp @@ -1,5 +1,4 @@ #include "MessageQueue.h" -#include "task.h" #include @@ -24,6 +23,12 @@ void MessageQueue::switchSystemContext(SystemContext callContext) { this->callContext = callContext; } +void MessageQueue::requestContextSwitch(SystemContext callContext) { + if(callContext == SystemContext::isr_context) { + portYIELD_FROM_ISR(); + } +} + ReturnValue_t MessageQueue::sendMessage(MessageQueueId_t sendTo, MessageQueueMessage* message, bool ignoreFault) { return sendMessageFrom(sendTo, message, this->getId(), ignoreFault); @@ -72,11 +77,7 @@ ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo, return handleSendResult(result, ignoreFault); } -void MessageQueue::requestContextSwitch(SystemContext callContext) { - if(callContext == SystemContext::isr_context) { - portYIELD_FROM_ISR(); - } -} + ReturnValue_t MessageQueue::handleSendResult(BaseType_t result, bool ignoreFault) { if (result != pdPASS) { diff --git a/osal/FreeRTOS/MessageQueue.h b/osal/FreeRTOS/MessageQueue.h index 9e2d7790..cdb2a798 100644 --- a/osal/FreeRTOS/MessageQueue.h +++ b/osal/FreeRTOS/MessageQueue.h @@ -8,6 +8,7 @@ #include #include "queue.h" #include "portmacro.h" +#include "task.h" //TODO this class assumes that MessageQueueId_t is the same size as void* (the FreeRTOS handle type), compiler will catch this but it might be nice to have something checking or even an always working solution // https://scaryreasoner.wordpress.com/2009/02/28/checking-sizeof-at-compile-time/ diff --git a/osal/FreeRTOS/Mutex.cpp b/osal/FreeRTOS/Mutex.cpp index 456506ea..616ef7b8 100644 --- a/osal/FreeRTOS/Mutex.cpp +++ b/osal/FreeRTOS/Mutex.cpp @@ -37,8 +37,7 @@ ReturnValue_t Mutex::lockMutex(uint32_t timeoutMs) { ReturnValue_t Mutex::unlockMutex() { if (handle == 0) { - //TODO Does not exist - return HasReturnvaluesIF::RETURN_FAILED; + return MutexIF::MUTEX_NOT_FOUND; } BaseType_t returncode = xSemaphoreGive(handle); if (returncode == pdPASS) { diff --git a/osal/FreeRTOS/Mutex.h b/osal/FreeRTOS/Mutex.h index 471b1113..2703df4e 100644 --- a/osal/FreeRTOS/Mutex.h +++ b/osal/FreeRTOS/Mutex.h @@ -1,5 +1,5 @@ -#ifndef OS_RTEMS_MUTEX_H_ -#define OS_RTEMS_MUTEX_H_ +#ifndef FRAMEWORK_FREERTOS_MUTEX_H_ +#define FRAMEWORK_FREERTOS_MUTEX_H_ #include @@ -8,7 +8,11 @@ #include "semphr.h" /** + * @brief OS component to implement MUTual EXclusion * + * @details + * Mutexes are binary semaphores which include a priority inheritance mechanism. + * Documentation: https://www.freertos.org/Real-time-embedded-RTOS-mutexes.html * @ingroup osal */ class Mutex : public MutexIF { @@ -21,4 +25,4 @@ private: SemaphoreHandle_t handle; }; -#endif /* OS_RTEMS_MUTEX_H_ */ +#endif /* FRAMEWORK_FREERTOS_MUTEX_H_ */ diff --git a/returnvalues/FwClassIds.h b/returnvalues/FwClassIds.h index beef0475..120d8b8c 100644 --- a/returnvalues/FwClassIds.h +++ b/returnvalues/FwClassIds.h @@ -60,6 +60,7 @@ enum { SGP4PROPAGATOR_CLASS, //SGP4 53 MUTEX_IF, //MUX 54 MESSAGE_QUEUE_IF,//MQI 55 + SEMAPHORE_IF, //SPH 56 FW_CLASS_ID_COUNT //is actually count + 1 ! };