二十四、USB协议


一、USB是什么

  USB,通用串行总线,是一种计算机与外围设备进行数据交互的通信协议。

  任何东西的出现都是有理可循的,在以前计算机刚兴起的时候,要连接一个新的设备,需要断电关闭计算机,连接好设备,配置好硬件,再上电运行,这个过程相当费时费力,为了能拥有随意接入设备这种热拔插特性,USB总线协议应运而生。

USB总线如今已经有USB1.0、USB1.1、USB2.0、USB3.0。

  USB协议采用主从工作模式,即只有主机与从机之间才能进行数据通信,也正是这样引发一个缺陷,就是主机与主机、从机与从机之间不能通信。后来,USB OTG的出现弥补了这一缺陷,USB OTG的特性,就是能将一个设备,在不同的场合进行主机或从机的身份切换,如何做到这一点的,就是USB OTG中增加了一种MINI USB接头,是五线制,跟四线制一样,多出来的一条是ID线,用来标识一个设备是主机还是从机。尽管如此,还是避免不了USB主从的工作模式,数据永远在主机和从机之间进行,永远是主机发起主动权,从机只是被动的读写。

  USB传输如今已经是一种普遍的手段,在USB1.0和USB1.1中,传输速度上有1.5Mb/s的低速模式和12Mb/s的全速模式,之后出了USB2.0,传输速度上就有了480Mb/s的高速模式、在USB3.0上,速度就更快了。这些低速、全速、高速指的是数据在每秒传输的位数,实际速率要低一点,因为还有同步域、令牌包、CRC校验、位填充、包间隙这些协议开销。而在传输距离上,建议低速不超过3米,全速不超过5米

  需要走出的一个误区就是:并不是设备拥有越高版本的协议,速度就一定快;就比如说PSIUSBD12这款USB芯片,虽然手册上写了符合USB2.0协议,实际上并没有高速模式,只有12Mb/s的全速模式。

二、USB协议的传输结构

以下是USB协议的LOGO:

                                                   

 

 

标准的USB协议传输结构是这样子的(设备端):

                                     

 

   USB协议采用的是差分传输模式,因而有两条数据线D+和D-,在低速和全速模式下,采用电压传输模式,在速下,采用电流传输模式。

  传输结构之所以采用两长两短的方式,是为了支持热拔插;当USB设备接入主机时,VCC和GND优先被接通;拔掉设备时,D-和D+数据线优先断电。原因很简单,如果D-和D+先于电源线被接通,那么此时电源为0,USB芯片的IO口引脚电压很有可能大于电源电压,很容易导致芯片闩锁,轻则无法工作,重则损坏芯片,这时候需要断电重新上电。

  在还没有进行配置前,数据线最大电流为100mA,配置后,数据线最大电流为500mA,数据的传输为小端序方式,在国际标准上,甚至对USB协议的四线做了颜色标注,VCC为红色,GND为黑色,D-为白色,D+为绿色。

三、USB的电气特性

在电气结构上,USB设备与主机的连接也很有讲究:

                                            

 

 

主机端的D-和D+数据线各自被串联15KR电阻下拉到地,当没有USB设备插入的时候,这两条数据线就一直呈现低电平状态。

设备端的D-或者D+数据线,串联一个1.5KR的电阻上拉到3.3V,一旦设备插入主机,那么当主机捕捉到自身的D-或者D+被拉到高电平时,就知道有USB设备连接进来了,这样就检测到有外来USB设备接入了。

对于从机设备中到底是D-还是D+串联1.5KR电阻,这个就要有传输协议的模式来决定了,当配置成全速或高速时,就由D+串联电阻;当配置成低速时,就是D-串联电阻了。

简单来说就是快的就连D+,慢的就连D-。

拓扑结构
刚才说了,USB是一种主从工作模式,大多数时候主机被叫“Host”,从机被叫“Device”;

主机端具有一个或者多个USB主控制器,每个USB主控制器下带有一条或者多条根集线器,主控制器负责数据处理,根集线器负责提供一条主控制器与设备连通的接口;

当然有这么一种情况,当设备越来越多,接口不够用的时候,就需要一个特殊的USB设备登场了,那就是USB集线器,他可以在原有的USB接口上扩展出更多的接口,当然了,扩展得再多,说白了也是共享一个主控制器,因此带宽是不会变多的。

在PC端的设备管理器中就可以看到主机的USB主控制器和根集线器:

 

 

 

