#include #include #include #include "freertos/isr_drivers.hpp" struct FakeQueue { UBaseType_t capacity; UBaseType_t item_size; UBaseType_t count; std::uint8_t * storage; }; static std::uint32_t fake_yield_calls; static BaseType_t fake_last_yield; extern "C" QueueHandle_t xQueueCreateStatic( UBaseType_t capacity, UBaseType_t item_size, std::uint8_t * storage, StaticQueue_t * control ) { static_assert( sizeof( FakeQueue ) <= sizeof( StaticQueue_t ) ); return new ( control->bytes ) FakeQueue{ capacity, item_size, 0U, storage }; } extern "C" BaseType_t xQueueSendFromISR( QueueHandle_t queue, const void * item, BaseType_t * woken ) { if( queue->count == queue->capacity ) { return pdFAIL; } auto const * source = static_cast< const std::uint8_t * >( item ); for( UBaseType_t index = 0U; index < queue->item_size; ++index ) { queue->storage[ queue->count * queue->item_size + index ] = source[ index ]; } ++queue->count; *woken = pdTRUE; return pdPASS; } extern "C" BaseType_t xQueueReceive( QueueHandle_t queue, void * item, TickType_t ) { if( queue->count == 0U ) { return pdFAIL; } auto * destination = static_cast< std::uint8_t * >( item ); for( UBaseType_t index = 0U; index < queue->item_size; ++index ) { destination[ index ] = queue->storage[ index ]; } --queue->count; return pdPASS; } extern "C" void vTaskNotifyGiveFromISR( TaskHandle_t, BaseType_t * woken ) { *woken = pdTRUE; } extern "C" void fake_yield_from_isr( BaseType_t request ) { ++fake_yield_calls; fake_last_yield = request; } int main() { StaticQueue_t control{}; std::uint8_t bytes[ 1 ]{}; freertos::StaticIsrQueue< std::uint8_t, 1U > queue{ control, bytes }; freertos::UartRegisters uart_registers{}; freertos::GpioRegisters gpio_registers{}; freertos::Uart uart{ uart_registers }; freertos::GpioPin gpio{ gpio_registers }; freertos::IsrContext context; uart.task_view().enable_rx_irq(); uart.task_view().inject_rx_pair_for_test( 0x41U, 0x42U ); gpio.task_view().configure_output( 1U ); gpio.task_view().inject_edge_for_test( 1U ); auto uart_isr = uart.isr_view(); auto gpio_isr = gpio.isr_view(); std::uint8_t const first = uart_isr.read_rx_from_isr(); std::uint8_t const second = uart_isr.read_rx_from_isr(); assert( queue.send_from_isr( first, context ) == freertos::IsrSendResult::queued ); assert( queue.send_from_isr( second, context ) == freertos::IsrSendResult::dropped_newest ); assert( !uart_isr.rx_ready_from_isr() ); assert( gpio_isr.edge_pending_from_isr( 1U ) ); gpio_isr.clear_edge_from_isr( 1U ); freertos::TaskNotificationRef notification{ reinterpret_cast< void * >( 1U ) }; assert( notification.give_from_isr( context ) ); assert( context.wake_requested() && context.yield_calls() == 0U ); assert( context.yield_if_needed() && context.yield_calls() == 1U ); assert( fake_yield_calls == 1U && fake_last_yield == pdTRUE ); std::uint8_t received = 0U; assert( queue.receive( received, 0U ) && received == 0x41U ); gpio.task_view().write_output( 1U, true ); assert( gpio_registers.direction == 1U && gpio_registers.data == 1U ); assert( gpio_registers.edge_status == 0U ); }