当前位置:文档之家› WinCE驱动开发流程

WinCE驱动开发流程

wince驱动开发学习笔记嵌入式技术/walking_man 发表于2007-03-20, 20:03首先是wince驱动的分类问题。

按照书上讲的说CE下驱动分成单体驱动和分层驱动,而看到另一种说法是本机驱动和流式驱动。

经过microsun大哥的指点,把这两种分类法分开了。

在这里引用一下:“单体与分层只是从代码的形式上做的分类.分层驱动代码上分为PD D与MDD,一般的微软已经实现了MDD,可能也实现了PDD,我们只需要对PDD做些修改就能使用,比如音频的驱动,显示的驱动。

单层驱动是把PDD与MDD写在一起,没有做严格的区分,通常这种驱动比较简单,比如:ATADISK。

至于本地驱动和流式驱动是从驱动与系统其它模块(调用者)的接口形式上做的分类.其实,本地驱动这个名称不大恰当,可能叫专用驱动或其它名字更为合适.它是指调用它的模块给它有特定的接口,比如电源驱动和通用LED驱动。

而串口,网卡等就是流接口驱动程序. 所以,一个驱动程序可以是单体的流式驱动,例如:ATADISK.也可以是分层的流式: 如OHCI ”按照我的理解,单体和分层是驱动实现方式上的分类,而本地和流式则是驱动模型上的分类,所谓本地驱动就是操作系统有保留专门的接口,所谓流式是指编写的DLL文件里可以导出各种流式接口函数。

第二点:驱动的功能属性。

设备驱动程序是操作系统内核和硬件的接口,操作系统定义了一组标准的接口,编写驱动的过程也就是实现这些接口。

从应用程序到具体硬件间有如下这些环节起作用:应用程序-调用OS函数-操作系统-驱动接口-驱动程序-硬件操作函数-硬件。

在wince里驱动都以用户态的DLL存在,需要通过进程加载到slot里。

共有三类系统进程用来加载:Device.exe,GWES.exe,File Sys.exe.绝大多数设备驱动都是通过Device.exe加载的。

需要注意的是,不同的OS保留的设备驱动接口是不一样的,如桌面windows 和wince就不同。

第三点:wince下设备的初始化分为两个阶段:Device.exe的初始化;外设的枚举和加载。

其流程是:上电-启动bootloader-启动N K-启动注册表init键(Device.exe启动)-初始化数据结构,I/O,电源管理等-加载BusEnum.dll(总线枚举器)-枚举注册表下Driver/buil din的所有子键。

这里的枚举过程就是循环调用ActivateDeviceEx()函数加载驱动的过程。

在OS启动完毕后,我们可以用PB的Remot e Registry Tool查看H_L_M/drivers/active包含的子键,看哪些驱动随启动而加载。

第四点:流接口驱动的概念。

暴露流式接口函数的驱动即是流驱动,它把外设抽象成一个文件。

过程是:应用程序使用文件API 对设备进行访问,OS接受API调用FileSys.exe,转到device.exe,调用流接口,与硬件交互。

所谓流接口函数有十个,包括XXX_Init、XXX_Deinit、XXX_Open、XXX_Close、XXX_Read、XXX_Write、XXX_P owerUp、XXX_PowerDown、XXX_Seek、XXX_IOControl,在wince5.0中增加le了XXX_PreClose,XXX_PreDeinit.而我们在应用程序里对应的文件A PI有CreateFile、DeviceIoControl、 ReadFile、 WriteFile,CloseHandle,SetFilePointer.第五点:编写流驱动的步骤。

有两种实现途径:1。

写DLL,做成Project,加入到OS里。

2。

改BSP,把驱动写在BSP里,再选择那个BSP做OS。

第一种方法步骤是在PB中新建一个DLL项目,编写一些输入函数,寄存器,外设的声明,写DLLENTRY函数;实现流接口函数;编写DLL的导出函数文件.DEF;为驱动程序写入注册表项,还需要修改bib文件。

第二种方法就是在platform/BSP/dr ivers下新建一个目录,然后在drivers目录中的dirs文件中加入新建的目录名。

在新建的目录下,新建你的源代码文件,在其中实现DL L函数。

新建名称分别为sources, makefile, ***.def的文件;修改pl atform.reg和p latform.bib文件。

几个小知识点:(1)应用程序可以通过ActivateDeviceEx()加载设备驱动;(2)注册表里的设备前缀Prefix项应该用三个字母表示,驱动的索引是I ndex.如果应用程序用CreateFile()来打开驱动程序时,第一个参数应该是这个Prefix项加上Index的值。

(3)驱动程序中要用DMA,需要为其保留一段物理空间,就要修改config.bib给驱动程序共享数据用。

(4)查看驱动是否加载,可以用远程工具看注册表buildin/a ctive键,或者是看device.exe的进程是否包含DLL文件。

