1. USB协议概述:从诞生到现在的技术演进

大家好,我是这次课程的主讲工程师。做嵌入式这些年,USB协议可以说是我打交道最多的接口之一了。从早期的USB 1.1到现在的USB4,这个协议栈变得越来越复杂,但核心思想其实一直没变——让设备之间能方便地通信。

这一章我们先打好基础,把USB的发展脉络、2.0和3.x的核心差异、以及物理层那些容易踩坑的细节理清楚。嗯,这些内容看似基础,但我在项目里见过太多人因为忽略物理层特性导致枚举失败的情况了。

1.1 USB的发展历史

USB(Universal Serial Bus)最初是1996年由Intel、Microsoft、IBM等公司联合推出的。当时的目标很明确:取代PC上那些乱七八糟的串口、并口、PS/2接口,实现真正的即插即用。

我最早接触USB是在2003年做一款数据采集卡,那时候用的还是USB 1.1 Full Speed,12Mbps的速率现在看来慢得可怜,但在当时已经比串口快了两个数量级。

版本 推出时间 理论速率 编码方式 关键特性
USB 1.0 1996 1.5 Mbps (Low Speed) NRZI 最初规范,实际很少产品
USB 1.1 1998 12 Mbps (Full Speed) NRZI 真正普及的版本
USB 2.0 2000 480 Mbps (High Speed) NRZI 微帧、事务分割
USB 3.0 2008 5 Gbps (SuperSpeed) 8b/10b 双总线架构、全双工
USB 3.1 2013 10 Gbps (SuperSpeed+) 128b/132b Type-C接口引入
USB 3.2 2017 20 Gbps 128b/132b 双通道聚合
USB4 2019 40 Gbps 128b/132b 基于Thunderbolt 3
个人经验: 做嵌入式开发,USB 2.0 High Speed和USB 3.0 SuperSpeed是最常见的两个目标。我建议初学者先从USB 2.0入手,因为它的协议栈相对简单,调试工具也成熟。等把枚举流程吃透了,再上3.x会轻松很多。

1.2 USB 2.0与3.x的核心区别

很多人以为USB 3.0就是USB 2.0的"提速版",其实不然。说白了,3.0几乎重新设计了一套物理层和协议层。我当年第一次看USB 3.0规范时,发现它和2.0的差异比想象中大得多。

1.2.1 总线架构的差异

USB 2.0是半双工、主机轮询的共享总线架构。所有设备共享一条数据线,主机挨个问设备"你有没有数据要发?"——效率确实不高。

USB 3.0则引入了双总线架构:保留了USB 2.0的D+/D-线用于兼容,同时新增了SSTX/SSRX两组差分对,实现全双工通信。这意味着设备可以同时收发数据,不再需要等主机轮询。

关键点: USB 3.0的物理层实际上包含两套独立的收发器——一套是传统的USB 2.0半双工通道,另一套是全新的SuperSpeed全双工通道。枚举时设备先通过2.0通道完成基本配置,再协商切换到SuperSpeed模式。

1.2.2 编码方式的区别

USB 2.0使用NRZI(Non-Return-to-Zero Inverted)编码,配合位填充(Bit Stuffing)来保证时钟同步。这种编码方式简单,但效率不高——连续6个1就要插入一个0,实际有效数据率会打折扣。

USB 3.0改用8b/10b编码(3.0)和128b/132b编码(3.1+)。8b/10b把8位数据映射成10位符号,虽然多了20%的开销,但提供了DC平衡、时钟恢复和错误检测能力。到了128b/132b,开销降到3%左右,效率大幅提升。

// USB 2.0 NRZI编码示例(伪代码)
// 数据: 0x55 (01010101)
// NRZI: 电平翻转表示0,电平不变表示1
bit_stuffing_threshold = 6;  // 连续6个1插入0

// USB 3.0 8b/10b编码示例
// 数据字节: 0x55 -> 8b/10b符号: D.21.0
// 实际传输的是10位符号,包含运行差异控制

1.2.3 电源管理的差异

USB 2.0的电源管理比较粗糙——设备要么唤醒,要么挂起。USB 3.0引入了更细粒度的电源状态:U0(活动)、U1(待机)、U2(休眠)、U3(挂起)。设备可以在微秒级时间内切换状态,这对电池供电的移动设备非常友好。

特性 USB 2.0 USB 3.0/3.x
数据传输方向 半双工 全双工
信号线数量 2 (D+/D-) 6 (D+/D- + SSTX/SSRX + GND)
编码方式 NRZI + 位填充 8b/10b 或 128b/132b
传输单位 帧 (1ms) / 微帧 (125μs) 数据包 + 链路管理包
主机控制方式 轮询 (Polling) 异步 + 轮询混合
电源状态 2种 (活动/挂起) 4种 (U0/U1/U2/U3)
向后兼容 — 保留USB 2.0通道
避坑指南: 我曾经在一个项目中,USB 3.0设备在U1/U2状态切换时出现数据丢失。后来发现是固件里电源管理状态机的超时参数没配好。记住:3.0的电源状态切换不是免费的,每次进出U1/U2都有几十微秒的延迟,对实时性要求高的应用要谨慎使用。

