Files

90 lines
3.3 KiB
C++

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