libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
stm32_uart.hpp
1#pragma once
2
3#include "main.h"
4
5#ifdef HAL_UART_MODULE_ENABLED
6
7#ifdef UART
8#undef UART
9#endif
10
11#include "double_buffer.hpp"
12#include "libxr_def.hpp"
13#include "libxr_rw.hpp"
14#include "uart.hpp"
15
16typedef enum
17{
18#ifdef USART1
19 STM32_USART1,
20#endif
21#ifdef USART2
22 STM32_USART2,
23#endif
24#ifdef USART3
25 STM32_USART3,
26#endif
27#ifdef USART4
28 STM32_USART4,
29#endif
30#ifdef USART5
31 STM32_USART5,
32#endif
33#ifdef USART6
34 STM32_USART6,
35#endif
36#ifdef USART7
37 STM32_USART7,
38#endif
39#ifdef USART8
40 STM32_USART8,
41#endif
42#ifdef USART9
43 STM32_USART9,
44#endif
45#ifdef USART10
46 STM32_USART10,
47#endif
48#ifdef USART11
49 STM32_USART11,
50#endif
51#ifdef USART12
52 STM32_USART12,
53#endif
54#ifdef USART13
55 STM32_USART13,
56#endif
57#ifdef UART1
58 STM32_UART1,
59#endif
60#ifdef UART2
61 STM32_UART2,
62#endif
63#ifdef UART3
64 STM32_UART3,
65#endif
66#ifdef UART4
67 STM32_UART4,
68#endif
69#ifdef UART5
70 STM32_UART5,
71#endif
72#ifdef UART6
73 STM32_UART6,
74#endif
75#ifdef UART7
76 STM32_UART7,
77#endif
78#ifdef UART8
79 STM32_UART8,
80#endif
81#ifdef UART9
82 STM32_UART9,
83#endif
84#ifdef UART10
85 STM32_UART10,
86#endif
87#ifdef UART11
88 STM32_UART11,
89#endif
90#ifdef UART12
91 STM32_UART12,
92#endif
93#ifdef UART13
94 STM32_UART13,
95#endif
96#ifdef LPUART1
97 STM32_LPUART1,
98#endif
99#ifdef LPUART2
100 STM32_LPUART2,
101#endif
102#ifdef LPUART3
103 STM32_LPUART3,
104#endif
105 STM32_UART_NUMBER,
106 STM32_UART_ID_ERROR
107} stm32_uart_id_t;
108
109stm32_uart_id_t STM32_UART_GetID(USART_TypeDef *addr);
110
111namespace LibXR
112{
113class STM32UART : public UART
114{
115 public:
116 static ErrorCode WriteFun(WritePort &port)
117 {
118 STM32UART *uart = CONTAINER_OF(&port, STM32UART, _write_port);
119 if (!uart->dma_buff_tx_.HasPending())
120 {
121 WriteInfoBlock info;
122 if (port.queue_info_->Peek(info) != ErrorCode::OK)
123 {
124 return ErrorCode::EMPTY;
125 }
126
127 uint8_t *buffer = nullptr;
128 bool use_pending = false;
129
130 if (uart->uart_handle_->gState == HAL_UART_STATE_READY)
131 {
132 buffer = reinterpret_cast<uint8_t *>(uart->dma_buff_tx_.ActiveBuffer());
133 }
134 else
135 {
136 buffer = reinterpret_cast<uint8_t *>(uart->dma_buff_tx_.PendingBuffer());
137 use_pending = true;
138 }
139
140 if (port.queue_data_->PopBatch(reinterpret_cast<uint8_t *>(buffer),
141 info.data.size_) != ErrorCode::OK)
142 {
143 ASSERT(false);
144 return ErrorCode::EMPTY;
145 }
146
147 if (use_pending)
148 {
149 uart->dma_buff_tx_.EnablePending();
150 if (uart->uart_handle_->gState == HAL_UART_STATE_READY)
151 {
152 uart->dma_buff_tx_.Switch();
153 }
154 else
155 {
156 return ErrorCode::FAILED;
157 }
158 }
159
160 port.queue_info_->Pop(uart->write_info_active_);
161
162#if __DCACHE_PRESENT
163 SCB_CleanDCache_by_Addr(reinterpret_cast<uint32_t *>(uart->dma_buff_tx_.ActiveBuffer()),
164 info.data.size_);
165#endif
166
167 auto ans = HAL_UART_Transmit_DMA(
168 uart->uart_handle_, static_cast<uint8_t *>(uart->dma_buff_tx_.ActiveBuffer()),
169 info.data.size_);
170
171 if (ans != HAL_OK)
172 {
173 port.Finish(false, ErrorCode::FAILED, info, 0);
174 }
175
176 return ErrorCode::FAILED;
177 }
178
179 return ErrorCode::FAILED;
180 }
181
182 static ErrorCode ReadFun(ReadPort &port)
183 {
184 STM32UART *uart = CONTAINER_OF(&port, STM32UART, _read_port);
185 UNUSED(uart);
186
187 return ErrorCode::EMPTY;
188 }
189
190 STM32UART(UART_HandleTypeDef *uart_handle, RawData dma_buff_rx, RawData dma_buff_tx,
191 uint32_t tx_queue_size = 5)
192 : UART(&_read_port, &_write_port),
193 _read_port(dma_buff_rx.size_),
194 _write_port(tx_queue_size, dma_buff_tx.size_ / 2),
195 dma_buff_rx_(dma_buff_rx),
196 dma_buff_tx_(dma_buff_tx),
197 uart_handle_(uart_handle),
198 id_(STM32_UART_GetID(uart_handle_->Instance))
199 {
200 ASSERT(id_ != STM32_UART_ID_ERROR);
201
202 map[id_] = this;
203
204 if ((uart_handle->Init.Mode & UART_MODE_TX) == UART_MODE_TX)
205 {
206 ASSERT(uart_handle_->hdmatx != NULL);
207 _write_port = WriteFun;
208 }
209
210 if ((uart_handle->Init.Mode & UART_MODE_RX) == UART_MODE_RX)
211 {
212 ASSERT(uart_handle->hdmarx != NULL);
213
214 uart_handle_->hdmarx->Init.Mode = DMA_CIRCULAR;
215 HAL_DMA_Init(uart_handle_->hdmarx);
216
217 __HAL_UART_ENABLE_IT(uart_handle, UART_IT_IDLE);
218
219 HAL_UART_Receive_DMA(uart_handle, reinterpret_cast<uint8_t *>(dma_buff_rx_.addr_),
220 dma_buff_rx_.size_);
221 _read_port = ReadFun;
222 }
223 }
224
226 {
227 uart_handle_->Init.BaudRate = config.baudrate;
228
229 switch (config.parity)
230 {
232 uart_handle_->Init.Parity = UART_PARITY_NONE;
233 uart_handle_->Init.WordLength = UART_WORDLENGTH_8B;
234 break;
236 uart_handle_->Init.Parity = UART_PARITY_EVEN;
237 uart_handle_->Init.WordLength = UART_WORDLENGTH_9B;
238 break;
240 uart_handle_->Init.Parity = UART_PARITY_ODD;
241 uart_handle_->Init.WordLength = UART_WORDLENGTH_9B;
242 break;
243 default:
244 ASSERT(false);
245 }
246
247 switch (config.stop_bits)
248 {
249 case 1:
250 uart_handle_->Init.StopBits = UART_STOPBITS_1;
251 break;
252 case 2:
253 uart_handle_->Init.StopBits = UART_STOPBITS_2;
254 break;
255 default:
256 ASSERT(false);
257 }
258
259 if (HAL_UART_Init(uart_handle_) != HAL_OK)
260 {
261 return ErrorCode::INIT_ERR;
262 }
263 return ErrorCode::OK;
264 }
265
266 ReadPort _read_port;
267 WritePort _write_port;
268
269 RawData dma_buff_rx_;
270 DoubleBuffer dma_buff_tx_;
271 WriteInfoBlock write_info_active_;
272
273 size_t last_rx_pos_ = 0;
274
275 UART_HandleTypeDef *uart_handle_;
276
277 stm32_uart_id_t id_ = STM32_UART_ID_ERROR;
278
279 static STM32UART *map[STM32_UART_NUMBER]; // NOLINT
280};
281
282} // namespace LibXR
283
284#endif
size_t size_
数据大小(字节)。 The size of the data (in bytes).
双缓冲区管理类 / Double buffer manager class
bool HasPending() const
判断是否有待切换的缓冲区 Checks whether a pending buffer is ready
uint8_t * ActiveBuffer()
获取当前正在使用的缓冲区指针 Returns the currently active buffer
void Switch()
切换到备用缓冲区(若其有效) Switches to the pending buffer if it's valid
uint8_t * PendingBuffer()
获取备用缓冲区的指针 Returns the pending (inactive) buffer
void EnablePending()
手动启用 pending 状态 Manually sets the pending state to true
ErrorCode PopBatch(Data *data, size_t size)
批量弹出数据 / Pops multiple elements from the queue
原始数据封装类。 A class for encapsulating raw data.
size_t size_
数据大小(字节)。 The size of the data (in bytes).
void * addr_
数据存储地址。 The storage address of the data.
ReadPort class for handling read operations.
Definition libxr_rw.hpp:270
ErrorCode SetConfig(UART::Configuration config)
设置 UART 配置 / Sets the UART configuration
通用异步收发传输(UART)基类 / Abstract base class for Universal Asynchronous Receiver-Transmitter (UART)
Definition uart.hpp:19
@ NO_PARITY
无校验 / No parity
@ ODD
奇校验 / Odd parity
@ EVEN
偶校验 / Even parity
UART(ReadPortType *read_port, WritePortType *write_port)
UART 构造函数 / UART constructor.
Definition uart.hpp:64
WritePort class for handling write operations.
Definition libxr_rw.hpp:564
void Finish(bool in_isr, ErrorCode ans, WriteInfoBlock &info, uint32_t size)
更新写入操作的状态。 Updates the status of the write operation.
Definition libxr_rw.hpp:665
LibXR 命名空间
Definition ch32_gpio.hpp:9
ErrorCode(* ReadFun)(ReadPort &port)
Function pointer type for read operations.
Definition libxr_rw.hpp:247
ErrorCode(* WriteFun)(WritePort &port)
Function pointer type for write operations.
Definition libxr_rw.hpp:243
UART 配置结构体 / UART configuration structure.
Definition uart.hpp:44
uint8_t stop_bits
停止位长度 / Number of stop bits
Definition uart.hpp:48
Parity parity
校验模式 / Parity mode
Definition uart.hpp:46
uint32_t baudrate
波特率 / Baud rate
Definition uart.hpp:45