wince6.0驱动开发

1、基础知识:

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 NT
           3)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 Host Controller,USB

Host 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函数间接调用之

。返回一个结构指针,用于区分哪个应用程序调用了驱动,这个值还作为参数传递给其他接口函数

XXX_Read、XXX_Write、XXX_Seek、XXX_IOControl。

4)BOOL XXX_Close(DWORD hOpenContext);
hOpenContext:XXX_Open返回值。
关闭设备,释放资源。由CloseHandle函数间接调用。


5)DWORD XXX_Read(DWORD hOpenContext, LPVOID pBuffer, DWORD Count);
hOpenContext:XXX_Open返回值。
pBuffer:缓冲区指针,接收数据。
Count:缓冲区长度。
由ReadFile函数间接调用,用来读取设备上的数据。返回读取的实际数据字节数。


6)DWORD XXX_Write(DWORD hOpenContext, LPCVOID pBuffer, DWORD Count);
hOpenContext:XXX_Open返回值。
pBuffer:缓冲区指针,接收数据。
Count:缓冲区长度。
由WriteFile函数间接调用,把数据写到设备上,返回实际写入的数据数。

7)BOOL XXX_IOControl(DWORD hOpenContext, DWORD dwCode, PBYTE pBufIn,      DWORD dwLenIn, PBYTE

pBufOut, DWORD dwLenOut,        PDWORD pdwActualOut);
hOpenContext:XXX_Open返回值。
dwCode:控制命令字。
pdwActualOut:实际输出数据长度。

用于向设备发送命令,应用程序通过DeviceIoControl调用来实现该功能。要调用这个接口还需要在应用

层和驱动之间建立一套相同的命令,通过宏定义CTL_CODE(DeviceType, Function, Method, Access来实

现。如:

#define IOCTL_INIT_PORTS / CTL_CODE

(FILE_DEVICE_UNKNOWN,0X801,METHOD_BUFFERED,FILE_ANY_ACCESS)

8)void XXX_PowerDown(DWORD hDeviceContext);

hDeviceContext:XXX_Init的返回值。

                  负责设备的上电控制。

9)void XXX_PowerUp(DWORD hDeviceContext);

hDeviceContext:XXX_Init的返回值。

           负责设备的断电控制

10)DWORD IOC_Seek(DWORD hOpenContext, long Amount, WORD Type)

hOpenContext:XXX_Open返回值。

                  Amount:指针的偏移量。

                  Type:指针的偏移方式。

将设备的数据指针指向特定的位置,应用程序通过SetFilePointer函数间接调用。不是所有设备的属性

上都支持这项功能。

5、流接口驱动的加载和注册表设置:

系统启动时启动设备管理程序,设备管理程序读取HKEY_LOCAL_MACHINE/Drivers/BuiltIn键的内容并加

载已列出的流接口驱动程序。因此注册表对于驱动的加载有着关键作用。下面是一个例子:

【HKEY_LOCAL_MACHINE/Drivers/BuiltI/IOControler】
“Prefix”=”XXX”
“Dll”=”drivername.dll”
其中,“Prefix”=“XXX”中的XXX要和XXX_Init等函数中的一样。CreateFile创建的驱动名前缀也必

须和它们一致。

6、驱动程序的编写、编译及其相关目录、配置文件的格式和修改:

1)首先必须在PB相应平台的的driver目录下建立要创建的驱动所在的目录。如在x:/Wince420

/platform/smdk2410/drivers目录下建立一个IOCtrol目录。

2)修改Drivers目录下的dirs文件。

3)创建驱动源文件XXX.c,在该文件中实现上述流接口函数。并且加入DLL入口函数:

BOOL DllEntry(HINSTANCE hinstDll, /*@parm Instance pointer. */

                    DWORD dwReason,   /*@parm Reason routine is called. */

                    LPVOID lpReserved   /*@parm system parameter. */

                       )

4)创建Makefile和Sources和.def文件,控制编译。

5)使用CEC Editor修改cec文件,编译添加的新特性。

6)复制新生成的4个文件到Release目录下,修改注册表文件platform.reg和platform.bib文件。

7)Make Image。

8)DownLoad Image

