90 lines
3.3 KiB
C++
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 );
|
|
}
|