WinCE7.0的驱动编写和加载


最近开始写 WinCE6.0 的驱动,当然从最简单的流驱动开始,选择了 GPIO 的驱动进行实验。本文参考了网上有很多流驱动的开发资料,但在开发的过程中也发现了一些细节问题,网络上并没有给出详细的解答,所以在这里记录下来,并对流驱动开发中的一些问题做了总结。
         流驱动的开发有两种方法:添加驱动到BSP和借助驱动调试助手。
         第一种,添加驱动到BSP修改BSP,将驱动加入到BSP当中,再选择该BSP当做OS下载到目标板上。下面以6410下实现GPIO为例,说明详细的步骤:
         首先,在\WINCE600\PLATFORM\SMDK6410\SRC\DRIVES目录下面创建文件夹,命名为GPIO,并在GPIO文件夹下面创建源代码文件,命名为gpio.c。同时在DRIVES目录下修改dirs文件,在dirs文件最后添加新建的目录名GPIO。在gpio.c文件中实现的流式接口函数如下(这些接口函数的参数介绍见博文最后):
BOOL WINAPI DllEntry(HANDLE hInstDll, DWORD dwReason, LPVOID lpvReserved)
DWORD GPI_Init(LPCTSTR PContext, LPCVOID lpvBuscontext)
BOOL GPI_Deinit(DWORD hDeviceContext)
DWORD GPI_Open(DWORD hDeviceContext, DWORD AccessCode, DWORD shareMode)
BOOL GPI_Close(DWORD hOpenContext)
DWORD GPI_Read(DWORD hOpenContext, LPVOID pBuff, DWORD Count)
DWORD GPI_Write(DWORD hOpenContext, LPVOID pBuff, DWORD Count)
DWORD GPI_Seek(DWORD hOpenContext, long Amount, WORD Type)
void GPI_PowerUp(DWORD hDeviceContext)
void GPI_PowerDown(DWORD hDeviceContext)
BOOL GPI_IOControl(
                                        DWORD hOpenContext,
                                        DWORD dwCode,
                                        PBYTE pBufIn,
                                        DWORD dwLenIn,
                                        PBYTE pBufOut,
                                        DWORD dwLenOut,
                                        PDWORD pdwactualOut
                                        )
         其次,在GPIO文件夹下面创建gpio.def文件,定义需要输出的函数,这些函数能够被其它代码用动态加载的方法调用。具体内容如下,有的介绍里面导出的函数中还有EntryDll,其实没有必要,它是一个入口函数而已,主要导出那些会被调用的就可以了。
LIBRARY     GPIO
EXPORTS GPI_Init
    GPI_Deinit
    GPI_Open
    GPI_Close
    GPI_Read
    GPI_Write
    GPI_Seek
    GPI_PowerDown
    GPI_PowerUp
GPI_IOControl
再次,在GPIO文件夹下面创建makefile文件,具体内容如下,这一步对于不同的流驱动基本不变。
!INCLUDE $(_MAKEENVROOT)\makefile.def
         接下来,在GPIO文件夹下面创建sources文件,具体内容如下,各个宏的意义不做详细介绍,也可以添加其他的一些宏,根据具体情况定。
WINCEOEM=1
TARGETNAME=GPIO
TARGETTYPE=DYNLINK
RELEASETYPE=PLATFORM
DEFFILE=gpio.def
DLLENTRY=DllEntry
TARGETLIBS= \
    $(_SYSGENSDKROOT)\lib\$(_CPUINDPATH)\coredll.lib
SOURCES=gpio.c
第五步,修改注册表信息了,打开WINCE600\PLATFORM\SMDK6410\FILES\Platform.reg 文件,添加以下内容:
[HKEY_LOCAL_MACHINE\Drivers\BuiltIn\GPIO]
"Prefix"="GPI"
"Dll"="GPIO.Dll"
"Index"=dword:1
"Order"=dword:1
这里要注意添加的时候不要添加到带有条件编译的语句当中去,否则还需要设置编译条件,比较麻烦。
最后,修改Platform.bib 文件,将GPIO驱动加载到NK当中。打开WINCE600\PLATFORM\SMDK6410\FILES\Platform.bib 文件,添加以下内容,
GPIO.dll     $(_FLATRELEASEDIR)\GPIO.dll     NK SH
到这里基本上准备工作就已经完成了,接下来编译,下载到目标板上。之后可以用调试工具查看驱动是否已经成功加入到注册表中,还有驱动是否被OS成功加载了。上述正确后,就可以编写上层测试代码进行验证了。
 
