WINCE驱动程序快速入门

有人也许和我一样比较心急,想尽快知道如何去写一个具体的驱动程序,这里,假设您对驱动程序已经有比较好的了解,告诉大家一个快速上路的方法。当然,如果您有足够的时间我建议在动手之前还是深入了解一下CE整个系统架构。
在CE中,最简单的一个驱动程序莫过于一个内置(Built-in)设备的流接口驱动。对于一个不支持热拔插的设备,最快捷的方法就是为其实现一个内置的流接口的驱动。
对于这样一类驱动程序,我们只需要按一种特定的规则实现一个动态库,其中实现对所有的硬件功能的调用,再将这个动态库加入系统中,然后设置相关的注册表项,使得在系统启动时设备管理器能识别并且加载这个设备即可。
3.1               实现动态链接库
此动态链接库与应用程序层所用的库并不很大差别,源文件可以是C、C++、甚至汇编,,只是它要实现以下函数。
l         DllEntry(HINSTANCE DllInstance, INT Reason, LPVOID Reserved)
这个函数是动态链接库的入口,每个动态链接库都需要输出这个函数,它只在动态库被加载和卸载时被调用,也就是设备管理器调用LoadLibrary而引起它被装入内存和调用UnloadLibrary将其从内存释放时被调用,因而它是每个动态链接库最早被调用的函数,一般用它做一些全局变量的初始化。
 
参数:
DllInstance:DLL的句柄,与一个EXE文件的句柄功能类似,一般可以通过它在得到DLL中的一些资源,例如对话框,除此之外一般没什么用处。
Reason:
一般我们只关心两个值:DLL_PROCESS_ATTACH与DLL_PROCESS_DETACH,Reason等于前者是动态库被加载,等于后者是动态库被释放。
所以,我们可以在Reason等于前者是初始化一些资源,等于后者时将其释放。
l        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即可。 l        DWORD XXX_Open(DWORD hDeviceContext,DWORD dwAccess, DWORD dwShareMode);当用户程序调用CreateFile打开这个设备时,设备管理器就会调用此驱动程序的XXX_Open函数。参数:hDeviceContext XXX_Init 返回给上层的值,也就是我们在XXX_Init中分配的用来记录驱动程序信息的那个结构体的指针,我们可以在这个函数中直接将其转化成所定义的结构,从而获取驱动程序的信息。dwAccess上层所要求的访问方式,可以是读或者写,或者是0,即不读也不写dwShareMode 上层程序所请求的共享模式,可以是共享读、共享写这两个值的逻辑或,或者是0,即独占式访问。系统层对设备文件的存取权限及共享方法已经做了处理,所以在驱动程序中对这两个参数一般可以不用理会。这个函数一般不用做太多处理,可以直接返回hDeviceContext表示成功,对于一个不支持多个用户的硬件,在设备已经打开后,应该总是返回0以至失败,则CreateFile调用不成功。 l        DWORD XXX_Close(  DWORD hDeviceContext );     当用户程序调用CloseHandle关闭这个设备句柄时,这个函数就会被设备管理器调用。参数:      hDeviceContext 为XXX_Open返回给上层的那个值。      这个函数应该做与XXX_Open相反的事情,具体包括:释放XXX_Open分配的内存,将驱动程序被打开的记数减少等。 l        DWORD XXX_Deinit( DWORD hDeviceContext );       这个函数在设备被卸载时被调用,它应该实现与XXX_Init相反的操作,主要为释放前者占用的所有系统资源。参数:       hDeviceContext XXX_Init函数返回给上层的那个句柄l        void XXX_PowerUp( DWORD hDeviceContext );l        void XXX_PowerDown(DWORD hDeviceContext );      正如其名称中体现的那样,这两个函数在系统PowerUp与PowerDown时被调用,这两个函数中不能使用任何可能引起线程切换的函数,否则会引起系统死机。所以,在这两个函数中,实际上几乎是什么做不了,一般在PowerDown时做一个标志,让驱动程序知道自已曾经被Power Down过。在Power Down/On的过程中硬件可能会掉电,所以,尽管Power On以后,原来的IO操作仍然会从接着执行,但可能会失败。这时,当我们发现一次IO操作失败是因为程序曾经进入过Power Down状态,就重新初始化一次硬件,再做同样的IO操作。l        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赋值时应该先判断它是否为一个有效的地址 3.2注册表设置
l         在注册表中添加如下项目。(一般放在Platform.reg)
[HKEY_LOCAL_MACHINE\Drivers\BuiltIn\SampleDev]
   "Prefix"="XXX"
   "Dll"="MyDev.Dll"
   "Order"=dword:1
 
