USB协议
2024年6月 · 预计阅读时间: 3 分钟
#
基础知识#
硬件结构USB在硬件上分为USB Host和USB Device。其中Host内部集成有一个root hub;Device分为Hub和Function,hub用来扩展USB接口,Function就是普通的USB设备了。
USB 2.0 协议支持 3 种速率:低速(Low Speed,1.5Mbps)、全速(Full Speed, 12Mbps)、 高速(High Speed, 480Mbps)。 一个USB设备可能兼容低速、全速,可能兼容全速、高速,但是不会同时兼容低速、高速。
USB有四条连接线,分别为5V,D+,D-,GND 使用这两条线路实现了空闲(Idle)、开始(SOP)、传输数据(Data)、结束(EOP) 等功能。
#
设备连接与速率识别Hub端口的D+,D-都有下拉电阻15K,没有设备接入的时候为低电平, 而当设备接入时,全速设备内部的 D+ 有 1.5K 的上拉电阻,低速设备内部的 D- 有 1.5K 的上拉电阻,连接到 Hub后会导致 Hub 的 D+或 D-电平变化,这样可以判断接入的是全速设备还是低速设备。
对于高速设备,它先作为全速设备被识别出来,然后再被识别为高速设备。 所以,高速设备内部 D+也有 1.5K 的上拉电阻,只不过这个电阻是可以断开的:工作于高速模式时要断开它。 高速设备的识别是通过通信实现的:
- Hub 端口发出 SE0 信号,这就是复位信号
- USB 设备监测到 SE0 信号后,会发出"a high-speed detection handshake"信号表示自己能支持高速模式,这可以细分为一下 3 种情景:
- 如果设备处于"suspend"状态,检测到 SE0 信号后,就发出"a high speed detection handshake"信号;
- 如果设备处于"non-suspend"状态,并且处于全速模式,就发出"a high speed detection handshake"信号。(这个情景,就是一个设备刚插到 Hub 端口时的情况,它一开始工作于全速模式);
- 如果设备处于"non-suspend"状态,并且处于高速模式,就切换回全速模式(重新连接D+的上拉电阻),然后发出"a high speed detection handshake"信号 那么什么是"a high speed detection handshake"信号(高速设备监测握手信号)? 它是一个hub和device的握手信号过程,流程如下:
- USB 设备维持 D+的上拉电阻,发出"Chirp K"信号,表示自己能支持高速模式
- USB 设备发出"Chirp K "信号后,就等待 Hub 回应一系列的"Chirp K"、"Chirp J"信号
- 如果 Hub 没监测到"Chirp K "信号,它就知道这个设备不支持高速模式
- 如果 Hub 监测到"Chirp K "信号后,如果 Hub 能支持高速模式,就发出一系列的"Chirp K"、"Chirp J"信号,这是用来通知 USB 设备:Hub 也能支持高速模式。发出一系列的 "Chirp K"、"Chirp J"信号后,Hub 继续维持E0 信号直到 10ms。
- 如果USB设备等待回应:
- 如果收到一系列的"Chirp K"、"Chirp J"信号:USB 设备断开端口 D+的上拉电阻,使能高速模式
- 如果没有收到一系列的"Chirp K"、"Chirp J"信号:USB设备保持全速模式运行
另外,工作于高速模式的设备,D+、D-两边有 45 欧姆的下拉电阻,用来消除反射信号
#
设备断开低速设备、全速设备通过检测D-或D+上电平是否拉低,就可以判断设备是否断开。 而高速设备上面提到"D+、D-两边有 45 欧姆的下拉电阻,用来消除反射信号", 当断开高速设备后,Hub 发出信号,得到的反射信号无法衰减,Hub 监测到这些反射信号后就知道高速设备已经断开。
#
USB协议数据格式#
概述注意:所有的 USB 文档提到的"输入"、"输出",都是基于 Host 的角度,"输出"表示从 Host 输出到设备,"输入"表示 Host 从设备得到数据。 先从整体上看:传输(Transfer) >= 过程(Stage) = 事务(Transaction) > 阶段(Phase) = 包(Pack)
- 四种传输(Transfer)类型:批量传输、中断传输、实时传输、控制传输 每种传输由多个过程(Stage)组成,每个过程由一个事务(Transaction)实现。
- 批量(Bulk)传输:批量事务
- 中断(Int)传输:中断事务
- 实时(Iso)传输:实时事务
- 控制(Control)传输
- 建立过程:由建立事务实现
- 数据过程:由批量事务实现
- 状态过程:由批量事务实现
- 上面最基础的单位是事务,而事务由多个阶段(Phase)组成(一般是3个阶段),每个阶段由一个包(Packet)实现
- 令牌阶段(Token phase):由令牌包实现
- 数据阶段(Data phase):由数据包实现
- 握手阶段(Handshake phase):由握手包实现
#
字节/位传输顺序先传输最低位(LSB)。描述数据时按照传输顺序从左到右列出来
#
反向不归零编码NRZI对于数据 0,波形翻转;对于数据 1,波形不变。
使用 NRZI,发送端可以很巧妙地把"时钟频率"告诉接收端:只要传输连续的数据 0 即可。在下图中,低速/全速协议中"Sync Pattern"的原始数据是"00000001",接收端从前面的 7 个 0 波形就可以算出"时钟频率"。
位填充: 使用 NRZI 时,如果传输的数据总是"1",会导致波形维持不变。如果电平长时间维持不变,比如传输 100 位 1 时,如果接收方稍有偏差,就可能认为接收到了 99 位 1、101 位1。而 USB 中采用了 Bit-Stuffing 位填充处理,即在连续发送 6 个 1 后面会插入 1 个 0,强制翻转发送信号,从而让接收方调整频率,同步接收。而接收方在接收时只要接收到连续的 6 个 1 后,直接将后面的 0 删除即可恢复数据的原貌。
包格式 在概述中描述到数据格式的单位是包Packet,传输由一个或多个过程组成,每个过程对应一个事务,而每个事务有多个阶段,每个阶段又对应一个包(令牌包、数据包、握手包、特殊包)。下面介绍包的格式。
USB 总线上传输的数据以包为单位。USB 包里含有哪些内容("域")?
- SOP:用来表示包的起始
- SYNC:用来同步时钟
- PID:表示包的类型
- 地址:在 USB 硬件体系中,一个 Host 对应多个 Logical Device,那么 Host 发出的包,如何确定发给谁? a. 发给所有设备:包里不含有设备地址 b. 发给某个设备:包里含有设备地址、端点号
- 帧号、数据等跟 PID 相关的内容
- CRC 校验码
SOP:Start Of Packet,Hub 驱动 D+、D-这两条线路从 Idle 状态变为 K 状态。SOP 中的 K 状态就是 SYNC 信号的第 1 位数据,SYNC 格式为 3 对 KJ 外加 2 个 K。 Host 发出 SOP 信号后,就会发出 SYNC 信号:它是一系列的、最大传输频率的脉冲,接收方使用它来同步数据。对于低速/全速设备,SYNC信号是8位数据(从做到右是00000001);对于高速设备,SYNC信号是32位数据(从左到右是00000000000000000000000000000001)。使用 NRZI 编码时,前面每个"0"都对应一个跳变。 在很多文档里,把 SOP 和 SYNC 统一称为"SYNC",它的意思是"SYNC"中含有"SOP"。 EOP:End Of Packet,由数据的发送方发出EOP,数据发送方驱动D+、D-这两条线路, 先设为 SE0 状态并维持 2 位时间,再设置为 J 状态并维持 1 位时间,最后 D+、D-变为高阻 状态,这时由线路的上下拉电阻使得总线进入 Idle 状态。
高速的 EOP 比较复杂,作为软件开发人员无需掌握。 高速模式中,Idle 状态为:D+、D-接地。SOP 格式为:从 Idle 状态切换为 K 状态。SOP 中的 K 状态就是 SYNC 信号的第 1 位数据。 高速模式中的 SYNC 格式为:KJKJKJKJ KJKJKJKJ KJKJKJKJ KJKJKJKK,即 15 对 KJ,外加 2 个 K。
#
包的PID域根据包数据里的 PID 的 bit1, bit0 可以分为 4 类:
- 令牌包(Token):01B
- 数据包(Data):11B
- 握手包(Handshake):10B
- 特殊包(Special):00B
如上图所示,PID 有 4 位,使用 bit1,bit0 确定分类,使用 bit3,bit2 进一步细分。
在 USB 包中,PID 域使用 8 位来表示,前 4 位表示 PID,后 4 位是对应位的取反。
#
USB描述符#
USB 设备状态切换
USB设备插入“Attached”状态,上电Powered后,Host会发送一个Reset信号(高速设备的识别需要复位信号),设备识别后进入默认状态,设置地址,进行设备配置。
设备/配置/接口/端点
一个 USB 设备:
- 只有一个设备描述符:用来表示设备的 ID、它有多少个配置、它的端点 0 一次最大能传输多少字节数据
- 可能有多个配置描述符:用来表示它有多少个接口、供电方式、最大电流
- 一个配置描述符下面,可能有多个接口描述符:用来表示它是哪类接口、有几个设置(Setting)、有几个端点
- 一个接口描述符符下面,可能有多个端点描述符:用来表示端点号、方向(IN/OUT)、类型(批量/中断/同步) 举例: 比如一个USB 4G上网卡就有2种配置: U 盘、上网卡。 第 1 次把 4G 上网卡插入电脑时,它是一个 U 盘,可以按照里面的程序。装 好程序后,把它再次插入电脑,它就是一个上网卡。 再比如,USB 耳机它可能只有1种配置,就是耳机,但是有两个接口(功能):声音收发、按键控制。声音收发接口可能也会有多个端点,比如端点0负责收发控制命令,端点1负责发送麦克风,端点2负责接收声音。
每种描述符就是在组件库中被定义成结构体,结构体中的成员就是每种描述符的属性。 比如设备描述符:
SETUP 事务的数据格式
Host 使用控制传输来识别设备、设置设备地址、启动设备的某些特性,对于控制传输, 它首先发出"setup 事务",如下:
在"setup 事务"中,
- SETUP 令牌包:用来通知设备,"要开始传输了"
- DATA0 数据包:它含有固定的格式,用来告诉设备"是读还是写"、"读什么"、"写什么"
DATA0 数据包发送 8 字节数据给设备,它的格式如下图:
标准设备请求
控制传输的建立事务中,可以使用下列格式的数据:
上表中各个"宏"取值如下:
#
USBX组件https://wiki.stmicroelectronics.cn/stm32mcu/wiki/Introduction_to_USBX