一 USB特点
1.1 USB协议版本介绍:
USB1.0/1.1(low/fullspeed):传输速率最大为12Mbps,是较早的USB协议版本。
USB2.0(highspeed):传输速率最大为480Mbps,相比USB1.0/1.1有了较大的提升。
USB3.0(superspeed):传输速率最大为5Gbps,是目前较快的USB协议版本。
注意:以上协议版本均存在向下兼容性。
1.2 USB接口分类:
Type A:这是我们电脑上常见的那种接口,形状较为标准。
Type B:不太常见,形状比较方正,呈T型,有的嵌入式开发板会使用这种接口。
Type C:现在开始流行起来,其最大的好处是可以盲插,而不用区分正反面,使用更加便捷。
Micro/mini:在手机上比较常见,形状较小巧。
补充说明:不管哪种USB接口,其内部使用的线都是4根,只是接口的形状和外观不同而已。
1.3 usb2.0、usb3.0、usb3.1、type-c 接口含义与区别
usb3.0 比2.0的传输速率快,充电快,能向下兼容2.0
usb3.1 通常是指 usb3.1 gen2,比3.0的传输速率更快、充电更快,同兼容
type-c 通常是指 usb3.1的一种接口形状,总共三大类,c就是第三大类
usb2.0
理论传输速率480Mbps,即60MB/s
四引脚
供电最高允许标准5V/0.5A
USB 2.0基于**半双工二线制总线**,两根线的差分信号来传输数据,只能提供单向数据流传输
usb3.0
理论传输速率5.0Gbps
采用了8/10b的编码方式,将8位的数据编码成10位来发送,即500MB/s9引脚,其中4个引脚的位置与usb2.0位置相同,也是其可以兼容usb2.0的原因注意,这里说的兼容只是说能物理兼容插进去,传输速度肯定还是2.0的效果里面的5根线路中2根用来发送数据,另2根用来接收数据,还有1根是地线。也就是说,USB 3.0可以同步全速地进行读写操作供电最高允许标准5V/0.9A
USB 3.0采用了TxRx四线制差分信号线,类似于PCIe总线,故而支持双向并发数据流传输,为**全双工传输**。
usb3.1
usb3.1并不像2.0、3.0那样,即使技术标准也是实际的插口,usb3.1只是一个标准,不代表实际的插口
包括两种技术标准:usb3.1 gen1,usb3.1 gen2
和三种接口标准:Type-A(Standard-A)、Type-B(Micro-B)以及Type-C
先介绍两种技术标准:
usb3.1 gen1:技术标准基本与usb3.0相同,没有很大提升(可以当做就是3.0)
usb3.1 gen2:才是真正的usb3.1。我们通常说的usb3.1,就是指的usb3.1 gen2。下面介绍的都是gen2的技术标准:
理论传输速率增加到10.0Gbps使用128b/132b编码,在132bit数据中,只需使用4bit做为检查码,编码损耗相比于usb3.0的20%(2/10)下降为约3%(4/132),大约为1.21GB/s供电最高允许标准20V/5A新增USB A/V 3.1 影音传输规范标签从3.0的"SuperSpeed"更新为"SuperSpeed+"
三种接口标准:
从左到右依次是type-a、b、c
type-a:与普通usb接口外设形状相
type-b:外部设备多采用,比如打印机,显示器等,和一些android手机type-b有两种细分形状:Mini USB 和 Micro USB,这两种都有各自的 A 和 B 形状(比较乱),主要用外设形状解决了防误插(与传统的长方形不同,为近似梯形或边缘缺角,方便识别正反)
type-c:"采用了 usb3.1 gen2 技术标准的 type-c 型接口",技术指标和usb3.1 gen2相同。同时还有一个优势:不会插反!(上下两排线,引脚设计中心对称)
注:
type-c实现usb3.1不是强制规范,没有规定说用type-c口一定就是usb3.1,
也没有规定说用usb3.1一定要用type-c
1.4 USB设备供电方式
USB设备有两种供电方式 :自供电设备:设备从外部电源获取工作电压
总线供电设备:设备从VBUS(5v) 取电对总线供电设备,区分低功耗和高功耗USB设备低功耗总线供电设备:最大功耗不超过100mA
高功耗总线供电设备: 枚举时最大功耗不超过100mA,枚举完成配置结束后功耗不超过500mA设备在枚举过程中,通过设备的配置描述符向主机报告它的供电配置(自供电/总线供电)以及它的功耗要求
1.5 USB总线信号
USB使用的是差分传输模式,两个数据线D+和D-
差分信号1:D+ > VOH(min) (2.8V) 且 D- < VOL(max)(0.3V)
差分信号0:D- > VOH and D+ < VOL
1.5.1 J态、K态、SE0态
USB协议中是是用J、K、SE0状态来表示总线状态的(J状态:(LS-低速:差分0;FS-全速:差分1) K状态:(LS:差分1;FS:差分0),具体的状态如下:
(1)低速设备:
J态: D+ ="0",D- ="1"
K态: D+ ="1",D- ="0"
SE0态:D+ ="0",D- ="0"
从J到K或者从K到J,信号翻转,说明发送的是信号0;
从J到J或者从K到K,信号保持不变,说明发送的是信号1。这就是差分信号0/1的发送。
(2)高速设备的J和K相反:
低速下: D+为"0",D-为"1"是为"J"状态,"K"状态相反;
全速/高速下:D+为"1",D-为"0"是为"J"状态,"K"状态相反;
(3)空闲状态(IDLE态)
低速下空闲状态为"K"状态;
全速下空闲状态为"J"状态;
高速下空闲状态为"SE0"状态;
1.5.2 设备复位RESET
在枚举过程中,主机向设备发出复位信号。注意此USB 复位与硬件或上电复位不相同,是两个概念。USB 复位的目的是设置设备的软件状态,以便进行枚举。
当 D- 和 D+ 都保持低电平 (SE0) 10 ms 时,器件会识别复位条件。在某些情况下,器件能够在 2.5 µs 内检测到复位,但是,主机将在整个 10 ms 内保持复位条件。
为了初始化复位,集线器将 D+ 和 D- 保持在低电平。让集线器将数据线保持在低电平允许主机持续为其他设备提供服务,并避免设备因 D+ 和 D- 上缺乏活动而进入挂起模式。主机通过向集线器发出SET_PORT_FEATURE(PORT_RESET)控制命令使集线器复位设备。
1.5.2 挂起Suspend
当连续三个帧都没有接收到帧开始信号时,设备将进入挂起状态。 当发生挂起时,设备中运行的应用软件通常会收到通知,并可能会采取措施降低功耗。在挂起模式下,设备将吸取不超过 50 毫安的电流。挂起的设备能够响应重置和恢复命令。
主机可以通过向连接到要挂起的设备的集线器发出
SET_PORT_FEATURE(PORT_SUSPEND)控制命令来使一个枚举设备挂起。
补充
我们知道,在USB系统中,正常状态下hub或root hub会一直周期性地发送SOF包(Start Of Frame,全速USB每1ms发送一个,高速USB则是125µs发送一个)。根据USB协议,如果USB线上一直处于空闲(Idle)状态超过3ms,设备应该把它当作一个挂起(Suspended)信号,要求设备在10ms内进入挂起状态,并把设备所需的电流大小降到规定的值(对于low-power设备,要求是500 µA,而对于high-power或支持远程唤醒(remote wakeup)功能的设备是2.5mA。
USB设备从上游主机端口接收到持续的IDLE信号超过3.0ms时,USB设备应当认为这是一个挂起的信号,然后开始进入挂起状态。当所有端口无总线活动时,要求设备在10ms内进入挂起状态,并把设备所需的电流大小降到规定的值,即挂起电流值(对于low-power设备,要求是500 µA,而对于high-power或支持远程唤醒(remote wakeup)功能的设备是2.5mA。
USB设备面向上游的端口上的任何总线活动都将使其退出挂起状态。
在没有任何其他总线流量的情况下,SOF令牌每(微)帧将发生一次,以防止全速/高速设备挂起。 在没有任何低速流量的情况下,低速设备将在每一帧中看到至少一个保持活动状态发生 SOF,使它们无法挂起。
当处于挂起状态时,设备必须继续为其 D+(全速/高速)或 D-(低速)上拉电阻供电,以保持IDLE状态,以便上游集线器可以保持正确的设备连接状态 。
USB设备挂起时,可以停止设备的时钟,以进入低功耗模式。而当USB设备可以通过外部中断唤醒自身,然后再由USB设备唤醒主机。
在挂起状态中,设备必须继续向数据项D+/D-的上拉电阻提供电压以维持Idle状态。而对于USB2.0高速设备,还有些额外的要求:
高速设备在收到挂起信号(3ms空闲)后,应在0.125ms内切换到全速状态,也就是说要把终端电阻移除,并在D+数据线上重新挂上1.5k上拉电阻。
设备在随后的100-875µs内检测数据线上的状态。如果该状态是一个Full speed J,那么说明host发下来的是一个挂起信号;如果此时该状态是SE0,说明是host drive数据线D+到0,这是一个复位信号(复位信号会持续至少10ms时间)。
要注意的是高速设备在挂起状态时处于高速模式,只是所用的是全速信号。一旦从挂起状态恢复回来,会马上进入高速工作状态而无需进行复位操作。
USB主机使使用周期性的SOF或Keep alive(低速)阻止设备进入挂起状态。
For High-speed, SOF is sent every micro-frame 125us +/- 65ns
For Full-speed, SOF is sent every frame 1ms +/- 500ns
For Low-speed, Keep Alive (End of Packet) is sent every 1ms in absence of low-speed data
USB设备要退出【挂起模式】 可以由Host唤醒,或者自己唤醒。
如果设备配置为高功率(高达 500 mA),并启用了远程唤醒功能,则在挂起期间允许消耗高达 2.5 mA 的电流。
1.5.3 恢复Resume
当设备处于#挂起Suspend状态时,设备端口上的数据K状态意味着从暂停状态恢复。这意味着恢复信号是全速段中从数据J状态到数据K状态的变化。
恢复设备操作的顺序是在 D+ 和 D- 上产生 K 状态 20 ms。 K 状态在 USB 规范中定义,由 USB 速度决定。
暂停的设备可以通过以下两种方式之一返回到运行状态(即恢复):
如果设备在 Suspend 状态至少 5 ms 后设置了远程恢复功能,则设备可以启动恢复正常操作的过程。要开始恢复,器件会在 D+ 和 D- 上断言 K 状态 1 到 15 ms。主机(即 HUB)将检测到此状态并在 1 毫秒内接管控制 D+ 和 D- 20 毫秒的剩余时间。20 ms 后,设备将恢复正常运行。
主机可以通过向连接到设备的集线器发送CLEAR_PORT_FEATURE(PORT_SUSPSEND)来恢复设备。 这将导致集线器在 D+ 和 D- 上驱动 K 状态 20 毫秒。
1.6 USB插入检测和速度检测
主机通过在设备D+或D-上的1.5K上拉电阻来检测设备的连接和断开事件,并由此判别低速和全速设备。当没有USB来连接时,由于主控器的D+和D-上的下拉电阻使得这条数据线上的电压是近地的,当连接设备时,通过检测设备上的D+和D-的电压,在D+/D-上出现大小为(Vcc*15/(15+1.5))直流高电平电压,而其他线保持接地时,就可以知道全速/低速设备了。
USB高速设备首先被识别成全速设备,然后通过集线器和设备两者的确认,再切换到高速模式下。在高速模式下,十点六传输模式,这是要将D+上的上拉电阻断开。
一个简单的实验:用一个10K的上拉电阻接在USB的+5V和D+(或者D-)上,Windoes也会提示发现新硬件,但无法找到驱动程序,这是因为D+或D-被拉高,集线器认为有设备插入了,它就报告给了主机;但主机获取数据却没有响应,就会得到一个无法识别的USB设备,这是设备管理器显示一个未知的USB设备,并且其VID和PID都为0(枚举不成功)。
USB连接和断开连接:
当主机检测到某一个数据线电平拉高并保持了一段时间,就认为有设备连上来了
主机必需在驱动SE0状态以复位设备之前,立刻采样总线状态来判断设备的速度
D+和D-数据线上的下拉电阻起作用,使得二者都在低电平;主机端看来就是个SE0状态;同样地,当数据线上的SE0状态持续一段时间了,就被主机认为是断开状态
二 USB设备枚举过程
2.1 USB设备状态
USB设备的状态如下:
接入态(Attached):设备接入主机后,主机通过检测信号线上的电平变化来发现设备的接入;
供电态(Powered):就是给设备供电,分为设备接入时的默认供电值,配置阶段后的供电值(按数据中要求的最大值,可通过编程设置)
缺省态(Default):USB在被配置之前,通过缺省地址0与主机进行通信;
地址态(Address):经过了配置,USB设备被复位后,就可以按主机分配给它的唯一地址来与主机通信,这种状态就是地址态;
配置态(Configured):通过各种标准的USB请求命令来获取设备的各种信息,并对设备的某此信息进行改变或设置。
挂起态(Suspended):总线供电设备在3ms内没有总线***作,即USB总线处于空闲状态的话,该设备就要自动进入挂起状态,在进入挂起状态后,总的电流功耗不超过280UA。
2.2 USB设备枚
对应USB设备的状态,host对USB设备会有以下活动:
在枚举过程中,都是使用控制传输。
第一步:
⑴集线器检测新设备
主机集线器监视着每个端口的信号电压,当有新设备接入时便可觉察。(集线器端口的两根信号线的每一根都有15kΩ的下拉电阻,而每一个设备在D+都有一个1.5kΩ的上拉电阻。当用USB线将PC和设备接通后,设备的上拉电阻使信号线的电位升高,因此被主机集线器检测到。)
⑵主机知道了新设备连接后
每个集线器用中断传输来报告在集线器上的事件。当主机知道了这个事件,主机给集线器发送Get_Port_Status(读端口状态)请求,以获取更多的设备信息。返回的消息告诉主机该设备是什么时候连接的。集线器检测设备是低速运行还是高速运行,并将此信息送给主机,这是对Get_Port_Status请求的响应。
⑶集线器重新设置这个新设备
主机发送Set_Port_Feature(写端口状态)请求给集线器,要求它复位端口,请求集线器来重新设置端口。集线器使设备的USB数据线处于重启(RESET)状态至少10ms。
⑷集线器在设备和主机之间建立一个信号通路
主机发送另一个Get_Port_Status请求,确定设备是否已经从复位状态退出。返回的数据有一位表示设备仍然处于重启状态。当集线器释放了重启状态,设备此时处于缺省状态,且已准备好在零端点通过缺省通道响应主机控制传输。缺省地址为00h,设备能从总线获取高达100mA的电流。
⑸集线器检测设备速度
集线器通过测定哪根信号线(D+或D-)在空闲时有更高的电压来检测设备是低速设备还是全速设备。全速和高速设备D+有上拉电阻,低速设备D-有上拉电阻。
⑹获取最大数据包长度(开始第一次数据传输)
主机向address 0发送USB协议规定的Get_Device_Deor命令,以取得却缺省控制管道所支持的最大数据包长度,并在有限的时间内等待USB设备的响应,该长度包含在设备描述符的bMaxPacketSize0字段中,其地址偏移量为7,所以这时主机只需读取该描述符的前8个字节。注意,主机一次只能列举一个USB设备,所以同一时刻只能有一个USB设备使用缺省地址0。
以下操作雷同,不同操作系统设定时延是不一样的,比如说win2k大概是几毫秒,如果没有反应就再发送一次命令,重复三次。
注意,第一次主机只会读取一个数据包的设备描述符。标准的设备描述符具有18个字节,有的USB设备的端点0大小不足18字节(但至少具有8字节),这种情况下USB主机也是只发送一次数据输入请求,多余的数据将不会再次请求,即在第一次获取设备描述符时,只需返回一次数据即可。端点0的长度包含在设备描述符的bMaxPacketSize0字段中,其地址偏移量为7,所以这时主机只需读取该描述符的前8个字节之后,就知道端点0的最大长度了,这是因为端点0最大包长度刚好在设备描述符的第8字节处。注意,主机一次只能枚举一个USB设备,所以同一时刻只能有一个USB设备使用缺省地址0。
例:主机向设备发送一个八字节请求:80 06 00 01 00 00 40 00,设备接收到请求后产生一个中断,我们可以通过读中断寄存器知道中断源,并且可以加读最后状态寄存器来确定第一个接到的包是否为一个Setup包。当控制器处理程序判断出它是一个Get_descriptor请求时,把设备描述符的前16个字节发送到端点0缓冲区中。剩下的2个字节描述符第一次请求时不再发送。
第二步:
⑻主机分配一个新的地址给设备
主机对设备又一次复位,这时就进入到了设置地址阶段。主机通过向地址0发送一个Set_Address请求来分配一个唯一的地址给设备(控制传输的建立过程),新的设备地址包含在建立过程的数据包中。设备在受到这个建立过程之后,直接进入到状态过程,因为这个控制传输没有数据过程。设备在等待主机请求状态返回(一个输入令牌包),收到令牌包后,设备就返回0长度的状态数据包。如果主机确认该状态包已经正常收到,就会发送应答包ACK给设备,设备在收到这个ACK之后,就会启用新的设备地址,这样设备就被分配到一个唯一的设备地址,从此开始所有通信都使用这个新地址。
例:当主机收到正确的前16字节描述符后,会给设备分配一个地址,我的PC分配的地址为:0x03(这个要看你的机子当时的USB接口设备数目而定) Set_Address 请求所发送的数据为:00 05 03 00 00 00 00 00,其中的03就表示主机为设备分配的地址为0x03,在以后的通信里设备就只对0x03地址作出应答。当设备产生一个接收中断后,根据所分配的地址设置设备的地址寄存器相应位。
第三步
⑼主机再次获取设备描述符,主机会向新地址重新发送Get_Device_Deor命令,此次读取其设备描述符的全部字段,以了解该设备的总体信息,如VID,PID,这是会存在多次的请求数据输入(即主机会发送多个IN令牌包)。
例:主机发送设备描述符标准请求Get_descriptor:80 06 00 01 00 00 12 00,此次将要求把18个字节全部发送完。所以主机要分两次来读取。第一次读取16个字节,第二次读取两个字节,最后主机发送0表示发送完毕的应答。
第四步
⑽主机获取配置描述符,配置描述符总共9字节,主机在获取配置描述符后,会根据描述符中所描述的配置集合总长度,获得配置集合。主机会向设备循环发送Get_Device_Configuration命令,要求USB设备回答,以读取全部配置信息。配置集合包括配置描述符、接口描述符、类特殊描述符(如果有)、端点描述符等。
⑾主机发送Get_Device_String命令,获得字符集描述(unicode)(如果有),比如产商、产品描述、型号等等。此时主机将会弹出窗口,展示发现新设备的信息,产商、产品描述、型号等。
根据Device_Deor和Device_Configuration应答,PC判断是否能够提供USB的Driver,一般win2k能提供几大类的设备,如游戏操作杆、存储、打印机、扫描仪等,操作就在后台运行。但是Win98却不可以,所以在此时将会弹出对话框,索要USB的Driver。
⑿主机分配并加载设备驱动程序,这时就可能作应用中的数据传输了。
⒀主机发送Set_Configuration(x)(写配置)命令请求为该设备选择一个合适的配置(x代表非0的配置值)。如果配置成功,USB设备进入"配置"状态,并可以和客户软件进行数据传输。此时,常规的USB完成了其必须进行的配置和连接工作,至此设备应当可以开始使用。不过,USB协议还提供了一些用户可选的协议,设备如果不应答,也不会出错,但是会影响到系统的功能。
⒁主机为复合设备接口分配驱动程序。如果集线器检测到有过流现象,或者主机要求集线器关闭电源,则USB总线切断设备供电电源。在这种情况下,设备与主机无法通信,但设备处于连接状态。
三 USB枚举实例
USB HOST进行初始化完毕(主要包括对符合OHCI规范的寄存器的初始化—总线复位、中断使能、清除中断标志、电源管理、内存指针寄存器的初始化,各种数据结构的初始化等),等待USB设备的插入,当主机检测到有设备插入,就要对设备进行枚举了。那么为什么要对设备进行枚举呢?枚举就相当于主机和设备建立连接的过程(接头),Host向Device询问一些东西,Device将自身的设备类型,如何进行通信报告给Host,这样Host就知道怎么着对Device进行操作了。
枚举的过程实际上用到而且只用到了总线的“控制传输(Control Transfer)”的传输方式。这种传输方式通常用于配置/命令/状态等情形,其中的设置操作setup和状态操作status过程的数据包具有USB协议定义的数据结构,因此,控制传输只能通过消息管道进行。
一个完整的控制传输包括三个过程:1.建立连接 2.数据过程(可选) 3.状态过程
建立连接的过程都是有Host发起,它开始于一个Setup令牌包,后面紧跟一个DATA0包。如果是控制输入传输,数据过程则为输入数据,若是控制输出传输,则数据过程是输出数据。
数据过程的可选型是指设置过程需要指定数据长度,如果指定为0,则没有数据过程。状态过程跟在数据过程之后,状态过程恰好和数据过程的数据传输方向相反,因为此阶段主要是用来确认之前两阶段的所有数据都已经正确传输了。
好了,下面就结合我的这个实例来看看枚举的详细过程:
1.主机向U盘发送第一个Setup包,内容是80 06 00 01 00 00 08 00,其中最后的0008表示得到DEVICE_DCESCRIPTOR的前8个字节,因为这个包的主要目的是要获得USB Device中端点0的最大包的大小(第8个字节),所以只需要8个字节就可以了。USB Device返回的设备标识符为12 01 10 01 00 00 00 40,下面我们需要对0x40记录下来,将其放到Endpoint Descriptor数据结构的DWORD0的MPS(bit16~bit32)块中去。
2.接下来主机发送第二个Setup包,内容是00 05 01 00 00 00 00 00这一个次的作用是为USB设备分配地址(相当于SD卡中的RCA)。如果USB Device接收并接受了此地址设置包,会返回一个长度为0的数据包。Host接收到长度为0的状态包之后就会返回一个ACK给Device,Device再接收到这个ACK之后,就可以启用新地址了。这样Device就得到了一个唯一的设备地址,作为主机通信的唯一表示。
3.发送第三个Setup包,内容是80 06 00 02 00 00 09 00,这次是为了获取配置描述符集合的大小,此位位于读回数据的第三个字节。U盘返回的数据为09 02 20 00 01 01 00 80 32,即描述符集合总大小为0x20。
4.发送第四个Setup包,内容是80 06 00 02 00 00 09 00,和上次不同的仅仅是,这次要读回来的数据是整个配置描述符区域。U盘返回来的数据是09 02 20 00 01 01 00 80 32 09 04 00 00 02 08 06 50 00 07 05 82 02 40 00 00 07 05 02 02 40 00 00。
这时候我们就可以知道该设备是什么类型的设备,支持什么样的操作了。
上述这两个过程也有的程序就是直接读取0xff个字符大小,当然同样可以达到读回设备描述符集合的目的。
至此,我们已经得到了所需要的设备信息,之后就可以对设备进行配置了。
5.向设备发送第五个Setup包,数据为00 09 01 00 00 00 00 00,USB Device返回一个长度为0的数据包,表明数据正确接收。
至此,USB的枚举过程就完成了