USB通信
1、USB是轮询总线,USB主机发起所有数据交换。数据往返于USB设备中的端点。USB主机输出使用OUT端点,USB主机输入使用IN端点。USB主机中没有端点,数据存储于缓冲区中。从主机的FIFO到设备的端点,中间是Pipes。全速USB传输中,固定的1帧时间为1ms,在高速USB中有将一帧分为了8个微帧,每个125us。
USB数据层次
USB数据层次从小到大分为域(field),包(packet),事务(transaction),传输(transfer),管道(pipes)。
1、域
域是USB数据的最小单位,其实域就像我们CAN通信中,一个CAN帧内的帧起始,帧ID,RTR,IDE等等。一个USB数据包由7个域组成。分别位同步域、标识域、地址域、端点域、帧号域、数据域、校验域。数据发送低位在前,高位在后。
- 同步域:用于本地时钟域输入同步,标志一个包的起始,全/低速为8位,高速为32位。
- 标识域PID:由4位表示符和4位表示符反码组成,用于表明包的类型和格式,有令牌包,数据包,握手包。
- 地址域ADDR:七位地址,表示设备在主机上的地址。复位和通电后默认为0,在枚举过程中由主机配置。
- 端点域ENDP:4位,表示端点编号。端点0默认作为控制传输端点,且双向控制。
- 帧号域:11位,帧号从0开始递增,到0x7FF后自动变为0。
- 数据域:0~1023字节,不同传输类型中,数据域的长度不同。
- 校验域:对令牌包(CRC5)和数据包(CRC16)中非PID域进行校验。
2、包
包是USB传输的基本单位。它分为四种类型,令牌包、数据包、握手包和特殊包。
令牌包
令牌包又可分为输出(OUT)、输入(IN)、帧起始(SOF)、建立(SETUP)。令牌包结构如下表所示
域 | PID | ADDR | ENDP | CRC5 |
---|---|---|---|---|
长度(bit) | 8 | 7 | 4 | 5 |
令牌包说明
包 | PID | 说明 |
---|---|---|
OUT | 0001B | 用来通知设备将要输出数据包 |
IN | 1001B | 用来通知设备将要返回一个数据包 |
SOF | 0101B | 每帧开始时发送,EOP是每帧结束的标志 |
SETUP | 1101B | 只用在控制传输中,它跟输出令牌包作用一样,也是通知设备将要输出一个数据包。SETUP包后只使用DATA0数据包。 |
数据包
数据包用来传输数据。数据包结构如下表所示
域 | PID | DATA | CRC16 |
---|---|---|---|
长度(bit) | 8 | 0~8192 | 16 |
低速设备允许的最大有效数据载荷为8字节,全速设备的最大有效数据负载大小为1023字节,告诉设备的最大有效数据载荷为1024
数据包说明
包 | PID | 说明 |
---|---|---|
DATA0 | 0011 | 数据包偶书包 |
DATA1 | 1011 | 数据包奇数包 |
DATA2 | 0111 | 高速同步事务的专用数据包 |
MDATA | 1111 | SPLIT事务专用数据包 |
握手包
握手包用来表示一个传输是否被对方确认。包结构如下表所示
域 | PID |
---|---|
长度(bit) | 8 |
握手包说明
包 | PID | 说明 |
---|---|---|
ACK | 0010 | 数据被正确接收 |
NAK | 1010 | 数据未正确接收、设备内存不够无法接收数据或设备无数据可发送 |
STALL | 1110 | 设备无法执行这个请求或者端点已经被挂起。 |
NYET | 0110 | 在高速设备OUT事务中使用,表示设备本次数据接收成功,但是没有足够的空间接收下次数据。主机下次输出数据时,将先使用PING命令来探测设备是否有足够的空间 |
3、事务
每个事务都包含由三个包,分别是令牌包,数据包,握手包。根据令牌包中PID的不同,事务可以分为三种:SETUP事务,IN事务,OUT事务。
SETUP事务
方向 | 包 | 组成 |
---|---|---|
主机到设备 | 令牌包 | SYNC+PID(SETUP)+ADDR+ENDP+CRC5 |
主机到设备 | 数据包 | SYNC+PID(DATA0)+8字节数据+CRC16 |
设备到主机 | 握手包 | SYNC+PID(ACK/NAK/STALL) |
- 主机先发送一个SETUP令牌包给设备,通知令牌包中的所包含的地址的设备准备接收数据(寻址)。
- 主机发送8字节的DATA0数据包给设备,SETUP事务必须使用DATA0。这8字节的内容就是标准的USB设备请求命令。
- 设备接收指令后会返回一个握手包给主机。
IN事务
方向 | 包 | 组成 |
---|---|---|
主机到设备 | 令牌包 | SYNC+PID(IN)+ADDR+ENDP+CRC5 |
设备到主机 | 数据包 | SYNC+PID(DATA0/1)+(0~1023)字节数据+CRC16 |
主机到设备 | 握手包 | SYNC+PID(ACK/NAK/STALL) |
- 主机先发送一个IN令牌包给设备,通知令牌包中的所包含的地址的设备向主机发送数据(寻址)。
- 设备如果正常,则向主机发送数据,如果数据需多次发送,则交替使用DATA0和DATA1。如果设备异常,则发送NAK或STALL提前结束IN事务。
- 主机收到数据后发送一个握手包给设备。
OUT事务
方向 | 包 | 组成 |
---|---|---|
主机到设备 | 令牌包 | SYNC+PID(OUT)+ADDR+ENDP+CRC5 |
主机到设备 | 数据包 | SYNC+PID(DATA0/1)+(0~1023)字节数据+CRC16 |
设备到主机 | 握手包 | SYNC+PID(ACK/NAK/STALL) |
- 主机先发送一个OUT令牌包给设备,通知令牌包中的所包含的地址的设备准备接收数据(寻址)。
- 主机发送数据包给设备,如果数据需多次发送,则交替使用DATA0和DATA1。
- 设备接收指令后会返回一个握手包给主机。
4、传输
传输时由事务构成的,有四种类型:中断传输、批量传输、同步传输、控制传输。传输的种类在端点描述符中确定。
中断传输
这里的中断并不是传统意义上的中断,它是主机通过固定时间对中断端点进行查询,轮询时间可以在端点描述符中设置(Interval)。它通常用于有一定实时性要求,但是数据量不大且数据不需要一直通信的传输中,就像我们的鼠标或键盘没有动作就不用传数据给主机。
低速 | 全速 | 高速 | |
---|---|---|---|
最大数据包长度 | 8byte | 64byte | 1024byte |
最大带宽占用 | 90% | 90% | 80% |
轮询间隔 | 10~255ms | 1~255ms | 2^(interval-1)*125us |
需要注意的是主机对中断端点的轮询间隔并不一定是按照我们设置的来,它的只会保证轮询的间隔小于我们设置的间隔。
对于低速和全速传输,一帧中最多只有一次中断传输。对于高速传输,在端点描述符中可以设置中断传输的额外通信次数,最多可以额外传输2次,也就是一微帧中总共传输2次。
中断传输包含了IN事务和OUT事务。如果传输的数据大于最大数据包长度,那么会分多个事务进行传输,直到传输的事务的数据长度小于最大数据包长度,则认为时最后一包数据,传输完成。在传输过程中会,PID会按照DATA0-DATA1-DATA0…来翻转传输。发送端只有在收到ACK的时候才会翻转PID。
批量传输
批量传输的实时性不高,相对来说它的传输优先级最低。只有当USB中有多余的带宽了,批量传输才会开始,但是当带宽比较紧张的时候,批量传输会把带宽让给其他传输。其端点描述符中的Interval不起作用。批量传输一般用于数据传输量大,但是对实时性要求不高的场合,例如打印机。
低速 | 全速 | 高速 | |
---|---|---|---|
最大数据包长度 | 不支持 | 8、16、32、64byte可选 | 512byte |
批量传输包含了IN事务和OUT事务,但是比中断传输多了一个PING事务,PING事务只在高速传输中存在。PING事务的用来查看端点的状态。在传输前先PING一下从机,看设备是否准备好接收数据,NYET表示没有准备好接收下一包数据,ACK表示已经准备好接收数据。如果传输的数据大于最大数据包长度,那么会分多个事务进行传输,直到传输的事务的数据长度小于最大数据包长度,则认为时最后一包数据,传输完成。在传输过程中会,PID会按照DATA0-DATA1-DATA0…来翻转传输。发送端只有在收到ACK的时候才会翻转PID。
同步传输
同步传输是一种实时的但是不可靠的传输,不支持错误重发机制。同步传输有固定的时间间隔,端点描述符中的Interval固定为1。对于全速传输,一帧中最多只有一次中断传输(个人理解是对某个端点的中断传输只有一次)。对于高速传输,在端点描述符中可以设置中断传输的额外通信次数,最多可以额外传输2次,也就是一微帧中总共传输2次。同步传输一般用于数据量大,实时性要求高,数据产生连续的场合,例如音视频的传输。
低速 | 全速 | 高速 | |
---|---|---|---|
最大数据包长度 | 不支持 | 1023byte | 1024byte |
最大带宽占用 | 不支持 | 80% | 90% |
轮询间隔 | 不支持 | 1~255ms | 2^(interval-1)*125us |
同步传输包含了IN事务和OUT事务,同步数据的IN和OUT事务没有包握手阶段,数据包的PID都是DATA0。
控制传输
控制传输使用端点0,进行双向传输,一般用于设备配置,枚举。控制传输一般在总线中没有进行同步与中断传输的时候,如果需要进行控制传输,才会启动。
低速 | 全速 | 高速 | |
---|---|---|---|
最大数据包长度 | 8byte | 8、16、32、64byte可选 | 512byte |
控制传输时可靠传输。分为三个过程:
- 建立过程:一个SETUP事务,用来告诉设备我们主机的请求时什么,数据为8个字节,可以参考标准请求介绍。
- 数据过程:数据过程不是必须的,数据过程用来读取或者设置请求内容,0个或多个IN/OUT事务。
- 状态过程:一个IN/OUT 事务,表明请求时否成功了。
标准请求代码表
bRequest | Value |
---|---|
GET_STATUS | 0 |
CLEAR_FEATURE | 1 |
SET_FEATURE | 3 |
SET_ADDRESS | 5 |
GET_DESCRIPTOR | 6 |
SET_DESCRIPTOR | 7 |
GET_CONFIGURATION | 8 |
SET_CONFIGURATION | 9 |
GET_INTERFACE | 10 |
SET_INTERFACE | 11 |
SYNCH_FRAME | 12 |
SET_ENCRYPTION | 13 (USB2.0以后) |
GET_ENCRYPTION | 14 |
SET_HANDSHAKE | 15 |
GET_HANDSHAKE | 16 |
SET_CONNECTION | 17 |
SET_SECURITY_DATA | 18 |
GET_SECURITY_DATA | 19 |
SET_WUSB_DATA | 20 |
LOOPBACKDATAWRITE | 21 |
LOOPBACK_DATA_READ | 22 |
SET_INTERFACE_DS | 23 |
SET_SEL | 48 |
SET_ISOCH_DELAY | 49 |
SETUP 8字节数据格式
Offset | Field | Size | Desc |
---|---|---|---|
0 | bmRequestType | 1 | bit7: 0,数据由主机到设备SET请求 1:数据由设备到主机GET请求 bit[6:5]:00,标准请求;01:特定类请求;10:用户定义的请求命令;11:保留 |
1 | bRequest | 1 | 标准请求代码,见标准请求表 |
2 | wValue | 2 | 根据请求的不同,该含义会由变化 |
4 | wIndex | 2 | 根据请求的不同,该含义会由变化 |
6 | wLenght | 2 | 指定第二阶段传输数据的长度,0表示没有数据传输阶段 |
bmRequestType(1) | bRequest(1) | wValue(2) | wIndex(2) | wLength(2) | 数据过程 |
---|---|---|---|---|---|
0x00 | CLEAR_FEATURE(1) | 特性选择 | 0 | 0 | 没有数据 |
0x01 | CLEAR_FEATURE(1) | 特性选择 | 接口号 | 0 | 没有数据 |
0x02 | CLEAR_FEATURE(1) | 特性选择 | 端点号 | 0 | 没有数据 |
0x80 | GET_CONFIGURATION(8) | 0 | 0 | 1 | 配置制 |
0x80 | GET_DESCRIPTOR(6) | 描述符类型(高字节)和描述符索引(低字节) | 0或语言ID(字符串描述符) | 描述符的长度 | 描述符 |
0x81 | GET_INTERFACE(10) | 0 | 接口号 | 1 | 备用(转换)接口 |
0x80 | GET_STATUS(0) | 0 | 0 | 2 | 设备状态 |
0x81 | GET_STATUS(0) | 0 | 接口号 | 2 | 接口状态 |
0x82 | GET_STATUS(0) | 0 | 端点号 | 2 | 端点状态 |
0x00 | SET_ADDRESS(5) | 设备地址 | 0 | 0 | 没有数据 |
0x00 | SET_CONFIGURATION(9) | 配置值 | 0 | 0 | 没有数据 |
0x00 | SET_DESCRIPTOR(7) | 描述符类型(高字节)和描述符索引(低字节) | 0或语言ID(字符串描述符) | 描述符的长度 | 描述符 |
0x00 | SET_FEATURE(3) | 特性选择 | 0 | 0 | 没有数据 |
0x01 | SET_FEATURE(3) | 特性选择 | 接口号 | 0 | 没有数据 |
0x02 | SET_FEATURE(3) | 特性选择 | 端点号 | 0 | 没有数据 |
0x01 | SET_INTERFACE(11) | 备用接口号(转换接口号) | 接口号 | 0 | 没有数据 |
0x82 | SYNCH_FRAME(12) | 0 | 端点号 | 2 | 帧号 |
参考
USB 标准请求 - USB中文网 (usbzh.com)
USB初学 – 入门篇 (USB基础知识速览) - STM32H7 - 硬汉嵌入式论坛 - Powered by Discuz! (armbbs.cn)