libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
LibXR::CH32UART Class Reference

CH32 UART 驱动实现 / CH32 UART driver implementation. More...

#include <ch32_uart.hpp>

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})
 构造 UART 对象 / Construct UART object
 
ErrorCode SetConfig (UART::Configuration config)
 设置 UART 配置 / Sets the UART configuration
 
void TxDmaIRQHandler ()
 
void RxDmaIRQHandler ()
 DMA中断处理函数
 
- 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, bool in_isr=false)
 
template<typename OperationType , typename = std::enable_if_t<std::is_base_of_v< ReadOperation, std::decay_t<OperationType>>>>
ErrorCode Read (RawData data, OperationType &&op, bool in_isr=false)
 

Static Public Member Functions

static ErrorCode WriteFun (WritePort &port, bool in_isr)
 
static ErrorCode ReadFun (ReadPort &port, bool in_isr)
 

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_
 
Flag::Plain in_tx_isr
 
Flag::Plain tx_busy_
 
- 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

CH32 UART 驱动实现 / CH32 UART driver implementation.

Definition at line 18 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} )

构造 UART 对象 / Construct UART object

Definition at line 15 of file ch32_uart.cpp.

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 dma_buff_rx_(dma_rx),
24 dma_buff_tx_(dma_tx),
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])
28{
29 map_[id] = this;
30
31 bool tx_enable = dma_tx.size_ > 1;
32 bool rx_enable = dma_rx.size_ > 0;
33
34 ASSERT(tx_enable || rx_enable);
35 if (tx_enable)
36 {
37 ASSERT(dma_tx_channel_ != nullptr);
38 ASSERT(CH32_UART_TX_DMA_IT_MAP[id] != 0);
39 }
40 if (rx_enable)
41 {
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);
45 }
46
47 /* GPIO配置(TX: 推挽输出,RX: 悬空输入) */
48 GPIO_InitTypeDef gpio_init = {};
49 gpio_init.GPIO_Speed = GPIO_Speed_50MHz;
50
51 if (tx_enable)
52 {
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);
57 (*write_port_) = WriteFun;
58 }
59
60 if (rx_enable)
61 {
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);
66 (*read_port_) = ReadFun;
67 }
68
69 /* 可选:引脚重映射 */
70 if (pin_remap != 0)
71 {
72 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
73 GPIO_PinRemapConfig(pin_remap, ENABLE);
74 }
75
76 /* 串口外设时钟使能 */
77 if (CH32_UART_APB_MAP[id] == 1)
78 {
79 RCC_APB1PeriphClockCmd(CH32_UART_RCC_PERIPH_MAP[id], ENABLE);
80 }
81 else if (CH32_UART_APB_MAP[id] == 2)
82 {
83 RCC_APB2PeriphClockCmd(CH32_UART_RCC_PERIPH_MAP[id], ENABLE);
84 }
85 else
86 {
87 ASSERT(false);
88 }
89 RCC_AHBPeriphClockCmd(CH32_UART_RCC_PERIPH_MAP_DMA[id], ENABLE);
90
91 // 3. USART 配置
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;
96 switch (config.parity)
97 {
99 usart_cfg.USART_Parity = USART_Parity_No;
100 usart_cfg.USART_WordLength = USART_WordLength_8b;
101 break;
103 usart_cfg.USART_Parity = USART_Parity_Even;
104 usart_cfg.USART_WordLength = USART_WordLength_9b;
105 break;
107 usart_cfg.USART_Parity = USART_Parity_Odd;
108 usart_cfg.USART_WordLength = USART_WordLength_9b;
109 break;
110 default:
111 ASSERT(false);
112 }
113
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);
119
120 /* DMA 配置 */
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;
128
129 if (rx_enable)
130 {
131 ch32_dma_callback_t rx_cb_fun = [](void* arg)
132 { reinterpret_cast<CH32UART*>(arg)->RxDmaIRQHandler(); };
133
134 ch32_dma_register_callback(ch32_dma_get_id(CH32_UART_RX_DMA_CHANNEL_MAP[id]),
135 rx_cb_fun, this);
136
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);
148 }
149
150 if (tx_enable)
151 {
152 ch32_dma_callback_t tx_cb_fun = [](void* arg)
153 { reinterpret_cast<CH32UART*>(arg)->TxDmaIRQHandler(); };
154
155 ch32_dma_register_callback(ch32_dma_get_id(CH32_UART_TX_DMA_CHANNEL_MAP[id]),
156 tx_cb_fun, this);
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);
166 }
167
168 // 6. USART和相关中断
169 USART_Cmd(instance_, ENABLE);
170
171 if (rx_enable)
172 {
173 USART_ITConfig(instance_, USART_IT_IDLE, ENABLE);
174 NVIC_EnableIRQ(CH32_DMA_IRQ_MAP[ch32_dma_get_id(dma_rx_channel_)]);
175 }
176
177 if (tx_enable)
178 {
179 NVIC_EnableIRQ(CH32_DMA_IRQ_MAP[ch32_dma_get_id(dma_tx_channel_)]);
180 }
181
182 NVIC_EnableIRQ(CH32_UART_IRQ_MAP[id]);
183}
CH32 UART 驱动实现 / CH32 UART driver implementation.
Definition ch32_uart.hpp:19
void RxDmaIRQHandler()
DMA中断处理函数
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:66
ErrorCode(* ReadFun)(ReadPort &port, bool in_isr)
Function pointer type for read operations.
Definition libxr_rw.hpp:249
ErrorCode(* WriteFun)(WritePort &port, bool in_isr)
Function pointer type for write operations.
Definition libxr_rw.hpp:245
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

