USB的4种传输类型
简介:本节介绍USB full speed function的四种传输类型。
3.1. 控制传输(Control Transfers)
上节中我们了解到了USB host 与USB function 之间采用的是一种“非对称”的传输,也就是说,无论USB接受数据还是发送数据,都是由USB host首先发起。即传输的第一个packet总是由USB host发出的。这个packet将声明本次即将进行的数据传输方向,数据传输地址和数据传输类型。
或许你已经注意到了,一个USB host端口并不是仅仅支持一个USB function,如图:

通过USB hub,一个USB host端口可以连接USB鼠标,USB键盘,USB写字板。..。..。要连接这么多东西在同一个USB host上,我们通常会有一个基本问题,即USB host如何识别这些被连接在它的端口上的设备呢?
正如通常的主从式通讯系统一样,如RS485多机通讯,我们通常是用一个特定的地址标志每一个从设备。对这里的USB,我们采用同样的方法,将为每个挂接在该USB host上的USB function指定一个特定地址,通过这个特定地址来识别每个USB function。
看来这将是一个USB function在数据传输之前必须解决的问题——如何得到它的地址分配?
这个“地址指定”的过程需要USB host通知USB function才能完成,这个交互过程就是一个“控制式传输”。
通过这个“控制式传输”,USB host将指定地址给USB function,以为即将进行的正式通讯做好准备工作。这里细心的读者可能已经注意到了,既然USB host总要分配地址给USB function才能进行正式的数据传输工作,那么USB host将如何与一个初始时未分配地址的USB function进行交互来分配地址呢?
这里,是这样解决的:
USB协议保留了一个“通用地址0”,USB host通过这个地址0来和初始未分配地址的USB function进行通讯,进行一些初始的准备工作,诸如这里的为它分配一个特定地址。后面我们就会了解到,USB除了配置地址外,还有一些其它参数需要事先主从双方达成共识。这些参数也都是通过控制式传输完成的。
一个USB的“控制式传输”如图:

一个USB的“控制式传输”分为两个或三个阶段进行传输:
SETUP stage ——》 DATA stage ——》 STATUS stage
首先是SETUP stage,联系上节所说的USB传输模式,USB Host总是先发起第一个packet:这里它首先发起SETUP,之后发起以DATA0为起始的Setup Data,最后USB function回应ACK结束一次交互。
其次如果有DATA stage,类似的,还是按照上节说的USB传输模式,USB host总是先发起第一个packet:OUT或IN,之后USB host(或USB function)发起以DATA1为起始的Payload Data,最后USB function(或USB host)回应ACK结束一次交互。
如果数据未传完,继续DATA stage,同上继续。
最后是status stage,类似的, USB host首先发起第一个Packet:IN或OUT,之后USB function(或USB host)发起以DATA1为起始的Null Data(0长度),最后USB host(或USB function)回应ACK结束一次交互。
如此,整个控制式传输结束。
你或许有疑问,DATA stage为什么进行了多次而非一次完成?
实际上,USB总是将一批大量的数据分成了许多小段来进行传输,称为一个Payload。这样传输的目的是容易对传输进行控制。既然一次大量的数据总是被分成一段一段来分次传输,那么这里就出现了一个需要事先确定的参数(wMaxPacketSize):即每次即这个小段有多大。这个参数如地址指派一样,正式传输之前需要事先达成共识。
USB host定时对USB集线器的状态进行查询。当一个新USB设备接入集线器时,主机会检测到集线器状态改变,主机发出一个命令使该端口有效并对其进行设置。位于这个端口上的设备进行响应,主机收到关于设备的信息,主机的操作系统确定对这个设备使用那种驱动程序,接着设备被分配一个唯一标识的地址,范围从0~127,其中0为所有的设备在没有分配惟一地址时使用的默认地址。主机向它发出内部设置请求。当一个设备从总线上移走时,主机就从其可用资源列表中将这个设备删除。
通过“控制式传输”,现在我们已经完成了USB function的地址指定等参数的设置工作,下一步可以进行正式的数据传输了。
3.2. 批量传输(Bulk Transactions)
我们终于等到USB function 配置完成,现在我们的任务是要传送一批数据,这里可以使用“批量数据传输(Bulk Transactions)”。 一个“批量传输”总是按照如图所示方式进行:

