feat: add lab-rv32i-freertos-semaphore-notify card
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
#ifndef K12_HOST_FREERTOS_H
|
||||
#define K12_HOST_FREERTOS_H
|
||||
#include <stdint.h>
|
||||
typedef int32_t BaseType_t;
|
||||
typedef uint32_t UBaseType_t;
|
||||
typedef uint32_t TickType_t;
|
||||
typedef void * TaskHandle_t;
|
||||
struct MockSemaphore
|
||||
{
|
||||
UBaseType_t count;
|
||||
UBaseType_t maximum;
|
||||
};
|
||||
typedef struct MockSemaphore * SemaphoreHandle_t;
|
||||
typedef struct MockSemaphore StaticSemaphore_t;
|
||||
#define pdFALSE ( ( BaseType_t ) 0 )
|
||||
#define pdTRUE ( ( BaseType_t ) 1 )
|
||||
#define pdFAIL ( ( BaseType_t ) 0 )
|
||||
#define pdPASS ( ( BaseType_t ) 1 )
|
||||
#endif
|
||||
@@ -0,0 +1,16 @@
|
||||
#ifndef K12_HOST_SEMPHR_H
|
||||
#define K12_HOST_SEMPHR_H
|
||||
#include "FreeRTOS.h"
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
SemaphoreHandle_t xSemaphoreCreateBinaryStatic( StaticSemaphore_t * );
|
||||
SemaphoreHandle_t xSemaphoreCreateCountingStatic( UBaseType_t, UBaseType_t, StaticSemaphore_t * );
|
||||
BaseType_t xSemaphoreTake( SemaphoreHandle_t, TickType_t );
|
||||
BaseType_t xSemaphoreGive( SemaphoreHandle_t );
|
||||
UBaseType_t uxSemaphoreGetCount( SemaphoreHandle_t );
|
||||
void vSemaphoreDelete( SemaphoreHandle_t );
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,22 @@
|
||||
#ifndef K12_HOST_TASK_H
|
||||
#define K12_HOST_TASK_H
|
||||
#include "FreeRTOS.h"
|
||||
typedef enum eNotifyAction
|
||||
{
|
||||
eNoAction = 0,
|
||||
eSetBits,
|
||||
eIncrement,
|
||||
eSetValueWithOverwrite,
|
||||
eSetValueWithoutOverwrite
|
||||
} eNotifyAction;
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
BaseType_t xTaskNotifyGive( TaskHandle_t );
|
||||
BaseType_t xTaskNotify( TaskHandle_t, uint32_t, eNotifyAction );
|
||||
uint32_t ulTaskNotifyTake( BaseType_t, TickType_t );
|
||||
BaseType_t xTaskNotifyWait( uint32_t, uint32_t, uint32_t *, TickType_t );
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,135 @@
|
||||
#include <cassert>
|
||||
#include <type_traits>
|
||||
|
||||
#include "freertos/synchronization.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
unsigned target_token;
|
||||
uint32_t notification_value;
|
||||
bool notification_pending;
|
||||
unsigned deletes;
|
||||
TickType_t last_timeout;
|
||||
eNotifyAction last_action;
|
||||
} // namespace
|
||||
|
||||
extern "C" SemaphoreHandle_t xSemaphoreCreateBinaryStatic(
|
||||
StaticSemaphore_t * storage )
|
||||
{
|
||||
*storage = MockSemaphore { 0U, 1U };
|
||||
return storage;
|
||||
}
|
||||
extern "C" SemaphoreHandle_t xSemaphoreCreateCountingStatic(
|
||||
UBaseType_t maximum, UBaseType_t initial, StaticSemaphore_t * storage )
|
||||
{
|
||||
if( initial > maximum ) return nullptr;
|
||||
*storage = MockSemaphore { initial, maximum };
|
||||
return storage;
|
||||
}
|
||||
extern "C" BaseType_t xSemaphoreTake( SemaphoreHandle_t semaphore,
|
||||
TickType_t timeout )
|
||||
{
|
||||
last_timeout = timeout;
|
||||
if( semaphore->count == 0U ) return pdFAIL;
|
||||
--semaphore->count;
|
||||
return pdPASS;
|
||||
}
|
||||
extern "C" BaseType_t xSemaphoreGive( SemaphoreHandle_t semaphore )
|
||||
{
|
||||
if( semaphore->count == semaphore->maximum ) return pdFAIL;
|
||||
++semaphore->count;
|
||||
return pdPASS;
|
||||
}
|
||||
extern "C" UBaseType_t uxSemaphoreGetCount( SemaphoreHandle_t semaphore )
|
||||
{
|
||||
return semaphore->count;
|
||||
}
|
||||
extern "C" void vSemaphoreDelete( SemaphoreHandle_t )
|
||||
{
|
||||
++deletes;
|
||||
}
|
||||
extern "C" BaseType_t xTaskNotifyGive( TaskHandle_t target )
|
||||
{
|
||||
if( target != &target_token ) return pdFAIL;
|
||||
++notification_value;
|
||||
notification_pending = true;
|
||||
return pdPASS;
|
||||
}
|
||||
extern "C" BaseType_t xTaskNotify( TaskHandle_t target, uint32_t value,
|
||||
eNotifyAction action )
|
||||
{
|
||||
if( target != &target_token ) return pdFAIL;
|
||||
last_action = action;
|
||||
if( action == eSetBits ) notification_value |= value;
|
||||
else if( action == eIncrement ) ++notification_value;
|
||||
else if( action == eSetValueWithOverwrite ) notification_value = value;
|
||||
else if( action == eSetValueWithoutOverwrite )
|
||||
{
|
||||
if( notification_pending ) return pdFAIL;
|
||||
notification_value = value;
|
||||
}
|
||||
notification_pending = true;
|
||||
return pdPASS;
|
||||
}
|
||||
extern "C" uint32_t ulTaskNotifyTake( BaseType_t clear, TickType_t timeout )
|
||||
{
|
||||
last_timeout = timeout;
|
||||
const uint32_t result = notification_value;
|
||||
if( result == 0U ) return 0U;
|
||||
if( clear != pdFALSE ) notification_value = 0U;
|
||||
else --notification_value;
|
||||
notification_pending = false;
|
||||
return result;
|
||||
}
|
||||
extern "C" BaseType_t xTaskNotifyWait( uint32_t clear_entry,
|
||||
uint32_t clear_exit,
|
||||
uint32_t * value,
|
||||
TickType_t timeout )
|
||||
{
|
||||
last_timeout = timeout;
|
||||
notification_value &= ~clear_entry;
|
||||
if( !notification_pending ) return pdFAIL;
|
||||
*value = notification_value;
|
||||
notification_value &= ~clear_exit;
|
||||
notification_pending = false;
|
||||
return pdPASS;
|
||||
}
|
||||
|
||||
static_assert( !std::is_copy_constructible< freertos::BinarySemaphore >::value );
|
||||
static_assert( !std::is_move_constructible<
|
||||
freertos::CountingSemaphore< 2U > >::value );
|
||||
static_assert( std::is_trivially_copyable<
|
||||
freertos::TaskNotification >::value );
|
||||
|
||||
int main()
|
||||
{
|
||||
freertos::StaticSemaphoreStorage binary_storage {};
|
||||
freertos::StaticSemaphoreStorage counting_storage {};
|
||||
{
|
||||
freertos::BinarySemaphore binary { binary_storage };
|
||||
assert( binary.valid() && binary.count() == 0U );
|
||||
assert( binary.give() && binary.count() == 1U );
|
||||
assert( !binary.give() );
|
||||
assert( binary.take( 7U ) && last_timeout == 7U );
|
||||
assert( binary.count() == 0U );
|
||||
|
||||
freertos::CountingSemaphore< 2U > counting { counting_storage, 2U };
|
||||
assert( counting.valid() && counting.maximum() == 2U );
|
||||
assert( !counting.give() );
|
||||
assert( counting.take( 0U ) && counting.count() == 1U );
|
||||
assert( counting.take( 0U ) && counting.count() == 0U );
|
||||
assert( !counting.take( 4U ) && last_timeout == 4U );
|
||||
assert( counting.give() && counting.count() == 1U );
|
||||
|
||||
freertos::TaskNotification notification { &target_token };
|
||||
assert( notification.valid() && notification.give() );
|
||||
assert( freertos::TaskNotification::take( true, 3U ) == 1U );
|
||||
assert( notification.notify(
|
||||
0xA5A55A5AU, freertos::NotificationAction::overwrite ) );
|
||||
assert( last_action == eSetValueWithOverwrite );
|
||||
uint32_t value = 0U;
|
||||
assert( freertos::TaskNotification::wait_value( value, 5U ) );
|
||||
assert( value == 0xA5A55A5AU && last_timeout == 5U );
|
||||
}
|
||||
assert( deletes == 2U );
|
||||
}
|
||||
Reference in New Issue
Block a user