WINCE学习经验总结三(希望给初学者一些建议,尽快入门)

 

 8、WINCE驱动开发介绍及实践

这一部分,对于一个项目来说比较重要的一个部分,如果我们有驱动开发的能力,那么硬件设计和软件的稳定性会有很大的保障。这一部分涉及的内容相对较难,不但要对系统的东西有深刻的认识,还要对硬件比较熟悉。学会了这样的开发能力,想要做的系统增加任何一个外设,开发周期都会变的短很多。我敢说,国内比较缺乏能够写驱动的人才。

驱动和我们平时写的硬件程序有些不同,它和系统的关系比较紧密,而且有着严格的调用机制。这一章,在课堂上只能说一个引导的作用,大部分的工作量还需下去同学们自己好好的研究和交流,请大家打起精神,查阅各种书籍及网络资源,来慢慢了解驱动,培养自己的开发能力。

由于这部分内容实在太多,我只以一个简单的流驱动作为例子,给大家讲解。

其余内容我把这部分课件上传到网上,大家可以下载阅读,或是去图书馆借书查阅。

参考资料:课件(http://d.download.csdn.net/down/3539921/liujianning)

我的例子参考资料:天嵌科技出品--WinCE开发完全手册(V2.5)   (这个在天嵌论坛和上就可以下载的到)

(以下参考http://blog.csdn.net/nanjianhui/article/details/2674753)

流设备驱动程序又称为可安装的驱动程序,也就是说,它们是可以后续安装的。它们是由设备管理器(Device)动态加载的用户模式的DLL。

流设备驱动的架构:

 

在WinCE启动的时候,OAL(OAL.exe)首先加载kernel.dll,然后kernel.dll加载device.dll,device.dll会加载devmgr.dll,devmgr.dll实际上就是Device Manager模块,他会负责流设备的加载,卸载和交互操作。

一般应用程序要通过文件系统接口来访问设备。首先调用CreateFile打开设备并获得相应的句柄,然后通过文件系统接口调用ReadFile或者WriteFile来访问相应的流设备驱动,或者通过DeviceIoControl直接访问。无论哪种方式,都是要通过Device Manager才能访问到相应的设备驱动。

下面介绍一下流设备驱动的接口函数:

 

函数名

说明

XXX_Close

关闭以hOpenContext标识的设备上下文。

XXX_Deinit

由设备管理器调用来删除对某一设备的初始化信息。

XXX_Init

由设备管理器调用来对某一设备进行初始化。

XXX_IOControl

向设备发送命令,以命令设备做一些事情。

XXX_Open

打开一个设备以进行读、写或者既读又写。

XXX_PowerDown

停止向设备供电。供可使用软件控制关闭的设备关闭自身电源。

XXX_PowerUp

恢复向设备供电

XXX_Read

从设备读取数据

XXX_Seek

在设备中移动数据指针

XXX_Write

向设备写数据

 

以下是依次详细介绍这些接口函数。

1、  XXX_Init接口函数

完成的功能:

①     在驱动被加载时,该函数被调用

②     初始化所需要的硬件资源,并在本接口处理中被分配

③     创建内存映射

接口的原型:

DWORD XXX_Init(DWORD dwContext):

参数说明:

dwContext:指向一个字符串,它描述注册表中一个流设备接口

本接口的处理返回时,设备管理器就在注册表中查找驱动的Ioctl子键,如果存在,设备管理器将调用XXX_IOControl()接口将dwcode参数传入驱动接口点。

2、  XXX_Deinit接口函数

完成的功能:

卸载一个设备驱动,释放被占用的资源,停止该设备的运行。

接口的原型:

BOOL XXX_Deinit(DWORD hDeviceContext)

参数说明:

hDeviceContext:指设备上下文的句柄,应由XXX_Init()返回。

3、  XXX_Open接口函数

完成功能:

当应用程序调用createfile()函数时,文件系统会自动调用该函数,打开一个存在的设备文件,当这个接口函数被调用后,也就为读/写做好了准备。

接口的原型:

DWORD XXX_Open(DWORD hDeviceContext, DWORD AccessCode, DWORD ShareMode):

参数说明:

hDeviceContext:指设备上下文的句柄,应由XXX_Init()返回。

AccessCode,打开设备的权限描述符,包括只读,只写,可读写。

4、  XXX_Close()接口函数

完成功能:

关闭一个设备,对应于closehandle接口

接口的原型:

BOOL XXX_Close(DWORD hOpenContext):

参数说明:

hDeviceContext:设备驱动的句柄,在XXX_Open调用时返回的

5、  XXX_Read()接口函数

完成功能:

应用程序中调用readfile()函数时,设备管理器会调用相应的接口。

接口的原型:

DWORD XXX_Read(DWORD hOpenContext, LPVOID pBuffer, DWORD Count):

参数说明:

hOpenContext:设备驱动的句柄,在XXX_Open调用时返回的

pBuffer:存放数据的Buffer,单位:字节(B)

Count:读取数据的长度

6、  XXX_Write()接口函数

完成的功能:

应用程序中调用writefile()函数时,设备管理器会调用相应的接口。

接口的原型:

DWORD XXX_Write(DWORD hOpenContext, LPCVOID pBuffer, DWORD Count):

参数说明:

hOpenContext:设备驱动的句柄,在XXX_Open调用时返回的

pBuffer:写入数据的Buffer,单位:字节(B)

Count:读取数据的长度

7、  XXX_Seek()接口函数

完成功能:

定义I/O指针时被调用,当应用程序调用setfliepointer()函数时,,设备管理器相应的调用该接口。

接口原型:

DWORD XXX_Seek(DWORD hOpenContext, long Amount, WORD Type)

参数说明:

hDeviceContext:设备驱动的句柄,在XXX_Open调用时返回的

Amount:移动的字节数,指针要移动的距离

Type:描述起始点位置,FILE_BEGIN表示从头移动,FILE_CURRENT表示从当前位置移动FILE_END表示从末尾往前移动

8、  XXX_IOControl()接口函数

完成功能:

主要传递包括读写命令在内的I/O控制命令给设备。

I/O控制字可以用来识别命令类型,普通的读写操作(XXX_Read和XXX_Write)通常能满足要求的,而I/O控制字可以与硬件相关。

接口原型:

BOOL XXX_IOControl(DWORD hOpenContext, DWORD dwCode, PBYTE pBufIn, DWORD dwLenIn, PBYTE pBufOut, DWORD dwLenOut, PDWORD pdwActualOut):

参数说明:

hDeviceContext:设备驱动的句柄,在XXX_Open调用时返回的

dwCode:由驱动程序指定,一般会在该驱动的说明文件中,提供相关的定义或通过头文件形式提供给应用程序。

pBufIn:输入Buffer

dwLenIn:输入Buffer的size

pBufOut:输出Buffer

dwLenOut:输出Buffer的size

pdwActualOut:实际输出的字节数

9、  XXX_PowerDown()接口函数

完成功能:

在停止对设备供电时被调用,完成关闭电源的安全性检查。

接口的原型:

void XXX_PowerDown(DWORD hOpenContext):

参数说明:

hDeviceContext:设备驱动的句柄,在XXX_Open调用时返回的

10、XXX_PowerUp()接口函数

完成功能:

恢复设备供电用。

接口的原型:

void XXX_PowerUp(DWORD hOpenContext)

参数说明:

hDeviceContext:设备驱动的句柄,在XXX_Open调用时返回的

 

下面,我们将介绍一下一个简单的GPIO的流驱动的开发流程。首先讲一个流驱动的一些知识

一个驱动至少需要包含:(.cpp、.def、.makefile、.sources、.reg、.bib)

.cpp是驱动源码,其中包含了头文件的函数调用,驱动代码和驱动接口。

.def提供驱动接口,内容大致如下:

LIBRARY XXX

EXPORTS

   XXX_CLOSE

   XXX_Deinit

   XXX_IOControl

   XXX_Open

   XXX_PowerDown

   XXX_PowerUp

   XXX_Read

   XXX_Seek

   XXX_Write

MakeFlie文件内容大致如下:

!INCLUDE $(_MAKEENVROOT)\makefile.def

Sources文件内容:

TARGETNAME=指定要生成的动态库的名称

TARGETTYPE=DYNLINK

TARGETLIBS=\

    $(_COMMONSDKROOT)\lib\$(_CPUINDPATH)\coredll.lib    \

    $(_SYSGENOAKROOT)\lib\$(_CPUINDPATH)\ceddk.lib    \

   (这个库需要自行添加)

DLLENTRY=DllEntry

DEFFILE=刚才提到的.def

SOURCES= \

(刚才见到的驱动源码)

.reg提供注册表信息,写入到Platform.reg中,内容大致如下:

[HKEY_LOCAL_MACHINE\Drivers\BuiltIn\驱动名称]

       "Prefix"="前缀"

       "Dll"="驱动的动态库文件"

       "Index"=dword:1

       "Order"=dword:30

Platform.bib中添加镜像:

驱动动态库文件    $(_FLATRELEASEDIR)\驱动动态库文件    NK   SHK

 

以上就是一个流驱动拥有的主要文件的改写,下面我们开始介绍添加一个驱动的流程。

1、  首先在BSP包DRIVERS目录下建立一个“mydrivers”的目录。

2、  进入到该目录下,新建“mydrivers.cpp”,完善接口函数内容

3、  新建“mydrivers.def”添加上面讲的内容,这里XXX为“MYD”

4、  新建makefile,内容如前面所示

5、  新建sources,内容如下:

TARGETNAME=mydrivers

TARGETTYPE=DYNLINK

TARGETLIBS=\

    $(_COMMONSDKROOT)\lib\$(_CPUINDPATH)\coredll.lib    \

$(_SYSGENOAKROOT)\lib\$(_CPUINDPATH)\ceddk.lib 

DLLENTRY=DllEntry

DEFFILE=mydrivers.def

SOURCES= \

     Mydrivers.cpp

6、  直接修改注册表信息

[HKEY_LOCAL_MACHINE\Drivers\BuiltIn\Mydrivers]

       "Prefix"="MYD"

       "Dll"="mydrivers.dll"

       "Index"=dword:1

       "Order"=dword:30

7、  修改BSP包中的Platform.bib

mydrivers.dll    $(_FLATRELEASEDIR)\ mydrivers.dll    NK   SHK

剩下的就是编译链接,调试驱动了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值