VxWorks驱动程序开发指南(四)--驱动程序的组织结构

驱动程序的组织结构

驱动程序最重要的部分就是驱动程序源代码文件,源文件描述了设备如何和VxBus、VxWorks OS交互。但是,VxWorks 设备驱动程序还需要另外一些文件,这些附加文件能够帮助你将自己编写的驱动集成到VxWorks编译环境中去,这也是发布驱动程序最重要的一步。本节主要讨论如何在源码树中找到相关的驱动程序文件和其他附加文件。最后还说明驱动程序的各个部分是如何安装在VxWorks OS中的。

3.1 文件位置

在开发驱动程序之前,了解驱动程序文件在VxWorks源码树中的位置是非常重要的,驱动程序文件主要分布在源码树中的3个不同位置。

  • installDir/vxworks-6.x/target/3rdparty      第三方提供的基于VxBus驱动模型的驱动,它们一般都做为插件安装到现有的VxWorks开发环境中
  • installDir/vxworks-6.x/target/src/hwif       风河官方提供的基于VxBus驱动模型的驱动程序,它们一般都作为标准产品的一部分,或者作为补丁来升级。
  • installDir/vxworks-6.x/target/src/drv         风河官方提供的基于传统模型的驱动程序,和VxBus不兼容

3.3.1 风河官方的驱动程序

根据驱动程序的类型,installDir/vxworks-6.x/target/src/hwif目录下的驱动被组织成不同的子目录,例如,定时器的驱动程序在目录installDir/vxworks-6.x/target/src/hwif/timer

3.3.2 第三方的驱动程序

第三方驱动程序的组织方式允许驱动程序开发厂商和开发者创建第三方驱动程序,不需要担心不同厂商的文件之间的命名空间冲突。每一个想提供VxWorks驱动程序的厂商必须在3rdparty目录创建自己的子目录,比如说,Acme公司计划为vxworks开发第三方设备驱动程序,那么就必须在3rdparty目录创建自己的目录installDir/vxworks-6.x/target/3rdparty/acme,在这个目录下,不同类型的驱动程序又组织成不同目录,跟hwif目录一样。

3.2 驱动程序文件例子:wrsample

风河公司提供的VxBus的驱动程序例子位于目录:installDir/vxworks-6.x/target/3rdparty/windriver/wrsample,这些文件可以被当做模板来帮助你开发第三方驱动程序,具体信息请参考wrsample目录下的README文件。

3.3 其他必须的文件

尽管一个驱动程序可以包括很多文件,比如多个源文件和多个头文件,但是一个标准的VxWorks驱动程序有一个最小的文件集,对于大多数vxworks驱动程序最少要求6个文件:

  • 驱动程序源文件                       实现驱动程序控制逻辑
  • 组件描述文件(CDF)          主要用于将驱动程序集成到VxWorks编译环境中,以便于配置
  • 一个driverName.dc文件        提供驱动注册例程的原型
  • 一个driverName.dr文件         提供一小段调用驱动注册例程的代码
  • README文件                          提供版本信息
  • Makefile文件                            提供编译规则

一般情况下,CDF文件,dc文件,dr文件都被认为是驱动程序的配置文件,下面详细介绍这些文件。

3.3.1 驱动程序源文件

驱动程序源文件包含了驱动程序功能的实现逻辑,它们被放在目录installDir/vxworks-6.x/target/src/hwif, 第三方的被放在目录installDir/vxworks-6.x/target/3rdparty。很多VxWorks设备驱动程序只包含一个源文件,一个驱动程序可以包含一个或者几个可选的头文件;但是驱动程序可以包含多个源文件,但是此时必须在Makefile里面提供各个模块的依赖规则。下面以文件vxbCn3xxxTimer.c来说明VxWorks驱动程序的结构。

 

设备驱动程序的第一部分是一个描述VxBus初始化阶段要调用的例程的结构:

/* data structures used by the driver to register itself
* with Vxworks
*/
/* drvBusFuncs provides a set of entry points into the
* driver that are called during various phases of the
* boot process. Drivers can choose to implement 1 or
* more of these entry point, according to the needs of
* the driver during its initialization phases.
*/
LOCAL struct drvBusFuncs cn3xxxTimerDrvFuncs =
{
cn3xxxTimerInstInit, /* devInstanceInit */
cn3xxxTimerInstInit2, /* devInstanceInit2 */
cn3xxxTimerInstConnect /* devConnect */
};

接着就是描述驱动程序所支持的驱动方法的数据结构(每一种类别的驱动程序都必须实现该类的驱动方法):

