4#include "ch32_uart.hpp"
7#include "ch32_gpio.hpp"
12CH32UART* CH32UART::map_[ch32_uart_id_t::CH32_UART_NUMBER] = {
nullptr};
16 GPIO_TypeDef* tx_gpio_port, uint16_t tx_gpio_pin,
17 GPIO_TypeDef* rx_gpio_port, uint16_t rx_gpio_pin, uint32_t pin_remap,
19 :
UART(&_read_port, &_write_port),
21 _read_port(dma_rx.size_),
22 _write_port(tx_queue_size, dma_tx.size_ / 2),
23 requested_config_(config),
24 rx_dma_model_(dma_rx),
25 tx_dma_model_(*this, _write_port, dma_tx),
26 instance_(ch32_uart_get_instance_id(id)),
27 dma_rx_channel_(CH32_UART_RX_DMA_CHANNEL_MAP[id]),
28 dma_tx_channel_(CH32_UART_TX_DMA_CHANNEL_MAP[id])
32 bool tx_enable = dma_tx.
size_ > 1;
33 bool rx_enable = dma_rx.
size_ > 0;
35 ASSERT(tx_enable || rx_enable);
38 ASSERT(dma_tx_channel_ !=
nullptr);
39 ASSERT(CH32_UART_TX_DMA_IT_MAP[
id] != 0);
43 ASSERT(dma_rx_channel_ !=
nullptr);
44 ASSERT(CH32_UART_RX_DMA_IT_TC_MAP[
id] != 0);
45 ASSERT(CH32_UART_RX_DMA_IT_HT_MAP[
id] != 0);
49 GPIO_InitTypeDef gpio_init = {};
50 gpio_init.GPIO_Speed = GPIO_Speed_50MHz;
54 RCC_APB2PeriphClockCmd(ch32_get_gpio_periph(tx_gpio_port), ENABLE);
55 gpio_init.GPIO_Pin = tx_gpio_pin;
56 gpio_init.GPIO_Mode = GPIO_Mode_AF_PP;
57 GPIO_Init(tx_gpio_port, &gpio_init);
63 RCC_APB2PeriphClockCmd(ch32_get_gpio_periph(rx_gpio_port), ENABLE);
64 gpio_init.GPIO_Pin = rx_gpio_pin;
65 gpio_init.GPIO_Mode = GPIO_Mode_IN_FLOATING;
66 GPIO_Init(rx_gpio_port, &gpio_init);
73 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
74 GPIO_PinRemapConfig(pin_remap, ENABLE);
78 if (CH32_UART_APB_MAP[
id] == 1)
80 RCC_APB1PeriphClockCmd(CH32_UART_RCC_PERIPH_MAP[
id], ENABLE);
82 else if (CH32_UART_APB_MAP[
id] == 2)
84 RCC_APB2PeriphClockCmd(CH32_UART_RCC_PERIPH_MAP[
id], ENABLE);
90 RCC_AHBPeriphClockCmd(CH32_UART_RCC_PERIPH_MAP_DMA[
id], ENABLE);
93 USART_InitTypeDef usart_cfg = {};
94 usart_cfg.USART_BaudRate = config.
baudrate;
95 usart_cfg.USART_StopBits =
96 (config.
stop_bits == 2) ? USART_StopBits_2 : USART_StopBits_1;
100 usart_cfg.USART_Parity = USART_Parity_No;
101 usart_cfg.USART_WordLength = USART_WordLength_8b;
104 usart_cfg.USART_Parity = USART_Parity_Even;
105 usart_cfg.USART_WordLength = USART_WordLength_9b;
108 usart_cfg.USART_Parity = USART_Parity_Odd;
109 usart_cfg.USART_WordLength = USART_WordLength_9b;
115 usart_cfg.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
116 usart_cfg.USART_Mode =
117 (tx_enable ? USART_Mode_Tx : 0) | (rx_enable ? USART_Mode_Rx : 0);
118 uart_mode_ = usart_cfg.USART_Mode;
119 USART_Init(instance_, &usart_cfg);
122 DMA_InitTypeDef dma_init = {};
123 dma_init.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
124 dma_init.DMA_MemoryInc = DMA_MemoryInc_Enable;
125 dma_init.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
126 dma_init.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
127 dma_init.DMA_Priority = DMA_Priority_High;
128 dma_init.DMA_M2M = DMA_M2M_Disable;
132 ch32_dma_callback_t rx_cb_fun = [](
void* arg)
135 ch32_dma_register_callback(ch32_dma_get_id(CH32_UART_RX_DMA_CHANNEL_MAP[
id]),
138 DMA_DeInit(dma_rx_channel_);
139 dma_init.DMA_PeripheralBaseAddr = (uint32_t)&instance_->DATAR;
140 dma_init.DMA_MemoryBaseAddr = (uint32_t)rx_dma_model_.
Buffer();
141 dma_init.DMA_DIR = DMA_DIR_PeripheralSRC;
142 dma_init.DMA_Mode = DMA_Mode_Circular;
143 dma_init.DMA_BufferSize = rx_dma_model_.
BufferSize();
144 DMA_Init(dma_rx_channel_, &dma_init);
145 rx_dma_model_.
Start(*
this);
146 DMA_ITConfig(dma_rx_channel_, DMA_IT_TC, ENABLE);
147 DMA_ITConfig(dma_rx_channel_, DMA_IT_HT, ENABLE);
148 USART_DMACmd(instance_, USART_DMAReq_Rx, ENABLE);
153 ch32_dma_callback_t tx_cb_fun = [](
void* arg)
154 {
reinterpret_cast<CH32UART*
>(arg)->TxDmaIRQHandler(); };
156 ch32_dma_register_callback(ch32_dma_get_id(CH32_UART_TX_DMA_CHANNEL_MAP[
id]),
158 DMA_DeInit(dma_tx_channel_);
159 dma_init.DMA_PeripheralBaseAddr = (u32)(&instance_->DATAR);
160 dma_init.DMA_MemoryBaseAddr = 0;
161 dma_init.DMA_DIR = DMA_DIR_PeripheralDST;
162 dma_init.DMA_Mode = DMA_Mode_Normal;
163 dma_init.DMA_BufferSize = 0;
164 DMA_Init(dma_tx_channel_, &dma_init);
165 DMA_ITConfig(dma_tx_channel_, DMA_IT_TC, ENABLE);
166 USART_DMACmd(instance_, USART_DMAReq_Tx, ENABLE);
170 USART_Cmd(instance_, ENABLE);
174 USART_ITConfig(instance_, USART_IT_IDLE, ENABLE);
175 NVIC_EnableIRQ(CH32_DMA_IRQ_MAP[ch32_dma_get_id(dma_rx_channel_)]);
180 NVIC_EnableIRQ(CH32_DMA_IRQ_MAP[ch32_dma_get_id(dma_tx_channel_)]);
183 NVIC_EnableIRQ(CH32_UART_IRQ_MAP[
id]);
199 requested_config_.Store(config);
200 tx_dma_model_.RequestConfig(
false);
204bool CH32UART::ApplyPendingConfig(
bool in_isr)
207 if (!rx_config_gate_.TryEnterConfig())
213 (void)requested_config_.LoadLatest(config);
215 if (uart_mode_ & USART_Mode_Tx)
217 USART_DMACmd(instance_, USART_DMAReq_Tx, DISABLE);
218 DMA_Cmd(dma_tx_channel_, DISABLE);
219 DMA_ClearITPendingBit(CH32_UART_TX_DMA_IT_MAP[id_]);
221 if (uart_mode_ & USART_Mode_Rx)
223 USART_DMACmd(instance_, USART_DMAReq_Rx, DISABLE);
224 DMA_Cmd(dma_rx_channel_, DISABLE);
225 DMA_ClearITPendingBit(CH32_UART_RX_DMA_IT_HT_MAP[id_]);
226 DMA_ClearITPendingBit(CH32_UART_RX_DMA_IT_TC_MAP[id_]);
229 USART_InitTypeDef usart_cfg = {};
230 usart_cfg.USART_BaudRate = config.baudrate;
231 usart_cfg.USART_StopBits =
232 (config.stop_bits == 2) ? USART_StopBits_2 : USART_StopBits_1;
234 switch (config.parity)
237 usart_cfg.USART_Parity = USART_Parity_No;
238 usart_cfg.USART_WordLength = USART_WordLength_8b;
241 usart_cfg.USART_Parity = USART_Parity_Even;
242 usart_cfg.USART_WordLength = USART_WordLength_9b;
245 usart_cfg.USART_Parity = USART_Parity_Odd;
246 usart_cfg.USART_WordLength = USART_WordLength_9b;
253 usart_cfg.USART_Mode = uart_mode_;
254 usart_cfg.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
255 USART_DeInit(instance_);
256 USART_Init(instance_, &usart_cfg);
258 if (uart_mode_ & USART_Mode_Rx)
260 rx_dma_model_.
Start(*
this);
261 USART_DMACmd(instance_, USART_DMAReq_Rx, ENABLE);
262 USART_ITConfig(instance_, USART_IT_IDLE, ENABLE);
265 if (uart_mode_ & USART_Mode_Tx)
267 USART_DMACmd(instance_, USART_DMAReq_Tx, ENABLE);
270 USART_Cmd(instance_, ENABLE);
278 return uart->tx_dma_model_.Submit(in_isr);
283 DMA_Cmd(dma_tx_channel_, DISABLE);
284 dma_tx_channel_->MADDR =
reinterpret_cast<uint32_t
>(data);
285 dma_tx_channel_->CNTR = size;
286 DMA_Cmd(dma_tx_channel_, ENABLE);
297void ch32_uart_rx_isr_handler(
LibXR::CH32UART* uart) { uart->OnRxDataAvailable(
true); }
299void CH32UART::OnRxDataAvailable(
bool in_isr)
301 if (!rx_config_gate_.TryEnterRx())
309 tx_dma_model_.RequestConfig(in_isr);
314extern "C" void ch32_uart_isr_handler_idle(ch32_uart_id_t
id)
316 auto uart = CH32UART::map_[id];
323 if (!USART_GetITStatus(uart->instance_, USART_IT_IDLE))
328 USART_ReceiveData(uart->instance_);
330 ch32_uart_rx_isr_handler(uart);
334extern "C" void ch32_uart_isr_handler_tx_cplt(
CH32UART* uart)
336 DMA_ClearITPendingBit(CH32_UART_TX_DMA_IT_MAP[uart->id_]);
337 uart->tx_dma_model_.OnTransferDone(
true);
341void CH32UART::TxDmaIRQHandler()
343 if (DMA_GetITStatus(CH32_UART_TX_DMA_IT_MAP[id_]) == RESET)
348 if (dma_tx_channel_->CNTR == 0)
350 ch32_uart_isr_handler_tx_cplt(
this);
364 if (DMA_GetITStatus(CH32_UART_RX_DMA_IT_HT_MAP[id_]) == SET)
366 DMA_ClearITPendingBit(CH32_UART_RX_DMA_IT_HT_MAP[id_]);
367 ch32_uart_rx_isr_handler(
this);
370 if (DMA_GetITStatus(CH32_UART_RX_DMA_IT_TC_MAP[id_]) == SET)
372 DMA_ClearITPendingBit(CH32_UART_RX_DMA_IT_TC_MAP[id_]);
373 ch32_uart_rx_isr_handler(
this);
380extern "C" void USART1_IRQHandler(
void) __attribute__((interrupt(
"WCH-Interrupt-fast")));
382extern "C" void USART1_IRQHandler(
void) { ch32_uart_isr_handler_idle(CH32_USART1); }
386extern "C" void USART2_IRQHandler(
void) __attribute__((interrupt(
"WCH-Interrupt-fast")));
388extern "C" void USART2_IRQHandler(
void) { ch32_uart_isr_handler_idle(CH32_USART2); }
392extern "C" void USART3_IRQHandler(
void) __attribute__((interrupt(
"WCH-Interrupt-fast")));
394extern "C" void USART3_IRQHandler(
void) { ch32_uart_isr_handler_idle(CH32_USART3); }
398extern "C" void USART4_IRQHandler(
void) __attribute__((interrupt(
"WCH-Interrupt-fast")));
400extern "C" void USART4_IRQHandler(
void) { ch32_uart_isr_handler_idle(CH32_USART4); }
404extern "C" void USART5_IRQHandler(
void) __attribute__((interrupt(
"WCH-Interrupt-fast")));
406extern "C" void USART5_IRQHandler(
void) { ch32_uart_isr_handler_idle(CH32_USART5); }
410extern "C" void USART6_IRQHandler(
void) __attribute__((interrupt(
"WCH-Interrupt-fast")));
412extern "C" void USART6_IRQHandler(
void) { ch32_uart_isr_handler_idle(CH32_USART6); }
416extern "C" void USART7_IRQHandler(
void) __attribute__((interrupt(
"WCH-Interrupt-fast")));
418extern "C" void USART7_IRQHandler(
void) { ch32_uart_isr_handler_idle(CH32_USART7); }
422extern "C" void USART8_IRQHandler(
void) __attribute__((interrupt(
"WCH-Interrupt-fast")));
424extern "C" void USART8_IRQHandler(
void) { ch32_uart_isr_handler_idle(CH32_USART8); }
428extern "C" void UART1_IRQHandler(
void) __attribute__((interrupt(
"WCH-Interrupt-fast")));
430extern "C" void UART1_IRQHandler(
void) { ch32_uart_isr_handler_idle(CH32_UART1); }
434extern "C" void UART2_IRQHandler(
void) __attribute__((interrupt(
"WCH-Interrupt-fast")));
436extern "C" void UART2_IRQHandler(
void) { ch32_uart_isr_handler_idle(CH32_UART2); }
440extern "C" void UART3_IRQHandler(
void) __attribute__((interrupt(
"WCH-Interrupt-fast")));
442extern "C" void UART3_IRQHandler(
void) { ch32_uart_isr_handler_idle(CH32_UART3); }
446extern "C" void UART4_IRQHandler(
void) __attribute__((interrupt(
"WCH-Interrupt-fast")));
448extern "C" void UART4_IRQHandler(
void) { ch32_uart_isr_handler_idle(CH32_UART4); }
452extern "C" void UART5_IRQHandler(
void) __attribute__((interrupt(
"WCH-Interrupt-fast")));
454extern "C" void UART5_IRQHandler(
void) { ch32_uart_isr_handler_idle(CH32_UART5); }
458extern "C" void UART6_IRQHandler(
void) __attribute__((interrupt(
"WCH-Interrupt-fast")));
460extern "C" void UART6_IRQHandler(
void) { ch32_uart_isr_handler_idle(CH32_UART6); }
464extern "C" void UART7_IRQHandler(
void) __attribute__((interrupt(
"WCH-Interrupt-fast")));
466extern "C" void UART7_IRQHandler(
void) { ch32_uart_isr_handler_idle(CH32_UART7); }
470extern "C" void UART8_IRQHandler(
void) __attribute__((interrupt(
"WCH-Interrupt-fast")));
472extern "C" void UART8_IRQHandler(
void) { ch32_uart_isr_handler_idle(CH32_UART8); }
CH32 UART 驱动实现 / CH32 UART driver implementation.
void RxDmaIRQHandler()
DMA中断处理函数
ErrorCode SetConfig(UART::Configuration config)
设置 UART 配置 / Sets the UART configuration
bool StartDmaTx(uint8_t *data, size_t size, int block)
配置并启动一个 active UART TX DMA 载荷 / Configure and start one active UART TX DMA payload
CH32UART(ch32_uart_id_t id, RawData dma_rx, RawData dma_tx, GPIO_TypeDef *tx_gpio_port, uint16_t tx_gpio_pin, GPIO_TypeDef *rx_gpio_port, uint16_t rx_gpio_pin, uint32_t pin_remap=0, uint32_t tx_queue_size=5, UART::Configuration config={115200, UART::Parity::NO_PARITY, 8, 1})
构造 UART 对象 / Construct UART object
可写原始数据视图 / Mutable raw data view
size_t size_
数据字节数 / Data size in bytes
ReadPort class for handling read operations.
通用异步收发传输(UART)基类 / Abstract base class for Universal Asynchronous Receiver-Transmitter (UART)
@ NO_PARITY
无校验 / No parity
uint8_t * Buffer() const
获取 DMA 可写缓冲区起始地址 / Get the DMA-writable buffer start address
size_t BufferSize() const
获取循环 DMA 缓冲区容量 / Get the circular DMA buffer capacity
void OnDataAvailable(Backend &backend, ReadPort &port, bool in_isr)
消费上次 DMA 事件后新产生的数据 / Consume bytes produced since the previous DMA event
void Start(Backend &backend)
复位读取位置并启动循环 DMA / Reset the read position and start circular DMA
WritePort class for handling write operations.
@ OK
操作成功 | Operation successful
@ ARG_ERR
参数错误 | Argument error
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
通过成员指针恢复其所属对象指针
UART 配置结构体 / UART configuration structure.
uint8_t stop_bits
停止位长度 / Number of stop bits
Parity parity
校验模式 / Parity mode
uint32_t baudrate
波特率 / Baud rate