一般我们在驱动程序中需用LocalAlloc保留一块存储空间,然后用LocalCopy将I/O端口映射到该地址上,以后就可以访问该保留下来的地址了。
而对中断的处理各种设备不尽相同。如果是一个内置设备(Built In),一般在oalintr.h文件中定义一个新的中断,OAL层中加上对该中断的处理。然后在驱动程序的Init函数中用CreateEvent创建一个事件,调用InterruptInitialize 将定义好的中断与创建的事件相关联,再创建一个线程,在该线程中调用WaitforSingleObject等待该事件,当该设备有中断发生时,这个事件就被触发,WaitforSingleOjbect返回,线程被运行,我们就可以处理该中断。
OAL中所新加的对该中断的处理就是所谓的ISR之内容,而这个线程就是所说的IST。

其它

1.CE下同名设备不能大于10

CE5.0中已经没有这个问题了,
以前的版本可以这样做:
只给上层输出一个设备,
然后用一个IOCTL去打开一个个的物理设备
这样就可以做到不受任何限制了


2.MDD与PDD

一个驱动程序通常会被分成硬件相关(PDD)与硬件无关(MDD)层两部分。
当然,这种分层不是必须的,只是采用这种分层以后可以少写很多代码,因为微软提供了很多驱动程序的MDD。即使CE中没有我们所写的驱动程序的样例,采用这种结构以后,当需要写第二个程序时,就可以重用它的代码,就可以提高开发效率。

MDD是提供同类型的设备(比如串口)都会有的功能,这样PDD基本上就只有寄存器操作了。
像串口的中断处理,Read/Write函数,其大部分代码都是在MDD中实现的,
不同的串口实现中只需要提供一些实际操作寄存器的函数


不同的驱动程序,其MDD与PDD的接口不尽相同,
所以,当我们面对一个具体的驱动程序时,需要查帮助弄清楚需要提供哪些函数


3 XXX_Init函数的返回句柄

通常,这个句柄是驱动程序自己保存数据的一个指针,
我们在Init返回时告诉上层程序,以后上层调用其它函数(例如Open)时,
会将这个值传入,这样,我们就可以访问自己的一些私有数据。

当然,也可以返回一个任意的非0值


对于一个设备驱动程序,系统不用的层会有不同的句柄。
我们在XXX_Init中返回的句柄保存在设备管理器中,别的程序中应该是看不到的,
而用CreateFile也会得到一个文件句柄,这个保存在哪我不知道,
但和前者是不一样的。

也就是说不同层的软件所关心的句柄也会不一样


4.DEBUGMSG与RETAILMSG的区别

它们都是输出调试信息用的,
区别是:
DEBUGMSG只在DEBUG版中有效,RELEASE版中它被定义成了NULL
RETAILMSG在DEBUG和RELEASE版中都可以输出,
而且DEBUGMSG可以在运行时刻用DEBUZONE控制要不要输出信息。

在ship build 时,RETAILMSG 和DEBUGMSG都无效


5. 显视屏出现了上下两个桌面,应该是:

屏幕大小设成了只有实际大小的一半(高度).

就是说你屏幕高是600,而你驱动程序中设置的高度是300.

当然,也可以修改程序使其下半部分输出黑色.

地址分配:

对于ARM来说,有虚拟地址和物理地址之分,对于WINCE来说,也有虚拟地址和物理地址之分. 可以这么说,ARM的虚拟地址就是WINCE系统的物理地址. 
32位的OS总共有4G的虚拟地址空间,WINCE也不例外. 其中,0x00000000~0x80000000是Application Space; 0x80000000~0xffffffff是System Reserved. 系统的物理地址就在System Reserved的这段,只能在KERNEL MODE访问. 那么,当APPLICATION和DRIVER(都是运行在USER MODE)要访问这些在System Reserved地址段的硬件寄存器或MEMORY怎么办呢? 只好再建立一层映射关系,在Application Space里分配一段空间,把它映射到System Reserved里的地址上,这就是VirtualAlloc/Copy和MmMapIoSpace干的事情

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

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

相关文章

在android studio中如何创建一个类来继承另外一个类_在Android使用Transition API检测用户活动...

在当今世界,移动设备是我们日常生活中必不可少的一部分,我们在走路、跑步、开车以及其他许多活动时都会使用移动设备。了解用户拿着手机的时候在做什么,可以让你的应用程序根据用户的动作进行直观的调整。对于某些应用程序,确定用…

拼接dem,山地出现平地

利用dem做山体阴影,错误示例: 解决办法: 调整以下参数即可

先容Oracle中null的运用要领。