首先,USB host发起第一个Packet:IN或OUT,表示要开始数据传输了;
其次,USB function(或USB host)发起以DATA1或DATA0为起头的Payload Data,开始一次交互;
最后,USB host(或USB function)发起ACK回应这次交互。
如果数据还未传完,继续上述过程,即:
首先,USB host再次发起一个Packet:IN或OUT,表示又要开始数据传输了;
其次,USB function(或USB host)发起以DATA0或DATA1为起头的Payload Data,开始又一次交互;
再次,USB host(或USB function)发起ACK回应这次交互。
如此继续直至传输完成。
这里的疑问依然是为什么一次可能传完的数据为什么分成多次进行传输,原因在上次介绍“控制式传输”时已经说明。后面我们就会明白,为什么这样可以方便控制传输过程。仔细看看控制式的DATA stage采用的传输方式,是否就是批量传输方式呢?!
注意,每次Payload Data的“牵头人(Preamble)”在轮番掉换,先是DATA1,接着DATA0,再是DATA1.。..。.如此接替,只要有一次交互出现问题,这个接替规则就会被打破进而被USB host识别而发现传输异常。所以这个交替的“牵头人”规则是可靠数据传输的所采取的措施之一。
3.3. 同步(及时)传输(Isochronous Transactions)和中断式传输(Interrupt Transactions)
在“批量数据传输”中,触发一次“批量数据传输”总是“被动”的,就是说需要数据传输时USB host并不会主动发起传输,而是需要得到你的指令。当你告诉它:“一切ok,让我们开始吧!” 这时它才开始数据传输。
这种方式显然在某些情况下并不适合。比如音视频流,你无法要求它听从你的“指挥”,让它等你发指令给USB host,然后开始一次传输。我们需要的是一种“及时的”传输。
一个好的方案就是设置一个Timer,按照Tick发起USB传输。这个Tick通常以1ms(USB full speed)为最小单位。这时,可以设置为每次1ms Tick出现,USB host“自动”发起一次数据传输。那么这种方案具体如何来实现呢?
看来最基本的要素便是一个发出Tick的Timer,而这个Timer需要USB host和USB function(事实上还要包括USB hub)双方均能“看到”,从而协调工作,否则单方面的Timer又有何意义?
这个Timer在USB中使用一个特殊的packet实现,即是SOF。
这个SOF由USB host相当精确地以每1.00ms ±0.0005ms的时间周期发送给USB device(function),来在二者之间定时。从而USB function能够“及时”了解到“现在时刻”。现在我们在USB host和USB function之间建立起了“对时机制”。那么接下来看看刚才设想的“自动”传输如何实现。
事实上,一旦USB host及USB function双方建立了一种时间机制,那么这种“自动”传输是很容易实现的。USB 实现“同步式传输”或“中断式传输”总是以一种类似于“批量数据传输”的方式进行的,唯一不同的是传输的触发不再是被动的,而是由SOF所建立的Tick触发。
首先,Tick时间到达,USB host发起第一个Packet:IN或OUT,表示要开始数据传输了;
其次,USB function(或USB host)发起以DATA1(或DATA0))为起头的Payload Data,开始一次交互;
再次,若是中断式传输,USB host(或USB function)发起ACK回应这次交互,若是同步式传输,该步跳过;
如此重复上述步骤,即USB host等待下一个Tick到达,并开始新一轮的交互。
这里我们注意到了,“同步式传输”和“中断式传输”二者虽然都是时间触发,但是中断式传输需要ACK应答,而“同步式传输”不需要。这个最大的区别决定了“同步式传输”是一种非可靠传输,但是因此换来了更多的USB传输时间。也因此,同步式传输的Payload Data(对应wMaxPacketSize)通常相较于其他传输方式比较大,因为它消掉了ACK所占有数据传输时间。
这里还有一个地方值得注意的是Tick的设定,这个Tick也是需要事先USB host和USB function达成共识的参数之一。
USB的4种传输类型
简介:本节介绍USB full speed function的四种传输类型。
3.1. 控制传输(Control Transfers)
上节中我们了解到了USB host 与USB function 之间采用的是一种“非对称”的传输,也就是说,无论USB接受数据还是发送数据,都是由USB host首先发起。即传输的第一个packet总是由USB host发出的。这个packet将声明本次即将进行的数据传输方向,数据传输地址和数据传输类型。
或许你已经注意到了,一个USB host端口并不是仅仅支持一个USB function,如图:

