USB协议简介
    USB是一种协议总线,即主机与设备之间的通信需要遵循一系列约定。协议内容较多,这里仅作一些简单介绍,深入学习,可参看USB规范(WWW.usb.org)。
    为了理解协议中的名称,先看图10.32。该图突出了主机上的客户软件和USB逻辑设备(编程涉及的设备)之间的通信流(Communication Flow),该通信流跨越了USB驱动程序USBD、主控制器驱动程序UHCD、主控制器等硬件接口及其连接。端点(Endpoints)是USB设备的惟一可识别的部分,是主机和设备之间通信流的终点。每一个逻辑设备有若干个独立端点,每一个端点在设计时被分配一个惟一的由设备确定的标识符,称之为端点号。
    如图10.32所示,将用于通信流流动的通道称为管道(Pipe),这是忽略了许多中间环节的很形象的称呼,对于理解USB系统中的信息传输很有帮助。图中把3个端点看成了一个接口,关于接口的说明安排在后面。

 

1.包格式
包的概念在前面已经介绍了,包是帧的基本成分。常用的包有令牌包、数据包和握手包。对于高速传输,还定义了事务分割专用令牌包(事务分割开始令牌包和事务分割完成令牌包)。
  1)令牌包格式
  在USB系统中,所有的通信都是由主机发出相应的令牌所引起的。令牌包格式图
10.33所示。
    其中PID为包标识,ADDR为设备地址,ENDP为端点号,CRC5是对ADDR和ENDP域进行校验的5位CRC校验码,校验多项式为:G(X)=X5+X2+1。
  2)数据包格式
  数据包用于主机与设备之间的数据传输。数据包格式如图10.34所示。
  其中PID为包标识,DATA为数据位,最多为8 192个位,DATA应是字节的整数倍。CRCl6是对DATA域进行校验的16位CRC校验码,校验多项式为:G(X)=X16+X15+X2+1.

 

3)握手包格式
    握手包用来指示数据被成功接收、命令被接收或被拒绝等事务状态。握手包格式如图10.35所示。
    握手包仅由PII)组成。有四种常用握手包(ACK、NAK、STALL和NYET)和一个专用握手包,握手包的类型是通过PID的编码来体现的。
·ACK包表示接收器已成功接收数据。
·NAK包表示接收设备不能接收数据或发送设备不能发送数据。
·STALL包表示端点已终止或不支持控制管道请求。
·NYET包表示接收器还没有任何响应。
    4)帧开始包SOF(Start Of Frame)

 

