8.6 数据切换同步和重试
USB 提供了一种机制,确保在多次传输中的数据发送方和接收方之间的数据序列同步。该机制可以确保数据传输的握手阶段被发送方和接收方正确地解释。同步是通过使用 DATA0 和 DATA1 的包标识符 (PID) 以及数据发送方和接收方的独立数据切换序列位来实现的。接收方的序列位仅在接收方能够接收数据并且接收了无错误的、带有正确数据 PID 的数据包时切换。发送方的序列位仅在数据发送方接收到有效的 ACK 握手时切换。数据发送方和接收方必须在事务开始时同步它们的序列位。同步机制根据事务类型有所不同。对于等时传输(isochronous transfers),不支持数据切换同步。
本章以及第11章中的状态机以更简洁的形式描述了数据切换同步机制。它没有明确标识 DATA0 和 DATA1,而是使用一个值“DATAx”来代表 DATA0 或 DATA1 的 PID。在某些情况下,如果需要特别指定数据 PID,会使用一个变量“x”,其中“0”代表 DATA0,而“1”代表 DATA1。
高速、高带宽的等时传输和中断端点采用了一种与数据切换同步不同的同步技术,称为 数据 PID 序列化。该技术代替了数据切换同步。第5.9.1节定义了数据 PID 序列化。
USB 的数据切换同步机制用于确保数据传输的顺序正确且一致。它通过在数据包中使用 DATA0 和 DATA1 两种 PID 以及切换序列位来实现同步。数据发送方和接收方的切换序列位分别依据接收到的正确数据包和有效的 ACK 握手来切换。该同步机制要求发送方和接收方在事务开始时要进行同步。对于等时传输(isochronous transfers),不使用此同步机制,而是采用 数据 PID 序列化 技术。两者之间的区别在于同步的方式不同,数据 PID 序列化用于高带宽、高速传输的场景,尤其是在等时和中断传输中。
USB 的数据切换同步机制在数据传输的过程中,确保了发送方和接收方之间对数据顺序的认同,防止了数据包丢失或者错乱。每一次数据传输都会通过一个三阶段的握手过程:发送数据包、接收确认以及根据接收结果进行必要的重试。为了确保这些操作的顺利进行,发送方和接收方必须在开始时保持数据序列的同步。
-
DATA0 和 DATA1 PID:USB 中的数据包通过 PID 来区分数据包的类型,而 DATA0 和 DATA1 作为数据包标识符,用于标记数据的顺序。每一方(发送方和接收方)都有一个独立的序列位来标记下一个期望的数据包顺序。
-
切换序列位:接收方的序列位仅在接收到无误的数据包且数据 PID 正确时切换,表示接收方已准备好接收下一个数据包。发送方的序列位则在收到有效的 ACK 握手信号时切换,表示确认已收到并正确理解数据。
-
同步机制:发送方和接收方必须在数据传输开始时同步它们的序列位,这样才能确保后续的所有数据包都能够按预期的顺序发送和接收。如果数据切换同步失败,可能会导致数据包丢失或错误地重试,影响数据传输的可靠性。
-
不支持等时传输:等时传输(isochronous transfer)通常用于视频或音频流等实时数据的传输,这些传输要求数据的时间间隔非常精确。因此,等时传输使用不同的同步机制,称为 数据 PID 序列化,而非数据切换同步。
8.6.1 通过SETUP令牌初始化
控制传输使用SETUP令牌来初始化主机和设备的序列位。图8-44展示了主机向设备发出SETUP数据包,之后紧接着进行OUT事务。圆圈中的数字表示发送方和接收方的序列位。设备必须接受数据并返回ACK。设备接受事务时,必须设置其序列位,以确保SETUP事务结束时,主机和设备的序列位都等于1。
-
数据传输过程
- 主机向设备发送一个SETUP包(数据包包含了控制传输的初始化信息)。
- 紧接着,主机发起一个OUT事务,向设备发送数据。
- 设备在接收到数据后,必须返回ACK信号,表示已成功接受数据。
-
序列位的作用与同步
- 序列位用于确保通信的顺序和可靠性。在SETUP过程中的每一步,主机和设备都有一个序列位。
- 在SETUP事务结束时,主机和设备的序列位必须都设置为1,表示它们都已正确处理当前的SETUP事务。
根据您的学习需求,以下是对USB 2.0协议第八章“协议层”中第8.6.2节“成功的数据事务”的翻译和汇总:
8.6.2 成功的数据事务
图8-45展示了两次成功的事务情形。对于数据发送方,这意味着在收到ACK握手包后会切换其序列位。接收方只有在收到一个有效的数据包并且该数据包的PID(数据包标识符)序列位与接收方的当前序列位匹配时,才会切换其序列位。发送方仅在其发送的数据包收到ACK时切换序列位。
在每次事务中,接收方将发送方的序列位(编码在数据包的PID中,例如DATA0或DATA1)与其自身的接收序列位进行比较。如果接收方无法接收数据,则必须发送NAK,且发送方和接收方的序列位均保持不变。如果接收方能够接收数据,并且接收方的序列位与PID序列位匹配,则接收方会接受数据并切换其序列位。在没有数据包的两阶段事务中,发送方和接收方的序列位保持不变。
-
序列位(Sequence Bit)和事务的关系:
- USB协议中,序列位用于确保数据包按序传输和接收。发送方和接收方通过切换各自的序列位来确认数据包的接收情况。
- 数据包的序列位信息嵌入到数据包的PID(Packet Identifier)字段中,分别为
DATA0
或DATA1
。
-
成功事务的条件:
- 数据接收方必须收到一个有效数据包。
- 数据包的PID序列位必须与接收方当前的序列位匹配。
- 只有在数据被成功接收且ACK(Acknowledgment)握手包被发送后,接收方才会切换其序列位。
-
错误处理机制:
- 如果接收方无法接收数据(例如,缓存已满),则发送一个NAK(Negative Acknowledgment),并且序列位保持不变。
- 在这种情况下,发送方不会切换其序列位,而是会重试数据传输。
-
两阶段事务:
- 某些情况下,USB事务可能只有令牌包(Token Packet)和握手包(Handshake Packet)两个阶段,没有数据包。在这些事务中,序列位不发生任何改变。
-
事务序列化的意义:
- 序列位的同步机制防止了由于重复或丢失数据包而引起的通信错误。
- 同时,这种机制也在传输过程中实现了事务的一致性和可靠性。
8.6.3 数据损坏或不接受
如果接收方无法接受数据包或者接收到的数据包损坏,接收方将根据具体情况发送一个NAK或STALL握手信号,或者直接超时,且接收方不会切换其序列位(Sequence Bit)。如图8-46所示,这是一次交易被NAK响应并重试的情况。任何非ACK握手信号或超时都会触发类似的重试行为。传输方在没有收到ACK握手信号的情况下,不会切换其序列位。因此,失败的数据包传输会使得传输方和接收方的序列位保持同步且未切换。随后,交易将被重试,如果成功,传输方和接收方的序列位将会切换。
- 数据包无法被接收。
- 接收到的数据包损坏。
-
接收方的响应:
- 根据具体情况,接收方会:
- 发送NAK握手信号(表明暂时无法接收数据)。
- 发送STALL握手信号(表明更严重的错误)。
- 或直接超时(无响应)。
- 根据具体情况,接收方会:
-
序列位的处理:
- 在上述情况下,接收方不会切换序列位。
- 传输方在未收到ACK的情况下,也不会切换序列位。
- 这确保了传输方和接收方的序列位在交易失败后仍保持同步。
-
重试机制:
- 交易失败后会被重试。
- 如果重试成功,传输方和接收方的序列位都会切换。
USB协议中,为了确保可靠性和数据完整性,采用了一种称为“握手包”的机制,用于在传输方和接收方之间确认数据的状态。当数据包传输失败时的处理流程:
-
失败的原因:
- 数据包在传输过程中可能被干扰损坏。
- 接收方因缓存不足或其他原因,无法接受数据。
-
握手信号的类型:
- ACK(Acknowledgment):表明接收成功。
- NAK(Negative Acknowledgment):表明暂时无法接收。
- STALL:表明设备状态异常或不支持该操作。
- 超时:接收方未在规定时间内响应。
-
序列位的作用:
- 序列位用于确保传输的顺序和同步。
- 在失败情况下,序列位不切换,避免了传输方和接收方的状态不同步。
- 成功传输后,双方序列位切换,表示完成一次完整的交易。
-
重试的意义:
- 传输方会在失败后根据协议规则自动重新发送数据包。
- 这提高了传输的可靠性,减少了因临时错误导致的数据丢失。
8.6.4 损坏的ACK握手
发送方是唯一能确认传输是否成功的设备,因为它会接收到ACK握手信号。如果ACK握手丢失或被损坏,可能导致发送方和接收方之间的同步暂时丧失,如图8-47所示。这里,发送方发送了一个有效的数据包,接收方成功接收了该数据包;然而,ACK握手信号却被损坏。
在事务i结束时,发送方和接收方之间暂时失去了一致性,表现为它们各自的序列位不匹配。接收方已经成功接收了数据,但发送方无法确认数据是否成功发送。在下一个事务中,发送方将重新发送之前的数据包,并使用先前的DATA0 PID。由于接收方的序列位与数据包的PID不匹配,它知道之前已经接受过这份数据。因此,接收方丢弃了传入的数据包,并且不再切换其序列位。接收方随后会发出ACK信号,这使得发送方认为重传的事务已经成功。收到ACK信号后,发送方会切换其序列位。在事务i+1开始时,序列位已经切换,发送方和接收方的同步得以恢复。
数据发送方必须确保任何重传的数据包与原始事务中发送的数据包完全相同(包括长度和内容)。如果由于缓冲区不足等问题,数据发送方无法传输与原始数据包相同的数据量,它必须通过在全速或低速模式下生成比特填充违规来中止该事务。高速模式下,则必须通过对当前计算出的CRC进行取反来强制产生错误,这将在接收方产生可检测的错误,保证部分数据包不会被接收方当作有效数据包。如果发送方试图通过发送一个已知的错误CRC来强制接收方出错,这种做法是不推荐的,因为结合一个坏数据包和“坏”CRC可能会被接收方误认为是有效数据包。
如果在USB传输过程中,ACK握手信号丢失或损坏,会影响发送方和接收方的同步。
ACK握手是传输成功的关键标志,损坏的ACK可能导致发送方和接收方之间短暂的同步失效,进而影响后续的数据传输。
-
同步失效
发送方通过接收ACK信号来确认数据是否成功传输。如果ACK信号丢失或损坏,发送方无法知道数据是否成功传输,导致它与接收方之间的同步丧失。例如,发送方发送了一个有效的数据包,接收方也成功接收了该数据包,但由于ACK信号损坏,发送方无法确认是否成功传输。 -
重传机制
在事务的下一轮,发送方将重发上次的数据包,使用相同的DATA0 PID(数据包标识符)。此时,接收方会注意到它之前已经接收过这个数据包,因为序列位和PID不匹配。接收方会丢弃这个数据包,并不会更改序列位。随后,接收方会发出ACK信号,表示它已经接收过数据,发送方此时会认为重传成功,并切换自己的序列位。 -
数据一致性要求
发送方在重传数据包时必须确保重传的数据与原始数据完全一致。如果发送方因缓冲区不足等原因无法重传相同的数据,它需要采取措施处理这种错误情况:- 对于全速或低速模式,发送方会通过生成比特填充错误(bit stuffing violation)来中止该事务。
- 对于高速模式,发送方必须通过取反当前CRC值来强制产生错误,确保接收方能检测到错误,避免接收方误解部分数据包为有效数据包。
-
错误处理原则
尽管可以通过错误机制强制中止传输,但发送方不应故意发送已知的错误CRC来“欺骗”接收方。这种行为可能导致接收方将一个损坏的数据包误认为是有效的。正确的做法是通过合理的错误生成机制确保数据包的有效性。
8.7错误检测和恢复
请参阅手册