summaryrefslogtreecommitdiff
path: root/app/platform/stm32f0-gcc/uart.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'app/platform/stm32f0-gcc/uart.cpp')
-rw-r--r--app/platform/stm32f0-gcc/uart.cpp121
1 files changed, 101 insertions, 20 deletions
diff --git a/app/platform/stm32f0-gcc/uart.cpp b/app/platform/stm32f0-gcc/uart.cpp
index 0fa6527..4d9bf5f 100644
--- a/app/platform/stm32f0-gcc/uart.cpp
+++ b/app/platform/stm32f0-gcc/uart.cpp
@@ -1,33 +1,114 @@
#include "uart.h"
+#include "ring_buffer.h"
-size_t UARTWrite(USART_TypeDef* uart, const void *data, size_t nbytes)
+#if defined(__GNUC__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wold-style-cast"
+#endif
+
+struct UART
+{
+ USART_TypeDef* usart;
+ RingBuffer<uint8_t> rx_buffer;
+ RingBuffer<uint8_t> tx_buffer;
+};
+
+static constexpr size_t kUART1RxBufferSize = 100;
+static constexpr size_t kUART1TxBufferSize = 256;
+static constexpr size_t kUART3RxBufferSize = 256;
+static constexpr size_t kUART3TxBufferSize = 256;
+static constexpr size_t kUART4RxBufferSize = 100;
+static constexpr size_t kUART4TxBufferSize = 100;
+static uint8_t g_uart1_rx_buffer[kUART1RxBufferSize]{};
+static uint8_t g_uart1_tx_buffer[kUART1TxBufferSize]{};
+static uint8_t g_uart3_rx_buffer[kUART3RxBufferSize]{};
+static uint8_t g_uart3_tx_buffer[kUART3TxBufferSize]{};
+static uint8_t g_uart4_rx_buffer[kUART4RxBufferSize]{};
+static uint8_t g_uart4_tx_buffer[kUART4TxBufferSize]{};
+
+UART g_uart1{
+ USART1,
+ RingBuffer<uint8_t>(g_uart1_rx_buffer, kUART1RxBufferSize),
+ RingBuffer<uint8_t>(g_uart1_tx_buffer, kUART1TxBufferSize),
+};
+UART g_uart3{
+ USART3,
+ RingBuffer<uint8_t>(g_uart3_rx_buffer, kUART3RxBufferSize),
+ RingBuffer<uint8_t>(g_uart3_tx_buffer, kUART3TxBufferSize),
+};
+UART g_uart4{
+ USART4,
+ RingBuffer<uint8_t>(g_uart4_rx_buffer, kUART4RxBufferSize),
+ RingBuffer<uint8_t>(g_uart4_tx_buffer, kUART4TxBufferSize),
+};
+
+static constexpr Min(size_t a, size_t b) { return (a >= b) ? a : b; }
+
+size_t UARTWrite(UART* uart, const void *buf, size_t nbytes)
+{
+ if (uart == nullptr || buf == nullptr) return 0;
+ const size_t size = Min(nbytes, uart->tx_buffer.Free());
+ if (size == 0) return 0;
+ uart->tx_buffer.Push(reinterpret_cast<const uint8_t*>(buf), size);
+ uart->usart->CR1 |= USART_CR1_TXEIE;
+ return size;
+}
+
+size_t UARTWriteDirect(UART* uart, const void *buf, size_t nbytes)
{
- if (uart == nullptr) return 0;
- (void) data;
- (void) nbytes;
- return 0;
+ if (uart == nullptr || buf == nullptr) return 0;
+ const uint8_t *data = reinterpret_cast<const uint8_t *>(buf);
+ // TODO disable interrupts here
+ for (size_t i = 0; i < nbytes; i++) {
+ while (!(uart->usart->ISR & USART_ISR_TXE));
+ uart->usart->TDR = data[i];
+ }
+ // TODO restore (not just enable) interrupts here
+ return nbytes;
}
-size_t UARTWriteDirect(USART_TypeDef* uart, const void *data, size_t nbytes)
+size_t UARTRead(UART* uart, void *buf, size_t nbytes)
{
- if (uart == nullptr) return 0;
- (void) data;
- (void) nbytes;
- return 0;
+ if (uart == nullptr || buf == nullptr) return 0;
+ const size_t size = Min(nbytes, uart->rx_buffer.Occupied());
+ uart->rx_buffer.Pop(reinterpret_cast<uint8_t*>(buf), size);
+ return size;
}
-size_t UARTRead(USART_TypeDef* uart, void *data, size_t nbytes)
+size_t UARTReadDirect(UART* uart, void *buf, size_t nbytes)
{
- if (uart == nullptr) return 0;
- (void) data;
- (void) nbytes;
- return 0;
+ if (uart == nullptr || buf == nullptr) return 0;
+ uint8_t *data = reinterpret_cast<uint8_t *>(buf);
+ // TODO disable interrupts here
+ for (size_t i = 0; i < nbytes; i++) {
+ while (!(uart->usart->ISR & USART_ISR_RXNE));
+ data[i] = uart->usart->RDR;
+ }
+ // TODO restore (not just enable) interrupts here
+ return nbytes;
}
-size_t UARTReadDirect(USART_TypeDef* uart, void *data, size_t nbytes)
+void UARTHandleInterrupt(UART* uart)
{
- if (uart == nullptr) return 0;
- (void) data;
- (void) nbytes;
- return 0;
+ volatile USART_TypeDef* usart_regs = uart->usart;
+ const uint32_t cr1 = usart_regs->CR1;
+ if ((cr1 & USART_CR1_UE) == 0)
+ return;
+ for (int _ = 0; _ < 256; _++) {
+ const uint32_t isr = usart_regs->ISR;
+ const bool rxne = isr & USART_ISR_RXNE;
+ const bool txe = isr & USART_ISR_TXE;
+ if (!rxne && !txe)
+ break;
+ if (rxne) {
+ uart->rx_buffer.Push(usart_regs->RDR);
+ }
+ if (txe) {
+ if (!uart->tx_buffer.IsEmpty()) {
+ usart_regs->TDR = uart->tx_buffer.Pop();
+ } else {
+ usart_regs->CR1 &= ~USART_CR1_TXEIE;
+ }
+ }
+ }
}