从零开始学USB(十三、USB的四种传输类型(2))

虽然USB定义了数据在总线上传输的基本单位是包,但是我们还不能随意地使用包来传输数据。必须按照一定的关系把这些不同的包组织成事务(Transaction)才能传输数据

一、USB事务

那么事务是什么呢?事务通常由两三个包组成:令牌包,数据包 和握手包。

  • 令牌包用来启动一个事务,总是由主机发送。
  • 数据包传送数据,可以从主机到设备,也可以从设备到主机,方向由令牌包决定。
  • 握手包的发送者通常为数据接收者,当数据接收正确后,发送握手包。设备也可以用NAK握手来决定数据还未准备好。

USB协议规定了4种传输类型:批量传输、等时传输、中断传输和控制传输。其中批量传输、等时传输和中断传输每传输一次数据都是一个事务;控制传输包括三个过程,建立过程和状态过程分别是一个事务,数据过程则可能包含多个事务。

二、批量传输

批量传输是使用批量事务(Bulk Transactions)来传输数据。一次批量事务有三个阶段:令牌包阶段,数据包阶段和握手包阶段。批量传输分为批量读和批量写。批量读使用批量输入事务,霹雳啊写使用批量输出事务。

批量传输没有规定数据包中数据的意义和结构,具体的数据结构要由设备自己定义。批量传输通常在数据量大、对数据的实时性要求不高的场合,例如USB打印机、扫描仪、大容量存储设备等。

首先介绍批量输出事务。主机发出一个OUT令牌包,这个令牌中包含了设备地址、端点地址。然后再发送一个DATA包,这时地址和端点匹配的设备就会手下这个数据包。然后主机切换到接收模式,等待设备返回握手包。设备解码令牌包、数据包都准确无误,并且有足够的缓冲区来保存数据后,就会使用ACK握手包或者NYET握手包来应答主机(只有高速模式才有NYTE握手包,它表示本次数据成功接收,但没能力接收下一次传输)。如果没有足够的缓冲区来保存数据,那么它就会返回一个NAK握手包,高速主机目前没缓冲可用,主机会在稍后的事件重试该批量输出事务,如果设备检测到数据正确,但是端点处于挂起状态,则返回一个STALL握手包。如果设备检测到有错误(例如校验错误、位填充错误),则不做任何响应,让主机等待超时。

接下来看批量输入事务。主机首先发送一个IN令牌包,同样,IN令牌包中包含了设备地址和端点号。然后主机切换到接收数据状态,等待设备返回数据。如果设备简单到错误,那么它不做任何响应,主机等待超时。如果此时有地址和端点匹配的设备,并且没有检测到错误,则该设备做出响应;如果设备有数据需要返回,那么它把 数据白放到总线上;如果设备没数据返回,那么直接使用NAK握手包来响应主机。如果该端点处于挂起状态,则返回一个STALL握手包。如果主机接收到设备发送的数据包并解码正确后,使用ACK握手包应答设备。如果主机检测到错误,则不作出任何响应,设备会检测超时。USB协议规定,不允许主机使用NAK握手包来拒绝接收数据包(否则,设备会想,这货“U”真的是“SB”啊,你既然没空间接收了,还请求个毛数据啊,浪费时间吗....)。主机在收到NAK握手包后,知道设备暂时无数据返回,主机会在稍后的事件里重试该输入事务。

在USB2.0高速设备中增加了一个PING令牌包,它不发出数据,直接等待 设备的握手包,因此PING事务只有令牌包和握手包。

下图是一个批量事务的流程图。下面对该流程进行简单的解释,后面几种事务的流程图表示方法是差不多的,就不再一一解释了。

平时无数据传输时,总线处于空闲状态。当需要传输一次事务时,主机发送一个令牌包,它可以是OUT令牌包、IN令牌包或者是PING令牌包。如最上面的oken哪行所示。其中PING令牌包是USB2.0告诉模式输出特有的,全速模式和低速模式没有这个令牌包。

如果设备解码令牌包时出错,直接进入空闲状态。

令牌阶段只会是数据阶段或者握手阶段。对于批量输入事务,则由设备返回数据,或者返回应答包NAK握手或者STALL握手。这由设备状态决定。对于批量暑促事务,则主机在令牌包后面再发送一个数据包。

PING令牌用来探测设备是否有空间接收数据,它没有数据阶段,只有握手阶段,设备根据实际情况返回握手包。ACK握手包表示有空间接收设备,NAK表示没空间接收,STALL表示握手包端点挂起。

