we-hjb的BLOG

嵌入式.WINDOWS EMBEDDED CE...

常用链接

统计

积分与排名

最新评论

Windows CE下流驱动的动态加载

    我想很多WinCE的开发人员,尤其是刚入门并且做驱动开发的工程师,都曾碰到这样一个问题,要编写一个外围设备的驱动,拿最简单的GPIO驱动来说,编写驱动本身可能只花了一会儿功夫,可要把编译生成的DLL打包到先前做好的操作系统映像当中,最简单也得MakeImg一下,还要修改BIB文件、注册表文件,以让系统启动的时候就加载该驱动,所有工作都做完了,还得花几分钟下载整个操作系统到内存去运行,这也得要个好几分钟。能力强的人一次成功,不走回头路也就算了。如果驱动编写得有问题,那又得改代码,重新编译,把刚刚所做的事情再做一遍。说出来不怕大家笑话,我刚开始做驱动时就这样,反反复复,半天下来,才调试好一个简单的驱动。而事实上很大一部分时间都浪费在重复操作上。这种调试驱动的方法实在效率太低了。想到Linux下面的驱动调试,多方便!直接INSMOD一下,应用程序就可以调用,出现问题就RMMOD,根本无须来回倒腾操作系统的映像文件。那么,WinCE下难道就没有这么简便的方法嘛?答案是肯定的。

       闲话少说,进入正题。查找EVC的帮助,发现函数ActivateDevice()可用来加载驱动程序。而这个函数的使用是相当简单的。我就不多说了,贴上一段帮助最能说明问题。当然,你也可以用ActivateDeviceEx()。

HANDLE ActivateDevice (

LPCWSTR lpszDevKey,

DWORD dwClientInfo

);

Parameters

lpszDevKey

[in] Pointer to the registry path string of the device's driver key under HKEY_LOCAL_MACHINE. A driver key contains the DLL name, the device prefix, friendly name, and other device information.

dwClientInfo

[in] Data that will be stored in the device's Active key in the ClientInfo value. The registry path to the driver's Active key is passed in as the context parameter to the device's XXX_Init function. The value in dwClientInfo is stored in the registry before XXX_Init is called.

Return Values

On success, ActivateDevice returns a handle to the device that can be used in subsequent calls to DeactivateDevice.

Remarks

This function is superseded by ActivateDeviceEx.

ActivateDevice loads a device driver. ActivateDevice reads the registry key specified in lpszDevKey to get the DLL name, device prefix, index, and other values. Next it adds the device to the active device list in the registry branch HKEY_LOCAL_MACHINE\Drivers\Active, and stores the relevant values there. If no device index was specified in the key named in lpszDevKey, then it assigns a free index. Then it loads the device driver DLL in the process space of the Device Manager. Then it broadcasts a WM_DEVICECHANGE message for the new device and triggers a NOTIFICATION_EVENT_DEVICE_CHANGE event in the application notification system to notify applications of the presence of the new device.

从上面的描述中可以看到,在使用该函数时,我们只要给出第一个参数就可以,而这个参数是注册表中的一个路径字符串。所以,要想很方便的动态加载任意一个驱动,我们还要了解一下有关注册表的内容。但其中最核心的就是一条,把你驱动的相关注册表信息放到HKEY_LOCAL_MACHINE下,主要内容包括PrefixDLLIndexOrder等信息。这里就不展开说明了。

       自己起初费了那么多冤枉时间,实在很郁闷。原理摸清后就做了一个小工具,实现动态加载流驱动,以提高开发效率,也能方便后来人。下面就详细介绍这个小工具的使用过程,让大家体验一下动态加载流驱动是多么畅快的一件事情。

       我们假设已经做好一个简单的流驱动DrvDemo.dll,其对应的注册表文件为DrvDemo.reg,用来测试驱动的应用程序DrvDemo.exe。我们把这三个文件和驱动调试助手(DM.exe)都拷贝到WinCE系统上,如下图所示。

     首先运行DrvDemo.exe,点击打开设备,或者其他按钮,我们发现打开设备失败,很正常,此时DrvDemo.dll还没有工作呢。

     运行驱动调试助手软件DM.exe,点击“驱动调试”菜单——选择“导入注册表”,浏览到我们准备好的注册表文件DrvDemo.reg,选中并点击OK按钮,这样,DrvDemo.reg中的内容就已经导入到系统中了,相应的信息能在“操作信息回显”中看到。

     此时你可以直接点击“驱动调试”菜单下的“激活驱动”,当然你也可以打开“驱动调试”——“驱动列表”,进而选择激活该驱动。正常情况下,操作回显中就会提示你“加载驱动成功”。

     这时,再到DrvDemo.exe点击打开设备,就完全没有问题了。

