3#include "ch32_uart.hpp"
6#include "ch32_gpio.hpp"
11CH32UART *CH32UART::map[ch32_uart_id_t::CH32_UART_NUMBER] = {
nullptr};
14CH32UART::CH32UART(ch32_uart_id_t
id,
RawData dma_rx,
RawData dma_tx,
15 GPIO_TypeDef *tx_gpio_port, uint16_t tx_gpio_pin,
16 GPIO_TypeDef *rx_gpio_port, uint16_t rx_gpio_pin, uint32_t pin_remap,
18 :
UART(&_read_port, &_write_port),
20 _read_port(dma_rx.size_),
21 _write_port(tx_queue_size, dma_tx.size_ / 2),
24 instance_(CH32_UART_GetInstanceID(id)),
25 dma_rx_channel_(CH32_UART_RX_DMA_CHANNEL_MAP[id]),
26 dma_tx_channel_(CH32_UART_TX_DMA_CHANNEL_MAP[id])
30 bool tx_enable = dma_tx.
size_ > 1;
31 bool rx_enable = dma_rx.
size_ > 0;
33 ASSERT(tx_enable || rx_enable);
36 GPIO_InitTypeDef gpio_init = {};
37 gpio_init.GPIO_Speed = GPIO_Speed_50MHz;
42 gpio_init.GPIO_Pin = tx_gpio_pin;
43 gpio_init.GPIO_Mode = GPIO_Mode_AF_PP;
44 GPIO_Init(tx_gpio_port, &gpio_init);
45 RCC_APB2PeriphClockCmd(CH32GetGPIOPeriph(tx_gpio_port), ENABLE);
51 gpio_init.GPIO_Pin = rx_gpio_pin;
52 gpio_init.GPIO_Mode = GPIO_Mode_IN_FLOATING;
53 GPIO_Init(rx_gpio_port, &gpio_init);
54 RCC_APB2PeriphClockCmd(CH32GetGPIOPeriph(rx_gpio_port), ENABLE);
60 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
61 GPIO_PinRemapConfig(pin_remap, ENABLE);
65 if (CH32_UART_APB_MAP[
id] == 1)
67 RCC_APB1PeriphClockCmd(CH32_UART_RCC_PERIPH_MAP[
id], ENABLE);
69 else if (CH32_UART_APB_MAP[
id] == 2)
71 RCC_APB2PeriphClockCmd(CH32_UART_RCC_PERIPH_MAP[
id], ENABLE);
77 RCC_AHBPeriphClockCmd(CH32_UART_RCC_PERIPH_MAP_DMA[
id], ENABLE);
80 USART_InitTypeDef usart_cfg = {};
81 usart_cfg.USART_BaudRate = config.
baudrate;
82 usart_cfg.USART_StopBits =
83 (config.
stop_bits == 2) ? USART_StopBits_2 : USART_StopBits_1;
86 case UART::Parity::NO_PARITY:
87 usart_cfg.USART_Parity = USART_Parity_No;
88 usart_cfg.USART_WordLength = USART_WordLength_8b;
90 case UART::Parity::EVEN:
91 usart_cfg.USART_Parity = USART_Parity_Even;
92 usart_cfg.USART_WordLength = USART_WordLength_9b;
94 case UART::Parity::ODD:
95 usart_cfg.USART_Parity = USART_Parity_Odd;
96 usart_cfg.USART_WordLength = USART_WordLength_9b;
102 usart_cfg.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
103 usart_cfg.USART_Mode =
104 (tx_enable ? USART_Mode_Tx : 0) | (rx_enable ? USART_Mode_Rx : 0);
105 uart_mode_ = usart_cfg.USART_Mode;
106 USART_Init(instance_, &usart_cfg);
109 DMA_InitTypeDef dma_init = {};
110 dma_init.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
111 dma_init.DMA_MemoryInc = DMA_MemoryInc_Enable;
112 dma_init.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
113 dma_init.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
114 dma_init.DMA_Priority = DMA_Priority_High;
115 dma_init.DMA_M2M = DMA_M2M_Disable;
119 DMA_DeInit(dma_rx_channel_);
120 dma_init.DMA_PeripheralBaseAddr = (uint32_t)&instance_->DATAR;
121 dma_init.DMA_MemoryBaseAddr = (uint32_t)dma_buff_rx_.addr_;
122 dma_init.DMA_DIR = DMA_DIR_PeripheralSRC;
123 dma_init.DMA_Mode = DMA_Mode_Circular;
124 dma_init.DMA_BufferSize = dma_buff_rx_.size_;
125 DMA_Init(dma_rx_channel_, &dma_init);
126 DMA_Cmd(dma_rx_channel_, ENABLE);
127 DMA_ITConfig(dma_rx_channel_, DMA_IT_TC, ENABLE);
128 DMA_ITConfig(dma_rx_channel_, DMA_IT_HT, ENABLE);
129 USART_DMACmd(instance_, USART_DMAReq_Rx, ENABLE);
134 DMA_DeInit(dma_tx_channel_);
135 dma_init.DMA_PeripheralBaseAddr = (u32)(&instance_->DATAR);
136 dma_init.DMA_MemoryBaseAddr = 0;
137 dma_init.DMA_DIR = DMA_DIR_PeripheralDST;
138 dma_init.DMA_Mode = DMA_Mode_Normal;
139 dma_init.DMA_BufferSize = 0;
140 DMA_Init(dma_tx_channel_, &dma_init);
141 DMA_ITConfig(dma_tx_channel_, DMA_IT_TC, ENABLE);
142 USART_DMACmd(instance_, USART_DMAReq_Tx, ENABLE);
146 USART_Cmd(instance_, ENABLE);
150 USART_ITConfig(instance_, USART_IT_IDLE, ENABLE);
151 NVIC_EnableIRQ(CH32_DMA_IRQ_MAP[CH32_DMA_GetID(dma_rx_channel_)]);
156 NVIC_EnableIRQ(CH32_DMA_IRQ_MAP[CH32_DMA_GetID(dma_tx_channel_)]);
159 NVIC_EnableIRQ(CH32_UART_IRQ_MAP[
id]);
165 USART_InitTypeDef usart_cfg = {};
166 usart_cfg.USART_BaudRate = config.
baudrate;
167 usart_cfg.USART_StopBits =
168 (config.
stop_bits == 2) ? USART_StopBits_2 : USART_StopBits_1;
173 usart_cfg.USART_Parity = USART_Parity_No;
174 usart_cfg.USART_WordLength = USART_WordLength_8b;
177 usart_cfg.USART_Parity = USART_Parity_Even;
178 usart_cfg.USART_WordLength = USART_WordLength_9b;
181 usart_cfg.USART_Parity = USART_Parity_Odd;
182 usart_cfg.USART_WordLength = USART_WordLength_9b;
185 return ErrorCode::NOT_SUPPORT;
188 usart_cfg.USART_Mode = uart_mode_;
189 usart_cfg.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
190 USART_DeInit(instance_);
191 USART_Init(instance_, &usart_cfg);
193 if (uart_mode_ & USART_Mode_Rx)
195 USART_DMACmd(instance_, USART_DMAReq_Rx, ENABLE);
196 USART_ITConfig(instance_, USART_IT_IDLE, ENABLE);
199 if (uart_mode_ & USART_Mode_Tx)
201 USART_DMACmd(instance_, USART_DMAReq_Tx, ENABLE);
204 USART_Cmd(instance_, ENABLE);
206 return ErrorCode::OK;
210ErrorCode CH32UART::WriteFun(
WritePort &port)
216 if (port.queue_info_->Peek(info) != ErrorCode::OK)
218 return ErrorCode::EMPTY;
221 uint8_t *buffer =
nullptr;
222 bool use_pending =
false;
225 bool dma_ready = uart->dma_tx_channel_->CNTR == 0;
228 buffer =
reinterpret_cast<uint8_t *
>(uart->dma_buff_tx_.
ActiveBuffer());
232 buffer =
reinterpret_cast<uint8_t *
>(uart->dma_buff_tx_.
PendingBuffer());
236 if (port.queue_data_->
PopBatch(buffer, info.data.
size_) != ErrorCode::OK)
239 return ErrorCode::EMPTY;
247 bool dma_ready = uart->dma_tx_channel_->CNTR == 0;
248 if (dma_ready && uart->dma_buff_tx_.
HasPending())
250 uart->dma_buff_tx_.
Switch();
254 return ErrorCode::FAILED;
258 port.queue_info_->Pop(uart->write_info_active_);
260 DMA_Cmd(uart->dma_tx_channel_, DISABLE);
261 uart->dma_tx_channel_->MADDR =
262 reinterpret_cast<uint32_t
>(uart->dma_buff_tx_.
ActiveBuffer());
263 uart->dma_tx_channel_->CNTR = info.data.
size_;
264 uart->_write_port.write_size_ = info.data.
size_;
265 DMA_Cmd(uart->dma_tx_channel_, ENABLE);
267 uart->write_info_active_.op.
UpdateStatus(
false, ErrorCode::OK);
269 return ErrorCode::FAILED;
271 return ErrorCode::FAILED;
275ErrorCode CH32UART::ReadFun(
ReadPort &port)
279 return ErrorCode::EMPTY;
284 auto rx_buf =
static_cast<uint8_t *
>(uart->dma_buff_rx_.
addr_);
285 size_t dma_size = uart->dma_buff_rx_.
size_;
286 size_t curr_pos = dma_size - uart->dma_rx_channel_->CNTR;
287 size_t last_pos = uart->last_rx_pos_;
289 if (curr_pos != last_pos)
291 if (curr_pos > last_pos)
294 uart->_read_port.queue_data_->
PushBatch(&rx_buf[last_pos], curr_pos - last_pos);
299 uart->_read_port.queue_data_->
PushBatch(&rx_buf[last_pos], dma_size - last_pos);
300 uart->_read_port.queue_data_->
PushBatch(&rx_buf[0], curr_pos);
302 uart->last_rx_pos_ = curr_pos;
308extern "C" void CH32_UART_ISR_Handler_IDLE(ch32_uart_id_t
id)
310 auto uart = CH32UART::map[id];
317 if (!USART_GetITStatus(uart->instance_, USART_IT_IDLE))
322 USART_ReceiveData(uart->instance_);
324 CH32_UART_RX_ISR_Handler(uart);
328extern "C" void CH32_UART_ISR_Handler_TX_CPLT(ch32_uart_id_t
id)
330 auto uart = CH32UART::map[id];
336 DMA_ClearITPendingBit(CH32_UART_TX_DMA_IT_MAP[
id]);
340 if (pending_len == 0)
345 uart->dma_buff_tx_.
Switch();
347 auto *buf =
reinterpret_cast<uint8_t *
>(uart->dma_buff_tx_.
ActiveBuffer());
348 DMA_Cmd(uart->dma_tx_channel_, DISABLE);
349 uart->dma_tx_channel_->MADDR = (uint32_t)buf;
350 uart->dma_tx_channel_->CNTR = pending_len;
351 uart->_write_port.write_size_ = pending_len;
352 DMA_Cmd(uart->dma_tx_channel_, ENABLE);
357 if (uart->_write_port.queue_info_->Pop(current_info) != ErrorCode::OK)
367 if (uart->
write_port_->queue_info_->Peek(next_info) != ErrorCode::OK)
373 reinterpret_cast<uint8_t *
>(uart->dma_buff_tx_.
PendingBuffer()),
374 next_info.data.
size_) != ErrorCode::OK)
386void CH32UART::TxDmaIRQHandler(DMA_Channel_TypeDef *channel, ch32_uart_id_t
id)
388 if (DMA_GetITStatus(CH32_UART_TX_DMA_IT_MAP[
id]) == RESET)
return;
390 if (channel->CNTR == 0) CH32_UART_ISR_Handler_TX_CPLT(
id);
393void CH32UART::RxDmaIRQHandler(DMA_Channel_TypeDef *channel, ch32_uart_id_t
id)
396 auto uart = CH32UART::map[id];
399 if (DMA_GetITStatus(CH32_UART_RX_DMA_IT_HT_MAP[
id]) == SET)
401 DMA_ClearITPendingBit(CH32_UART_RX_DMA_IT_HT_MAP[
id]);
402 CH32_UART_RX_ISR_Handler(uart);
405 if (DMA_GetITStatus(CH32_UART_RX_DMA_IT_TC_MAP[
id]) == SET)
407 DMA_ClearITPendingBit(CH32_UART_RX_DMA_IT_TC_MAP[
id]);
408 CH32_UART_RX_ISR_Handler(uart);
414extern "C" void USART1_IRQHandler(
void) __attribute__((interrupt));
415extern "C" void USART1_IRQHandler(
void) { CH32_UART_ISR_Handler_IDLE(CH32_USART1); }
418extern "C" void USART2_IRQHandler(
void) __attribute__((interrupt));
419extern "C" void USART2_IRQHandler(
void) { CH32_UART_ISR_Handler_IDLE(CH32_USART2); }
422extern "C" void USART3_IRQHandler(
void) __attribute__((interrupt));
423extern "C" void USART3_IRQHandler(
void) { CH32_UART_ISR_Handler_IDLE(CH32_USART3); }
426extern "C" void USART4_IRQHandler(
void) __attribute__((interrupt));
427extern "C" void USART4_IRQHandler(
void) { CH32_UART_ISR_Handler_IDLE(CH32_USART4); }
430extern "C" void USART5_IRQHandler(
void) __attribute__((interrupt));
431extern "C" void USART5_IRQHandler(
void) { CH32_UART_ISR_Handler_IDLE(CH32_USART5); }
434extern "C" void USART6_IRQHandler(
void) __attribute__((interrupt));
435extern "C" void USART6_IRQHandler(
void) { CH32_UART_ISR_Handler_IDLE(CH32_USART6); }
438extern "C" void USART7_IRQHandler(
void) __attribute__((interrupt));
439extern "C" void USART7_IRQHandler(
void) { CH32_UART_ISR_Handler_IDLE(CH32_USART7); }
442extern "C" void USART8_IRQHandler(
void) __attribute__((interrupt));
443extern "C" void USART8_IRQHandler(
void) { CH32_UART_ISR_Handler_IDLE(CH32_USART8); }
446extern "C" void UART1_IRQHandler(
void) __attribute__((interrupt));
447extern "C" void UART1_IRQHandler(
void) { CH32_UART_ISR_Handler_IDLE(CH32_UART1); }
450extern "C" void UART2_IRQHandler(
void) __attribute__((interrupt));
451extern "C" void UART2_IRQHandler(
void) { CH32_UART_ISR_Handler_IDLE(CH32_UART2); }
454extern "C" void UART3_IRQHandler(
void) __attribute__((interrupt));
455extern "C" void UART3_IRQHandler(
void) { CH32_UART_ISR_Handler_IDLE(CH32_UART3); }
458extern "C" void UART4_IRQHandler(
void) __attribute__((interrupt));
459extern "C" void UART4_IRQHandler(
void) { CH32_UART_ISR_Handler_IDLE(CH32_UART4); }
462extern "C" void UART5_IRQHandler(
void) __attribute__((interrupt));
463extern "C" void UART5_IRQHandler(
void) { CH32_UART_ISR_Handler_IDLE(CH32_UART5); }
466extern "C" void UART6_IRQHandler(
void) __attribute__((interrupt));
467extern "C" void UART6_IRQHandler(
void) { CH32_UART_ISR_Handler_IDLE(CH32_UART6); }
470extern "C" void UART7_IRQHandler(
void) __attribute__((interrupt));
471extern "C" void UART7_IRQHandler(
void) { CH32_UART_ISR_Handler_IDLE(CH32_UART7); }
474extern "C" void UART8_IRQHandler(
void) __attribute__((interrupt));
475extern "C" void UART8_IRQHandler(
void) { CH32_UART_ISR_Handler_IDLE(CH32_UART8); }
ErrorCode SetConfig(UART::Configuration config)
设置 UART 配置 / Sets the UART configuration
size_t size_
数据大小(字节)。 The size of the data (in bytes).
uint8_t * PendingBuffer()
获取备用缓冲区的指针 Returns the pending (inactive) buffer
void EnablePending()
手动启用 pending 状态 Manually sets the pending state to true
bool HasPending() const
判断是否有待切换的缓冲区 Checks whether a pending buffer is ready
void SetPendingLength(size_t size)
设置备用缓冲区的数据长度 Sets the size of the pending buffer
void Switch()
切换到备用缓冲区(若其有效) Switches to the pending buffer if it's valid
uint8_t * ActiveBuffer()
获取当前正在使用的缓冲区指针 Returns the currently active buffer
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
void UpdateStatus(bool in_isr, Status &&...status)
Updates operation status based on type.
原始数据封装类。 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.
通用异步收发传输(UART)基类 / Abstract base class for Universal Asynchronous Receiver-Transmitter (UART)
@ NO_PARITY
无校验 / No parity
WritePort * write_port_
写入端口 / Write port
WritePort class for handling write operations.
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