1#include "stm32_uart.hpp"
3#ifdef HAL_UART_MODULE_ENABLED
7STM32UART* STM32UART::map[STM32_UART_NUMBER] = {
nullptr};
9stm32_uart_id_t stm32_uart_get_id(USART_TypeDef* addr)
13 return stm32_uart_id_t::STM32_UART_ID_ERROR;
16 else if (addr == USART1)
18 return stm32_uart_id_t::STM32_USART1;
22 else if (addr == USART2)
24 return stm32_uart_id_t::STM32_USART2;
28 else if (addr == USART3)
30 return stm32_uart_id_t::STM32_USART3;
34 else if (addr == USART4)
36 return stm32_uart_id_t::STM32_USART4;
40 else if (addr == USART5)
42 return stm32_uart_id_t::STM32_USART5;
46 else if (addr == USART6)
48 return stm32_uart_id_t::STM32_USART6;
52 else if (addr == USART7)
54 return stm32_uart_id_t::STM32_USART7;
58 else if (addr == USART8)
60 return stm32_uart_id_t::STM32_USART8;
64 else if (addr == USART9)
66 return stm32_uart_id_t::STM32_USART9;
70 else if (addr == USART10)
72 return stm32_uart_id_t::STM32_USART10;
76 else if (addr == USART11)
78 return stm32_uart_id_t::STM32_USART11;
82 else if (addr == USART12)
84 return stm32_uart_id_t::STM32_USART12;
88 else if (addr == USART13)
90 return stm32_uart_id_t::STM32_USART13;
94 else if (addr == UART1)
96 return stm32_uart_id_t::STM32_UART1;
100 else if (addr == UART2)
102 return stm32_uart_id_t::STM32_UART2;
106 else if (addr == UART3)
108 return stm32_uart_id_t::STM32_UART3;
112 else if (addr == UART4)
114 return stm32_uart_id_t::STM32_UART4;
118 else if (addr == UART5)
120 return stm32_uart_id_t::STM32_UART5;
124 else if (addr == UART6)
126 return stm32_uart_id_t::STM32_UART6;
130 else if (addr == UART7)
132 return stm32_uart_id_t::STM32_UART7;
136 else if (addr == UART8)
138 return stm32_uart_id_t::STM32_UART8;
142 else if (addr == UART9)
144 return stm32_uart_id_t::STM32_UART9;
148 else if (addr == UART10)
150 return stm32_uart_id_t::STM32_UART10;
154 else if (addr == UART11)
156 return stm32_uart_id_t::STM32_UART11;
160 else if (addr == UART12)
162 return stm32_uart_id_t::STM32_UART12;
166 else if (addr == UART13)
168 return stm32_uart_id_t::STM32_UART13;
172 else if (addr == LPUART1)
174 return stm32_uart_id_t::STM32_LPUART1;
178 else if (addr == LPUART2)
180 return stm32_uart_id_t::STM32_LPUART2;
184 else if (addr == LPUART3)
186 return stm32_uart_id_t::STM32_LPUART3;
191 return stm32_uart_id_t::STM32_UART_ID_ERROR;
195ErrorCode STM32UART::WriteFun(
WritePort& port,
bool)
199 if (uart->in_tx_isr.
IsSet())
201 return ErrorCode::PENDING;
207 if (port.queue_info_->Peek(info) != ErrorCode::OK)
209 return ErrorCode::PENDING;
212 uint8_t* buffer =
nullptr;
213 bool use_pending =
false;
215 if (uart->uart_handle_->gState == HAL_UART_STATE_READY)
217 buffer =
reinterpret_cast<uint8_t*
>(uart->dma_buff_tx_.
ActiveBuffer());
221 buffer =
reinterpret_cast<uint8_t*
>(uart->dma_buff_tx_.
PendingBuffer());
225 if (port.queue_data_->
PopBatch(
reinterpret_cast<uint8_t*
>(buffer), info.
data.
size_) !=
229 return ErrorCode::EMPTY;
236 if (uart->uart_handle_->gState == HAL_UART_STATE_READY &&
239 uart->dma_buff_tx_.
Switch();
243 return ErrorCode::PENDING;
247 port.queue_info_->Pop(uart->write_info_active_);
249#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
250 SCB_CleanDCache_by_Addr(
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()),
262 uart->tx_busy_.
Clear();
263 return ErrorCode::FAILED;
267 return ErrorCode::OK;
271 return ErrorCode::PENDING;
274ErrorCode STM32UART::ReadFun(
ReadPort&,
bool) {
return ErrorCode::PENDING; }
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))
286 ASSERT(id_ != STM32_UART_ID_ERROR);
290 if ((uart_handle->Init.Mode & UART_MODE_TX) == UART_MODE_TX)
292 ASSERT(uart_handle_->hdmatx != NULL);
301 HAL_UART_DeInit(uart_handle_);
302 uart_handle_->Init.BaudRate = config.
baudrate;
307 uart_handle_->Init.Parity = UART_PARITY_NONE;
308 uart_handle_->Init.WordLength = UART_WORDLENGTH_8B;
311 uart_handle_->Init.Parity = UART_PARITY_EVEN;
312 uart_handle_->Init.WordLength = UART_WORDLENGTH_9B;
315 uart_handle_->Init.Parity = UART_PARITY_ODD;
316 uart_handle_->Init.WordLength = UART_WORDLENGTH_9B;
325 uart_handle_->Init.StopBits = UART_STOPBITS_1;
328 uart_handle_->Init.StopBits = UART_STOPBITS_2;
334 if (HAL_UART_Init(uart_handle_) != HAL_OK)
336 return ErrorCode::INIT_ERR;
343 if (tx_busy_.
IsSet())
345 HAL_UART_Transmit_DMA(uart_handle_, dma_buff_tx_.
ActiveBuffer(),
349 return ErrorCode::OK;
352void STM32UART::SetRxDMA()
354 if ((uart_handle_->Init.Mode & UART_MODE_RX) == UART_MODE_RX)
356 ASSERT(uart_handle_->hdmarx != NULL);
358 uart_handle_->hdmarx->Init.Mode = DMA_CIRCULAR;
359 HAL_DMA_Init(uart_handle_->hdmarx);
361 HAL_UARTEx_ReceiveToIdle_DMA(
362 uart_handle_,
reinterpret_cast<uint8_t*
>(dma_buff_rx_.
addr_), dma_buff_rx_.
size_);
368static inline void STM32_UART_RX_ISR_Handler(UART_HandleTypeDef* uart_handle)
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_;
375 dma_size - __HAL_DMA_GET_COUNTER(uart_handle->hdmarx);
376 size_t last_pos = uart->last_rx_pos_;
378#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
379 SCB_InvalidateDCache_by_Addr(rx_buf, dma_size);
382 if (curr_pos != last_pos)
384 if (curr_pos > last_pos)
396 uart->last_rx_pos_ = curr_pos;
402void STM32_UART_ISR_Handler_TX_CPLT(stm32_uart_id_t
id)
404 auto uart = STM32UART::map[id];
406 uart->tx_busy_.
Clear();
412 if (pending_len == 0)
417 uart->dma_buff_tx_.
Switch();
419#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
420 SCB_CleanDCache_by_Addr(
reinterpret_cast<uint32_t*
>(uart->dma_buff_tx_.
ActiveBuffer()),
425 uart->tx_busy_.
Set();
427 auto ans = HAL_UART_Transmit_DMA(
428 uart->uart_handle_,
static_cast<uint8_t*
>(uart->dma_buff_tx_.
ActiveBuffer()),
431 ASSERT(ans == HAL_OK);
435 if (uart->
write_port_->queue_info_->Pop(current_info) != ErrorCode::OK)
446 if (uart->
write_port_->queue_info_->Peek(next_info) != ErrorCode::OK)
452 reinterpret_cast<uint8_t*
>(uart->dma_buff_tx_.
PendingBuffer()),
464extern "C" void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef* huart, uint16_t)
466 STM32_UART_RX_ISR_Handler(huart);
469extern "C" void HAL_UART_TxCpltCallback(UART_HandleTypeDef* huart)
471 STM32_UART_ISR_Handler_TX_CPLT(stm32_uart_get_id(huart->Instance));
474extern "C" __attribute__((used))
void HAL_UART_ErrorCallback(UART_HandleTypeDef* huart)
476 HAL_UART_Abort_IT(huart);
479extern "C" void HAL_UART_AbortCpltCallback(UART_HandleTypeDef* huart)
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())
486 HAL_UART_Transmit_DMA(huart, uart->dma_buff_tx_.
ActiveBuffer(),
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
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 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.
void ProcessPendingReads(bool in_isr)
Processes pending reads.
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)
ReadPort * read_port_
读取端口 / Read port
@ NO_PARITY
无校验 / No parity
WritePort * write_port_
写入端口 / Write port
WritePort class for handling write operations.
void Finish(bool in_isr, ErrorCode ans, WriteInfoBlock &info)
更新写入操作的状态。 Updates the status of the write operation.
ErrorCode(* ReadFun)(ReadPort &port, bool in_isr)
Function pointer type for read operations.
ErrorCode(* WriteFun)(WritePort &port, bool in_isr)
Function pointer type for write operations.
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. 数据缓冲区。