通过USB hub,一个USB host端口可以连接USB鼠标,USB键盘,USB写字板。..。..。要连接这么多东西在同一个USB host上,我们通常会有一个基本问题,即USB host如何识别这些被连接在它的端口上的设备呢?
正如通常的主从式通讯系统一样,如RS485多机通讯,我们通常是用一个特定的地址标志每一个从设备。对这里的USB,我们采用同样的方法,将为每个挂接在该USB host上的USB function指定一个特定地址,通过这个特定地址来识别每个USB function。
看来这将是一个USB function在数据传输之前必须解决的问题——如何得到它的地址分配?
这个“地址指定”的过程需要USB host通知USB function才能完成,这个交互过程就是一个“控制式传输”。
通过这个“控制式传输”,USB host将指定地址给USB function,以为即将进行的正式通讯做好准备工作。这里细心的读者可能已经注意到了,既然USB host总要分配地址给USB function才能进行正式的数据传输工作,那么USB host将如何与一个初始时未分配地址的USB function进行交互来分配地址呢?
这里,是这样解决的:
USB协议保留了一个“通用地址0”,USB host通过这个地址0来和初始未分配地址的USB function进行通讯,进行一些初始的准备工作,诸如这里的为它分配一个特定地址。后面我们就会了解到,USB除了配置地址外,还有一些其它参数需要事先主从双方达成共识。这些参数也都是通过控制式传输完成的。
一个USB的“控制式传输”如图:

一个USB的“控制式传输”分为两个或三个阶段进行传输:
SETUP stage ——》 DATA stage ——》 STATUS stage
首先是SETUP stage,联系上节所说的USB传输模式,USB Host总是先发起第一个packet:这里它首先发起SETUP,之后发起以DATA0为起始的Setup Data,最后USB function回应ACK结束一次交互。
其次如果有DATA stage,类似的,还是按照上节说的USB传输模式,USB host总是先发起第一个packet:OUT或IN,之后USB host(或USB function)发起以DATA1为起始的Payload Data,最后USB function(或USB host)回应ACK结束一次交互。
如果数据未传完,继续DATA stage,同上继续。
最后是status stage,类似的, USB host首先发起第一个Packet:IN或OUT,之后USB function(或USB host)发起以DATA1为起始的Null Data(0长度),最后USB host(或USB function)回应ACK结束一次交互。
如此,整个控制式传输结束。
你或许有疑问,DATA stage为什么进行了多次而非一次完成?
实际上,USB总是将一批大量的数据分成了许多小段来进行传输,称为一个Payload。这样传输的目的是容易对传输进行控制。既然一次大量的数据总是被分成一段一段来分次传输,那么这里就出现了一个需要事先确定的参数(wMaxPacketSize):即每次即这个小段有多大。这个参数如地址指派一样,正式传输之前需要事先达成共识。
USB host定时对USB集线器的状态进行查询。当一个新USB设备接入集线器时,主机会检测到集线器状态改变,主机发出一个命令使该端口有效并对其进行设置。位于这个端口上的设备进行响应,主机收到关于设备的信息,主机的操作系统确定对这个设备使用那种驱动程序,接着设备被分配一个唯一标识的地址,范围从0~127,其中0为所有的设备在没有分配惟一地址时使用的默认地址。主机向它发出内部设置请求。当一个设备从总线上移走时,主机就从其可用资源列表中将这个设备删除。
通过“控制式传输”,现在我们已经完成了USB function的地址指定等参数的设置工作,下一步可以进行正式的数据传输了。
3.2. 批量传输(Bulk Transactions)
我们终于等到USB function 配置完成,现在我们的任务是要传送一批数据,这里可以使用“批量数据传输(Bulk Transactions)”。 一个“批量传输”总是按照如图所示方式进行:

