libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
LibXR::CH32UART Class Reference
Inheritance diagram for LibXR::CH32UART:
[legend]
Collaboration diagram for LibXR::CH32UART:
[legend]

Public Member Functions

 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})
 
ErrorCode SetConfig (UART::Configuration config)
 设置 UART 配置 / Sets the UART configuration
 
- Public Member Functions inherited from LibXR::UART
template<typename ReadPortType = ReadPort, typename WritePortType = WritePort>
 UART (ReadPortType *read_port, WritePortType *write_port)
 UART 构造函数 / UART constructor.
 
template<typename OperationType , typename = std::enable_if_t<std::is_base_of_v< WriteOperation, std::decay_t<OperationType>>>>
ErrorCode Write (ConstRawData data, OperationType &&op)
 
template<typename OperationType , typename = std::enable_if_t<std::is_base_of_v< ReadOperation, std::decay_t<OperationType>>>>
ErrorCode Read (RawData data, OperationType &&op)
 

Static Public Member Functions

static ErrorCode WriteFun (WritePort &port)
 
static ErrorCode ReadFun (ReadPort &port)
 
static void TxDmaIRQHandler (DMA_Channel_TypeDef *channel, ch32_uart_id_t id)
 
static void RxDmaIRQHandler (DMA_Channel_TypeDef *channel, ch32_uart_id_t id)
 

Data Fields

ch32_uart_id_t id_
 
uint16_t uart_mode_
 
ReadPort _read_port
 
WritePort _write_port
 
RawData dma_buff_rx_
 
DoubleBuffer dma_buff_tx_
 
WriteInfoBlock write_info_active_
 
size_t last_rx_pos_ = 0
 
USART_TypeDef * instance_
 
DMA_Channel_TypeDef * dma_rx_channel_
 
DMA_Channel_TypeDef * dma_tx_channel_
 
- Data Fields inherited from LibXR::UART
ReadPortread_port_
 读取端口 / Read port
 
WritePortwrite_port_
 写入端口 / Write port
 

Static Public Attributes

static CH32UARTmap [CH32_UART_NUMBER] = {nullptr}
 

Additional Inherited Members

- Public Types inherited from LibXR::UART
enum class  Parity : uint8_t { NO_PARITY = 0 , EVEN = 1 , ODD = 2 }
 奇偶校验模式 / Parity mode More...
 

Detailed Description

Definition at line 16 of file ch32_uart.hpp.

Constructor & Destructor Documentation

◆ CH32UART()

CH32UART::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} )

Definition at line 14 of file ch32_uart.cpp.

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 (*write_port_) = WriteFun;
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);
46 }
47
48 if (rx_enable)
49 {
50 (*read_port_) = ReadFun;
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);
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 {
87 usart_cfg.USART_Parity = USART_Parity_No;
88 usart_cfg.USART_WordLength = USART_WordLength_8b;
89 break;
91 usart_cfg.USART_Parity = USART_Parity_Even;
92 usart_cfg.USART_WordLength = USART_WordLength_9b;
93 break;
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 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);
130 }
131
132 if (tx_enable)
133 {
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);
143 }
144
145 // 6. USART和相关中断
146 USART_Cmd(instance_, ENABLE);
147
148 if (rx_enable)
149 {
150 USART_ITConfig(instance_, USART_IT_IDLE, ENABLE);
151 NVIC_EnableIRQ(CH32_DMA_IRQ_MAP[CH32_DMA_GetID(dma_rx_channel_)]);
152 }
153
154 if (tx_enable)
155 {
156 NVIC_EnableIRQ(CH32_DMA_IRQ_MAP[CH32_DMA_GetID(dma_tx_channel_)]);
157 }
158
159 NVIC_EnableIRQ(CH32_UART_IRQ_MAP[id]);
160}
size_t size_
数据大小(字节)。 The size of the data (in bytes).
void * addr_
数据存储地址。 The storage address of the data.
@ NO_PARITY
无校验 / No parity
@ ODD
奇校验 / Odd parity
@ EVEN
偶校验 / Even parity
UART(ReadPortType *read_port, WritePortType *write_port)
UART 构造函数 / UART constructor.
Definition uart.hpp:64
ErrorCode(* ReadFun)(ReadPort &port)
Function pointer type for read operations.
Definition libxr_rw.hpp:245
ErrorCode(* WriteFun)(WritePort &port)
Function pointer type for write operations.
Definition libxr_rw.hpp:241
uint8_t stop_bits
停止位长度 / Number of stop bits
Definition uart.hpp:48
Parity parity
校验模式 / Parity mode
Definition uart.hpp:46
uint32_t baudrate
波特率 / Baud rate
Definition uart.hpp:45

