USB-概述和基础
本文是作者在学习USB过程中记录的笔记,是为了制作一个USB小键盘而想入门一下USB。
主要学习的参考是《圈圈教你玩USB》这本书。
一,USB物理层
USB物理层一般由芯片或者外设处理,除非要进行非常底层的设计,不然一般不会动这一块。但为了一些板级设计,应用开发者还是需要对改部分有一定了解。
USB的结构与分类
USB是一种主从结构的通信协议,由主机(Host)发起通信,从机(Device,设备)响应信息。因此,USB中所有数据传输方向都是以主机位参考,即输出是主机向设备传输,输入是设备向主机传输。
另外,为了扩展使用场景,还有USB-OTG这种可以切换主机和从机的协议。
USB有多个版本标准,其物理接口和传输速度各有不同。如下表:
| 标准 | 最大传输速率 | 特点/备注 |
|---|---|---|
| USB 1.0 | 1.5Mbps/12 Mbps | 低速/全速,已淘汰 |
| USB 2.0 | 480 Mbps | 高速模式(High-speed)480Mbps但不强制。核心为一对差分线,黑色或白色舌片,广泛使用。 |
| USB 3.0+ | 5 Gbps+ | 命名很乱,引入了另外的差分对,带宽大且支持其他协议。保留原来2.0的差分对向下兼容。 |
本文章主要基于USB2.0进行。
USB的电气特性
USB2.0使用4根线,包括5V供电线(Vbus)和地线(GND),以及两根差分数据线(D+、D-)。数据线的电气参数这里不做介绍。
USB物理层使用NRZI编码,数据为0电平翻转,数据为1电平不变,多个1在一起会插入一个0来对齐时钟。这部分一般由底层硬件实现,了解即可。
USB插入检测
在USB2.0设备端,使用数据线上的1.5k上拉到3.3V电阻来检测插入,高速/全速设备上拉在D+,低速在D-,同时另外一脚悬空。
由于Host下拉电阻的作用,没有插入时为低电平,插入后拉高,检测到设备。
一些芯片会集成该电阻。
对Type-C接口,设备端使用5.1k电阻下拉CC1/CC2到地,表示从设备。
二,USB链路层
这里借用了计通网的概念来说明USB的成帧(包)和传输过程(毕竟这两干的事是一样的)。
USB的数据包
数据包是USB数据传输的基本单元,进行成帧和基本数据控制。采用LSB方式进行传输。
一个数据包以一串同步域开始,同步时钟;然后紧跟着4位PID包类型标识(先低位);然后是包其他数据;最后以EOP结束符结尾。
USB数据包有多种类型,由PID标注,不同类型的其他数据部分不同。
但一般CRC检验、PID包标识检验、位填充甚至包与包之间的关系都由硬件处理完毕,大部分时间,用户只需要根据芯片的标志位,准备要发送的数据到端点或者从端点读取接收到的数据即可。对于控制传输(下面介绍),需要关注其他标志位准备数据。
令牌包
令牌包用于发起USB传输,由主机发送。令牌包主要分为四类:
- OUT——输出
用于通知设备将要输出一个数据包。
- IN——输入
用于通知设备返回一个数据包。
- SETUP——建立
用于控制传输中,作用同OUT一样通知设备将要输出数据,但SETUP后只能使用DATA0数据包,且只能发送到控制端点。
关于控制传输概念和端点概念后面介绍。
上述三种令牌包的结构如图:

图中的地址和端点号后面解释。
- SOF——帧起始包
主要用于同步时钟。“SOF 就是 USB 的心跳:主机每 1 ms(或 125 µs)向外发一次滴答,让所有设备跟着同一个节拍跳舞。”
其结构如图:

数据包
数据包用于传输数据,主机从机皆可发送。
数据包有四种,DATA0、DATA1、DATA2、MDATA。其中后面两种主要用于高速传输中。正常主要用的还是DATA0和DATA1。
使用不同类型的数据包可以在传输中进行纠错,如在数据包成功发送或者接收时,数据包类型进行切换,在DATA0和DATA1切换,检测对方使用的数据包和本地的进行对比,判断是否发生了错误。
收到数据包后,会返回ACK握手包。若对方下次使用的数据包与自己不一样,说明对方成功接收握手包(进行了数据包切换);若下次对方的数据包和自己一样,则说明对方接收失败(没有切换),该数据是上次数据的重发。
最大字节数受最端点最大包长限制。
数据包的结构如下:

握手包
握手包类似ACK功能,用于确认传输是否成功接收。主要分为以下几类:
- ACK
表示正确接收数据,并且本设备有足够的空间来接收数据,主机和从机都可以使用。
- NAK
表示本设备没有数据返回或者本设备没有足够的空间来接收数据,只有从机可用。主机接收后,会在合适时机重试请求。
- STALL
表示本设备无法执行接收数据这个请求,或者接收端点被挂起了不能接收数据,只能从机使用。
- NYET
表示本次能正确接收数据,但是没有足够的空间来接收下一次数据,只能从机使用。在高速中使用,在下次输出数据时,主机需要使用PING包试探是否有空间。