首先,USB host发起第一个Packet:IN或OUT,表示要开始数据传输了;
其次,USB function(或USB host)发起以DATA1或DATA0为起头的Payload Data,开始一次交互;
最后,USB host(或USB function)发起ACK回应这次交互。
如果数据还未传完,继续上述过程,即:
首先,USB host再次发起一个Packet:IN或OUT,表示又要开始数据传输了;
其次,USB function(或USB host)发起以DATA0或DATA1为起头的Payload Data,开始又一次交互;
再次,USB host(或USB function)发起ACK回应这次交互。
如此继续直至传输完成。
这里的疑问依然是为什么一次可能传完的数据为什么分成多次进行传输,原因在上次介绍“控制式传输”时已经说明。后面我们就会明白,为什么这样可以方便控制传输过程。仔细看看控制式的DATA stage采用的传输方式,是否就是批量传输方式呢?!
注意,每次Payload Data的“牵头人(Preamble)”在轮番掉换,先是DATA1,接着DATA0,再是DATA1.。..。.如此接替,只要有一次交互出现问题,这个接替规则就会被打破进而被USB host识别而发现传输异常。所以这个交替的“牵头人”规则是可靠数据传输的所采取的措施之一。
3.3. 同步(及时)传输(Isochronous Transactions)和中断式传输(Interrupt Transactions)
在“批量数据传输”中,触发一次“批量数据传输”总是“被动”的,就是说需要数据传输时USB host并不会主动发起传输,而是需要得到你的指令。当你告诉它:“一切ok,让我们开始吧!” 这时它才开始数据传输。
这种方式显然在某些情况下并不适合。比如音视频流,你无法要求它听从你的“指挥”,让它等你发指令给USB host,然后开始一次传输。我们需要的是一种“及时的”传输。
一个好的方案就是设置一个Timer,按照Tick发起USB传输。这个Tick通常以1ms(USB full speed)为最小单位。这时,可以设置为每次1ms Tick出现,USB host“自动”发起一次数据传输。那么这种方案具体如何来实现呢?
看来最基本的要素便是一个发出Tick的Timer,而这个Timer需要USB host和USB function(事实上还要包括USB hub)双方均能“看到”,从而协调工作,否则单方面的Timer又有何意义?
这个Timer在USB中使用一个特殊的packet实现,即是SOF。
这个SOF由USB host相当精确地以每1.00ms ±0.0005ms的时间周期发送给USB device(function),来在二者之间定时。从而USB function能够“及时”了解到“现在时刻”。现在我们在USB host和USB function之间建立起了“对时机制”。那么接下来看看刚才设想的“自动”传输如何实现。
事实上,一旦USB host及USB function双方建立了一种时间机制,那么这种“自动”传输是很容易实现的。USB 实现“同步式传输”或“中断式传输”总是以一种类似于“批量数据传输”的方式进行的,唯一不同的是传输的触发不再是被动的,而是由SOF所建立的Tick触发。
首先,Tick时间到达,USB host发起第一个Packet:IN或OUT,表示要开始数据传输了;
其次,USB function(或USB host)发起以DATA1(或DATA0))为起头的Payload Data,开始一次交互;
再次,若是中断式传输,USB host(或USB function)发起ACK回应这次交互,若是同步式传输,该步跳过;
如此重复上述步骤,即USB host等待下一个Tick到达,并开始新一轮的交互。
这里我们注意到了,“同步式传输”和“中断式传输”二者虽然都是时间触发,但是中断式传输需要ACK应答,而“同步式传输”不需要。这个最大的区别决定了“同步式传输”是一种非可靠传输,但是因此换来了更多的USB传输时间。也因此,同步式传输的Payload Data(对应wMaxPacketSize)通常相较于其他传输方式比较大,因为它消掉了ACK所占有数据传输时间。
这里还有一个地方值得注意的是Tick的设定,这个Tick也是需要事先USB host和USB function达成共识的参数之一。
举报