51 本源:网海拾贝 问:什么是NULL? 答:在我们不晓得详细有什么数据的时分,也即未知,可以用NULL,我们称它为空,ORACLE中,含有空值的表列长度为零。 ORACLE许可任何一种数据…

Wince6 Eboot中加入开机画面

昨天研究了一下wince开机时加入个性化的画面,折腾了一上午,不是花屏就是CE起不来……终于搞定,分享一下经验吧。。。 Wince加入开机画面方法一般有以下两种: 1、 在文件中下定义一个常量大数组,几百K,如con…

hive 窗口函数_Datatist科技专栏 | Hive排序窗口函数速学教程!

作者:原上野设计:Cindy编辑:AI君在开发过程中经常会遇见排序的场景,比如取top N的问题,这时候row_number(),rank,dense_ran()这三个函数就派上用场了,其中,row_number()最为常用。虽然都可以排序…

arcgis利用python赋值

、 rec0 def autoIncrement(): global rec pStart 1 pInterval 1 if (rec 0): rec pStart else: rec rec pInterval return rec

人生九度

1.工作方面,能力不敌态度; 2.事业方面,才华不敌韧度; 3.知识方面,广博不敌深度; 4.思想方面,敏锐不敌高度; 5.做人方面,精明不敌气度; 6.做事方面&#xff0c…

platform Builder导出SDK

一、编译好wince系统 二、选择[platform]->[configur SDK],第一次进入的话,会要求输入一些SDK名字等信息。完成后再一次进入才是配置SDK的属性。 三、有几项需要注意的: CPU选项:若是输出仿真器的SDK,这项不要选入…

idea修改代码后没有重新编译_SpringBoot中实现代码修改之后的自动更新与热加载...

在实际的开发过程中,我们经常修改代码之后,手动的重启项目,查看修改效果。那么有没有一种方式能够快速的、自动的帮我们将修改代码自动更新,避免手动重启,从而提高开发效率呢?是有的,对于这个功…

android 从assets和res中读取文件(转)

1. 相关文件夹介绍 在Android项目文件夹里面,主要的资源文件是放在res文件夹里面的。assets文件夹是存放不进行编译加工的原生文件,即该文件夹里面的文件不会像xml,java文件被预编译,可以存放一些图片,html&#xff0c…

WINCE6开机进度条

大致思路,在NBoot或EBoot加开机进度条,由于WINCE启动主要时间都花在读取NK,因此每读取一定的页,就在屏上画一条固定高度的线,并记录画线的位置,下次接着画,直到读取完NK,这样就产生的…

电脑查看wifi密码

右键 打开“网络。。。。。。”

软件oem要注意什么_做化妆品oem,选择化妆品包材要注意什么问题

化妆品企业找厂家做oem,一般厂家都是负责设计研发生产的,但是设计出来的产品包材,就需要找其它的包材厂家去采购了,很多没有经验的品牌商都不清楚找包材要怎么找,好看质量好就可以了吗?韵丽生物科技化妆品代…

等高线转dem

可以自行设置分辨率

ARM指令 LDR 和 ADR的一些区别

LDR 是ARM中的指令,也是伪指令。 当用 LDR r, imd // r 为寄存器, imd为立即数 LDR 是一条伪指令。编译器会根据 立即数的大小,决定用 ldr 指令或者是mov或mvn指令。 当imd能用mov或者mvn操作时,就将它翻译成一条mov或mvn指令。当…

阻塞 cpu占用

请问,windowsxp系统下,有一个线程A,此线程中需要wait一个信号,我有以下观点,请大家帮我判断一下我的观点对不对,谢谢!如果我用阻塞方式,则一旦轮到这个线程执行,os只要发…

登录验证应该是进行在客户端还是服务器端_网站登录认证方式

目前大部分软件系统资源访问都是使用HTTP协议,HTTP是无状态的协议,每次请求默认都是相互独立的。但是大部分情况下我们需要记录请求资源的用户信息,也就是保存会话,从而对资源的访问做限制,这是我们认证功能。常用的认…

arcgis将点的属性赋值给面

例子:将点的编号属性列赋值到对应的面属性

关于application title一直是untitled的问题

建立了一个cocoaapplication项目,在Interface Builder中修改了title,在运行时标题始终是“Untitled”。这是我在http://stackoverflow.com/questions/4720030/cocoa-mac-application-title-says-untitled上找的解决方法。I have created a document base…