USB 2.0 协议支持 3 种速率:低速 (Low Speed,1.5Mbps)、全速 (Full Speed, 12Mbps)、高速 (High Speed, 480Mbps)。

USB Hub、USB 设备,也分为低速、全速、高速三种类型。一个 USB 设备,可能兼容低速、全速,可能兼容全速、高速,但是不会同时兼容低速、高速。

USB 设备状态切换图

  • 连接 (Attached):USB 设备在已连接到 USB,但还没有上电的时候处于连接状态。
  • 上电 (Powered):USB 设备在已连接到 USB,并且已经上电,但还没有被复位的时候,处于上电状态。 USB 设备的电源获取分为两种,一种是通过外部电源进行获取,另一种是通过设备所连接的集线器 (hub) 处获得电源。通过外部供电的 USB 设备被称为自供电 (self-powered) 设备。尽管自供电设备在连接到 USB 之前可能已经有了电源,但在连接到 USB 并且 VBUS 被应用到设备之前,它们不被认为是处于上电状态。USB 设备可以同时支持自供电和总线供电 (bus-powered) 的配置。某些设备配置支持任一电源,其他设备配置可能只有在设备是自供电的情况下才可用。设备通过配置描述符 (configuration descriptor) 报告其电源能力 (power source capability)。当前电源作为设备状态的一部分进行报告。
  • 默认 (Default):USB 设备在已连接到 USB,且已经上电,并已经复位,但还没有分配唯一的地址时,处于默认状态,设备响应默认地址。 当复位过程完成后,USB 设备以正确的速度运行(即低速 low-speed/全速 full-speed/高速 high-speed)。低速和全速的速度选择由设备端终端电阻决定。作为复位过程的一部分,能够高速运行的设备决定是否以高速运行。
  • 地址 (Address):USB 设备在已连接到 USB,且已经上电和复位,并已分配了一个唯一的设备地址,但还没有被配置时,处于地址状态。 在完成 Set Address 请求后,如果指定的地址是个非零地址,则设备进入地址状态;否则,设备将保持处于默认状态。
  • 配置 (Configured):USB 设备已连接到 USB,已上电和复位,已分配了一个唯一的设备地址,并且已配置,且未挂起,处于配置状态。 配置设备或改变备用设置,会导致与受影响接口中的端点相关的所有状态和配置值被设置为其默认值。这包括任何使用数据切换 (data toggle) 的端点将其数据切换 (data toggle) 重置成值 DATA0。
  • 挂起 (Suspended):USB 设备在已连接到 USB,且已上电,并且 3ms 内未看到总线活动时,USB 设备会进入挂起状态。

硬件线路

USB 连接涉及 Hub Port 和 USB 设备,硬件连接如下:

USB 总线信号

USB 连接线有 4 条:5V、D+、D-、GND。数据线 D+、D-,只能表示 4 种状态。USB 协议中,很巧妙地使用这两条线路实现了信号 1、信号 0、SE0 状态、SE1 状态、J 状态、K 状态、空闲 IDLE、开始 SOP、结束 EOP、复位 Reset、Suspend 信号、Resume 信号、SYNC 信号、Connect 信号、Disconnect 信号等。

低速/全速信号电平

高速信号电平