如果在测试时,发现驱动有问题,那么你可以选择“卸载驱动”,然后将修改好的新的驱动拷贝过来,再点击“激活驱动”菜单。如此往复,直至调试成功。

至此,我们采用了通过导入注册表文件的方法激活驱动。下面再说说在没有注册表文件时直接通过浏览DLL文件本身来加载驱动的方法。先把刚刚加载的驱动卸载了。

运行驱动调试助手软件,点击“驱动调试”菜单——选择“浏览DLL文件”,浏览到我们准备好的DrvDemo.dll文件。在弹出的对话框中设置正确的PrefixOrderIndex信息,点击“确定”。

同样,此时你可以直接通过“驱动调试”下的“激活驱动”直接激活该驱动,或者从“驱动列表”中激活.

其余的操作跟上面讲的完全一样了,不再重复。

     怎么样,这种方法就很类似于Linux下的InsmodRmmod了吧?^_^

     其实,如果在注册表中已经有了相应的键,你甚至可以直接选中它,然后在“驱动调试”中选择“激活驱动”,如果一切正常,也可以达到上面两种方法的效果,但这样就连导入文件都省了。有兴趣的同志可以自己试一下。

好了,我相信到这里,大家应该对动态加载流驱动的原理和方法都了解了,也能从此摆脱不断MakeImgDownload的梦魇,节省很多宝贵的开发时间。

    最后,针对驱动调试助手简单说明一下几个要注意的地方。

1.       在调试驱动时,加载完驱动后,千万不要关闭驱动调试助手,最小化就行,否则,它会在关闭时自动卸载掉你所加载的驱动。

2.       WinCE4.2中,有关中断的驱动是无法直接用此方法来动态加载的,而在5.06.0中不会有此限制。这是因为WinCE4.2中的中断处理机制所致。

3.       驱动调试助手可以同时加载几个驱动,这时候建议将所有注册表信息写到一个文件中,并导入。剩下的工作就是从驱动列表中选择加载你所需要的驱动了。

4.       驱动调试助手中的注册表编辑功能经过几番修改,已基本完善,编辑、导入、导出都没有问题。如果系统支持HIVE-REG,在退出驱动调试助手时,可以选择保存此次的注册表修改。

5.      上面的截图是在WinCE6.0的模拟器上面做的,应该算是内核态的驱动,至于用户态的驱动也可以通过该方法加载,但是需要设定相应的注册表信息。

6.       做这样一个小工具,主要是想提高自己的工作效率。现在贴出来,望也能为同道中人所用。在使用该程序时有任何问题,请发邮件到 wince.he@gmail.com,我会尽力解决。本篇中的视频录像和最新版的驱动调试助手可以在http://files.cnblogs.com/we-hjb/WINCEDM.rar下载到。

上面所讲的并不是新鲜或者高深的技术,但相信对某些技术人员还是有一定的帮助。当然,文中有不尽如人意处,还请你见谅。以后争取多写一点东西,跟大家一起学习Windows Embedded

最后,希望不要被认为是“广告性质的文章”。^_^

posted on 2008-07-24 20:11 wince.he 阅读(3898) 评论(34)  编辑 收藏 网摘

评论

#1楼 2008-07-25 17:57 aawolf[未注册用户]

强烈支持一下   回复  引用    

#2楼 2008-07-28 14:42 gniy[未注册用户]

顶一下,想请问何兄,我在5.0的版本上面用不了你的压缩包里面的实例,这固然是由于版本问题所致,因此想请教何兄能否指点一二教我也在5.0的版本上面弄出这么个好东西!!!   回复  引用    