在全速或低速时,主机每隔1 ms±0.0005 ms发出一个帧开始包SOF,在高速时,每隔125 μs±0.0625μs发出一个SOF,以表示开始一个新帧。SOF包的格式如图10.36所示。
   

   
    其中FmmeNumber为帧编号,每发一帧后FrameNumber加l,当11位都为1(即3FFH)时再加1又回到0。在SOF包中对FrameNumber域进行CRC校验。
    2.PID域格式
    上面的几种包的开始都是PID域。PID域的格式如图10.37所示。

 

    低4位用来标识不同的包,高4位分别为低4位的非。这样安排是为了保证对PID可靠的译码,从而也使得包的其他部分能得到正确解释。表lO.20表示了PID编码和对应的PID类型。其中第3列是PID的低4位,即PID编码。
    表中有两种数据包PID,都用于数据的传输,以它们开头的两种数据包除了包PID部分有一位(及与它对应的反向位)不同外,其他部分都相同。设置这两种数据包是为了使发送方和接收方保持同步,这涉及到一些细节,将在10.3.6小节中介绍。在图10.38~10.40中不妨将它们看成一种数据包。

 

    3.USB传输的处理过程
    前面已经提到USB系统中有四种传输:一个传输通常要分解成若干个事务;而一个事务的处理一般要经历令牌包、数据包和握手包三个阶段,但也有一些事务的处理没有数据包阶段或没有握手包阶段,还有一些事务只有令牌包阶段。下面对这四种传输的处理过程分别作一些介绍。
    1)块传输
    用于主机与USB设备之间的批量数据传输,通常一次块传输需要分解成若干个块传输事务。显然,一次块传输的方向是单一的,对主机而言,要么是输入,要么是输出。因此,一次块传输是由若干个IN事务或由若干个OUT事务组成的。图10.38所示是块传输事务处理过程示意图。图中的PING包和NYET包仅用于高速传输设备,初学者暂时可以不考虑。

    对于要进行输入的块传输,一般要执行若干个IN事务。每执行一个IN事务时,主机都首先发出IN令牌包。设备端点收到后做出响应,一般是回送一个数据包。如果不能回送数据,则回送NAK包或STALL包。NAK表示设备暂时不能回送数据;STALL表示端点一直停着或需要IJSB系统软件进行干预;如果主机收到合法数据包,则回以ACK握手包;如果主机在接收数据时发现有错,则不给设备任何回音。
    对于要进行输出的块传输,一般要执行若干个OUT事务。每执行一个OUT事务时,主机都首先发出OUT令牌包,接着发出数据包。设备在收到数据包后,根据情况回以握手包;回以ACK表示数据已接收无误,并通知主机可开始下一个0UT事务,以便传送下一个数据包;回以NAK表示数据已接收无误,但是主机不要再送数据,因为设备暂时不能接收(如缓冲区满);如果端点已终止,则回以STALL,通知主机不要再重发数据,因为设备出现了故障;如果接收时出现CRC校验错,则不发任何握手包。
    需要指出,IN事务和OUT事务不仅在块传输事务中用到,在其他几种传输事务中也要用到,当然,处理的过程可能有所不同。
    2)中断传输
    用于数据传输量小,无周期性,但对响应时间敏感,要求马上响应的数据传输。中断传输的名字暗示一个设备可以引起一个硬件中断,这个硬件中断将使主机进行快速响应。但真实情况是中断传输和所有其他USB传输一样,只在主机访问设备时出现。之所以将其称为中断传输,是因为它可保证主机将在最短的延迟里响应或发送数据。中断传输的特别之处在于主机将按照特定的周期访问可引起中断的端点(称为中断端点),看是否有中断情况发生。图10.39所示为中断传输事务的处理过程。

 

对于要进行输入的中断传输,主机按照特定的周期执行IN事务,如果没有中断发生,中断端点回以NAK包;如果有中断情况发生,则回送中断数据。主机收到数据后,发一个ACK包。
    对于要进行输出的中断传输,主机按照特定的周期执行OUT事务,在发送OUT令牌后,接着发送数据包。如果没有中断发生,中断端点回以NAK包或STALL包;如果有中断情况发生且接收数据无误,则回送ACK包。需要指出,在设备没有中断发生的情况下,主机一直会按照特定的周期执行OUT事务,并且所发送的数据保持不变。当有中断发生时,才修改数据指针,指向下一个数据区。
    一个中断传输由一个或多个IN事务或者一个或多个OUT事务组成。一个中断传输用以下两种情况之一结束:当请求的数据量被传送完时,或者当数据包的长度小于规定的最大值(包括0长度包)时。中断传输的结束表示要传送的数据已经到齐,接收方可以加以利用;而主机对中断端点周期性的查询还将继续进行下去,以便在下一个中断情况发生时,开始下一个中断传输。
    3)等时传输
    用于有周期性、传输速率不变的数据传输。等时传输在每帧中传送的字节数是一定的。一个等时传输由一个或多个连续帧里每帧一个IN或一个OUT事务所组成。图10.40表示了等时传输事务的处理过程。可以看出,等时传输的IN事务和OUT事务只包括令牌包和数据包两个阶段,没有握手包阶段,也不支持重试。
    4)控制传输
    控制传输提供了一种方法来配置USB设备,并对它的操作的某些方面进行控制。每个设备必须设置一个缺省的控制端点(通常是O号端点)。控制端点用来配置设备、控制设备状态以及设备操作的某些方面。控制端点响应一些通过控制传输发送过来的USB特殊请求。例如,当系统检测到设备时,系统软件必须读取该设备的描述符,以确定其类型和操作特性。
    控制传输至少由两个阶段组成,也可以是三个阶段:
    ①SETUP阶段:控制传输总是从SETUP阶段开始,这个阶段把信息发送给目标设备,定义对设备的请求类型(例如,读设备描述符)。
    ②数据阶段:这个阶段仅仅是为需要数据传输的请求定义的。例如,在数据阶段,读描述符请求把描述符的内容发送给主机。一些请求在SETUP阶段之外不需要数据传输。
    ③状态阶段:这个阶段总是用来报告被请求的操作的结果。
    在SETUP阶段,一个SETUP事务被用来向控制端点传输信息。SETUP事务类似于