/* cn3xxxTimerDrv_methods provides the list of driver
* methods that this driver supports. For each driver
* class supported by Wind River, one or more methods
* are expected to be defined for the driver. For
* timer driver class, the 'vxbTimerFuncGet' method
* is required to be supported.
*/
LOCAL struct vxbDeviceMethod cn3xxxTimerDrv_methods[] =
{
DEVMETHOD(vxbTimerFuncGet, cn3xxxTimerFuncGet),
{0,NULL}
};

跟着就是描述该驱动程序需要的注册信息的结构:

/* The cnxxxTimerDrvRegistration structure provides a
* description of the driver to VxWorks, so that VxWorks
* can connect this driver to appropriate hardware during
* the boot process.
*/
LOCAL struct vxbDevRegInfo cn3xxxTimerDrvRegistration =
{
NULL, /* reserved for VxBus use */
VXB_DEVID_DEVICE, /* devID */
VXB_BUSID_PLB, /* busID = PLB */
VXB_VER_4_0_0, /* vxbVersion */
"cn3xxxTimerDev", /* drvName */
&cn3xxxTimerDrvFuncs, /* pDrvBusFuncs */
NULL /* pMethods */
NULL /* devProbe */
};

在注册信息后面,驱动程序必须提供一个例程来向VxBus注册,表明该驱动程序的存在:

/* The vxbCn3xxxTimerDrvRegister function contains the
* first instructions of the device driver that are
* ever executed within a VxWorks system. This function
* registers the driver with VxBus by providing pointers
* to the data structures listed previously. Once this
* step is complete, VxWorks is able to associate this
* driver with appropriate hardware within the system
* to form an instance.
*/
void vxbCn3xxxTimerDrvRegister (void)
{
vxbDevRegister (&cn3xxxTimerDrvRegistration);
}

由于驱动程序注册方法被当做是驱动程序的第一个入口点,VxWorks必须被配置成:当该驱动程序向VxBus注册时,VxWorks知道调用该入口点。为了做到这点,VxWorks使用了之前提到了那几个驱动配置文件:CDF文件,dc文件,dr文件。

注意:VxBus和VxWorks要求驱动程序的注册方法必须是全局的。大多数驱动程序并不需要其他的全局符号,因此都可以声明成LOCAL。

3.3.2 CDF文件

该文件的全称是:component description File,组件描述文件。根据VxBus标准开发的VxWorks设备驱动程序都被编译成一个单独的模块,可以使用VxWorks配置工具非常轻松地将驱动程序配置进BSP中。但是,你必须为你的设备驱动程序创建一个VxWorks组件。

 

一个组件是一个基本的功能单元,它可以单独配置进入VxWorks内核镜像中。为了能够单独添加和删除设备驱动程序到VxWorks中,驱动程序必须能够被VxWorks配置工具识别成individual 组件。为了让驱动程序能够在Workbench或者vxprj中是可以配置的,你必须创建CDF文件,CDF文件提供VxWorks配置工具所需要的信息。针对风河公司发布的设备驱动程序,其对应的CDF文件位于以下目录:

installDir/vxworks-6.x/target/config/comps/vxWorks

在风河提供的驱动程序中,一个CDF文件可能包含着描述多个设备驱动程序的信息,对于第三方驱动,其CDF文件路径是在驱动程序目录下。

注意:内核配置工具并不自动搜索installDir/vxworks-6.x/target/3rdparty/ directories下的文件,为了让内核配置工具能够读取第三方驱动的CDF文件,必须手工将CDF文件拷贝到以下目录:installDir/vxworks-6.x/target/config/comps/vxWorks

 

为新驱动编写CDF文件之前,首先拷贝一个标准的CDF文件到你的驱动程序目录,然后根据你的驱动程序来修改CDF文件。CDF文件主要放在以下目录:

installDir/vxworks-6.x/target/config/comps/vxWorks

以下以一个PCI总线控制器的CDF文件为例,这个文件的路径是:installDir/vxworks-6.x/target/config/comps/vxWorks/40m85xxPci.cdf:

/* 40m85xxPci.cdf - Component configuration file */
Component DRV_PCIBUS_M85XX {
NAME M85xx PCI bus
SYNOPSIS M85xx PCI bus controller Driver
MODULES m85xxPci.o
SOURCE $(WIND_BASE)/target/src/hwif/busCtlr
_CHILDREN FOLDER_DRIVERS
_INIT_ORDER hardWareInterFaceBusInit
INIT_RTN m85xxPciRegister();
PROTOTYPE void m85xxPciRegister (void);
REQUIRES DRV_RESOURCE_M85XXCCSR \
INCLUDE_PARAM_SYS \
INCLUDE_PCI_BUS \
INCLUDE_PLB_BUS \
INCLUDE_VXBUS
INIT_AFTER INCLUDE_PCI_BUS
}

