libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
ch32_uart.cpp
1// ch32_uart.cpp
2
3#include "ch32_uart.hpp"
4
5#include "ch32_dma.hpp"
6#include "ch32_gpio.hpp"
7
8using namespace LibXR;
9
10// === 静态对象指针表 ===
11CH32UART *CH32UART::map[ch32_uart_id_t::CH32_UART_NUMBER] = {nullptr};
12
13// === 构造函数:串口+DMA+GPIO初始化 ===
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,
17 uint32_t tx_queue_size, UART::Configuration config)
18 : UART(&_read_port, &_write_port),
19 id_(id),
20 _read_port(dma_rx.size_),
21 _write_port(tx_queue_size, dma_tx.size_ / 2),
22 dma_buff_rx_(dma_rx),
23 dma_buff_tx_(dma_tx),
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])
27{
28 map[id] = this;
29
30 bool tx_enable = dma_tx.size_ > 1;
31 bool rx_enable = dma_rx.size_ > 0;
32
33 ASSERT(tx_enable || rx_enable);
34
35 /* GPIO配置(TX: 推挽输出,RX: 悬空输入) */
36 GPIO_InitTypeDef gpio_init = {};
37 gpio_init.GPIO_Speed = GPIO_Speed_50MHz;
38
39 if (tx_enable)
40 {
41 RCC_APB2PeriphClockCmd(CH32GetGPIOPeriph(tx_gpio_port), ENABLE);
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 (*write_port_) = WriteFun;
46 }
47
48 if (rx_enable)
49 {
50 RCC_APB2PeriphClockCmd(CH32GetGPIOPeriph(rx_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 (*read_port_) = ReadFun;
55 }
56
57 /* 可选:引脚重映射 */
58 if (pin_remap != 0)
59 {
60 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
61 GPIO_PinRemapConfig(pin_remap, ENABLE);
62 }
63
64 /* 串口外设时钟使能 */
65 if (CH32_UART_APB_MAP[id] == 1)
66 {
67 RCC_APB1PeriphClockCmd(CH32_UART_RCC_PERIPH_MAP[id], ENABLE);
68 }
69 else if (CH32_UART_APB_MAP[id] == 2)
70 {
71 RCC_APB2PeriphClockCmd(CH32_UART_RCC_PERIPH_MAP[id], ENABLE);
72 }
73 else
74 {
75 ASSERT(false);
76 }
77 RCC_AHBPeriphClockCmd(CH32_UART_RCC_PERIPH_MAP_DMA[id], ENABLE);
78
79 // 3. USART 配置
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;
84 switch (config.parity)
85 {
86 case UART::Parity::NO_PARITY:
87 usart_cfg.USART_Parity = USART_Parity_No;
88 usart_cfg.USART_WordLength = USART_WordLength_8b;
89 break;
90 case UART::Parity::EVEN:
91 usart_cfg.USART_Parity = USART_Parity_Even;
92 usart_cfg.USART_WordLength = USART_WordLength_9b;
93 break;
94 case UART::Parity::ODD:
95 usart_cfg.USART_Parity = USART_Parity_Odd;
96 usart_cfg.USART_WordLength = USART_WordLength_9b;
97 break;
98 default:
99 ASSERT(false);
100 }
101
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);
107
108 /* DMA 配置 */
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;
116
117 if (rx_enable)
118 {
119 ch32_dma_callback_t rx_cb_fun = [](void *arg)
120 { reinterpret_cast<CH32UART *>(arg)->RxDmaIRQHandler(); };
121
122 CH32_DMA_RegisterCallback(CH32_DMA_GetID(CH32_UART_RX_DMA_CHANNEL_MAP[id]), rx_cb_fun,
123 this);
124
125 DMA_DeInit(dma_rx_channel_);
126 dma_init.DMA_PeripheralBaseAddr = (uint32_t)&instance_->DATAR;
127 dma_init.DMA_MemoryBaseAddr = (uint32_t)dma_buff_rx_.addr_;
128 dma_init.DMA_DIR = DMA_DIR_PeripheralSRC;
129 dma_init.DMA_Mode = DMA_Mode_Circular;
130 dma_init.DMA_BufferSize = dma_buff_rx_.size_;
131 DMA_Init(dma_rx_channel_, &dma_init);
132 DMA_Cmd(dma_rx_channel_, ENABLE);
133 DMA_ITConfig(dma_rx_channel_, DMA_IT_TC, ENABLE);
134 DMA_ITConfig(dma_rx_channel_, DMA_IT_HT, ENABLE);
135 USART_DMACmd(instance_, USART_DMAReq_Rx, ENABLE);
136 }
137
138 if (tx_enable)
139 {
140 ch32_dma_callback_t tx_cb_fun = [](void *arg)
141 { reinterpret_cast<CH32UART *>(arg)->TxDmaIRQHandler(); };
142
143 CH32_DMA_RegisterCallback(CH32_DMA_GetID(CH32_UART_TX_DMA_CHANNEL_MAP[id]), tx_cb_fun,
144 this);
145 DMA_DeInit(dma_tx_channel_);
146 dma_init.DMA_PeripheralBaseAddr = (u32)(&instance_->DATAR);
147 dma_init.DMA_MemoryBaseAddr = 0;
148 dma_init.DMA_DIR = DMA_DIR_PeripheralDST;
149 dma_init.DMA_Mode = DMA_Mode_Normal;
150 dma_init.DMA_BufferSize = 0;
151 DMA_Init(dma_tx_channel_, &dma_init);
152 DMA_ITConfig(dma_tx_channel_, DMA_IT_TC, ENABLE);
153 USART_DMACmd(instance_, USART_DMAReq_Tx, ENABLE);
154 }
155
156 // 6. USART和相关中断
157 USART_Cmd(instance_, ENABLE);
158
159 if (rx_enable)
160 {
161 USART_ITConfig(instance_, USART_IT_IDLE, ENABLE);
162 NVIC_EnableIRQ(CH32_DMA_IRQ_MAP[CH32_DMA_GetID(dma_rx_channel_)]);
163 }
164
165 if (tx_enable)
166 {
167 NVIC_EnableIRQ(CH32_DMA_IRQ_MAP[CH32_DMA_GetID(dma_tx_channel_)]);
168 }
169
170 NVIC_EnableIRQ(CH32_UART_IRQ_MAP[id]);
171}
172
173// === 串口运行时配置变更 ===
175{
176 USART_InitTypeDef usart_cfg = {};
177 usart_cfg.USART_BaudRate = config.baudrate;
178 usart_cfg.USART_StopBits =
179 (config.stop_bits == 2) ? USART_StopBits_2 : USART_StopBits_1;
180
181 switch (config.parity)
182 {
184 usart_cfg.USART_Parity = USART_Parity_No;
185 usart_cfg.USART_WordLength = USART_WordLength_8b;
186 break;
188 usart_cfg.USART_Parity = USART_Parity_Even;
189 usart_cfg.USART_WordLength = USART_WordLength_9b;
190 break;
192 usart_cfg.USART_Parity = USART_Parity_Odd;
193 usart_cfg.USART_WordLength = USART_WordLength_9b;
194 break;
195 default:
196 return ErrorCode::NOT_SUPPORT;
197 }
198
199 usart_cfg.USART_Mode = uart_mode_;
200 usart_cfg.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
201 USART_DeInit(instance_);
202 USART_Init(instance_, &usart_cfg);
203
204 if (uart_mode_ & USART_Mode_Rx)
205 {
206 USART_DMACmd(instance_, USART_DMAReq_Rx, ENABLE);
207 USART_ITConfig(instance_, USART_IT_IDLE, ENABLE);
208 }
209
210 if (uart_mode_ & USART_Mode_Tx)
211 {
212 USART_DMACmd(instance_, USART_DMAReq_Tx, ENABLE);
213 }
214
215 USART_Cmd(instance_, ENABLE);
216
217 return ErrorCode::OK;
218}
219
220// === 写操作回调(DMA搬运) ===
221ErrorCode CH32UART::WriteFun(WritePort &port)
222{
223 CH32UART *uart = CONTAINER_OF(&port, CH32UART, _write_port);
224 if (!uart->dma_buff_tx_.HasPending())
225 {
226 WriteInfoBlock info;
227 if (port.queue_info_->Peek(info) != ErrorCode::OK)
228 {
229 return ErrorCode::EMPTY;
230 }
231
232 uint8_t *buffer = nullptr;
233 bool use_pending = false;
234
235 // DMA空闲判断
236 bool dma_ready = uart->dma_tx_channel_->CNTR == 0;
237 if (dma_ready)
238 {
239 buffer = reinterpret_cast<uint8_t *>(uart->dma_buff_tx_.ActiveBuffer());
240 }
241 else
242 {
243 buffer = reinterpret_cast<uint8_t *>(uart->dma_buff_tx_.PendingBuffer());
244 use_pending = true;
245 }
246
247 if (port.queue_data_->PopBatch(buffer, info.data.size_) != ErrorCode::OK)
248 {
249 ASSERT(false);
250 return ErrorCode::EMPTY;
251 }
252
253 if (use_pending)
254 {
255 uart->dma_buff_tx_.SetPendingLength(info.data.size_);
256 uart->dma_buff_tx_.EnablePending();
257 // 检查当前DMA是否可切换
258 bool dma_ready = uart->dma_tx_channel_->CNTR == 0;
259 if (dma_ready && uart->dma_buff_tx_.HasPending())
260 {
261 uart->dma_buff_tx_.Switch();
262 }
263 else
264 {
265 return ErrorCode::FAILED;
266 }
267 }
268
269 port.queue_info_->Pop(uart->write_info_active_);
270
271 DMA_Cmd(uart->dma_tx_channel_, DISABLE);
272 uart->dma_tx_channel_->MADDR =
273 reinterpret_cast<uint32_t>(uart->dma_buff_tx_.ActiveBuffer());
274 uart->dma_tx_channel_->CNTR = info.data.size_;
275 uart->_write_port.write_size_ = info.data.size_;
276 DMA_Cmd(uart->dma_tx_channel_, ENABLE);
277
278 return ErrorCode::OK;
279 }
280 return ErrorCode::FAILED;
281}
282
283// === 读操作回调(由中断驱动) ===
284ErrorCode CH32UART::ReadFun(ReadPort &port)
285{
286 UNUSED(port);
287 // 接收由 IDLE 中断驱动,读取在 ISR 中完成
288 return ErrorCode::EMPTY;
289}
290
291void CH32_UART_RX_ISR_Handler(LibXR::CH32UART *uart)
292{
293 auto rx_buf = static_cast<uint8_t *>(uart->dma_buff_rx_.addr_);
294 size_t dma_size = uart->dma_buff_rx_.size_;
295 size_t curr_pos = dma_size - uart->dma_rx_channel_->CNTR;
296 size_t last_pos = uart->last_rx_pos_;
297
298 if (curr_pos != last_pos)
299 {
300 if (curr_pos > last_pos)
301 {
302 // 普通区间
303 uart->_read_port.queue_data_->PushBatch(&rx_buf[last_pos], curr_pos - last_pos);
304 }
305 else
306 {
307 // 回卷区
308 uart->_read_port.queue_data_->PushBatch(&rx_buf[last_pos], dma_size - last_pos);
309 uart->_read_port.queue_data_->PushBatch(&rx_buf[0], curr_pos);
310 }
311 uart->last_rx_pos_ = curr_pos;
312 uart->_read_port.ProcessPendingReads(true);
313 }
314}
315
316// === USART IDLE中断服务 ===
317extern "C" void CH32_UART_ISR_Handler_IDLE(ch32_uart_id_t id)
318{
319 auto uart = CH32UART::map[id];
320 if (!uart)
321 {
322 return;
323 }
324
325 // 检查和清除IDLE标志
326 if (!USART_GetITStatus(uart->instance_, USART_IT_IDLE))
327 {
328 return;
329 }
330
331 USART_ReceiveData(uart->instance_);
332
333 CH32_UART_RX_ISR_Handler(uart);
334}
335
336// === DMA TX完成中断服务 ===
337extern "C" void CH32_UART_ISR_Handler_TX_CPLT(CH32UART *uart)
338{
339 DMA_ClearITPendingBit(CH32_UART_TX_DMA_IT_MAP[uart->id_]);
340
341 size_t pending_len = uart->dma_buff_tx_.GetPendingLength();
342
343 if (pending_len == 0)
344 {
345 return;
346 }
347
348 uart->dma_buff_tx_.Switch();
349
350 auto *buf = reinterpret_cast<uint8_t *>(uart->dma_buff_tx_.ActiveBuffer());
351 DMA_Cmd(uart->dma_tx_channel_, DISABLE);
352 uart->dma_tx_channel_->MADDR = (uint32_t)buf;
353 uart->dma_tx_channel_->CNTR = pending_len;
354 uart->_write_port.write_size_ = pending_len;
355 DMA_Cmd(uart->dma_tx_channel_, ENABLE);
356
357 WriteInfoBlock &current_info = uart->write_info_active_;
358
359 // 有pending包,继续取下一包
360 if (uart->_write_port.queue_info_->Pop(current_info) != ErrorCode::OK)
361 {
362 ASSERT(false);
363 return;
364 }
365
366 current_info.op.UpdateStatus(true, ErrorCode::OK);
367
368 // 预装pending区
369 WriteInfoBlock next_info;
370 if (uart->write_port_->queue_info_->Peek(next_info) != ErrorCode::OK)
371 {
372 return;
373 }
374
375 if (uart->write_port_->queue_data_->PopBatch(
376 reinterpret_cast<uint8_t *>(uart->dma_buff_tx_.PendingBuffer()),
377 next_info.data.size_) != ErrorCode::OK)
378 {
379 ASSERT(false);
380 return;
381 }
382
383 uart->dma_buff_tx_.SetPendingLength(next_info.data.size_);
384
385 uart->dma_buff_tx_.EnablePending();
386}
387
388// === DMA 通道中断回调 ===
389void CH32UART::TxDmaIRQHandler()
390{
391 if (DMA_GetITStatus(CH32_UART_TX_DMA_IT_MAP[id_]) == RESET) return;
392
393 if (dma_tx_channel_->CNTR == 0) CH32_UART_ISR_Handler_TX_CPLT(this);
394}
395
405{
406 if (DMA_GetITStatus(CH32_UART_RX_DMA_IT_HT_MAP[id_]) == SET)
407 {
408 DMA_ClearITPendingBit(CH32_UART_RX_DMA_IT_HT_MAP[id_]);
409 CH32_UART_RX_ISR_Handler(this);
410 }
411
412 if (DMA_GetITStatus(CH32_UART_RX_DMA_IT_TC_MAP[id_]) == SET)
413 {
414 DMA_ClearITPendingBit(CH32_UART_RX_DMA_IT_TC_MAP[id_]);
415 CH32_UART_RX_ISR_Handler(this);
416 }
417}
418
419// === 各类串口中断入口适配 ===
420#if defined(USART1)
421extern "C" void USART1_IRQHandler(void) __attribute__((interrupt));
422extern "C" void USART1_IRQHandler(void) { CH32_UART_ISR_Handler_IDLE(CH32_USART1); }
423#endif
424#if defined(USART2)
425extern "C" void USART2_IRQHandler(void) __attribute__((interrupt));
426extern "C" void USART2_IRQHandler(void) { CH32_UART_ISR_Handler_IDLE(CH32_USART2); }
427#endif
428#if defined(USART3)
429extern "C" void USART3_IRQHandler(void) __attribute__((interrupt));
430extern "C" void USART3_IRQHandler(void) { CH32_UART_ISR_Handler_IDLE(CH32_USART3); }
431#endif
432#if defined(USART4)
433extern "C" void USART4_IRQHandler(void) __attribute__((interrupt));
434extern "C" void USART4_IRQHandler(void) { CH32_UART_ISR_Handler_IDLE(CH32_USART4); }
435#endif
436#if defined(USART5)
437extern "C" void USART5_IRQHandler(void) __attribute__((interrupt));
438extern "C" void USART5_IRQHandler(void) { CH32_UART_ISR_Handler_IDLE(CH32_USART5); }
439#endif
440#if defined(USART6)
441extern "C" void USART6_IRQHandler(void) __attribute__((interrupt));
442extern "C" void USART6_IRQHandler(void) { CH32_UART_ISR_Handler_IDLE(CH32_USART6); }
443#endif
444#if defined(USART7)
445extern "C" void USART7_IRQHandler(void) __attribute__((interrupt));
446extern "C" void USART7_IRQHandler(void) { CH32_UART_ISR_Handler_IDLE(CH32_USART7); }
447#endif
448#if defined(USART8)
449extern "C" void USART8_IRQHandler(void) __attribute__((interrupt));
450extern "C" void USART8_IRQHandler(void) { CH32_UART_ISR_Handler_IDLE(CH32_USART8); }
451#endif
452#if defined(UART1)
453extern "C" void UART1_IRQHandler(void) __attribute__((interrupt));
454extern "C" void UART1_IRQHandler(void) { CH32_UART_ISR_Handler_IDLE(CH32_UART1); }
455#endif
456#if defined(UART2)
457extern "C" void UART2_IRQHandler(void) __attribute__((interrupt));
458extern "C" void UART2_IRQHandler(void) { CH32_UART_ISR_Handler_IDLE(CH32_UART2); }
459#endif
460#if defined(UART3)
461extern "C" void UART3_IRQHandler(void) __attribute__((interrupt));
462extern "C" void UART3_IRQHandler(void) { CH32_UART_ISR_Handler_IDLE(CH32_UART3); }
463#endif
464#if defined(UART4)
465extern "C" void UART4_IRQHandler(void) __attribute__((interrupt));
466extern "C" void UART4_IRQHandler(void) { CH32_UART_ISR_Handler_IDLE(CH32_UART4); }
467#endif
468#if defined(UART5)
469extern "C" void UART5_IRQHandler(void) __attribute__((interrupt));
470extern "C" void UART5_IRQHandler(void) { CH32_UART_ISR_Handler_IDLE(CH32_UART5); }
471#endif
472#if defined(UART6)
473extern "C" void UART6_IRQHandler(void) __attribute__((interrupt));
474extern "C" void UART6_IRQHandler(void) { CH32_UART_ISR_Handler_IDLE(CH32_UART6); }
475#endif
476#if defined(UART7)
477extern "C" void UART7_IRQHandler(void) __attribute__((interrupt));
478extern "C" void UART7_IRQHandler(void) { CH32_UART_ISR_Handler_IDLE(CH32_UART7); }
479#endif
480#if defined(UART8)
481extern "C" void UART8_IRQHandler(void) __attribute__((interrupt));
482extern "C" void UART8_IRQHandler(void) { CH32_UART_ISR_Handler_IDLE(CH32_UART8); }
483#endif
void RxDmaIRQHandler()
DMA中断处理函数
ErrorCode SetConfig(UART::Configuration config)
设置 UART 配置 / Sets the UART configuration
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
void UpdateStatus(bool in_isr, Status &&...status)
Updates operation status based on type.
Definition libxr_rw.hpp:171
原始数据封装类。 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.
Definition libxr_rw.hpp:269
virtual void ProcessPendingReads(bool in_isr)
Processes pending reads.
Definition libxr_rw.cpp:126
通用异步收发传输(UART)基类 / Abstract base class for Universal Asynchronous Receiver-Transmitter (UART)
Definition uart.hpp:19
@ NO_PARITY
无校验 / No parity
@ ODD
奇校验 / Odd parity
@ EVEN
偶校验 / Even parity
WritePort * write_port_
写入端口 / Write port
Definition uart.hpp:54
WritePort class for handling write operations.
Definition libxr_rw.hpp:403
LibXR 命名空间
ErrorCode(* ReadFun)(ReadPort &port)
Function pointer type for read operations.
Definition libxr_rw.hpp:246
ErrorCode(* WriteFun)(WritePort &port)
Function pointer type for write operations.
Definition libxr_rw.hpp:242
UART 配置结构体 / UART configuration structure.
Definition uart.hpp:44
uint8_t stop_bits
停止位长度 / Number of stop bits
Definition uart.hpp:50
Parity parity
校验模式 / Parity mode
Definition uart.hpp:47
uint32_t baudrate
波特率 / Baud rate
Definition uart.hpp:45
ConstRawData data
Data buffer. 数据缓冲区。
Definition libxr_rw.hpp:260
WriteOperation op
Write operation instance. 写入操作实例。
Definition libxr_rw.hpp:261