1. USB协议简介
做硬件调试这些年,我拆过的设备、抓过的波形不计其数。但不管遇到多刁钻的问题,最后都得回到最基础的东西——协议本身。今天咱们就从USB的根儿上聊起,把那些基础概念掰扯清楚。
1.1 USB标准发展史
USB这东西,说白了就是解决设备怎么连电脑的问题。我最初接触USB是2001年,那时候大部分设备还在用串口并口,插个鼠标都要重启机器。
| 版本 | 发布时间 | 理论速率 | 标志性变化 |
|---|---|---|---|
| USB 1.0 / 1.1 | 1996 / 1998 | 1.5 Mbps / 12 Mbps | 取代串口/并口,支持热插拔 |
| USB 2.0 | 2000 | 480 Mbps | 高速模式引入,兼容1.x设备 |
| USB 3.0 | 2008 | 5 Gbps | 增加一对差分线,全双工 |
| USB 3.1 | 2013 | 10 Gbps | Gen2编码改为128b/132b |
| USB 3.2 | 2017 | 20 Gbps | 双通道,Type-C独享 |
| USB4 | 2019 | 40 Gbps | 基于Thunderbolt 3,动态带宽分配 |
核心要点:USB 2.0和之前是半双工,数据线只有D+/D-两条。从USB 3.0开始变成全双工,多了SSTX+/SSTX-和SSRX+/SSRX-两对独立的差分线。这个变化直接影响了咱们后面的链路训练分析。
为什么突然这么多版本?其实每次升级都是被应用逼出来的。我记得2010年左右,高清摄像头、外置硬盘越来越多,USB 2.0的480 Mbps根本不够用,一个蓝光电影拷半天。USB 3.0出来之后大家才松了口气。
调试小经验:我习惯看设备插上后系统的枚举信息。USB 2.0设备枚举速度明显比3.0慢,因为握手步骤更多。如果你发现插一个3.0设备但系统只识别成2.0,多半是链路训练没通过,降级了。
1.2 USB2.0与USB3.x的关键区别
很多刚入行的工程师会把USB 2.0和USB 3.0搞混。其实从物理层开始它们就是两套东西。
- 物理层差异:USB 2.0用D+/D-两根线,半双工;USB 3.x新增SSTX/SSRX两对差分线,收发独立,全双工。
- 编码方式:USB 2.0是NRZI编码加位填充;USB 3.0是8b/10b编码;USB 3.1 Gen2开始是128b/132b。
- 电源管理:USB 2.0只有Suspend状态;USB 3.x有U0/U1/U2/U3多个链路状态,功耗控制更精细。
| 对比项 | USB 2.0 | USB 3.x |
|---|---|---|
| 信号线数量 | 2条(D+/D-) | 6条(D+/D- + SSTX+/SSTX- + SSRX+/SSRX-) |
| 传输模式 | 半双工,主机轮询 | 全双工,异步 |
| 终端匹配 | 端点匹配在设备端 | 链路两端都有匹配 |
| 链路训练 | 无,直接上电识别速率 | 有完整的LTSSM状态机 |
| 数据包结构 | + Data + Handshake | Packet + Link Command + Data |
我个人觉得,调试USB 2.0相对简单,信号稳定度要求没那么高。但USB 3.x就麻烦多了,5 Gbps的信号对阻抗、线长、去耦电容都很敏感。我记得有次调一个USB 3.0的摄像头,插上之后时好时坏,波形看是眼图闭合。最后发现是PCB上差分线走线绕了个弯,等长没做好。
注意:USB 2.0和3.x的电源管理完全不同。3.x的U1/U2/U3状态切换非常频繁,如果链路训练出了偏差,设备可能会不断进出低功耗状态,表现就是设备间歇性断开重连。这坑我踩过不止一次。
1.3 USB拓扑结构
你想想看,一个USB口能接那么多设备,靠的是啥?靠的就是树形拓扑。主机在最上面,Hub在中间,设备在最下面。
这块内容跟咱们链路训练关系很大。为什么?因为USB 3.x的链路训练是在每一条链路独立进行的。主机和第一个Hub之间是一条链路,Hub和U盘之间又是一条链路。你可能会问,主机怎么找到新插上去的设备?
嗯,这里要注意:枚举过程是有层级的。设备插上,Hub检测到信号变化,通知主机。主机发命令给Hub,让Hub复位这个端口,然后开始枚举。每次Hub只暴露一个设备给主机,这样就不会乱套。
记住这个图:后面咱们分析链路训练故障时,得先搞清楚出问题的是哪一段。是主机到Hub?还是Hub到设备?不同位置的故障表现完全不一样。
关于拓扑还有个事要留心——USB 3.0的Hub比USB 2.0复杂得多。2.0的Hub就是个简单的中继器,转发数据包。3.0的Hub需要处理两套独立的链路层,还要做速率转换。我在某项目里见过一个3.0 Hub,插上后链路训练老是超时,最后查到是Hub内部3.0和2.0模块的时钟没对齐,导致信号抖动超标。