文章目录
USB是什么
- 说法一:you sb,你是沙雕
- 说法二:美国USA的弟弟USB
- 说法三:通用串行总线(universal serial bus)
USB解决什么问题
简化PC与外围设备的连接,增加易用性
因为外围设备是各种各样的,所以的PC有很多种接口,比如早期键盘鼠标的PS/2,9针串口,23针并口,DVI,VGA,RJ45,RJ11,HDMI,SATA,PCIE等等,很多接口还是不支持热拔插的
在比较老的PC中,连接外围设备时,要断电,甚至要打开机箱,而且因为接口的不同,想要支持这些外围设备,主板就得做各种接口出来,非常的麻烦
如果能够实现一种统一的接口,主板上不需要做N种接口就能接入任何外围设备,而且支持热拔插,传输速度也很快,那无疑是帮大忙了
USB是基于此而实现,支持即插即用(plug and play),并且支持热拔插(hot plug)
USB-OTG
由于USB是主从模式,只能由主机发起通信,从机响应,因而两个主机或者两个从机是无法通信的,因此提出了OTG(on to go),同一个设备,在不同场合下,可以在主从之间切换
USB的特点
- USB1.0和USB1.1版本中,支持低速(1.5Mbps)和全速(12Mbps)
- USB2.0加入高速模式(480Mbps),高速模式是可选的,不一定所有USB芯片都支持
- USB3.0(5.0Gbps)
注:bps是每秒多少位
USB的拓扑结构
USB是主从机构,主机叫host,从机叫device
一个主机具有一个或者多个USB主控制器(host controller)和根集线器(root hub)
主控制器负责数据处理,根集线器提供一个连接主控制器与设备的接口和通路
USB集线器(usb hub)对原有的USB口在数量上扩展,但是并不增加带宽,每一个usb集线器下,又可以接入新的USB集线器,因此可以层层拓展,但是总数是有限制的
通常情况下,一个PC具有多个主控制器,每个主控制器下面有一个根集线器,根集线器下通常具有1-N个USB口,如果希望插入的几个USB设备具有较大的传输速度,可以考虑连接到不同的USB主控上
USB的电气特性
标准USB是四线:5V电源VCC,地GND,差分数据线正D+,差分数据线D-
OTG中多一根线(ID),用于身份识别,判断是主还是从
USB2.0的三种传输速度:低速(1.5Mpbs)、全速(12Mpbs)、高速(480Mpbs)
USB数据的编码:NRZI,数据为0时,电平翻转;数据为1时,电平不翻转
位填充:根据上述,可能存在长时间电平不变化的情况,因此数据出现连续6个1时,强制插入一个0后编码发送,在接收端,需要检测并去掉这个0,才能恢复数据
USB的插入检测机制
主机端:D+和D-分别接15K电阻下地,当悬空时保持为低电平
从机端:D+或D-接1.5K电阻上拉,具体接到D+还是D-,由速度决定
全速&高速:D+
低速:D-
因此从机接入到主机后,主机端的集线器能检测到D+或D-的电平出现变化,随后报告给USB主控制器
USB描述符
USB主机如何知道一个设备的功能、行为呢,需要通过描述符实现,描述符中记录了设备的类型、厂商ID、产品ID、端点情况、版本号等众多信息
qualifier descriptor 和 other speed configuration descriptor 以及一些特殊的描述符不做介绍
如果有特殊描述符,它跟在相应接口描述符之后
-
设备描述符:Device descriptor
一个USB设备只有一个设备描述符,设备描述符里决定了该设备有多少在种配置,每种配置都对应一个配置描述符
设备描述符主要记录信息:USB协议版本号、设备类型、端点0的最大包大小、厂商ID、产品ID、设备版本号、厂商字符串、产品字符串、设备序列号、可能的配置数等 -
配置描述符:configuration descriptor
每个配置描述符中,定义了该配置里有多少个接口,每个接口对应一个接口描述符
配置描述符主要记录的信息:配置所含接口数,配置的编号、供电方式、是否支持远程唤醒、电流需求等 -
接口描述符:interface descriptor
接口描述符里定义了该接口有多少个端点,每个端点对应一个端点描述符
接口描述符主要记录的信息:接口的编号、接口的端点数、接口所使用的类、子类、协议 -
端点描述符:endpoint descriptor
端点描述符定义了端点的大小、类型等
端点描述符主要记录的信息:端点号及方向、端点的传输类型、最大包长度、查询时间间隔等 -
字符串描述符:string descriptor
提供一些方便人们阅读的信息,它不是必须的
在主机获取描述符时,首先获取设备描述符,接着获取配置描述符,然后根据配置描述符中的配置集合的总长度,一次将配置描述符、接口描述符、类特殊描述符、端点描述符一次读回,对于字符串描述符则是单独获取的
USB设备的枚举过程
枚举:从设备读取各种描述符信息
USB主机检测到USB设备插入后,进行枚举,根据获取的信息,加载合适的驱动程序
在设备的枚举过程中,使用控制传输,控制传输分为三个过程:建立过程、可选的数据过程、状态过程
- 建立过程:它开始于一个setup令牌包,后面紧跟一个data0数据包,后面就是数据过程
- 数据过程:输入数据或者输出数据,数据过程后是状态过程
- 状态过程:与数据过程相反,是输出数据或者输入数据,用来确认所有的数据是否都已经正确传输完成
枚举的详细过程:
-
主机检测到设备插入,对设备复位
设备复位后地址为0,主机通过0地址和刚插入的设备通信,主机往0地址的设备的端点0发送获取设备描述符的标准请求(这是一个标准传输的建立过程),设备收到请求后,返回设备描述符给主机(8字节),主机收到设备描述符确认无误后,返回一个0长度的确认数据包给设备,进入设置地址阶段 -
主机再次对设备复位,设置地址
再一次复位后,进入设置地址阶段,USB主机往0地址的设备端点0发出一个设置地址的请求(控制传输的建立过程),新的设备地址在建立过程的数据包中,因此没有数据过程,具体的地址由USB主机管理,分配一个唯一的地址给刚接入的设备。USB设备在接收到请求后,就进入状态过程,主机会再次发送一个请求状态返回,这时USB设备返回0长度的状态数据包,主机收到后,经过确认,发送应答包ACK给USB设备,设备收到ACK后,启用新的设备地址 -
主机再次获得设备描述符
主机使用新设置的地址访问USB设备,这次获取全部的18字节的设备描述符 -
主机获取配置描述符
配置描述符共9个字节,主机获取到配置描述符后,根据配置描述符中所描述的配置集合总长度,获取配置集合。
配置集合包括配置描述符、接口描述符、类特殊描述符、端点描述符等 -
获取字符串描述符
如果有字符串描述符的话,可以获取这个
USB包结构和传输过程
包的结构
USB总线上传输数据是以包为基本单位,一个包被分为不同的域,包的类型不同,包含的域也不同
包有个共同特点,那就是以同步域开始,紧跟一个包标识符,最终以包结束符来收尾
- 同步域:用于告诉USB的串行接口引擎数据就要开始传输了,请做好准备,除此之外,同步域还可以用来同步主机端和设备端的数据时钟
- 包结束符:对于高速设备,用故意的填充错误来表示,此时CRC校验仍然可以通过,因此可以判断是故意的错误填充,而不是数据传输错了;对于全速和低速设备,将D+和D-都保持低电平,时间为2个数据位宽度
- 包标识符:用来表示一个包的类型,共有8位,只前4位是有效数据,后4位是前4位的取反,用于校验
包的分类
包的类型:令牌包(token packet)、数据包(data packet)、握手包(handshake packet)、特殊包(special packet)
PID类型 | PID名 | PID[3:0] | 说明 |
---|---|---|---|
令牌类 | OUT | 0001 | 通知设备将要输出数据 |
令牌类 | IN | 1001 | 通知设备将要输入数据 |
令牌类 | SOF | 0101 | 通知设备这是一个帧起始包 |
令牌类 | SETUP | 1101 | 通知设备将要开始一个控制传输 |
数据类 | DATA0 | 0011 | 数据包 |
数据类 | DATA1 | 1011 | 数据包 |
数据类 | DATA2 | 0111 | 数据包 |
数据类 | MDATA | 1111 | 数据包 |
握手类 | ACK | 0010 | 确认 |
握手类 | NAK | 1010 | 不确认 |
握手类 | STALL | 1110 | 挂起 |
握手类 | NYET | 0110 | 未准备好 |
特殊类 | PRE | 1100 | 前导(这是一个令牌包) |
特殊类 | ERR | 1100 | 错误(这是一个握手包) |
特殊类 | SPLIT | 1000 | 分裂事务(这是一个令牌包) |
特殊类 | PING | 0100 | PING测试(这是一个令牌包) |
特殊类 | - | 0000 | 保留 |
令牌包
令牌包用来启动一次USB传输,USB是主从结构,数据传输由主机发起,主机发送一个令牌包,通知哪个设备进行响应,如何响应
令牌包分四种:输出、输入、建立、帧起始
- 输出:通知设备将要输出一个数据包
- 输入:通知设备返回一个数据包
- 建立:只用在控制传输中,通知设备将要输出一个数据包,但是只是用DATA0数据包,且只能发送到设备的控制端点,设备必须接收
- 帧起始:在每帧开始时发送,以广播的形式发送,所有USB设备均可接收到
令牌包结构:
-
OUT、IN、SETUP
| 同步域 | 8位包标识符PID | 7位地址 | 4位端点号 | 5位CRC校验 | EOP | -
SOF
| 同步域 | 8位包标识符PID | 11位帧号 | 5位CRC校验 | EOP |
数据包
用来传输数据,数据包都具有同样的结构
| 同步域 | 8位包标识符PID | 字节0 | 字节1 | … | 字节N | 16位CRC校验 | EOP |
为什么同样用于传输数据,会有不同类型的数据包,是因为传输错误时需要纠错
例如:主机向设备发送了一个包,设备接收到并返回确认信号ACK,但是这个ACK在传输过程中受到干扰而损坏,主机无法正确获取ACK,就没办法判断是否传输成功
解决办法:主机和设备都维护自己的一个数据包类型切换机制,发送或接收成功时切换数据包类型,正常情况下,主机和设备的数据包类型保持一致,如果检测到包的类型不一致,则认为发生了错误,例如当发生上述情况时,主机无法获取ACK导致主机的数据包切换少了一次,下一次获取设备发送的包时,就会检测到包的类型不一致
握手包
握手包用来表示一个传输是否被对方确认,握手包只有同步域、PID、EOP,是最简单的一种数据包
握手包的类型:
- ACK:正确接收数据,并且有足够的空间来容纳数据,主机和设备都可以用ACK来确认,其它3种只能用于设备返回
- NAK:没有数据需要返回,或者数据正确但是没有足够的空间容纳,主机接到NAK时,会尝试重传,NAK并不代表数据出错,如果是数据出错,则什么都不会返回,等待方会因获取不到返回而等待超时
- STALL:设备无法执行这个请求,或端点已被挂起,表示一种错误的状态,需要主机进行干预才能解除
- NYET:设备本次数据接收成功,但是没有足够的空间容纳下一次数据,主机下一次输出时,应先使用ping试探设备是否有足够空间
特殊包
特殊包是一些在特殊场合使用的包,总共4种:PRE、ERR、SPLIT、PING,其中ERR是握手包,其余是令牌包
特殊包的类型:
- PRE:通知集线器打开其低速端口的一种前导包,只用于全速模式中,一般情况下,为了防止全速信号使低速设备误动作,集线器不会将全速信号送给低速设备,当收到PRE令牌包时,才会打开低速端口,接着以低速模式给低速设备发送其它包
- ERR:在分裂事务中表示错误
- SPLIT:高速事务分裂令牌包,通知集线器将高速数据包转化为全速或低速数据包发送给下面的端口
- PING:该令牌包不发送数据,而是等待设备返回ACK或NAK,用于判断是否能传输数据,它只用于批量传输和控制传输的输出事务中
USB的四种传输类型
虽然已经定义了基本传输单位为包,但是还需要按照一定的关系将不同的包组织成事务才能传输数据
USB事务
事务通常由两个或三个包组成:令牌包、数据包、握手包
- 令牌包:由主机发送,用于启动一个事务
- 数据包:存放数据,可以由主到从,也可以由从到主,方向由令牌包决定
- 握手包:由数据接收者发送,将数据接收状态反馈给发送方
USB协议规定了4中传输类型:批量传输、同步传输、中断传输、控制传输
其中批量、同步、中断每次传输都是一个事务,而控制包括三个过程,建立和状态过程分别是一个事务,数据过程可能包含多个事务
批量传输
批量传输通常用于数据量大、对数据的实时性要求不高的场合,例如USB打印机、扫描仪、大容量存储设备等
批量传输使用批量事务传输数据,一次批量事务有三个阶段:令牌包阶段、数据包阶段、握手包阶段
批量输出事务:
- 主机发送一个OUT令牌包,这个令牌包包含了设备地址、端点号
- 主机发送一个DATA包,这时指定的设备接收DATA包
- 主机切换到接收模式,等到设备返回握手包
- 设备的返回情况
- 设备正确接收数据,返回ACK或NYET
- 设备没有足够的空间接收,返回NAK
- 设备的端点处于挂起状态,返回SALLL
- 设备检测到有错误,不返回,让主机等待超时
批量输入事务:
- 主机发送一个IN令牌包,这个令牌包包含了设备地址、端点号
- 主机切换到接收模式,等到设备返回数据包
- 设备返回的情况
- 设备未检测到错误,将数据包放到总线上
- 设备没有数据需要返回,则使用NAK握手包响应主机
- 设备的端点处于挂起状态,返回SALLL握手包
- 设备检测到有错误,不返回,让主机等待超时
- 主机返回的情况
- 主机未检测到错误,使用ACK握手包应答
- 主机检测到错误,不做任何响应,让设备检测超时
PING事务:
- 主机发出PING令牌包
- 设备根据情况返回ACK、NAK、STALL握手包
中断传输
- 中断传输通常用在数据量不大,但是对时间要求严格的设备中,例如鼠标、键盘等,中断传输也可以用于检测某个标志位,当条件满足时进行批量传输
- 这里的中断,并不是硬件意义上的中断,而是指由主机按照一定的频率去发出中断传输请求
- 设备的端点描述符将会报告它的查询间隔,主机会保证在小于这个时间间隔内安排一次中断传输事务
- 中断传输和批量传输结构上基本一样,只是中断传输没有PING和NYET两种包
同步传输
用于数据量大、对实时性要求高的场合,例如音视频设备,但是同步传输不保证数据100%正确,因为它没有应答包
控制传输
控制传输分为三个过程:建立过程、可选的数据过程、状态过程
- 建立过程:建立事务是一个输出数据的过程,令牌包是SETUP,数据包只能是DATA0,握手包为ACK或者不应答
- 数据过程:数据过程是可选的,也可以没有,如果有的话,可以包含多个方向相同的数据事务,数据过程的第一个包必须是DATA1,正确传输一个包后,进行包类型切换
- 状态过程:状态过程只使用DATA1包
端点类型与传输类型的关系
一个具体的端点,只能工作在一种传输模式下,例如:控制端点、批量端点、中断端点
端点0是每个USB设备都必须具备的默认控制端点,非0端点要设置后才能使用