2、USB包结构与传输机制

大家好,我是老张。做了十几年USB底层,今天咱们来聊聊USB协议里最基础、也最核心的部分——包结构和传输机制。说实话,很多工程师做USB驱动开发,调了半天不通,最后发现是包结构理解有偏差。嗯,咱们今天就把这块彻底讲透。

2.1 包类型:三种基本包

USB通信说白了就是“一问一答”的模式。主机发一个包,设备回一个包。这个过程中,有三种包类型贯穿始终:

  • 令牌包(Token Packet):主机发起的“指令”,告诉设备接下来要干什么
  • 数据包(Data Packet):真正要传输的数据内容
  • 握手包(Handshake Packet):接收方回复的“确认”或“拒绝”

我刚开始做USB项目时,总以为数据包最重要。后来踩了坑才明白——令牌包才是整个通信的“指挥棒”。没有它,数据包根本不知道该往哪送。

2.2 包格式:每个字节都有讲究

一个完整的USB包,由以下几个字段组成。我习惯把它们拆开来看:

字段 长度 说明
SYNC 8位 同步序列,用于时钟同步
PID 8位 包标识符,告诉接收方这是什么包
ADDR 7位 设备地址,最多127个设备
ENDP 4位 端点号,每个设备最多16个端点
CRC 5位或16位 循环冗余校验,保证数据完整性

这里有个细节我想强调一下:PID字段其实有8位,但只有低4位是有效数据,高4位是低4位的取反。为什么这么设计?说白了就是为了增加容错性。我曾经在调试时遇到过PID被干扰的情况,正是靠这个校验机制才定位到问题。

避坑指南:我曾经在一个量产项目中,发现部分设备偶尔通信失败。排查了三天,最后发现是SYNC字段的时钟同步没做好。USB 2.0的SYNC是8位,但USB 3.0改成了16位。如果你在混合模式下开发,一定要确认PHY层配置正确。

2.3 传输类型:四种场景四种玩法

USB定义了四种传输类型,每种都有自己适用的场景。我按使用频率给大家排个序:

2.3.1 控制传输(Control Transfer)

这是USB的“官方语言”。每个设备必须支持。枚举过程、配置设置、状态查询,全走这条路。控制传输分三个阶段:建立阶段、数据阶段(可选)、状态阶段。说白了就是“先问能不能干、再干、最后确认干完了”。

2.3.2 批量传输(Bulk Transfer)

适合大数据量、非实时场景。比如U盘读写、打印机数据传输。批量传输的特点是:保证数据正确,但不保证实时性。如果总线忙,它就得等着。我记得有一次做打印机驱动,批量传输一直超时,最后发现是中断传输占用了太多带宽。

2.3.3 中断传输(Interrupt Transfer)

别被名字骗了,USB的中断传输其实是轮询。主机定期询问设备有没有数据要发。适合鼠标、键盘这类人机交互设备。轮询间隔可以配置,从1ms到255ms不等。你想想看,鼠标移动如果延迟100ms,那体验得多糟糕?

2.3.4 同步传输(Isochronous Transfer)

这个最特殊——没有重传机制。适合音频、视频这类对实时性要求高、但能容忍少量丢包的场景。我做过一个USB摄像头项目,刚开始用批量传输传视频流,结果画面卡得不行。换成同步传输后,流畅度直接起飞。当然,偶尔丢几帧画面,人眼根本看不出来。

个人经验:选择传输类型时,我建议先问自己三个问题:1)数据量多大?2)实时性要求多高?3)丢包能不能忍?答案清楚了,类型自然就定了。

2.4 事务与帧:USB的时间轴

USB通信的最小单位是事务(Transaction)。一个事务包含:令牌包 + 数据包(可选) + 握手包。比如主机想从设备读数据,流程是这样的:

  1. 主机发IN令牌包(告诉设备:我要读数据)
  2. 设备发数据包(把数据送上来)
  3. 主机发ACK握手包(确认收到)

帧(Frame)是USB的时间基准。全速和低速模式下,每1ms产生一个帧起始包(SOF)。高速模式下,每125μs产生一个微帧。所有事务都在帧的边界内完成。

为什么会这样设计?说白了就是为了公平分配带宽。主机在每个帧内规划好:这个帧里要处理哪些事务、给每个端点分配多少时间。这样就不会出现某个设备霸占总线的情况。

注意:我曾经在调试一个复合设备(同时包含音频和存储功能)时,发现音频偶尔出现爆音。分析后发现,是批量传输占用了太多帧时间,导致同步传输的时隙被挤占。解决方案是调整端点描述符中的bInterval参数,给同步传输预留足够的带宽。

2.5 知识体系总览

下面这张图是我自己整理的USB包结构与传输机制的关系图。你看一眼就能明白整个体系是怎么串起来的:

USB包结构与传输机制知识体系 包类型 令牌包(Token) 数据包(Data) 握手包(Handshake) 包格式 SYNC PID ADDR ENDP CRC 传输类型 控制传输 批量传输 中断传输 同步传输 事务(Transaction) + 帧(Frame)

这张图把USB包结构的核心逻辑串起来了。从上到下看:包类型决定了通信的“角色”,包格式定义了每个角色的“台词”,传输类型规定了“演出的方式”,而事务和帧则是“舞台的时间轴”。

好了,这一章的内容就到这里。USB的包结构看似复杂,但只要你理解了“令牌-数据-握手”这个三角关系,剩下的都是细节。下一章咱们聊聊USB枚举过程——设备插上后,主机是怎么认出它的。


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