l         在BIB文件中添加项目,将所用到的文件加入BIN文件(一般放在Platform.bib)。
MyDev.dll      $(_FLATRELEASEDIR)\MyDev.dll       NK SH
l         注:
SampleDev为任意与其它项目不重名的字符串.
每个函数名的前缀XXX可以是任意大写的字符串,只要保证与注册表中Prefix后面的值相同就行。
3.3编译程序
       现在,已经知道了需要实现哪些东西,一定想知道如何去实现它。一个最直接的方法就是在platform/BSP/drivers 下新建一个目录,然后在drivers目录中的dirs文件中加入以你刚新建的目录名。
       在刚新建的目录下,新建你的C源代码文件,在其中实现上面所述的函数,及其功能。新建名称分别为sources, makefile, mydev.def的文件。其内容如下:
       makefile: 只需要这样一行
!INCLUDE $(_MAKEENVROOT)\makefile.def
 
mydriver.def文件定义需要输出的函数,这些函数能够被其它代码用动态加载的方法调用。格式:
 
LIBRARY       MyDev(这个字符串要和将要生成的动态库的文件名一样)
 
EXPORTS
       XXX_Init
       XXX_Deinit
       XXX_Open
       XXX_Close
       XXX_PowerOff
       XXX_Power_Down
       XXX_IOControl
Sources:这个文件很重要,内容也多,最基本的一个文件该有如下内容。
 
TARGETNAME= MyDev(指定要生成的动态库的名称)
TARGETTYPE=DYNLINK(指定要生成的是一个动态库)
(下面两项指定需要与哪些动态库链接,一般要第一项就足够了)
TARGETLIBS=$(_COMMONSDKROOT)\lib\$(_CPUINDPATH)\coredll.lib
SOURCELIBS= $(_COMMONOAKROOT)\lib\$(_CPUINDPATH)\ceddk.lib \
 
DEFFILE=MyDev.def (指定def文件)
 
DLLENTRY=DllEntry(指定动态库的入口函数)
 
SOURCES=(请在这写上你所有源文件的名字,它们将会被编译)
 
 
       好了,现在万事俱备,只剩编译啦。
 
3.4用一个Project文件来编译出驱动程序库文件
如果您在用CE5.0,那用一个Project来构造一个驱动程序将是一个不错的选择。即在新建一个Project时设置其类型为DLL,其它设置根据提示即可。并且可以将注册表设置放在Project所在文件夹。
3.5基本调试方法
一般驱动程序可以用DEBUG版来调试,也可以用输出调试信息的方法。我们一般用这两个函数输出调试信息:RETAILMSG和 DEBUGMS,后者只能在DEBUG版中输出,而前者在RELEASE和DEBUG版中都可以输出,而且,可以在系统运行时刻根据Debug Zone选择让DEBUGMSG输出哪些调试信息。
驱动程序的调试一般可以分为以下几步:
1.看驱动程序的DllEntry是否被调用。如果这个函数被调用,说明驱动程序的文件已经在CE的image中,而且与注册表中设置的文件名相同。
2.看Init 函数是否被调用。如果它被调用,刚说明注册表设置正确。如果它没有被调用,一般是因为注册表中的Prefix设置与Init函数前面那三个字符不相同。或者def文件中没有定义Init函数。如果这个函数能够被调用,但驱动程序还是不能正确加载,请详细检查代码。

本文来自CSDN博客,转载请标明出处:http://blog.chinaunix.net/uid-1818867-id-2835874.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/436455.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【转】Azure Az-900认证 04——-考取AZ900所有知识点总结--获取证书!

结合最近所做的模拟题,把一些容易考的知识和概念重新回顾记录一下。标红的字要注意一下,有可能这几个简单的字,就是最能概括这个概念的关键点,个人在回顾的时候把这些点红色标出来了,会在题干中以不同的案例形式来考察…

怎么用vc采集ni卡数据_8bit,200MS/s 低成本模拟输入高速采集卡FCFR-PCI9850

FCFR-PCI98508bit,200MS/s 低成本模拟输入高速采集卡FCFR-PCI9850(简称PCI9850)是低成本高速数字化化仪,AD分辨率8bit,AD采样率200MS/s,硬件FIFO缓存32M字节,采集卡支持50MS/s的高速连续采集,触…

网站程序安全分析器 VB源码

本程序通杀:ASP ASPX PHP CGI JSP VBS 等脚本WebShell并能查出99%加密过的脚本WebShell后来发现..精度越高误杀越高...基本做到宁误扫三千不放过1马~其实是利用串判断.原理很简单.有很多人向偶要代码.想到人家ScanWebshell都贡献出来了~偶要是不贡献出来就不厚道咯.以下是全部代…

S3C6410启动模式介绍

目前的ARM处理器都支持多种启动模式,S3C6410和以前的Samsung的ARM处理器一样,通过外部管脚OM[4:0]的拉高拉低来决定是从哪个存储设备上启动。我认为S3C6410的User Manual并没有说的很清楚,所以我在最开始使用的时候,也对其启动模式…

如何用木板做桥_如何辨别使用的公园椅是否需要保养

如何辨别使用的公园椅存在哪些问题新城市公园椅小编与您分享,每一项事物都会有它的使用寿命,公园椅也不例外。公园椅使用有几年后后,我们通过公园椅的哪些表现来发现公园椅存在哪些隐患呢?通过观察、触摸、按压这三种方式来发现公…