Member Function Documentation

◆ ReadFun()

ErrorCode CH32UART::ReadFun ( ReadPort & port,
bool in_isr )
static

Definition at line 310 of file ch32_uart.cpp.

311{
312 // 接收由 IDLE 中断驱动,读取在 ISR 中完成
313 return ErrorCode::PENDING;
314}

◆ RxDmaIRQHandler()

void CH32UART::RxDmaIRQHandler ( )

DMA中断处理函数

如果DMA中断触发,且中断状态为半满或传输完成,清除中断标志, 并调用对应的中断处理函数

Parameters
[in]idUART的ID

Definition at line 439 of file ch32_uart.cpp.

440{
441 if (DMA_GetITStatus(CH32_UART_RX_DMA_IT_HT_MAP[id_]) == SET)
442 {
443 DMA_ClearITPendingBit(CH32_UART_RX_DMA_IT_HT_MAP[id_]);
444 ch32_uart_rx_isr_handler(this);
445 }
446
447 if (DMA_GetITStatus(CH32_UART_RX_DMA_IT_TC_MAP[id_]) == SET)
448 {
449 DMA_ClearITPendingBit(CH32_UART_RX_DMA_IT_TC_MAP[id_]);
450 ch32_uart_rx_isr_handler(this);
451 }
452}

◆ 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 186 of file ch32_uart.cpp.

187{
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;
192
193 switch (config.parity)
194 {
196 usart_cfg.USART_Parity = USART_Parity_No;
197 usart_cfg.USART_WordLength = USART_WordLength_8b;
198 break;
200 usart_cfg.USART_Parity = USART_Parity_Even;
201 usart_cfg.USART_WordLength = USART_WordLength_9b;
202 break;
204 usart_cfg.USART_Parity = USART_Parity_Odd;
205 usart_cfg.USART_WordLength = USART_WordLength_9b;
206 break;
207 default:
208 return ErrorCode::NOT_SUPPORT;
209 }
210
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);
215
216 if (uart_mode_ & USART_Mode_Rx)
217 {
218 USART_DMACmd(instance_, USART_DMAReq_Rx, ENABLE);
219 USART_ITConfig(instance_, USART_IT_IDLE, ENABLE);
220 }
221
222 if (uart_mode_ & USART_Mode_Tx)
223 {
224 USART_DMACmd(instance_, USART_DMAReq_Tx, ENABLE);
225 }
226
227 USART_Cmd(instance_, ENABLE);
228
229 if (tx_busy_.IsSet())
230 {
231 dma_tx_channel_->CNTR = dma_buff_tx_.GetActiveLength();
232 dma_tx_channel_->MADDR = reinterpret_cast<uint32_t>(dma_buff_tx_.ActiveBuffer());
233 DMA_Cmd(dma_tx_channel_, ENABLE);
234 }
235
236 return ErrorCode::OK;
237}
uint8_t * ActiveBuffer() const
获取当前正在使用的缓冲区指针 Returns the currently active buffer
size_t GetActiveLength() const
获取当前活动缓冲区中准备好的数据长度 Gets the size of valid data in active buffer
bool IsSet() const noexcept
判断是否已置位 / Check whether the flag is set
Definition flag.hpp:138

◆ TxDmaIRQHandler()

void CH32UART::TxDmaIRQHandler ( )

Definition at line 418 of file ch32_uart.cpp.

419{
420 if (DMA_GetITStatus(CH32_UART_TX_DMA_IT_MAP[id_]) == RESET)
421 {
422 return;
423 }
424
425 if (dma_tx_channel_->CNTR == 0)
426 {
427 ch32_uart_isr_handler_tx_cplt(this);
428 }
429}

◆ WriteFun()

ErrorCode CH32UART::WriteFun ( WritePort & port,
bool in_isr )
static

