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),
25 instance_(ch32_uart_get_instance_id(id)),
26 dma_rx_channel_(CH32_UART_RX_DMA_CHANNEL_MAP[id]),
27 dma_tx_channel_(CH32_UART_TX_DMA_CHANNEL_MAP[id])
31 bool tx_enable = dma_tx.
size_ > 1;
32 bool rx_enable = dma_rx.
size_ > 0;
34 ASSERT(tx_enable || rx_enable);
37 ASSERT(dma_tx_channel_ !=
nullptr);
38 ASSERT(CH32_UART_TX_DMA_IT_MAP[
id] != 0);
42 ASSERT(dma_rx_channel_ !=
nullptr);
43 ASSERT(CH32_UART_RX_DMA_IT_TC_MAP[
id] != 0);
44 ASSERT(CH32_UART_RX_DMA_IT_HT_MAP[
id] != 0);
48 GPIO_InitTypeDef gpio_init = {};
49 gpio_init.GPIO_Speed = GPIO_Speed_50MHz;
53 RCC_APB2PeriphClockCmd(ch32_get_gpio_periph(tx_gpio_port), ENABLE);
54 gpio_init.GPIO_Pin = tx_gpio_pin;
55 gpio_init.GPIO_Mode = GPIO_Mode_AF_PP;
56 GPIO_Init(tx_gpio_port, &gpio_init);
62 RCC_APB2PeriphClockCmd(ch32_get_gpio_periph(rx_gpio_port), ENABLE);
63 gpio_init.GPIO_Pin = rx_gpio_pin;
64 gpio_init.GPIO_Mode = GPIO_Mode_IN_FLOATING;
65 GPIO_Init(rx_gpio_port, &gpio_init);
72 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
73 GPIO_PinRemapConfig(pin_remap, ENABLE);
77 if (CH32_UART_APB_MAP[
id] == 1)
79 RCC_APB1PeriphClockCmd(CH32_UART_RCC_PERIPH_MAP[
id], ENABLE);
81 else if (CH32_UART_APB_MAP[
id] == 2)
83 RCC_APB2PeriphClockCmd(CH32_UART_RCC_PERIPH_MAP[
id], ENABLE);
89 RCC_AHBPeriphClockCmd(CH32_UART_RCC_PERIPH_MAP_DMA[
id], ENABLE);
92 USART_InitTypeDef usart_cfg = {};
93 usart_cfg.USART_BaudRate = config.
baudrate;
94 usart_cfg.USART_StopBits =
95 (config.
stop_bits == 2) ? USART_StopBits_2 : USART_StopBits_1;
99 usart_cfg.USART_Parity = USART_Parity_No;
100 usart_cfg.USART_WordLength = USART_WordLength_8b;
103 usart_cfg.USART_Parity = USART_Parity_Even;
104 usart_cfg.USART_WordLength = USART_WordLength_9b;
107 usart_cfg.USART_Parity = USART_Parity_Odd;
108 usart_cfg.USART_WordLength = USART_WordLength_9b;
114 usart_cfg.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
115 usart_cfg.USART_Mode =
116 (tx_enable ? USART_Mode_Tx : 0) | (rx_enable ? USART_Mode_Rx : 0);
117 uart_mode_ = usart_cfg.USART_Mode;
118 USART_Init(instance_, &usart_cfg);
121 DMA_InitTypeDef dma_init = {};
122 dma_init.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
123 dma_init.DMA_MemoryInc = DMA_MemoryInc_Enable;
124 dma_init.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
125 dma_init.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
126 dma_init.DMA_Priority = DMA_Priority_High;
127 dma_init.DMA_M2M = DMA_M2M_Disable;
131 ch32_dma_callback_t rx_cb_fun = [](
void* arg)
134 ch32_dma_register_callback(ch32_dma_get_id(CH32_UART_RX_DMA_CHANNEL_MAP[
id]),
137 DMA_DeInit(dma_rx_channel_);
138 dma_init.DMA_PeripheralBaseAddr = (uint32_t)&instance_->DATAR;
139 dma_init.DMA_MemoryBaseAddr = (uint32_t)dma_buff_rx_.
addr_;
140 dma_init.DMA_DIR = DMA_DIR_PeripheralSRC;
141 dma_init.DMA_Mode = DMA_Mode_Circular;
142 dma_init.DMA_BufferSize = dma_buff_rx_.
size_;
143 DMA_Init(dma_rx_channel_, &dma_init);
144 DMA_Cmd(dma_rx_channel_, ENABLE);
145 DMA_ITConfig(dma_rx_channel_, DMA_IT_TC, ENABLE);
146 DMA_ITConfig(dma_rx_channel_, DMA_IT_HT, ENABLE);
147 USART_DMACmd(instance_, USART_DMAReq_Rx, ENABLE);
152 ch32_dma_callback_t tx_cb_fun = [](
void* arg)
153 {
reinterpret_cast<CH32UART*
>(arg)->TxDmaIRQHandler(); };
155 ch32_dma_register_callback(ch32_dma_get_id(CH32_UART_TX_DMA_CHANNEL_MAP[
id]),
157 DMA_DeInit(dma_tx_channel_);
158 dma_init.DMA_PeripheralBaseAddr = (u32)(&instance_->DATAR);
159 dma_init.DMA_MemoryBaseAddr = 0;
160 dma_init.DMA_DIR = DMA_DIR_PeripheralDST;
161 dma_init.DMA_Mode = DMA_Mode_Normal;
162 dma_init.DMA_BufferSize = 0;
163 DMA_Init(dma_tx_channel_, &dma_init);
164 DMA_ITConfig(dma_tx_channel_, DMA_IT_TC, ENABLE);
165 USART_DMACmd(instance_, USART_DMAReq_Tx, ENABLE);
169 USART_Cmd(instance_, ENABLE);
173 USART_ITConfig(instance_, USART_IT_IDLE, ENABLE);
174 NVIC_EnableIRQ(CH32_DMA_IRQ_MAP[ch32_dma_get_id(dma_rx_channel_)]);
179 NVIC_EnableIRQ(CH32_DMA_IRQ_MAP[ch32_dma_get_id(dma_tx_channel_)]);
182 NVIC_EnableIRQ(CH32_UART_IRQ_MAP[
id]);
188 USART_InitTypeDef usart_cfg = {};
189 usart_cfg.USART_BaudRate = config.
baudrate;
190 usart_cfg.USART_StopBits =
191 (config.
stop_bits == 2) ? USART_StopBits_2 : USART_StopBits_1;
196 usart_cfg.USART_Parity = USART_Parity_No;
197 usart_cfg.USART_WordLength = USART_WordLength_8b;
200 usart_cfg.USART_Parity = USART_Parity_Even;
201 usart_cfg.USART_WordLength = USART_WordLength_9b;
204 usart_cfg.USART_Parity = USART_Parity_Odd;
205 usart_cfg.USART_WordLength = USART_WordLength_9b;
208 return ErrorCode::NOT_SUPPORT;
211 usart_cfg.USART_Mode = uart_mode_;
212 usart_cfg.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
213 USART_DeInit(instance_);
214 USART_Init(instance_, &usart_cfg);
216 if (uart_mode_ & USART_Mode_Rx)
218 USART_DMACmd(instance_, USART_DMAReq_Rx, ENABLE);
219 USART_ITConfig(instance_, USART_IT_IDLE, ENABLE);
222 if (uart_mode_ & USART_Mode_Tx)
224 USART_DMACmd(instance_, USART_DMAReq_Tx, ENABLE);
227 USART_Cmd(instance_, ENABLE);
229 if (tx_busy_.
IsSet())
232 dma_tx_channel_->MADDR =
reinterpret_cast<uint32_t
>(dma_buff_tx_.
ActiveBuffer());
233 DMA_Cmd(dma_tx_channel_, ENABLE);
236 return ErrorCode::OK;
240ErrorCode CH32UART::WriteFun(
WritePort& port,
bool)
244 if (uart->in_tx_isr.
IsSet())
246 return ErrorCode::PENDING;
252 if (port.queue_info_->Peek(info) != ErrorCode::OK)
254 return ErrorCode::PENDING;
257 uint8_t* buffer =
nullptr;
258 bool use_pending =
false;
261 bool dma_ready = uart->dma_tx_channel_->CNTR == 0;
264 buffer =
reinterpret_cast<uint8_t*
>(uart->dma_buff_tx_.
ActiveBuffer());
268 buffer =
reinterpret_cast<uint8_t*
>(uart->dma_buff_tx_.
PendingBuffer());
275 return ErrorCode::EMPTY;
283 bool dma_ready = uart->dma_tx_channel_->CNTR == 0;
284 if (dma_ready && uart->dma_buff_tx_.
HasPending())
286 uart->dma_buff_tx_.
Switch();
290 return ErrorCode::PENDING;
294 port.queue_info_->Pop(uart->write_info_active_);
296 DMA_Cmd(uart->dma_tx_channel_, DISABLE);
297 uart->dma_tx_channel_->MADDR =
298 reinterpret_cast<uint32_t
>(uart->dma_buff_tx_.
ActiveBuffer());
299 uart->dma_tx_channel_->CNTR = info.
data.
size_;
301 uart->tx_busy_.
Set();
302 DMA_Cmd(uart->dma_tx_channel_, ENABLE);
304 return ErrorCode::OK;
306 return ErrorCode::PENDING;
310ErrorCode CH32UART::ReadFun(
ReadPort&,
bool)
313 return ErrorCode::PENDING;
318 auto rx_buf =
static_cast<uint8_t*
>(uart->dma_buff_rx_.
addr_);
319 size_t dma_size = uart->dma_buff_rx_.
size_;
320 size_t curr_pos = dma_size - uart->dma_rx_channel_->CNTR;
321 size_t last_pos = uart->last_rx_pos_;
323 if (curr_pos != last_pos)
325 if (curr_pos > last_pos)
328 uart->_read_port.queue_data_->
PushBatch(&rx_buf[last_pos], curr_pos - last_pos);
333 uart->_read_port.queue_data_->
PushBatch(&rx_buf[last_pos], dma_size - last_pos);
334 uart->_read_port.queue_data_->
PushBatch(&rx_buf[0], curr_pos);
336 uart->last_rx_pos_ = curr_pos;
342extern "C" void ch32_uart_isr_handler_idle(ch32_uart_id_t
id)
344 auto uart = CH32UART::map_[id];
351 if (!USART_GetITStatus(uart->instance_, USART_IT_IDLE))
356 USART_ReceiveData(uart->instance_);
358 ch32_uart_rx_isr_handler(uart);
362extern "C" void ch32_uart_isr_handler_tx_cplt(
CH32UART* uart)
364 DMA_ClearITPendingBit(CH32_UART_TX_DMA_IT_MAP[uart->id_]);
366 uart->tx_busy_.
Clear();
372 if (pending_len == 0)
377 uart->dma_buff_tx_.
Switch();
379 auto* buf =
reinterpret_cast<uint8_t*
>(uart->dma_buff_tx_.
ActiveBuffer());
380 DMA_Cmd(uart->dma_tx_channel_, DISABLE);
381 uart->dma_tx_channel_->MADDR = (uint32_t)buf;
382 uart->dma_tx_channel_->CNTR = pending_len;
384 DMA_Cmd(uart->dma_tx_channel_, ENABLE);
389 if (uart->_write_port.queue_info_->Pop(current_info) != ErrorCode::OK)
399 if (uart->
write_port_->queue_info_->Peek(next_info) != ErrorCode::OK)
405 reinterpret_cast<uint8_t*
>(uart->dma_buff_tx_.
PendingBuffer()),
418void CH32UART::TxDmaIRQHandler()
420 if (DMA_GetITStatus(CH32_UART_TX_DMA_IT_MAP[id_]) == RESET)
425 if (dma_tx_channel_->CNTR == 0)
427 ch32_uart_isr_handler_tx_cplt(
this);
441 if (DMA_GetITStatus(CH32_UART_RX_DMA_IT_HT_MAP[id_]) == SET)
443 DMA_ClearITPendingBit(CH32_UART_RX_DMA_IT_HT_MAP[id_]);
444 ch32_uart_rx_isr_handler(
this);
447 if (DMA_GetITStatus(CH32_UART_RX_DMA_IT_TC_MAP[id_]) == SET)
449 DMA_ClearITPendingBit(CH32_UART_RX_DMA_IT_TC_MAP[id_]);
450 ch32_uart_rx_isr_handler(
this);
457extern "C" void USART1_IRQHandler(
void) __attribute__((interrupt));
459extern "C" void USART1_IRQHandler(
void) { ch32_uart_isr_handler_idle(CH32_USART1); }
463extern "C" void USART2_IRQHandler(
void) __attribute__((interrupt));
465extern "C" void USART2_IRQHandler(
void) { ch32_uart_isr_handler_idle(CH32_USART2); }
469extern "C" void USART3_IRQHandler(
void) __attribute__((interrupt));
471extern "C" void USART3_IRQHandler(
void) { ch32_uart_isr_handler_idle(CH32_USART3); }
475extern "C" void USART4_IRQHandler(
void) __attribute__((interrupt));
477extern "C" void USART4_IRQHandler(
void) { ch32_uart_isr_handler_idle(CH32_USART4); }
481extern "C" void USART5_IRQHandler(
void) __attribute__((interrupt));
483extern "C" void USART5_IRQHandler(
void) { ch32_uart_isr_handler_idle(CH32_USART5); }
487extern "C" void USART6_IRQHandler(
void) __attribute__((interrupt));
489extern "C" void USART6_IRQHandler(
void) { ch32_uart_isr_handler_idle(CH32_USART6); }
493extern "C" void USART7_IRQHandler(
void) __attribute__((interrupt));
495extern "C" void USART7_IRQHandler(
void) { ch32_uart_isr_handler_idle(CH32_USART7); }
499extern "C" void USART8_IRQHandler(
void) __attribute__((interrupt));
501extern "C" void USART8_IRQHandler(
void) { ch32_uart_isr_handler_idle(CH32_USART8); }
505extern "C" void UART1_IRQHandler(
void) __attribute__((interrupt));
507extern "C" void UART1_IRQHandler(
void) { ch32_uart_isr_handler_idle(CH32_UART1); }
511extern "C" void UART2_IRQHandler(
void) __attribute__((interrupt));
513extern "C" void UART2_IRQHandler(
void) { ch32_uart_isr_handler_idle(CH32_UART2); }
517extern "C" void UART3_IRQHandler(
void) __attribute__((interrupt));
519extern "C" void UART3_IRQHandler(
void) { ch32_uart_isr_handler_idle(CH32_UART3); }
523extern "C" void UART4_IRQHandler(
void) __attribute__((interrupt));
525extern "C" void UART4_IRQHandler(
void) { ch32_uart_isr_handler_idle(CH32_UART4); }
529extern "C" void UART5_IRQHandler(
void) __attribute__((interrupt));
531extern "C" void UART5_IRQHandler(
void) { ch32_uart_isr_handler_idle(CH32_UART5); }
535extern "C" void UART6_IRQHandler(
void) __attribute__((interrupt));
537extern "C" void UART6_IRQHandler(
void) { ch32_uart_isr_handler_idle(CH32_UART6); }
541extern "C" void UART7_IRQHandler(
void) __attribute__((interrupt));
543extern "C" void UART7_IRQHandler(
void) { ch32_uart_isr_handler_idle(CH32_UART7); }
547extern "C" void UART8_IRQHandler(
void) __attribute__((interrupt));
549extern "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
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
size_t size_
数据大小(字节)。 The size of the data (in bytes).
void SetActiveLength(size_t length)
设置当前活动缓冲区的数据长度 Sets the size of the active buffer
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
size_t GetActiveLength() const
获取当前活动缓冲区中准备好的数据长度 Gets the size of valid data in 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
void Set() noexcept
置位标志 / Set the flag
bool IsSet() const noexcept
判断是否已置位 / Check whether the flag is set
void Clear() noexcept
清除标志 / Clear the flag
作用域标志管理器:构造时写入指定值,析构时恢复原值 / Scoped flag restorer: set on entry, restore on exit
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.
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.
void Finish(bool in_isr, ErrorCode ans, WriteInfoBlock &info)
更新写入操作的状态。 Updates the status of the write operation.
ErrorCode(* ReadFun)(ReadPort &port, bool in_isr)
Function pointer type for read operations.
ErrorCode(* WriteFun)(WritePort &port, bool in_isr)
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. 数据缓冲区。