#include "uart2.h" #include "gpio.h" #include "lock.h" #include "pol0.h" #include "ring_buffer.h" #include "xuartlite.h" namespace { constexpr uintptr_t kUart0BaseAddress = UART0_BASE; XUartLite uart0_inst; XUartLite_Config uart0_config = { .DeviceId = 0, .RegBaseAddr = kUart0BaseAddress, .BaudRate = 115200, .UseParity = false, .DataBits = 8, }; constexpr size_t kUartRxBufferSize = 256; std::array rx_buffer = {}; RingBuffer rx_ring_buffer{.buffer = rx_buffer}; constexpr size_t kUartTxBufferSize = 256; std::array tx_buffer = {}; RingBuffer tx_ring_buffer{.buffer = tx_buffer}; XUartLite* uart0 = &uart0_inst; volatile int sending = 0; void StartReceiving() { while (1) { if (rx_ring_buffer.FreeSpace() < 1) { // woops, full. discard some data // TODO: keep track of overrun stats rx_ring_buffer.Pop(1); } if (XUartLite_Recv(uart0, rx_ring_buffer.RawWritePointer(), 1) < 1) { break; } rx_ring_buffer.Push(1); } } void StartSending() { if (tx_ring_buffer.AvailableData() > 0 && sending < 1) { sending += 1; XUartLite_Send(uart0, tx_ring_buffer.RawReadPointer(), 1); } } std::byte UartReadByte() { std::byte c; while (!rx_ring_buffer.Load(std::span{&c, 1})) { } return c; } void UartWriteByte(std::byte c) { while (!tx_ring_buffer.Store(std::span{&c, 1})) { } { InterruptLock lock; StartSending(); } } } // namespace void InitUarts() { XUartLite_CfgInitialize(uart0, &uart0_config, uart0_config.RegBaseAddr); XUartLite_SetSendHandler(uart0, HandleUartTxFromIsr, nullptr); XUartLite_SetRecvHandler(uart0, HandleUartRxFromIsr, nullptr); StartReceiving(); XUartLite_EnableInterrupt(uart0); } void UartWriteCrash(std::span data) { XUartLite_DisableInterrupt(uart0); while (data.size() > 0) { while (XUartLite_IsSending(uart0)) { } auto* dat = reinterpret_cast(const_cast(data.data())); uint8_t sent = XUartLite_Send(uart0, dat, data.size()); data = data.subspan(sent); } while (XUartLite_IsSending(uart0)) { } XUartLite_EnableInterrupt(uart0); } void UartEcho() { while (1) { gpio0->data = tx_ring_buffer.AvailableData(); std::byte c = UartReadByte(); UartWriteByte(c); //gpio0->data = uart0->Stats.ReceiveOverrunErrors; } } void HandleUartTxFromIsr(void*, unsigned int transmitted) { sending -= 1; tx_ring_buffer.Pop(transmitted); StartSending(); } void HandleUartRxFromIsr(void*, unsigned int transmitted) { rx_ring_buffer.Push(transmitted); StartReceiving(); } void HandleUartIsr() { XUartLite_InterruptHandler(uart0); }