上述的步骤基本和网络的介绍一致,在调试过程中,遇到了以下两个问题:
1、驱动信息已经加入到注册表中,但是NK总是没有加载成功GPIO.dll驱动?
解决:出现这种情况,有可能是一下原因造成的:(1)没有实现上面提到的全部的流驱动接口函数,只是实现了其中的一部分,只要补齐所有的驱动接口函数就可以了;(2)在修改Platform.bib文件时,在文件末尾添加的内容。应该在宏FILES前面添加内容,否则就会无法加载驱动了。也有可能是其他原因,本人暂时没有遇到。
2、驱动加载后立马又被卸载?
解决:本人在调试过程中,通过串口输出信息,发现驱动GPIO被加载后立马又被卸载了,并且调用了GPI_Init函数,后来发现时由GPI_Init的返回值引起的。GPI_Init函数是驱动成功加载后调用的第一个函数,设备管理器通过调用GPI_Init初始化硬件,分配自己的内存空间,并将此内存块的地址以一个DWORD值返回给上层。如果返回0,说明初始化失败,之前分配的系统资源将全部释放,也就是驱动会被卸载。在简单的输出信息的流驱动中,最好将所有的流接口都设置为返回成功。
 
快速编译技巧:上面的方法要求每次都重新编译内核,很耗费时间,这里收集了网络上提供的修改驱动后快速编译的方法,下面的步骤建立在已经进行过一次上面的操作了,否则必须先修改注册表和.bib文件:
1)在VS2005Build菜单选择“Open Release Directory in Build Window”,进入到命令行模式,在命令行中进入到你的驱动目录,执行build命令就OK了。其实也可以直接在右侧“Solution Explorer”中找到你的驱动目录,右键选择Build就可以了。
2)在VS2005Build菜单选择“Make Run-Time Image”就可以产生NK文件了。
第二种,使用串口助手调试,这里给出原创的连接we-hjbBLOG 该方法将会比第一种方法效率高,不需要每次都编译NK,然后下载镜像到目标板,但存在适用范围的问题,即该方法并不是适用于任何的驱动。驱动调试助手,是用来动态管理流驱动。本地驱动和USB驱动不再它的控制范围之内,各位在使用时注意这一点。
 
补充流接口函数介绍(转自网络):
DllEntry(HINSTANCE DllInstance, INT Reason, LPVOID Reserved )
这个函数是动态链接库的入口,每个动态链接库都需要输出这个函数,它只在动态库被加载和卸载时被调用,也就是设备管理器调用LoadLibrary而引起它被装入内存和调用UnloadLibrary将其从内存释放时被调用,因而它是每个动态链接库最早被调用的函数,一般用它做一些全局变量的初始化。
参数:
DllInstance:DLL的句柄,与一个EXE文件的句柄功能类似,一般可以通过它在得到DLL中的一些资源,例如对话框,除此之外一般没什么用处。
Reason:
一般我们只关心两个值:DLL_PROCESS_ATTACH与DLL_PROCESS_DETACH,Reason等于前者是动态库被加载,等于后者是动态库被释放。
所以,我们可以在Reason等于前者是初始化一些资源,等于后者时将其释放。
    DWORD XXX_Init( LPCTSTR pContext, LPCVOID lpvBusContext);它是驱动程序的动态库被成功装载以后第一个被调用的函数。其调用时间仅次与DllEntry,而且,当一个库用来生成多于一个的驱动程序实例时仅调用一次DllEntry,而xxx_Init会被调用多次。驱动程序应当在这个函数中初始化硬件,如果初始化成功,就分配一个自已的内存空间(通常用结构体表示),将自已的状态保存起来,并且将此内存块的地址做为一个DWORD值返回给上层。设备管理器就会用在调用XXX_Open时将此句柄传回,我们就能访问自已的状态。如果初始化失败,则返回0以通知这个驱动程序没有成功加载,先前所分配的系统资源应该全部释放,此程序的生命即告终至。当这个函数成功返回,设备管理器对这个程序就不做进一步处理,除非它设置了更多的特性。至此一个各为XXX的设备就已经加载成功,当用户程序调用CreateFile来打开这个设备时,设备管理器就会调XXX_Open函数。参数:pContext:系统传入的注册表键,通过它可以讲到我们在注册表中设置的配置信息。lpvBusContext:一般不用。实际上,很多程序中将这个函数写成了DWORD XXX_Init( DWORD pContext ),我们只需要将pContext转化成LPCTSTR即可。
