3. USB包结构与传输:包格式与传输类型详解

大家好,我是你们的USB协议讲师。今天我们来聊聊USB通信中最基础、也最核心的部分——包结构。

说实话,我刚接触USB协议时,看到那一堆PID、CRC、SOP的缩写,头都大了。但后来我发现,只要你理解了包的结构,整个USB的通信机制就清晰了一半。

3.1 包的基本格式

USB总线上的所有通信,都是以“包”为单位的。一个标准的USB包,由以下几个字段组成:

字段 长度 说明
SOP 同步序列 包的起始标志,告诉接收端“我要发数据了”
PID 8位(4位类型+4位校验) 包标识符,决定这个包是干什么的
ADDR 7位 设备地址,最多支持127个设备
ENDP 4位 端点号,每个设备最多16个端点
DATA 0~1023字节 数据载荷(部分包没有这个字段)
CRC 5位或16位 循环冗余校验,保证数据完整性
EOP 结束符 包结束标志

核心要点:每个USB包都以SOP开始,以EOP结束。PID决定了包的类型和用途。

3.2 包标识符(PID)详解

PID是包的“身份证”。它只有4位有效位,但USB协议用了另外4位做校验。为什么?因为PID一旦出错,整个通信就会乱套。

我记得有一次调试一个USB设备,发现主机总是收不到正确的响应。折腾了两天,最后发现是PID校验位算错了。嗯,从那以后我再也不敢小看这8个bit了。

常见的PID类型分为四大类:

  • 令牌包(Token):OUT(0xE1)、IN(0x69)、SETUP(0x2D)
  • 数据包(Data):DATA0(0xC3)、DATA1(0x4B)、DATA2(0x87)、MDATA(0x0F)
  • 握手包(Handshake):ACK(0xD2)、NAK(0x5A)、STALL(0x1E)、NYET(0x96)
  • 特殊包(Special):PRE(0x3C)、ERR(0x3C)、SPLIT(0x78)、PING(0xB4)

小技巧:PID的校验位是类型位的按位取反。比如OUT包的类型位是0xE,校验位就是0x1。你可以用这个规律快速验证PID是否正确。

3.3 令牌包

令牌包是所有传输的“发令枪”。主机先发一个令牌包,告诉总线上的设备:“我要跟谁说话,说什么。”

令牌包的结构很简单:PID + ADDR + ENDP + CRC5。没有数据字段。

三种令牌包各有用途:

  • SETUP令牌:用于控制传输的建立阶段,发送配置命令
  • IN令牌:主机要从设备读取数据
  • OUT令牌:主机要向设备发送数据

你想想看,如果没有令牌包,总线上那么多设备,谁该响应谁该沉默?令牌包就是那个“点名”的角色。

3.4 数据包

数据包是真正承载信息的包。它由PID + DATA + CRC16组成。

这里有个关键点:数据包有DATA0和DATA1两种PID。为什么需要两种?

说白了,这是USB协议用来做数据同步的机制。发送方和接收方通过交替使用DATA0和DATA1,来确认数据有没有丢包。如果接收方收到两个连续的DATA0,就知道中间肯定有包丢了。

我在项目中遇到过一个问题:一个批量传输的设备,偶尔会出现数据错位。查了很久才发现,是固件里数据包PID切换的逻辑写错了。嗯,这种bug最难找。

3.5 握手包

握手包是接收方对发送方的“回应”。它只有一个PID字段,没有数据。

常见的握手包有:

  • ACK:数据接收成功,没毛病
  • NAK:设备忙,暂时处理不了(不是错误)
  • STALL:出错了,设备不支持这个请求
  • NYET:高速模式下,设备还没准备好接收下一包

注意:NAK不是错误!它只是设备说“我现在忙,你过会儿再来”。我曾经见过新手把NAK当成错误处理,导致驱动不停地复位设备,反而把系统搞崩了。

3.6 特殊包

特殊包用得比较少,但很重要:

  • PRE包:用于低速设备,告诉高速集线器“我要切换到低速模式了”
  • SPLIT包:高速模式下,主机通过这个包跟低速/全速设备通信
  • PING包:主机先问问设备“你准备好了吗”,避免盲目发送数据
  • ERR包:高速拆分传输中,报告错误

3.7 四种传输类型

USB协议定义了四种传输类型,每种都有自己的特点。我习惯用一个表格来对比:

传输类型 特点 典型应用 带宽保证 错误重试
控制传输 双向、可靠、有固定格式 设备枚举、配置 10%保留带宽 支持
批量传输 可靠、无带宽保证 U盘、打印机 支持
中断传输 可靠、有轮询周期 鼠标、键盘 有(按轮询间隔) 支持
同步传输 不可靠、实时性高 摄像头、音频 有(固定带宽) 不支持

3.8 控制传输详解

控制传输是最复杂的传输类型。它分为三个阶段:

  1. 建立阶段:主机发SETUP令牌 + DATA0包,设备必须回复ACK
  2. 数据阶段:可选,根据建立阶段的方向,进行IN或OUT传输
  3. 状态阶段:确认整个控制传输完成

我建议你把控制传输想象成一个“三次握手”的过程。建立阶段是“我要开始说话了”,数据阶段是“这是我要说的内容”,状态阶段是“我说完了,你确认一下”。

3.9 批量、中断、同步传输

批量传输:说白了就是“尽力而为”。USB控制器会在空闲时传输批量数据,不保证延迟。但出错了一定会重试。U盘就是典型的批量传输设备。

中断传输:名字叫“中断”,其实不是硬件中断。它是主机定期轮询设备,看看有没有新数据。鼠标每8ms被轮询一次,这就是中断传输。

同步传输:实时性最高,但不保证数据正确。音频设备用同步传输,因为偶尔丢一个音频包,人耳听不出来。但如果延迟太大,声音就会卡顿。

经验之谈:选传输类型时,先问自己两个问题:数据必须100%正确吗?延迟要求高吗?如果两个都是“是”,那就只能用控制或批量传输。如果延迟更重要,考虑同步传输。

3.10 本章知识体系

下面这张图,是我自己总结的USB包结构知识体系。你可以把它当成一个“地图”,随时回来查阅。

USB包结构与传输类型知识体系 USB包结构 包格式 PID类型 传输类型 包交互流程 SOP/EOP PID ADDR/ENDP CRC 令牌包 数据包 握手包 特殊包 控制传输 批量传输 中断传输 同步传输 令牌→数据→握手 重试机制 数据同步 每个分支都可以继续深入,后续章节会逐一展开 包格式 PID类型 传输类型 包交互

好了,这一章的内容就到这里。包结构是USB协议的基石,后面的LTSSM状态机、事务处理,全都建立在这个基础上。希望你能把这张图印在脑子里,以后遇到USB问题,先想想“这个包是什么类型?它的PID对不对?”。


公众号:蓝海资料掘金营,微信deep3321