您的位置:首页 > 产品设计 > UI/UE

PlatformBuilder 文档中关于“如何开发设备驱动”的翻译

2009-08-17 13:47 531 查看



如何创建一个驱动程序

—— 翻译自PlatformBuilder文档(cquyyang)

在操作系统定制之后,可以创建WinCE下针对特定目标设备的驱动程序。一旦确定了操作系统将要使用的硬件,就可以开发驱动了。

硬件和软件假设

l 在下述步骤中所描述的驱动代码例子仅仅是一个开始,没有运行在特定的硬件上。必须修改驱动代码以使得该代码能够正确的运行在目标设备上。
l 可以创建一个电源管理流接口驱动。更多的关于流接口驱动,请参考Stream Interface Driver Development Concept。关于电源管理方面,请参考Power Management。
l 你已经熟悉如何使用Platform Builder命令行工具,可参考Build Tool。
l 你已经熟悉Windows CE驱动开发工具,可参考Driver Development Tool。

按照下述步骤建立驱动程序

1.请熟悉Windows CE设备驱动的代码结构

大部分的Windows CE设备驱动包含PDD(platform dependent driver)和MDD(model device driver)两个部分。单体驱动将PDD和MDD合成为一个驱动,分层驱动则不合并。

MDD有以下特性:
n 包含给定种类的驱动使用的通用代码。
n 使用PDD功能来访问硬件。
n 连接到PDD层并且声明设备驱动服务接口函数。MDD将在此层调用该函数。
n 显示对应该操作系统的设备驱动接口函数(DDI)。
操作系统的其他部分可以调用这些函数。相关设备可以共享同一个DDI。单体驱动也可以显示DDI函数。
n 处理中断程序。
n 可以让开发者重用。
n 可以连接至多个PDD。
n 要求通常不会变化
如果改变了,在将驱动迁移至未来版本的过程中可能会存在问题。
n 包含所有中断服务线程(ISTs)。

PDD有以下特性:
n 包含硬件平台的特定代码。
n 可能会应为硬件平台而需要改变。
n 用于协同特定的MDD驱动。
n 显示DDSI用于MDD调用的函数
单体驱动不显示DDSI函数。

选择分层驱动还是单体驱动,请参考以下列表:
n 分层驱动可能仅需要改变PDD。
n 由于MDD访问PDD的原因,所以分层驱动在函数调用中的负载要高。
n 对于单体驱动而言,由于集成了MDD和PDD,无需再由MDD访问PDD,所以其性能要好。
n 由于大部分WINDOWS CE所包含的驱动都被分成PDD和MDD,所以单体驱动在移植到以后WINDOWS CE版本中会出现困难。
n 如果设备能力和执行在MDD层的任务匹配的很好,那么单体驱动可以简单而高效。

2.请熟悉Windows CE的驱动开发

设备驱动是一种从物理设备或虚拟设备中将功能抽象出来的软件。一个设备驱动管理着这些设备的操作。例如,物理设备有网路适配器、时钟和异步串行通讯接口;虚拟设备有文件系统。设备驱动允许应用和操作系统可以看到设备的功能。在开发设备驱动时,需要利用系统提供的服务。虽然Windows CE设备驱动是可信的独立模块,但是它们不需要运行在内核模式。
许多Windows CE实现流接口。核心的流接口入口是XXX_Open(Device Manager),XXX_Close(Device Manager),XX_Read(Device Manager),XXX_Write(Device Manager)。更多的信息请参考《流接口驱动》。
网路适配器、显示适配器、鼠标、键盘和其他专用设备不使用流接口。这些设备使用与之功能相符的接口。
不管设备驱动显示的接口如何,你可能必须得实现中断服务程序(ISR)。更多关于中断和ISR的信息请参考《中断》。
不同的处理加载不同的驱动,下述表格显示了需要加载驱动的处理以及该处理加载那些驱动。
处 理
驱 动
文件系统
(FileSys.exe)
FileSys.exe加载文件系统驱动,详细信息请参考《文件系统》
设备管理器
(Device.exe)
设备管理器加载声音驱动、电池驱动、键盘驱动、鼠标驱动、NDIS驱动、LED驱动、串行驱动、PC卡驱动、USB驱动和其他在流接口中声明的驱动。
Device.exe通常使用ActivateDeviceEx来加载大部分驱动,这些驱动在流接口中声明。详细信息参考《设备管理》。
显示、窗体、事件子系统
(GWES.exe)
当GWES是唯一的驱动客户端时,GWES.exe加载设备驱动。由其加载的设备驱动对相似的设备开放一系列的标准功能。有GWES加载的驱动有可能显示流接口或其他接口。Having alternatives make accessing the drivers much faster.GWES加载显示驱动、打印驱动、触摸屏驱动。更多信息请参考《Shell和用户界面综述》。

