vxWorks中USB驱动栈-1

来源:互联网 发布:js区分大小写吗 编辑:程序博客网 时间:2024/06/05 05:58

    USB模块可以分为多端口主机(MPH)模块和双角色(DR)模块,它们都能够连接一个或者二个外部端口,这些模块和外部端口总称为USB接口。Mpc8379的USB模块采用的是DR,它的寄存器和数据结构均基于Intel的EHCI(Enhanced Host Controller Interface Specification for Universal Serial Bus),DR模块可以充当USB总线上的主机、外设、以及支持便携式On-The-Go(OTG))可协商主机/外设。

    DR模块有三个基本操作模式:主机(Host)、设备和OTG。可以把DR模块配置成使用UTMI、ULPI 或者FS/LS串行收发器中的任何一种PHY接口。由于引脚的限制,UTMI接口只能用在设备操作模式。值得注意的是,设备模式下的DR模块不支持LS操作。8377使用的phy芯片smsc3300的接口为ULPI(UTMI + Low Pin Interface)。

    风河USB为通用串行总线提供USB传输初始化(USB hosts)和允许vxWorks目标作为USB外设的支持,USB hosts(又叫USB host stack)和USB外设(又叫USB peripheral stack)都遵循USB 2.0规约。Host Stack使vxWorks可以使用USB设备,而Peripheral Stack允许Windows机器将vxWorks板当做一个USB设备。这里先介绍Host,下图为USB Host驱动栈结构:

    USB Host Stack驱动包括USB驱动(USBD)、主机控制驱动(HCD)、hub驱动和class驱动。风河为标准接口协议EHCI、UHCI、OHCI提供HCD驱动,另外,还为USB控制器提供了root hub diver,为各种USB外设提供class driver合集。其中,USBD是硬件独立的,它提供了驱动栈上层(包括USB class drivers)与USB总线的通讯通道,还负责电源管理、USB带宽管理、动态挂载/释放USB设备等功能。下图为vxWorks中所体现的USB Host Stack组成图:

 

 

    这里从上往下来理解,usbTool是风河提供的USB测试工具包,从使用usbTool的过程可知,USB在初始化时的步骤如下:

1、先执行usbInit初始化USB2的Host Stack,源码如下:

