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 控制传输详解
控制传输是最复杂的传输类型。它分为三个阶段:
- 建立阶段:主机发SETUP令牌 + DATA0包,设备必须回复ACK
- 数据阶段:可选,根据建立阶段的方向,进行IN或OUT传输
- 状态阶段:确认整个控制传输完成
我建议你把控制传输想象成一个“三次握手”的过程。建立阶段是“我要开始说话了”,数据阶段是“这是我要说的内容”,状态阶段是“我说完了,你确认一下”。
3.9 批量、中断、同步传输
批量传输:说白了就是“尽力而为”。USB控制器会在空闲时传输批量数据,不保证延迟。但出错了一定会重试。U盘就是典型的批量传输设备。
中断传输:名字叫“中断”,其实不是硬件中断。它是主机定期轮询设备,看看有没有新数据。鼠标每8ms被轮询一次,这就是中断传输。
同步传输:实时性最高,但不保证数据正确。音频设备用同步传输,因为偶尔丢一个音频包,人耳听不出来。但如果延迟太大,声音就会卡顿。
经验之谈:选传输类型时,先问自己两个问题:数据必须100%正确吗?延迟要求高吗?如果两个都是“是”,那就只能用控制或批量传输。如果延迟更重要,考虑同步传输。
3.10 本章知识体系
下面这张图,是我自己总结的USB包结构知识体系。你可以把它当成一个“地图”,随时回来查阅。
好了,这一章的内容就到这里。包结构是USB协议的基石,后面的LTSSM状态机、事务处理,全都建立在这个基础上。希望你能把这张图印在脑子里,以后遇到USB问题,先想想“这个包是什么类型?它的PID对不对?”。
公众号:蓝海资料掘金营,微信deep3321