USB协议

📅 2026/7/2 14:01:02 👁️ 阅读次数 📝 编程学习
USB协议

USB协议中:多个域组成包,多个包组成事务,多个事务组成不同类型的传输。
包是USB系统中信息传输的基本单元,不能被打断和干扰,包只能在帧内传输。若干包组成一个事务传输,一次事务传输也不能打断,属于一次事务传输的几个包必须连续,不能跨帧完成。一次传输由一次到多次事务传输构成,可以跨帧完成
帧的起始由一个特定的SOF包表示,帧尾为EOF,一种电平状态。EOF期间不准传输数据。

USB包由五部分域组成

同步字段SYNC 包标识字段PID 地址域(7+4 bits)、Frame Number(11 bits)、数据字段DATA(0-1024字节) 校验字段CRC 包结尾字段EOP


PID域:
不同的PID(8 bits)标记了不同类型的USB包。四位标识符 + 四位标识符反码构成
PID将USB包分为4类:
1.令牌包
0x01:启动一个OUT(主机到设备)的传输,并包含设备地址和标号
0x09:启动一个IN(设备到主机)的传输,并包含设备地址和标号包是USB总线上数据传输的最小单位,不能被打断或干扰,否则会引发错误。若干个数据包组成一次事务传输,一次事务传输也不能打断,属于一次事务传输的几个包必须连续,不能跨帧完成。一次传输由一次到多次事务传输构成,可以跨帧完成。
0x05:帧起始(SOF),表示一个帧的开始,并且包含相应的帧号
0x0d:设置(SETUP)启动一个控制传输,用于主机初始化
2.数据包
0x03:偶数据包(DATA0)
0x0b:奇数据包(DATA1)
0x07:高速设备的PID同步包
0x0f:高数设备分离包,高带宽的同步事务
3.握手包
0x02:确认接收无误的数据包(ACK)
0x0a:无效(NACK),接收端(发送端)在忙无法接受(发送)设备
0x0e:错误(STALL),端点被禁止活不支持控制管道请求
0x06:无响应(NYET)
4.特殊类
前导包,错误包,分裂事务和Ping测试

地址域:
地址域ADDR 由两部分组成:7bits的设备地址addr + 4bits的端点地址ENDP
addr(7 bits) +ENDP(4 bits)
所以可以知道USB设备最大支持127个设备,每个设备最多16个端点
这个ENDP只用在IN/OUT/SETUP中


帧号域:
当USB令牌包的PID为SOF时,其数据字段必须为11bits的帧序列号
Frame Number
主机每发出一个帧,帧号自动加1,当达到0x7FF时,归零重新开始计数,对同步传输有重要意义。

数据域:
只存在于DATA信息包,根据不同的传输类型拥有不同小大的字节(0-1023字节)

CRC域:用于数据的CRC校验


包类型
根据PID域的同,分为4类包
1.令牌包,也有四种
OUT:通知设备将要输出一个数据包
IN:通知设备返回一个数据包
SETUP:只用在控制传输中,也是通知设备将要输出一个数据包,与OUT令牌的区别是:只使用DATA0数据包,且只能发到device的控制端点
SOF:在每帧开始时以广播的形式发送,针对USB全速设备,主机每1ms/125us产生一个帧,USB主机会对当前帧号进行统计,每次帧开始时通过SOF包发送帧号。

输入包IN,输出包OUT,设置包SETUP 的格式都是一样的:
SYNC + PID + ADDR(7 bits) + ENDP(4bits) + CRC5(五位的校验码)

帧起始包SOF的格式:
SYNC + PID + Frame Number + CRC5

2.数据包:
分为DATA0和DATA1数据包,当USB发送数据的时候,如果一次发送的数据长度大于相应端点的容量时,就需要把数据包分为好几个包,分批发送,DATA0包和DATA1包交替发送
同步传输中(四类传输类型中之一),所有的数据包都是为DATA0。
SYNC + PID + DATA + CRC16

3.握手包:
SYNC + PID
ACK、NACK、STALL、NYET/ERR

事务:
在USB上数据信息的一次接收或发送的处理过程称为事务处理
事务有三种:
SETUP事务:主机用来向设备发送控制命令
SETUP令牌包 + DATA包 + ACK

IN事务:主机用来从设备读取数据
IN令牌包 + DATA包 +ACK
OUT事务:主机用来从设备读取数据
OUT令牌包 + DATA包 +ACK

传输:
传输包括四种:控制传输、中断传输、同步传输、批量传输

1.控制传输:
由三个阶段组成
1.建立阶段
2.数据阶段
3.状态阶段:用来表示整个传输的过程已完全结束。

以usb设备枚举为例:
SETUP令牌包 + DATA数据包 + ACK ------》 建立阶段,DATA数据包中存放了GET_DESCRIPTOR
IN令牌包 + DATA数据包 + ACK ------》 数据阶段,DATA数据包大小八字节,存放的设备描述符前八字节
OUT令牌包 + DATA数据包 + ACK ------》状态阶段,主机确认收到

// 驱动里的典型同步控制传输
usb_control_msg(dev, usb_sndctrlpipe(dev, 0),request, requesttype, value, index,data, size, timeout);
底层拆成 SETUP + DATA + STATUS 三个阶段事务。

2.批量传输
USB 允许连续 3次以下的传输错误,会重试该传输 -----》“重传”
DATA0-DATA1-DATA0翻转PID ------》“错误检测”
上面两个机制保证数据准确

[OUT] + [DATA0: 512字节] + [ACK]
[OUT] + [DATA1: 512字节] + [ACK]
[OUT] + [DATA0: 200字节] + [ACK] ← 短包,传输结束
usb2.0是512字节,3.0是1024字节

驱动里的典型批量传输
// U 盘驱动 (usb-storage)
usb_bulk_msg(dev, usb_sndbulkpipe(dev, endpoint_out), buf, len, &actual, timeout);
usb_bulk_msg(dev, usb_rcvbulkpipe(dev, endpoint_in), buf, len, &actual, timeout);
底层就是组装 OUT/IN 事务,发出去。

3.中断传输
事务结构和批量相同。批量是有空就发,中断是主机周期轮旋

4.同步传输
没有ACK
时间轴: SOF#0 SOF#1 SOF#2 SOF#3
│ │ │ │
主机: ├──[OUT+1024]─┼──[OUT+1024]─┼──[OUT+1024]─┼──...
│ │ │ │
└── 每帧/微帧固定发送,SOF提供时间基准

传输类型 是否依赖 SOF 说明
控制 间接 在帧内调度,不严格依赖
批量 间接 帧剩余带宽传输,不严格依赖
中断 ✅ 直接 按 bInterval(以帧为单位)轮询
同步 ✅ 直接 每帧/微帧固定时隙,严格依赖