虽然说一个USB主控制器可以连接多个设备,这种连接并不是串联,也不是并联,而是通过集线器来实现的。

 

 

 

如图,主控制器和根集线器后有集线器,集线器将一个或者多个USB接口扩展成更多接口,将更多接口拓展成再多,但是这种拓展并不是无休止进行下去的,USB1.1最多扩展4层,USB2.0最多扩展6层。

因此大概的传输过程是这样的:

  首先由主控制器发出数据,通过各层的集线器传送到相对应的某一层的接口给USB设备,设备接收到数据后进行分析处理,然后发送回一组数据或应答,它最先被送至本层的集线器,然后被送到上一层集线器,一直到主控制器为止,最终,主控制器将数据或者应答交给计算机进行处理。

四、编码方式  

无论USB协议再怎么高深,发送端实际上数据传输的本质就是0和1。

USB采用的是NRZI编码方式,数据为0的时候电平翻转,数据为1的时候电平不反转。

当出现连续6位为1的时候,自动填充进一个0,这样做的目的是防止长时间的电平不变化,不利于时钟的提取。而在接收端则完全相反,自动去掉填充的0,还原出原本的数据。

这就是位填充处理了。

当然,这种编码的处理过程,USB芯片都已经自动处理好了,我们只要知道有这些细节便可。

五、描述符

  USB协议只是一条总线,提供了一条通路而已,那么传了那么多0和1的数据,到底传输的是什么数据呢,原来是要告诉主机,这个设备的具体功能、会有什么行为,该设备的出厂商,设备ID号,厂商ID号,版本号,端点情况等等信息。

这些信息,都是由主机从设备那里获取的描述符得知的,因此,USB总线上传输的0和1数据,实际上就组成了描述符数据,发送给了主机。

描述符种类多样:设备描述符、配置描述符、接口描述符、端点描述符、类特殊描述符、字符串描述符·····

一个设备只有一个设备描述符,该设备描述符定义了多种配置;

每一种配置对应一个配置描述符,该配置描述符定义了多种接口;

每一个接口对应一个接口描述符,该接口描述符定义了多个端口;

每个端点对应一个端点描述符,端点描述符定义了该端点的大小、类型等等。

因此可看出来,在主机获取描述符的过程是有顺序的,从设备描述符,到配置描述符,再到接口描述符,最后到端点描述符,如果由类特殊描述符,那就跟在端点描述符之后。

可见,描述符的获取是一层一层来的,不过在获取配置描述符的时候,可以根据配置描述符得到配置集合的总长度,从该集合我们一口气得到配置描述符、接口描述符、端点描述符和类特殊描述符。

这样也就引发了一个疑问,既然可以一口气从配置集合中获取到端点描述符了,那我为什么还要去费劲获取配置描述符和接口描述符呢,理论上讲是可以的。

我们来捋一下各种描述符之间的关系,假如有一个U盘(U盘当然是用USB通信协议啦),它有一个设备描述符,因此也有一个设备地址(USB设备采用7位来表示地址,即0~127,其中0号地址是保留给未初始化的设备用的,因此理论上可以连接127个设备,但实际上并不会接那么多),主机是通过该设备地址找到U盘并与它通信的,但是仅仅只有设备地址是不够的,还要知道主机与U盘中哪一个端点进行通信,因此还需要有一个端点地址,只有知道了设备地址和端点地址,才能实现对设备点对点发送和接收数据。

因此按道理来说,只要知道设备描述符和端点描述符就够了,就好比你要去XX学校找XX人一样,花点时间总会找得到行得通的。

而配置描述符和接口描述符的出现,只是为了能更好的管理端点而抽象出来的概念罢了,就好比指定了XX栋xx室一样,想象一下,你得到了这么一条信息,去深圳大学3栋305室找某某某,这是不是就比单纯告诉你去深圳大学找某某某要效率高很多了?

有这么三条需要注意的点:

1、一个设备可以有多种配置,但同一时刻只能有一种配置模式;

2、同一个端点不能出现在同一个配置下的一个或几个接口中;

3、同一个端点可以出现在不同配置下的一个或几个接口中;

好了说了这么多,到现在只知道有这么几种描述符,通过设备描述符可以知道配置描述符,通过配置描述符可以知道接口描述符,通过接口描述符可以知道端点描述符;从微观上来推理数据传输的过程就很简单了:

设备端USB协议产生0和1数据,在端点出构成一个接口,由接口又构成一种配置,由配置又构成一个设备,最后把这设备的信息交给主机进行数据处理,大概过程就是这样。

