2. USB批量传输协议基础

批量传输(Bulk Transfer)是USB体系中唯一提供数据完整性保证且不占用固定带宽的传输类型。在Gadget驱动中,批量传输是吞吐量优化的主战场。本节从端点特性、事务格式、数据包大小与NAK机制三个维度拆解批量传输的底层协议规则。

2.1 批量传输端点特性

批量端点与其他端点类型(控制、中断、同步)的关键区别在于:没有预留带宽,且硬件自动重试。下表列出批量端点的核心属性:

属性 批量端点 对比:中断端点 对比:同步端点
带宽保证 无(空闲时抢带宽) 有(轮询间隔保证) 有(固定带宽预留)
错误重试 硬件自动重试(直到成功) 硬件自动重试 无重试(允许丢包)
最大包大小(HS) 512字节 1024字节 1024字节
最大包大小(SS) 1024字节 1024字节 1024字节
事务方向 单向(IN/OUT独立端点) 单向 单向
流控机制 NAK握手 NAK握手 无流控
Gadget优化提示: 批量端点的“无带宽保证”特性意味着:当总线上同时存在同步或中断传输时,批量传输的延迟会显著增加。性能优化时,应优先确保批量端点在USB调度中的权重不被其他传输类型过度挤压。

批量端点必须成对使用(一个IN端点 + 一个OUT端点),且端点号通常从1开始(端点0为控制端点保留)。在Linux Gadget驱动中,批量端点通过 usb_ep 结构体描述,其 maxpacket 字段决定了单次传输的数据载荷上限。

2.2 批量传输事务格式

USB批量传输采用令牌-数据-握手三段式事务结构。每个批量事务由主机发起,包含三个连续的包阶段:

  1. 令牌包(Token Packet):主机发送OUT令牌(写设备)或IN令牌(读设备),包含设备地址和端点号。
  2. 数据包(Data Packet):数据源(主机OUT或设备IN)发送0~1024字节的数据载荷,附带CRC16校验。
  3. 握手包(Handshake Packet):接收方返回ACK(成功)、NAK(忙)或STALL(错误)。
关键规则: 批量传输不支持PING协议(仅同步和中断端点使用),流控完全依赖NAK握手。这意味着设备端必须通过硬件或软件及时响应事务,否则主机将反复重试同一事务。

下图展示一个完整的批量OUT事务(主机→设备)的包序列:

批量OUT事务包序列 OUT令牌 主机→设备 (地址+端点) 数据包 主机→设备 (0~1024B + CRC16) ACK/NAK 设备→主机 (握手响应) 批量事务:每个事务严格按 令牌→数据→握手 顺序执行,不可跨越

批量IN事务(设备→主机)的包序列与OUT对称,区别在于:

  • 令牌包为IN令牌(主机请求数据)。
  • 数据包由设备发送,主机接收。
  • 握手包由主机返回ACK(成功接收)或NAK(缓冲区满)。

2.3 数据包大小与最大包限制

批量传输的数据包大小受端点描述符中的wMaxPacketSize约束。不同USB速度下的批量最大包大小如下:

USB速度 批量最大包大小 每微帧事务数 理论峰值(单向)
全速(FS, 12 Mbps) 64字节 1 1.216 MB/s
高速(HS, 480 Mbps) 512字节 3(微帧内突发) 53.248 MB/s
超高速(SS, 5 Gbps) 1024字节 突发(Burst) >400 MB/s
常见陷阱: 批量传输的短包(Short Packet)规则:当数据长度小于wMaxPacketSize时,该包被视为传输结束(Transfer Complete)。Gadget驱动必须正确处理短包中断,否则可能导致数据粘包或丢失。

数据包大小对性能的影响体现在两个方面:

  • 协议开销占比:每个批量事务有20字节的协议开销(令牌+握手+帧间隔)。包越大,有效载荷占比越高。
  • DMA对齐:许多USB控制器要求DMA缓冲区地址和大小对齐到wMaxPacketSize边界,否则触发PIO模式,性能骤降。

下图展示不同包大小下的有效带宽利用率(假设HS 480 Mbps,忽略帧调度延迟):

批量包大小 vs 有效带宽利用率 批量包大小与有效带宽利用率(高速模式) 64B 利用率: 76% 128B 利用率: 86% 256B 利用率: 92% 512B 利用率: 96% 利用率 = 数据载荷 / (数据载荷 + 协议开销 + 帧间隔),协议开销约20字节/事务

2.4 NAK机制与流控

NAK(Negative Acknowledge)是批量传输的核心流控手段。当设备端无法立即处理数据时(如缓冲区满或DMA未就绪),硬件自动返回NAK握手包,通知主机重试当前事务。

NAK机制的工作流程如下:

  1. 主机发起批量事务(OUT或IN令牌)。
  2. 设备硬件检查端点状态:
    • 如果端点就绪(缓冲区可用):接收数据(OUT)或发送数据(IN),返回ACK。
    • 如果端点忙(缓冲区满/空):返回NAK,事务不完成。
  3. 主机收到NAK后,在当前微帧内立即重试同一事务(HS下最多3次/微帧)。
  4. 若连续NAK超过主机重试限制,主机将暂停该端点调度,等待下一微帧再试。
性能影响: 每次NAK意味着一个完整的事务时间片被浪费(约1μs @ HS)。如果Gadget驱动频繁NAK(例如中断处理延迟过高),有效带宽将急剧下降。优化目标是:将NAK率控制在1%以下。

下图展示NAK重试的时序细节:

NAK重试时序图 t0 t0+1μs t0+2μs t0+3μs OUT令牌 NAK 主机→设备 设备→主机 OUT令牌 NAK 主机→设备 设备→主机 OUT令牌 ACK 设备就绪,成功 高速模式下,主机可在同一微帧内连续重试最多3次NAK事务

在Gadget驱动层面,NAK的产生原因通常包括:

  • 中断延迟过高:CPU未能及时处理端点中断,导致硬件缓冲区未及时清空/填充。
  • DMA未完成:DMA传输正在进行,硬件FIFO被锁定。
  • 协议层背压:上层应用未及时消费数据,导致驱动层缓冲区满。
优化切入点: 使用 perf top 或 usbmon 监控NAK频率。如果NAK率超过5%,优先检查中断处理函数(IRQ handler)的执行时间,确保在10μs内完成端点服务。

2.5 批量传输的协议约束总结

下表汇总了批量传输协议中直接影响Gadget驱动性能的关键约束:

约束项 具体规则 性能影响
最大包大小 HS: 512B, SS: 1024B 包越小,协议开销占比越大
短包结束 小于wMaxPacketSize的包标记传输结束 需正确处理,避免数据截断
NAK重试 HS下每微帧最多3次重试 高NAK率导致带宽浪费
无PING协议 批量端点不支持PING流控 设备必须主动NAK,无法预查询
事务原子性 令牌-数据-握手不可分割 任何阶段失败都需整个事务重试