Member Function Documentation

◆ ReadFun()

ErrorCode CH32UART::ReadFun ( ReadPort & port)
static

Definition at line 275 of file ch32_uart.cpp.

276{
277 UNUSED(port);
278 // 接收由 IDLE 中断驱动,读取在 ISR 中完成
279 return ErrorCode::EMPTY;
280}

◆ RxDmaIRQHandler()

void CH32UART::RxDmaIRQHandler ( DMA_Channel_TypeDef * channel,
ch32_uart_id_t id )
static

Definition at line 393 of file ch32_uart.cpp.

394{
395 UNUSED(channel);
396 auto uart = CH32UART::map[id];
397 if (!uart) return;
398
399 if (DMA_GetITStatus(CH32_UART_RX_DMA_IT_HT_MAP[id]) == SET)
400 {
401 DMA_ClearITPendingBit(CH32_UART_RX_DMA_IT_HT_MAP[id]);
402 CH32_UART_RX_ISR_Handler(uart);
403 }
404
405 if (DMA_GetITStatus(CH32_UART_RX_DMA_IT_TC_MAP[id]) == SET)
406 {
407 DMA_ClearITPendingBit(CH32_UART_RX_DMA_IT_TC_MAP[id]);
408 CH32_UART_RX_ISR_Handler(uart);
409 }
410}

◆ SetConfig()

ErrorCode CH32UART::SetConfig ( UART::Configuration config)
virtual

设置 UART 配置 / Sets the UART configuration

Parameters
configUART 配置信息 / UART configuration settings
Returns
返回操作状态,成功时返回 ErrorCode::OK,否则返回相应错误码 / Returns the operation status, ErrorCode::OK if successful, otherwise an error code

该方法为纯虚函数,子类必须实现具体的 UART 配置逻辑。 This is a pure virtual function. Subclasses must implement the specific UART configuration logic.

Implements LibXR::UART.

Definition at line 163 of file ch32_uart.cpp.

164{
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;
169
170 switch (config.parity)
171 {
173 usart_cfg.USART_Parity = USART_Parity_No;
174 usart_cfg.USART_WordLength = USART_WordLength_8b;
175 break;
177 usart_cfg.USART_Parity = USART_Parity_Even;
178 usart_cfg.USART_WordLength = USART_WordLength_9b;
179 break;
181 usart_cfg.USART_Parity = USART_Parity_Odd;
182 usart_cfg.USART_WordLength = USART_WordLength_9b;
183 break;
184 default:
185 return ErrorCode::NOT_SUPPORT;
186 }
187
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);
192
193 if (uart_mode_ & USART_Mode_Rx)
194 {
195 USART_DMACmd(instance_, USART_DMAReq_Rx, ENABLE);
196 USART_ITConfig(instance_, USART_IT_IDLE, ENABLE);
197 }
198
199 if (uart_mode_ & USART_Mode_Tx)
200 {
201 USART_DMACmd(instance_, USART_DMAReq_Tx, ENABLE);
202 }
203
204 USART_Cmd(instance_, ENABLE);
205
206 return ErrorCode::OK;
207}

◆ TxDmaIRQHandler()

void CH32UART::TxDmaIRQHandler ( DMA_Channel_TypeDef * channel,
ch32_uart_id_t id )
static

Definition at line 386 of file ch32_uart.cpp.

