USB通讯过程

By | 2019-10-16

原文: https://blog.csdn.net/go_str/article/details/80802452

================================================================
USB行业标准介绍
USB通讯过程
USB中的端点详细了解
USB传输之控制传输
================================================================

一、USB系统的结构

USB系统是由三个逻辑层组成:功能层、USB设备层和USB总线接口层。并且每一层都是由主机和USB设备不同的功能模块组成,如下图所示:

1、功能层(接口)

功能层是由客户软件和设备方的功能单元组成,其能够实现USB设备传输的特定功能。通过功能层可直观地理解USB传输的数据内容。其中,客户软件通过USB系统软件来与USB设备进行通信。功能单元对于客户软件,可视为接口的集合。

2、USB设备层 (端点)

    USB设备层是由USB系统软件和USB设备的USB逻辑设备组成,其实现主机和USB设备之间传输的具体配置。USB逻辑设备对于USB系统软件,可视为端点的集合。

3、USB总线接口层

USB总线接口层是由主机的USB主控制器和设备的USB总线接口组成。其实现主机和USB设备实际的数据传输。

4、主机部分

USB主机部分由客户软件、USB系统软件和USB总线接口组成。

  1. 客户软件
    客户软件负责和USB设备的功能单元进行通信,以实现特定的功能。客户软件不能直接与USB设备相连接,必须通过USB系统软件和USB总线接口才能实现连接。客户软件包括USB设备驱动程序和界面应用程序两部分。
  2. USB系统软件
    USB系统软件负责和USB逻辑设备进行配置通信,并管理客户软件启动的数据。一般包括USB总线驱动程序USB主控制驱动程序和非USB主机软件三个部分,这部分会由系统提供。
  3. USB总线接
    USB总线接口包括主控制器和跟集线器两部分。其中,主控制器是负责完成主机和USB设备间的数据实际传输。根集线器是为USB系统连接起点。

5、设备部分

USB设备部分由三个功能模块组成,分别是USB总线接口、USB逻辑设备和功能单元。
功能单元看作是一个接口的集合;
USB 逻辑设备被USB系统软件看作一个端点的集合;
USB总线接口是USB设备中的串行接口引擎(SIE)。

当客户程序通过USB管道发送或接收数据时,它首先调用Win32 APl,调用最终将使功能驱动程序收到一个IRP。而驱动程序的工作就是把客户的请求引导到有正确端点的管道上。它把请求提交到总线驱动程序,总线驱动程序再把请求分解成多个事务,然后这些事务被送往总线。总线上的信息流以每毫秒一帧数据的形式流动。总线驱动程序必须安排好多个事务以使它们能被装入同一帧中。

二、USB的拓扑结构

USB是一种主从结构的系统。主机叫Host,从机叫做Device(也叫设备)。通常所说的主机具有一个或者多个USB主控制器(host  controller)和根集线器(root hub)。主控制器主要负责数据处理,而跟集线器则提供一个连接主控制器与设备之间的接口和通路。

通常情况下,PC机上有多个主控器和多个USB口,一个主控器下有一根集线器,一根集线器通常具有一个或者几个USB接口。通常集线器可以通过USB集线器来扩展USB接口,只是带宽是不能够拓宽的,因为带宽是共享一个USB主控器的。

了解上面的信息后,再来看USB的拓扑结构如下图:

USB 结构

USB的拓扑结构看起来是一个金字塔形的结构,具体构成如下:

塔顶是USB的主控器和根集线器,下面接USB集线器,USB集线器将一个USB口扩展为多个USB口,多个USB口同样可以通过USB集线器扩展出更多的接口。不过USB口并不能通过USB集线器无止境的扩展,他是有限制的,例如在USB2.0规定它最多扩展6次。

理论上一个USB主控器最多可接127个设备,这是因为协议规定每个USB设备具有一个7bit地址(取值范围为0~127,地址用于给主机识别是哪个设备,其中0地址值得注意,是给刚接入未初始化的设备使用的)。

三、USB的设备架构

设备架构认为设备是由一些配置、接口和端点构成的。其中配置和接口是USB功能的抽象,实际的数据传输由端点来完成。其对应关系如下图所示:

  1. 设备
    设备代表USB设备,它由一个或多个配置组成。设备描述符用于说明设备的总体信息,并指出其所包含配置的个数。
  2. 配置
    在使用USB设备前,必须为其选择一个合适的配置。如USB设备的低功耗模式和高功耗模式分别对应一个配置。配置描述符用于说明USB设备中各个配置的特性。
  3. 接口
    一个配置可以包含一个或多个接口。接口是一个端点的集合。接口描述符用于说明USB设备中各个接口的特性。
  4. 端点
    端点是USB设备中的实际物理单元,USB数据传输就是在主机和USB设备各个端点之间进行的。
  5. 管道
    管道,是主机软件(数据缓冲区)和USB设备的各个端点之间的数据传输链接,它是两者之间通信流的抽象。然而,实际的数据传输是由USB总线接口层来完成的。管道和USB设备中的端点一一对应,并且各个管道的数据传输是相互独立的。
    管道有两种类型:流管道和消息管道。其中最为重要的消息管道是“缺省控制管道”,这个管道在设备开始上电后就存在了,它用于提供设备的配置与状态等信息。主机与设备之间的联络就是通过消息管道实现的。

四、USB枚举与通信的具体过程

1、USB接头
下图是一个USB接头的结构图:

由图可以看出,标准的USB链接线使用4芯电缆:5V电源线(Vbus)\差分数据线负(D-)、差分数据线正(D+)和地线(GND)。

在hub端,数据线D+和D-都有一个阻值在14.25k到24.8k的下拉电阻Rpd,而在设备端,D+(全速,高速)和D-(低速)上有一个1.5k的上拉电阻Rpu。当设备插入到hub端口时,有上拉电阻的一根数据线被拉高到幅值的90%的电压(大致是3V)。hub检测到它的一根数据线是高电平,就认为是有设备插入,并能根据是D+还是D-被拉高来判断到底是什么设备(全速/低速)插入端口。

2、USB通信过程

主机和USB设备可以相互传输数据,其具体过程如下(以主机箱设备传输为例):

step1:客户软件首先将要传输的数据放入缓冲区,同时向USB总线驱动程序发出IRPS,请求数据传输。(客户软件)

step2:USB总线驱动接收到程序接收请求,并对数据进行处理,转化为具有USB格式的事务处理。(USB系统软件)

step3:USB主控制器驱动程序将这些事务处理建立成事务列表,同时要求不能超过USB带宽。(USB系统软件)

step4:USB主控制器读取到事务列表并将事务转化为信息包,发送到USB总线上。(USB总线接口)

step5:USB设备收到这些信息后,SIE(USB总线接口是USB设备中的串行接口引擎)将其解包后放入指定端点的接收缓冲区内,由芯片固件对其进行处理。

图表展示如下:

3、USB枚举通信具体过程

枚举就是从设备读取一些信息,知道设备是什么样的设备,如何进行通信,这样主机就可以根据这些信息来加载合适的驱动程序。调试USB设备,很重要的一点就是USB的枚举过程,只要枚举成功了,那么就已经成功大半了。

枚举通信过程具体如下:

Step1:检测电压变化,报告主机
首先,USB设备上电后,一直监测USB设备接口电平变化HUB检测到有电压变化,将利用自己的中断端点将信息反馈给主控制器有设备连接。

Step2:主机了解连接设备
主机在知道有设备接入后会发送一个Get_Port_Status请求(request)给hub以了解此次状态改变的确切含义。

Step3:Hub检测所插入的设备是高速还是低速
hub通过检测USB总线空闲(Idle)时差分线的高低电压来判断所连接设备的速度类型,当host发来Get_Port_Status请求时,hub就可以将此设备的速度类型信息回复给host。USB 2.0规范要求速度检测要先于复位(Reset)操作。

Step4:hub复位设备
主机一旦得知新设备已连上以后,它至少等待100ms以使得插入操作的完成以及设备电源稳定工作。然后主机控制器就向hub发出一个 Set_Port_Feature请求让hub复位其管理的端口(刚才设备插上的端口)。hub通过驱动数据线到复位状态(D+和D-全为低电平 ),并持续至少10ms。当然,hub不会把这样的复位信号发送给其他已有设备连接的端口,所以其他连在该hub上的设备自然看不到复位信号,不受影响。

Step5: Host检测所连接的全速设备是否是支持高速模式
因为根据USB 2.0协议,高速(High Speed)设备在初始时是默认全速(Full Speed )状态运行,所以对于一个支持USB 2.0的高速hub,当它发现它的端口连接的是一个全速设备时,会进行高速检测,看看目前这个设备是否还支持高速传输,如果是,那就切到高速信号模式,否则就一直在全速状态下工作。
    同样的,从设备的角度来看,如果是一个高速设备,在刚连接bub或上电时只能用全速信号模式运行(根据USB 2.0协议,高速设备必须向下兼容USB 1.1的全速模式)。随后hub会进行高速检测,之后这个设备才会切换到高速模式下工作。假如所连接的hub不支持USB 2.0,即不是高速hub,不能进行高速检测,设备将一直以全速工作。

Step6:Hub建立设备和主机之间的信息通道
主机不停地向hub发送Get_Port_Status请求,以查询设备是否复位成功。Hub返回的报告信息中有专门的一位用来标志设备的复位状态。
       当hub撤销了复位信号,设备就处于默认/空闲状态(Default state),准备接收主机发来的请求。设备和主机之间的通信通过控制传输,默认地址0,端点号0进行。此时,设备能从总线上得到的最大电流是100mA。(所有的USB设备在总线复位后其地址都为0,这样主机就可以跟那些刚刚插入的设备通过地址0通信。)

Step7:主机发送Get_Descriptor请求获取默认管道的最大包长度
默认管道(Default Pipe)在设备一端来看就是端点0。主机此时发送的请求是默认地址0,端点0,虽然所有未分配地址的设备都是通过地址0来获取主机发来的请求,但由于枚举过程不是多个设备并行处理,而是一次枚举一个设备的方式进行,所以不会发生多个设备同时响应主机发来的请求。
      设备描述符的第8字节代表设备端点0的最大包大小。虽然说设备所返回的设备描述符(Device Descriptor)长度只有18字节,但系统也不在乎,此时,描述符的长度信息对它来说是最重要的,其他的瞄一眼就过了。当完成第一次的控制传输后,也就是完成控制传输的状态阶段,系统会要求hub对设备进行再一次的复位操作(USB规范里面可没这要求)。再次复位的目的是使设备进入一个确定的状态。

Step8:主机给设备分配一个地址
主机控制器通过Set_Address请求向设备分配一个唯一的地址。在完成这次传输之后,设备进入地址状态(Address state),之后就启用新地址继续与主机通信。这个地址对于设备来说是终生制的,设备在,地址在;设备消失(被拔出,复位,系统重启),地址被收回。同一个设备当再次被枚举后得到的地址不一定是上次那个了。

Step9:主机获取设备的信息
主机发送 Get_Descriptor请求到新地址读取设备描述符,这次主机发送Get_Descriptor请求可算是诚心,它会认真解析设备描述符的内容。设备描述符内信息包括端点0的最大包长度,设备所支持的配置(Configuration)个数,设备类型,VID(Vendor ID,由USB-IF分配), PID(Product ID,由厂商自己定制)等信息。
    之后主机发送Get_Descriptor请求,读取配置描述符(Configuration Descriptor),字符串等,逐一了解设备更详细的信息。事实上,对于配置描述符的标准请求中,有时wLength一项会大于实际配置描述符的长度(9字节),比如255。这样的效果便是:主机发送了一个Get_Descriptor_Configuration 的请求,设备会把接口描述符,端点描述符等后续描述符一并回给主机,主机则根据描述符头部的标志判断送上来的具体是何种描述符。
      接下来,主机就会获取配置描述符。配置描述符总共为9字节。主机在获取到配置描述符后,根据里面的配置集合总长度,再获取配置集合。配置集合包括配置描述符,接口描述符,端点描符等等。
     如果有字符串描述符的话,还要获取字符串描述符。另外HID设备还有HID描述符等。

Step10: 主机给设备挂载驱动(复合设备除外)
主机通过解析描述符后对设备有了足够的了解,会选择一个最合适的驱动给设备。  然后tell the world(announce_device)说明设备已经找到了,最后调用设备模型提供的接口device_add将设备添加到 usb 总线的设备列表里,然后 usb总线会遍历驱动列表里的每个驱动,调用自己的 match(usb_device_match) 函数看它们和你的设备或接口是否匹配,匹配的话调用device_bind_driver函数,现在就将控制权交到设备驱动了。   
     对于复合设备,通常应该是不同的接口(Interface)配置给不同的驱动,因此,需要等到当设备被配置并把接口使能后才可以把驱动挂载上去。

Step11:设备驱动选择一个配置
驱动(注意,这里是驱动,之后的事情都是有驱动来接管负责与设备的通信)根据前面设备回复的信息,发送Set_Configuration请求来正式确定选择设备的哪个配置(Configuration)作为工作配置(对于大多数设备来说,一般只有一个配置被定义)。至此,设备处于配置状态(Configured),当然,设备也应该使能它的各个接口(Interface)。
    对于复合设备,主机会在这个时候根据设备接口信息,给它们挂载驱动。

发表评论

邮箱地址不会被公开。 必填项已用*标注