#3楼[楼主] 2008-07-28 15:58 何建邦      

--引用--------------------------------------------------
aawolf: 强烈支持一下
--------------------------------------------------------
谢谢aawolf的"强烈支持"。^_^
  回复  引用  查看    

#4楼[楼主] 2008-07-28 15:59 何建邦      

@gniy
请详细描述一下你的硬件平台,主要是采用的哪一个处理器。
压缩包里的程序是ARM版本的。
  回复  引用  查看    

#5楼 2008-10-25 13:45 wogoyixikexie@live.cn[未注册用户]

强!
你的驱动调试助手是放在ARM平台下运行的?还是只能用于模拟器?
如果放在ARM平台下运行估计不行吧,没有源码不能和ARM生成的SDK绑定肯定不行的。请介绍一下啊
  回复  引用    

#6楼 2008-10-29 18:02 D_BOY[未注册用户]

请问能否公布源代码?我刚开始学些CE的驱动编程,想学习一下驱动的加载/卸载,以及那些注册表的意思等等   回复  引用    

#7楼[楼主] 2008-10-29 22:53 wince.he      

@D_BOY
驱动的动态加载/卸载主要涉及两个API,
注册表的解释,MSDN里有详细介绍,建议你看看。
  回复  引用  查看    

#8楼 2009-01-16 20:20 西毒的眼泪(gooogleman)      

哈哈,楼主新年快乐。快放假了。
在你这里学到不少高招,放完假回来继续学习...
  回复  引用  查看    

#9楼[楼主] 2009-01-17 12:19 wince.he      

@西毒的眼泪(gooogleman)
新年快乐,一起学习!
  回复  引用  查看    

#10楼 2009-01-19 23:50 sagelny[未注册用户]

先生
请教两个问题:
操作系统 微软Windows CE 5.0
中央处理器 SAMSUNG ARM920 / 400 MHz 处理器

1、WinCE 使用ppc 手机软件,如何将原程序240*320改为324*240。
2、使用MDict 3.0 ,需要调用htmlview.dll,可是分别下载8KB和240KB的两个dll,都不合适,应该怎样找到合适的dll?
  回复  引用    

#11楼 2009-01-20 13:36 西毒的眼泪(gooogleman)      

@wince.he
楼主,哈哈,这个方法不错,我毕业这半年来,都是做点小改动就打包,下载内核,哎,真是惭愧,,好方法啊。
不过我觉得如果不是流驱动,应该也可以采用这种方法来做的吧,比如LCD等,随其启动的时候初始化了,但是我们在起来后改动他应该也是可以的吧,我想试试。
  回复  引用  查看    

#12楼 2009-02-09 14:26 gooogleman[未注册用户]

博主,元宵节快乐。

我年前用了你的驱动调试助手,觉得非常好用。真是太感谢你了。
我不会写应用程序。我想问一个问题。
你的程序在大液晶和小液晶上都能全屏,不越界也不会有空隙,能够自动适应液晶大小。这是怎么做到的?谢谢。
  回复  引用    

#13楼[楼主] 2009-02-14 20:37 wince.he      

@gooogleman
谢谢你,也祝你今天快乐啊。^_^

你说的问题是通过MoveWindow()来实现的,
它可以设定窗口的大小。
  回复  引用  查看    

#14楼 2009-02-15 15:09 北航[未注册用户]

我在wince中做了个can驱动,启动是会加载,但是用了dm看下,dll被停用了,这是什么原因造成的,还是因为物理地址有问题?谢谢博主解答啊   回复  引用    

#15楼[楼主] 2009-02-15 19:54 wince.he      

@北航
你好,你说的情况有可能是物理地址的问题。
启动时虽然加载了,但可能没有加载成功。
修改代码后,用DM动态加载看看,帮助确认问题所在。
  回复  引用  查看    

#16楼 2009-02-16 17:58 gooogleman[未注册用户]

博主,又来烦恼你了。你的驱动调试助手我用在简单的驱动上有用,但是我弄串口驱动就出问题了。

我把串口驱动删除了(删除注册表以及platform.bib文件)然后把使用驱动调试助手来动态加载,结果导致产生异常,不知怎么回事。