STATUS usbInit (void){if (!usbdInitByKernel){/* 为USB驱动设置内存空间(默认2M)*/ossPartSizeSet(USB_MEM_PART_SIZE);      /* 初始化USB2 Host Stack,主要初始化USBD2.0层的全局变量*/      if (usbdInit() == OK)      {      usbdInitByKernel = TRUE;#ifdef DEBUG_ANNOUNCE_USB          printf("USB2 Host Stack Initialized\n");#endif/*注册USB Hub Class驱动到USB Host驱动栈,以及初始化USB1.1转换层*/      if ((usrUsbHubInit() != OK) || (usbdTranslationInit() != OK))      {      return ERROR;      }      }      }  else  {  printf("USB2 Host Stack Already Initialized\n");  }  return OK;}

2、然后执行usbdInitialize初始化USBD,该函数在系统调用其他USBD函数前必须执行一次以上,有一个公用计数器guUSBDInited ,Initialize函数时会加1,ShutDown时会减1,大于0时表示初识化完成,注意:由于usbdInitialize可以嵌套执行,所以在执行计数器操作时,必须要遵循互斥访问规则。它用于准备访问URBs所需的USBD和传送单元。oss为O/S-independent services,用于保护互斥信号量。Host Stack的USBD2.0和Hub class模块的源码可以参考这两个目录:

installDir/target/src/hwif/usbinstallDir/target/src/hwif/busCtlr/usb/hub

3、再初始化EHCI、OHCI、UHCI控制器,在usbTool中,这个过程叫做Attach,用于初始化hcd并注册到vxBus。先后调用usbxhcdInit和vxbUsbxhciRegister两个函数,前者的使用过程实际上就是调用usbHstHCDRegister,将HCD注册到USBD中,这里涉及到一个结构体USBHST_HC_DRIVER,它包含了HCD的函数指针,在HCD初始化时会将它传给USBD,后者利用这些指针和HCD进行通信。该结构体定义如下:

typedef struct usbhst_hc_driver    {    /* 用于此HCD的总线数目 */    UINT8       uNumberOfBus;   /* 结构体vxbBusTypeInfo保存总线信息 */     struct vxbBusTypeInfo        * pUsbHcdBusType;   /*下面均为函数指针*/    /* 从frame number Reg中获取num*/    USBHST_STATUS   (*getFrameNumber)  (UINT8   uBusIndex,                                        UINT16 *puFrameNumber);    /* 设置frame位宽 */    USBHST_STATUS   (*setBitRate)      (UINT8   uBusIndex,                                        BOOL    bIncrement,                                        UINT32 *puCurrentFrameWidth);    /* 判断总线带宽是否足够支持接口设置的改动 */    USBHST_STATUS   (*isBandwidthAvailable)                                           (UINT8   uBusIndex,                                            UINT8   uDeviceAddress,                                            UINT8   uDeviceSpeed,                                            UCHAR  *pCurrentDescriptor,                                            UCHAR  *pNewDescriptor);    /* 为特定USB endpoint解析并创建pipe */    USBHST_STATUS   (*createPipe)      (UINT8   uBusIndex,                                        UINT8   uDeviceAddress,                                        UINT8   uDeviceSpeed,                                        UCHAR  *pEndPointDescriptor,                                        UINT16  uHighSpeedHubInfo,                                        UINT32 *puPipeHandle);    /* 修改默认pipe属性(address 0,endpoint 0) */    USBHST_STATUS   (*modifyDefaultPipe)                                           (UINT8   uBusIndex,                                            UINT32  uDefaultPipeHandle,                                            UINT8   uDeviceSpeed,                                            UINT8   uMaxPacketSize,                                            UINT16   uHighSpeedHubInfo);    /* 删除pipe */    USBHST_STATUS   (*deletePipe)      (UINT8   uBusIndex,                                        UINT32  uPipeHandle);    /* pipe上的请求pending  */    USBHST_STATUS   (*isRequestPending)(UINT8   uBusIndex,                                        UINT32  uPipeHandle);    /* 提交请求到endpoint,URB:USB Request Block  */    USBHST_STATUS   (*submitURB)       (UINT8          uBusIndex,                                        UINT32         uPipeHandle,                                        pUSBHST_URB    pURB);    USBHST_STATUS   (*cancelURB)       (UINT8          uBusIndex,                                        UINT32         uPipeHandle,                                        pUSBHST_URB    pURB);  /* 以下两个用于处理split transaction时出现的错误 */    USBHST_STATUS (*clearTTRequestComplete)(UINT8         uRelativeBusIndex,                                            void *         pContext,                                            USBHST_STATUS nStatus);    /* Function pointer to submit the status of the reset TT request */    USBHST_STATUS (*resetTTRequestComplete)(UINT8         uRelativeBusIndex,                                            void *         pContext,                                            USBHST_STATUS nStatus);} USBHST_HC_DRIVER, *pUSBHST_HC_DRIVER;

后者则分析意义不大,全部都是调用vxbDevRegister注册到vxBus上。

    至于这些驱动,风河已经编译好了(郁闷,还是只能看代码学习),见目录installDir/target/src/hwif/busCtrl/usb/hcd,三种接口都分开放置了,尽管一次只能使用一种接口,但风河允许同时添加多个接口驱动,从而加强了产品的兼容性。到这里需要注意,添加usbTool就不能添加其他任何Init函数,否则会编译出错。

    若不是有usbTool,将组件完全包含后,系统若要使用USBD2.0接口,需要在vxWorks启动时经历4步初始化过程:

1、根据选择的组件将USB host控制器注册到vxBus。该过程是vxBus发现控制器设备并执行特定的vxBus初始化操作,调用函数为vxbUsbControllerRegister,

2、执行USBD入口函数usbdInit,

3、执行usbHubInit初始化hub class Drivers;

4、执行usbHcdInit将特定的HCD注册到USBD。

    上图中还有个OSAL,该组件用于为vxWorks关于host Stack的操作系统服务提供一个抽象、简化的视图。它包含了进程管理、互斥量、内存调度以及系统时间等,在usbd中,就是ossLib库。需要注意,在编写USB驱动时,需要有大部分精力是放在互斥访问和内存调度上的。

原创粉丝点击