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 拓扑结构示意图 主机 (Host) 根 Hub (Root Hub) Hub 1 Hub 2 键盘 鼠标 U盘 摄像头 • 每个Hub下可再接 Hub,理论支持127个设备 • 复合设备(如带 Hub 的键盘)可内部挂多个功能 • 设备地址由主机在枚举时分配,地址范围 1~127

这块内容跟咱们链路训练关系很大。为什么?因为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模块的时钟没对齐,导致信号抖动超标。