最后是握手阶段,对于批量输入事务,如果主机接收设备返回的数据正确,则由主机返回ACK握手包;否则数据出错,主机什么也不返回。主机必须要能够接收数据,不能用NAK握手包回应设备。对于批量输出事务,如果设备能够接收数据,则返回握手包;如果设备没有接收空间,则返回NAK握手包;如果设备端点挂起,则返回STALL握手包;如果检测到传输错误,则什么都不回应,直接进入到空间状态

下图给出了传输正确的批量输入和批量输出事务的数据包。

三、中断传输

中断传输是一种保证查询频率的传输。中断端点在端点描述符中要报告它的查询时间,主机会保证在小于这个事件间隔的范围内安排一次传输。

这里所说的中断,和我们硬件CPU上的中断是不一样的。他不是由设备主动的发出一个设备请求,而是由主机保证不大于某个时间间隔内安排一次传输。中断传输通常用在数据量不大,但是对时间要求较严格的设备中,例如人机接口设备(HID)中的鼠标,键盘,轨迹球。中断传输也可以用来不停的检查某个状态,当条件满足后再用批量传输来传送大量的设备。除了对端点查询的策略上不一样之外,中断传输和批量传输的结构基本上是一样的。只是中断传输中没有PING和NYET两种包。中断传输使用中断事务(Interrupt Transactions)。中断事务的流程图如下。

当端点使用中断传输机制来获取实际的中断数据时,必须遵循数据切换协议。 这允许该功能知道主机已经接收到数据并且可以清除事件条件。 这种“保证”的事件传递允许该功能仅在主机接收到中断信息之前发送中断信息,而不是每次轮询功能时都必须发送中断数据,直到USB系统软件清除中断条件。 在切换模式下使用时,中断端点通过端点上的任何配置事件初始化为DATA0 PID,其行为与批量事务相同。

下图给出了USB鼠标在按键中断事务中一次输入传输。可以看到格式和批量传输是一样的。

 

四、等时传输

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

五、控制传输

控制传输与前面三种传输相比,要稍微负责一些。

控制传输分为三个过程:

  • 第一个过程是建立过程
  • 第二个过程是可选的数据过程
  • 第三个过程是状态过程

建立过程使用一个建立事务。建立事务是一个输出数据包的过程,与批量传输的输出事务相比,有几处不一样:

  • 首先是令牌包不一样,建立过程使用SETUP令牌包。
  • 其次是数据包类型,SETUP只能使用DATA0包。
  • 最后是握手,设备只能采用ACK来应答(错了的情况不应答),不能使用NAK或者STALL来应答,即设备必须要接受建立事务的数据。

下图是一个建立事务的流程图。

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

控制传输的Status阶段是序列中的最后一个事务。状态阶段事务遵循与批量事务相同的协议序列。高速运行的设备的状态阶段还包括PING协议。状态阶段由前一阶段的数据流方向改变描绘,并始终使用DATA1 PID。例如,如果数据阶段由OUT组成,则为状态是一个单一的IN交易。如果控制序列没有数据阶段,则它由一个Setup阶段和一个由IN事务组成的Status阶段组成。
下图显示了事务顺序,数据序列位值和控制读取的数据PID类型并写入序列。序列位显示在括号中。

当控制端点在控制传输的数据或状态阶段发送STALL握手时,必须在对该端点的所有后续访问中返回STALL握手,直到收到SETUP PID为止。 在接收到后续SETUP PID之后,端点不需要返回STALL握手。 对于默认端点,如果为SETUP事务返回ACK握手,则主机期望端点已自动从导致STALL的条件中恢复,并且端点必须正常运行。

数据的拆分和数据传输完毕的判定 
以高速设备的最大数据包长度64字节为例 :

要传输250字节,拆分成4个packet 

要传输正好256字节,通过最后一个0字节包告诉设备传输完成

下图是一个低速(从每次发送最大字节为8推断)设备的控制读传输过程。

下图是两个没数据的控制传输过程。

下图给出一组控制传输,想学习的可以自己分析一下上面的格式。

六、总结

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/qq_16777851/article/details/85463744

发布了47 篇原创文章 · 获赞 9 · 访问量 1万+

虽然USB定义了数据在总线上传输的基本单位是包,但是我们还不能随意地使用包来传输数据。必须按照一定的关系把这些不同的包组织成事务(Transaction)才能传输数据

猜你喜欢

转载自blog.csdn.net/u013836909/article/details/104902167