数据信号

  • Reset 信号:

    • 主机拉低两根信号线(SE0 状态)并保持 10ms
    • USB 设备看到 Reset 信号后,需要准备接收"SetAddress()"请求;如果它不能回应这个请求,就是"不能识别的设备"
  • Suspend 信号:

    • 总线 3ms 以上的 IDLE 状态,则设备会认为主机发起了一次挂起操作
  • Resume 信号:

    • Resume 信号可以由 USB 主机发起,也可以由 USB 设备本身触发,但是只有 USB 主机可以结束 Resume 信号
    • 主机在挂起设备后可通过翻转数据线上的极性并保持 20ms 来唤醒设备,并以低速 EOP 信号结尾
    • 如果设备支持远程唤醒,设备可向主机发起远程唤醒请求,前提是设备已进入 idle 状态至少 5ms,设备会驱动总线进入 K 状态,如下图,K 状态必须维持 1ms-15ms 之内,此信号会在 1ms 内被主机接管,主机会继续驱动唤醒信号直到 20ms,并以低速 EOP 信号结尾
  • SYNC 信号:

    • 低速设备的 SYNC 信号,3 个 KJ 状态的切换,后跟随 2 位时间的 K 状态,完成一次同步信号的发送 Idle-K-J-K-J-K-J-K-K
    • 高速模式中的 SYNC 格式为:KJKJKJKJ KJKJKJKJ KJKJKJKJ KJKJKJKK,即 15 对 KJ,外加 2 个 K
  • Connect 信号:
    Hub 端口的 D+、D-都有 15K 的下拉电阻,平时为低电平。全速设备内部的 D+有 1.5K 的上拉电阻,低速设备内部的 D-有 1.5K 的上拉电阻,连接到 Hub 后会导致 Hub 的 D+或 D-电平变化,Hub 根据变化的引脚分辨接进来的是全速设备还是低速设备。

    高速设备一开始也是作为全速设备被识别的。

    全速设备、高速设备连接时,D+引脚的电平由低变高:

    低速设备连接时,D-引脚的电平由低变高:

  • Disconnect 信号:
    对于低速、全速设备,接到 Hub 时导致 D-或 D+引脚变为高电平,断开设备后,D-或 D+引脚变为低电平:

    对于高速设备,它先作为全速设备被识别出来,然后再被识别为高速设备。工作于高速模式时,D+的上拉电阻是断开的,所以对于工作于高速模式的 USB 设备,无法通过 D+的引脚电平变化监测到它已经断开。

    工作于高速模式的设备,D+、D-两边有 45 欧姆的下拉电阻,用来消除反射信号:

    当断开高速设备后,Hub 发出信号,得到的反射信号无法衰减,Hub 监测到这些信号后就知道高速设备已经断开,内部电路图如下:

  • SOP 信号 (Start Of Packet):

    • 低速设备 SOP 信号:总线从 IDLE 状态(J 状态:差分 0)切到 K 状态(差分 1),即可完成低速 SOP 信号的发送
    • 全速设备 SOP 信号:总线从 IDLE 状态(J 状态:差分 1)切到 K 状态(差分 0),即可完成全速 SOP 信号的发送
  • EOP 结束包(End of Packet):

    • 全速或低速设备的结束包:SE0 状态用于发信号通知分组结束(EOP)。 通过将 D +和 D-驱动到 SE0 状态两位时间,然后将线路驱动到 J 状态一位时间来发信号通知 EOP。 从 SE0 到 J 状态的转换定义了接收器处的分组的结束。 J 状态被置位一个位时间,然后 D +和 D-输出驱动器都处于高阻态。 总线终端电阻将总线保持在空闲状态
    • 高速设备的 EOP: 在高速信号中,以从 EOP 之前的最后一个符号到相反符号的转换开始。这个相反的符号是 EOP 模式中的第一个符号对于 SOF 以外的高速数据包。故意生成位填充错误以指示 EOP。需要接收器将任何位错误解释为 EOP。发送的 EOP 定界符必须是没有位填充的 NRZ 字节 01111111。例如,如果 EOP 字段之前的最后一个符号是 J,则这将导致 EOP 为 KKKKKKKK。对于高速 SOF,传输的 EOP 分隔符需要 5 个 NRZ 字节而不需要填充比特,由 01111111 11111111 11111111 11111111 11111111 组成。因此,如果 EOP 字段之前的最后一位是 J,这将导致线路上有 40 个 K 状态,线路必须返回到高速空闲状态。额外的 EOP 长度对接收器没有意义,它用于断开检测

NRZI 与位填充