Definition at line 240 of file ch32_uart.cpp.

241{
242 CH32UART* uart = CONTAINER_OF(&port, CH32UART, _write_port);
243
244 if (uart->in_tx_isr.IsSet())
245 {
246 return ErrorCode::PENDING;
247 }
248
249 if (!uart->dma_buff_tx_.HasPending())
250 {
251 WriteInfoBlock info;
252 if (port.queue_info_->Peek(info) != ErrorCode::OK)
253 {
254 return ErrorCode::PENDING;
255 }
256
257 uint8_t* buffer = nullptr;
258 bool use_pending = false;
259
260 // DMA空闲判断
261 bool dma_ready = uart->dma_tx_channel_->CNTR == 0;
262 if (dma_ready)
263 {
264 buffer = reinterpret_cast<uint8_t*>(uart->dma_buff_tx_.ActiveBuffer());
265 }
266 else
267 {
268 buffer = reinterpret_cast<uint8_t*>(uart->dma_buff_tx_.PendingBuffer());
269 use_pending = true;
270 }
271
272 if (port.queue_data_->PopBatch(buffer, info.data.size_) != ErrorCode::OK)
273 {
274 ASSERT(false);
275 return ErrorCode::EMPTY;
276 }
277
278 if (use_pending)
279 {
280 uart->dma_buff_tx_.SetPendingLength(info.data.size_);
281 uart->dma_buff_tx_.EnablePending();
282 // 检查当前DMA是否可切换
283 bool dma_ready = uart->dma_tx_channel_->CNTR == 0;
284 if (dma_ready && uart->dma_buff_tx_.HasPending())
285 {
286 uart->dma_buff_tx_.Switch();
287 }
288 else
289 {
290 return ErrorCode::PENDING;
291 }
292 }
293
294 port.queue_info_->Pop(uart->write_info_active_);
295
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_;
300 uart->dma_buff_tx_.SetActiveLength(info.data.size_);
301 uart->tx_busy_.Set();
302 DMA_Cmd(uart->dma_tx_channel_, ENABLE);
303
304 return ErrorCode::OK;
305 }
306 return ErrorCode::PENDING;
307}
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 * PendingBuffer() const
获取备用缓冲区的指针 Returns the pending (inactive) buffer
void Switch()
切换到备用缓冲区(若其有效) Switches to the pending buffer if it's valid
void Set() noexcept
置位标志 / Set the flag
Definition flag.hpp:125
ErrorCode PopBatch(Data *data, size_t size)
批量弹出数据 / Pops multiple elements from the queue
ConstRawData data
Data buffer. 数据缓冲区。
Definition libxr_rw.hpp:263

Field Documentation

◆ _read_port

ReadPort LibXR::CH32UART::_read_port

Definition at line 40 of file ch32_uart.hpp.

◆ _write_port

WritePort LibXR::CH32UART::_write_port

Definition at line 41 of file ch32_uart.hpp.

◆ dma_buff_rx_

RawData LibXR::CH32UART::dma_buff_rx_

Definition at line 43 of file ch32_uart.hpp.

◆ dma_buff_tx_

DoubleBuffer LibXR::CH32UART::dma_buff_tx_

Definition at line 44 of file ch32_uart.hpp.

◆ dma_rx_channel_

DMA_Channel_TypeDef* LibXR::CH32UART::dma_rx_channel_

Definition at line 50 of file ch32_uart.hpp.

◆ dma_tx_channel_

DMA_Channel_TypeDef* LibXR::CH32UART::dma_tx_channel_

Definition at line 51 of file ch32_uart.hpp.

◆ id_

ch32_uart_id_t LibXR::CH32UART::id_

Definition at line 37 of file ch32_uart.hpp.

◆ in_tx_isr

Flag::Plain LibXR::CH32UART::in_tx_isr

Definition at line 53 of file ch32_uart.hpp.

◆ instance_

USART_TypeDef* LibXR::CH32UART::instance_

Definition at line 49 of file ch32_uart.hpp.

◆ last_rx_pos_

size_t LibXR::CH32UART::last_rx_pos_ = 0

Definition at line 47 of file ch32_uart.hpp.

◆ map_

CH32UART * CH32UART::map_ = {nullptr}
static

Definition at line 55 of file ch32_uart.hpp.

◆ tx_busy_

Flag::Plain LibXR::CH32UART::tx_busy_

Definition at line 53 of file ch32_uart.hpp.

◆ uart_mode_

uint16_t LibXR::CH32UART::uart_mode_

Definition at line 38 of file ch32_uart.hpp.

◆ write_info_active_

WriteInfoBlock LibXR::CH32UART::write_info_active_

Definition at line 45 of file ch32_uart.hpp.


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