注意,当CRC校验失败等出错时,不会返回握手包,让发送方超时重传。
特殊包
特殊包用于特殊功能。
特殊包一共有四种:PRE,SPLIT,PING是令牌包,ERR是握手包。
PRE是USB1.0和USB1.1中的协议,而ERR,SPLIT,PING是USB2.0中新增的。
- PRE
PRE:这是一种通知集线器打开低速端口的一种包,它虽然是令牌包,但是却只有同步域,PID包标识和结束符标志,而且只用在全速模式中。
在平时的全速设备中,为了防止其低速状态产生误操作,所以一般全速模式中不会把信号传给低速设备,只有当接收到了PRE令牌包,才会将低速端口给打开。
在全速模式下,假如需要处理低速事务,主机会发送一个PRE包,全速端口接收到次包会直接忽略,但当集线器接收到时,会打开其低速端口,然后主机就以低速模式给低速设备发送一系列令牌包、数据包等。
- SPLIT
SPILT:这是高速事务分裂令牌包,可以将只有在高速模式下才能处理的数据包转化为低速或者全速数据包发送给相应的端口。
- ERR
ERR握手包表示分裂事务中的错误。分裂事务属于集线器功能这里不深入。
- PING
PING:PING令牌包跟OUT输出令牌包一样,都是通知设备说主机将要发送数据了,但是PING令牌包后面是不接数据包的,只有当收到了设备发回来的ACK或者NAK应答才会开始发数据包,这就是为什么在将握手包的时候,NYET情况下主机会先发一个PING令牌包,确定设备有足够空间了才发送数据包,这就避免了浪费资源。
USB事务和传输过程
单独的USB数据包不能完成USB数据传输,需要把不同包组合成事务才能进行传输。
USB事务
上面介绍的令牌包、数据包、握手包根据需要组合成USB事务。
一般事务由主机发送令牌包发起,根据需要由主机/从机发送数据包传输数据,接收方接收数据包后用握手包回复。
传输类型是USB规定的传输数据的方法,由一个或多个USB事务组成。
对于数据的传输,USB规定了几种传输类型:批量传输、等时传输、中断传输、控制传输。其中,控制传输包含多个事务,其他为单事务传输。
批量传输
批量传输为单事务过程,分为批量读(批量输入)和批量写(批量输出)。一般用于数据量大、实时性不高的场合,如USB打印机、U盘等。
- 批量输出
对批量输出,主机先发送一个OUT令牌包包含设备地址和端点,然后主机发送一个DATA包,相应设备就会接收,接收完成后设备发送握手包确认。
设备接收准确无误且有空间接收,则返回ACK或者NYET(高速模式-表示本次接收完毕但没有空间接收下次的);如果没有空间,返回NAK,主机会在一定时间后重试输出事务;若端点挂起,返回STALL;若检测错误,不返回,等到主机超时重发。

- 批量输入
对批量输入,主机先发送一个IN令牌包包含设备地址和端点,然后从机发送一个DATA包,主机就会接收,接收完成后主机发送握手包确认。若设备没有数据,设备直接返回握手包。
如果设备检测到错误或者地址不匹配,不响应等待主机超时;如果有数据,设备发送DATA包;如果设备没有数据,设备发送NAK响应主机;如果端点挂起,设备直接返回STALL。主机接收正确发送ACK;出现错误则等待超时。

高速设备还有一个PING令牌包,不带数据,等待设备的握手包表示设备是否准备完成。
实际传输时,可能会有多个批量事务来传输大于最大包长的数据,若发送的数据长度是最大包长的整数倍(即最后一包最大长度刚刚好发完数据),设备或主机必须再发一个 0长DATA包结束。
等时传输
等时传输为单事务传输,用于高实时场景如音频、视频设备等,对数据正确性要求低一点。
等时传输没有应答令牌包,因此没有重传机制。
中断传输
中断传输是单事务传输过程,用于保证查询频率的传输。由主机保证在不大于某个时间的间隔中查询一次。
中断传输和批量传输结构基本一致,单中断传输没有PING和NYET包。
最后的0长度包规则也一样。
控制传输
控制传输是多事务传输,用于需要保证数据传输的完整性的场景,比如USB设备枚举过程。
控制传输分为三个过程:建立过程、数据过程、状态过程。其中,数据过程是可选的。
- 建立过程——1个事务
同批量传输相比,建立过程使用SETUP令牌包,并使用DATA0输出数据,设备只能使用ACK应答。
即,设备必须接收建立过程中的数据。
只使用DATA0包。
- 数据过程——1个或多个事务
该过程使用的事务同批量过程,但要求一个控制传输中,数据传输方向相同。(全是批量读或者批量写)
数据包DATA0/DATA1交替使用。
一旦传输方向发生变换,认为进入状态过程。
- 状态过程——一个事务
该过程使用的事务同批量过程,但传输方向与数据过程相反。
只使用DATA1包。