3.如果尚未设计系统,请于Platform Builder 的IDE环境中创建一个系统设计。

在Platform Builder的集成开发环境中,可以使用“新工程向导”来创建一个基本的操作系统设计。“新工程向导”在目录表选择中提供了各种设计模板。需要提供唯一的工程名称,以标识该设计工程和相关文件位置。
当完成了系统设计之后,就可以向自己设计的系统中添加或删除目录表下的项目或者是个人创建的功能。
在建立可运行的镜像后,就可以向目标设备下载并调试,更多信息请参考《如何连接至目标设备并调试》。
创建系统设计工程:
1.选择File->New Platform,显示向导界面。
2.选择Next
3.在名称输入框中输入该工程的名称,并点击Next。
工程名称不能含有空格。可以在Location输入框中键入新的工程路径或者点击Browse按钮选择不同的路径。路劲不能超过32个字符且不能含有空格。
4.选择一个或多个可用BSP,点击Next。
关于BSP的列表和描述请参考《板载支持包》。
这个列表包含了所有被选中的CPU的BSP。所有支持的CPU列表存放在每个BSP的目录表项目文件中(.cec文件)。
5.从设计模板区域选择设计模板,并点击Next。
关于设计模板的列表和描述,请参考《设计模板选择》。
6.选择系统需要的选项,点击Next。如果采用默认方式请点击Finish。
7.如果出现了工程相关的特殊提示,请参看提示内容并点击Next。
完成工作区创建后,可以从Platform的菜单中随时查看提示内容。参看时,请选择Review Special Notification。
8.在向导的最后一页,建立新的设计工程,选择Finish。

4.将电源管理驱动例子拷贝至自己设计的系统中

例如:将 %_WINCEROOT%/Public/Common/Oak/Drivers/PM/Test/DevSample拷贝至
%WINCEROOT%/Platform/<your OS design>/drivers/<your driver name>。

5.将电源管理驱动例子的文件名称更改为与将要实现的功能一致的名字。

6.更改源代码文件中TARGETNAME和SOURCES的值,和文件名称对应。

7.添加WINCEOEM=1到源代码文件,以便于驱动可以访问%_WINCEROOT%/Public。更多信息请参考《源代码文件》。

8.修改源代码,以实现正确的流驱动接口。
电源管理驱动例子包含了对流接口功能的支持。这些功能的prefix修改成PDX。
各种问题都有可能影响流驱动接口DLL的开发。为了实现流接口驱动,需要创建一个含有驱动入口地址的DLL,而后决定该驱动是否可以单独或重复访问(single or multiple access)。
对驱动来说,Service.exe中的服务程序行为和设备管理程序是相似的。

