一,USB协议发展
USB接口自1994年推出以来,经过30年的发展,从USB1.0发展到了现在的USB4.0,传输速率也从最开始的1.5Mbps,大幅提高到了最新的40Gbps。
USB协议按照速度等级和连接方式分可分为7个版本,但是从USB3.0开始,USB-IF对之前的接口标准重命名了,导致协议名称混乱,市场中的习惯叫法和官方命名不一样,现在USB-IF正式的主版本号只有USB 2.0、USB 3.2和USB4这3个。
从上表可知,USB2.0根据速度分类,可分为低速(Low Speed)、全速(Full Speed)和高速(High Speed)3个版本。
二,USB2.0速度识别
根据规范,全速(Full Speed)和低速(Low Speed)很好区分,因为在设备端有一个1.5k的上拉电阻,当设备插入hub或上电(固定线缆的USB设备)时,有上拉电阻的那根数据线就会被拉高,hub根据D+/D-上的电平判断所挂载的是全速设备还是低速设备。如下两图:
2.1 USB低速设备连接器的D-接有1.5K的上拉电阻
2.2 USB高速设备连接器的D+接有1.5K的上拉电阻。
2.3 高速识别
USB全速/低速识别相当简单,但USB2.0,USB1.x就一对数据线,不能像全速/低速那样仅依靠数据线上拉电阻位置就能识别USB第三种速度:高速。因此对于高速设备的识别就显得稍微复杂些。
高速设备初始是以一个全速设备的身份出现的,即和全速设备一样,D+线上有一个1.5k的上拉电阻。USB2.0的hub把它当作一个全速设备,之后,hub和设备通过一系列握手信号确认双方的身份。在这里对速度的检测是双向的,比如高速的hub需要检测所挂上来的设备是高速、全速还是低速,高速的设备需要检测所连上的hub是USB2.0的还是1.x的,如果是前者,就进行一系列动作切到高速模式工作,如果是后者,就以全速模式工作。
下图展示了一个高速设备连到USB2.0 hub上的情形:
hub检测到有设备插入/上电时,向主机通报,主机发送Set_Port_Feature请求让hub复位新插入的设备。设备复位操作是hub通过驱动数据线到复位状态SE0(Single-ended 0,即D+和D-全为低电平),并持续至少10ms。
高速设备看到复位信号后,通过内部的电流源向D-线持续灌大小为17.78mA电流。因为此时高速设备的1.5k上拉电阻还未撤销,在hub端,全速/低速驱动器形成一个阻抗为45欧姆(Ohm)的终端电阻,2电阻并联后仍是45欧姆左右的阻抗,所以在hub端看到一个约800mV的电压(45欧姆*17.78mA),这就是Chirp K信号。Chirp K信号的持续时间是1ms~7ms。
在hub端,虽然下达了复位信号,并一直驱动着SE0,但USB2.0的高速接收器一直在检测Chirp K信号,如果没有Chirp K信号看到,就继续复位操作,直到复位结束,之后就在全速模式下操作。如果只是一个全速的hub,不支持高速操作,那么该hub不理会设备发送的Chirp K信号,之后设备也不会切换到高速模式。
设备发送的Chirp K信号结束后100us内,hub必须开始回复一连串的KJKJKJ…序列,向设备表明这是一个USB2.0的hub。这里的KJ序列是连续的,中间不能间断,而且每个K或J的持续时间在40us60us之间。KJ序列停止后的100500us内结束复位操作。hub发送Chirp KJ序列的方式和设备一样,通过电流源向差分数据线交替灌17.78mA的电流实现。
再回到设备端来。设备检测到6个hub发出的Chirp 信号后(3对KJ序列),它必须在500us内切换到高速模式。切换动作有:
-
断开1.5k的上拉电阻。
-
连接D+/D-上的高速终端电阻(high-speed termination),实际上就是全速/低速差分驱动器。
-
进入默认的高速状态。
执行1,2两步后,USB信号线上看到的现象就发生变化了:hub发送出来的Chirp KJ序列幅值降到了原先的一半,400mV。这是因为设备端挂载新的终端电阻后,配上原先hub端的终端电阻,并联后的阻抗是22.5欧姆。400mV就是由17.78mA*22.5Ohm得来。以后高速操作的信号幅值就是400mV而不像全速/低速那样的3V。
至此,高速设备与USB2.0 hub握手完毕,进行后续的480Mbps高速信号通信。
2.4 信号电平
在分析USB2.0设备的检测过程之前,需要先了解一下低速、全速、高速设备信号电平及电气参数。
低速、全速设备使用电压信号,总线状态对应的电平范围如下表所示。
2.5 低速设备/全速设备的识别
低速设备/全速设备的识别发生在上电过程中,即Attached–>Powered转换的过程,在usb设备进入Powered状态后就已经确定好速率,速率的确定依赖于Rpu上拉电阻。
在下游设备未插入的情况下,总线受Rpd下拉电阻的影响均处于被拉低的状态,将总线此时的状态称为Single-ended 0 (SE0),当设备插入后Rpu被供电,此时若Rpd上拉电阻连接D+,D+将被拉高,此时总线上的状态被称为Differential “1”;此时若Rpd上拉电阻连接D-,D-将被拉高,此时总线上的状态被称为Differential “0”。
低速设备的IDLE信号,J信号,都是使用Differential “0”来表示的,全速设备的IDLE信号,J信号,都是使用Differential “1”来表示的,将总线idle信号(J信号)维持超过2ms的状态称为connect信号,下游设备产生connect信号之后便进入Powered状态,此时设备支持的速率已经确定;即D+被拉高的时间超过2ms,便认为设备进入Powered模式且处于全速模式,若D-被拉高的时间超过2ms,便认为设备进入Powered模式且处于低速模式。
简单来说,即usb下游设备在插入usb上游设备后,上拉电阻Rpu将D+/D-持续拉高超过2ms(协议中将这一行为称为connect信号),设备便进入Powered状态(进入Powered状态,设备便已经被识别为低速设备/全速设备),下图是上述描述的简化图:
2.6 低速设备/全速设备的断开
针对上游设备的信号,上游设备检测到SE0信号维持超过2.5us的信号称为disconnect信号,上游低速/全速设备检测到disconnect信号便认为设备已经断开,下游设备故障或被拔出后,在失去了上拉电阻Rpu后,D+/D-会全部变为低(SE0信号),SE0信号维持超过2.5us,上游设备便认为下游低速/全速设备已经断开。
2.7 高速设备的识别
高速设备的识别发生在Powered–>Default的过程,Powered–>Default的转化首先由上游设备发送一个reset信号(SE0信号维持超过10ms),之后的行为分为两种情况:
下游设备此时被识别为低速设备,在接受到上游设备发送的reset信号后直接进入Default状态,等待下一阶段的地址设置,此时不会去识别设备是否支持高速模式。
设备此时被识别为全速设备,此时由上游设备发送reset信号,之后双方协商是否支持高速模式,待速率协商完成后进入Default状态,等待进行地址设置,Default状态速率已经识别完成,但还没有进行地址分配,此时使用0地址进行下一步通信。只有进入到Default状态后设备才有了使用packet通信的能力。
注:下游设备处于Default状态之后的状态,上游设备也可通过发送reset信号重新使设备进入Default状态,然后按照usb状态切换图重新驱动设备。
下面描述高速设备的识别过程:
注:前提是usb已经被识别为全速设备且处于Powered状态。
上游设备在下游设备进入Powered状态后便会主动发送reset信号,(SE0信号维持超过10ms)。
事实上在此时发送reset信号及之后进入高速模式的通信中,Rpu电阻便会一直处于断开状态,高速模式已经不需要Rpu电阻了,而是依赖另外一种电阻**Rs(45Ω),Rs(45Ω)在主从设备上都存在,D+ D-各一个,在之后的高速模式通信 高速模式断开检测 Rpu电阻都处于断开状态,电气层信号依赖Rs(45Ω),**但在高速模式的识别过程中,Rpu上拉电阻还是处于工作状态的。
下游设备在检测到上游设备发送的reset信号后,若下游设备支持高速模式则发出Chirp K 信号,上游设备在接受到Chirp K信号后,上游设备便知道下游设备支持高速模式,若上游设备也支持高速模式,就发出连续的Chirp K Chirp J信号,用来通知下游设备Hub也能支持高速模式。之后上游设备继续维持SE0信号直到10ms,断开Rpu电阻,便进入Default状态(高速模式),若速率协商阶段上下游设备中有任何一方不支持高速模式,便终止速率协商进入Default状态(全速模式)
2.8 高速设备的断开
高速设备 断开,即Rs(45Ω)电阻也会断开,此时电气层信号会发生变化,高速设备基于此判断设备的断开。
三,检测过程
Hub识别设备的过程,同时也是检测设备速度的过程,具体流程如下:
3.1 由于低速设备D-接有1.5K上拉电阻,当设备接入Hub时,Hub的D-会被拉高,此时Hub会检测到有低速设备接入,而全速和高速设备D+接有1.5K上拉电阻,当USB设备接入USB Hub时,Hub的D+会被拉高,此时Hub会检测到有全速或高速设备接入。D-或D+拉高最少为2V。
3.2 当D-或D+被拉高后,主机识别到有设备接入,会将D+和D-拉到低于0.3V,使总线处于SE0状态,并持续2.5us以上,将设备复位。此时Hub已经能区分低速和全速/高速设备。
3.3 若是高速设备,则会向D-灌入电流,在总线上形成Chirp K状态,至少持续1毫秒,但不超过7毫秒。Hub检测到Chirp K信号持续的时间至少为2.5微秒。若Hub没检测到Chirp K信号或Hub只支持低速或全速,则会一直保持SE0状态,直到复位完成。
3.4 若Hub支持高速,则在总线退出Chirp K状态的100微秒内,Hub开始发送交替的Chirp K和Chirp J序列(K-J-K-J-K-J),Chirp K和Chirp J状态必须连续,无空闲状态。Chirp K和Chirp J序列持续时间范围为100微秒-500微秒。每个Chirp K和Chirp J持续的时间不小于40微秒,不超过60微秒(Hub发送交替的Chirp K和Chirp J序列的目的是使总线保持活跃状态,避免设备进入Suspend状态)。
3.5 如果设备检测到了Hub发送的Chirp K和Chirp J序列,设备将在500微秒内断开D+的上拉电阻,使能高速功能并进入高速默认状态。如果设备在1毫秒-2.5毫秒内没检测到Hub发送的Chirp K和Chirp J序列,设备将进入全速状态并等待复位完成。
上述流程对应于Linux里面的操作如下:
3.6. 当Hub某个port(设备接入的port)的D+或D-被拉高时,port检测到设备接入,会设置USB_PORT_STAT_C_CONNECTION状态,然后触发xHCI中断,最后系统会调用Hub的中断函数轮询Hub的port状态,找到有设备接入的port。
3.7. 主机向有设备接入的port发送USB_PORT_FEAT_RESET命令,此时port会拉低对应的总线,使其进入SE0状态,发起复位流程。
3.8. 此使Hub会和设备进行一系列的信号交互,此过程由硬件完成,无需软件参与。当复位完成后,主机使用HUB_PORT_STATUS命令获取设备连接状态、速度等信息,然后读取设备的描述符走枚举流程。
下图是使用示波器抓到的USB2.0设备检测过程的波形图。