发帖数

53

原创数

53

关注者

11

阅读数

9073

点赞数

1

黄忠

  • USB之特殊包

    前面文章我们说了令牌包、数据包、握手包,今天我们来看最后一个特殊包,本篇文章主要说明特殊包以及如何处理数据包,下面们开说.

    特殊包是一些在特殊场合使用的包。总共有4:pErSPLITPNG其中PRESPLITPING是令牌包,ERR是握手包。ERRSPLITPING三个是在USB2.0协议中新增的。

    PRE是通知集线器打开其低速端口的一种前导包。PRE只使用在全速模式中。平时,为了防止全速信号使低速设备误动作,集线器是没有将全速信号传送给低速设备的。只有当收到PRE令牌包时,才打开其低速端口。PRE令牌包与握手包的结构一样,只有同步域、PIDEOP。当需要传送低速事务时,主机首先发送一个PRE令牌包(以全速模式发送)。对于全速设备,将会忽略这个令牌包。集线器在收到这个令牌包后,打开其连接了低速设备的端口。接着,主机就会以低速模式给低速设备发送令牌包、数据包等。

    PING令牌包与OUT令牌包具有一样的结构,但是PING令牌包后并不发送数据,而是等待设备返回ACK或者NAK,以判断设备是否能够传送数据。在USB1.1,是没有PING令牌包的。只有在USB.0高速环境中才会使用PING令牌包,它只被使用在批量传输和控制传输的输出事务中直接使用OUT令牌包发送数据时,不管设备是否有空间接收数据,都会在OUT令牌包之后跟着发送一个数据包,如果设备没有空间接收数据,就返回一个NAK这样的结果就是浪费了总线带宽,白白传送了数据。在高速设备中增加了这个PING机制,主机先用PING令牌包试试设备是否有空间接收数据,而不用事先把数据发送出去。在全速模式下,有时会遇到一个很有趣的现象,就是下位机程序慢了一点点处理完数据,结果传输速度却下降了很多。这就是前面所说的OUT过程直接发送数据导致的,也就是说,虽然程序只慢了一点,但是却丢弃了整个数据包。

    接下来我们来说说如何处理数据包. SPLIT令牌包是高速事务分裂令牌包,通知集线器将高速数据包转化为全速或者低速数据包发送给其下面的端口。ERR握手包是在分裂事务中表示错误使用。由于高速分裂事务过程比较复杂,主要属于集线器的功能,在此就不详述了,感兴趣的读者可以阅读USB2.0协议相关部分。

    这么多类型的包以及传输过程,那我们该怎么去处理呢?其实,如果使用现成的USB接口芯片,很多过程,USB接口芯片都已经处理好了,可以不用太关心这些细节,只要知道有这么一个过程就行了。

    一般的USB接口芯片会完成如CRC校验、位填充、PD识别、数据包切换、握手等协议的处理。

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

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

    通常只需要根据芯片提供的一些标志,准备要发送的数据到端点,或者从端点读取接收到的数据即可。所要发送和接收的数据是指数据包中的数据,至于同步域、包标识、地址、端点、CRC等是看不到的在 BUS Hound中抓到数据也是如此,仅是数据包;并且, BUS Hound中只能看到成功传输的数据,即只有ACK确认过的数据包。在USB接口芯片中,通过一些标志可以知道是哪个端点接收或者成功发送了数据。另外,由于控制传输比较特殊, SETUP包也会有相应的标志供我们使用。

    至此为止我们的包结构和包分类就全部说完了,通过对这些包的了解,我们会更加清楚的认识USB的通信知识.对我们做USB通信有很大的帮助.希望通过文章的内容分享,能给大家带来收获.


    收藏 0 回复 0 浏览 118
  • USB的包结构以及包的类型

    今天我们来详细地说说数据包的结构以及它们的传输过程。

    USB是串行总线,所以数据是一位一位地在数据线上传送的。既然是一位一位地传送,就存在着一个数据位先后的问题。usb使用的是LSB在前的方式,即先出来的是最低位数据,接下来是次低位,最后是最高位(MSB)。一个包,又被分成了很多个域(field),LSBMSB就是以域为单位来划分的。

    前面说过,USB数据在发送到总线上之前,要先经过位填充,再经过NRZ1编码。在这里讨论时,所用的数据都是原始的数据,即没有经过位填充和NRZ编码的原始数据。以后也是如此,凡是没有明确说明是位填充或NRZI编码过的数据,默认为原始的数据。另外还有一个数据传输方向的问题,因为在USB系统中,主机处于主导地位,所以把从设备到主机的数据叫做输入,从主机到设备的数据叫做输出。

    USB总线上传输数据是以包为基本单位的。一个包被分成不同的域。根据不同类型的包,所包含的域是不一样的。但是不同的包有个共同的特点,就是都要以同步域开始,紧跟一个包标识符PD( Packet Identifier),最终以包结束符EOP(End Of Packet)来结束这个包。

    同步域是用来告诉USB的串行接口引擎数据要开始传输了,请做好准备。除此之外,同步域还可以用来同步主机端和设备端的数据时钟,因为同步域是以一串0开始的,0USB总线上就被编码为电平翻转,结果就是每个数据位都发生电平变化,这让串行接口引擎很容易就能恢复出采样时钟信号;对于全速设备和低速设备,同步域使用的是0000001(二进制数,线上的发送顺序);对于高速设备,同步域使用的是310,后面跟11(需要注意的是,这是对发送端的要求,接收端解码时,0的个数可以少于这个数)

    1是一个全速或者低速USB数据包的同步域经过NRZ编码后的波形。这个波形有7次电平翻转,即对应着70,最后一个电平不翻转,即对应着11当串行接口引擎检测到一个位的数据未发生翻转后(即收到数据1),就认为包标识符PID开始了,如图1.9.1中的PID0PD1,就是包标识符的最低两位。

    image.png

    1 全速设备和低速设备的同步域

     

    包结束符EOP,对于高速设备和全速/低速设备也是不一样的。全速/低速设备的EOP是一个大约为2个数据位宽度的单端0(SE0)信号。SE0的意思就是,D+D同时都保持为低电平。由于USB使用的是差分数据线,通常都是一高一低的,SE0不同,是一种都为低特殊的状态。SE0用来表示一些特殊的意义,例如包结束、复位信号等。前面提到USB集线器对USB设备进行复位的操作,就是通过将总线设置为SE0状态大约10ms来实现的。对于高速设备的EOP,使用故意的位填充错误来表示。那么如何判断一个位填充错误是真的位填充错误还是包结束呢?这个由CRC校验来判断。如果CRC校验正确,则说明这个位填充错误是EOP;否则,说明传输出错。具体的定义请参看USB协议,这里只要知道有EOP这么一个东西就行了。

    包标识符PID是用来标识一个包的类型的它总共有8,其中USB协议使用的只有4(PID~PID3),另外4(PI4~PID7)PID~PD3的取反,用来校验PIDUSB协议规定了4类包,分别是令牌包(token packet,PD1~001)、数据包( data packet,pid1~011)、握手包(handshake packet,piD~010)和特殊包( special packet,PiD1~000)。不同类的包又分成几种具体的包。图2 USB2.0协议中规定的各种PID,其中有些是在USB1.1协议中没有的,用号标出。

    image.png

    2  USB2.0中定义的各种PID

    以上是数据包的结构以及它们传输的过程,今天的分享就到这里。


    收藏 0 回复 0 浏览 196
  • USB的四种传输类型之控制传输

    在我们前面的文章里面,我们描述了什么是批量传输,中断传输,等时传输,下面的文章我们来介绍一下控制传输。

    控制传输与前面三种传输相比,要稍微复杂一些。前面在介绍设备的枚举过程时,就提到过控制传输。控制传输分为三个过程:第一个过程是建立过程;第二个过程是可选的数据过程;第三个过程是状态过程。

    建立过程使用一个建立事务。建立事务是一个输出数据的过程,与批量传输的输出事务相比,有几处不一样:首先是令牌包不一样,建立过程使用 SETUP令牌包;其次是数据包类型, SETUP只能使用DATA0;最后是握手包,设备只能使用ACK来应答(除非出错了,不应答),而不能使用NAK或者 STALL来应答,即设备必须要接收建立事务的数据。图1是建立事务的流程图.

    image.png

    1

    数据过程是可选的,即一个控制传输可能没有数据过程。如果有,一个数据过程可以包含一笔或者多笔数据事务。控制传输所使用的数据事务与批量传输中的批量事务是一样的。要注意的是,在数据过程中,所有的数据事务必须是同一个传输方向的。也就是说,在控制读传输中,数据过程中的所有数据事务都必须是输入的;在控制写传输中,数据过程中的所有数据事务都必须是输出的。一旦数据传输方向发生改变,就会认为进入到了状态过程。数据过程的第一个数据包必须是DATA1,然后每次正确传输一个数据包后就在DATA0DATA1之间交替。

    状态过程也是一笔批量事务,它的传输方向刚好跟前面的数据阶段相反,即控制写传输在状态过程使用一个批量输入事务;控制读传输在状态过程使用一个批量输出事务。状态过程只使用DATA1包。

    控制传输之所以要弄得这么复杂,是因为它要保证数据传输过程的数据完整性。设备枚举过程中各种描述符的获取以及设置地址、设置配置等,都是通过控制传输来实现的。关于USB协议中定义的控制传输所使用的各种标准请求的数据结构和请求命令,将会在后面的实例中具体、详细地分析。

    接下来我们来说一下端点类型和传输类型的关系。一个具体的端点,只能工作在一种传输模式下。通常,我们把工作在什么模式下的端点,就叫做什么端点。例如,控制端点、批量端点等。端点0是每个USB设备都必须具备的默认控制端点,它一上电就存在并且可用。设备的各种描述符以及主机发送的一些命令,都是通过端点0传输的。其他端点是可选的,需要根据具体的设备来决定。非0端点只有在 Set Config之后才能使用。

    今天就跟大家分享到这里,你学会了吗?

     


    收藏 0 回复 0 浏览 101
  • 指针和数组的恩恩怨怨

    指针和数组有没有关系呢?到底有什么关系,今天我们就来好好的看一看。

    指针就是指针,指针变量在32位系统下,永远占4字节,其值为某一个内存的地址。指针可以指向任何地方,但是不是任何地方你都能通过这个指针变量访问到呢?

    数组就是数组,其大小与元素的类型和个数有关;定义数组时必须指定其元素的类型和个数;数组可以存任何类型的数据,但不能存函数。

    既然它们之间没有任何关系,那为何很多人经常把数组和指针混淆,甚至很多人认为指针和数组是一样的呢?我们先来看下吧。

    1、以指针的形式访问和以下标的形式访问
    下面我们就详细讨论讨论它们之间似是而非的一些特点。例如,函数内部有如下定义:

    (A)char *p = abcdef;

    (B)char a[ ] = abcdef;

    ①以指针的形式访问指针和以下标的形式访问指针

    以指针的形式:*p+4

    以下标的形式:p[4]

    这里的4 是偏移量,都是先取出p里存储的地址值,加上偏移量,计算出新的地址,然后从新的地址中取出值。那么上面形式不同,访问的本质是一样的。

    ②以指针的形式访问数组和以下标的形式访问数组

    以指针形式:*a+4

    以下标形式:a[4]

    我们都知道数组名代表数组首元素的首地址,加上4个元素的偏移量,得到新的地址,然后取出新地址上的值。

    由此得出指针和数组都是可以“以指针的形式”或“以下标的形式”进行访问,但是是完全不一样的东西。

    还有需要注意的是这个偏移量代表的是元素,而不是字节,偏移元素的个数再计算新的地址取值。

    2、a &a 的区别

    先来举个例子:

    int a[5] = {1,2,3,4,5},b,c;

    int *prt = (int *)(&a + 1);

    b = *(a+1);

    c = *(ptr-1);

    对指针进行加1操作,得到的是下一个元素的地址,而不是原有地址值直接加1,所以一个类型为T的指针的移动,以sizeof(T)为移动单位。因此,对上面例子来说,a是一个一维数组,数组中有5个元素,所以&a+1是取数组a的首地址,该地址的值加上sizeof(a)的值,也就是&a+5*sizeof(int),也就是下一个数组的首地址,显然当前指针已经越过了数组的界限。

    那么*a+1):a&a的值是一样的,但是意思不一样,a是数组首元素的地址,也就是a[0]的首地址,&a是数组的首地址,a+1是数组下一个元素的首地址,也就是a[1]的首地址,&a+1是下一个数组的首地址,所以b的值应该是输出2*ptr-1),因为前面我们分析ptr是指向a[5]的,并且ptrint*类型,所以*ptr-1)是指向a[4],输出为5

    由此我们可以得知数组名a代表的是数组首元素的首地址,而不是数组的首地址,&a才是整个数组的首地址。

    指针和数组你能完全理清楚了吗?

     


    收藏 0 回复 0 浏览 108
  • USB的四种传输类型之中断传输等时传输

    USB协议规定了4中传输类型:批量传输,等时传输,中断传输和控制传输.我们已经有相关文章介绍了批量传输,接着下面我们来说说中断传输和等时传输.

    中断传输是一种保证查询频率的传输中断端点在端点描述符中要报告它的查询间隔,主机会保证在小于这个时间间隔的范围内安排一次传输这里所说的中断,跟我们硬件上的中断是不一样的。它不是由设备主动地发出一个中断请求,而是由主机保证在不大于某个时间间隔内安排一次传输。中断传输通常用在数据量不大,但是对时间要求较严格的设备中,例如人机接口设备(HID)中的鼠标、键盘、轨迹球等。中断传输也可以用来不断地检测某个状态,当条件满足后再使用批量传输来传送大量的数据。除了在对端点查询的策略上不一样之外中断传输和批量传输的结构基本上是一样的,只是中断传输中没有PINGNYE两种包。中断传输使用中断事务(interrupt-transaction),中断事务的流程图如图1所示

    image.png

    等时传输(同步传输)用在数据量大、对实时性要求高的场合,例如音频设备、视频设备等,这些设备对数据延迟很敏感。对于音频或者视频设备来说,对数据的100%正确要求不高,少量数据的错误还是能够容忍的,主要的是要保证不能停顿;所以等时传输是不保证数据100%正确的。当数据错误时,并不进行重传操作。因此等时传输也就没有应答包。数据是否正确,可以由数据包的CRC校验来确认。至于出错的数据如何处理,由软件来决定。等时传输使用等时事务(isochronous-transaction)来传输数据。图2是等时事务的流程图

    image.png

    以上就是中断传输和等时传输了,你明白了吗?


    收藏 0 回复 0 浏览 125
×
黄忠