参考文章:USB 的 NRZI 信号格式
NRZI:Non Return Zero Inverted Code,反向不归零编码。NRZI 的编码方位为:对于数据 0,波形翻转;对于数据 1,波形不变。

使用 NRZI,发送端可以很巧妙地把"时钟频率"告诉接收端:只要传输连续的数据 0 即可。在下图中,低速/全速协议中"Sync Pattern"的原始数据是"00000001",接收端从前面的 7 个 0 波形就可以算出"时钟频率"。

NRZI 数据格式如上图所示。

使用 NRZI 时,如果传输的数据总是"1",会导致波形维持不变。如果电平长时间维持不变,比如传输 100 位 1 时,如果接收方稍有偏差,就可能认为接收到了 99 位 1、101 位 1。而 USB 中采用了 Bit-Stuffing 位填充处理,即在连续发送 6 个 1 后面会插入 1 个 0,强制翻转发送信号,从而让接收方调整频率,同步接收。而接收方在接收时只要接收到连续的 6 个 1 后,直接将后面的 0 删除即可恢复数据的原貌。

设备速率识别

低速/全速

Hub 端口的 D+、D-都有 15K 的下拉电阻,平时为低电平。全速设备内部的 D+有 1.5K 的上拉电阻,低速设备内部的 D-有 1.5K 的上拉电阻,连接到 Hub 后会导致 Hub 的 D+或 D-电平变化,Hub 根据变化的引脚分辨接进来的是全速设备还是低速设备。

高速

高速设备必定兼容全速模式,所以高速设备内部 D+也有 1.5K 的上拉电阻,只不过这个电阻是可以断开的:工作于高速模式时要断开它。

高速设备首先作为全速设备被识别出来,然后 Hub 如何确定它是否支持高速模式?

Hub 端口如何监测一个新插入的 USB 设备能否工作于高速模式?流程如下:

  • 对于低速设备,Hub 端口不会监测它能否工作于高速模式。低速设备不能兼容高速模式。
  • Hub 端口发出 SE0 信号(10ms),这就是复位信号。
  • USB 设备监测到 SE0 信号后,会发出"a high-speed detection handshake"信号表示自己能支持高速模式,这可以细分为一下 3 种情景。
    • 如果 USB 设备原来处于"suspend"状态,它检测到 SE0 信号后,就发出"a high-speed detection handshake"信号
    • 如果 USB 设备原来处于"non-suspend"状态,并且处于全速模式,它检测到 SE0 信号后,就发出"a high-speed detection handshake"信号。这个情景,就是一个设备刚插到 Hub 端口时的情况,它一开始工作于全速模式
    • 如果 USB 设备原来处于"non-suspend"状态,并且处于高速模式,它会切换回到全速模式(重新连接 D+的上拉电阻),然后发出"a high-speed detection handshake"信号

"a high-speed detection handshake"信号,就是"高速设备监测握手信号",既然是握手信号,自然是有来有回:

  • USB 设备维持 D+的上拉电阻,发出"Chirp K "信号,表示自己能支持高速模式。
  • 如果 Hub 没监测到"Chirp K "信号,它就知道这个设备不支持高速模式。
  • 如果 Hub 监测到"Chirp K "信号后,如果 Hub 能支持高速模式,就发出一系列的"Chirp K"、"Chirp J"信号,这是用来通知 USB 设备:Hub 也能支持高速模式。发出一系列的"Chirp K"、"Chirp J"信号后,Hub 继续维持 SE0 信号直到 10ms。
  • USB 设备发出"Chirp K "信号后,就等待 Hub 回应一系列的"Chirp K"、"Chirp J"信号。
    • 收到一系列的"Chirp K"、"Chirp J"信号:USB 设备端口 D+的上拉电阻,使能高速模式
    • 没有收到一系列的"Chirp K"、"Chirp J"信号:USB 设备转入全速模式

参考文献

https://blog.csdn.net/weiaipan1314/article/details/113639911
《韦东山老师相关课程》
《USB2.0 协议规范》