Component DRV_PCIBUS_M85XX {

CDF文件使用上述语句来定义一个组件ID。VxWorks中的每个组件必须用Component关键字来描述,驱动程序的ID一般以DRV_开始,并在ID中包含该驱动程序的描述性信息,每一类的驱动程序对组件ID都有着相同的命名习惯,比如DRV_PCIBUS_M85XX意味着它是一个PCI 总线控制器的组件。设备驱动程序组件标准的命名习惯应该是:DRV_CLASS_NAME,组件名字必须是唯一的,因此DRV_CLASS_NAME中的DRV和CLASS都有可能相同,这就要求NAME必须唯一才行。如果为第三方驱动写CDF文件,可以考虑把VENDOR和驱动程序名作为NAME的一部分。总之,保证DRV_CLASS_NAME唯一就可以。

注意:以前老的驱动程序一般以INCLUDE_开头,不过新驱动都更改了这一用法,使用DRV_开头。

 

NAME     M85xx    PCI   bus

这是名字域,可读性较强,会在内核配置工具的名字栏显示该域定义的信息

SYNOPSIS M85xx PCI bus controller Driver

摘要域,主要是对该组件的简短介绍

MODULES m85xxPci.o

模块域,它列举了编译驱动程序生成的目标文件的名字。当一个驱动程序被包含在工程中时,VxWorks配置服务会分析模块域定义的目标文件中的内容,以决定是否会包含其他组件来把该驱动程序编译进VxWorks镜像。MODULES和REQUIES域一起,提供了把驱动程序编译进VxWorks内核所有需要的信息。

_CHILDREN FOLDER_DRIVERS

这个域用来帮助Workbench对相似的组件的显示进行管理,如下图:

组织

_INIT_ORDER hardWareInterFaceBusInit

这个初始化顺序域描述的是:在VxWorks启动的过程中,应该在什么时候初始化本驱动程序,所有的总线驱动程序都必须在hardWareInterFaceBusInit中初始化,PCI总线也不例外。

INIT_RTN m85xxPciRegister();

定义设备驱动程序的初始化方法,因此,我们必须在这个域提供驱动程序注册方法。这个只是一个初级或者说最小的初始化,后续的初始化会等到VxWorks找到相关的硬件后就会将驱动程序和硬件绑定,形成了一个实例。

PROTOTYPE void m85xxPciRegister (void);

驱动注册方法的原型定义

REQUIRES …

该域描述了驱动程序能够在VxWorks中正常工作所必须有的组件。这个域是必须存在的,因为不是所有设备驱动程序的依赖性都能够通过检查驱动中的unresolved externals来决定的。为了支持该驱动程序,它和MODULES域一起决定哪些组件还需要被包含进来。

INIT_AFTER INCLUDE_PCI_BUS

这个INIT_AFTER和INIT_BEFORE被用于指明INIT_ORDER的依赖性,INIT_AFTER说明必须先初始化PCI总线,才能够初始化本驱动。INIT_BEFORE是在这之前必须要初始化本驱动。

HDR_FILES $(WIND_BASE)/target/src/hwif/h/end/fei8255xVxbEnd.h

上面的这行代码并没有在例子中出现,HDR_FILES主要提供驱动注册函数的原型

 

CFG_PARAMS参数配置

在初始化期间,有时候设备驱动程序需要一些配置信息,如果这些信息是和设备而不是实例相关的,则可以再编译阶段通过传递参数来实现。CFG_PARAMS和Parameter关键字将帮你实现这些任务。CFG_PARAMS用来指明组件要用的参数,而Parameter用来定义参数。如:

Component DRV_NET_SAMPLE {
NAME network device supporting jumbo frames
...
CFG_PARAMS SAMPLE_JUMBO_MTU_VALUE
}
Parameter SAMPLE_JUMBO_MTU_VALUE {
NAME Jumbo frame MTU size
SYNOPSIS max num of bytes in a jumbo MTU
TYPE int
DEFAULT 9000
}

每个参数都必须有NAME,SYNOPSIS,TYPE,DEFAULT四个域。TYPE描述了参数的数据类型,包括任何C类型,BOOL,string(NULL-terminated);DEFAULT定义的值是参数的默认值。

 

 

未完......................待续

您的回应...

相关话题

查看全部

也许你感兴趣

换一批

热门标签

更多