1. USB 概述与历史
做嵌入式或驱动开发的同行,多半都跟 USB 打过交道。鼠标、键盘、U 盘、摄像头、调试线……一插一拔之间,背后其实是一套相当精巧的协议在运转。我个人最早接触 USB 是在一块 ARM9 板子上调 U 盘读写,那时候连描述符是什么都没搞懂,折腾了一周才把枚举跑通。今天我们先聊聊 USB 的来龙去脉,把底层的演进和常见场景理清楚,后面再深入描述符和枚举细节时会更顺。
USB 是怎么来的?
上世纪 90 年代,外设接口可谓“战国时代”:串口、并口、PS/2、Game Port……每种设备可能自带一根专用线缆,插拔还不支持热拔,速度也慢。Intel、Microsoft、IBM 等几家大厂实在看不下去了,1995 年联合推出了 USB 1.0 规范。目的很明确:统一接口、即插即用、热插拔、提供电源。
我印象很深,早期 USB 1.0 设备并不多,大部分人还在用 PS/2 键盘。直到 USB 1.1 把速度提到 12 Mbps(全速),才逐渐出现 U 盘、USB 鼠标这些产品。你想想看,当年一个 32MB 的 U 盘要卖两百多块,传输速度比现在的蓝牙还慢——但比起软盘已经算是飞跃了。
USB 标准发展脉络
从 1.0 到今天的 USB4,中间经历了多次重大升级。我习惯把主要版本整理成一张表,方便对照关键参数。
| 版本 | 发布时间 | 最高速率 | 信号层/编码 | 里程碑特征 |
|---|---|---|---|---|
| USB 1.0 | 1996年 | 1.5 Mbps (低速) | NRZI | 首个统一外设接口标准 |
| USB 1.1 | 1998年 | 12 Mbps (全速) | NRZI | 真正普及的开端 |
| USB 2.0 | 2000年 | 480 Mbps (高速) | NRZI + 微帧 | 引入微帧、小包传输、突发 |
| USB 3.0 | 2008年 | 5 Gbps (SuperSpeed) | 8b/10b + 差分对增加 | 双总线架构(SS + 2.0) |
| USB 3.1 | 2013年 | 10 Gbps (SuperSpeed+) | 128b/132b | 编码效率提升,Type-C 开始部署 |
| USB 3.2 | 2017年 | 20 Gbps (双通道) | 128b/132b ×2 | 双通道复用 Type-C 线缆 |
| USB4 | 2019年 | 40 Gbps | 基于 Thunderbolt 3 协议 | 隧道协议、动态带宽分配、兼容 DP/PCIe |
从 USB 1.0 到 USB4,我经历的演进
我最早做 USB 驱动是在 2005 年左右,那时 USB 2.0 刚普及不久。调试一个高速 HID 设备,经常因为描述符长度写错导致枚举失败。举个例子:USB 2.0 引入了微帧(Microframe)概念,把 1ms 帧拆成 8 个 125µs 微帧,才能做到 480 Mbps 的实时调度。很多初次接触的朋友不理解为什么端点的 wMaxPacketSize 最大只能到 1024 字节——说白了就是因为高速模式下一个微帧只能传输这么多数据。
到了 USB 3.0,变化更大。它不再是单纯提升速率,而是加了一套并行的超高速总线。你插一个 USB 3.0 U 盘到电脑,主机首先通过 2.0 那套走线完成设备识别,然后切换成超高速链路干活。我遇到过最头疼的问题:某款设备在 USB 3.0 端口上枚举始终拿不到配置描述符,用逻辑分析仪抓包才发现是超高速终端的链路训练没有完成——根本原因在于 Type-A 插头的 D+/D- 和 SS 差分对之间的串扰。
USB4 时代我接触不多,但最近在做 Thunderbolt 兼容性测试。USB4 本质上把 Thunderbolt 3、DisplayPort 和 PCIe 都 Tunnel 在一起,主机可以动态给不同流量分配带宽。举个例子:你接一个 4K 显示器和一块 NVMe 硬盘,USB4 控制器会自动给显示器留足带宽,剩下的分给硬盘。这种灵活性是以前 USB 3.x 无法想象的。
常见应用场景
USB 之所以能取代那么多旧接口,靠的就是场景全覆盖。我把最常见的几类整理一下,后面调试描述符时你会频繁遇到对应的设备类规范。
- 存储类(Mass Storage):U盘、移动硬盘、读卡器。使用 BOT(Bulk-Only Transport)或 UASP 协议。注意:有些低速 MCU 实现的 MSD 设备在描述符里把端点大小设小了,主机端驱动就会陷入反复重试。
- 输入设备(HID):键盘、鼠标、游戏杆、条形码扫描器。描述符里需要定义 Report Descriptor,结构稍微复杂一点。我建议新手先用 HID 类做入门调试,因为不需要装单独驱动。
- 通信类(CDC):虚拟串口、调制解调器、网络适配器。很多嵌入式设备通过 USB CDC ACM 模拟串口,枚举时至少需要两个接口:一个管理接口(通信类)和一个数据接口(数据类)。当年我在调试时忘了配数据接口,结果设备连上后主机只能识别但打不开串口。
- 视频类(UVC):摄像头、视频采集卡。UVC 描述符里要声明格式、帧率、色彩空间等信息,相对复杂。不过随着 USB3.0 带宽增加,4K 摄像头也普遍采用 UVC 了。
- 音频类(UAC):麦克风、音箱、声卡。USB 音频描述符会定义音频控制接口和音频流接口,频点、采样率、位深都需枚举给主机。
- 大容量传输(MTP):手机文件传输、数码相机。MTP 基于 USB Mass Storage 扩充,但设备端更像一个文件系统服务器,枚举过程和普通 MSD 略有不同。
一句话总结:USB 就是靠一套通用的枚举流程——获取设备描述符、配置描述符、接口描述符、端点描述符——让主机知道“你是什么设备,该用什么驱动”。后面 29 章我们就是围绕这套枚举流程一点一点拆解。
USB 演进知识体系图
下面这张 SVG 图把 USB 发展的关键节点和速度提升串联起来,你扫一眼就能建立整体印象。
曾经踩过的坑:我第一次用 USB 3.0 飞线调试设备时,没注意超高速差分对需要等长布线,结果链路训练始终过不去,逻辑分析仪抓出来全是「训练失败重试」。后来查规范才知道 SS 对间 skew 要求极严。如果你的板子枚举不稳定,先检查物理层。