4. USB协议与传输类型:控制传输、批量传输、中断传输、等时传输的特点与性能差异
USB协议定义了四种基本的传输类型,每种类型针对不同的应用场景设计,在带宽、延迟、可靠性和硬件开销上存在显著差异。在USB Gadget驱动开发中,选择合适的传输类型是性能调优的第一步。错误的传输类型选择可能导致吞吐量下降、CPU占用率飙升或实时性无法满足要求。
4.1 四种传输类型概述
USB规范将总线上的数据传输分为四种类型,分别对应不同的端点(Endpoint)属性。端点的bmAttributes字段决定了其传输类型。下表从核心维度对比了四种传输类型:
| 传输类型 | 典型端点 | 带宽保证 | 错误重试 | 延迟特性 | 最大包长(FS) | 最大包长(HS) | 典型应用 |
|---|---|---|---|---|---|---|---|
| 控制传输 | 端点0(双向) | 10% 保留 | 硬件重试,保证送达 | 中等,受限于握手 | 64字节 | 64字节 | 枚举、配置、命令 |
| 批量传输 | BULK IN/OUT | 无保证,利用空闲带宽 | 硬件重试,保证送达 | 高,取决于总线负载 | 8/16/32/64字节 | 512字节 | U盘、网卡、打印机 |
| 中断传输 | INTERRUPT IN/OUT | 保证轮询间隔 | 硬件重试,保证送达 | 低,可预测 | 1~64字节 | 1~1024字节 | 鼠标、键盘、HID设备 |
| 等时传输 | ISOCHRONOUS IN/OUT | 保证带宽 | 无重试,允许丢包 | 最低,固定延迟 | 1~1023字节 | 1~1024字节 | 音频、视频、摄像头 |
4.2 控制传输:可靠但低效的命令通道
控制传输是USB设备枚举和配置的基础,也是唯一必须实现的传输类型。它使用端点0,采用主机驱动的请求-应答模型。一次控制传输分为三个阶段:Setup阶段、Data阶段(可选)、Status阶段。
- Setup阶段:主机发送8字节的Setup包,包含请求类型、请求码、值和索引。
- Data阶段:根据Setup包的方向,传输数据。无数据请求则跳过此阶段。
- Status阶段:设备返回握手包确认完成,或主机发送OUT令牌结束传输。
控制传输的带宽被限制在总线带宽的10%以内(USB 2.0规范),且每次传输的协议开销较大。在Gadget驱动中,控制传输通常用于处理标准设备请求(如Get_Descriptor、Set_Configuration)和类特定请求(如CDC的Set_Line_Coding)。
4.3 批量传输:高吞吐量的主力
批量传输是USB Gadget驱动中最常用的传输类型,特别适合数据量大、实时性要求不高的场景,如USB存储、USB网卡(RNDIS/ECM)、USB串口等。批量传输利用总线上的空闲带宽,当总线空闲时,批量传输可以占据几乎全部带宽(约90%)。
批量传输的错误恢复机制由硬件自动完成:如果数据包在传输中出错(CRC校验失败),接收方不发送ACK,发送方超时后重传。这种机制保证了数据的可靠性,但也引入了延迟不确定性。
- wMaxPacketSize:USB 2.0高速模式下固定为512字节,USB 3.0 SuperSpeed下可达1024字节。
- bMaxBurst:USB 3.0引入,允许一次突发传输多个数据包,最大可达16个包(16 * 1024 = 16KB/事务)。
- 端点数量:批量端点通常成对出现(IN和OUT),Gadget驱动中需要合理分配DMA缓冲区。
以下是一个典型的USB Gadget批量端点初始化代码片段(基于Linux Kernel UDC框架):
/* 注册批量IN端点 */
struct usb_endpoint_descriptor bulk_in_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = USB_DIR_IN | 0x01, // EP1 IN
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = cpu_to_le16(512), // HS模式
.bInterval = 0, // 批量传输忽略此字段
};
/* 注册批量OUT端点 */
struct usb_endpoint_descriptor bulk_out_desc = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = USB_DIR_OUT | 0x02, // EP2 OUT
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = cpu_to_le16(512),
.bInterval = 0,
};
4.4 中断传输:低延迟的可靠通道
中断传输并非真正的中断,而是主机以固定的轮询间隔(bInterval)查询设备是否有数据需要传输。它保证了最大延迟,适合小数据量、低延迟、高可靠性的场景,如HID设备(鼠标、键盘)、游戏手柄、某些传感器设备。
中断传输的轮询间隔在USB 2.0高速模式下以125微秒(微帧)为单位,bInterval值表示间隔的微帧数。例如bInterval=4表示每4个微帧(500微秒)轮询一次。在USB 1.1全速模式下,以1毫秒(帧)为单位。
| USB速度 | 轮询单位 | bInterval范围 | 最小轮询间隔 | 最大轮询间隔 |
|---|---|---|---|---|
| 低速 (1.5 Mbps) | 1 ms (帧) | 10~255 | 10 ms | 255 ms |
| 全速 (12 Mbps) | 1 ms (帧) | 1~255 | 1 ms | 255 ms |
| 高速 (480 Mbps) | 125 μs (微帧) | 1~16 | 125 μs | 2 ms |
| 超速 (5 Gbps) | 125 μs (微帧) | 1~16 | 125 μs | 2 ms |
4.5 等时传输:确定性的实时通道
等时传输是唯一不保证数据可靠性的传输类型。它没有握手阶段和重试机制,数据包一旦出错就被丢弃。作为交换,等时传输提供了确定的带宽和固定的延迟,非常适合音频、视频、摄像头等流媒体应用。
等时传输的带宽在USB帧/微帧开始时由主机控制器预留。在USB 2.0高速模式下,每个微帧最多可预留80%的带宽(约480 MB/s * 80% = 384 MB/s),但实际可用带宽受限于端点数量和包大小。
等时端点的wMaxPacketSize字段还包含bMulti(事务数)信息,允许在一个微帧内进行多次事务(最多3次),以支持更高的数据率。
4.6 传输类型选择与性能对比SVG
下图从可靠性、延迟、带宽利用率、硬件复杂度四个维度对比四种传输类型,帮助Gadget驱动开发者快速做出选择:
4.7 传输类型选择决策流程
在USB Gadget驱动设计阶段,可以按照以下流程选择传输类型:
- 是否需要可靠传输? 是 → 进入步骤2;否 → 考虑等时传输(音频/视频流)。
- 数据量是否大于几百字节? 是 → 进入步骤3;否 → 考虑中断传输(HID/传感器)。
- 是否需要低延迟保证? 是 → 考虑中断传输(配合较大bInterval);否 → 使用批量传输(最高吞吐量)。
- 是否为控制/配置命令? 是 → 使用控制传输(端点0)。
- 批量传输:追求吞吐量时首选,注意DMA对齐和URB合并。
- 中断传输:追求低延迟时首选,bInterval是核心调优参数。
- 等时传输:追求确定性延迟时使用,需要处理丢包和欠载。
- 控制传输:仅用于枚举和配置,避免传输大数据。
4.8 传输类型与USB Gadget驱动性能的关系
在Linux USB Gadget子系统中,每种传输类型对应不同的UDC(USB Device Controller)硬件处理路径。批量传输通常使用DMA引擎进行数据搬运,中断传输可能触发每微帧的中断处理,等时传输则需要精确的时序管理。理解这些差异有助于在驱动层面进行针对性优化:
- 批量传输优化:增大URB缓冲区(如从16KB增加到64KB),减少中断次数;使用SG(Scatter-Gather)列表减少DMA映射开销。
- 中断传输优化:合理设置bInterval,避免过小导致中断风暴;使用NAPI或线程化中断减少上下文切换。
- 等时传输优化:预分配多个等时URB形成流水线;使用双缓冲(Double Buffering)避免欠载。
- 控制传输优化:尽量在Setup包的Data阶段完成数据交换,避免额外的状态阶段延迟。