当然了,设备描述符中的数据不止有配置描述符,配置描述符中的数据不止有接口描述符,接口描述符中的数据不止有端点描述符,具体有以下的数据:

设备描述符:设备使用的USB协议版本、设备类型,设备版本号,端点0的最大包大小,厂商ID,产品ID,厂商字符串索引,产品字符串索引,设备序列号索引、包含的配置数······

配置描述符:包含的接口熟,配置编号,供电方式,是否支持远程呼唤,电流需求大小·····

接口描述符:接口编号,接口端点数,接口所使用的类、子类、协议······

端点描述符:端点号、方向,端点传输类型,最大包大小,查询时间间隔·······

六、USB传输类型

  数据和控制信号在主机和USB设备间的交换存在两种通道:单向双向

  USB的数据传送是在主机软件和一个USB设备的指定端口之间。这种主机软件和USB设备的端口间的联系称为通道。总的来说,各通道之间的数据流动是相互独立的。一个指定的USB设备可有许多通道。例如,一个USB设备存在一个端口,可建立一个向其他USB设备的端口,发送数据的通道,它可建立一个从其他USB设备的端口接收数据的通道。

  USB包含四种基本的数据传输类型:

  1、控制传输

  设备连接时用来对设备进行设置,还可对指定的设备进行控制。

  2、批量传输

  大批量产生并使用的数据,在传输约束下,具有很广的动态范围。

  3、中断传输

  用来描述或匹配人的感觉或特征反应的回馈。

  4、同步传输

  由预先确定的传送延迟来填满预定的USB带宽。

七、USB传输的数据格式

  在物理层,USB通过二进制数据进行传输,首先二进制数据构成域(有七种),域再构成包,包再构成事务(in、out、setup),事务最后构成传输。

  1、域:是USB数据最小的单位,由若干位组成,域可分为七个类型:

  (1)同步域 :八位,值固定为00000001,用于本地时钟和输入同步。

  (2)标识域:由四位标识符+四位标识符反码构成,表明包的类型和格式,这是个很重要的部分,这里能够计算出,USB的标识码有16种。

   (3)地址域:七位地址,代表了设备在主机上的地址,地址00000000被命名为零地址,是任何一个设备第一次连接到主机时,在被主机配置、枚举前的默认地址,由此能够知道为什么一个usb主机只能接127个设备的原因。

        (4)端点域:四位、由此可知一个USB设备的端点数量最大为16个。

  (5)帧号域:11位,每一个帧都有一个特定的帧号,帧号域最大容量为0x800,对于同步传输有重要意义。

  (6)数据域:长度为0~1023字节,在不同的传输类型中,数据域的长度各不相同,但必须为整数个字节的长度。

     (7)校验域:对令牌包和数据包中非pid域进行校验的一种方法,CRC校验在通讯中应用很泛,是一种会很好的校验方法

   2、包

  由域构成的包有四种类型:令牌包数据包握手包、特别包。

  (1)令牌包

  可分为输入包、输出包、配置包和帧起始包(注意这里的输入包是用于配置输入命令的,输出包是用来配置输出命令的,而不是放数据的)。其中输入包、输出包和配置包的格式都是相同的:sync+pid+addR+endp+CRC5(五位的校验码)。

  帧起始包的格式:

    sync+pid+11位FRam+CRC5

  (2)数据包

    分为data0包和data1包,当usb发送数据的时候,当一次发送的数据长度大于相应端点的容量时,就需要把数据包分为好几个包,分批发送,data0包和data1包交替发送即假如第一个数据包是data0,那第二个数据包就是data1。但也有例外情况,在同步传输中(四类传输类型中之一),任何的数据包都是为data0,格式如下:

  sync+pid+0~1023字节+cRc16 (16位的校验码)

  (3)握手包    

    结构最为简单的包,格式如下:sync+pid.

   (4)特别包:这里不做解释

  3、事务

分别有in事务out事务setup事务三大事务,每一种事务都由令牌包、数据包、握手包三个阶段构成,这里用阶段的意思是因为这些包的发送是有一定的时间先后顺序的,事务的三个阶段如下:

  • 令牌包阶段:启动一个输入、输出或配置的事务。
  • 数据包阶段:按输入、输出发送相应的数据。
  • 握手包阶段:返回数据接收情况,在同步传输的in和out事务中没有这个阶段,这是比较特别的。