Proc=81d36340 'device.exe'
AKY=00010005 PC=01e23010(serial_smdk2440.dll+0x00003010) RA=01e23008(serial_smdk2440.dll+0x00003008) BVA=06000004 FSR=00000007
RaiseException: Thread=982f6000 Proc=81d36340 'device.exe'
AKY=00010005 PC=03f8dfec(coredll.dll+0x0001dfec) RA=802135e8(NK.EXE+0x000135e8) BVA=00000001 FSR=00000001
Prefetch Abort: Thread=98252000 Proc=81d36340 'device.exe'
AKY=00000005 PC=01e22160(???+0x01e22160) RA=03f8df18(coredll.dll+0x0001df18) BVA=01e22160 FSR=00000005
  回复  引用    

#17楼[楼主] 2009-02-16 20:02 wince.he      

@gooogleman
看起来是serial_smdk2440.dll有问题。
在系统启动时加载该串口驱动怎样呢?
  回复  引用  查看    

#18楼 2009-02-16 20:21 gooogleman[未注册用户]

以前这样加载不会产生异常,还用过。应该不是这个问题。

我觉得有点奇怪。明天我再分析一下。
  回复  引用    

#19楼 2009-02-17 11:33 gooogleman[未注册用户]

博主,我的串口驱动本来是可以用的。我觉得可能是驱动调试助手有些功能还未完善。依照你的例子,放入
[HKEY_LOCAL_MACHINE\Drivers\BuiltIn\Serial]
"Index"=dword:1
"Prefix"="COM"
"Dll"="\\serial_smdk2440.dll"
"Order"=dword:0
就没有问题,不会产生异常,当再加入任何一项,比如"DeviceArrayIndex"=dword:0的时候异常就产生了。
这个"DeviceArrayIndex"=dword:0的值是在com_init函数中由注册表函数读出的,我想可能是这个问题了。我的原注册表是这样的。
[HKEY_LOCAL_MACHINE\Drivers\BuiltIn\Serial]
"DeviceArrayIndex"=dword:0
"Irq"=dword:1c
"MemBase"=dword:50000000
"MemLen"=dword:2C
"InterruptBitsShift"=dword:0 ; UART 0 Interrupt Sub Register shift bit.
"ISTTimeouts"=dword:200 ; every 512 ticks checking Modem status.
"Prefix"="COM"
"Index"=dword:1
"Dll"="serial_smdk2440.dll"
"Order"=dword:0
"Priority"=dword:0
"Port"="COM1:"
"DeviceType"=dword:0
"FriendlyName"=LOC_DISPLAYNAME_COM1
"Tsp"="unimodem.dll"
"IClass"="{CC5195AC-BA49-48a0-BE17-DF6D1B0173DD}"
"DevConfig"=hex: 10,00, 00,00, 05,00,00,00, 10,01,00,00, 00,4B,00,00, 00,00, 08, 00, 00, 00,00,00,00
——现在的情况根本用不了注册表。全部弄进去会导致注册表解析失败。





  回复  引用    

#20楼 2009-02-17 11:59 gooogleman[未注册用户]

博主,现在我发现一个更加简单可靠的方法来调试流驱动。就是把把更新的驱动DLL拷贝到开发板的windows目录下,代替原来的即可。哈哈。现在我就这么做了   回复  引用    

#21楼[楼主] 2009-02-17 19:35 wince.he      

@gooogleman
涉及到注册表的驱动无法正常加载的问题,我会查一下。
另外,你说的注册表解析失败是什么现象?
从你贴出的注册表可以看出,其中的LOC_DISPLAYNAME_COM1应该是一个宏定义吧。DM是无法处理的。其他应该不会有解析失败的情况吧?

有好的方法,写出来跟大家一起分享啊。
  回复  引用  查看    

#22楼 2009-02-17 21:16 gooogleman[未注册用户]

总之,写多点他就异常了,我一个个试过了。   回复  引用    

#23楼 2009-02-18 10:19 letway[未注册用户]

