libxr
Embedded C++ framework for bare-metal, RTOS and Linux
Loading...
Searching...
No Matches
cdc_uart.hpp
1#pragma once
2
3#include "cdc_base.hpp"
4#include "ep.hpp"
5#include "libxr_def.hpp"
6#include "libxr_rw.hpp"
7#include "serialized_service.hpp"
8
9namespace LibXR::USB
10{
11
12class CDCUart;
13
18{
19 public:
25 explicit CDCUartReadPort(uint32_t size, CDCUart& owner) : ReadPort(size), owner_(owner)
26 {
27 }
28
29 protected:
34 void OnReadQueueSpaceAvailable(bool in_isr) override;
35
36 public:
38 bool recv_pause_ = false;
40 0};
41};
42
46class CDCUart : public CDCBase, public LibXR::UART
47{
48 public:
49 using LibXR::UART::Read;
51 using LibXR::UART::Write;
53
66 Endpoint::EPNumber data_in_ep_num, Endpoint::EPNumber data_out_ep_num,
67 Endpoint::EPNumber comm_ep_num, size_t rx_buffer_size = 128,
68 size_t tx_buffer_size = 128, size_t tx_queue_size = 5,
69 const char* control_interface_string = CDCBase::DEFAULT_CONTROL_INTERFACE_STRING,
70 const char* data_interface_string = CDCBase::DEFAULT_DATA_INTERFACE_STRING)
71 : CDCBase(data_in_ep_num, data_out_ep_num, comm_ep_num, control_interface_string,
72 data_interface_string),
73 LibXR::UART(&read_port_cdc_, &write_port_cdc_),
74 read_port_cdc_(rx_buffer_size, *this),
75 write_port_cdc_(tx_queue_size, tx_buffer_size)
76 {
77 write_port_cdc_ = WriteFun; // NOLINT
78 }
79
87 ErrorCode SetConfig(UART::Configuration cfg, bool in_isr = false) override
88 {
89 UNUSED(in_isr);
90 auto& line_coding = GetLineCoding();
91
92 switch (cfg.stop_bits)
93 {
94 case 1:
95 line_coding.bCharFormat = 0;
96 break;
97 case 2:
98 line_coding.bCharFormat = 2;
99 break;
100 default:
101 return ErrorCode::ARG_ERR;
102 }
103
104 switch (cfg.parity)
105 {
107 line_coding.bParityType = 0;
108 break;
110 line_coding.bParityType = 1;
111 break;
113 line_coding.bParityType = 2;
114 break;
115 default:
116 return ErrorCode::ARG_ERR;
117 }
118
119 switch (cfg.data_bits)
120 {
121 case 5:
122 case 6:
123 case 7:
124 case 8:
125 case 16:
126 line_coding.bDataBits = static_cast<uint8_t>(cfg.data_bits);
127 break;
128 default:
129 return ErrorCode::ARG_ERR;
130 }
131
132 line_coding.dwDTERate = cfg.baudrate;
134 return ErrorCode::OK;
135 }
136
142 bool TryRearmOut(bool in_isr)
143 {
144 auto* ep = GetDataOutEndpoint();
145 if (ep == nullptr || ep->MaxPacketSize() == 0U || !read_port_cdc_.Readable())
146 {
147 return false;
148 }
149
150 if (read_port_cdc_.recv_pause_ && read_port_cdc_.pending_data_.size_ != 0U)
151 {
152 auto queue = read_port_cdc_.GetReadQueue(in_isr);
153 if (queue.EmptySize() < read_port_cdc_.pending_data_.size_)
154 {
155 queue.Publish();
156 return false;
157 }
158
159 [[maybe_unused]] const auto ans =
160 queue.PushBatch(static_cast<const uint8_t*>(read_port_cdc_.pending_data_.addr_),
161 read_port_cdc_.pending_data_.size_);
162 DEV_ASSERT_FROM_CALLBACK(ans == ErrorCode::OK, in_isr);
163 read_port_cdc_.pending_data_ = {nullptr, 0};
164 queue.Publish();
165 }
166
167 if (ep->GetState() != Endpoint::State::IDLE)
168 {
169 return false;
170 }
171
172 [[maybe_unused]] const auto ans = ep->Transfer(ep->MaxPacketSize());
173 if (ans == ErrorCode::OK)
174 {
175 read_port_cdc_.recv_pause_ = false;
176 return true;
177 }
178 return false;
179 }
180
181 protected:
196 void BindEndpoints(EndpointPool& endpoint_pool, uint8_t start_itf_num,
197 bool in_isr) override;
198
204 void UnbindEndpoints(EndpointPool& endpoint_pool, bool in_isr) override
205 {
206 CDCBase::UnbindEndpoints(endpoint_pool, in_isr);
207 need_write_zlp_ = false;
208 read_port_cdc_.recv_pause_ = false;
209 read_port_cdc_.pending_data_ = {nullptr, 0};
210 }
211
217 static void WriteFun(WritePort& port, bool in_isr);
218
224 void OnDataOutComplete(bool in_isr, ConstRawData& data) override
225 {
226 if (data.size_ != 0U)
227 {
228 auto queue = read_port_cdc_.GetReadQueue(in_isr);
229 if (queue.EmptySize() < data.size_)
230 {
231 read_port_cdc_.recv_pause_ = true;
232 read_port_cdc_.pending_data_ = data;
233 queue.Publish();
234 return;
235 }
236
237 [[maybe_unused]] const auto ans =
238 queue.PushBatch(static_cast<const uint8_t*>(data.addr_), data.size_);
239 DEV_ASSERT_FROM_CALLBACK(ans == ErrorCode::OK, in_isr);
240 queue.Publish();
241 }
242 (void)TryRearmOut(in_isr);
243 }
244
250 void OnDataInComplete(bool in_isr, ConstRawData& data) override;
251
252 private:
263 void RequestTx(bool in_isr);
264
270 void ServiceTx(bool in_isr);
271
277 void StartTxBuffer(Endpoint& ep, [[maybe_unused]] bool in_isr);
278
286 void FillTxBuffer(Endpoint& ep, bool in_isr);
287
293 void ProgressTx(bool in_isr);
294
295 CDCUartReadPort read_port_cdc_;
296 LibXR::WritePort write_port_cdc_;
297 SerializedService tx_service_;
299 bool need_write_zlp_ = false;
300};
301
303{
304 if (recv_pause_)
305 {
306 (void)owner_.TryRearmOut(in_isr);
307 }
308}
309
310} // namespace LibXR::USB
只读原始数据视图 / Immutable raw data view
size_t size_
数据字节数 / Data size in bytes
const void * addr_
数据起始地址 / Data start address
ErrorCode PushBatch(const uint8_t *data, size_t size)
批量复制字节到接收队列 / Copy a batch of bytes into the RX queue.
Definition read_port.cpp:22
基于 SPSC 字节队列的读端口 / Read endpoint backed by an SPSC byte queue.
Definition read_port.hpp:30
bool Readable() const
检查端口是否支持读取 / Check whether the port supports reads.
Definition read_port.cpp:67
ReadQueue GetReadQueue(bool in_isr=false)
获取后端接收入队接口 / Obtain the backend RX producer interface.
Definition read_port.cpp:14
事件合并与回调串行化服务 / Event-coalescing serialized-callback service.
通用异步收发传输(UART)基类 / Abstract base class for Universal Asynchronous Receiver-Transmitter (UART)
Definition uart.hpp:19
ReadPort * read_port_
读取端口 / Read port
Definition uart.hpp:56
@ NO_PARITY
无校验 / No parity
@ ODD
奇校验 / Odd parity
@ EVEN
偶校验 / Even parity
WritePort * write_port_
写入端口 / Write port
Definition uart.hpp:57
USB CDC ACM (Abstract Control Model) 设备类实现 USB CDC ACM (Abstract Control Model) device class implemen...
Definition cdc_base.hpp:24
ErrorCode SendSerialState()
发送串行状态通知 Send serial state notification
Definition cdc_base.hpp:189
virtual void UnbindEndpoints(EndpointPool &endpoint_pool, bool) override
反初始化CDC设备 Deinitialize CDC device
Definition cdc_base.hpp:396
USB CDC-ACM UART 适配器 / USB CDC-ACM UART adapter.
Definition cdc_uart.hpp:47
bool TryRearmOut(bool in_isr)
回填暂存数据并重新启动 OUT 接收 / Enqueue saved data and restart OUT reception
Definition cdc_uart.hpp:142
void UnbindEndpoints(EndpointPool &endpoint_pool, bool in_isr) override
解绑端点并清理接收暂存状态 / Unbind endpoints and clear saved receive state
Definition cdc_uart.hpp:204
CDCUart(Endpoint::EPNumber data_in_ep_num, Endpoint::EPNumber data_out_ep_num, Endpoint::EPNumber comm_ep_num, size_t rx_buffer_size=128, size_t tx_buffer_size=128, size_t tx_queue_size=5, const char *control_interface_string=CDCBase::DEFAULT_CONTROL_INTERFACE_STRING, const char *data_interface_string=CDCBase::DEFAULT_DATA_INTERFACE_STRING)
构造 CDC UART / Construct the CDC UART
Definition cdc_uart.hpp:65
void BindEndpoints(EndpointPool &endpoint_pool, uint8_t start_itf_num, bool in_isr) override
绑定端点并恢复配置前已排队的发送 / Bind endpoints and resume queued writes
Definition cdc_uart.cpp:8
void OnDataInComplete(bool in_isr, ConstRawData &data) override
在 IN 完成后请求推进发送 / Request TX progress after IN completion
Definition cdc_uart.cpp:21
void OnDataOutComplete(bool in_isr, ConstRawData &data) override
将 OUT 数据放入接收队列 / Enqueue completed OUT data
Definition cdc_uart.hpp:224
ErrorCode SetConfig(UART::Configuration cfg, bool in_isr=false) override
设置 CDC 线路编码 / Set CDC line coding
Definition cdc_uart.hpp:87
USB CDC 接收端口 / USB CDC receive port.
Definition cdc_uart.hpp:18
CDCUartReadPort(uint32_t size, CDCUart &owner)
构造接收端口 / Construct the receive port
Definition cdc_uart.hpp:25
ConstRawData pending_data_
待入队的端点数据 / Endpoint data awaiting enqueue
Definition cdc_uart.hpp:39
CDCUart & owner_
所属 CDC UART / Owning CDC UART
Definition cdc_uart.hpp:37
void OnReadQueueSpaceAvailable(bool in_isr) override
在接收队列腾出空间后恢复接收 / Resume reception when queue space is available
Definition cdc_uart.hpp:302
bool recv_pause_
接收暂停标志 / Receive pause flag
Definition cdc_uart.hpp:38
USB 端点基类 / USB Endpoint base class.
Definition ep.hpp:24
EPNumber
端点号 Endpoint number
Definition ep.hpp:42
USB端点池类 / USB endpoint pool class.
Definition ep_pool.hpp:29
基于 SPSC 字节队列的写端口 / Write endpoint backed by an SPSC byte queue.
LibXR 命名空间 / LibXR namespace.
Definition ch32_can.hpp:14
ErrorCode
定义错误码枚举 / Defines an enumeration for error codes
@ OK
操作成功 / Operation successful
@ ARG_ERR
参数错误 / Argument error
void(* WriteFun)(WritePort &port, bool in_isr)
写入进度通知函数类型 / Write progress notification function type.
UART 配置结构体 / UART configuration structure.
Definition uart.hpp:44
uint8_t stop_bits
停止位长度 / Number of stop bits
Definition uart.hpp:53
uint32_t baudrate
波特率 / Baud rate
Definition uart.hpp:45