密码学概述

时间点: 公元前400年,希腊人发明了置换密码; 1881年,世界上第一个电话保密专利出现; 二战期间,德国军方启用“恩尼格玛”密码机; 1976年,由于对称加密算法已经不能满足需要&#…

【转】关于医疗术语 CT,MR,DR,CR,DSA 等

医疗术语解释: Digital Radiography (CR, DX) :数字X线摄影 Mammography (MG):乳房X射线照相术 Computed Tomography (CT):计算机断层扫描 Magnetic Resonance (MR):磁共振 Positron Emission Tomography PET-CT …

c语言删除文件remove_Python中的文件和目录操作

对于文件和目录的处理,虽然可以通过操作系统命令来完成,但是Python语言为了便于开发人员以编程的方式处理相关工作,提供了许多处理文件和目录的内置函数。重要的是,这些函数无论是在Unix、Windows还是Macintosh平台上,…

漏洞:Client ReDos From Regex Injection

漏洞描述: 扫描漏洞如下:代码: // In IE6, the hash fragment and search params are incorrect if the // fragment contains ?. getSearch: function() { var match this.location.href.replace(/#.*/, ).match(/\?./); …

【转】mysql 、oracle中char和varchar以及varchar2的区别

mysql char是固定长度,varchar是可变长度的,varchar2是oracle特有的。 char定长存储,速度快,但是存在一定空间的资源浪费,适用于存储字段不是很大、对速度要求高的场合。速度快是因为在物理上是按照定长存储的,这样就…

WinCE Boot方式及 Bootloader架构概述

Bootloader的概念就是一个用于引导的loader,在系统上电的时候最先被运行,然后对硬件平台做最基本的初始化,最后把操作系统加载起来。不同的嵌入式操作系统都有自己的Bootloader,但是本质功能都是一样的。 在WinCE中用的最多的就是…

静物摄影用光技巧_摄影技巧:摄影如何用光?摄影大师总结的10点,非常受用!...

点击上方蓝字关注「摄影技巧入门教程」ID:sheying116找到右上角点击?... 设为星标/置顶 丨摄影技巧丨丨摄影入门丨丨摄影教程丨丨摄影图片丨摄影技巧:光线的运用在摄影中至关重要,但很多摄影新手却不知道该如何用光,今天我们就来…

Python如何创建相同值的数组/列表

题目要求 现在有这样的一个需求:创建一个数组或列表,列表中的所有值是相同的。 解决方法 找到两种解决方法,第一种是使用Python的基础语法,第二种是借助numpy包提供的函数实现。分别为大家进行介绍。 方法一:使用P…

【转】肺小结节就诊指南:4种CT的区别及如何选择?

又到医院体检的季节,胸外科医师又要忙着给本院同事看片子了。目前体检查出的早期肺癌越来越多,主要归功于CT检查的普及,相较于X-ray胸片,CT对肺内小结节,特别是小于1cm的结节诊断率更高。因此,要提高早期肺…

CTL_CODE说明

我们在说DeviceIoControl函数时其第二个参数dwIoControlCode就是由CTL_CODE宏定义的,下边我们可以了解一下CTL_CODE的内容。CTL_CODE:用于创建一个唯一的32位系统I/O控制代码,这个控制代码包括4部分组成:DeviceType(设…

修改Linux主机名和IP

问题描述 又到了例行的系统安全测试时间,公司部署的一套系统需要做安全测试了,首先要做主机渗透,显然不可能在正式环境直接测,于是就把几台服务器做了个镜像,作为测试环境。 现在问题是,测试环境的ip要修…

可以获得索引值码_搜索引擎优化最适合什么样子的工作?

有些人一直在学习搜索引擎优化,并一直想学习搜索引擎优化。这里是一个关于搜索引擎优化职位的简要介绍。1、 搜索引擎优化的位置是什么?随着电子商务产业的发展,搜索引擎优化的地位越来越重要。它主要负责优化网页的自然排名,这与…

【转】医学图像之DICOM格式解析

最近导师给安排了新任务,由于刚进入实验室,对于医学图像这一块还一知半解,所以就想分享一下有关医学常见影像的学习资料(尤其是dicom后缀的图像文件),欢迎大家一起交流。 目录 1.医学影像学的介绍 2.DICOM信息的简介 3.DICOM内…

DeviceIoControl的使用说明

应用程序和驱动程序的通信过程是:应用程序使用CreateFile函数打开设备,然后用DeviceIoControl与驱动程序进行通信,包括读和写两种操作。还可以用ReadFile读数据用WriteFile写数据。操作完毕时用CloseHandle关闭设备。我们比较常用的就是用Dev…

多元有序logistic回归分析_一文详述:观察性研究中的logistic回归分析思路

本文内容来自《中华流行病学杂志》2019年第40卷第8期,作者为冯国双教授,原题目为《观察性研究中的logistic回归分析思路》。将这篇文章分享给医咖会的伙伴们,希望大家能从领域大咖的见解中有所收获,指导医学研究之路。&#xff08…