Bootstrap

Linux内核USB2.0驱动框架分析--USB包

一, 包的组成

每个包都由SOP(包起始域)、SYNC(同步域)、Packet Content(包内容)、EOP(包结束域)四部分组成,其中SOP、SYNC、EOP为所有包共有的域,Packet Content最为核心,不同类型的包由不同的Packet Content组成。
在这里插入图片描述

包的组成结构,由SOP、SYNC、Packet Content、EOP四部分组成,其中Packet Content最为核心,Packet Content由PID、地址、帧号、数据、CRC组成。
在这里插入图片描述
1.1 包的内容:
包是USB总线上数据传输的最小单位,不能被打断或干扰,否则会引发错误。若干个数据包组成一次事务传输,一次事务传输也不能打断,属于一次事务传输的几个包必须连续,不能跨帧完成。一次传输由一次到多次事务传输构成,可以跨帧完成
在这里插入图片描述
1.1.1 SOP域(Start Of Packet)

通过将D +和D-线从空闲状态驱动到相反的逻辑电平(K状态),由始发端口发信号通知分组的开始(SOP)。 此开关级别表示SYNC字段的第一位。 当重新传输到小于±5 ns时,集线器必须限制SOP第一位宽度的变化。 通过将通过集线器的标称数据延迟与集线器的输出使能延迟相匹配,可以最小化失真。
  在这里插入图片描述

1.1.2 SYNC字段:
同步域,由8位组成,作为每个数据包的前导,用来产生同步作用,使USB设备与总线的包传输率同步,对于低速和全速设备,它的数值固定为00000001.该数据通过NRZI编码后,就是一串0101010的方波,而发送方波的频率,就是发送数据的波特率。对于高速设备,同步域使用的是31个0,后面跟随1个1.

1.1.3 PID字段:
用来表示数据封包的类型。包标识符的校验字段是通过对类型字段的每个位反码产生的,PID字符如下图所示:
在这里插入图片描述

这里只用(PID04),PID47是PID0~4的取反,用来校验PID

PID1~0:01 令牌包、11 数据包、10 握手包、00 特殊包 

在这里插入图片描述
其中PID传送的前两位(PID<0:1>指出了其属于哪个组),这说明了PID的编码分布。
在这里插入图片描述

1.1.4 数据字段:
用来携带主机和设备之间传递的信息,其内容和长度根据包标识符、传输类型的不同而各不同。在USB包中,数据字段可以包括设备地址、端点号、帧序列号以及数据等内容。在总线传输中总是先传输字节的最低位,最后传输字节的最高位。

设备地址(ADDR)数据域:ADDR数据域由7位组成,代表了设备在主机上的地址,地址000 0000被命名为零地址,是任何一个设备第一次连接到主机时,在被主机配置、枚举前的默认地址,可用来寻址多达127个外围设备。

端点(ENDP)数据域.:ENDP数据域由4位组成。通过4个位最多可寻址出16个端点。这个ENDP数据域仅用在IN、OUT与SETUP令牌信息包中。对于慢速设备可支持端点0以及端点1作为终端传输模式,而全速设备则可以拥有16个输入端点(IN)与16个输出端点(OUT)共32个端点。
在这里插入图片描述

帧序列号(FRAM)域:帧号字段用于指出当前帧的帧号,它仅在每帧/小帧开始的SOF令牌包中被发送,其数据位长度为11位,每传输一帧,主机就将其内容加1,最大数值为0X7FF,当帧序列号达到最大数时将自动从0开始循环。
在这里插入图片描述

数据域:长度为0到1023字节(实时传输),它仅存在于DATA信息包中,根据不同的传输类型,拥有不同的字节大小,但必须为整个字节的长度。
在这里插入图片描述

CRC字段:由不同数目的位组成。根据不同的信息包的类型,CRC数据域由不同数目的位所组成。其中重要的数据信息包采用CRC16的数据域(16个位),而其余的信息包类型采用CRC5的数据域(5个位)。其中的循环冗余码校验CRC,是一种错误检测技术。由于数据在传输时,有时候会发生错误,因此CRC可根据数据算出一个校验值,然后依此判断数据的正确性。CRC只校验PID之后的数据,不包括PID本身,因为PID本身通过四个取反位校验。
在这里插入图片描述

1.1.5 EOP段:
全速或低速设备的结束包:SE0状态用于发信号通知分组结束(EOP)。 通过将D +和D-驱动到SE0状态两位时间,然后将线路驱动到J状态一位时间来发信号通知EOP。 从SE0到J状态的转换定义了接收器处的分组的结束。 J状态被置位一个位时间,然后D +和D-输出驱动器都处于高阻态。 总线终端电阻将总线保持在空闲状态。

注:SE0的意思是D+和D-都表示为低电平。
在这里插入图片描述
二、包的分类

每种类型的包组成会有所不同,按照组成所有的包会被分成帧首包SOF(Start of Frame)、命令包(Token)、数据包(Data)、握手包(Handshake)四大类型。
在这里插入图片描述
①令牌包(Token Packet):

在USB系统中,只有主机才能发出令牌包。令牌包定义了数据传输的类型,它是事务处理的第一个阶段,用来启动一次USB传输。令牌包中较为重要的是SRTUP、IN和OUT这三个令牌包。他们用来在根集线器和设备端点之间建立数据传输。

