USB 协议层
这一章从底层视角介绍 USB 协议,首先讲解字段和数据包的定义。接下来,描述不同事务类型的数据包的事务格式。然后介绍链路层的流控制和事务级别的故障恢复。最后讨论重试同步、数据总线混乱、总线活动丢失的恢复以及高速PING协议。本章作为USB软件开发的重要一章会对重要内容详细注解,其余内容提供说明详解请参阅手册。
8.1 USB 的字节/位顺序
数据位在总线上按照从最低位(LSb)开始依次发送,接着是下一个LSb,直到最高位(MSb)最后发送。在后面的图示中,数据包的显示方式使得每个独立的位和字段都按照总线传输的顺序(从左到右阅读顺序)呈现。
标准描述符、请求和响应中的多字节字段按照小端序(little-endian)解释和传输到总线上,即从LSB到MSB的顺序。
这一章节的内容主要介绍了USB协议底层的细节,关注于数据在 USB 总线上的传输方式,以及如何进行不同类型的事务处理。
-
位传输顺序:
- 数据在USB总线上是按位(bit)传输的,从最低位(LSb)开始,逐位发送到最高位(MSb)。这种顺序也叫做倒序传输,即低位先行。
-
字节顺序(Little-endian):
- USB协议使用小端字节序(Little-endian),即低位字节(LSB)先传输,随后是高位字节(MSB)。
- 在传输多字节数据时,多字节的数据(例如一个32位整数)会从最低有效字节(LSB)开始传送,而最高有效字节(MSB)最后传输。
-
协议层级的事务类型:
- 在这一章的后续内容中,会介绍USB协议中的不同事务类型,包括控制传输、批量传输、等时传输和中断传输,以及它们如何通过数据包的格式来定义。
- 每种事务类型有不同的数据包结构和传输规则。
-
链路层的流控制和事务级别的故障恢复:
- USB协议有一定的流控制机制,确保数据可以可靠地传输。
- 如果出现故障或丢包情况,USB协议提供了一定的故障恢复机制,保证通信能继续进行。
-
重试和同步机制:
- 在一些特殊情况下,如发生冲突或信号丢失时,USB协议会进行重试。
- 还涉及到一些特定的错误恢复策略,如数据总线的混乱(babble)和总线活动丢失(loss of bus activity)后的恢复机制。
-
高速PING协议:
- 高速模式下的PING协议是为了解决总线上的延迟问题而设计的,用于减少数据传输过程中的空闲时间,提高数据传输效率。
8.2 SYNC 字段(SYNC Field)
所有数据包都是以同步(SYNC)字段开始,这是一个编码序列,用于产生最大边缘转换密度。它被输入电路用来将接收到的数据与本地时钟对齐。来自初始发送器的 SYNC 字段在全速/低速模式下定义为 8 位长度,在高速模式下定义为 32 位长度。接收到的 SYNC 字段可能较短,具体描述见第 7 章。SYNC 字段仅用作同步机制,因此在后续的数据包图中不会显示(参考第 7.1.10 节)。SYNC 字段的最后两位是一个标记,用于识别 SYNC 字段的结束,并推断出 PID(包标识符)字段的开始。
SYNC 字段是 USB 数据包的开头部分,其主要作用是帮助数据接收端对接收到的信号进行同步。它通过包含一个具有最大边缘变化密度的编码序列,确保在数据通信过程中接收端能够与发送端保持时序一致。
- 全速/低速模式: 在这两种模式下,SYNC 字段的长度为 8 位
- 高速模式: 在高速模式下,SYNC 字段的长度扩展至 32 位。
-
对齐时钟:
SYNC 字段的设计是为了让接收端能够将接收到的数据流与其内部时钟进行同步。USB 使用的是非归零反转(NRZI)编码,边缘变化密度对于解码非常重要。 -
识别 PID 的起点:
SYNC 字段的最后两位作为标记,指示 SYNC 字段的结束和 PID 字段的开始。这有助于数据包的解码器正确识别数据包的结构。
8.3 数据包字段格式
以下描述令牌包(Token Packet)、数据包(Data Packet)和握手包(Handshake Packet)的字段格式。数据包的比特定义以未编码的数据格式显示。为了清晰起见,NRZI编码和比特填充的影响已被移除。所有数据包都有明确的开始和结束包定界符。开始包定界符(SOP)是同步字段(SYNC)的一部分,而结束包定界符(EOP)在第7章中有详细描述。
在USB 2.0中,数据传输是通过数据包来完成的。数据包用于承载通信信息,并且它们的格式是规范化的,以便确保数据在设备之间准确传输。每个数据包都由多个字段组成,其中最重要的字段之一就是定界符,它标识数据包的开始和结束。
-
数据包字段格式:
数据包的各个字段按照特定格式进行编码,但为了简化讨论,文档中以未经过编码的数据格式进行说明。通常,USB 2.0协议采用NRZI编码和比特填充来保证数据传输的稳定性,但在此处为了便于理解,这些编码技术的影响被忽略。 -
开始包定界符(SOP):
每个数据包的开始部分都会有一个标识开始的定界符(SOP),它位于同步字段(SYNC)中。同步字段有助于接收端正确同步接收数据包,确保数据的正确解析。 -
结束包定界符(EOP):
数据包的结束部分由结束包定界符(EOP)标识。EOP的作用是指示数据包的结束,确保接收端能准确知道数据包的边界。EOP的具体定义在第7章有详细讨论。
8.3.1 包标识符字段(Packet Identifier Field,PID)
每个 USB 包的同步字段 (SYNC field) 之后紧跟一个包标识符 (PID)。一个 PID 由一个 4 位的包类型字段和一个 4 位的校验字段组成,如图 8-1 所示。PID 指示包的类型,并由此推断包的格式以及应用于该包的错误检测类型。
PID 的 4 位校验字段确保 PID 能被可靠地解码,以便正确解释包的其余部分。PID 校验字段通过对包类型字段进行一位补码操作生成。如果这 4 位校验位不是其对应的包标识符位的补码,则存在 PID 错误。
主机和所有功能设备必须对接收到的所有 PID 字段进行完整解码。如果接收到的 PID 校验字段验证失败,或者解码出一个未定义的值,则认为其已损坏,该 PID 及其余的包将被包接收方忽略。如果某个功能设备接收到一个有效的 PID,但该 PID 对应的事务类型或方向不受支持,则该设备不应响应。例如,仅支持 IN 操作的端点必须忽略 OUT 标志。
- 包标识符 (PID) 位于每个 USB 包的同步字段之后。
- PID 包含两个部分:
- 包类型字段 (4 位):标识包的类型和格式。
- 校验字段 (4 位):通过包类型字段的一位补码生成,用于检测 PID 的完整性。
- 错误检测:
- 如果校验位与包类型位不匹配,则认为 PID 有错误。
- 有错误的 PID 和其余包内容将被忽略。
- 设备响应规则:
- 主机和设备必须能完整解码所有 PID。
- 未定义或校验失败的 PID 会被忽略。
- 不支持的事务类型 PID 会被设备无视(如 IN-only 设备忽略 OUT 标志)。
主机和所有功能模块必须对接收到的所有PID字段进行完整解码。任何PID若检查字段校验失败或解码为未定义值,则被认为已损坏,此类PID及其余数据包将被数据包接收器忽略。如果功能模块接收到适用于其不支持的事务类型或方向的有效PID,则功能模块必须不响应。例如,纯IN端点必须忽略OUT令牌。PID的类型、编码和描述详见表8-1。
-
PID完整解码规则:
- 完整解码:主机和所有设备必须完全解码接收到的PID字段。
- 校验失败:若PID字段中的校验字段失败,或其解码结果为未定义值,则数据包被视为损坏,接收方必须忽略此PID及后续数据包内容。
- 不支持的事务方向:如果接收到一个有效的事务PID,但功能模块不支持该事务类型或方向,则设备不能响应。例如:
- 一个仅支持IN方向的端点必须忽略OUT令牌。
-
表格8-1将PID分为四大类:
- 令牌类(Token):
- OUT:用于从主机到设备的传输事务。
- IN:用于从设备到主机的传输事务。
- SOF:帧起始标志及帧编号。
- SETUP:用于控制端点的初始化事务。
- 数据类(Data):
- DATA0/DATA1:分别表示奇偶数据包,用于数据同步。
- DATA2/MDATA:高带宽事务专用,用于微帧数据传输。
- 握手类(Handshake):
- ACK:表示接收成功。
- NAK:设备无法接收或发送数据。
- STALL:端点暂停或控制请求不支持。
- NYET:接收器尚未响应。
- 特殊类(Special):
- PRE:低速设备的预处理标志。
- ERR:拆分事务的错误标志。
- SPLIT:用于高速拆分事务。
- PING:高速流量控制探测。
- 令牌类(Token):
8.3.2 地址字段( Address Fields)
USB功能设备的端点(Function Endpoints)通过两个字段进行寻址:功能设备地址字段和端点字段。设备必须完全解码这两个字段。地址或端点字段的混叠(aliasing)是不允许的。如果任意字段不匹配,将导致令牌被忽略。访问未初始化的端点也将导致令牌被忽略。
8.3.2.1 地址字段
USB功能设备的地址(ADDR)字段根据令牌PID的值指定数据包的源或目的地址。ADDR字段如图8-2所示,总共支持128个地址,表示为ADDR<6:0>。该字段用于IN、SETUP和OUT令牌以及特殊令牌(如PING和SPLIT)。每个ADDR值定义一个唯一的功能。在复位和上电时,功能地址默认为零,必须由主机在枚举过程中编程。地址0被保留为默认地址,不能分配用于其他用途。
8.3.2.2 端点字段
附加的4位端点字段(ENDP),如图8-3所示,使得在需要多个端点的情况下更灵活地寻址。除端点地址零外,端点号是设备特定的。ENDP字段用于IN、SETUP和OUT令牌以及特殊的PING令牌。所有设备必须支持端点0(默认控制管道)。低速设备每个功能最多支持三个管道:一个控制管道(端点0)和另外两个(可以是两个控制管道、一个控制管道和一个中断端点,或两个中断端点)。全速和高速功能最多支持16个IN和OUT端点。
USB功能设备的寻址分为功能地址和端点号两部分。
-
功能地址字段(ADDR):
- 在USB协议中,主机负责分配地址给USB设备,每个USB设备在枚举过程中被赋予一个唯一地址。
- 地址范围为0-127,其中地址0是初始化阶段的默认地址,不用于数据通信。
- 功能地址用于区分主机所连接的多个设备,并指导数据传输的目标设备。
-
端点字段(ENDP):
- 一个设备内可以包含多个端点,每个端点通过一个4位字段编码,范围为0-15。
- 端点0为默认控制管道,必须支持,用于设备初始化及基本通信。
- 不同速度的设备支持的端点数不同:
- 低速设备:最多支持3个端点(包括默认控制管道)。
- 全速/高速设备:最多支持32个端点(16个IN和16个OUT)。
-
地址与端点的组合:
- USB协议通过ADDR和ENDP字段联合唯一标识一个通信目标。
- 每个数据传输令牌(如IN、OUT、SETUP)都需要包含这两个字段,主机和设备根据其值决定如何处理数据。
-
错误处理:
- 如果地址或端点字段解码失败,或试图访问未初始化的端点,USB设备将忽略对应的数据包。
- 这种设计确保了通信的稳定性与安全性,避免数据包误处理或冲突。
8.3.3 帧号字段(Frame Number Field)
帧号字段是一个11位字段,由主机每帧递增一次。当帧号字段达到其最大值(7FFH)时,会回绕(即归零)。此字段仅在每个(微)帧开始时的SOF(Start of Frame,帧起始)令牌中发送。
在USB 2.0规范中,**帧号字段(Frame Number Field)**用于标识每个帧的编号。其关键特点包括:
- 11位长度:允许帧号从0递增至2047(十六进制7FFH)。
- 回绕机制:当帧号达到最大值后,会自动归零并从0重新开始。
- SOF令牌中发送:帧号仅存在于SOF令牌中,用于标识帧的开始位置。
- 由主机控制:该字段由主机生成,并在每个帧周期递增一次。
-
帧的概念与作用
在USB 2.0中,时间被划分为以帧(Frame)和微帧(Microframe)为单位的时间片段:
- 全速设备(Full-speed):帧间隔为1毫秒(ms)。
- 高速设备(High-speed):微帧间隔为125微秒(µs)。
每个帧的起始由SOF(Start of Frame)令牌标记。SOF令牌不仅通知设备新帧的开始,还包含一个11位的帧号字段,用于唯一标识当前帧。
-
帧号的递增与回绕
- 帧号从0开始,每帧递增1。
- 当帧号达到其最大值7FFH(即十进制的2047)时,会回绕至0。
- 这种循环机制保证了帧号的持续更新,避免因编号用尽而停止。
-
SOF令牌中的帧号字段
SOF令牌专为帧时间同步设计,帧号字段是其关键组成部分。通过解码帧号字段,USB设备可以:- 确定当前帧的编号。
- 实现帧时间的同步和跟踪,特别是对时间敏感的操作,如等时传输(Isochronous Transfers)。
-
主机的作用
帧号字段完全由主机控制,设备仅用于读取和参考。主机每发送一个SOF令牌都会更新帧号字段,并以此确保总线的时间同步性。 -
微帧(Microframe)与帧号
在高速USB传输中,每个1毫秒帧被进一步细分为8个125微秒的微帧:- 每个微帧的帧号相同。
- 当进入下一个毫秒帧时,帧号递增1。
这种设计提供了精确的时间分辨率,支持高带宽应用。
8.3.4 数据字段(Data Field)
数据字段可以在0到1024字节之间,且必须为整数量的字节。图8-4展示了多字节的数据格式。每字节内的数据位按最低有效位(LSb)优先的顺序输出。
数据包的大小根据传输类型而变化,具体描述见第5章 USB 数据流模型。
-
数据字段的大小范围
USB协议规定数据字段可以容纳0到1024字节的数据,具体的大小限制取决于传输类型:
- 控制传输和批量传输通常支持更大的数据字段大小。
- 中断传输和同步传输的大小限制根据设备速度(低速、全速或高速)可能有所不同。
-
字节完整性的重要性
数据包必须是完整的字节数,原因在于USB协议的标准化要求。每个字节的完整性可以确保数据传输的稳定性,避免因不完整字节导致的错误。
-
数据位的输出顺序
数据位采用**最低有效位优先(LSb First)**的方式传输。
8.3.5 循环冗余校验(CRC)
参阅手册
8.4 数据包格式
此部分描述令牌、数据和握手数据包的数据包格式。数据包中的字段以比特移出到总线上的顺序显示在这些图中。
8.4.1 Token 包
图 8-5 显示了令牌(token)包的字段格式。一个 token 包含一个 PID,用来指定 IN、OUT 或 SETUP 包类型,并且有 ADDR 和 ENDP 字段。PING 这种特殊的 token 包也具有与普通 token 包相同的字段。对于 OUT 和 SETUP 事务,地址和端点字段唯一地标识将接收后续数据包的端点。对于 IN 事务,这些字段唯一地标识应该传输数据包的端点。对于 PING 事务,这些字段唯一地标识将响应握手包的端点。只有主机可以发出 token 包。一个 IN PID 定义了从设备到主机的数据传输。OUT 和 SETUP PID 定义了从主机到设备的数据传输。PING PID 定义了从设备到主机的握手事务。
Token 包有一个五位的 CRC,覆盖了如上所示的地址和端点字段。CRC 不覆盖 PID,因为 PID 有它自己的校验字段。Token 和 SOF 包在三个字节的包字段数据后由 EOP 进行定界。如果一个包被解码为一个有效的 token 或 SOF,但在三个字节之后没有 EOP 定界,它必须被视为无效,并被接收方忽略。
Token 包的结构与功能:
-
Token 包的组成:
- 包含 PID(包标识符),指定包的类型(IN、OUT 或 SETUP)。
- 包含地址(ADDR)和端点(ENDP)字段。
- PING 包也包含相同的字段。
-
用途与事务类型:
- OUT 和 SETUP 事务:地址和端点字段标识接收后续数据包的端点。
- IN 事务:地址和端点字段标识发送数据包的端点。
- PING 事务:地址和端点字段标识响应握手包的端点。
- 只有主机可以发出 token 包。
-
PID 类型与数据流方向:
- IN PID:从设备到主机的数据传输。
- OUT 和 SETUP PID:从主机到设备的数据传输。
- PING PID:从设备到主机的握手事务。
-
CRC 校验:
- Token 包具有一个五位的 CRC,覆盖地址和端点字段,但不覆盖 PID。
- PID 有自己的校验字段。
-
数据包终止:
- Token 和 SOF 包应在三个字节数据后以 EOP(数据包结束标志)终止。
- 如果包未以 EOP 结束,则被视为无效,接收方应忽略它。
-
Token 包的结构
在 USB 2.0 协议中,Token 包用于控制数据的流动,它携带关键信息,用于指定数据传输的方向、源和目标端点。Token 包含:
- PID(包标识符):指定包类型,标明数据流的方向或事务的类型。常见的 PID 类型有:
- IN:表示从设备到主机的数据传输。
- OUT:表示从主机到设备的数据传输。
- SETUP:用于设备配置的初始化事务,通常用于控制传输。
- PING:用于设备响应的握手协议。
- ADDR(地址):指定目标设备的地址。一个 USB 总线上,所有的设备都有唯一的地址。
- ENDP(端点):指定设备内的特定端点。每个设备有多个端点,用于不同类型的数据传输。
- PID(包标识符):指定包类型,标明数据流的方向或事务的类型。常见的 PID 类型有:
-
Token 包的用途
-
OUT 和 SETUP 事务:
地址和端点字段标识主机需要将数据发送到设备的目标端点。例如,在 OUT 事务中,主机通过 token 包告诉设备,从哪个端点接收数据。 -
IN 事务:
地址和端点字段标识设备需要将数据发送到主机的端点。在 IN 事务中,设备通过 token 包告诉主机,从哪个端点获取数据。 -
PING 事务:
PING 包用于设备向主机确认其准备状态。通过发送 PING 包,设备表明自己已经准备好响应后续的数据传输。
-
-
CRC 校验
Token 包具有五位的 CRC,用于校验地址和端点字段的正确性。CRC 校验用于检测传输过程中数据的损坏,确保包正确到达接收方。然而,PID 本身有独立的校验机制,因此 CRC 不会覆盖 PID 字段。
-
数据包终止与 EOP
USB 数据包需要以 EOP(数据包结束标志)进行终止。EOP 是 USB 协议中的一部分,表示包的结束。如果一个包在传输过程中没有正确终止,则会被认为是无效的。例如,Token 和 SOF 数据包必须在三个字节后以 EOP 终止。如果没有,接收方应该忽略这个数据包。
8.4.2 分割事务特殊令牌包
USB定义了一种用于分割事务的特殊令牌:SPLIT。这是一个4字节的令牌包,相比其他普通的3字节令牌包。分割事务令牌包提供了额外的事务类型和特定事务的附加信息。分割事务令牌用于支持主机控制器与高速度的集线器(hub)之间的通信,后者与一些全速或低速设备连接。定义了两种使用SPLIT特殊令牌的分割事务:开始分割事务(SSPLIT)和完成分割事务(CSPLIT)。SPLIT特殊令牌中的一个字段(在下面的章节中描述)指示具体的分割事务类型。
-
SPLIT特殊令牌包
SPLIT令牌包的设计目的是为了在USB系统中支持高速主机和集线器之间的通信,而这些集线器下游连接的是全速或低速设备。USB协议通常要求在主机和设备之间的通信速度要匹配,即主机和设备必须支持相同的传输速率。然而,当一个高速主机控制器与一个集线器(hub)通信时,集线器可能连接的是低速或全速设备,这就需要一种机制来分割这些事务,使得低速和全速设备能够与高速主机正常通信。
普通的USB令牌包是3字节的,包含了基本的事务信息,如目标设备地址、事务类型等。而SPLIT令牌包则需要4字节,这额外的一个字节用来提供更复杂的事务类型和信息。
-
SSPLIT和CSPLIT
为了实现分割事务,USB协议定义了两种特殊的分割事务类型:
- SSPLIT(Start-Split):开始分割事务。它是用来在主机和集线器之间启动分割事务的标志。
- CSPLIT(Complete-Split):完成分割事务。这种令牌用来告知系统一个分割事务的处理已经完成。
SSPLIT和CSPLIT在SPLIT令牌包中通过一个字段进行标识。具体而言,SPLIT令牌包的结构会根据这个标识来决定是开始事务还是完成事务。这两个事务类型的存在,使得数据传输能够在不同速度的设备之间顺利进行,避免因为速度不匹配而造成的通信失败。
-
主机与集线器的关系
分割事务特别适用于主机控制器与集线器之间的通信。在USB系统中,集线器是连接多个设备的桥梁,尤其是当这些设备的通信速度较低时,集线器会充当转接的角色,将高速数据转换成低速数据。这就需要分割事务的支持,确保数据在这些设备之间能够正确、有效地传输。通过使用SPLIT令牌包,主机控制器能够在高速模式下与集线器沟通,同时确保下游设备(全速或低速)能够以适合它们的速度进行通信。
8.4.2.1 分离事务
高速分离事务仅用于主控制器和集线器之间的通信,当集线器连接了全速或低速设备时会使用此事务。此高速分离事务用于通过集线器启动一个全速或低速事务,与某个全速或低速设备端点进行交互。此外,高速分离事务还允许从集线器中检索全速或低速事务的完成状态。这种方式使主控制器能够通过高速事务启动一个全速或低速事务,同时继续进行其他高速事务,而无需等待全速或低速事务以较慢的速度进行或完成。有关分离事务状态机和事务定义的更多细节,请参见第11章。
高速分离事务分为两部分:启动分离和完成分离。分离事务仅定义用于主控制器与集线器之间的通信,其他高速或全速/低速设备无法使用分离事务。
图8-6显示了一个通用启动分离事务的包组成。在令牌阶段有两个数据包:一个SPLIT特殊令牌和一个全速或低速令牌。根据数据传输的方向和事务类型是否定义握手,令牌阶段后可能跟随数据包和握手包。启动分离事务可以由2个、3个或4个数据包组成,具体取决于特定的传输类型和数据方向。
分离事务是USB 2.0协议中的一种特殊机制,用于主控制器和集线器之间的高速通信。主要应用场景是当集线器下挂有全速或低速设备时,主控制器通过集线器以高速传输发起这些设备的事务,同时不会因为设备的低速处理而阻塞高速链路。分离事务由两个阶段组成:启动阶段(Start Split)和完成阶段(Complete Split)。这些事务设计目的是提高通信效率,使主控制器可以在管理低速设备时继续执行其他高速任务。
-
为什么需要分离事务?
- USB 2.0引入了高速模式(480 Mbps),而许多设备仍然以全速(12 Mbps)或低速(1.5 Mbps)运行。为了让主控制器能够有效处理这类设备,同时不因低速设备的延迟而降低系统整体性能,引入了分离事务。
- 分离事务允许主控制器通过高速链路快速指令集线器去处理全速/低速设备,然后无需等待处理结果就可以继续进行其他高速事务。
-
分离事务的工作原理
-
启动分离事务(Start Split):
- 主控制器发送一个特殊的SPLIT令牌,指定目标设备地址、端点号以及期望的操作(例如传输数据或接收数据)。
- SPLIT令牌后跟一个全速/低速令牌,例如OUT、IN或SETUP。
- 根据需要,可能会附加数据包或握手包。
-
完成分离事务(Complete Split):
- 主控制器在之后的时间段中发送Complete Split令牌,以查询全速/低速事务的完成状态。
- 集线器根据低速设备的响应(ACK、NAK或STALL等)返回状态。
-
-
数据包组成
- 分离事务的数据包包括:
- 令牌阶段:一个SPLIT令牌和一个全速/低速令牌。
- 数据阶段(可选):如果需要传输数据,会附加一个数据包。
- 握手阶段(可选):确认事务是否成功完成。
- 分离事务的数据包包括:
-
应用场景
- 分离事务仅适用于主控制器与集线器之间的通信。
- 它主要用于当集线器下挂全速或低速设备时,提高事务处理效率。
图8-7展示了组成一个通用完整分割事务的报文。令牌阶段包含两个报文:SPLIT特殊令牌和一个全速/低速令牌。根据数据传输方向和特定事务类型,数据报文或握手报文跟随在令牌阶段的报文之后。完整分割事务可能由2个或3个报文组成,具体取决于特定的传输类型和数据方向。
完整分割事务用于返回分割事务的结果。图8-8展示了这种概念性的“转换”,以一个中断IN(Interrupt IN)传输类型为例。主机向集线器发送开始分割(标记为1),然后可以继续进行其他高速事务。开始分割命令导致集线器稍后发出一个全速/低速IN令牌(标记为2)。在本例中,设备通过一个数据报文响应IN令牌,并且集线器向设备发送一个握手。最后,主机稍后发出一个完整分割(标记为3)以检索设备提供的数据。注意,在本例中,集线器在完整分割之前向设备端点提供了全速/低速握手(此处为ACK),而完整分割没有向集线器提供高速握手。
-
完整分割事务:
完整分割事务是USB 2.0协议中分割事务的一部分,包含两种报文:一个特殊的SPLIT令牌和一个全速/低速令牌。数据报文或握手报文会根据传输类型和方向跟随这些令牌。 -
事务工作原理:
- 主机发送开始分割(Start-Split)指令到集线器。
- 集线器稍后通过全速/低速信号与设备交互,执行数据传输。
- 主机随后通过完整分割(Complete-Split)检索传输数据。
- 集线器在完整分割之前完成了与设备的握手响应,而完整分割阶段无需主机再进行高速握手。
-
分割事务的目的:
分割事务主要用于在高速USB总线和全速/低速设备之间进行数据交互。这是因为高速设备和全速/低速设备的通信速率不同,不能直接交互。分割事务通过将通信分成两个阶段——“开始分割”和“完整分割”——解决了这一问题。 -
SPLIT令牌的作用:
SPLIT令牌是分割事务的关键,它用来指示接下来的通信是在全速或低速下完成的。这个特殊的令牌允许高速总线暂时停用与目标设备的高速通信。 -
事务的分段执行:
- 开始分割(Start-Split):主机将分割任务传递给集线器,并可以继续处理其他事务。
- 集线器-设备通信:集线器在全速或低速条件下与设备通信,接收数据或状态响应。
- 完整分割(Complete-Split):主机通过完整分割报文向集线器获取设备的返回结果(数据或握手状态)。
-
优点:
- 带宽优化:主机在分割事务期间可以执行其他高速事务,而不需要等待设备的响应,从而最大化带宽利用率。
- 兼容性:支持全速/低速设备与高速主机系统的通信。
一个正常的全速/低速的 OUT 事务会被概念上“转换”为起始分割 (start-split) 和完成分割 (complete-split) 事务。图 8-9 显示了这种“转换”过程,示例为中断 OUT 传输类型。主机发起一个起始分割事务,该事务由一个 SSPLIT 特殊标记、一个 OUT 标记和一个数据包组成。稍后,集线器在全速/低速总线上发出 OUT 标记和数据包。设备通过握手响应。稍后,主机发起完成分割事务,集线器根据设备提供的结果(可能是全速/低速的数据或握手)进行响应。
-
事务概念:
- 全速/低速 OUT 事务被拆分为两部分:
- 起始分割事务 (start-split)。
- 完成分割事务 (complete-split)。
- 起始分割事务包含 SSPLIT 标记、OUT 标记和数据包。
- 完成分割事务用于返回设备的响应。
- 全速/低速 OUT 事务被拆分为两部分:
-
工作流程:
- 主机发送起始分割事务。
- 集线器稍后通过全速/低速总线传输 OUT 标记和数据包。
- 设备处理并发送握手。
- 主机发送完成分割事务,集线器返回结果(如数据或握手信号)。
-
起始分割事务 (Start-Split Transaction)
- 组成:
- SSPLIT 特殊标记:用于指示分割事务的开始。
- OUT 标记:指定向设备发送数据。
- 数据包 (DATAx):实际传输的数据。
- 功能:
- 起始分割事务负责在高带宽的高速总线 (High-Speed Bus) 上,通知集线器准备向设备传输数据。
- 组成:
-
完成分割事务 (Complete-Split Transaction)**
- 组成:
- CSPLIT 标记:用于指示事务的完成部分。
- 数据包或握手:可能包含设备的响应数据,也可能是握手信号(如 ACK、NAK)。
- 功能:
- 处理设备的响应。
- 将设备的结果返回给主机。
- 组成:
-
数据流转示意 (结合图 8-9)**
- 阶段一:主机发送起始分割事务,包括 SSPLIT 标记、OUT 标记和数据包。
- 阶段二:集线器稍后在全速/低速总线上传输 OUT 标记和数据包,设备对此进行响应。
- 阶段三:主机发送完成分割事务,从集线器接收设备的响应(数据或握手)。
-
重要特点
- 这种分割机制的优势在于:
- 提高了高速总线的利用率。
- 允许主机在等待低速设备响应的同时,执行其他高速事务。
- 这种分割机制的优势在于:
8.4.3 帧开始包
帧开始包(SOF包)由主机以固定速率发出,全速总线的发出速率为每1.00毫秒±0.0005毫秒,高速总线的发出速率为每125微秒±0.0625微秒。SOF包由一个PID(包标识符)和一个11位帧编号字段组成,如图8-13所示。
SOF标记包含一个仅限令牌的事务,它在精确的时间间隔发出SOF标记和附带的帧编号,表示每一帧的开始。所有的高速和全速设备,包括集线器,都接收SOF包。SOF令牌不会导致任何接收设备生成回传包;因此,SOF包的传递到任何特定设备并不能得到保证。
SOF包传递了两个时间信息。设备在检测到SOF PID时,就知道SOF已发生。那些对帧计时敏感的设备(如全速操作的集线器),如果不需要追踪帧编号,只需解码SOF PID即可;它们可以忽略帧编号及其CRC。如果设备需要追踪帧编号,那么它必须理解PID和时间戳。对于没有特别需要总线计时信息的全速设备,它们可以忽略SOF包。
-
SOF包发出的频率:
- 全速总线:每1毫秒±0.0005毫秒。
- 高速总线:每125微秒±0.0625微秒。
-
SOF包的内容:
- 包含一个PID(包标识符),指示包的类型。
- 后跟11位的帧编号字段(用于标识每一帧的编号)。
-
SOF包的作用:
- SOF包用于标记每一帧的开始。
- 高速和全速设备,包括集线器,都会接收到SOF包。
- SOF包本身不会导致设备产生回传包。
-
SOF包的信息传递:
- SOF包传递两个时间信息:帧开始的时间(SOF PID)和帧编号(11位数字)。
- 对于那些不需要追踪帧编号的设备(如集线器),它们只需解析SOF PID即可。
- 需要追踪帧编号的设备(如一些高性能设备),则必须解析SOF PID和帧编号。
- 如果全速设备不需要时间信息,它们可以忽略SOF包。
在USB 2.0协议中,Start-of-Frame(SOF)包是非常重要的,它们用于同步总线上的各个设备。SOF包的作用是在总线上标记每一帧的开始,并为各个设备提供一个统一的时间参考。每一帧的时间长度为1毫秒(对于全速总线),或者125微秒(对于高速总线),这一时间标准被所有设备遵循。通过这些SOF包,设备能够确定何时开始一个新的数据帧,并且保持总线操作的同步。
SOF包的结构非常简单,它包含一个PID(包标识符)和一个11位帧编号字段。PID用于指示包的类型,而11位帧编号字段则用于标识当前的帧编号。每次SOF包被发送时,主机会发出一个新的帧编号,用以标识帧的顺序。帧编号对于一些设备来说是非常重要的,尤其是那些需要精确跟踪数据传输和时间的设备。
设备在接收到SOF包后会解析PID。如果设备对帧编号不感兴趣(比如一些集线器或者简单的全速设备),它只需要关注PID,不需要处理帧编号及其附带的CRC(循环冗余校验)。但是对于一些复杂的设备(如高性能的传感器或音频设备)来说,它们可能需要追踪帧编号以保证数据同步和处理的正确性。
SOF包的发出间隔非常精确,这是USB总线协议中一个非常重要的特性。全速设备和高速设备之间的同步保持,使得在同一个USB总线上的多个设备能够以协调一致的方式进行通信。尽管SOF包本身不直接参与数据传输(即它不会引发数据回传),但它为整个系统提供了一个共享的时间基准。
总结来说,SOF包在USB通信中起到了“时钟同步”的作用,确保所有设备在一个精确的时间基准上工作,有助于数据的精确传输和处理。
8.4.3.1 USB 帧与微帧
USB 定义了一个全速 (Full-Speed) 1 毫秒的帧时间,通过每 1 毫秒周期的帧起始 (SOF) 数据包表示,同时定义了相关的抖动容差范围。此外,USB 还定义了高速 (High-Speed) 的 125 微秒微帧时间及其相关的抖动容差(详见第 7 章)。
对于全速链接,每隔 1 毫秒由主机控制器或集线器的事务转换器生成 SOF 数据包。而对于高速链接,在 125 微秒的周期内,每隔 1 毫秒也会生成一次 SOF 数据包。
图 8-14 展示了微帧与帧的关系。
在高速设备中,设备在每 1 毫秒内会看到 8 次(每隔 125 微秒)带有相同帧编号的 SOF 数据包。如果需要,高速设备可以通过检测与之前不同帧编号的 SOF 来局部确定特定微帧编号,并将其视为第 0 个微帧。接下来的 7 个带有相同帧编号的 SOF 数据包可以依次作为微帧 1 至微帧 7。
USB 的帧和微帧机制如下:
- 全速 (Full-Speed) 模式
- 每 1 毫秒产生一次帧,使用 SOF 数据包标识。
- 有一定的抖动容差。
- 高速 (High-Speed) 模式
- 每隔 125 微秒产生一个微帧,总共 8 个微帧组成一个 1 毫秒帧。
- 每 1 毫秒内,SOF 数据包的帧编号保持一致。
- 通过检测帧编号变化,设备可确定“第 0 微帧”,其后 7 个微帧编号依次递增。
-
帧 (Frame) 和微帧 (Microframe) 的定义
帧是 USB 协议中的基本时间单元,用于同步和调度数据传输。在全速模式下,帧时间为 1 毫秒。而在高速模式中,每个帧被分为 8 个微帧,每个微帧持续 125 微秒。这样做的目的是提高数据传输的精度和实时性,特别是对于高速设备。 -
SOF 数据包的作用
SOF (Start Of Frame) 是一种特殊的数据包,用于:- 指示帧或微帧的开始。
- 提供时间参考以支持设备的同步操作。
全速和高速模式下 SOF 数据包的发送频率不同,但它们的基本功能相同。
-
高速设备如何解析微帧编号
高速设备通过检测帧编号的变化来确定微帧的起始位置。设备可以:- 将帧编号变化后的 SOF 数据包标识为第 0 微帧。
- 随后的 SOF 数据包根据出现的顺序编号为微帧 1 到 7。
-
抖动容差的意义
抖动容差是 USB 时间控制的关键参数,确保即使存在轻微的时间偏差,设备仍能正确识别帧和微帧的边界。这对于高速数据传输尤为重要。 -
微帧的实际应用
微帧在实时性要求高的场景(如音视频数据传输)中起到至关重要的作用,允许设备在更短的时间内分配带宽,从而提高传输效率。
8.4.4 数据包
数据包由一个PID(包标识符)、一个包含零个或多个字节数据的数据字段和一个CRC(循环冗余校验)组成,如图8-15所示。数据包有四种类型,通过不同的PID进行区分:DATA0、DATA1、DATA2和MDATA。为了支持数据切换同步(参见第8.6节),定义了两种数据包PID(DATA0和DATA1)。所有四种数据PID都用于高带宽高速等时性端点的数据PID序列(参见第5.9节)。三种数据PID(MDATA、DATA0、DATA1)用于分割事务(参见第11.17至11.21节)。
数据总是以整字节的方式发送。数据的CRC是计算在数据字段上的,仅包括数据部分,而不包括PID,PID有自己的校验字段。
低速设备的最大数据负载大小为8字节;全速设备的最大数据负载大小为1023字节;高速设备的最大数据负载大小为1024字节。
-
数据包结构:一个USB数据包包括PID、数据字段和CRC。PID用于标识数据包类型,数据字段包含要传输的数据,CRC用于校验数据的正确性。
-
数据包类型:有四种数据包类型:
- DATA0、DATA1:这两种用于支持数据切换同步。
- DATA2:用于高带宽数据传输。
- MDATA:用于高带宽和分割事务。
-
数据传输单位:USB传输的数据必须是整字节,且CRC仅用于数据字段部分,PID有独立的校验机制。
-
设备的最大数据负载:
- 低速设备:最大数据负载为8字节。
- 全速设备:最大数据负载为1023字节。
- 高速设备:最大数据负载为1024字节。
-
数据包的组成
USB数据包由三个主要部分组成:PID、数据字段和CRC。- PID(Packet Identifier,包标识符):用于标识数据包的类型。不同的PID表示不同的功能或操作(如数据传输、握手、错误处理等)。
- 数据字段:包含实际的传输数据。数据字段的大小可以变化,取决于USB的传输模式和设备的速度。数据字段可以为空,表示没有要传输的数据。
- CRC(循环冗余校验):用于检查数据字段中的内容是否正确。CRC是根据数据字段计算的,并且不包括PID部分。PID本身有独立的校验机制,确保传输中的数据包标识没有错误。
-
数据包类型
USB协议定义了四种数据包类型,用于支持不同的传输场景:- DATA0和DATA1:这两种数据包用于数据切换同步(data toggle synchronization)。在某些情况下,设备需要使用这两种数据包交替传输数据,以保证数据包的有效性和可靠性。每次传输数据时,主机和设备会根据上一包的状态(DATA0或DATA1)来决定使用哪种数据包。
- DATA2:这种数据包用于高带宽的高速等时性端点(high-speed isochronous endpoints)。在USB中,高速传输数据需要保证较低的延迟和高带宽,因此使用DATA2进行数据传输。
- MDATA:这种数据包通常用于分割事务(split transactions)。分割事务用于高带宽数据传输,特别是在数据无法一次性传输时,采用MDATA来继续分割并传输数据。
-
数据传输的要求
- USB的数据必须以整字节的形式传输,不能发送部分字节。这是为了确保数据的一致性和有效性。
- CRC的计算:在每个数据包中,只有数据字段部分会参与CRC校验,不包括PID。这是因为PID本身有单独的校验字段。
-
最大数据负载大小
根据设备的不同速率,USB协议规定了不同的最大数据负载:- 低速设备(Low-speed):这种设备的最大数据负载为8字节。这类设备通常用于低带宽应用,如键盘和鼠标。
- 全速设备(Full-speed):全速设备的最大数据负载为1023字节。全速设备常见于许多传统的USB设备,如打印机和音响。
- 高速设备(High-speed):高速设备的最大数据负载为1024字节。这类设备支持更快的数据传输速度,常用于高清视频、外部硬盘等要求高带宽的应用。
8.4.5 握手包
握手包仅包含一个PID(Packet Identifier,数据包标识符),用于报告数据传输的状态。握手包可以返回几种不同的状态,表示数据是否成功接收、命令是否被接受或拒绝、流量控制的情况,以及是否存在停止条件。只有支持流量控制的事务才会返回握手包。握手包总是在事务的握手阶段返回,并且可能在数据阶段代替数据包进行返回。握手包以一个字节的包字段,并通过EOP(End of Packet,数据包结束符)来标识包的结束。如果一个数据包解码为有效的握手包,但没有以EOP标志结束,则必须认为这个包无效,并且接收方应忽略它。
握手包类型
有四种类型的握手包,以及一个特殊的握手包:
-
ACK (确认)
- 定义:ACK表示数据包成功接收且没有比特填充或CRC错误,且数据PID接收正确。ACK可以在以下两种情况下发出:
- 序列位匹配且接收方可以接受数据。
- 序列位不匹配,表示发送方和接收方必须重新同步。
- 应用:ACK仅在有数据传输并且期望握手的事务中返回。对于IN事务,ACK由主机返回;对于OUT、SETUP或PING事务,ACK由设备返回。
- 定义:ACK表示数据包成功接收且没有比特填充或CRC错误,且数据PID接收正确。ACK可以在以下两种情况下发出:
-
NAK (否定确认)
- 定义:NAK表示设备无法从主机接收数据(OUT),或者设备没有数据要发送给主机(IN)。NAK只能在IN事务的数据阶段由设备返回,或者在OUT或PING事务的握手阶段返回。主机不能返回NAK。
- 应用:NAK用于流量控制,表示设备暂时无法发送或接收数据,但未来会恢复,无需主机干预。
-
STALL (停止)
- 定义:STALL表示设备无法传输或接收数据,或者设备无法处理控制管道请求。设备在收到IN令牌、OUT数据阶段,或者PING事务时可以返回STALL。对于除默认端点以外的任何端点,返回STALL后的状态是未定义的。主机不能返回STALL。
- 两种情况:
- 功能性停顿(Functional Stall):当端点的停止功能被设置时,设备会返回STALL,直到主机干预并清除停止状态。
- 协议性停顿(Protocol Stall):这是控制管道中的特殊情况,表示控制传输的状态阶段出错。协议停顿在下一个控制传输的Setup阶段开始时终止。
-
NYET (未完成确认) - 仅限高速
- 定义:NYET用于高速端点,在以下两种情况下返回:
- 在PING协议中返回,表示该端点暂时不能返回数据。
- 高速集线器在响应拆分事务时,如果全速或低速事务尚未完成或集线器无法处理拆分事务时返回NYET。
- 定义:NYET用于高速端点,在以下两种情况下返回:
-
ERR (错误) - 仅限高速
- 定义:ERR是高速专用的握手包,用于高速集线器在全速或低速总线上报告错误。它仅由高速集线器在拆分事务协议中作为响应返回。
8.4.6 握手响应
参阅手册
8.5 事务包序列
组成事务的包根据端点类型的不同而有所变化。USB有四种端点类型:批量(bulk)、控制(control)、中断(interrupt)和等时(isochronous)。
主机控制器和设备每一方都需要不同的状态机来正确地对每种类型的事务进行包的顺序控制。接下来的章节中的图表展示了状态机,定义了事务中每种类型的包的正确顺序。
这些图表不应当被视为一种强制实现,而是规定了所需的行为。
图8-17展示了状态机图表的图例。带有三条线边框的圆表示引用另一个(层次化的)状态机。带有两条线边框的圆表示初始状态。带有单条线边框的圆表示简单状态。
事务包的序列在不同类型的端点之间存在差异。USB有四种端点类型:批量、控制、中断和等时,每种类型都涉及不同的包序列和状态机逻辑。
8.5.1通过Ping流量控制进行NAK限制
参阅手册