496 lines
19 KiB
C++
496 lines
19 KiB
C++
|
/*
|
||
|
* FreeRTOS-Cpp
|
||
|
* Copyright (C) 2021 Jon Enz. All Rights Reserved.
|
||
|
*
|
||
|
* SPDX-License-Identifier: MIT
|
||
|
*
|
||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||
|
* of this software and associated documentation files (the "Software"), to deal
|
||
|
* in the Software without restriction, including without limitation the rights
|
||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||
|
* copies of the Software, and to permit persons to whom the Software is
|
||
|
* furnished to do so, subject to the following conditions:
|
||
|
*
|
||
|
* The above copyright notice and this permission notice shall be included in
|
||
|
* all copies or substantial portions of the Software.
|
||
|
*
|
||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||
|
* SOFTWARE.
|
||
|
*
|
||
|
* https://github.com/jonenz/FreeRTOS-Cpp
|
||
|
*/
|
||
|
|
||
|
#ifndef FREERTOS_MUTEX_HPP
|
||
|
#define FREERTOS_MUTEX_HPP
|
||
|
|
||
|
#include "FreeRTOS.h"
|
||
|
#include "semphr.h"
|
||
|
|
||
|
namespace FreeRTOS {
|
||
|
|
||
|
/**
|
||
|
* @class MutexBase Mutex.hpp <FreeRTOS/Mutex.hpp>
|
||
|
*
|
||
|
* @brief Base class that provides the standard mutex interface to
|
||
|
* FreeRTOS::Mutex, FreeRTOS::StaticMutex, FreeRTOS::RecursiveMutex, and
|
||
|
* FreeRTOS::StaticRecursiveMutex.
|
||
|
*
|
||
|
* @note This class is not intended to be instantiated by the user. Use
|
||
|
* FreeRTOS::Mutex, FreeRTOS::StaticMutex, FreeRTOS::RecursiveMutex, and
|
||
|
* FreeRTOS::StaticRecursiveMutex.
|
||
|
*/
|
||
|
class MutexBase {
|
||
|
public:
|
||
|
friend class Mutex;
|
||
|
friend class StaticMutex;
|
||
|
friend class RecursiveMutexBase;
|
||
|
friend class RecursiveMutex;
|
||
|
friend class StaticRecursiveMutex;
|
||
|
|
||
|
MutexBase(const MutexBase&) = delete;
|
||
|
MutexBase& operator=(const MutexBase&) = delete;
|
||
|
|
||
|
static void* operator new(size_t, void* ptr) { return ptr; }
|
||
|
static void* operator new[](size_t, void* ptr) { return ptr; }
|
||
|
static void* operator new(size_t) = delete;
|
||
|
static void* operator new[](size_t) = delete;
|
||
|
|
||
|
/**
|
||
|
* Mutex.hpp
|
||
|
*
|
||
|
* @brief Function that checks if the underlying semaphore handle is not NULL.
|
||
|
* This should be used to ensure a semaphore has been created correctly.
|
||
|
*
|
||
|
* @retval true the handle is not NULL.
|
||
|
* @retval false the handle is NULL.
|
||
|
*/
|
||
|
inline bool isValid() const { return (handle != NULL); }
|
||
|
|
||
|
/**
|
||
|
* Mutex.hpp
|
||
|
*
|
||
|
* @brief Function that calls <tt>xSemaphoreTake( SemaphoreHandle_t
|
||
|
* xSemaphore, TickType_t xTicksToWait )</tt>
|
||
|
*
|
||
|
* @see <https://www.freertos.org/a00122.html>
|
||
|
*
|
||
|
* @param ticksToWait The time in ticks to wait for the mutex to become
|
||
|
* available. The macro portTICK_PERIOD_MS can be used to convert this to a
|
||
|
* real time. A block time of zero can be used to poll the mutex.
|
||
|
* @retval true If the mutex was locked.
|
||
|
* @retval false If ticksToWait expired without the mutex becoming available.
|
||
|
*
|
||
|
* <b>Example Usage</b>
|
||
|
* @include Mutex/lock.cpp
|
||
|
*/
|
||
|
inline bool lock(const TickType_t ticksToWait = portMAX_DELAY) const {
|
||
|
return (xSemaphoreTake(handle, ticksToWait) == pdTRUE);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Mutex.hpp
|
||
|
*
|
||
|
* @brief Function that calls <tt>xSemaphoreTakeFromISR ( SemaphoreHandle_t
|
||
|
* xSemaphore, signed BaseType_t *pxHigherPriorityTaskWoken )</tt>
|
||
|
*
|
||
|
* @see <https://www.freertos.org/xSemaphoreTakeFromISR.html>
|
||
|
*
|
||
|
* @param higherPriorityTaskWoken It is possible (although unlikely, and
|
||
|
* dependent on the semaphore type) that a mutex will have one or more tasks
|
||
|
* blocked on it waiting to give the mutex. Calling lockFromISR() will make a
|
||
|
* task that was blocked waiting to give the mutex leave the Blocked state. If
|
||
|
* calling the API function causes a task to leave the Blocked state, and the
|
||
|
* unblocked task has a priority equal to or higher than the currently
|
||
|
* executing task (the task that was interrupted), then, internally, the API
|
||
|
* function will set higherPriorityTaskWoken to true.
|
||
|
* @return true If the mutex was successfully locked.
|
||
|
* @return false If the mutex was not successfully locked because it was not
|
||
|
* available.
|
||
|
*/
|
||
|
inline bool lockFromISR(bool& higherPriorityTaskWoken) const {
|
||
|
BaseType_t taskWoken = pdFALSE;
|
||
|
bool result = (xSemaphoreTakeFromISR(handle, &taskWoken) == pdTRUE);
|
||
|
if (taskWoken == pdTRUE) {
|
||
|
higherPriorityTaskWoken = true;
|
||
|
}
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Mutex.hpp
|
||
|
*
|
||
|
* @brief Function that calls <tt>xSemaphoreTakeFromISR ( SemaphoreHandle_t
|
||
|
* xSemaphore, signed BaseType_t *pxHigherPriorityTaskWoken )</tt>
|
||
|
*
|
||
|
* @see <https://www.freertos.org/xSemaphoreTakeFromISR.html>
|
||
|
*
|
||
|
* @overload
|
||
|
*/
|
||
|
inline bool lockFromISR() const {
|
||
|
return (xSemaphoreTakeFromISR(handle, NULL) == pdTRUE);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Mutex.hpp
|
||
|
*
|
||
|
* @brief Function that calls <tt>xSemaphoreGive( SemaphoreHandle_t xSemaphore
|
||
|
* )</tt>
|
||
|
*
|
||
|
* @see <https://www.freertos.org/a00123.html>
|
||
|
*
|
||
|
* @warning This must not be used from an ISR.
|
||
|
*
|
||
|
* @return true If the mutex was unlocked.
|
||
|
* @return false If an error occurred. Mutexes (semaphores) are implemented
|
||
|
* using queues. An error can occur if there is no space on the queue to post
|
||
|
* a message indicating that the mutex was not first locked correctly.
|
||
|
*
|
||
|
* <b>Example Usage</b>
|
||
|
* @include Mutex/unlock.cpp
|
||
|
*/
|
||
|
inline bool unlock() const { return (xSemaphoreGive(handle) == pdTRUE); }
|
||
|
|
||
|
private:
|
||
|
MutexBase() = default;
|
||
|
|
||
|
/**
|
||
|
* Mutex.hpp
|
||
|
*
|
||
|
* @brief Destroy the MutexBase object by calling <tt>void vSemaphoreDelete(
|
||
|
* SemaphoreHandle_t xSemaphore )</tt>
|
||
|
*
|
||
|
* @see <https://www.freertos.org/a00113.html#vSemaphoreDelete>
|
||
|
*
|
||
|
* @note Do not delete a mutex that has tasks blocked on it (tasks that are in
|
||
|
* the Blocked state waiting for the mutex to become available).
|
||
|
*/
|
||
|
~MutexBase() { vSemaphoreDelete(this->handle); }
|
||
|
|
||
|
MutexBase(MutexBase&&) noexcept = default;
|
||
|
MutexBase& operator=(MutexBase&&) noexcept = default;
|
||
|
|
||
|
/**
|
||
|
* @brief Handle used to refer to the semaphore when using the FreeRTOS
|
||
|
* interface.
|
||
|
*/
|
||
|
SemaphoreHandle_t handle = NULL;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* @class RecursiveMutexBase Mutex.hpp <FreeRTOS/Mutex.hpp>
|
||
|
*
|
||
|
* @brief Base class that provides the recursive mutex interface to
|
||
|
* FreeRTOS::RecursiveMutex and FreeRTOS::StaticRecursiveMutex. This class
|
||
|
* exists to override the lock() and unlock() functions which require different
|
||
|
* underlying functions from what is used in FreeRTOS::MutexBase.
|
||
|
*
|
||
|
* @note This class is not intended to be instantiated by the user. Use
|
||
|
* FreeRTOS::RecursiveMutex or FreeRTOS::StaticRecursiveMutex.
|
||
|
*/
|
||
|
class RecursiveMutexBase : public MutexBase {
|
||
|
public:
|
||
|
friend class RecursiveMutex;
|
||
|
friend class StaticRecursiveMutex;
|
||
|
|
||
|
RecursiveMutexBase(const RecursiveMutexBase&) = delete;
|
||
|
RecursiveMutexBase& operator=(const RecursiveMutexBase&) = delete;
|
||
|
|
||
|
static void* operator new(size_t, void*);
|
||
|
static void* operator new[](size_t, void*);
|
||
|
static void* operator new(size_t) = delete;
|
||
|
static void* operator new[](size_t) = delete;
|
||
|
|
||
|
/**
|
||
|
* Mutex.hpp
|
||
|
*
|
||
|
* @brief Function that calls <tt>xSemaphoreTakeRecursive( SemaphoreHandle_t
|
||
|
* xMutex, TickType_t xTicksToWait )</tt>
|
||
|
*
|
||
|
* @see <https://www.freertos.org/xSemaphoreTakeRecursive.html>
|
||
|
*
|
||
|
* @param ticksToWait The time in ticks to wait for the mutex to become
|
||
|
* available. The macro portTICK_PERIOD_MS can be used to convert this to a
|
||
|
* real time. A block time of zero can be used to poll the mutex. If the task
|
||
|
* already owns the mutex then take() will return immediately no matter what
|
||
|
* the value of ticksToWait.
|
||
|
* @retval true If the mutex was locked.
|
||
|
* @retval false If ticksToWait expired without the mutex becoming available.
|
||
|
*
|
||
|
* <b>Example Usage</b>
|
||
|
* @include Mutex/recursiveLock.cpp
|
||
|
*/
|
||
|
inline bool lock(const TickType_t ticksToWait = portMAX_DELAY) const {
|
||
|
return (xSemaphoreTakeRecursive(handle, ticksToWait) == pdTRUE);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Mutex.hpp
|
||
|
*
|
||
|
* @brief Function that calls <tt>xSemaphoreGiveRecursive( SemaphoreHandle_t
|
||
|
* xSemaphore )</tt>
|
||
|
*
|
||
|
* @see <https://www.freertos.org/xSemaphoreGiveRecursive.html>
|
||
|
*
|
||
|
* A mutex used recursively can be locked repeatedly by the owner. The mutex
|
||
|
* doesn't become available again until the owner has called unlock() for each
|
||
|
* successful lock request. For example, if a task successfully locks the
|
||
|
* same mutex 5 times then the mutex will not be available to any other task
|
||
|
* until it has also unlocked the mutex back exactly five times.
|
||
|
*
|
||
|
* @return true If the mutex was unlocked.
|
||
|
* @return false Otherwise.
|
||
|
*
|
||
|
* <b>Example Usage</b>
|
||
|
* @include Mutex/recursiveLock.cpp
|
||
|
*/
|
||
|
inline bool unlock() const {
|
||
|
return (xSemaphoreGiveRecursive(handle) == pdTRUE);
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
RecursiveMutexBase() = default;
|
||
|
~RecursiveMutexBase() = default;
|
||
|
|
||
|
RecursiveMutexBase(RecursiveMutexBase&&) noexcept = default;
|
||
|
RecursiveMutexBase& operator=(RecursiveMutexBase&&) noexcept = default;
|
||
|
};
|
||
|
|
||
|
#if (configSUPPORT_DYNAMIC_ALLOCATION == 1)
|
||
|
|
||
|
/**
|
||
|
* @class Mutex Mutex.hpp <FreeRTOS/Mutex.hpp>
|
||
|
*
|
||
|
* @brief Class that encapsulates the functionality of a FreeRTOS mutex.
|
||
|
*
|
||
|
* Each mutex require a small amount of RAM that is used to hold the mutex's
|
||
|
* state. If a mutex is created using FreeRTOS::Mutex then the required RAM is
|
||
|
* automatically allocated from the FreeRTOS heap. If a mutex is created using
|
||
|
* FreeRTOS::StaticMutex then the RAM is provided by the application writer and
|
||
|
* allows the RAM to be statically allocated at compile time. See the Static Vs
|
||
|
* Dynamic allocation page for more information.
|
||
|
*
|
||
|
* Mutexes and binary semaphores are very similar but have some subtle
|
||
|
* differences: Mutexes include a priority inheritance mechanism, binary
|
||
|
* semaphores do not. This makes binary semaphores the better choice for
|
||
|
* implementing synchronisation (between tasks or between tasks and an
|
||
|
* interrupt), and mutexes the better choice for implementing simple mutual
|
||
|
* exclusion.
|
||
|
*
|
||
|
* The priority of a task that locks a mutex will be temporarily raised if
|
||
|
* another task of higher priority attempts to obtain the same mutex. The task
|
||
|
* that owns the mutex 'inherits' the priority of the task attempting to lock
|
||
|
* the same mutex. This means the mutex must always be unlocked back otherwise
|
||
|
* the higher priority task will never be able to lock the mutex, and the lower
|
||
|
* priority task will never 'disinherit' the priority.
|
||
|
*/
|
||
|
class Mutex : public MutexBase {
|
||
|
public:
|
||
|
/**
|
||
|
* Mutex.hpp
|
||
|
*
|
||
|
* @brief Construct a new Mutex object by calling <tt>SemaphoreHandle_t
|
||
|
* xSemaphoreCreateMutex( void )</tt>
|
||
|
*
|
||
|
* @see <https://www.freertos.org/CreateMutex.html>
|
||
|
*
|
||
|
* @warning The user should call isValid() on this object to verify that the
|
||
|
* mutex was created successfully in case the memory required to create the
|
||
|
* queue could not be allocated.
|
||
|
*
|
||
|
* <b>Example Usage</b>
|
||
|
* @include Mutex/mutex.cpp
|
||
|
*/
|
||
|
Mutex() { this->handle = xSemaphoreCreateMutex(); }
|
||
|
~Mutex() = default;
|
||
|
|
||
|
Mutex(const Mutex&) = delete;
|
||
|
Mutex& operator=(const Mutex&) = delete;
|
||
|
|
||
|
Mutex(Mutex&&) noexcept = default;
|
||
|
Mutex& operator=(Mutex&&) noexcept = default;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* @class RecursiveMutex Mutex.hpp <FreeRTOS/Mutex.hpp>
|
||
|
*
|
||
|
* @brief Class that encapsulates the functionality of a FreeRTOS recursive
|
||
|
* mutex.
|
||
|
*
|
||
|
* Each recursive mutex require a small amount of RAM that is used to hold the
|
||
|
* recursive mutex's state. If a mutex is created using FreeRTOS::RecursiveMutex
|
||
|
* then the required RAM is automatically allocated from the FreeRTOS heap. If a
|
||
|
* recursive mutex is created using FreeRTOS::StaticRecursiveMutex then the RAM
|
||
|
* is provided by the application writer, which requires an additional
|
||
|
* parameter, but allows the RAM to be statically allocated at compile time. See
|
||
|
* the Static Vs Dynamic allocation page for more information.
|
||
|
*
|
||
|
* Contrary to non-recursive mutexes, a task can lock a recursive mutex multiple
|
||
|
* times, and the recursive mutex will only be returned after the holding task
|
||
|
* has unlocked the mutex the same number of times it locked the mutex.
|
||
|
*
|
||
|
* Like non-recursive mutexes, recursive mutexes implement a priority
|
||
|
* inheritance algorithm. The priority of a task that locks a mutex will be
|
||
|
* temporarily raised if another task of higher priority attempts to obtain the
|
||
|
* same mutex. The task that owns the mutex 'inherits' the priority of the task
|
||
|
* attempting to lock the same mutex. This means the mutex must always be
|
||
|
* unlocked otherwise the higher priority task will never be able to obtain the
|
||
|
* mutex, and the lower priority task will never 'disinherit' the priority.
|
||
|
*/
|
||
|
class RecursiveMutex : public RecursiveMutexBase {
|
||
|
public:
|
||
|
/**
|
||
|
* Mutex.hpp
|
||
|
*
|
||
|
* @brief Construct a new RecursiveMutex object by calling
|
||
|
* <tt>SemaphoreHandle_t xSemaphoreCreateRecursiveMutex( void )</tt>
|
||
|
*
|
||
|
* @see <https://www.freertos.org/xSemaphoreCreateRecursiveMutex.html>
|
||
|
*
|
||
|
* @warning The user should call isValid() on this object to verify that the
|
||
|
* recursive mutex was created successfully in case the memory required to
|
||
|
* create the queue could not be allocated.
|
||
|
*
|
||
|
* <b>Example Usage</b>
|
||
|
* @include Mutex/recursiveMutex.cpp
|
||
|
*/
|
||
|
RecursiveMutex() { this->handle = xSemaphoreCreateRecursiveMutex(); }
|
||
|
~RecursiveMutex() = default;
|
||
|
|
||
|
RecursiveMutex(const RecursiveMutex&) = delete;
|
||
|
RecursiveMutex& operator=(const RecursiveMutex&) = delete;
|
||
|
|
||
|
RecursiveMutex(RecursiveMutex&&) noexcept = default;
|
||
|
RecursiveMutex& operator=(RecursiveMutex&&) noexcept = default;
|
||
|
};
|
||
|
|
||
|
#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
|
||
|
|
||
|
#if (configSUPPORT_STATIC_ALLOCATION == 1)
|
||
|
|
||
|
/**
|
||
|
* @class StaticMutex Mutex.hpp <FreeRTOS/Mutex.hpp>
|
||
|
*
|
||
|
* @brief Class that encapsulates the functionality of a FreeRTOS mutex.
|
||
|
*
|
||
|
* Each mutex require a small amount of RAM that is used to hold the mutex's
|
||
|
* state. If a mutex is created using FreeRTOS::Mutex then the required RAM is
|
||
|
* automatically allocated from the FreeRTOS heap. If a mutex is created using
|
||
|
* FreeRTOS::StaticMutex then the RAM is provided by the application writer and
|
||
|
* allows the RAM to be statically allocated at compile time. See the Static Vs
|
||
|
* Dynamic allocation page for more information.
|
||
|
*
|
||
|
* Mutexes and binary semaphores are very similar but have some subtle
|
||
|
* differences: Mutexes include a priority inheritance mechanism, binary
|
||
|
* semaphores do not. This makes binary semaphores the better choice for
|
||
|
* implementing synchronisation (between tasks or between tasks and an
|
||
|
* interrupt), and mutexes the better choice for implementing simple mutual
|
||
|
* exclusion.
|
||
|
*
|
||
|
* The priority of a task that locks a mutex will be temporarily raised if
|
||
|
* another task of higher priority attempts to obtain the same mutex. The task
|
||
|
* that owns the mutex 'inherits' the priority of the task attempting to lock
|
||
|
* the same mutex. This means the mutex must always be unlocked back otherwise
|
||
|
* the higher priority task will never be able to lock the mutex, and the lower
|
||
|
* priority task will never 'disinherit' the priority.
|
||
|
*/
|
||
|
class StaticMutex : public MutexBase {
|
||
|
public:
|
||
|
/**
|
||
|
* Mutex.hpp
|
||
|
*
|
||
|
* @brief Construct a new StaticMutex object by calling
|
||
|
* <tt>SemaphoreHandle_t xSemaphoreCreateMutexStatic( StaticSemaphore_t
|
||
|
* *pxMutexBuffer )</tt>
|
||
|
*
|
||
|
* @see <https://www.freertos.org/xSemaphoreCreateMutexStatic.html>
|
||
|
*
|
||
|
* @warning This class contains the storage buffer for the mutex, so the user
|
||
|
* should create this object as a global object or with the static storage
|
||
|
* specifier so that the object instance is not on the stack.
|
||
|
*
|
||
|
* <b>Example Usage</b>
|
||
|
* @include Mutex/staticMutex.cpp
|
||
|
*/
|
||
|
StaticMutex() { this->handle = xSemaphoreCreateMutexStatic(&staticMutex); }
|
||
|
~StaticMutex() = default;
|
||
|
|
||
|
StaticMutex(const StaticMutex&) = delete;
|
||
|
StaticMutex& operator=(const StaticMutex&) = delete;
|
||
|
|
||
|
StaticMutex(StaticMutex&&) noexcept = default;
|
||
|
StaticMutex& operator=(StaticMutex&&) noexcept = default;
|
||
|
|
||
|
private:
|
||
|
StaticSemaphore_t staticMutex;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* @class StaticRecursiveMutex Mutex.hpp <FreeRTOS/Mutex.hpp>
|
||
|
*
|
||
|
* @brief Class that encapsulates the functionality of a FreeRTOS recursive
|
||
|
* mutex.
|
||
|
*
|
||
|
* Each recursive mutex require a small amount of RAM that is used to hold the
|
||
|
* recursive mutex's state. If a mutex is created using FreeRTOS::RecursiveMutex
|
||
|
* then the required RAM is automatically allocated from the FreeRTOS heap. If a
|
||
|
* recursive mutex is created using FreeRTOS::StaticRecursiveMutex then the RAM
|
||
|
* is provided by the application writer, which requires an additional
|
||
|
* parameter, but allows the RAM to be statically allocated at compile time. See
|
||
|
* the Static Vs Dynamic allocation page for more information.
|
||
|
*
|
||
|
* Contrary to non-recursive mutexes, a task can lock a recursive mutex multiple
|
||
|
* times, and the recursive mutex will only be returned after the holding task
|
||
|
* has unlocked the mutex the same number of times it locked the mutex.
|
||
|
*
|
||
|
* Like non-recursive mutexes, recursive mutexes implement a priority
|
||
|
* inheritance algorithm. The priority of a task that locks a mutex will be
|
||
|
* temporarily raised if another task of higher priority attempts to obtain the
|
||
|
* same mutex. The task that owns the mutex 'inherits' the priority of the task
|
||
|
* attempting to lock the same mutex. This means the mutex must always be
|
||
|
* unlocked otherwise the higher priority task will never be able to obtain the
|
||
|
* mutex, and the lower priority task will never 'disinherit' the priority.
|
||
|
*/
|
||
|
class StaticRecursiveMutex : public RecursiveMutexBase {
|
||
|
public:
|
||
|
/**
|
||
|
* Mutex.hpp
|
||
|
*
|
||
|
* @brief Construct a new StaticRecursiveMutex object by calling
|
||
|
* <tt>SemaphoreHandle_t xSemaphoreCreateRecursiveMutexStatic(
|
||
|
* StaticSemaphore_t *pxMutexBuffer )</tt>
|
||
|
*
|
||
|
* @see <https://www.freertos.org/xSemaphoreCreateRecursiveMutexStatic.html>
|
||
|
*
|
||
|
* @warning This class contains the storage buffer for the recursive mutex, so
|
||
|
* the user should create this object as a global object or with the static
|
||
|
* storage specifier so that the object instance is not on the stack.
|
||
|
*
|
||
|
* <b>Example Usage</b>
|
||
|
* @include Mutex/staticRecursiveMutex.cpp
|
||
|
*/
|
||
|
StaticRecursiveMutex() {
|
||
|
this->handle = xSemaphoreCreateRecursiveMutexStatic(&staticRecursiveMutex);
|
||
|
}
|
||
|
~StaticRecursiveMutex() = default;
|
||
|
|
||
|
StaticRecursiveMutex(const StaticRecursiveMutex&) = delete;
|
||
|
StaticRecursiveMutex& operator=(const StaticRecursiveMutex&) = delete;
|
||
|
|
||
|
StaticRecursiveMutex(StaticRecursiveMutex&&) noexcept = default;
|
||
|
StaticRecursiveMutex& operator=(StaticRecursiveMutex&&) noexcept = default;
|
||
|
|
||
|
private:
|
||
|
StaticSemaphore_t staticRecursiveMutex;
|
||
|
};
|
||
|
|
||
|
#endif /* configSUPPORT_STATIC_ALLOCATION */
|
||
|
|
||
|
} // namespace FreeRTOS
|
||
|
|
||
|
#endif // FREERTOS_MUTEX_HPP
|