3. USB 2.0 高速协议回顾:高速事务类型与微帧结构

USB 2.0 高速(High-Speed, 480 Mbps)协议在事务层引入了比全速/低速更复杂的机制,包括微帧(Microframe)、PING 流控以及 SPLIT 拆分事务。理解这些基础结构是利用 xHCI 调试端口捕获和分析事务的前提。

3.1 微帧(Microframe)与帧结构

USB 2.0 全速模式下,每 1 ms 生成一个帧(Frame)。高速模式下,为了支持更低的延迟和更高的带宽利用率,将 1 ms 的帧进一步划分为 8 个微帧(Microframe),每个微帧持续 125 µs。

关键指标: 高速总线每 125 µs 发送一个 SOF(Start-of-Frame)包,SOF 包中的帧号(Frame Number)每 1 ms 递增一次,但微帧号(Microframe Number)隐含在 SOF 的时序中(0-7 循环)。
USB 2.0 高速微帧结构 1 帧 (Frame) = 1 ms 微帧 0 微帧 1 微帧 2 微帧 3 微帧 4 微帧 5 微帧 6 微帧 7 每个微帧 = 125 µs SOF 包在每个微帧起始发送;帧号每 8 个微帧递增一次

3.2 高速事务类型

USB 2.0 高速总线定义了 5 种核心事务类型,每种事务由不同的令牌包(Token Packet)标识。xHCI 调试端口捕获的每个事务包都对应以下类型之一:

事务类型 令牌 PID 方向 主要用途 高速特性
IN 0x69 (1001) 设备 → 主机 主机从端点读取数据 支持 NYET 握手
OUT 0xE1 (0001) 主机 → 设备 主机向端点发送数据 支持 PING 流控
SETUP 0x2D (1101) 主机 → 设备 控制传输的建立阶段 固定 8 字节数据
PING 0xB4 (0100) 主机 → 设备 查询端点是否可接收数据 高速专用,替代全速的 NAK 轮询
SPLIT 0x2C (1100) / 0xAC (0100) 主机 ↔ 集线器 高速主机与全速/低速设备通信 分为开始拆分(SSPLIT)和完成拆分(CSPLIT)
调试提示: 在 xHCI 调试端口捕获的数据中,PING 事务是高速总线独有的流量控制机制。如果捕获到大量连续的 PING 事务且设备回复 NAK,说明设备端点处于繁忙状态,需要检查设备固件或驱动调度。

3.3 数据包格式(高速层)

USB 2.0 高速数据包在物理层使用 NRZI 编码 并带有 位填充(Bit Stuffing)。每个事务由三个连续的包阶段组成(部分事务可能省略数据包或握手包)。

3.3.1 令牌包(Token Packet)格式

所有高速事务都以令牌包开始。令牌包由 PID(8 位)、地址/端点字段(11 位) 和 CRC5(5 位) 组成:

字节 0: [PID0-PID7]          — 包标识符(含反码校验)
字节 1-2: [ADDR6..ADDR0][ENDP3..ENDP0] — 设备地址 + 端点号
字节 2 (低5位): [CRC4..CRC0] — 5 位循环冗余校验

3.3.2 数据包(Data Packet)格式

高速数据包在 DATA0/DATA1 基础上增加了 DATA2 和 MDATA 类型,用于支持高带宽等时端点:

数据 PID 二进制值 用途 数据长度
DATA0 1100 0011 数据切换偶数帧 0-1024 字节
DATA1 0100 1011 数据切换奇数帧 0-1024 字节
DATA2 1011 0100 高带宽等时(微帧内第 2 个数据包) 0-1024 字节
MDATA 1111 0000 高带宽等时(微帧内第 3+ 个数据包) 0-1024 字节

数据包结构:

[SYNC] [PID (8位)] [DATA PAYLOAD (0-1024字节)] [CRC16 (16位)] [EOP]

3.3.3 握手包(Handshake Packet)格式

高速握手包只有 1 字节 PID,无 CRC:

握手 PID 二进制值 含义 高速特有
ACK 0010 1101 数据正确接收 —
NAK 1010 1011 设备忙,无法处理 —
STALL 0001 1110 端点挂起/错误 —
NYET 1001 0110 设备未准备好接收下一数据 ✓ 高速专用
ERR 0110 0001 拆分事务错误 ✓ 高速专用
USB 2.0 高速事务包序列 典型高速事务包序列(IN 事务示例) 令牌包 (IN PID + ADDR + CRC5) 数据包 (DATA0/1 + PAYLOAD + CRC16) 握手包 (ACK/NAK/NYET) IFG IFG 主机 → 设备 设备 → 主机 设备 → 主机 PING 事务与 OUT 事务的配合 1. 主机发送 PING 令牌包 → 设备回复 ACK(可接收)或 NAK(忙) 2. 若收到 ACK,主机立即发送 OUT 令牌包 + 数据包 → 设备回复 ACK/NYET 3. NYET 表示设备接收了数据但暂时无法处理下一笔,主机需再次 PING

3.4 SPLIT 拆分事务机制

当高速主机需要与全速(12 Mbps)或低速(1.5 Mbps)设备通信时,必须通过 USB 2.0 集线器 进行事务拆分。SPLIT 事务分为两个阶段:

  1. 开始拆分(SSPLIT):主机在高速微帧中向集线器发送令牌,集线器将其转换为全速/低速事务转发给下游设备。
  2. 完成拆分(CSPLIT):主机在后续微帧中向集线器查询事务结果,集线器返回设备的数据或握手。
调试陷阱: 在 xHCI 调试端口捕获的数据中,SPLIT 事务的令牌包 PID 与普通 IN/OUT 不同。SSPLIT 使用 0x2C,CSPLIT 使用 0xAC。如果调试端口只显示标准 IN/OUT 而看不到 SPLIT,说明捕获点位于集线器下游,而非主机控制器侧。

3.5 高速事务时序与带宽计算

每个微帧(125 µs)内可以调度多个事务。对于高速批量端点,每个微帧最多可传输 3 个 512 字节的数据包(受限于微帧带宽预算)。

传输类型 每微帧最大事务数 最大数据负载/微帧 典型延迟
控制(Control) 1 64 字节 高(保证交付)
批量(Bulk) 3 1536 字节 低(尽力而为)
等时(Isochronous) 3 3072 字节 最低(无重试)
中断(Interrupt) 1 1024 字节 中(轮询周期)
性能调优要点: 使用 xHCI 调试端口捕获事务时,关注每个微帧内的 总线空闲时间(Idle Time)。如果微帧内空闲时间占比超过 30%,说明调度效率不足,可以尝试增大端点请求大小或调整驱动批量提交深度。
微帧内批量事务调度示例 一个微帧(125 µs)内的批量事务调度 125 µs 批量事务 1 (512B) 批量事务 2 (512B) 批量事务 3 (512B) 空闲 空闲时间占比 = 70/740 ≈ 9.5% → 调度效率良好;若空闲 > 30% 需优化