USB 协议基础:USB 2.0 / 3.0 协议简介与传输类型
做 OTG 调优,绕不开协议本身。今天咱把 USB 2.0 和 3.0 的核心概念捋一遍,顺便聊聊控制、批量、中断、同步四种传输类型,以及最底层的数据包结构。这些东西不是死记硬背的,你在调试波形、分析抓包时,每个字段都会对应到实际现象。
从 USB 2.0 到 3.0:变与不变
先说个总印象。USB 2.0 是半双工,一根差分对(D+ / D-)负责所有传输。USB 3.0 加了一套独立的高速差分对(SSTX / SSRX),变成了全双工。我最早接触 USB 3.0 时有个误区——以为所有的 2.0 特性都升级了。其实不是,控制、批量、中断、同步这些逻辑类型在两代协议里基本一致,只是物理层和链路层天差地别。
关键对比点: USB 2.0 用 帧/微帧 来调度传输,USB 3.0 改用 DPP(Device Packet Protocol) 加流控机制。但这不影响应用层看到的传输类型。
四种传输类型——你的外设该选哪个?
USB 规范定义了四种传输类型:控制、批量、中断、同步。每种都有固定的端点属性和调度要求。我习惯把它们比作快递服务:控制是挂号信,批量是卡车运输,中断是加急件,同步是实时直播流。
1. 控制传输(Control Transfer)
用于设备枚举、标准请求,比如获取描述符、设置配置。每个设备必须有一个默认控制端点(端点 0)。控制传输分三个阶段:Setup / Data(可选)/ Status。数据阶段可以双向,但最常用的还是主机发起的控制请求。
- 典型场景: 插拔识别、配置接口、HID 报告描述符获取。
- 带宽占用: 10% 常驻预留,不能做大流量。
- 我踩过的坑: 曾经用控制传输批量输出日志,结果枚举时反复超时,因为控制端点一次只能处理一个请求,排队多了就丢。
2. 批量传输(Bulk Transfer)
最常用,也是最需要调优的类型。批量传输没有带宽保证,但出错后自动重试,适合打印机、U 盘、数据采集这类非实时的大量数据。
调优提示: USB 2.0 批量传输最大包大小是 512 字节,USB 3.0 升到 1024 字节,而且可以开启单次突发(Burst)传输,一个微帧里连续发多个包。我在做硬盘加密卡时,把包大小从 512 改成 1024,配合队列深度优化,吞吐量直接翻了一倍。
3. 中断传输(Interrupt Transfer)
名义上叫“中断”,其实和硬件中断不是一回事。它是主机轮询端点,定时获取数据。USB 2.0 轮询间隔最小 1 微帧(125 μs),USB 3.0 间隔可以更小,但实际受总线调度影响。
- 适用场景: 鼠标、键盘、游戏手柄。
- 注意: 中断传输有最大延迟保证,但不保证带宽。
你应该遇到过鼠标偶尔跳帧,往往不是鼠标坏了,是轮询间隔太大了。我习惯把快速鼠标的轮询间隔设成 1 ms(USB 2.0 下就是 8 个微帧),再低的话主机可能拒绝。
4. 同步传输(Isochronous Transfer)
专门对付实时流,比如音频、视频、工业相机。同步传输不保证成功送达——它没有重试机制。你想想看,USB 麦克风如果因为丢了一个包就重传,录音直接卡顿,反而不如丢掉那一个采样。
| 特性 | 控制 | 批量 | 中断 | 同步 |
|---|---|---|---|---|
| 保证传输 | 是 | 是(重试) | 是(重试) | 否(无重试) |
| 带宽保证 | 10% 预留 | 无 | 有最高延迟 | 有固定带宽 |
| 最大包大小(2.0) | 64 B | 512 B | 64 B(低速)/ 1023 B(全速) | 1023 B |
| 最大包大小(3.0) | 64 B | 1024 B | 1024 B | 1024 B(可突发) |
数据包结构——从 到 Handshake
USB 2.0 的包格式简单:每个事务由 包 + Data 包(可选)+ Handshake 包构成。 包指明设备地址和端点。Data 包包含实际数据。Handshake 包给 ACK、NAK、STALL。我记得刚学 USB 时,抓了个枚举过程,看到 ACK 一直以为是好信号,结果发现设备一直 NAK,主机只能轮询等待,浪费了很多时间。
// USB 2.0 令牌包格式(以 IN 事务为例)
字节0: PID (0x96 = IN)
字节1-2: 设备地址 (7bit) + 端点号 (4bit)
+ CRC5 (5bit)
字节3: 包结束 EOP
USB 3.0 的包结构复杂得多。它取消了传统 包,用链路层包(Header Packet) + 数据包(Data Packet)区分,并且每个包都有 LCRC 和链路层确认。你看 3.0 的抓包,会发现多了很多 LTSSM(链路训练)状态,比如 Polling、Recovery。这不是故障,是正常的链路管理。
避坑: 你做 OTG 调试时,如果看到 USB 3.0 链路反复退出 U0 进入 U1/U2/U3 低功耗状态,千万不要直接关掉电源策略。有时只是线缆太长导致信号不稳定,触发链路训练。我曾经贴了铝箔屏蔽线解决过一例。
一张图看懂本章知识脉络
上图展示了两代协议共用四种传输类型,但数据包结构完全不同。做调优时,你得时刻记住当前工作在哪个协议版本下——写固件时经常要查 usb_ctrlrequest 结构体里的 bMaxPacketSize,写错了枚举就会卡住。
避坑指南:传输类型选错会怎样?
- 把中断当批量用: 主机规定轮询间隔,你的数据量一大,就被截碎成小包,吞吐上不去。
- 把批量当同步用: 批量传输的实时性没法保证,直播流一旦被前面的大包堵塞,画面直接卡成幻灯片。
- 忽略端点描述符的 bInterval: 我接手过一个 USB 音频项目,播放时莫名爆音,查了两天发现中断端点的 bInterval 写成了 0,规范不允许,主机根本不认。
我的个人习惯: 设计 OTG 设备时,先把四个传输类型的典型用途列在纸上,然后给每个数据流画一条“端点到端点”的带宽预算线。这样既不会错选类型,也能提前发现瓶颈。