1.3 USB的物理层与电气特性

物理层是USB协议栈的最底层,也是问题最多的地方。我调试过的枚举失败案例,至少有一半是物理层的问题——电平不对、终端电阻错了、线缆太长导致信号衰减。

1.3.1 USB 2.0物理层

USB 2.0使用一对差分信号线D+和D-,特性阻抗要求90Ω ±15%。信号电平是3.3V(实际规范是3.0V-3.6V),但接收端的阈值是0.8V和2.0V——这个余量设计得挺大,就是为了抗干扰。

设备端的上拉电阻是识别设备速度的关键:

  • Low Speed (1.5 Mbps): D-线上拉1.5kΩ到3.3V
  • Full Speed (12 Mbps): D+线上拉1.5kΩ到3.3V
  • High Speed (480 Mbps): 先以Full Speed上拉D+,收到复位信号后切换为电流驱动模式

主机端的下拉电阻是15kΩ到GND。设备插入时,主机通过检测D+或D-的电平变化来感知设备插入,并判断速度等级。

核心原理: 设备插入瞬间,主机端D+或D-被上拉电阻拉高到约3.0V(分压结果),主机检测到这个上升沿就知道有设备插入了。这就是USB热插拔检测的物理基础。

1.3.2 USB 3.0物理层

USB 3.0的物理层复杂得多。除了保留2.0的D+/D-,还新增了SSTX+/SSTX-(发送差分对)和SSRX+/SSRX-(接收差分对)。这些差分对的特性阻抗也是90Ω,但信号电平只有1.0V左右,摆幅更小,频率更高。

3.0的接收端均衡(Equalization)是个关键点。因为5Gbps的信号在铜线上衰减很严重,接收端必须做CTLE(连续时间线性均衡)和DFE(判决反馈均衡)来恢复信号质量。

// USB 3.0 物理层初始化流程(简化)
1. 设备插入,2.0通道先完成枚举
2. 主机发送LFPS(低频周期性信号)唤醒3.0通道
3. 双方进行Rx Detect,确认对方存在
4. 训练均衡器(EQ Training)
5. 进入U0状态,开始数据传输

1.3.3 线缆与连接器

线缆质量直接影响信号完整性。USB 2.0 High Speed的线缆最长5米,而USB 3.0的线缆建议不超过3米——频率高了,损耗自然更大。

Type-C接口的出现解决了"正反插"的痛点,但也带来了新的挑战:CC(Configuration Channel)线用于检测插头方向、协商供电和替代模式。我在做Type-C项目时,CC逻辑的调试花了不少时间。

参数 USB 2.0 USB 3.0 USB 3.1/3.2
信号速率 480 Mbps 5 Gbps 10/20 Gbps
信号摆幅 3.3V 1.0V 1.0V
差分阻抗 90Ω ±15% 90Ω ±15% 90Ω ±15%
最大线缆长度 5m 3m 1m (20Gbps)
连接器类型 Type-A/B, Mini, Micro Type-A/B, Micro-B Type-C为主
终端电阻 设备: 1.5kΩ上拉
主机: 15kΩ下拉
设备/主机: 差分终端匹配 设备/主机: 差分终端匹配
避坑指南: 我曾经遇到一个案例,设备在USB 2.0下工作正常,但插到USB 3.0端口上就枚举失败。查了两天才发现是PCB上D+/D-走线没做等长处理,导致信号偏移超过了规范允许的100ps。记住:高速信号对PCB布局非常敏感,差分对等长、阻抗控制、回流路径这些都不能马虎。

1.4 USB协议栈的整体架构

在进入后续章节之前,我们先从整体上看一下USB协议栈的分层结构。这样你在学习状态机设计时,心里有个全局图。

USB协议栈分层架构图 USB协议栈分层架构 应用层 (Application Layer) 设备类驱动 (HID, Mass Storage, CDC, Audio...) 设备层 (Device Layer) 枚举管理、端点配置、标准请求处理 协议层 (Protocol Layer) 事务处理、包格式、握手协议、错误重试 链路层 (Link Layer) 帧/微帧调度、SOF、带宽管理 物理层 (Physical Layer) NRZI/8b10b编码、电平转换、终端匹配 状态机设计贯穿协议层、链路层和设备层,是USB固件开发的核心

从这张图可以看到,USB协议栈从下到上分为五层。我们这门课的重点是协议层、链路层和设备层的状态机设计,以及枚举调试的实战技巧。物理层的问题通常用示波器和逻辑分析仪排查,而协议层以上的问题更多靠USB分析仪和固件调试。

学习建议: 我个人习惯是先吃透物理层和协议层的基础,再动手写代码。很多初学者一上来就抄USB库的代码,遇到枚举失败完全不知道从哪下手。如果你能把这一章的内容真正理解透,后面调试时会少走很多弯路。