流接口驱动入口
你可以实现一个驱动,仅含有Init和Deinit入口地址且没有设备的prefix。不能利用CreateFile来访问驱动。PCIBUS和RegEnum是两个这种驱动的例子。这两个驱动在 %_WINCEROOT%/Public/Common/OAK/Drivers/PCIbus
%_WINCEROOT%/Public/Common/OAK/Drivers/RegEnum。
如果DEVFLAGS_NAKEDENTRIES在驱动的标志注册表子键(Flags registry subkey)中定义,那么入口点名称可以undecorated。例如:Open、Close等等。电池驱动的例子是就一个使用undecorated入口的驱动,该驱动位于%WINCEROOT%/ Public/ Common/ OAK/ Drivers/ Battdrvr中。电池驱动的注册表设置依然依然必须含有prefix。
这些入口必须在DLL中声明,通过将__declspec(dllexport)添加至函数的声明前实现。如果你在使用C++开发,那么入口必须还要声明为extern "C"。更多信息,请参考《流接口驱动函数》。

单独或可重复访问(Single Access and Multiple Access)
当创建流接口时,外设是以文件形式对应用程序开放的,所以需要提供设备文件。基于设备的能力,需要考虑是否允许多个应用同时访问设备文件。也就是说,考虑驱动是否可以在设备上重复打开。流接口驱动利用hOpenContext参数可以使用所有文件的IO功能,进而实现单独访问或者是重复访问。
对于重复访问而言,每一次调用XXX_Open(Device Manager)函数都需要放回一个不同的hOpenContext值。设备驱动必须追踪XXX_Open返回值中的那一个正在使用。接下来访问XXX_Close()、XXX_Read()、XXX_Write()、XXX_Seek()、XXX_IOControl()函数时将这些值写回设备而驱动,以使得驱动可以区分哪个内部数据结构将被操作。
对于单独访问而言,只需要开始访问XXX_Open函数时返回一个有效的hOpenContext即可。在XXX_Close调用之前这个值是有效的,在此时调用XXX_Open会返回NULL以表示执行失败。
为了实现Telephony API,必须拥有支持重复访问的串行设备。那些有Microsoft提供的使用上层串口实现的OEM会自动的获得此功能。

9.如果设备驱动需要流接口函数以外的功能,那么可以选择采用“用户IO控制代码”方式实现
流接口驱动的很多类型都是使用IO控制代码来实现它们的部分功能的。IO控制代码是一种常用的扩展流接口功能的方式。流接口驱动定义抽象的IO控制代码,而不管驱动将要实现何种目的。有些预定义的IO控制代码用于部分流接口驱动类型,如:块设备驱动、串口驱动和USB口驱动。如果为了流接口驱动定义了额外的IO控制代码,那么有义务需要将该代码的信息公布出来,这样应用程序开发者就可以充分利用你的设备驱动。
这些IO控制代码由XXX_IOControl函数中的参数dwCode传递。XXX_IOControl函数的其他参数提供IO控制代码所需的其他数据,这意味着其他参数对于不同的控制代码有不同的内容。

10.修改驱动的源代码以实现对应设备的电源管理驱动功能。由于预先已经创建了驱动,所以请跳至相关主题的第2步。
请参考《How to Add Power Management to a Device Driver》

11.确认驱动的入口点是否声明正确。这个函数既可以通过.Def文件声明也可以通过 extern "C" 声明。
电源管理驱动开发例子程序的.def文件位于%_WINCEROOT%/ Public /Common/Oak/ Drivers/ PM/ Test/ Devsample/ Pmdevsample.def。
关于extern "C"的信息请参考《流接口驱动实施》。

12.将驱动的注册表信息添加进Platform.reg文件。
例如,添加以下代码到Platform.reg以指定驱动对应的注册表信息。
#include "$(_winceroot)/platform/<your OS design>/drivers/<your driver name>/<your driver name>.reg"
Makeimg.exe使用注册表文件来建立运行镜像的注册表入口。
当冷启动设备时,Filesys.exe使用.reg文件来建立默认的注册表。Platform.reg确定了目标设备的硬件注册信息,Project.reg确定了基于WinCE执行文件的注册信息。
注册表文件的形式如下
[KEY1]
"ValueName1"={Value Type}:{data}
"ValueName2"={Value Type}:{data}
[KEY2]
"ValueName1"={Value Type}:{data}
...
采用以下方式可以指定一个缺省的数值名称
[KEY1]
@ = "default value name"

