1. USB协议基础
1.1 USB总线发展历史
通用串行总线(Universal Serial Bus,USB)自1996年正式发布以来,经历了多个版本的演进,每一次迭代都带来了带宽、供电能力和协议功能的显著提升。下表总结了各主要版本的关键参数:
| 版本 | 发布时间 | 理论带宽 | 信号速率 | 编码方式 | 供电能力 |
|---|---|---|---|---|---|
| USB 1.0 / 1.1 | 1996 / 1998 | 1.5 Mbps (Low-Speed) 12 Mbps (Full-Speed) | 1.5 / 12 Mbps | NRZI + 位填充 | 5V / 500 mA |
| USB 2.0 | 2000 | 480 Mbps (High-Speed) | 480 Mbps | NRZI + 位填充 | 5V / 500 mA |
| USB 3.2 Gen 1×1 | 2008 (USB 3.0) | 5 Gbps (SuperSpeed) | 5 Gbps | 8b/10b | 5V / 900 mA |
| USB 3.2 Gen 2×1 | 2013 (USB 3.1) | 10 Gbps (SuperSpeed+) | 10 Gbps | 128b/132b | 5V / 900 mA |
| USB 3.2 Gen 2×2 | 2017 | 20 Gbps | 10 Gbps × 2 通道 | 128b/132b | 5V / 1.5 A (BC 1.2) |
| USB4 Gen 3×2 | 2019 | 40 Gbps | 20 Gbps × 2 通道 | 64b/66b | 5V / 3 A (USB PD) |
关键理解:USB 2.0 之前的版本使用半双工共享总线架构,而 USB 3.x 引入了独立的发送/接收差分对,实现了全双工通信。USB4 则进一步融合了 Thunderbolt 3 协议,支持隧道传输(PCIe、DisplayPort)。
1.2 USB物理拓扑结构
USB 采用星型-菊花链混合拓扑,由主机(Host)、集线器(Hub)和设备(Device)三级构成。主机控制器位于根集线器(Root Hub)之上,最多支持 127 个设备地址(地址 0 保留给未配置设备)。
拓扑规则:最大层级深度为 7 层(包括根集线器),每个集线器最多连接 7 个下游端口。物理连接必须构成树形结构,不允许环路。
1.3 USB电气特性
USB 总线使用差分信号传输数据,并同时提供VBUS(+5V)和GND电源线。不同速度模式下的电气参数差异显著:
| 速度模式 | 信号电平 | 终端电阻 | 电缆最大长度 | 驱动方式 |
|---|---|---|---|---|
| Low-Speed (1.5 Mbps) | 差分 0~3.3V | 上游 15 kΩ 下拉 下游 1.5 kΩ 上拉 (D-) | 5 m | 电压驱动 |
| Full-Speed (12 Mbps) | 差分 0~3.3V | 上游 15 kΩ 下拉 下游 1.5 kΩ 上拉 (D+) | 5 m | 电压驱动 |
| High-Speed (480 Mbps) | 差分 0~400 mV | 45 Ω 对地 (D+/D-) | 5 m | 电流驱动 |
| SuperSpeed (5 Gbps) | 差分 0~1.0V | 100 Ω 差分终端 | 3 m | 电流驱动 + 去加重 |
工程注意:USB 2.0 High-Speed 模式下,D+ 和 D- 上的终端电阻从 Full-Speed 的 1.5 kΩ 上拉切换为 45 Ω 对地,这是由集线器或主机在握手阶段通过 Chirp 信号动态配置的。驱动开发中,终端电阻的检测是枚举流程中判断设备速度等级的关键依据。
1.4 USB数据流模型
USB 的数据传输采用主机驱动的轮询模型,所有通信均由主机发起。数据流在逻辑上分为四个层级:
- 应用层(Client Software):设备驱动程序与用户空间交互,通过 URBs(USB Request Blocks)与 USB 核心层通信。
- USB 系统软件层(USB Core / HCD):Linux 内核中的 USB 核心子系统,负责协议解析、带宽管理、设备枚举。
- 主机控制器层(Host Controller):硬件实现 OHCI / UHCI / EHCI / xHCI 规范,管理事务处理列表。
- 物理层(Bus Interface):差分信号、包编码、位填充、CRC 校验。
1.4.1 传输类型与数据流特征
USB 规范定义了四种传输类型,每种类型对应不同的数据流模型和带宽保证:
| 传输类型 | 方向 | 带宽保证 | 错误重试 | 典型应用 | 最大包大小 (FS/HS/SS) |
|---|---|---|---|---|---|
| 控制传输 | 双向 | 10% 保留 | 硬件重试 | 枚举、配置、命令 | 64 / 64 / 512 |
| 批量传输 | 单向 | 尽力而为 | 硬件重试 | 存储、打印机、网络 | 64 / 512 / 1024 |
| 中断传输 | 单向 | 保证延迟 | 硬件重试 | HID 键盘/鼠标、游戏杆 | 64 / 1024 / 1024 |
| 等时传输 | 单向 | 保证带宽 | 无重试 | 音频、视频、实时数据 | 1023 / 1024 / 1024 |
驱动开发要点:在 Linux 内核中,每种传输类型对应不同的 URB 处理函数和完成回调。批量传输适合大数据量但无实时要求的场景;中断传输适合周期性小数据;等时传输必须处理丢包,因为硬件不自动重试。控制传输是所有设备枚举的必经之路,必须优先实现。
1.4.2 数据流单元:包、事务与传输
USB 数据流在物理层以包(Packet)为最小单位,多个包组成事务(Transaction),多个事务构成一次传输(Transfer)。以批量 OUT 传输为例:
传输 (Transfer)
├── 事务 1 (Transaction)
│ ├── 令牌包 (Token Packet): OUT + 地址 + 端点
│ ├── 数据包 (Data Packet): DATA0 / DATA1 + 数据负载 + CRC16
│ └── 握手包 (Handshake Packet): ACK / NAK / STALL
├── 事务 2
│ ├── 令牌包: OUT + 地址 + 端点
│ ├── 数据包: DATA0 / DATA1 (切换同步)
│ └── 握手包: ACK
└── ... (直到传输完成)
数据切换(Data Toggle)机制:USB 使用 DATA0 和 DATA1 交替发送来保证数据完整性。主机和设备各自维护一个 toggle 位,只有 toggle 匹配的数据包才会被接收。驱动开发中,toggle 同步错误是常见的枚举失败原因之一,通常需要复位端点或重新配置接口。