USB 的DataToggle

本文详细解读了USB通信过程中的DataToggle概念及其在处理通信错误时的作用,包括令牌包IN、数据包和ACK握手包的交互流程,以及DataToggle如何通过数据包的交替传输确保通信同步和错误检测。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

USB 的DataToggle

USB在通信过程中,有DataToggle这么一个概念。

例如,在一次通信中,主机如果需要接收一个数据包,那么,主机会先发送一个IN的令牌包,然后从机发送数据包,然后主机再发送ACK握手包进行确认,这就完成了一次数据的接收。

假如出现通信错误,掉包的情况,那么又如何处理呢?

第一步,假如是令牌包IN发生了通信错误,那么主机则不会发送数据包。主机可以再次发送令牌包IN来让从机发送数据包。

第二步,假如是数据包发生了错误,那么主机收不到数据,则不会发出ACK信号,而再次发送IN;而从机由于没有收到ACK,则得知数据包出错,可以再次发送该数据包。

现在问题来了,假如是ACK信号出错,主机已经成功接收到数据,认为通信完成。由于从机并没有接收到ACK信号,还认为数据出错,继续准备上一包数据,此时岂不是要不同步了?

这个时候,DataToggle就派上用场了。DataToggle要求数据包前加DATA0和DATA1标识,并且要求每成功完成一次通信后,对DATA标识进行切换,这样,主机在下一次的IN包中,就可能通过DATA的标识来判断从机是否成功地完成上一次数据通信了。

DataToggle在USB Reset阶段是要清为0的,而今天就发现了一个错误,不幸在GetMaxLun和ClassReset这两条命令中对DataToggle进行了清零操作,造成了USB的通信过程中,发送这两条命令则有可能通信失败。

特记录一下:在A1 FE和21 FF这两条类命令中,是不需要对Bulk的DataToggle进行清零操作的。


因为USB构架对错误的校正是非常严谨的。就如前面所提的,ACK握手是给主机一个信号:外围器件正确的接收到了主机所发送的数据。但是握手数据包自身会不会在传输中被混淆呢?为了能够检测这个错误,主机和外围设备两边都各自维护一个与数据包传输相关的校验位,当数据到达目的地时,内部校验位就会与DATA0或者DATA1来进行比较。当主机或者外围设备发送数据时,它们交互的发送DATA0和DATA1。主机和外围设备就可以通过对数据PID与内部校验位状态的比较来确定错误的握手数据包。
<wbr><wbr><wbr>综上得出一个结论:ACK信号只是在收到DATA0或DATA1数据包后的一个回应,如果DATA0或者DATA1无法</wbr></wbr></wbr>到达目标自然目标就认为不存在这次数据传输,这样容易产生书籍。因此通过DATA0和DATA1的交替传输,如果检测到两个DATA0或者两个DATA1那么就表明数据包传输错误或者被遗漏。
### USB 协议中的 PID (包标识符) 在USB协议中,PID(Packet IDentifier)是每个数据包的第一个字段,长度为8位。PID不仅定义了数据传输的方向,还指示了当前包的类型以及功能[^1]。 #### PID 的基本特性 - **方向性**:某些类型的PID专门用于从USB主机向设备发送命令或数据;而另一些则相反,允许设备响应主机请求。 - **功能性**:除了标明传输方向外,PID也决定了该次通信的具体行为模式——例如初始化一次新的事务处理、实际传送有效载荷或是确认先前接收的内容无误等。 #### PID 数据结构 每一个PID实际上是由两部分组成: | 字节位置 | 描述 | |----------|--------------------| | 7:4 | 类型编码 | | 3:0 | 补码验证 | 其中,“类型编码”的四位用来区分不同种类的数据包,如令牌(Tokenizer)、数据(Data Toggle) 和握手.Handshake)三种主要类别下的具体子类;而后四位则是前者的按位取反值,作为简单的错误检测机制的一部分,确保这八比特被正确解读[^3]。 #### 常见 PID 及其含义 以下是几种常见的PID及其作用说明: - **TOKEN PIDs**: 包含`OUT`, `IN`, `SETUP`. 这些主要用于启动特定端点上的操作序列. - OUT (`0100_1011`) : 主机准备写入数据给选定的终端节点; - IN (`1100_0011`) : 请求读取来自某个终端节点的信息; - SETUP(`1101_0010`) : 特定于控制传输阶段一期间使用的特殊指令传递. - **DATA PIDS**: 存在两种形式,即`DATA0`(0011_1100), `DATA1`(1011_0100). 它们交替使用以支持连续批量传输过程中的差错恢复策略. - **HANDSHAKE PIDS**: 如ACK(`0010_1101`), NAK(`1110_0001`), STALL(`1010_0101`). ACK表示成功接收到预期的消息;NAK意味着暂时无法完成相应动作;STALL表明遇到了不可逾越的问题. ```python # Python 示例代码展示如何解析一个假设性的PID字节流 def parse_pid(pid_byte): pid_type = { b'\x4B': 'OUT', # 二进制: 0100_1011 b'\xC3': 'IN', # 二进制: 1100_0011 b'\xD2': 'SETUP', # 二进制: 1101_0010 b'\x3C': 'DATA0', # 二进制: 0011_1100 b'\xB4': 'DATA1', # 二进制: 1011_0100 b'\x2D': 'ACK', # 二进制: 0010_1101 b'\xE1': 'NAK', # 二进制: 1110_0001 b'\xA5': 'STALL' # 二进制: 1010_0101 } try: return f"The parsed PID is {pid_type[bytes([pid_byte])]}" except KeyError: return "Unknown or invalid PID" print(parse_pid(int('01001011', 2))) # 应输出 "The parsed PID is OUT" ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值