2、批量传输协议基础:USB批量传输的端点特性、事务格式(令牌、数据、握手包)

批量传输(Bulk Transfer)是 USB 协议中用于传输大量数据、且对传输延迟不敏感的主要传输类型。它利用 USB 总线上的空闲带宽进行传输,当总线繁忙时,批量传输会被挂起,直到有可用带宽。本章将深入剖析批量传输的端点特性、事务格式以及构成事务的三个基本阶段:令牌包、数据包和握手包。

2.1 批量传输端点特性

批量端点(Bulk Endpoint)是 USB 设备中实现批量传输的硬件逻辑单元。与中断端点或等时端点不同,批量端点具有以下核心特性:

特性 描述 关键参数
传输方向 分为 IN(设备到主机)和 OUT(主机到设备)两种。一个批量端点只能支持单一方向。 端点描述符中的 bEndpointAddress 的 bit7 指示方向。
数据负载 全速(Full Speed)模式下最大包大小为 8、16、32 或 64 字节;高速(High Speed)模式下固定为 512 字节。 端点描述符中的 wMaxPacketSize 字段。
错误重试 支持硬件级别的错误检测与重传。若数据包或握手包出错,事务会被重试。 通过 CRC 校验和 PID 验证实现。
带宽保证 无固定带宽保证。批量传输仅在总线空闲时进行,优先级低于中断和等时传输。 由主机控制器(EHCI)的调度策略决定。
数据流控制 通过握手包中的 NYET(高速模式)或 NAK 实现流控。设备未准备好时返回 NAK,主机将重试。 NYET 仅在高速批量 OUT 事务中使用。
PING 协议 高速批量 OUT 端点使用 PING 协议探测设备接收能力,避免无效数据发送。 通过 PING 令牌包和 NYET/ACK 握手包实现。
开发提示: 在 EHCI 驱动中配置批量端点时,必须正确设置 wMaxPacketSize 为 512(高速),否则会导致数据包分割错误。同时,批量端点的 bEndpointAddress 中的方向位不可更改,IN 和 OUT 必须使用不同的端点号。

2.2 批量事务格式

一个完整的批量事务由三个连续的阶段组成:令牌阶段、数据阶段和握手阶段。每个阶段都通过一个独立的 USB 包(Packet)实现。下图展示了批量 IN 事务和批量 OUT 事务的标准流程。

批量事务标准流程(IN / OUT) 批量 IN 事务: 令牌包 (IN) 数据包 (DATA0/1) 握手包 (ACK/NAK) 主机 → 设备 设备 → 主机 主机 → 设备 批量 OUT 事务: 令牌包 (OUT) 数据包 (DATA0/1) 握手包 (ACK/NAK) 主机 → 设备 主机 → 设备 设备 → 主机 令牌包 数据包 握手包

2.3 事务阶段详解

2.3.1 令牌阶段(Token Stage)

令牌阶段由主机发送一个令牌包(Token Packet)开始。令牌包定义了后续事务的类型和方向。批量传输使用以下三种令牌:

  • OUT 令牌(PID = 0x01): 通知设备主机将要发送数据。令牌包中包含设备地址和端点号。
  • IN 令牌(PID = 0x09): 通知设备向主机发送数据。令牌包中包含设备地址和端点号。
  • PING 令牌(PID = 0x04): 高速批量 OUT 专用。主机在发送数据前先探测设备是否准备好接收。设备以 NYET 或 ACK 响应。
令牌包结构: 同步域(SYNC, 8位)+ 包标识符(PID, 8位)+ 地址域(ADDR, 7位)+ 端点域(ENDP, 4位)+ CRC5(5位)+ 包结束(EOP)。PID 的低 4 位为类型,高 4 位为校验位。

2.3.2 数据阶段(Data Stage)