一个OUT事务,只是包标识PID是SETUP,而不是OUT。图10.41所示为SETUP事务的执行过程。SETUP事务的数据阶段总是利用DATA0 PID。如果接收正确,控制端点则回以ACK包;如果接收不正确或数据丢失,则不回送任何握手包。
    控制传输的数据阶段不是必需的。如果需要有这个阶段,则它由一个或多个IN事务或者一个或多个OUT事务组成。数据阶段的所有事务的方向必须是一致的,即都是IN事务或都是OUT事务。数据阶段传送的数据量及方向是在SETUP阶段规定的。如果数据量超过了预先确定的数据包规模,则数据的发送需要多个能携带最大包的事务(IN或OUT),剩下的部分(不足最大包规模)再安排一个事务。
    控制传输的状态阶段是该传输的最后一个阶段,它只需要一个事务。状态阶段的数据流方向应该与前面的阶段不同,并且总是利用DATAl PID.例如,如果数据阶段执行的是OUT事务,则状态阶段就是一个IN事务。如果一个控制传输没有数据阶段,则状态阶段由一个IN事务组成。图10.42所示为控制读传输、控制写传输以及没有数据阶段的控制传输的事务排列顺序、触发位的值(在括号内)及数据PID的类型。

    上面介绍的传输及传输事务的处理过程反映了USB系统中数据传输的过程。注意到一帧(或微帧)中包括了四种传输事务,所以实际的传输过程要比这里所讲的复杂。
4.数据触发技术
    在USB系统中采用了数据触发技术。数据触发是一种机制,用来确保数据传输的发送方和接收方之间保持同步,对于需要大量事务的一次长传输过程尤为重要。数据触发机制可以使握手包出错情况下发送方和接收方之间能重新同步。
    数据触发仅仅支持中断传输、块传输和控制传输。支持数据触发机制的发送方和接收方在每一次数据传输时都必须具有触发位。当双方都认为数据传输已经正确完成以后,都会把自己的触发位转换为和原来相反的状态。两种类型的数据包(DATAO和DATAl)被交替传送,并且包的接收方将会把它和触发位作比较,以确定接收的包是否正确。发送方使用的数据包类型和它的触发位当前状态保持一致(例如,如果触发位为0,则数据包用DATA0)。下面仅以OUT事务为例来理解数据触发机制。
    例10.1  图10.43所示为无错误的OUT事务的处理过程和触发位的变化情况。假定发送方和接收方的触发位开始都是0。传输的过程

 

如下:
    事务处理l:

 

