USB协议概述:版本演进、物理层、电气特性与传输类型

搞Android驱动的人,天天都要和USB打交道。不管是调试用的ADB,还是外接U盘、鼠标、键盘,底层全是这套协议在跑。我个人习惯把USB协议栈想象成一栋楼——物理层是地基,协议层是框架,驱动层是装修。地基没打好,楼上再漂亮也白搭。

所以第一章,我们先把这个地基摸清楚。别嫌基础,我在项目里见过太多人因为忽略了物理层细节,折腾好几天才发现是D+、D-线序反了,或者VBUS压降太大导致设备枚举失败。嗯,这些都是血泪教训。

1.1 USB版本演进:从1.0到4.0

先看版本演进,这张表基本能说明一切:

版本 发布年份 标称速率 编码方式 接口形态
USB 1.0/1.1 1996/1998 1.5 Mbps (Low-Speed)
12 Mbps (Full-Speed)
NRZI + 位填充 Type-A/B
USB 2.0 2000 480 Mbps (Hi-Speed) NRZI + 位填充 Type-A/B/Micro
USB 3.0/3.1 2008/2013 5 Gbps (SuperSpeed)
10 Gbps (SuperSpeed+)
8b/10b Type-A/B/C
USB 3.2 2017 10/20 Gbps (双通道) 128b/132b (Gen2×2) Type-C
USB4 2019 40 Gbps 基于Thunderbolt 3协议 Type-C
实践经验:你在Android内核里看到的 usb_device_speed 枚举,就是根据版本信息来填充的。我调试过一台机器,插USB 3.0设备却只在2.0模式下跑,查到最后是Type-C接口的CC逻辑没配置对——硬件上走了USB 2.0差分对,根本没连SS引脚。

这里有个容易踩的坑。很多人以为USB 3.0直接把速度提升了10倍那么简单。其实不是。USB 3.0引入了全新的物理层——它增加了一组独立的SSTX/SSRX差分对,和原有的D+/D-完全隔离。也就是说,USB 3.0的线缆里实际上跑着两套总线。

为什么会这样做?兼容性。你插一个USB 3.0 U盘到USB 2.0接口,它能降级用;反过来USB 2.0设备插到3.0接口,也用不了高速。这套机制在Android的OTG驱动里经常要处理,后面章节会细说。

1.2 物理层:信号传输的实物基础

USB的物理层就这么几件事:一对差分信号线(D+/D-)、一根VBUS供电线、一根GND。USB 3.0以上再加一组SuperSpeed差分对。

差分信号为什么好?说白了,抗干扰能力强。D+和D-线上的信号是反相的,外部噪声对两根线的影响差不多,接收端一相减,噪声就被抵消了。我在项目中遇到过焊接D+线虚焊的情况,结果USB设备能检测到插入,但无法完成枚举——因为差分信号幅度不对称,主机端收不到正确的包。

电气特性方面,几个关键参数:

  • VBUS电压:标准值5V ±5%。OTG模式下Device可作为Host供电,至少提供5V/500mA。做手机USB充电侦测的时候,VBUS上的电压跳变直接影响状态机,不要只在软件层面想问题。
  • 终端电阻:全速/低速设备在D+/D-上分别有1.5kΩ上拉电阻,主机端有15kΩ下拉电阻。这个阻值决定了主机能否检测到设备。我曾经在产线上遇到一批USB鼠标插上没反应,最后发现是上拉电阻焊成了10kΩ——阻值不对,电平判定失败。
  • 信号电平:低速/全速下单端信号摆幅0~3.3V,差分信号要求至少0.2V的幅值差异。高速模式下要通过电流驱动,不是电压驱动。

1.3 传输类型:四种数据流动模式

USB协议定义了4种传输类型,每种解决的场景不同。我在Android USB驱动里基本都遇到过,来做一下对比:

传输类型 特点 典型应用 带宽保障 错误重传
控制传输 双向、可靠、低带宽 设备枚举、请求描述符、配置设备 10%(保留) 硬件自动重传
批量传输 可靠、无带宽保证、数据量大 U盘读写、ADB数据传输 尽力而为 CRC + 自动重传
中断传输 可靠、有延迟保证、数据量小 鼠标、键盘、HID设备 90%以内可配 CRC + 自动重传
实时传输 不可靠、有延迟保证、数据量大 USB摄像头、音频流 按带宽预留 无重传(数据过期重传无意义)

你想想看,U盘用批量传输,是因为它能容忍延迟但不能容忍数据错。摄像头用实时传输,是因为丢掉一帧画面还能接受,但如果等重传,画面就会卡住。这个设计理念在系统软件层面也是通用的。

控制传输是特殊的关键。任何USB设备接入后的第一件事,就是通过控制传输完成枚举。在Android中,USB Gadget驱动里处理设备枚举的代码可以说直接影响整个OTG功能的稳定性。

我踩过的坑:在调试某款手机的外接U盘功能时,一直卡在获取设备描述符的步骤。反复抓USB分析仪才发现,控制传输的Setup包被Gadget驱动错误地当成了数据包来处理。原因是没搞清楚控制传输的令牌阶段、数据阶段、状态阶段的时序差别。

1.4 协议框架概览:一张图理清整体知识脉络

我把前面讲的版本、物理层、传输类型、以及后续会展开的协议层次、驱动栈结构,画成一张框架图。你先对全章的内容有个俯瞰视角:

USB协议栈知识体系框架 USB 1.0/1.1 USB 2.0 USB 3.x USB4 USB版本演进 物理层 D+/D-差分对 | VBUS供电 终端电阻(1.5kΩ / 15kΩ) 信号电平 | SuperSpeed差分对 电气特性 VBUS 5V±5% | 差分信号抗干扰 上拉/下拉电阻判定 高速模式电流驱动 四种传输类型 控制传输 批量传输 中断传输 实时传输 Android OTG驱动栈 USB Gadget | DWC3/CI | PHY | 状态机 | 电源管理 后续章节展开 协议包格式 → 枚举流程 → OTG状态机 → 驱动开发实战 版本演进决定接口标准,物理层决定管脚定义 传输类型与应用场景强相关
本章核心要点:
  • USB各版本之间物理层不兼容(2.0 vs 3.0),但协议层面通过枚举协商降级。在Android驱动的PHY配置里,经常需要同时处理这两种模式。
  • 差分信号和终端电阻是硬件是否能被正确检测的关键。做OTG调试时,抓USB分析仪优先看D+/D-的电平是否产生正确的SE0和J/K状态。
  • 控制传输是USB设备的命门。Android中Gadget驱动的composite_bind()函数里,控制传输的端点0配置错一个参数,设备就上不了线。

这一章的内容算是开胃菜。你只要把版本差异、物理层参数、传输类型这三点记牢了,后面读USB框架驱动代码会顺畅很多。我在实际的Android OTG调试中,十之八九的问题都可以追溯到本章讲的某个细节——要么是终端电阻配置不对,要么是传输类型选错导致带宽不足。