数据阶段承载实际的有效载荷。批量传输使用 DATA0 和 DATA1 两种数据包 PID 进行交替翻转(Toggle),以实现数据同步和错误恢复。

  • DATA0 包(PID = 0xC3): 用于事务序列中的第一个数据包。
  • DATA1 包(PID = 0x4B): 用于事务序列中的第二个数据包,之后交替使用。

数据包的最大有效载荷由端点的 wMaxPacketSize 决定。高速批量端点每次最多传输 512 字节。如果传输的数据量超过此值,主机控制器会将其分割为多个连续的事务,每个事务携带一个数据包,并正确维护数据切换序列。

数据切换同步: 主机和设备的批量端点各自维护一个数据切换序列位(Data Toggle Bit)。主机发送 DATA0 后,期望设备返回 ACK,然后切换为 DATA1。如果设备返回 NAK,主机必须重发相同的 DATA0 包,不得切换序列。EHCI 控制器通过 qTD 描述符中的 Toggle 位自动管理此过程。

2.3.3 握手阶段(Handshake Stage)

握手阶段由接收方返回一个握手包,报告事务的接收状态。批量传输中使用的握手包包括:

握手包 PID 含义 使用场景
ACK 0xD2 数据正确接收,无错误。 IN 事务中主机发送;OUT 事务中设备发送。
NAK 0x5A 设备暂时无法发送或接收数据(忙状态)。 IN 事务中设备无数据;OUT 事务中设备缓冲区满。
NYET 0x96 高速批量 OUT 事务中,设备尚未准备好接收下一个数据包。 仅高速模式,设备在 PING 响应或 OUT 事务握手阶段使用。
STALL 0x1E 端点发生不可恢复的错误,或端点被主机强制设置为 Halt 状态。 设备返回 STALL 后,主机需通过控制传输清除端点停止状态。

2.4 批量传输数据流与错误恢复

批量传输的可靠性建立在错误检测与重试机制之上。下图展示了批量 OUT 事务中可能出现的错误场景及恢复流程。

批量 OUT 事务错误恢复流程 正常流程: OUT 令牌 DATA0 ACK 成功,切换 Toggle NAK 重试: OUT 令牌 DATA0 NAK 重发相同 DATA0,不切换 Toggle STALL 错误: OUT 令牌 DATA0 STALL → 主机停止端点,需控制传输清除

2.5 批量传输与 EHCI 调度

在 EHCI 主机控制器中,批量传输的调度遵循以下原则:

  1. 异步调度列表: 批量传输被组织在异步调度列表(Async List)中。EHCI 在每个微帧(Microframe)中轮询此列表,处理批量请求。
  2. 带宽回收: 批量传输利用每个微帧中未被中断或等时传输占用的剩余带宽。EHCI 通过 PeriodicListBase 和 AsyncListAddr 寄存器管理两种调度列表。
  3. 事务重试: 当批量事务因 NAK 失败时,EHCI 不会立即重试,而是将 qTD 保留在异步列表中,等待下一次调度轮询。这避免了总线被 NAK 风暴淹没。
  4. PING 协议优化: 对于高速批量 OUT 端点,EHCI 可以启用 PING 协议。在发送数据前先发送 PING 令牌,若设备返回 NYET,则主机推迟数据发送,避免无效的 OUT 事务。
EHCI 配置要点: 在 EHCI 驱动中,批量传输的 qTD 描述符必须设置 Active 位为 1,并正确初始化 Alternate Next 指针。对于高速批量端点,Mult 字段(在 qTD 的 dwToken 中)应设置为 0,表示每个微帧只处理一个事务。

2.6 批量传输应用场景

批量传输广泛应用于以下设备类型:

  • 大容量存储设备(Mass Storage): U 盘、移动硬盘、SD 卡读卡器。批量传输用于传输文件数据块。
  • 打印机(Printer): 传输打印作业数据。
  • 网络适配器(Ethernet Adapter): 传输网络数据包。
  • 数据采集设备: 如 USB 示波器、逻辑分析仪,用于传输采样数据。