下述列表显示了可能的数值类型
值类型
形 式
REG_SZ
"my string"
REG_DWORD
双字: XXXX(16进制数值)
该类型通常采用16进制描述
REG_MULTI_SZ
multi_sz:"my string ","my string"
REG_BINARY
十六进制: XX,XX,XX,XX...
HEX
十六进制: XX,XX,XX,XX...
16进制形式需要和Windows 的注册表类型一致。
可以使用IF/ENDIF关键字。这样当环境变量被设置或等于某个定值时可以执行注册表设置。
在环境变量没有设置或不等于某个设定值的时候运行注册表设置,则需在行尾使用空格和感叹号(!)。
IF/ENDIF块是可以嵌套的。
IF/ENDIF关键字采用如下形式:
IF environment variable [= value] [!]
[KEY1]
"ValueName1"={Value Type}:{data}
"ValueName2"={Value Type}:{data}
[KEY2]
"ValueName1"={Value Type}:{data}
...
ENDIF
使用分号(;)表示数据的开始。

以下列表显示了可以在注册表中操作的任务
任 务
描 述
建立注册表入口
使用以下语句更新注册表文件
[Key1]
"ValueName"="Value Type"
删除注册表的Key
将短横线(-)放置在Key的名称前,格式如下
[-Key]
删除注册表值
将短横线(-)放置在值的等号后面,格式如下
"ValueName1"=-
例子:
下述代码例子显示了如何添加注册表入口以建立一个值为字符类型的Key。在例子中,如果IMGNOCONDEXAMPLE环境变量没有被设置,额外的子键和值被添加进注册表。
[HKEY_LOCAL_MACHINE/RegExample]
"MyValue"="MyString"
IF IMGNOCONDEXAMPLE !
[HKEY_LOCAL_MACHINE/RegExample/ConditionalSubKey]
"MyString"="This is a string"
ENDIF

备注:
当Makeimg,exe执行所有.reg文件创建单个文件时,复制入口会导致一个警告(在最终.reg文件、默认的.fdf文件、系统.hiv文件和用户.hiv文件存在重复入口)。

13.修改Platform.Bib文件以包含驱动。
例如,你可以将下面代码添加进Platform.bib文件的模式部分以指定驱动的位置。
MyDriver.dll $(_FLATRELEASEDIR)/<your driver name>.dll NK SH

二进制镜像建立文件
二进制镜像建立文件(.bib)确定了运行镜像所包含的模式和文件。Makimg.exe使用.bib文件来确定如何调用模块和文件进入目标设备的内存中。
下述列表显示了.bib文件包含的主要部分
部 分
描 述
MEMORY
确定物理内存的可用性,包括开始地址、大小、内存类型。
这个部分在Config.bib文件中,位于Platform/MYBSP/Files 目录下。
CONFIG
确定Romimage,exe的配置选项以定制其输出。默认情况下,这个部分在Config.bib文件中。然而,您可以不要求包含.bib文件的CONFIG部分。
MODULES
确定将由Romimage.exe加载进内存区域的目标模式。在MODULE部分中未被压缩的目标模式适当的执行。(Object modules that are not compressed in the MODULE section execute in place)
FILES
保存.bib文件的内存部分。
14.修改文件路径使得系统包含驱动。

15.从%_WINCEROOT%/Platform/<your OS design>/Drivers/<your driver name>中建立驱动。

16.在IDE中建立包含驱动的运行镜像文件

17.调试驱动代码
参见《How to Debug a Device Drive》
18.使用Windows CE 测试工具测试驱动
参见《How to Use the CETK to Test a Driver》

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: