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_get_id(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) // NOLINT
17 {
18 return stm32_uart_id_t::STM32_USART1;
19 }
20#endif
21#ifdef USART2
22 else if (addr == USART2) // NOLINT
23 {
24 return stm32_uart_id_t::STM32_USART2;
25 }
26#endif
27#ifdef USART3
28 else if (addr == USART3) // NOLINT
29 {
30 return stm32_uart_id_t::STM32_USART3;
31 }
32#endif
33#ifdef USART4
34 else if (addr == USART4) // NOLINT
35 {
36 return stm32_uart_id_t::STM32_USART4;
37 }
38#endif
39#ifdef USART5
40 else if (addr == USART5) // NOLINT
41 {
42 return stm32_uart_id_t::STM32_USART5;
43 }
44#endif
45#ifdef USART6
46 else if (addr == USART6) // NOLINT
47 {
48 return stm32_uart_id_t::STM32_USART6;
49 }
50#endif
51#ifdef USART7
52 else if (addr == USART7) // NOLINT
53 {
54 return stm32_uart_id_t::STM32_USART7;
55 }
56#endif
57#ifdef USART8
58 else if (addr == USART8) // NOLINT
59 {
60 return stm32_uart_id_t::STM32_USART8;
61 }
62#endif
63#ifdef USART9
64 else if (addr == USART9) // NOLINT
65 {
66 return stm32_uart_id_t::STM32_USART9;
67 }
68#endif
69#ifdef USART10
70 else if (addr == USART10) // NOLINT
71 {
72 return stm32_uart_id_t::STM32_USART10;
73 }
74#endif
75#ifdef USART11
76 else if (addr == USART11) // NOLINT
77 {
78 return stm32_uart_id_t::STM32_USART11;
79 }
80#endif
81#ifdef USART12
82 else if (addr == USART12) // NOLINT
83 {
84 return stm32_uart_id_t::STM32_USART12;
85 }
86#endif
87#ifdef USART13
88 else if (addr == USART13) // NOLINT
89 {
90 return stm32_uart_id_t::STM32_USART13;
91 }
92#endif
93#ifdef UART1
94 else if (addr == UART1) // NOLINT
95 {
96 return stm32_uart_id_t::STM32_UART1;
97 }
98#endif
99#ifdef UART2
100 else if (addr == UART2) // NOLINT
101 {
102 return stm32_uart_id_t::STM32_UART2;
103 }
104#endif
105#ifdef UART3
106 else if (addr == UART3) // NOLINT
107 {
108 return stm32_uart_id_t::STM32_UART3;
109 }
110#endif
111#ifdef UART4
112 else if (addr == UART4) // NOLINT
113 {
114 return stm32_uart_id_t::STM32_UART4;
115 }
116#endif
117#ifdef UART5
118 else if (addr == UART5) // NOLINT
119 {
120 return stm32_uart_id_t::STM32_UART5;
121 }
122#endif
123#ifdef UART6
124 else if (addr == UART6) // NOLINT
125 {
126 return stm32_uart_id_t::STM32_UART6;
127 }
128#endif
129#ifdef UART7
130 else if (addr == UART7) // NOLINT
131 {
132 return stm32_uart_id_t::STM32_UART7;
133 }
134#endif
135#ifdef UART8
136 else if (addr == UART8) // NOLINT
137 {
138 return stm32_uart_id_t::STM32_UART8;
139 }
140#endif
141#ifdef UART9
142 else if (addr == UART9) // NOLINT
143 {
144 return stm32_uart_id_t::STM32_UART9;
145 }
146#endif
147#ifdef UART10
148 else if (addr == UART10) // NOLINT
149 {
150 return stm32_uart_id_t::STM32_UART10;
151 }
152#endif
153#ifdef UART11
154 else if (addr == UART11) // NOLINT
155 {
156 return stm32_uart_id_t::STM32_UART11;
157 }
158#endif
159#ifdef UART12
160 else if (addr == UART12) // NOLINT
161 {
162 return stm32_uart_id_t::STM32_UART12;
163 }
164#endif
165#ifdef UART13
166 else if (addr == UART13) // NOLINT
167 {
168 return stm32_uart_id_t::STM32_UART13;
169 }
170#endif
171#ifdef LPUART1
172 else if (addr == LPUART1) // NOLINT
173 {
174 return stm32_uart_id_t::STM32_LPUART1;
175 }
176#endif
177#ifdef LPUART2
178 else if (addr == LPUART2) // NOLINT
179 {
180 return stm32_uart_id_t::STM32_LPUART2;
181 }
182#endif
183#ifdef LPUART3
184 else if (addr == LPUART3) // NOLINT
185 {
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, bool)
196{
197 STM32UART* uart = CONTAINER_OF(&port, STM32UART, _write_port);
198
199 if (uart->in_tx_isr.IsSet())
200 {
201 return ErrorCode::PENDING;
202 }
203
204 if (!uart->dma_buff_tx_.HasPending())
205 {
206 WriteInfoBlock info;
207 if (port.queue_info_->Peek(info) != ErrorCode::OK)
208 {
209 return ErrorCode::PENDING;
210 }
211
212 uint8_t* buffer = nullptr;
213 bool use_pending = false;
214
215 if (uart->uart_handle_->gState == HAL_UART_STATE_READY)
216 {
217 buffer = reinterpret_cast<uint8_t*>(uart->dma_buff_tx_.ActiveBuffer());
218 }
219 else
220 {
221 buffer = reinterpret_cast<uint8_t*>(uart->dma_buff_tx_.PendingBuffer());
222 use_pending = true;
223 }
224
225 if (port.queue_data_->PopBatch(reinterpret_cast<uint8_t*>(buffer), info.data.size_) !=
226 ErrorCode::OK)
227 {
228 ASSERT(false);
229 return ErrorCode::EMPTY;
230 }
231
232 if (use_pending)
233 {
234 uart->dma_buff_tx_.SetPendingLength(info.data.size_);
235 uart->dma_buff_tx_.EnablePending();
236 if (uart->uart_handle_->gState == HAL_UART_STATE_READY &&
237 uart->dma_buff_tx_.HasPending())
238 {
239 uart->dma_buff_tx_.Switch();
240 }
241 else
242 {
243 return ErrorCode::PENDING;
244 }
245 }
246
247 port.queue_info_->Pop(uart->write_info_active_);
248
249#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
250 SCB_CleanDCache_by_Addr(
251 reinterpret_cast<uint32_t*>(uart->dma_buff_tx_.ActiveBuffer()), info.data.size_);
252#endif
253
254 uart->dma_buff_tx_.SetActiveLength(info.data.size_);
255 uart->tx_busy_.Set();
256 auto ans = HAL_UART_Transmit_DMA(
257 uart->uart_handle_, static_cast<uint8_t*>(uart->dma_buff_tx_.ActiveBuffer()),
258 info.data.size_);
259
260 if (ans != HAL_OK)
261 {
262 uart->tx_busy_.Clear();
263 return ErrorCode::FAILED;
264 }
265 else
266 {
267 return ErrorCode::OK;
268 }
269 }
270
271 return ErrorCode::PENDING;
272}
273
274ErrorCode STM32UART::ReadFun(ReadPort&, bool) { return ErrorCode::PENDING; }
275
276STM32UART::STM32UART(UART_HandleTypeDef* uart_handle, RawData dma_buff_rx,
277 RawData dma_buff_tx, uint32_t tx_queue_size)
278 : UART(&_read_port, &_write_port),
279 _read_port(dma_buff_rx.size_),
280 _write_port(tx_queue_size, dma_buff_tx.size_ / 2),
281 dma_buff_rx_(dma_buff_rx),
282 dma_buff_tx_(dma_buff_tx),
283 uart_handle_(uart_handle),
284 id_(stm32_uart_get_id(uart_handle_->Instance))
285{
286 ASSERT(id_ != STM32_UART_ID_ERROR);
287
288 map[id_] = this;
289
290 if ((uart_handle->Init.Mode & UART_MODE_TX) == UART_MODE_TX)
291 {
292 ASSERT(uart_handle_->hdmatx != NULL);
293 _write_port = WriteFun;
294 }
295
296 SetRxDMA();
297}
298
300{
301 HAL_UART_DeInit(uart_handle_);
302 uart_handle_->Init.BaudRate = config.baudrate;
303
304 switch (config.parity)
305 {
307 uart_handle_->Init.Parity = UART_PARITY_NONE;
308 uart_handle_->Init.WordLength = UART_WORDLENGTH_8B;
309 break;
311 uart_handle_->Init.Parity = UART_PARITY_EVEN;
312 uart_handle_->Init.WordLength = UART_WORDLENGTH_9B;
313 break;
315 uart_handle_->Init.Parity = UART_PARITY_ODD;
316 uart_handle_->Init.WordLength = UART_WORDLENGTH_9B;
317 break;
318 default:
319 ASSERT(false);
320 }
321
322 switch (config.stop_bits)
323 {
324 case 1:
325 uart_handle_->Init.StopBits = UART_STOPBITS_1;
326 break;
327 case 2:
328 uart_handle_->Init.StopBits = UART_STOPBITS_2;
329 break;
330 default:
331 ASSERT(false);
332 }
333
334 if (HAL_UART_Init(uart_handle_) != HAL_OK)
335 {
336 return ErrorCode::INIT_ERR;
337 }
338
339 last_rx_pos_ = 0;
340
341 SetRxDMA();
342
343 if (tx_busy_.IsSet())
344 {
345 HAL_UART_Transmit_DMA(uart_handle_, dma_buff_tx_.ActiveBuffer(),
346 dma_buff_tx_.GetActiveLength());
347 }
348
349 return ErrorCode::OK;
350}
351
352void STM32UART::SetRxDMA()
353{
354 if ((uart_handle_->Init.Mode & UART_MODE_RX) == UART_MODE_RX)
355 {
356 ASSERT(uart_handle_->hdmarx != NULL);
357
358 uart_handle_->hdmarx->Init.Mode = DMA_CIRCULAR;
359 HAL_DMA_Init(uart_handle_->hdmarx);
360
361 HAL_UARTEx_ReceiveToIdle_DMA(
362 uart_handle_, reinterpret_cast<uint8_t*>(dma_buff_rx_.addr_), dma_buff_rx_.size_);
363 _read_port = ReadFun;
364 }
365}
366
367// NOLINTNEXTLINE
368static inline void STM32_UART_RX_ISR_Handler(UART_HandleTypeDef* uart_handle)
369{
370 auto uart = STM32UART::map[stm32_uart_get_id(uart_handle->Instance)];
371 auto rx_buf = static_cast<uint8_t*>(uart->dma_buff_rx_.addr_);
372 size_t dma_size = uart->dma_buff_rx_.size_;
373
374 size_t curr_pos =
375 dma_size - __HAL_DMA_GET_COUNTER(uart_handle->hdmarx); // 当前 DMA 写入位置
376 size_t last_pos = uart->last_rx_pos_;
377
378#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
379 SCB_InvalidateDCache_by_Addr(rx_buf, dma_size);
380#endif
381
382 if (curr_pos != last_pos)
383 {
384 if (curr_pos > last_pos)
385 {
386 // 线性接收区
387 uart->read_port_->queue_data_->PushBatch(&rx_buf[last_pos], curr_pos - last_pos);
388 }
389 else
390 {
391 // 回卷区:last→end,再从0→curr
392 uart->read_port_->queue_data_->PushBatch(&rx_buf[last_pos], dma_size - last_pos);
393 uart->read_port_->queue_data_->PushBatch(&rx_buf[0], curr_pos);
394 }
395
396 uart->last_rx_pos_ = curr_pos;
397 uart->read_port_->ProcessPendingReads(true);
398 }
399}
400
401// NOLINTNEXTLINE
402void STM32_UART_ISR_Handler_TX_CPLT(stm32_uart_id_t id)
403{
404 auto uart = STM32UART::map[id];
405
406 uart->tx_busy_.Clear();
407
408 Flag::ScopedRestore tx_flag(uart->in_tx_isr);
409
410 size_t pending_len = uart->dma_buff_tx_.GetPendingLength();
411
412 if (pending_len == 0)
413 {
414 return;
415 }
416
417 uart->dma_buff_tx_.Switch();
418
419#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
420 SCB_CleanDCache_by_Addr(reinterpret_cast<uint32_t*>(uart->dma_buff_tx_.ActiveBuffer()),
421 pending_len);
422#endif
423
424 uart->dma_buff_tx_.SetActiveLength(pending_len);
425 uart->tx_busy_.Set();
426
427 auto ans = HAL_UART_Transmit_DMA(
428 uart->uart_handle_, static_cast<uint8_t*>(uart->dma_buff_tx_.ActiveBuffer()),
429 pending_len);
430
431 ASSERT(ans == HAL_OK);
432
433 WriteInfoBlock& current_info = uart->write_info_active_;
434
435 if (uart->write_port_->queue_info_->Pop(current_info) != ErrorCode::OK)
436 {
437 ASSERT(false);
438 return;
439 }
440
441 uart->write_port_->Finish(true, ans == HAL_OK ? ErrorCode::OK : ErrorCode::BUSY,
442 current_info);
443
444 WriteInfoBlock next_info;
445
446 if (uart->write_port_->queue_info_->Peek(next_info) != ErrorCode::OK)
447 {
448 return;
449 }
450
451 if (uart->write_port_->queue_data_->PopBatch(
452 reinterpret_cast<uint8_t*>(uart->dma_buff_tx_.PendingBuffer()),
453 next_info.data.size_) != ErrorCode::OK)
454 {
455 ASSERT(false);
456 return;
457 }
458
459 uart->dma_buff_tx_.SetPendingLength(next_info.data.size_);
460
461 uart->dma_buff_tx_.EnablePending();
462}
463
464extern "C" void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef* huart, uint16_t)
465{
466 STM32_UART_RX_ISR_Handler(huart);
467}
468
469extern "C" void HAL_UART_TxCpltCallback(UART_HandleTypeDef* huart)
470{
471 STM32_UART_ISR_Handler_TX_CPLT(stm32_uart_get_id(huart->Instance));
472}
473
474extern "C" __attribute__((used)) void HAL_UART_ErrorCallback(UART_HandleTypeDef* huart)
475{
476 HAL_UART_Abort_IT(huart);
477}
478
479extern "C" void HAL_UART_AbortCpltCallback(UART_HandleTypeDef* huart)
480{
481 auto uart = STM32UART::map[stm32_uart_get_id(huart->Instance)];
482 uart->last_rx_pos_ = 0;
483 HAL_UARTEx_ReceiveToIdle_DMA(huart, huart->pRxBuffPtr, uart->dma_buff_rx_.size_);
484 if (uart->tx_busy_.IsSet())
485 {
486 HAL_UART_Transmit_DMA(huart, uart->dma_buff_tx_.ActiveBuffer(),
487 uart->dma_buff_tx_.GetActiveLength());
488 }
489}
490
491#endif
size_t size_
数据大小(字节)。 The size of the data (in bytes).
void SetActiveLength(size_t length)
设置当前活动缓冲区的数据长度 Sets the size of the active buffer
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
size_t GetActiveLength() const
获取当前活动缓冲区中准备好的数据长度 Gets the size of valid data in 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
void Set() noexcept
置位标志 / Set the flag
Definition flag.hpp:125
bool IsSet() const noexcept
判断是否已置位 / Check whether the flag is set
Definition flag.hpp:138
void Clear() noexcept
清除标志 / Clear the flag
Definition flag.hpp:130
作用域标志管理器:构造时写入指定值,析构时恢复原值 / Scoped flag restorer: set on entry, restore on exit
Definition flag.hpp:199
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:272
void ProcessPendingReads(bool in_isr)
Processes pending reads.
Definition libxr_rw.cpp:127
STM32 UART 驱动实现 / STM32 UART driver implementation.
STM32UART(UART_HandleTypeDef *uart_handle, RawData dma_buff_rx, RawData dma_buff_tx, uint32_t tx_queue_size=5)
构造 UART 对象 / Construct UART object
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:413
void Finish(bool in_isr, ErrorCode ans, WriteInfoBlock &info)
更新写入操作的状态。 Updates the status of the write operation.
Definition libxr_rw.cpp:191
LibXR 命名空间
Definition ch32_can.hpp:14
ErrorCode(* ReadFun)(ReadPort &port, bool in_isr)
Function pointer type for read operations.
Definition libxr_rw.hpp:249
ErrorCode(* WriteFun)(WritePort &port, bool in_isr)
Function pointer type for write operations.
Definition libxr_rw.hpp:245
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:263