三,USB描述符
我们已经知道了基础的数据传输过程,这一节将介绍设备描述符、端点地址等上层数据概念。
USB中的地址
USB中有设备地址和端口号,其功能和计通网中的IP地址和端口相似。
设备地址
每一个USB设备只有一个设备地址。
设备接入总线时,设备地址为0,主机与设备通信后,主机分配一个新的设备地址给设备,之后使用新的地址进行通信。
端口地址(号)
每一个设备中有多个端点,具体数量由硬件决定。
接入总线时,主机通过端点0配置设备地址和其他设置,其他的端点在配置完成后才能使用。
端点是具体的信息发送接收方,USB的数据最后由端点接收发送。
每个端点只能工作在一种传输模式,一般可以以传输模式命名端点,如控制端点、批量端点等,端点0恒为控制端点。
每个端点只能是输入输出中的一种,部分芯片支持单端点同时输入输出,但这只是共享端点号,在端点描述符中,依然是两个端点。
端点描述符中规定了端点所支持的最大数据包长,主机发送数据包不能超过端点的最大包长。
对于控制传输的端点,低速模式最大包长固定为8字节,高速模式最大包长固限为64字节,高速模式最大包长上限为1024字节。
对于等时传输的端点,全速模式最大包长上限为1023字节,高速模式最大包定为64字节,而全速模式可在8、16、32、64字节中选择。
对于中断传输的端点,低速模式最大包长上限为8字节,全速模式最大包长上限为1024字节,低速模式不支持等时传输。
对于批量传输的端点,高速模式固定为512字节,全速模式最大包长可在8、16、32、64字节中选择,低速模式不支持批量传输。
USB描述符
描述符记录了设备的类型、厂商ID、产品ID、端点情况等信息,主机通过该信息驱动设备。
标准描述符有设备描述符(Device Descriptor)、配置描述符(Configuration Descriptor)、接口描述符(Interface Descriptor)、端点描述符(Endpoint Descriptor)、字符串描述符(String Descriptor)。
USB2.0又新增了:Device Qualifier Descriptor、Other Speed Configuration Descriptor。
另外,还有类特殊描述符(HID描述符、音频接口描述符等)、厂商自定义描述符等。
端点描述符
主要记录了:端点号和方向、端点的传输类型、最大包长度、查询时间间隔等。
接口描述符
主要记录了:接口的编号、接口的端点数量、接口使用的类、子类、协议等。
一个接口可以看作一个功能,包含了多个数据端点用于收发数据。
配置描述符
主要记录了:配置包含的接口数、配置的编号、供电方式、是否支持远程唤醒、电流的需求量等。
一个配置包含多种功能(接口),多个接口共同组成一个USB设备的全部功能。
设备描述符
主要记录了:设备使用的USB协议版本号、设备类型、端点0的最大包大小、厂商ID(VID)和产品ID(PID)、设备版本号、厂商字符串索引、产品字符串索引、设备序列号索引、可能的配置数等。
设备描述符描述了配置数量,可以理解为有多少套功能组,同一时间只能有一套生效。
描述符关系
USB描述符组织结构是分层结构。
一个具体的设备有一个设备描述符,设备描述符定义了配置数量;
每一种配置有一个配置描述符,配置描述符定义了接口数量;
每一个接口描述符有一个接口描述符,接口描述符定义有多个端口;
每个端点有一个端点描述符。
四,USB枚举过程简介
USB主机检测到USB设备插入后,会对设备进行枚举,读取各种描述符信息。
设备枚举过程都是使用控制传输。
获取部分描述符
USB主机检测到USB设备插入后,对设备进行第一次复位,让设备地址变成0。
该过程的控制传输如下:
-
USB主机向设备地址0的端点0发送获取设备描述符的标准请求(建立过程)。
-
设备收到请求后,发送一个数据包设备的描述符(数据过程)。
-
主机收到数据包后确认无误,会发送一个0长度数据包确认(状态过程)。
主机这时只读取一个数据包的设备描述符,而标准USB设备描述符有18字节,对某些端点0大小没有18字节的设备(但规定至少有8字节),也只读取一个数据包,因为第八个字节就是端点0的最大包长度,主机读取后就知道了。
设置地址
USB主机对设备再次进行复位,开始设置地址。
该过程的控制传输如下:
- USB主机向设备地址0的端点0发送设置地址请求,包含新地址信息(建立过程)。
- USB设备收到该请求后会通过0数据的状态数据包确认(状态过程)。
之后,该地址生效,之后的通信都使用该设备地址。
获取描述符
主机再次获取设备描述符,但这次通过新设备地址,并获取全部18个字节的设备描述符。
若端点大小不够,会多次请求数据输入(多个IN令牌)。
之后,主机获取配置描述符。配置描述符共9字节,主机获取后通过其中的描述获取配置集合,请求和获取配置描述符差不多,只是长度不一样,
配置集合包含配置描述符、接口描述符、类特殊描述符、端点描述符等。
如果有字符串描述符,还需要获取字符串描述符。

浙公网安备 33010602011771号