(5)DL L的入口函数名称默认是DllMain,但我们可以改成别的名称,在SOU RCES文件中加入这样一行,DLLENTRY=ABCD入口函数就被改成了ABCD,我们就应该实现名为ABCD的函数.(6)感觉写驱动无从下手的时候,可以尝试看现有的代码与平台无关驱动源码位于public\common\OAK\Drivers与平台相关驱动platform\{bsp}\srv\Drivers基础知识:1)系统调用是操作系统内核和应用程序之间的接口,设备驱动程序是操作系统内核和机器硬件之间的接口。

设备驱动程序为应用程序屏蔽了硬件细节,在应用程序看来硬件只是一个设备文件,应用程序可以像操作普通文件一样对硬件设备进行操作。

设备驱动是内核的一部分。

2)驱动程序完成以下功能:——对设备初始化和释放;——把数据从内核传送到硬件和从硬件读取数据;——读取应用程序传送给设备文件的数据和回送应用程序请求的数据;——检测和处理设备出现的错误。

3)上层应用程序运行在用户模式(非特权模式,Ring 3),代码被严格约束执行。

如不能执行硬件IO指令。

所有的这些被阻止的操作如果想运行必须通过陷阱门来请求操作系统内核。

4)操作系统内核运行在内核模式(特权模式,Ring 0),可以执行所有有效的CPU指令。

包括IO操作,可访问任何内存区。

5)整个硬件系统资源在驱动程序面前是赤裸裸的,驱动可以使用所有系统资源,编写驱动程序时我们必须格外小心驱动代码的边界条件,确保它们不会损坏整个操作系统。

2、Windows支持的驱动:1)虚拟设备驱动程序(Virtual Device Driver):Windows3.1(Windows95/98/Me)2)内核模式驱动程序(Kernel Mode Driver):Windows NT3)Win32驱动程序模型(Win32 Driver Mode):从Windows98开始使用。

其中WDM是目前主流,然而在WinCE系统中,由于硬件资源有限和嵌入式系统的特点,对其的支持非常有限。

3、WinCE系统驱动简介:1)WinCE毕竟是一个嵌入式系统,有其自身的特殊性,为了提高运行效率,所有驱动皆为动态链接库,驱动实现中可以调用所有标准的API。

而在其他Windows系统中可能的驱动文件还有.vxd,.sys 和动态链接库。

2)WinCE驱动从结构上讲分为本地驱动(Native Driver)和流接口驱动(Stream Driver)。

——本地驱动主要用于低级、内置的设备。

实现它们的接口并不统一,而是针对不同类型的设备相应设计。

因此开发过程相对复杂,没有固定的模式,一般做法是通过移植、定制现有的驱动样例来实现。

——流接口驱动是最基本的一种驱动结构,它的接口是一组固定的流接口函数,具有很高的通用性,WinCE的所有驱动程序都可以通过这种方式来实现。

流接口驱动程序通过文件系统调用从设备管理器和应用程序接收命令。

该驱动程序封装了将这些命令转换为它所控制的设备上的适当操作所需的全部信息。

流接口驱动是动态链接库,由一个叫做设备管理程序的特殊应用程序加载、管理和卸载。

与本地驱动程序相比,所有流接口驱动程序使用同一组接口函数集,包括实现函数:XXX_Init、XXX_Deinit、XXX_Open、XXX_Close、XXX_Read、XXX_Write、XXX_PowerUp、XXX_PowerDown、XXX_Seek、XXX_IOControl,这些函数与硬件打交道。

用户函数:CreateFile、DeviceIoControl、ReadFile、WriteFile,这些函数方便用户使用驱动程序。

3)WinCE下驱动的加载方式:——通过GWES(Graphics, Windowing, and Events Subsystem):主要加载与显示和输入有关的驱动,如鼠标、键盘驱动等。

这些驱动一般为本地驱动。

——通过设备管理器:两种结构的驱动都加载,加载的本地驱动主要由PCMCIA HostController,USBHost Controller driver,主要是总线类的驱动;流接口驱动主要有音频驱动,串并口驱动。

——动态加载:前两者都是系统启动时加载的,动态加载则允许设备挂载上系统时将驱动调入内核,主要有外接板卡驱动,USB设备驱动等。

4、流接口驱动函数介绍:1)DWORD XXX_Init(LPCTSTR pContext, LPCVOID lpvBusContext);pContext:指向一个字符串,包含注册表中该流接口活动键值的路径lpvBusContext:该函数是驱动挂载后第一个被执行的。

主要负责完成对设备的初始化操作和驱动的安全性检查。

由ActiveDeviceEx通过设备管理器调用。

其返回值一般是一个数据结构指针,作为函数参数传递给其他流接口函数。

2)BOOL XXX_Deinit(DWORD hDeviceContext);hDeviceContext:XXX_Init的返回值。

整个驱动中最后执行。

用来停止和卸载设备。

由DeactivateDevice触发设备管理器调用。

成功返回TRUE。

3)DWORD XXX_Open(DWORD hDeviceContext, DWORD AccessCode , DWORD ShareMode);hDeviceContext:XXX_Init的返回值。

AccessCode:访问模式标志,读、写或其他。

ShareMode:驱动的共享方式标志。

打开设备,为后面的操作初始化数据就够,准备相应的资源。

应用程序通过CreateFile函数间接调用之。

相关主题