arm: async uart writes & fixes
This commit is contained in:
54
arm/uart.cc
54
arm/uart.cc
@@ -1,10 +1,13 @@
|
||||
#include "uart.h"
|
||||
|
||||
#include "async.h"
|
||||
#include "gpio.h"
|
||||
#include "ring_buffer.h"
|
||||
#include "trace.h"
|
||||
#include "xuartlite.h"
|
||||
|
||||
namespace {
|
||||
using async::AwaitableType;
|
||||
|
||||
constexpr uintptr_t kUart0BaseAddress = 0x40001000;
|
||||
XUartLite uart0_inst;
|
||||
@@ -20,18 +23,22 @@ constexpr size_t kUartTxBufferSize = 256;
|
||||
std::array<std::byte, kUartTxBufferSize> tx_buffer = {};
|
||||
RingBuffer tx_ring_buffer{.buffer = tx_buffer};
|
||||
|
||||
} // namespace
|
||||
|
||||
XUartLite* uart0 = &uart0_inst;
|
||||
} // namespace
|
||||
|
||||
void InitUarts() {
|
||||
XUartLite_CfgInitialize(uart0, &uart0_config, uart0_config.RegBaseAddr);
|
||||
|
||||
XUartLite_SetSendHandler(uart0, HandleUartTxFromIsr, nullptr);
|
||||
XUartLite_SetRecvHandler(uart0, HandleUartRxFromIsr, nullptr);
|
||||
XUartLite_EnableInterrupt(uart0);
|
||||
}
|
||||
|
||||
// xuartlite private header stuff
|
||||
extern "C" uint8_t XUartLite_GetSR(XUartLite* InstancePtr);
|
||||
#define XUL_SR_TX_FIFO_EMPTY 0x04 /* transmit FIFO empty */
|
||||
|
||||
void UartSendCrash(std::span<const std::byte> data) {
|
||||
void UartWriteCrash(std::span<const std::byte> data) {
|
||||
while (data.size() > 0) {
|
||||
while ((XUartLite_GetSR(uart0) & XUL_SR_TX_FIFO_EMPTY) == 0) {
|
||||
}
|
||||
@@ -44,8 +51,27 @@ void UartSendCrash(std::span<const std::byte> data) {
|
||||
}
|
||||
}
|
||||
|
||||
// blocking
|
||||
void UartSend(std::span<const std::byte> data) {
|
||||
async::task<> UartWrite(std::span<const std::byte> data) {
|
||||
while (!tx_ring_buffer.Store(data)) {
|
||||
co_await async::await(AwaitableType::kUartTx);
|
||||
}
|
||||
|
||||
if (!XUartLite_IsSending(uart0)) {
|
||||
XUartLite_Send(uart0, tx_ring_buffer.RawReadPointer(),
|
||||
tx_ring_buffer.ContiguousAvailableData());
|
||||
}
|
||||
}
|
||||
|
||||
void UartReadBlocking(std::span<std::byte> data) {
|
||||
size_t bytes_received = 0;
|
||||
while (bytes_received < data.size()) {
|
||||
auto* buffer = reinterpret_cast<uint8_t*>(data.data() + bytes_received);
|
||||
bytes_received +=
|
||||
XUartLite_Recv(uart0, buffer, data.size() - bytes_received);
|
||||
}
|
||||
}
|
||||
|
||||
void UartWriteBlocking(std::span<const std::byte> data) {
|
||||
while (!tx_ring_buffer.Store(data)) {
|
||||
}
|
||||
|
||||
@@ -55,6 +81,16 @@ void UartSend(std::span<const std::byte> data) {
|
||||
}
|
||||
}
|
||||
|
||||
async::task<buffer> UartRead(int size) {
|
||||
auto buff = buffer::make(size);
|
||||
auto* data = reinterpret_cast<uint8_t*>(buff.data.data());
|
||||
size_t received = XUartLite_Recv(uart0, data, buff.data.size());
|
||||
if (received < buff.data.size()) {
|
||||
co_await async::await(AwaitableType::kUartRx);
|
||||
}
|
||||
co_return buff;
|
||||
}
|
||||
|
||||
void HandleUartTxFromIsr(void*, unsigned int transmitted) {
|
||||
tracing::trace(tracing::TraceEvent::kUartTxCb);
|
||||
tx_ring_buffer.Pop(transmitted);
|
||||
@@ -62,4 +98,12 @@ void HandleUartTxFromIsr(void*, unsigned int transmitted) {
|
||||
XUartLite_Send(uart0, tx_ring_buffer.RawReadPointer(),
|
||||
tx_ring_buffer.ContiguousAvailableData());
|
||||
}
|
||||
async::resume(AwaitableType::kUartTx);
|
||||
}
|
||||
|
||||
void HandleUartRxFromIsr(void*, unsigned int) {
|
||||
tracing::trace(tracing::TraceEvent::kUartRxCb);
|
||||
async::resume(AwaitableType::kUartRx);
|
||||
}
|
||||
|
||||
void HandleUartIsr() { XUartLite_InterruptHandler(uart0); }
|
||||
|
Reference in New Issue
Block a user