libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
cdc_uart.hpp
1#pragma once
2#include <cstring>
3
4#include "cdc_base.hpp"
5
6namespace LibXR::USB
7{
8
23class CDCUart : public CDCBase, public LibXR::UART
24{
25 public:
26 // 公开 UART API 及底层端口对象(如需隐藏端口对象,可移除 read_port_/write_port_ 的
27 // using)
28 using LibXR::UART::Read;
30 using LibXR::UART::Write;
32
44 CDCUart(size_t rx_buffer_size = 128, size_t tx_buffer_size = 128,
45 size_t tx_queue_size = 5,
49 : CDCBase(data_in_ep_num, data_out_ep_num, comm_ep_num),
51 read_port_cdc_(rx_buffer_size),
52 write_port_cdc_(tx_queue_size, tx_buffer_size)
53 {
54 // 初始化端口读写函数
55 read_port_cdc_ = ReadFun; // NOLINT
56 write_port_cdc_ = WriteFun; // NOLINT
57 }
58
71 ErrorCode SetConfig(UART::Configuration cfg) override
72 {
73 auto& line_coding = GetLineCoding();
74
75 // 设置停止位
76 switch (cfg.stop_bits)
77 {
78 case 1:
79 line_coding.bCharFormat = 0;
80 break;
81 case 2:
82 line_coding.bCharFormat = 2;
83 break;
84 default:
85 return ErrorCode::ARG_ERR;
86 }
87
88 // 设置校验位
89 switch (cfg.parity)
90 {
92 line_coding.bParityType = 0;
93 break;
95 line_coding.bParityType = 1;
96 break;
98 line_coding.bParityType = 2;
99 break;
100 default:
101 return ErrorCode::ARG_ERR;
102 }
103
104 // 设置数据位
105 switch (cfg.data_bits)
106 {
107 case 5:
108 line_coding.bDataBits = 5;
109 break;
110 case 6:
111 line_coding.bDataBits = 6;
112 break;
113 case 7:
114 line_coding.bDataBits = 7;
115 break;
116 case 8:
117 line_coding.bDataBits = 8;
118 break;
119 case 16:
120 line_coding.bDataBits = 16;
121 break;
122 default:
123 return ErrorCode::ARG_ERR;
124 }
125
126 // 设置波特率
127 line_coding.dwDTERate = cfg.baudrate;
128
130
131 return ErrorCode::OK;
132 }
133
134 protected:
145 void Deinit(EndpointPool& endpoint_pool) override
146 {
147 CDCBase::Deinit(endpoint_pool);
149 while (write_port_cdc_.queue_info_->Pop(info) == ErrorCode::OK)
150 {
151 write_port_cdc_.queue_data_->PopBatch(nullptr, info.data.size_);
152 write_port_cdc_.Finish(true, ErrorCode::INIT_ERR, info, 0);
153 }
155 }
156
170 static ErrorCode WriteFun(WritePort& port)
171 {
172 CDCUart* cdc = CONTAINER_OF(&port, CDCUart, write_port_cdc_);
173
174 auto ep_data_in = cdc->GetDataInEndpoint();
175
176 // 检查是否已初始化且DTR已设置
177 if (!cdc->Inited() || !cdc->IsDtrSet())
178 {
179 if (ep_data_in->GetActiveLength() == 0)
180 {
181 WriteInfoBlock info;
182 auto ans = port.queue_info_->Pop(info);
183 if (ans != ErrorCode::OK)
184 {
185 return ErrorCode::EMPTY;
186 }
187 port.queue_data_->PopBatch(nullptr, info.data.size_);
188 port.Finish(true, ErrorCode::INIT_ERR, info, 0);
189 }
190 return ErrorCode::FAILED;
191 }
192
193 size_t dequeued = 0;
194
195 while (port.queue_info_->Size() > 0)
196 {
197 // 检查当前是否有传输正在进行
198 if (ep_data_in->GetActiveLength() > 0 || cdc->need_write_zlp_)
199 {
200 return ErrorCode::FAILED;
201 }
202
203 auto buffer = ep_data_in->GetBuffer();
204
205 WriteInfoBlock info;
206
207 // 获取队列中的写操作信息
208 if (port.queue_info_->Peek(info) != ErrorCode::OK)
209 {
210 return ErrorCode::EMPTY;
211 }
212
213 size_t need_write = info.data.size_ - dequeued;
214
215 if (need_write == 0)
216 {
217 return ErrorCode::OK;
218 }
219
220 // 检查数据大小是否超出缓冲区
221 if (need_write > buffer.size_)
222 {
223 need_write = buffer.size_;
224 }
225
226 // 从队列获取数据
227 if (port.queue_data_->PopBatch(reinterpret_cast<uint8_t*>(buffer.addr_),
228 need_write) != ErrorCode::OK)
229 {
230 ASSERT(false);
231 return ErrorCode::EMPTY;
232 }
233
234 dequeued += need_write;
235
236 cdc->written_ += need_write;
237
238 if (cdc->written_ >= info.data.size_)
239 {
240 port.queue_info_->Pop();
241 port.Finish(false, ErrorCode::OK, info, info.data.size_);
242 cdc->written_ -= info.data.size_;
243 }
244
245 ep_data_in->SetActiveLength(need_write);
246
247 // 保证对 ActiveLength/缓冲区的可见性顺序(与 ISR/USB 控制器交互)
248 // Ensure visibility/order for ActiveLength/buffer updates across ISR/USB controller
249 std::atomic_signal_fence(std::memory_order_seq_cst);
250
251 // 如果端点空闲且有数据待发送
252 if (ep_data_in->GetState() == Endpoint::State::IDLE &&
253 ep_data_in->GetActiveLength() != 0)
254 {
255 /* 可以立即发送 */
256 }
257 else
258 {
259 return ErrorCode::FAILED;
260 }
261
262 // 启动传输
263 auto ans = ErrorCode::OK;
264
265 ep_data_in->SetActiveLength(0);
266
267 ans = ep_data_in->Transfer(need_write);
268
269 ASSERT(ans == ErrorCode::OK);
270 }
271
272 return ErrorCode::OK;
273 }
274
284 static ErrorCode ReadFun(ReadPort& port)
285 {
286 UNUSED(port);
287 return ErrorCode::EMPTY;
288 }
289
300 void OnDataOutComplete(bool in_isr, ConstRawData& data) override
301 {
302 // 重启OUT端点传输
303 auto ep_data_out = GetDataOutEndpoint();
304 ep_data_out->Transfer(ep_data_out->MaxTransferSize());
305
306 if (data.size_ > 0)
307 {
308 // 将接收到的数据推入接收缓冲区
309 read_port_cdc_.queue_data_->PushBatch(reinterpret_cast<const uint8_t*>(data.addr_),
310 data.size_);
311 // 处理待处理的读取操作
313 }
314 }
315
323 void OnDataInComplete(bool in_isr, ConstRawData& data) override
324 {
325 UNUSED(in_isr);
326 UNUSED(data);
327
328 auto ep_data_in = GetDataInEndpoint();
329
330 size_t pending_len = ep_data_in->GetActiveLength();
331
332 if (pending_len == 0)
333 {
334 // TODO: zlp check
335 return;
336 }
337
338 ep_data_in->SetActiveLength(0);
339 auto ans = ep_data_in->Transfer(pending_len);
340 ASSERT(ans == ErrorCode::OK);
341
343
344 if (write_port_cdc_.queue_info_->Peek(info) != ErrorCode::OK)
345 {
346 return;
347 }
348
349 if (!Inited() || !IsDtrSet())
350 {
351 write_port_cdc_.queue_data_->PopBatch(nullptr, info.data.size_);
352 write_port_cdc_.Finish(true, ErrorCode::INIT_ERR, info, 0);
353 return;
354 }
355
356 auto need_write = info.data.size_ - written_;
357
358 if (need_write > 0)
359 {
360 auto buffer = ep_data_in->GetBuffer();
361 if (buffer.size_ < need_write)
362 {
363 need_write = buffer.size_;
364 }
365
366 write_port_cdc_.queue_data_->PopBatch(reinterpret_cast<uint8_t*>(buffer.addr_),
367 need_write);
368 ep_data_in->SetActiveLength(need_write);
369 written_ += need_write;
370
371 if (written_ >= info.data.size_)
372 {
373 write_port_cdc_.queue_info_->Pop(info);
374 write_port_cdc_.Finish(true, ErrorCode::OK, info, info.data.size_);
375 written_ -= info.data.size_;
376 ASSERT(written_ == 0);
377 }
378 }
379 }
380
381 private:
382 // 端口对象
385
386 // 状态标志
387 bool need_write_zlp_ = false;
388 size_t written_ = 0;
389};
390
391} // namespace LibXR::USB
常量原始数据封装类。 A class for encapsulating constant raw data.
size_t size_
数据大小(字节)。 The size of the data (in bytes).
const void * addr_
数据存储地址(常量)。 The storage address of the data (constant).
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
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
ReadPort * read_port_
读取端口 / Read port
Definition uart.hpp:53
@ NO_PARITY
无校验 / No parity
@ ODD
奇校验 / Odd parity
@ EVEN
偶校验 / Even parity
WritePort * write_port_
写入端口 / Write port
Definition uart.hpp:54
USB CDC ACM (Abstract Control Model) 设备类实现 USB CDC ACM (Abstract Control Model) device class implemen...
Definition cdc_base.hpp:23
virtual void Deinit(EndpointPool &endpoint_pool) override
反初始化CDC设备 Deinitialize CDC device
Definition cdc_base.hpp:352
ErrorCode SendSerialState()
发送串行状态通知 Send serial state notification
Definition cdc_base.hpp:164
bool IsDtrSet() const
检查DTR状态 Check DTR state
Definition cdc_base.hpp:146
USB CDC ACM UART 适配类 USB CDC ACM UART adaptation class.
Definition cdc_uart.hpp:24
CDCUart(size_t rx_buffer_size=128, size_t tx_buffer_size=128, size_t tx_queue_size=5, Endpoint::EPNumber data_in_ep_num=Endpoint::EPNumber::EP_AUTO, Endpoint::EPNumber data_out_ep_num=Endpoint::EPNumber::EP_AUTO, Endpoint::EPNumber comm_ep_num=Endpoint::EPNumber::EP_AUTO)
CDCUart 构造函数 / CDCUart constructor.
Definition cdc_uart.hpp:44
static ErrorCode ReadFun(ReadPort &port)
读端口回调(占位) Read port callback (placeholder)
Definition cdc_uart.hpp:284
LibXR::ReadPort read_port_cdc_
读取端口 / Read port
Definition cdc_uart.hpp:383
size_t written_
已写入字节数 / Number of bytes written
Definition cdc_uart.hpp:388
void Deinit(EndpointPool &endpoint_pool) override
反初始化 CDC 设备并清理写队列 Deinitialize CDC device and drain TX queue
Definition cdc_uart.hpp:145
void OnDataInComplete(bool in_isr, ConstRawData &data) override
数据IN端点传输完成处理 Handle data IN endpoint transfer completion
Definition cdc_uart.hpp:323
void OnDataOutComplete(bool in_isr, ConstRawData &data) override
OUT 端点完成:预装下一次接收,并将本次数据推入软件缓冲 Data OUT complete: arm next receive and push to software buffer.
Definition cdc_uart.hpp:300
static ErrorCode WriteFun(WritePort &port)
写端口回调(从软件队列取数据并通过 CDC Data IN 端点发送) Write port callback (dequeue and transmit via CDC Data IN endpoin...
Definition cdc_uart.hpp:170
bool need_write_zlp_
需要写入ZLP标志 / Need to write ZLP flag
Definition cdc_uart.hpp:387
LibXR::WritePort write_port_cdc_
写入端口 / Write port
Definition cdc_uart.hpp:384
ErrorCode SetConfig(UART::Configuration cfg) override
设置 UART 配置并同步到 CDC line coding Set UART configuration and sync to CDC line coding
Definition cdc_uart.hpp:71
EPNumber
端点号 / Endpoint number
Definition ep.hpp:39
@ EP_AUTO
自动分配端点号 / Auto allocate
USB端点池类 / USB endpoint pool class.
Definition ep_pool.hpp:23
WritePort class for handling write operations.
Definition libxr_rw.hpp:403
virtual void Reset()
Resets the WritePort.
Definition libxr_rw.cpp:333
void Finish(bool in_isr, ErrorCode ans, WriteInfoBlock &info, uint32_t size)
更新写入操作的状态。 Updates the status of the write operation.
Definition libxr_rw.cpp:207
LibXR 命名空间
Definition ch32_gpio.hpp:9
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
uint8_t data_bits
数据位长度 / Number of data bits
Definition uart.hpp:48
uint32_t baudrate
波特率 / Baud rate
Definition uart.hpp:45
ConstRawData data
Data buffer. 数据缓冲区。
Definition libxr_rw.hpp:260