①主机向目标设备发送一个OUT令牌。
②目标设备无错误地收到该令牌包。
③主机向目标设备发送一个DATA0数据包(和它的触发位保持一致)。
④目标设备收到数据包DATA0,它和触发位一致。
⑤目标设备成功收到数据包DATA0,触发位转变为1。
⑥目标设备向主机发送一个ACK握手包,通知主机数据已经被无错误接收。
⑦主机无错误地收到ACK包。
⑧成功地收到ACK包,主机把触发位转变为l。
事务处理2:
①主机向目标设备发送一个新的OUT令牌,开始下一个事务处理过程。
②目标设备无错误地收到该令牌包。
③主机向目标设备发送一个DAl、A1数据包(和它的触发位保持一致)。
④目标设备收到数据包DATAl,它和触发位一致。
⑤目标设备成功收到数据包DATAl,触发位转变为0。
⑥目标设备向主机发送一个ACK握手包,通知主机数据已经被无错误接收。
    ⑦主机无错误地收到ACK包。
    ⑧成功地收到ACK包,主机把触发位转变为0。
    这个处理过程对每一个事务都是如此,直到整个传输完成。只要收到的数据包和触发位相一致,并且发送方无错误地收到ACK握手包,那么发送方和接收方就保持同步。
    上面是数据包和握手包都被正确传输的情况。下面分别看一下数据包传输出错和握手包传输出错时的情况。
    例l0.2  图10.44所示为一个传输的第m个OUT。事务的处理过程,期间数据包传输出现了错误。主机和目标设备所采取的行动如下:
    事务处理m:
    ①主机向目标设备发送一个OUT令牌。
    ②目标设备无错误地收到该令牌包。    ,
    ③主机向目标设备发送一个DATA0数据包(和它的触发位保持一致)。
    ④当目标设备收到数据包DATAO时,发现有错。
    ⑤因为检测到数据包的错误,目标设备将会忽略这个包。数据被丢弃,不向主机发握手包。因为数据包没有正确接收,触发位保持不变。
    ⑥主机等待握手包的返回,但是没有响应。在总线超时周期(16个位时间)到达后,主机检测到没有响应,于是它认为数据包的传输不成功,主机的触发位保持不变。主机必须在以后重新进行该事务处理。
  事务m重新进行:
  ①主机再向目标设备发送OUT令牌。
  ②目标设备无错误地收到该令牌包。
  ③主机向目标设备发送一个DATAO数据包(和它的触发位保持一致),这个数据包在上一次传送时没有成功。
    ④目标设备成功地收到数据包DATA0,它和触发位保持一致。
    ⑤因为正确收到数据包DATA0,所以目标设备将触发位转变为1。
    ⑥目标设备向主机发送一个ACK握手包,通知主机数据已经被无错误接收。
    ⑦主机无错误地收到ACK包。
    ⑧成功地收到了ACK包,主机把触发位转变为l。
    由上面的处理过程可以看出,尽管传输发生了错误,但是主机和目标设备还是能够保持同步。
    例10.3  图10.45所示为一个传输的第n个OUT事务的处理过程,期间由于ACK包错误而失败。对错误检测和恢复的每一步列举如下:
    事务处理n:
    ①主机向目标设备发送一个OUT令牌。
    ②目标设备无错误地收到该令牌包。
    ③然后主机向目标设备发送一个DATA0数据包(和它的触发位保持一致)。
    ④目标设备收到数据包DATA0,它和触发位一致。
    ⑤目标设备成功收到数据包DATA0,触发位转变为1。
    ⑥目标设备向主机发送一个ACK握手包,通知主机数据已经被无错误接收。
    ⑦主机收到的ACK包出现了错误。
    ⑧由于主机检测到了错误,所以它不能确定目标设备是否已经成功地接收到数据。因此,主机的触发位没有改变(还是0)。主机假定目标设备没有收到数据,因而会重新进行该事务处理。
    事务n重新进行:
    ①主机再向目标设备发送OUT令牌。
    ②目标设备无错误地收到该令牌包。
    ③主机重新向目标设备发送DATA0数据包(和它的触发位保持一致),这个数据包在上一次传

 
 

送时不知道目标设备是否已正确接收。
    ④目标设备无错误地收到数据包DATA0,但是它和触发位不一致。
    ⑤目标设备认为其本身和主机不同步,因而丢弃数据,并且触发位保持不变(1)。
    ⑥目标设备向主机发送一个ACK握手包,通知主机数据已经被无错误接收,这是因为
主机明显没有收到上一次的ACK握手包。
    ⑦主机无错误地收到ACK握手包。
    ⑧成功地收到了ACK包,主机把触发位转变为1。现在主机和目标设备就为下一次的事务处理做好了准备。
    通过该例可以看出,主机和目标设备暂时在数据传输是否完成的问题上没有达成一致。然而,数据触发机制保证了不同步的状态能够被检测到,并且能够重新实现同步。