libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
stm32_uart.cpp
1#include "stm32_uart.hpp"
2
3#ifdef HAL_UART_MODULE_ENABLED
4
5using namespace LibXR;
6
7STM32UART *STM32UART::map[STM32_UART_NUMBER] = {nullptr};
8
9stm32_uart_id_t STM32_UART_GetID(USART_TypeDef *addr)
10{
11 if (addr == nullptr)
12 { // NOLINT
13 return stm32_uart_id_t::STM32_UART_ID_ERROR;
14 }
15#ifdef USART1
16 else if (addr == USART1)
17 { // NOLINT
18 return stm32_uart_id_t::STM32_USART1;
19 }
20#endif
21#ifdef USART2
22 else if (addr == USART2)
23 { // NOLINT
24 return stm32_uart_id_t::STM32_USART2;
25 }
26#endif
27#ifdef USART3
28 else if (addr == USART3)
29 { // NOLINT
30 return stm32_uart_id_t::STM32_USART3;
31 }
32#endif
33#ifdef USART4
34 else if (addr == USART4)
35 { // NOLINT
36 return stm32_uart_id_t::STM32_USART4;
37 }
38#endif
39#ifdef USART5
40 else if (addr == USART5)
41 { // NOLINT
42 return stm32_uart_id_t::STM32_USART5;
43 }
44#endif
45#ifdef USART6
46 else if (addr == USART6)
47 { // NOLINT
48 return stm32_uart_id_t::STM32_USART6;
49 }
50#endif
51#ifdef USART7
52 else if (addr == USART7)
53 { // NOLINT
54 return stm32_uart_id_t::STM32_USART7;
55 }
56#endif
57#ifdef USART8
58 else if (addr == USART8)
59 { // NOLINT
60 return stm32_uart_id_t::STM32_USART8;
61 }
62#endif
63#ifdef USART9
64 else if (addr == USART9)
65 { // NOLINT
66 return stm32_uart_id_t::STM32_USART9;
67 }
68#endif
69#ifdef USART10
70 else if (addr == USART10)
71 { // NOLINT
72 return stm32_uart_id_t::STM32_USART10;
73 }
74#endif
75#ifdef USART11
76 else if (addr == USART11)
77 { // NOLINT
78 return stm32_uart_id_t::STM32_USART11;
79 }
80#endif
81#ifdef USART12
82 else if (addr == USART12)
83 { // NOLINT
84 return stm32_uart_id_t::STM32_USART12;
85 }
86#endif
87#ifdef USART13
88 else if (addr == USART13)
89 { // NOLINT
90 return stm32_uart_id_t::STM32_USART13;
91 }
92#endif
93#ifdef UART1
94 else if (addr == UART1)
95 { // NOLINT
96 return stm32_uart_id_t::STM32_UART1;
97 }
98#endif
99#ifdef UART2
100 else if (addr == UART2)
101 { // NOLINT
102 return stm32_uart_id_t::STM32_UART2;
103 }
104#endif
105#ifdef UART3
106 else if (addr == UART3)
107 { // NOLINT
108 return stm32_uart_id_t::STM32_UART3;
109 }
110#endif
111#ifdef UART4
112 else if (addr == UART4)
113 { // NOLINT
114 return stm32_uart_id_t::STM32_UART4;
115 }
116#endif
117#ifdef UART5
118 else if (addr == UART5)
119 { // NOLINT
120 return stm32_uart_id_t::STM32_UART5;
121 }
122#endif
123#ifdef UART6
124 else if (addr == UART6)
125 { // NOLINT
126 return stm32_uart_id_t::STM32_UART6;
127 }
128#endif
129#ifdef UART7
130 else if (addr == UART7)
131 { // NOLINT
132 return stm32_uart_id_t::STM32_UART7;
133 }
134#endif
135#ifdef UART8
136 else if (addr == UART8)
137 { // NOLINT
138 return stm32_uart_id_t::STM32_UART8;
139 }
140#endif
141#ifdef UART9
142 else if (addr == UART9)
143 { // NOLINT
144 return stm32_uart_id_t::STM32_UART9;
145 }
146#endif
147#ifdef UART10
148 else if (addr == UART10)
149 { // NOLINT
150 return stm32_uart_id_t::STM32_UART10;
151 }
152#endif
153#ifdef UART11
154 else if (addr == UART11)
155 { // NOLINT
156 return stm32_uart_id_t::STM32_UART11;
157 }
158#endif
159#ifdef UART12
160 else if (addr == UART12)
161 { // NOLINT
162 return stm32_uart_id_t::STM32_UART12;
163 }
164#endif
165#ifdef UART13
166 else if (addr == UART13)
167 { // NOLINT
168 return stm32_uart_id_t::STM32_UART13;
169 }
170#endif
171#ifdef LPUART1
172 else if (addr == LPUART1)
173 { // NOLINT
174 return stm32_uart_id_t::STM32_LPUART1;
175 }
176#endif
177#ifdef LPUART2
178 else if (addr == LPUART2)
179 { // NOLINT
180 return stm32_uart_id_t::STM32_LPUART2;
181 }
182#endif
183#ifdef LPUART3
184 else if (addr == LPUART3)
185 { // NOLINT
186 return stm32_uart_id_t::STM32_LPUART3;
187 }
188#endif
189 else
190 {
191 return stm32_uart_id_t::STM32_UART_ID_ERROR;
192 }
193}
194
195ErrorCode STM32UART::WriteFun(WritePort &port)
196{
197 STM32UART *uart = CONTAINER_OF(&port, STM32UART, _write_port);
198
199 if (!uart->dma_buff_tx_.HasPending())
200 {
201 WriteInfoBlock info;
202 if (port.queue_info_->Peek(info) != ErrorCode::OK)
203 {
204 return ErrorCode::EMPTY;
205 }
206
207 uint8_t *buffer = nullptr;
208 bool use_pending = false;
209
210 if (uart->uart_handle_->gState == HAL_UART_STATE_READY)
211 {
212 buffer = reinterpret_cast<uint8_t *>(uart->dma_buff_tx_.ActiveBuffer());
213 }
214 else
215 {
216 buffer = reinterpret_cast<uint8_t *>(uart->dma_buff_tx_.PendingBuffer());
217 use_pending = true;
218 }
219
220 if (port.queue_data_->PopBatch(reinterpret_cast<uint8_t *>(buffer),
221 info.data.size_) != ErrorCode::OK)
222 {
223 ASSERT(false);
224 return ErrorCode::EMPTY;
225 }
226
227 if (use_pending)
228 {
229 uart->dma_buff_tx_.SetPendingLength(info.data.size_);
230 uart->dma_buff_tx_.EnablePending();
231 if (uart->uart_handle_->gState == HAL_UART_STATE_READY &&
232 uart->dma_buff_tx_.HasPending())
233 {
234 uart->dma_buff_tx_.Switch();
235 }
236 else
237 {
238 return ErrorCode::FAILED;
239 }
240 }
241
242 port.queue_info_->Pop(uart->write_info_active_);
243
244#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
245 SCB_CleanDCache_by_Addr(
246 reinterpret_cast<uint32_t *>(uart->dma_buff_tx_.ActiveBuffer()), info.data.size_);
247#endif
248
249 auto ans = HAL_UART_Transmit_DMA(
250 uart->uart_handle_, static_cast<uint8_t *>(uart->dma_buff_tx_.ActiveBuffer()),
251 info.data.size_);
252
253 if (ans != HAL_OK)
254 {
255 port.Finish(false, ErrorCode::FAILED, info, 0);
256 return ErrorCode::FAILED;
257 }
258 else
259 {
260 return ErrorCode::OK;
261 }
262 }
263
264 return ErrorCode::FAILED;
265}
266
267ErrorCode STM32UART::ReadFun(ReadPort &port)
268{
269 STM32UART *uart = CONTAINER_OF(&port, STM32UART, _read_port);
270 UNUSED(uart);
271
272 return ErrorCode::EMPTY;
273}
274
275STM32UART::STM32UART(UART_HandleTypeDef *uart_handle, RawData dma_buff_rx,
276 RawData dma_buff_tx, uint32_t tx_queue_size)
277 : UART(&_read_port, &_write_port),
278 _read_port(dma_buff_rx.size_),
279 _write_port(tx_queue_size, dma_buff_tx.size_ / 2),
280 dma_buff_rx_(dma_buff_rx),
281 dma_buff_tx_(dma_buff_tx),
282 uart_handle_(uart_handle),
283 id_(STM32_UART_GetID(uart_handle_->Instance))
284{
285 ASSERT(id_ != STM32_UART_ID_ERROR);
286
287 map[id_] = this;
288
289 if ((uart_handle->Init.Mode & UART_MODE_TX) == UART_MODE_TX)
290 {
291 ASSERT(uart_handle_->hdmatx != NULL);
292 _write_port = WriteFun;
293 }
294
295 if ((uart_handle->Init.Mode & UART_MODE_RX) == UART_MODE_RX)
296 {
297 ASSERT(uart_handle->hdmarx != NULL);
298
299 uart_handle_->hdmarx->Init.Mode = DMA_CIRCULAR;
300 HAL_DMA_Init(uart_handle_->hdmarx);
301
302 __HAL_UART_ENABLE_IT(uart_handle, UART_IT_IDLE);
303
304 HAL_UART_Receive_DMA(uart_handle, reinterpret_cast<uint8_t *>(dma_buff_rx_.addr_),
305 dma_buff_rx_.size_);
306 _read_port = ReadFun;
307 }
308}
309
311{
312 uart_handle_->Init.BaudRate = config.baudrate;
313
314 switch (config.parity)
315 {
317 uart_handle_->Init.Parity = UART_PARITY_NONE;
318 uart_handle_->Init.WordLength = UART_WORDLENGTH_8B;
319 break;
321 uart_handle_->Init.Parity = UART_PARITY_EVEN;
322 uart_handle_->Init.WordLength = UART_WORDLENGTH_9B;
323 break;
325 uart_handle_->Init.Parity = UART_PARITY_ODD;
326 uart_handle_->Init.WordLength = UART_WORDLENGTH_9B;
327 break;
328 default:
329 ASSERT(false);
330 }
331
332 switch (config.stop_bits)
333 {
334 case 1:
335 uart_handle_->Init.StopBits = UART_STOPBITS_1;
336 break;
337 case 2:
338 uart_handle_->Init.StopBits = UART_STOPBITS_2;
339 break;
340 default:
341 ASSERT(false);
342 }
343
344 if (HAL_UART_Init(uart_handle_) != HAL_OK)
345 {
346 return ErrorCode::INIT_ERR;
347 }
348 return ErrorCode::OK;
349}
350
351static void STM32_UART_RX_ISR_Handler(UART_HandleTypeDef *uart_handle)
352{
353 auto uart = STM32UART::map[STM32_UART_GetID(uart_handle->Instance)];
354 auto rx_buf = static_cast<uint8_t *>(uart->dma_buff_rx_.addr_);
355 size_t dma_size = uart->dma_buff_rx_.size_;
356
357 size_t curr_pos =
358 dma_size - __HAL_DMA_GET_COUNTER(uart_handle->hdmarx); // 当前 DMA 写入位置
359 size_t last_pos = uart->last_rx_pos_;
360
361#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
362 SCB_InvalidateDCache_by_Addr(rx_buf, dma_size);
363#endif
364
365 if (curr_pos != last_pos)
366 {
367 if (curr_pos > last_pos)
368 {
369 // 线性接收区
370 uart->read_port_->queue_data_->PushBatch(&rx_buf[last_pos], curr_pos - last_pos);
371 }
372 else
373 {
374 // 回卷区:last→end,再从0→curr
375 uart->read_port_->queue_data_->PushBatch(&rx_buf[last_pos], dma_size - last_pos);
376 uart->read_port_->queue_data_->PushBatch(&rx_buf[0], curr_pos);
377 }
378
379 uart->last_rx_pos_ = curr_pos;
380 uart->read_port_->ProcessPendingReads(true);
381 }
382}
383
384void STM32_UART_ISR_Handler_TX_CPLT(stm32_uart_id_t id)
385{ // NOLINT
386 auto uart = STM32UART::map[id];
387
388 size_t pending_len = uart->dma_buff_tx_.GetPendingLength();
389
390 if (pending_len == 0)
391 {
392 return;
393 }
394
395 uart->dma_buff_tx_.Switch();
396
397#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
398 SCB_CleanDCache_by_Addr(reinterpret_cast<uint32_t *>(uart->dma_buff_tx_.ActiveBuffer()),
399 pending_len);
400#endif
401
402 auto ans = HAL_UART_Transmit_DMA(
403 uart->uart_handle_, static_cast<uint8_t *>(uart->dma_buff_tx_.ActiveBuffer()),
404 pending_len);
405
406 ASSERT(ans == HAL_OK);
407
408 WriteInfoBlock &current_info = uart->write_info_active_;
409
410 if (uart->write_port_->queue_info_->Pop(current_info) != ErrorCode::OK)
411 {
412 ASSERT(false);
413 return;
414 }
415
416 uart->write_port_->Finish(true, ans == HAL_OK ? ErrorCode::OK : ErrorCode::BUSY,
417 current_info, current_info.data.size_);
418
419 WriteInfoBlock next_info;
420
421 if (uart->write_port_->queue_info_->Peek(next_info) != ErrorCode::OK)
422 {
423 return;
424 }
425
426 if (uart->write_port_->queue_data_->PopBatch(
427 reinterpret_cast<uint8_t *>(uart->dma_buff_tx_.PendingBuffer()),
428 next_info.data.size_) != ErrorCode::OK)
429 {
430 ASSERT(false);
431 return;
432 }
433
434 uart->dma_buff_tx_.SetPendingLength(next_info.data.size_);
435
436 uart->dma_buff_tx_.EnablePending();
437}
438
439// NOLINTNEXTLINE
440extern "C" void STM32_UART_ISR_Handler_IDLE(UART_HandleTypeDef *huart)
441{
442 if (__HAL_UART_GET_FLAG(huart, UART_FLAG_IDLE))
443 {
444 __HAL_UART_CLEAR_IDLEFLAG(huart);
445
446 STM32_UART_RX_ISR_Handler(huart);
447 }
448}
449
450extern "C" void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart)
451{
452 STM32_UART_RX_ISR_Handler(huart);
453}
454
455extern "C" void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
456{
457 STM32_UART_RX_ISR_Handler(huart);
458}
459
460extern "C" void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
461{
462 STM32_UART_ISR_Handler_TX_CPLT(STM32_UART_GetID(huart->Instance));
463}
464
465extern "C" __attribute__((used)) void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
466{
467 HAL_UART_Abort_IT(huart);
468}
469
470extern "C" void HAL_UART_AbortCpltCallback(UART_HandleTypeDef *huart)
471{
472 auto uart = STM32UART::map[STM32_UART_GetID(huart->Instance)];
473 HAL_UART_Receive_DMA(huart, huart->pRxBuffPtr, uart->dma_buff_rx_.size_);
474 uart->last_rx_pos_ = 0;
475 WriteInfoBlock info;
476 if (uart->write_port_->queue_info_->Peek(info) == ErrorCode::OK)
477 {
478 uart->write_port_->Finish(true, ErrorCode::FAILED, info, 0);
479 }
480}
481
482extern "C" void HAL_UART_AbortTransmitCpltCallback(UART_HandleTypeDef *huart)
483{
484 auto uart = STM32UART::map[STM32_UART_GetID(huart->Instance)];
485 WriteInfoBlock info;
486 if (uart->write_port_->queue_info_->Peek(info) == ErrorCode::OK)
487 {
488 uart->write_port_->Finish(true, ErrorCode::FAILED, info, 0);
489 }
490}
491
492extern "C" void HAL_UART_AbortReceiveCpltCallback(UART_HandleTypeDef *huart)
493{
494 HAL_UART_Receive_DMA(
495 huart, huart->pRxBuffPtr,
496 STM32UART::map[STM32_UART_GetID(huart->Instance)]->dma_buff_rx_.size_);
497}
498
499#endif
size_t size_
数据大小(字节)。 The size of the data (in bytes).
void SetPendingLength(size_t length)
设置备用缓冲区的数据长度 Sets the size of the pending buffer
void EnablePending()
手动启用 pending 状态 Manually sets the pending state to true
bool HasPending() const
判断是否有待切换的缓冲区 Checks whether a pending buffer is ready
uint8_t * ActiveBuffer() const
获取当前正在使用的缓冲区指针 Returns the currently active buffer
uint8_t * PendingBuffer() const
获取备用缓冲区的指针 Returns the pending (inactive) buffer
void Switch()
切换到备用缓冲区(若其有效) Switches to the pending buffer if it's valid
size_t GetPendingLength() const
获取 pending 缓冲区中准备好的数据长度 Gets the size of valid data in pending buffer
ErrorCode PushBatch(const Data *data, size_t size)
批量推入数据 / Pushes multiple elements into the queue
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:269
virtual void ProcessPendingReads(bool in_isr)
Processes pending reads.
Definition libxr_rw.cpp:126
ErrorCode SetConfig(UART::Configuration config)
设置 UART 配置 / Sets the UART configuration
通用异步收发传输(UART)基类 / Abstract base class for Universal Asynchronous Receiver-Transmitter (UART)
Definition uart.hpp:19
ReadPort * read_port_
读取端口 / Read port
Definition uart.hpp:53
@ NO_PARITY
无校验 / No parity
@ ODD
奇校验 / Odd parity
@ EVEN
偶校验 / Even parity
WritePort * write_port_
写入端口 / Write port
Definition uart.hpp:54
WritePort class for handling write operations.
Definition libxr_rw.hpp:403
void Finish(bool in_isr, ErrorCode ans, WriteInfoBlock &info, uint32_t size)
更新写入操作的状态。 Updates the status of the write operation.
Definition libxr_rw.cpp:207
LibXR 命名空间
Definition ch32_gpio.hpp:9
ErrorCode(* ReadFun)(ReadPort &port)
Function pointer type for read operations.
Definition libxr_rw.hpp:246
ErrorCode(* WriteFun)(WritePort &port)
Function pointer type for write operations.
Definition libxr_rw.hpp:242
UART 配置结构体 / UART configuration structure.
Definition uart.hpp:44
uint8_t stop_bits
停止位长度 / Number of stop bits
Definition uart.hpp:50
Parity parity
校验模式 / Parity mode
Definition uart.hpp:47
uint32_t baudrate
波特率 / Baud rate
Definition uart.hpp:45
ConstRawData data
Data buffer. 数据缓冲区。
Definition libxr_rw.hpp:260