DWORD XXX_Open(DWORD hDeviceContext,DWORD dwAccess, DWORD dwShareMode);当用户程序调用CreateFile打开这个设备时,设备管理器就会调用此驱动程序的XXX_Open函数。参数:hDeviceContext XXX_Init 返回给上层的值,也就是我们在XXX_Init中分配的用来记录驱动程序信息的那个结构体的指针,我们可以在这个函数中直接将其转化成所定义的结构,从而获取驱动程序的信息。dwAccess 上层所要求的访问方式,可以是读或者写,或者是0,即不读也不写。dwShareMode 上层程序所请求的共享模式,可以是共享读、共享写这两个值的逻辑或,或者是0,即独占式访问。系统层对设备文件的存取权限及共享方法已经做了处理,所以在驱动程序中对这两个参数一般可以不用理会。这个函数一般不用做太多处理,可以直接返回hDeviceContext表示成功,对于一个不支持多个用户的硬件,在设备已经打开后,应该总是返回0以至失败,则CreateFile调用不成功。
DWORD XXX_Close(  DWORD hDeviceContext );      当用户程序调用CloseHandle关闭这个设备句柄时,这个函数就会被设备管理器调用。参数:hDeviceContext 为XXX_Open返回给上层的那个值。这个函数应该做与XXX_Open相反的事情,具体包括:释放XXX_Open分配的内存,将驱动程序被打开的记数减少等。
DWORD XXX_Deinit( DWORD hDeviceContext );这个函数在设备被卸载时被调用,它应该实现与XXX_Init相反的操作,主要为释放前者占用的所有系统资源。参数:hDeviceContext XXX_Init函数返回给上层的那个句柄u       void XXX_PowerUp(  DWORD hDeviceContext );
void XXX_PowerDown(DWORD hDeviceContext );正如其名称中体现的那样,这两个函数在系统PowerUp与PowerDown时被调用,这两个函数中不能使用任何可能引起线程切换的函数,否则会引起系统死机。所以,在这两个函数中,实际上几乎是什么做不了,一般在PowerDown时做一个标志,让驱动程序知道自已曾经被Power Down过。在Power Down/On的过程中硬件可能会掉电,所以,尽管Power On以后,原来的IO操作仍然会从接着执行,但可能会失败。这时,当我们发现一次IO操作失败是因为程序曾经进入过Power Down状态,就重新初始化一次硬件,再做同样的IO操作。
BOOL XXX_IOControl(DWORD hDeviceContext,DWORD dwCode, PBYTE pBufIn,  DWORD dwLenIn, PBYTE pBufOut, DWORD dwLenOut, PDWORD pdwActualOut );几乎可以说一个驱动程序的所有功能都可以在这个函数中实现。对于一类CE自身已经支持的设备,它们已经被定义了一套IO操作定,我们只需按照各类设备已经定义的内容去实现所有的IO操作。但当我们实现一个自定义的设备时,我们就可以随心所欲定义我们自已的IO操作。参数:hDeviceContext XXX_Open返回给上层的那个句柄,即我们自已定义的,用来存放程序所有信息的一个结构。dwCode IO操作码,如果是CE已经支持的设备类,就用它已经定义好码值,否则就可以自已定义。pBufIn 传入的Buffer,每个IO操作码都会定义自已的Buffer结构dwLenIn pBufIn以字节记的大小 pBufOut,dwLenOut分别为传出的Buffer,及其以字节记的大小pdwActualOut 驱动程序实际在pBufOut中填入的数据以字节记的大小其中,前两个参数是必须的,其它的任何一个都有可能是NULL或0。所以,当给pdwActualOut赋值时应该先判断它是否为一个有效的地址。

本文出自 “飞雪待剑” 博客,请务必保留此出处http://jazka.blog.51cto.com/809003/583199

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ATHEROS The Licensed Software includes software developed by Atheros Communications, Inc. (“Atheros”). You must separately obtain rights beyond evaluation and demonstration in connection with the Licensed Software from Atheros. ARM The Licensed Software may include software developed by ARM, Ltd. The software may only be used with an ARM microprocessor, which includes the Freescale i.MX and MXC product lines. CODEC STANDARDS This software includes codec standards for encoding and decoding audio and visual content. You are not licensed for any implementation or distribution of the technology in any commercial product or service such as runtime images that you develop using this software. You are responsible for determining and securing these license rights. CSR The Licensed Software includes software and hardware developed by Cambridge Silicon Radio, Inc. (“CSR”). You must separately obtain rights beyond evaluation and demonstration in connection with the Licensed Software from CSR. AVC/H.264 VISUAL STANDARD. This software may include AVC/H.264 video decoding technology, MPEG LA, L.L.C. requires this notice: THIS PRODUCT IS LICENSED UNDER THE AVC/H.264 PATENT PORTFOLIO LICENSES FOR THE PERSONAL AND NON-COMMERCIAL USE OF A CONSUMER TO (A) ENCODE VIDEO IN COMPLIANCE WITH THE AVC/H.264 STANDARD (“AVC/H.264 VIDEO”) OR (B) DECODE AVC/H.264 VIDEO THAT WAS ENCODED BY A CONSUMER ENGAGED IN A PERSONAL AND NON-COMMERCIAL ACTIVITY AND/OR WAS OBTAINED FROM A VIDEO PROVIDER LICENSED TO PROVIDE AVC/H.264 VIDEO. NO LICENSE IS GRANTED OR WILL BE IMPLIED FOR ANY OTHER USE. If you have questions about the AVC/H.264 visual standard, please contact MPEG LA, L.L.C., 250 Steele Street, Suite 300, Denver, Colorado 80206; www.mpegla.com. MPEG-2 VISUAL STANDARD. This software includes MPEG-2 visual decoding technology. MPEG LA, L.L.C. requires this notice: USE OF THIS PRODUCT IN ANY MANNER THAT COMPLIES WITH THE MPEG 2 VISUAL STANDARD IS PROHIBITED, EXCEPT FOR USE DIRECTLY
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值