1#include "stm32_uart.hpp"
3#include "stm32_dcache.hpp"
4#ifdef HAL_UART_MODULE_ENABLED
8STM32UART* STM32UART::map[STM32_UART_NUMBER] = {
nullptr};
10stm32_uart_id_t stm32_uart_get_id(USART_TypeDef* addr)
14 return stm32_uart_id_t::STM32_UART_ID_ERROR;
17 else if (addr == USART1)
19 return stm32_uart_id_t::STM32_USART1;
23 else if (addr == USART2)
25 return stm32_uart_id_t::STM32_USART2;
29 else if (addr == USART3)
31 return stm32_uart_id_t::STM32_USART3;
35 else if (addr == USART4)
37 return stm32_uart_id_t::STM32_USART4;
41 else if (addr == USART5)
43 return stm32_uart_id_t::STM32_USART5;
47 else if (addr == USART6)
49 return stm32_uart_id_t::STM32_USART6;
53 else if (addr == USART7)
55 return stm32_uart_id_t::STM32_USART7;
59 else if (addr == USART8)
61 return stm32_uart_id_t::STM32_USART8;
65 else if (addr == USART9)
67 return stm32_uart_id_t::STM32_USART9;
71 else if (addr == USART10)
73 return stm32_uart_id_t::STM32_USART10;
77 else if (addr == USART11)
79 return stm32_uart_id_t::STM32_USART11;
83 else if (addr == USART12)
85 return stm32_uart_id_t::STM32_USART12;
89 else if (addr == USART13)
91 return stm32_uart_id_t::STM32_USART13;
95 else if (addr == UART1)
97 return stm32_uart_id_t::STM32_UART1;
101 else if (addr == UART2)
103 return stm32_uart_id_t::STM32_UART2;
107 else if (addr == UART3)
109 return stm32_uart_id_t::STM32_UART3;
113 else if (addr == UART4)
115 return stm32_uart_id_t::STM32_UART4;
119 else if (addr == UART5)
121 return stm32_uart_id_t::STM32_UART5;
125 else if (addr == UART6)
127 return stm32_uart_id_t::STM32_UART6;
131 else if (addr == UART7)
133 return stm32_uart_id_t::STM32_UART7;
137 else if (addr == UART8)
139 return stm32_uart_id_t::STM32_UART8;
143 else if (addr == UART9)
145 return stm32_uart_id_t::STM32_UART9;
149 else if (addr == UART10)
151 return stm32_uart_id_t::STM32_UART10;
155 else if (addr == UART11)
157 return stm32_uart_id_t::STM32_UART11;
161 else if (addr == UART12)
163 return stm32_uart_id_t::STM32_UART12;
167 else if (addr == UART13)
169 return stm32_uart_id_t::STM32_UART13;
173 else if (addr == LPUART1)
175 return stm32_uart_id_t::STM32_LPUART1;
179 else if (addr == LPUART2)
181 return stm32_uart_id_t::STM32_LPUART2;
185 else if (addr == LPUART3)
187 return stm32_uart_id_t::STM32_LPUART3;
192 return stm32_uart_id_t::STM32_UART_ID_ERROR;
200 if (uart->in_tx_isr.IsSet())
205 if (!uart->dma_buff_tx_.HasPending())
213 uint8_t* buffer =
nullptr;
214 bool use_pending =
false;
216 if (uart->uart_handle_->gState == HAL_UART_STATE_READY)
218 buffer =
reinterpret_cast<uint8_t*
>(uart->dma_buff_tx_.ActiveBuffer());
222 buffer =
reinterpret_cast<uint8_t*
>(uart->dma_buff_tx_.PendingBuffer());
235 uart->dma_buff_tx_.SetPendingLength(info.
data.
size_);
236 uart->dma_buff_tx_.EnablePending();
237 if (uart->uart_handle_->gState == HAL_UART_STATE_READY &&
238 uart->dma_buff_tx_.HasPending())
240 uart->dma_buff_tx_.Switch();
252 uart->dma_buff_tx_.SetActiveLength(info.
data.
size_);
253 uart->tx_busy_.Set();
254 auto ans = HAL_UART_Transmit_DMA(
255 uart->uart_handle_,
static_cast<uint8_t*
>(uart->dma_buff_tx_.ActiveBuffer()),
260 uart->tx_busy_.Clear();
275 RawData dma_buff_tx, uint32_t tx_queue_size)
276 :
UART(&_read_port, &_write_port),
277 _read_port(dma_buff_rx.size_),
278 _write_port(tx_queue_size, dma_buff_tx.size_ / 2),
279 dma_buff_rx_(dma_buff_rx),
280 dma_buff_tx_(dma_buff_tx),
281 uart_handle_(uart_handle),
282 id_(stm32_uart_get_id(uart_handle_->Instance))
284 ASSERT(id_ != STM32_UART_ID_ERROR);
288 if ((uart_handle->Init.Mode & UART_MODE_TX) == UART_MODE_TX)
290 ASSERT(uart_handle_->hdmatx != NULL);
299 HAL_UART_DeInit(uart_handle_);
300 uart_handle_->Init.BaudRate = config.
baudrate;
305 uart_handle_->Init.Parity = UART_PARITY_NONE;
306 uart_handle_->Init.WordLength = UART_WORDLENGTH_8B;
309 uart_handle_->Init.Parity = UART_PARITY_EVEN;
310 uart_handle_->Init.WordLength = UART_WORDLENGTH_9B;
313 uart_handle_->Init.Parity = UART_PARITY_ODD;
314 uart_handle_->Init.WordLength = UART_WORDLENGTH_9B;
323 uart_handle_->Init.StopBits = UART_STOPBITS_1;
326 uart_handle_->Init.StopBits = UART_STOPBITS_2;
332 if (HAL_UART_Init(uart_handle_) != HAL_OK)
341 if (tx_busy_.
IsSet())
343 HAL_UART_Transmit_DMA(uart_handle_, dma_buff_tx_.
ActiveBuffer(),
350void STM32UART::SetRxDMA()
352 if ((uart_handle_->Init.Mode & UART_MODE_RX) == UART_MODE_RX)
354 ASSERT(uart_handle_->hdmarx != NULL);
356 uart_handle_->hdmarx->Init.Mode = DMA_CIRCULAR;
357 HAL_DMA_Init(uart_handle_->hdmarx);
359 HAL_UARTEx_ReceiveToIdle_DMA(
360 uart_handle_,
reinterpret_cast<uint8_t*
>(dma_buff_rx_.
addr_), dma_buff_rx_.
size_);
366static inline void STM32_UART_RX_ISR_Handler(UART_HandleTypeDef* uart_handle)
368 auto uart = STM32UART::map[stm32_uart_get_id(uart_handle->Instance)];
369 auto rx_buf =
static_cast<uint8_t*
>(uart->dma_buff_rx_.addr_);
370 size_t dma_size = uart->dma_buff_rx_.
size_;
373 dma_size - __HAL_DMA_GET_COUNTER(uart_handle->hdmarx);
374 size_t last_pos = uart->last_rx_pos_;
378 if (curr_pos != last_pos)
380 if (curr_pos > last_pos)
383 uart->read_port_->queue_data_->PushBatch(&rx_buf[last_pos], curr_pos - last_pos);
388 uart->read_port_->queue_data_->PushBatch(&rx_buf[last_pos], dma_size - last_pos);
389 uart->read_port_->queue_data_->PushBatch(&rx_buf[0], curr_pos);
392 uart->last_rx_pos_ = curr_pos;
393 uart->read_port_->ProcessPendingReads(
true);
398void STM32_UART_ISR_Handler_TX_CPLT(stm32_uart_id_t
id)
400 auto uart = STM32UART::map[id];
402 uart->tx_busy_.
Clear();
406 size_t pending_len = uart->dma_buff_tx_.GetPendingLength();
408 if (pending_len == 0)
413 uart->dma_buff_tx_.Switch();
417 uart->dma_buff_tx_.SetActiveLength(pending_len);
418 uart->tx_busy_.Set();
420 auto ans = HAL_UART_Transmit_DMA(
421 uart->uart_handle_,
static_cast<uint8_t*
>(uart->dma_buff_tx_.ActiveBuffer()),
424 ASSERT(ans == HAL_OK);
428 if (uart->write_port_->queue_info_->Pop(current_info) !=
ErrorCode::OK)
439 if (uart->write_port_->queue_info_->Peek(next_info) !=
ErrorCode::OK)
444 if (uart->write_port_->queue_data_->PopBatch(
445 reinterpret_cast<uint8_t*
>(uart->dma_buff_tx_.PendingBuffer()),
452 uart->dma_buff_tx_.SetPendingLength(next_info.
data.
size_);
454 uart->dma_buff_tx_.EnablePending();
457extern "C" void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef* huart, uint16_t)
459 STM32_UART_RX_ISR_Handler(huart);
462extern "C" void HAL_UART_TxCpltCallback(UART_HandleTypeDef* huart)
464 STM32_UART_ISR_Handler_TX_CPLT(stm32_uart_get_id(huart->Instance));
467extern "C" __attribute__((used))
void HAL_UART_ErrorCallback(UART_HandleTypeDef* huart)
469 HAL_UART_Abort_IT(huart);
472extern "C" void HAL_UART_AbortCpltCallback(UART_HandleTypeDef* huart)
474 auto uart = STM32UART::map[stm32_uart_get_id(huart->Instance)];
475 uart->last_rx_pos_ = 0;
476 HAL_UARTEx_ReceiveToIdle_DMA(huart, huart->pRxBuffPtr, uart->dma_buff_rx_.size_);
477 if (uart->tx_busy_.IsSet())
479 HAL_UART_Transmit_DMA(huart, uart->dma_buff_tx_.ActiveBuffer(),
480 uart->dma_buff_tx_.GetActiveLength());
size_t size_
数据字节数 / Data size in bytes
uint8_t * ActiveBuffer() const
获取当前正在使用的缓冲区指针 Returns the currently active buffer
size_t GetActiveLength() const
获取当前活动缓冲区中准备好的数据长度 Gets the size of valid data in active buffer
bool IsSet() const noexcept
判断是否已置位 / Check whether the flag is set
void Clear() noexcept
清除标志 / Clear the flag
作用域标志管理器:构造时写入指定值,析构时恢复原值 / Scoped flag restorer: set on entry, restore on exit
ErrorCode PopBatch(Data *data, size_t size)
批量弹出数据 / Pops multiple elements from the queue
可写原始数据视图 / Mutable raw data view
size_t size_
数据字节数 / Data size in bytes
void * addr_
数据起始地址 / Data start address
ReadPort class for handling read operations.
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)
@ NO_PARITY
无校验 / No parity
WritePort class for handling write operations.
LockFreeQueue< uint8_t > * queue_data_
Payload queue for pending write bytes. 挂起写入字节的数据队列。
LockFreeQueue< WriteInfoBlock > * queue_info_
Metadata queue for pending write batches. 挂起写批次的元数据队列。
void STM32_InvalidateDCacheByAddr(const void *addr, size_t size)
Invalidates D-Cache lines covering the specified memory range.
@ INIT_ERR
初始化错误 | Initialization error
@ FAILED
操作失败 | Operation failed
@ OK
操作成功 | Operation successful
ErrorCode(* ReadFun)(ReadPort &port, bool in_isr)
Function pointer type for read notifications.
ErrorCode(* WriteFun)(WritePort &port, bool in_isr)
Function pointer type for write operations.
OwnerType * ContainerOf(MemberType *ptr, MemberType OwnerType::*member) noexcept
通过成员指针恢复其所属对象指针
void STM32_CleanDCacheByAddr(const void *addr, size_t size)
Cleans D-Cache lines covering the specified memory range.
UART 配置结构体 / UART configuration structure.
uint8_t stop_bits
停止位长度 / Number of stop bits
Parity parity
校验模式 / Parity mode
uint32_t baudrate
波特率 / Baud rate
ConstRawData data
Data buffer. 数据缓冲区。