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字节 音频、视频、摄像头
性能调优要点:批量传输虽然带宽利用率高,但延迟不可预测;中断传输适合低延迟小数据量场景;等时传输牺牲可靠性换取确定性延迟。Gadget驱动中,批量端点的bMaxBurst(SuperSpeed下的突发传输)和中断端点的bInterval(轮询间隔)是关键的调优参数。

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)。

性能陷阱:不要在控制传输中传输大量数据(如超过几百字节)。控制传输的Setup阶段和Status阶段引入了额外的总线事务,吞吐量远低于批量传输。如果需要在枚举后传输大量数据,应切换到批量或中断端点。

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
调优建议:对于Gadget驱动中的中断端点,bInterval的设置需要权衡延迟和CPU开销。过小的bInterval(如1)会导致主机频繁轮询,增加总线负载和CPU中断频率;过大的bInterval则可能使设备响应变慢。对于鼠标等需要快速响应的设备,建议bInterval=1~4(125~500μs)。

4.5 等时传输:确定性的实时通道

等时传输是唯一不保证数据可靠性的传输类型。它没有握手阶段和重试机制,数据包一旦出错就被丢弃。作为交换,等时传输提供了确定的带宽和固定的延迟,非常适合音频、视频、摄像头等流媒体应用。

等时传输的带宽在USB帧/微帧开始时由主机控制器预留。在USB 2.0高速模式下,每个微帧最多可预留80%的带宽(约480 MB/s * 80% = 384 MB/s),但实际可用带宽受限于端点数量和包大小。

等时端点的wMaxPacketSize字段还包含bMulti(事务数)信息,允许在一个微帧内进行多次事务(最多3次),以支持更高的数据率。

Gadget驱动注意事项:等时传输对DMA缓冲区的管理要求更高。由于没有重试机制,驱动必须确保数据在USB帧边界前准备好,否则会导致欠载运行(Underrun),产生数据空洞。在Linux UDC驱动中,等时端点通常需要更大的环形缓冲区(Ring Buffer)来吸收主机和设备之间的处理延迟差异。

4.6 传输类型选择与性能对比SVG

下图从可靠性、延迟、带宽利用率、硬件复杂度四个维度对比四种传输类型,帮助Gadget驱动开发者快速做出选择:

USB四种传输类型性能对比雷达图 可靠性 带宽利用率 低延迟 确定性 硬件开销 控制 批量 中断 等时 控制传输 批量传输 中断传输 等时传输 雷达图越靠近外圈表示该维度 性能越好。等时在低延迟和确定性 上最优,但可靠性最差。

4.7 传输类型选择决策流程

在USB Gadget驱动设计阶段,可以按照以下流程选择传输类型:

  1. 是否需要可靠传输? 是 → 进入步骤2;否 → 考虑等时传输(音频/视频流)。
  2. 数据量是否大于几百字节? 是 → 进入步骤3;否 → 考虑中断传输(HID/传感器)。
  3. 是否需要低延迟保证? 是 → 考虑中断传输(配合较大bInterval);否 → 使用批量传输(最高吞吐量)。
  4. 是否为控制/配置命令? 是 → 使用控制传输(端点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阶段完成数据交换,避免额外的状态阶段延迟。