1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
|
#include "uart.h"
#include "ring_buffer.h"
#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 || 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 UARTRead(UART* uart, void *buf, size_t nbytes)
{
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 UARTReadDirect(UART* uart, void *buf, size_t nbytes)
{
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;
}
void UARTHandleInterrupt(UART* uart)
{
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;
}
}
}
}
|