#include #include #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 ); }