136 lines
4.5 KiB
C++
136 lines
4.5 KiB
C++
#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 );
|
|
}
|