@楼主&gooogleman
我也在调串口程序,老是报ERROR ID:2404;
年前的程序还能加载成功,现在就不行了,报ERROR ID:2404是不是根本还没加载驱动,调试信息都不出来,不知道是注册表的问题还是驱动的问题?gooogleman你的报错是什么,怎么解决的?
  回复  引用    

#24楼 2009-02-18 20:13 gooogleman[未注册用户]

估计楼主的驱动调试助手还需要修改一下。我的在启动的时候加载是没有问题的。但是使用驱动调试助手就会了。所以相当郁闷。
不过现在我不使用它来加载注册表了,只用来激活
  回复  引用    

#25楼[楼主] 2009-02-19 08:12 wince.he      

--引用--------------------------------------------------
gooogleman: 估计楼主的驱动调试助手还需要修改一下。我的在启动的时候加载是没有问题的。但是使用驱动调试助手就会了。所以相当郁闷。
不过现在我不使用它来加载注册表了,只用来激活
--------------------------------------------------------
只用来激活就可以?
我跟踪了一下串口驱动的加载,应该跟注册表没有太大关系。

出现异常是在COM_Init中调用HWInit()时,但原因还不清楚。
另外有一个现象,在加载驱动时,注册表Active键下,没有正确建立相应的键值。
  回复  引用  查看    

#26楼[楼主] 2009-02-19 08:14 wince.he      

--引用--------------------------------------------------
letway: @楼主&gooogleman
我也在调串口程序,老是报ERROR ID:2404;
年前的程序还能加载成功,现在就不行了,报ERROR ID:2404是不是根本还没加载驱动,调试信息都不出来,不知道是注册表的问题还是驱动的问题?gooogleman你的报错是什么,怎么解决的?
--------------------------------------------------------

DM目前不能调试串口驱动,在动态加载串口驱动时会有问题。
你可以查一下2404对应的是什么错误,记得没错的话,可能是设备处于活动状态,说明驱动已经加载了。
  回复  引用  查看    

#27楼 2009-02-19 21:59 gooogleman[未注册用户]

@wince.he

激活确实可行,比如停用,再激活。

我的串口驱动用起来没有问题。

如果使用导入注册表的方法,总是说加载失败什么的,楼主可以试试你的串口驱动会怎么样。因为串口注册表涉及好多东西,会在com_init中读入注册表,不知道什么原因导致异常了。
  回复  引用    

#28楼[楼主] 2009-02-19 23:45 wince.he      

@gooogleman
我跟踪了模拟器中的串口驱动,停用后再启用,会在HWInit()时出现DataAbort,返回错误号87。

以前也动态加载过XXX_init中包涵注册表操作的驱动,是没有问题的。从跟踪串口驱动加载的过程看,似乎跟读注册表没有关系,倒是Active键下没有创建正确的键值。

这个问题值得研究,有时间再看看吧。你有空也帮忙看看。不过,感觉我的问题跟你的问题似乎还不一样。


  回复  引用  查看    

#29楼 2009-03-25 15:01 fendou_mo[未注册用户]

那还要添加注册表吗@gooogleman
@gooogleman
  回复  引用    

#30楼 2009-04-07 10:56 gooogleman[未注册用户]

楼上注册表是必须添加的——要么是在第一次编译时候就修改好注册表,打包进内核,要么就再后来添加,但是后来添加会造成一些问题。

还有楼主,我还发现一个问题就是:停用PowerButton驱动之后再次启用PowerButton驱动之后就不会工作了,但是驱动调试助手提示启用成功的,不知道怎么回事。
  回复  引用    

#31楼 2009-04-08 10:32 good[未注册用户]

附件有木马   回复  引用    

#32楼 2009-04-08 21:03 ztg

你好 能不能把那个测试驱动的那个应用程序的源码也打包在压缩包里 发现有些驱动只要需要博主的那个应用程序就可以了 可是不会写应用   回复  引用    

#33楼 2009-04-10 22:12 gooogleman[未注册用户]

@ztg
可以自己写个啊。这东西还是挺有意思的。
  回复  引用    

#34楼 2009-05-05 11:02 张云杰[未注册用户]

非常感谢你的热心帮助!!!!!   回复  引用    

发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

[使用Ctrl+Enter键快速提交评论]

0 1250838




相关文章:

相关链接: