19 :
UART(&_read_port, &_write_port),
20 id_(id),
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])
29{
30 map_[id] = this;
31
32 bool tx_enable = dma_tx.
size_ > 1;
33 bool rx_enable = dma_rx.
size_ > 0;
34
35 ASSERT(tx_enable || rx_enable);
36 if (tx_enable)
37 {
38 ASSERT(dma_tx_channel_ != nullptr);
39 ASSERT(CH32_UART_TX_DMA_IT_MAP[id] != 0);
40 }
41 if (rx_enable)
42 {
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);
46 }
47
48
49 GPIO_InitTypeDef gpio_init = {};
50 gpio_init.GPIO_Speed = GPIO_Speed_50MHz;
51
52 if (tx_enable)
53 {
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);
59 }
60
61 if (rx_enable)
62 {
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);
68 }
69
70
71 if (pin_remap != 0)
72 {
73 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
74 GPIO_PinRemapConfig(pin_remap, ENABLE);
75 }
76
77
78 if (CH32_UART_APB_MAP[id] == 1)
79 {
80 RCC_APB1PeriphClockCmd(CH32_UART_RCC_PERIPH_MAP[id], ENABLE);
81 }
82 else if (CH32_UART_APB_MAP[id] == 2)
83 {
84 RCC_APB2PeriphClockCmd(CH32_UART_RCC_PERIPH_MAP[id], ENABLE);
85 }
86 else
87 {
88 ASSERT(false);
89 }
90 RCC_AHBPeriphClockCmd(CH32_UART_RCC_PERIPH_MAP_DMA[id], ENABLE);
91
92
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;
98 {
100 usart_cfg.USART_Parity = USART_Parity_No;
101 usart_cfg.USART_WordLength = USART_WordLength_8b;
102 break;
104 usart_cfg.USART_Parity = USART_Parity_Even;
105 usart_cfg.USART_WordLength = USART_WordLength_9b;
106 break;
108 usart_cfg.USART_Parity = USART_Parity_Odd;
109 usart_cfg.USART_WordLength = USART_WordLength_9b;
110 break;
111 default:
112 ASSERT(false);
113 }
114
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);
120
121
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;
129
130 if (rx_enable)
131 {
132 ch32_dma_callback_t rx_cb_fun = [](void* arg)
134
135 ch32_dma_register_callback(ch32_dma_get_id(CH32_UART_RX_DMA_CHANNEL_MAP[id]),
136 rx_cb_fun, this);
137
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);
149 }
150
151 if (tx_enable)
152 {
153 ch32_dma_callback_t tx_cb_fun = [](void* arg)
154 {
reinterpret_cast<CH32UART*
>(arg)->TxDmaIRQHandler(); };
155
156 ch32_dma_register_callback(ch32_dma_get_id(CH32_UART_TX_DMA_CHANNEL_MAP[id]),
157 tx_cb_fun, this);
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);
167 }
168
169
170 USART_Cmd(instance_, ENABLE);
171
172 if (rx_enable)
173 {
174 USART_ITConfig(instance_, USART_IT_IDLE, ENABLE);
175 NVIC_EnableIRQ(CH32_DMA_IRQ_MAP[ch32_dma_get_id(dma_rx_channel_)]);
176 }
177
178 if (tx_enable)
179 {
180 NVIC_EnableIRQ(CH32_DMA_IRQ_MAP[ch32_dma_get_id(dma_tx_channel_)]);
181 }
182
183 NVIC_EnableIRQ(CH32_UART_IRQ_MAP[id]);
184}
CH32 UART 驱动实现 / CH32 UART driver implementation.
void RxDmaIRQHandler()
DMA中断处理函数
size_t size_
数据字节数 / Data size in bytes
@ NO_PARITY
无校验 / No parity
UART(ReadPortType *read_port, WritePortType *write_port)
UART 构造函数 / UART constructor.
uint8_t * Buffer() const
获取 DMA 可写缓冲区起始地址 / Get the DMA-writable buffer start address
size_t BufferSize() const
获取循环 DMA 缓冲区容量 / Get the circular DMA buffer capacity
void Start(Backend &backend)
复位读取位置并启动循环 DMA / Reset the read position and start circular DMA
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.
uint8_t stop_bits
停止位长度 / Number of stop bits
Parity parity
校验模式 / Parity mode
uint32_t baudrate
波特率 / Baud rate