输出(OUT)令牌包:用来通知设备将要输出一个数据包
输入(IN)令牌包:用来通知设备返回一个数据包
建立(SETUP)令牌包:只用在控制传输中,和输出令牌包作用一样,也是通知设备将要输出一个数据包,
两者区别在于:

SETUP令牌包后只使用DATA0数据包,且只能发送到设备的控制端点,并且设备必须要接收,
而OUT令牌包没有这些限制。 

其格式如下:
在这里插入图片描述
在这里插入图片描述
例子:
在这里插入图片描述
②SOF Packet

SOF包由Host发送给Device,在每帧(或微帧)开始时发送,以广播的形式发送,所有USB全速设备和高速设备都可以接收到SOF包。

1) 对于full-speed总线,每隔1.00 ms ±0.0005 ms发送一次;

2) 对于high-speed总线,每隔125 μs ±0.0625 μs发送一次; 

在这里插入图片描述

SOF包以相对于每帧的开始精确计算的时间间隔发送SOF记号和伴随的帧数,包括集线器的所有全速/高速设备都可以接收到SOF包。SOF包不会使得接收功能部件产生返回包,因此,不能保证向任何给定的设备发送SOF都能被接收到。当设备探测到SOF的PID时,会被告知发生了SOF。

例子:
在这里插入图片描述

0xA5:1010 0101:对应上面PID表可知是帧起始包

③Data Packet、

数据包含有4个域:SYNC、PID、DATA和CRC16。有四种类型的数据包:DATA0, DATA1, DATA2,and MDATA,且由PID来区分。DATA0和DATA1被定义为支持数据切换同步(data toggle synchronization)。在USB1.1协议中,只有两种数据包:DATA0和DATA1,USB2.0中增加了DATA2和MDATA,主要用于高速分裂事务和高速高带宽同步传输中。

DATA数据域的位值是根据USB设备的传输速度及传输类型而定的,且须以8字节为基本单位。也就是传输的数据不足8字节的。或是传输到最后所剩余的也不足8字节的,仍需传输8字节的数据域。格式如下:
在这里插入图片描述
在这里插入图片描述

主机和设备都会维护自己的一个数据包类型切换机制:当数据成功发送或者接收时,数据包类型会进行切换。当检测到对方所使用的数据包类型不对时(未切换),USB系统会认为这发生了一个错误,并试图从错误中恢复。数据包类型不匹配主要发生在握手包被损坏的情况,当一端已经正确接收到数据并返回确认信号时,确认信号却在传输过程中被损坏。此时另一端就无法知道刚刚发送的数据是否已经成功,由于未接到返回确认信号,则只好保持自己的数据包类型不变,这时就要通过对方下一次的数据包类型判断传输是否成功。如果对方下一次使用的数据包类型和自己的不一致,则可以确定自己刚刚已经成功发送(因为对方已经做了数据切换,只有正确接收才会如此);如果下一次对方发送的数据和自己一致。则说明刚刚发送的数据包没有成功。

例子:
在这里插入图片描述

④Handshake Packet

握手信息包是最简单的信息包类型。在这个握手信息包中仅包含一个PID数据域而已,其格式如下:
在这里插入图片描述
在这里插入图片描述

握手包主要用来报告数据事务的状态,还能表示数据成功接收、命令的接收或拒绝、流控制和停止条件,只有支持流控制的事务类型才能返回握手信号。

主机和设备都可以使用ACK来确认,而NAK、STALL、NYET只有设备可以返回,主机不能使用这些握手包。NYET只在USB2.0的高速设备的输出事务中使用,表示本次数据成功接收,但没有足够的空间接收下一次数据,主机在下一次输出数据时,将先使用PING令牌包试探设备是否有空间接收数据,避免不必要的带宽浪费。

注意,当USB主机或设备检测到数据传输错误时(如CRC校验错、PID校验错、位填充错误时),将什么都不返回,这是等待接收握手信号包的一方将不会收到握手包而等待超时。

例子:
在这里插入图片描述

三,总结
数据包处理的很多过程在USB接口芯片中都已经处理好,故我们不必关心这些细节。一般的USB接口芯片会完成如CRC校验、位填充、数据切换、握手等协议的处理。

当USB接口芯片正确接收到数据时,如有空间保存,则将数据保存并返回ACK,同时设置一个标志表示已经正确接收到数据;如果没有空间保存,则自动返回一个NAK。

收到输入请求时,如有数据需要发送,则发送数据,并等待接收ACK。只有当数据成功发送出去(即接收到应答信号ACK)之后,它才设置标志,表示数据已经成功发送;如果无数据需要发送,则地洞返回NAK。

通常只需要根据芯片提供的一些标志,准备要发送的数据到端点,或从端点读取接收到的数据即可。所要发送的数据是指数据包中的数据,至于同步域、包标识、地址、端点、CRC等是看不到的,在**BUS Hound(USB抓包工具)**中抓到的数据也是如此,仅是数据包。在USB接口芯片中,通过一些标志,我们知道哪个端点接收或成功发送了数据。

;