feat: add lab-rv32i-freertos-semaphore-notify card
This commit is contained in:
@@ -0,0 +1,183 @@
|
||||
#ifndef FREERTOS_CPP_SYNCHRONIZATION_HPP
|
||||
#define FREERTOS_CPP_SYNCHRONIZATION_HPP
|
||||
|
||||
#include <stdint.h>
|
||||
#include <type_traits>
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include "FreeRTOS.h"
|
||||
#include "semphr.h"
|
||||
#include "task.h"
|
||||
}
|
||||
|
||||
namespace freertos
|
||||
{
|
||||
|
||||
struct StaticSemaphoreStorage final
|
||||
{
|
||||
StaticSemaphore_t control {};
|
||||
};
|
||||
|
||||
class BinarySemaphore final
|
||||
{
|
||||
public:
|
||||
explicit BinarySemaphore( StaticSemaphoreStorage & storage ) noexcept
|
||||
: handle_ { xSemaphoreCreateBinaryStatic( &storage.control ) }
|
||||
{
|
||||
}
|
||||
|
||||
~BinarySemaphore() noexcept
|
||||
{
|
||||
if( handle_ != nullptr ) vSemaphoreDelete( handle_ );
|
||||
}
|
||||
|
||||
BinarySemaphore( const BinarySemaphore & ) = delete;
|
||||
BinarySemaphore & operator=( const BinarySemaphore & ) = delete;
|
||||
BinarySemaphore( BinarySemaphore && ) = delete;
|
||||
BinarySemaphore & operator=( BinarySemaphore && ) = delete;
|
||||
|
||||
[[nodiscard]] bool valid() const noexcept { return handle_ != nullptr; }
|
||||
[[nodiscard]] bool give() noexcept
|
||||
{
|
||||
return handle_ != nullptr && xSemaphoreGive( handle_ ) == pdPASS;
|
||||
}
|
||||
[[nodiscard]] bool take( TickType_t timeout ) noexcept
|
||||
{
|
||||
return handle_ != nullptr &&
|
||||
xSemaphoreTake( handle_, timeout ) == pdPASS;
|
||||
}
|
||||
[[nodiscard]] UBaseType_t count() const noexcept
|
||||
{
|
||||
return handle_ == nullptr ? 0U : uxSemaphoreGetCount( handle_ );
|
||||
}
|
||||
[[nodiscard]] SemaphoreHandle_t native_handle() const noexcept
|
||||
{
|
||||
return handle_;
|
||||
}
|
||||
|
||||
private:
|
||||
SemaphoreHandle_t handle_ {};
|
||||
};
|
||||
|
||||
template< UBaseType_t Maximum >
|
||||
class CountingSemaphore final
|
||||
{
|
||||
static_assert( Maximum > 0U, "CountingSemaphore maximum must be positive" );
|
||||
|
||||
public:
|
||||
CountingSemaphore( StaticSemaphoreStorage & storage,
|
||||
UBaseType_t initial ) noexcept
|
||||
: handle_ { initial <= Maximum ?
|
||||
xSemaphoreCreateCountingStatic(
|
||||
Maximum, initial, &storage.control ) : nullptr }
|
||||
{
|
||||
}
|
||||
|
||||
~CountingSemaphore() noexcept
|
||||
{
|
||||
if( handle_ != nullptr ) vSemaphoreDelete( handle_ );
|
||||
}
|
||||
|
||||
CountingSemaphore( const CountingSemaphore & ) = delete;
|
||||
CountingSemaphore & operator=( const CountingSemaphore & ) = delete;
|
||||
CountingSemaphore( CountingSemaphore && ) = delete;
|
||||
CountingSemaphore & operator=( CountingSemaphore && ) = delete;
|
||||
|
||||
[[nodiscard]] bool valid() const noexcept { return handle_ != nullptr; }
|
||||
[[nodiscard]] bool give() noexcept
|
||||
{
|
||||
return handle_ != nullptr && xSemaphoreGive( handle_ ) == pdPASS;
|
||||
}
|
||||
[[nodiscard]] bool take( TickType_t timeout ) noexcept
|
||||
{
|
||||
return handle_ != nullptr &&
|
||||
xSemaphoreTake( handle_, timeout ) == pdPASS;
|
||||
}
|
||||
[[nodiscard]] UBaseType_t count() const noexcept
|
||||
{
|
||||
return handle_ == nullptr ? 0U : uxSemaphoreGetCount( handle_ );
|
||||
}
|
||||
static constexpr UBaseType_t maximum() noexcept { return Maximum; }
|
||||
[[nodiscard]] SemaphoreHandle_t native_handle() const noexcept
|
||||
{
|
||||
return handle_;
|
||||
}
|
||||
|
||||
private:
|
||||
SemaphoreHandle_t handle_ {};
|
||||
};
|
||||
|
||||
enum class NotificationAction : uint8_t
|
||||
{
|
||||
no_action,
|
||||
set_bits,
|
||||
increment,
|
||||
overwrite,
|
||||
without_overwrite
|
||||
};
|
||||
|
||||
class TaskNotification final
|
||||
{
|
||||
public:
|
||||
explicit constexpr TaskNotification( TaskHandle_t target ) noexcept
|
||||
: target_ { target }
|
||||
{
|
||||
}
|
||||
|
||||
[[nodiscard]] bool valid() const noexcept { return target_ != nullptr; }
|
||||
|
||||
[[nodiscard]] bool give() const noexcept
|
||||
{
|
||||
return target_ != nullptr && xTaskNotifyGive( target_ ) == pdPASS;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool notify( uint32_t value,
|
||||
NotificationAction action ) const noexcept
|
||||
{
|
||||
return target_ != nullptr &&
|
||||
xTaskNotify( target_, value, raw_action( action ) ) == pdPASS;
|
||||
}
|
||||
|
||||
[[nodiscard]] static uint32_t take( bool clear_on_exit,
|
||||
TickType_t timeout ) noexcept
|
||||
{
|
||||
return ulTaskNotifyTake( clear_on_exit ? pdTRUE : pdFALSE, timeout );
|
||||
}
|
||||
|
||||
[[nodiscard]] static bool wait_value( uint32_t & value,
|
||||
TickType_t timeout,
|
||||
uint32_t clear_on_entry = 0U,
|
||||
uint32_t clear_on_exit = UINT32_MAX ) noexcept
|
||||
{
|
||||
return xTaskNotifyWait( clear_on_entry, clear_on_exit,
|
||||
&value, timeout ) == pdPASS;
|
||||
}
|
||||
|
||||
[[nodiscard]] TaskHandle_t target() const noexcept { return target_; }
|
||||
|
||||
private:
|
||||
static eNotifyAction raw_action( NotificationAction action ) noexcept
|
||||
{
|
||||
switch( action )
|
||||
{
|
||||
case NotificationAction::no_action: return eNoAction;
|
||||
case NotificationAction::set_bits: return eSetBits;
|
||||
case NotificationAction::increment: return eIncrement;
|
||||
case NotificationAction::overwrite: return eSetValueWithOverwrite;
|
||||
case NotificationAction::without_overwrite:
|
||||
return eSetValueWithoutOverwrite;
|
||||
}
|
||||
return eNoAction;
|
||||
}
|
||||
|
||||
TaskHandle_t target_ {};
|
||||
};
|
||||
|
||||
static_assert( !std::is_copy_constructible< BinarySemaphore >::value );
|
||||
static_assert( !std::is_move_constructible< CountingSemaphore< 2U > >::value );
|
||||
static_assert( std::is_trivially_copyable< TaskNotification >::value );
|
||||
|
||||
} // namespace freertos
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user