1#include "stm32_uart.hpp"
3#ifdef HAL_UART_MODULE_ENABLED
7STM32UART *STM32UART::map[STM32_UART_NUMBER] = {
nullptr};
9stm32_uart_id_t STM32_UART_GetID(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)
202 if (port.queue_info_->Peek(info) != ErrorCode::OK)
204 return ErrorCode::EMPTY;
207 uint8_t *buffer =
nullptr;
208 bool use_pending =
false;
210 if (uart->uart_handle_->gState == HAL_UART_STATE_READY)
212 buffer =
reinterpret_cast<uint8_t *
>(uart->dma_buff_tx_.
ActiveBuffer());
216 buffer =
reinterpret_cast<uint8_t *
>(uart->dma_buff_tx_.
PendingBuffer());
220 if (port.queue_data_->
PopBatch(
reinterpret_cast<uint8_t *
>(buffer),
224 return ErrorCode::EMPTY;
231 if (uart->uart_handle_->gState == HAL_UART_STATE_READY &&
234 uart->dma_buff_tx_.
Switch();
238 return ErrorCode::FAILED;
242 port.queue_info_->Pop(uart->write_info_active_);
244#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
245 SCB_CleanDCache_by_Addr(
249 auto ans = HAL_UART_Transmit_DMA(
250 uart->uart_handle_,
static_cast<uint8_t *
>(uart->dma_buff_tx_.
ActiveBuffer()),
255 port.
Finish(
false, ErrorCode::FAILED, info, 0);
256 return ErrorCode::FAILED;
260 return ErrorCode::OK;
264 return ErrorCode::FAILED;
267ErrorCode STM32UART::ReadFun(
ReadPort &port)
272 return ErrorCode::EMPTY;
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))
285 ASSERT(id_ != STM32_UART_ID_ERROR);
289 if ((uart_handle->Init.Mode & UART_MODE_TX) == UART_MODE_TX)
291 ASSERT(uart_handle_->hdmatx != NULL);
295 if ((uart_handle->Init.Mode & UART_MODE_RX) == UART_MODE_RX)
297 ASSERT(uart_handle->hdmarx != NULL);
299 uart_handle_->hdmarx->Init.Mode = DMA_CIRCULAR;
300 HAL_DMA_Init(uart_handle_->hdmarx);
302 __HAL_UART_ENABLE_IT(uart_handle, UART_IT_IDLE);
304 HAL_UART_Receive_DMA(uart_handle,
reinterpret_cast<uint8_t *
>(dma_buff_rx_.addr_),
312 uart_handle_->Init.BaudRate = config.
baudrate;
317 uart_handle_->Init.Parity = UART_PARITY_NONE;
318 uart_handle_->Init.WordLength = UART_WORDLENGTH_8B;
321 uart_handle_->Init.Parity = UART_PARITY_EVEN;
322 uart_handle_->Init.WordLength = UART_WORDLENGTH_9B;
325 uart_handle_->Init.Parity = UART_PARITY_ODD;
326 uart_handle_->Init.WordLength = UART_WORDLENGTH_9B;
335 uart_handle_->Init.StopBits = UART_STOPBITS_1;
338 uart_handle_->Init.StopBits = UART_STOPBITS_2;
344 if (HAL_UART_Init(uart_handle_) != HAL_OK)
346 return ErrorCode::INIT_ERR;
348 return ErrorCode::OK;
351static void STM32_UART_RX_ISR_Handler(UART_HandleTypeDef *uart_handle)
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_;
358 dma_size - __HAL_DMA_GET_COUNTER(uart_handle->hdmarx);
359 size_t last_pos = uart->last_rx_pos_;
361#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
362 SCB_InvalidateDCache_by_Addr(rx_buf, dma_size);
365 if (curr_pos != last_pos)
367 if (curr_pos > last_pos)
379 uart->last_rx_pos_ = curr_pos;
384void STM32_UART_ISR_Handler_TX_CPLT(stm32_uart_id_t
id)
386 auto uart = STM32UART::map[id];
390 if (pending_len == 0)
395 uart->dma_buff_tx_.
Switch();
397#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
398 SCB_CleanDCache_by_Addr(
reinterpret_cast<uint32_t *
>(uart->dma_buff_tx_.
ActiveBuffer()),
402 auto ans = HAL_UART_Transmit_DMA(
403 uart->uart_handle_,
static_cast<uint8_t *
>(uart->dma_buff_tx_.
ActiveBuffer()),
406 ASSERT(ans == HAL_OK);
410 if (uart->
write_port_->queue_info_->Pop(current_info) != ErrorCode::OK)
421 if (uart->
write_port_->queue_info_->Peek(next_info) != ErrorCode::OK)
427 reinterpret_cast<uint8_t *
>(uart->dma_buff_tx_.
PendingBuffer()),
440extern "C" void STM32_UART_ISR_Handler_IDLE(UART_HandleTypeDef *huart)
442 if (__HAL_UART_GET_FLAG(huart, UART_FLAG_IDLE))
444 __HAL_UART_CLEAR_IDLEFLAG(huart);
446 STM32_UART_RX_ISR_Handler(huart);
450extern "C" void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart)
452 STM32_UART_RX_ISR_Handler(huart);
455extern "C" void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
457 STM32_UART_RX_ISR_Handler(huart);
460extern "C" void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
462 STM32_UART_ISR_Handler_TX_CPLT(STM32_UART_GetID(huart->Instance));
465extern "C" __attribute__((used))
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
467 HAL_UART_Abort_IT(huart);
470extern "C" void HAL_UART_AbortCpltCallback(UART_HandleTypeDef *huart)
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;
476 if (uart->
write_port_->queue_info_->Peek(info) == ErrorCode::OK)
482extern "C" void HAL_UART_AbortTransmitCpltCallback(UART_HandleTypeDef *huart)
484 auto uart = STM32UART::map[STM32_UART_GetID(huart->Instance)];
486 if (uart->
write_port_->queue_info_->Peek(info) == ErrorCode::OK)
492extern "C" void HAL_UART_AbortReceiveCpltCallback(UART_HandleTypeDef *huart)
494 HAL_UART_Receive_DMA(
495 huart, huart->pRxBuffPtr,
496 STM32UART::map[STM32_UART_GetID(huart->Instance)]->dma_buff_rx_.size_);
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.
virtual void ProcessPendingReads(bool in_isr)
Processes pending reads.
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, uint32_t size)
更新写入操作的状态。 Updates the status of the write operation.
ErrorCode(* ReadFun)(ReadPort &port)
Function pointer type for read operations.
ErrorCode(* WriteFun)(WritePort &port)
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. 数据缓冲区。