387{
388 if (DMA_GetITStatus(CH32_UART_TX_DMA_IT_MAP[id]) == RESET) return;
389
390 if (channel->CNTR == 0) CH32_UART_ISR_Handler_TX_CPLT(id);
391}

◆ WriteFun()

ErrorCode CH32UART::WriteFun ( WritePort & port)
static

Definition at line 210 of file ch32_uart.cpp.

211{
212 CH32UART *uart = CONTAINER_OF(&port, CH32UART, _write_port);
213 if (!uart->dma_buff_tx_.HasPending())
214 {
215 WriteInfoBlock info;
216 if (port.queue_info_->Peek(info) != ErrorCode::OK)
217 {
218 return ErrorCode::EMPTY;
219 }
220
221 uint8_t *buffer = nullptr;
222 bool use_pending = false;
223
224 // DMA空闲判断
225 bool dma_ready = uart->dma_tx_channel_->CNTR == 0;
226 if (dma_ready)
227 {
228 buffer = reinterpret_cast<uint8_t *>(uart->dma_buff_tx_.ActiveBuffer());
229 }
230 else
231 {
232 buffer = reinterpret_cast<uint8_t *>(uart->dma_buff_tx_.PendingBuffer());
233 use_pending = true;
234 }
235
236 if (port.queue_data_->PopBatch(buffer, info.data.size_) != ErrorCode::OK)
237 {
238 ASSERT(false);
239 return ErrorCode::EMPTY;
240 }
241
242 if (use_pending)
243 {
244 uart->dma_buff_tx_.SetPendingLength(info.data.size_);
245 uart->dma_buff_tx_.EnablePending();
246 // 检查当前DMA是否可切换
247 bool dma_ready = uart->dma_tx_channel_->CNTR == 0;
248 if (dma_ready && uart->dma_buff_tx_.HasPending())
249 {
250 uart->dma_buff_tx_.Switch();
251 }
252 else
253 {
254 return ErrorCode::FAILED;
255 }
256 }
257
258 port.queue_info_->Pop(uart->write_info_active_);
259
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);
266
267 uart->write_info_active_.op.UpdateStatus(false, ErrorCode::OK);
268
269 return ErrorCode::FAILED; // 实际是发起传输成功,但等待DMA完成
270 }
271 return ErrorCode::FAILED;
272}
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
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

Field Documentation

◆ _read_port

ReadPort LibXR::CH32UART::_read_port

Definition at line 35 of file ch32_uart.hpp.

◆ _write_port

WritePort LibXR::CH32UART::_write_port

Definition at line 36 of file ch32_uart.hpp.

◆ dma_buff_rx_

RawData LibXR::CH32UART::dma_buff_rx_

Definition at line 38 of file ch32_uart.hpp.

◆ dma_buff_tx_

DoubleBuffer LibXR::CH32UART::dma_buff_tx_

Definition at line 39 of file ch32_uart.hpp.

◆ dma_rx_channel_

DMA_Channel_TypeDef* LibXR::CH32UART::dma_rx_channel_

Definition at line 45 of file ch32_uart.hpp.

◆ dma_tx_channel_

DMA_Channel_TypeDef* LibXR::CH32UART::dma_tx_channel_

Definition at line 46 of file ch32_uart.hpp.

◆ id_

ch32_uart_id_t LibXR::CH32UART::id_

Definition at line 32 of file ch32_uart.hpp.

◆ instance_

USART_TypeDef* LibXR::CH32UART::instance_

Definition at line 44 of file ch32_uart.hpp.

◆ last_rx_pos_

size_t LibXR::CH32UART::last_rx_pos_ = 0

Definition at line 42 of file ch32_uart.hpp.

◆ map

CH32UART * CH32UART::map = {nullptr}
static

Definition at line 48 of file ch32_uart.hpp.

◆ uart_mode_

uint16_t LibXR::CH32UART::uart_mode_

Definition at line 33 of file ch32_uart.hpp.

◆ write_info_active_

WriteInfoBlock LibXR::CH32UART::write_info_active_

Definition at line 40 of file ch32_uart.hpp.


The documentation for this class was generated from the following files: