新闻中心

EEPW首页 > 嵌入式系统 > 设计应用 > VxWorks实时操作系统的USB驱动程序原理与分析

VxWorks实时操作系统的USB驱动程序原理与分析

作者:时间:2012-03-27来源:网络收藏

  在栈的最底部是USB主控制器(USB HC, 即USB Host Controller), 这是主系统中控制每一个USB设备的硬件部分。

  目前,市场上主要有两大类USB主控制器,一种是支持由ime1公司最先提出的通用主控制器接口(Universal Host Controller Interface,简称UHCI),另一种是支持由微软、康柏和国家半导体公司联合设计提出的开放主控制器接口(Open Host Controller Interface,简称OHCI)。硬件厂商一般根据这两个规范设计他们的USB主控制器。

  对于每一类型的主控制器都有一个与硬件独立的USB主控制器驱动(Host Controller Driver,简称HCD)。WindRiver提供了两个驱动:usbHcdUhciLib (UHCI 主控制器库)和usbHedOheiLib (OHCI主控制器库)。USB主驱动(USB host driver,简称USBD)和HCD之间的接口允许一个或超过一个的底层主控制器。而且,WindRiver的USBD能够同时连接多个USB HCD。这样的设计特点可以使开发者建立复杂的USB系统。

  USBD是在HCD之上的与硬件独立的模块。USBD管理每一个与主机相连的USB设备,向更高层次提供了可与USB设备通信的路径。它还负责自动处理USB电力管理以及USB带宽管理。而且,USBD还管理 USB hub,Hub功能是一个驱动能否对USB正确操作的评价之一。因此WindRiver的USBD设计者要使USBD透明地处理hub的功能。这意味着, USBD 还能处理USB hub和设备的动态插拔。
  USB Client模块在USB主驱动栈的顶端。USB类驱动(USB Class Driver)是Client模块的典型例子。USB类驱动负责管理连接到USB上的不同类型的设备;它们依靠USBD来提供与每个设备的通信路径。 USB client模块的其他例子就是那些利用USBD与USB设备通信的应用程序。

4、 USBD驱动详解

  这一部分将要描述USBD(USB Host Driver)的典型应用。例如初始化,client注册,动态连接注册,设备配置,数据传输,同时还探讨了USBD内部设计的关键特性。这部分是的核心。

4.1 初始化USBD:分为两步

  (1)必须至少调用一次函数usbdInitialize()。在一个给定的系统中,usbdlnifialize()初始化内部USBD数据结构,并依次调用其它栈模块的入口。usbdinitialize()可以在启动时调用一次,也可以对每一个设备各调用一次。USBD 自己记录了调用usbdInitialize()(‘+’)和usbdShutDown()(‘-’)的次数。只有大于等于1时才是真正初始化了,而等于 0是关闭了。

  (2)用USBD 的lisbdHedAttaeh()函数来把至少一个HCD连接到USBD上。这一过程既可以在启动时,也可以在运行时把HCD 连接到USBD 上去。后一种机制可以支持“热插拔”,而不用象前一种那样需要重新启动。

4.2 HCD的连接(attaching)与断开(detaching)

  当HCD连接到USBD 时,调用者为usbdHedattaeh函数传递HCD执行入口(表HCD_EXEC_FUNC)和HCD连接参数(HCD attach parameter)。USBD用HCD FNC ATYACH 服务请求依次激活HCD的执行入口,传递同样的HCD attach参数。

  需要强调虽然可以改变用HCD定义的参数,但是最好不应该有所改变。对于WindRiver提供的UHCI和OHCI的HCD,HCI attach参数是一个指向结构PCI_CFG_HEADER (定义在pciConstants.h) 的指针。

  该结构用UHCI和OHCI主控制器的PCI配置头来初始化,而HCD用这个结构中的信息来定位,管理特定的主控制器。典型的,调用者用 usbPeiClassFind ()和usbPciConfigHeaderGet()来得到想要的主控制器的PCI配置头- 这两个函数定义在usbPciLib 中(stubUsbarchPciLib.h中)。如果有UHCI或OHCI要连接到USBD,就要调用这些函数来获得每一个主控制器的 PCI_CFG_HEADER。然后利用usbdHedAttaeh来激活已鉴别出的每一个主控制器。

  注意:底层BSP可能不支持USB的HCD断开,因为当中断向量表重新使能时,如果还应用的是过期的向量表,会导致错误。

4.3 启动顺序

  必须在所有USBD函数前执行函数usbdInitialize()。存在以下两种调用方式:
  (1)传统的“启动”初始化。执行顺序与其意义如下:
  a.usbdInitialize();
  b.usbdPciClassFind():定位一个USB主控制器;
  c.usbdPeiConfigHeaderGet():读USB主控制器配置头;
  d.usbdHedAttaeh():连接HCD,将其作为特定的主控制器:
  e.调用USB class driver初始化入口点;
  f.USB class driver调用usbdlnitialize()。

  (2)“热插拔”调用。执行顺序与其意义如下:
  Boot Code里调用:
  a.USB class driver初始化入口点;
  b.USB class driver调用usbdlnitialize();
  Hot-Swap code调用:
  c.Hot-Swap 鉴别USB主控制器的连接或断开;
  d.Usbdlnitialize();
  e.UsbdPciConfigHeaderGet():读USB主控制器配置头;
  f.UsbdHedAttaeh():连接HCD,将其作为特定的主控制器。

  因为热插拔可以在任何时刻发生,所以USBD和其Client都必须被写成可以动态识别USB设备被插入还是被拔出。当主控制器连接到系统时,USBD 自动地鉴别与其相连的设备,并通知相关的client;同样,拔出设备时,也要通知相关设备。重要的是,USBD 的client,比如USB class driver,在client初始化时,从不设想特定的设备已经出现;而在其他时候,这些驱动随时检查设备是否已经连接到系统上。

4.4 总线任务

  对每一个连接到USBD 的主控制器,例如插入或拔出设备,USBD都会产生一个总线任务,来监控总线事件。一般情况下,这些任务是休眠的(不消耗CPU),只有当USB hub报告它的一个端口有变化时,它们才被唤醒。每一个USBD总线任务有任务名:UsbdBus。

  虽然 HCD委托USBD来管理,但有可能HCD 亲自监视主控制器事件。例如WindRiver提供了UHCI和OHCI的HCD来创造这样的任务。对于WindRiver的UHCI模块 (usbHcdUheiLib),后台任务只是被周期地唤醒,目的是为了检查超时IRP(用一个中断来通知OHCI根hub发生改变)。
  
  用以在USBD和USB之问进行通信的client模块,除了调用usbdlnitialize()外,必须调用usbClientRegister ()使其在USBD注册。当一个client注册到USBD时,USBD把每一个以后将要用到的client的数据结构定位,并跟踪那个client的请求。

  对于每一个client,在client注册过程中,USBD还创建了一个callback任务。在成功注册 client后,USBD返回一个句柄USBD_CLIENT_HANDLE。以下对USBD的调用,将会用到这个句柄。当所有句柄都不需要时,可以调用 usbdClientUnregister()来释放每一个client的数据结构和callback任务。注意:此时所有client要求的任务都会被取消。

  例如:注册一个叫USBD_TEST的client,再注销。
  注册:usbdClientRegister("USBD_TEST',usbdClientHandle);
  注销:usbdClientUnregister(usbdClientHandle);

linux操作系统文章专题:linux操作系统详解(linux不再难懂)


评论


相关推荐

技术专区

关闭