1、地址:中国深圳经济特区福田区中康路32号弘亿大厦 电话:0755-83142770 传真:0755-83142771 邮政编码:518000 网址:http/,Windows CE6.0 的驱动程序,第三部分,目 录,3.1 驱动程序的分类 3.2 设备管理器 3.3 驱动程序的加载机制 3.4 驱动注册表配置 3.5 流接口驱动及实例,支 持,支 持,本地驱动,流式驱动,Windows CE,提供给 系统 使用,提供给 用户 使用,3.1 驱动程序的分类,本地驱动,本地驱动由GWES加载和管理,3.1 驱动程序的分类,流式驱动,流式驱动由Device加载和管理,3.1 驱动程序的分类,本地驱
2、动,流式驱动,GWES,Device,Windows CE,加载,加载,两种驱动加载对象不同!,3.1 驱动程序的分类,XXX_Init XXX_Open XXX_Close XXX_Deinit XXX_Read XXX_Write,3.1 驱动程序的分类,本地驱动,流式驱动,DDSI接口,在移植过程中, 通常不需要修改,在移植过程中, 通常需要修改, 并且是硬件通信的抽象层,模型设备驱动(Model Device Driver),平台设备驱动 (Platform Device Driver ),设备驱动服务接口(Device Driver Service provider Interfac
3、e),3.1 驱动程序的分类,DDSI接口,整体结构依赖于单个 DLL 来实现,3.1 驱动程序的分类,整体结构,分层结构,开 发 成 本,开 发 成 本,代 码 重 用,执 行 效 率,执 行 效 率,代 码 重 用,输,羸,输,羸,羸,输,比武大赛第 场,1,2,3,3.1 驱动程序的分类,目 录,3.1 驱动程序的分类 3.2 设备管理器 3.3 驱动程序的加载机制 3.4 驱动注册表配置 3.5 流接口驱动及实例,3.2 设备管理器,HKEY_LOCAL_MACHINEinit“Launch20“=“device.dll“,设备管理器外壳程序(Device.dll),内核,设备管理器的
4、核心(Devmgr.dll),内核在启动过程期间加载Device Manager (设备管理器)的外壳程序,Device Manager (设备管理器)的外壳程序载入真正的核心 Device Manager ( 设备管理器) 代码 (Devmgr.dll),设备管理器 (Device Manager),3.2 设备管理器,设备 管理 器,流接口,流式 驱动 文件,通过XXX_Init函数加载驱动,通过XXX_Close函数关闭驱动,通过XXX_Deinit函数卸载驱动,通过XXX_Open函数打开驱动,通过XXX_Read函数读取数据,通过XXX_Write函数写入数据,通过XXX_IOCon
5、trol函数进行输出输入,3.2 设备管理器,设备管理器与应用程序通信过程,1,用户应用程序,调用CreateFile函数,文件系统,设备管理器,2,3,获得句柄,4,调用DeviceIoControl函数进行通信,5,3.2 设备管理器,设备管理器与硬件通信过程,1,用户应用程序,调用CreateFile函数,CE内核,OEM适配层(OAL),文件系统,设备管理器,2,3,获得句柄,4,调用DeviceIoControl函数进行通信,5,硬件,设备驱动程序 (流接口),6,7,8,9,IST创建与调用,中断的异常处理,调用xxx_stream函数,3.2 设备管理器,目 录,3.1 驱动程序
6、的分类 3.2 设备管理器 3.3 驱动程序的加载机制 3.4 驱动注册表配置 3.5 流接口驱动及实例,3.3 驱动程序的加载机制,驱动程序的加载方法,3.3 驱动程序的加载机制,静态加载-在内核启动过程中,文件被加载到相应的运行空间运行.,1,2,3,修改Platform.reg文件,修改Platform.bib文件,静态加载过程,3.3 驱动程序的加载机制,4,5,加载,加载,6,静态加载过程,3.3 驱动程序的加载机制,是,否,加载,1,2,3,4,系统检测外围 设备来加载设备驱动,手动安装设备驱动,动态加载过程,3.3 驱动程序的加载机制,静态加载与动态加载的比较,目 录,3.1 驱
7、动程序的分类 3.2 设备管理器 3.3 驱动程序的加载机制 3.4 驱动注册表配置 3.5 流接口驱动及实例,3.4 驱动注册表配置,Windows CE 注册表,Windows CE 注册表分类,3.4 驱动注册表配置,注册表(.reg)文件重要组成,3.4 驱动注册表配置,HKEY_LOCAL_MACHINEDriversBuiltInXXX,流式驱动的加载信息配置,3.4 驱动注册表配置,LED驱动配置路径和信息,串口驱动配置路径和信息,流式驱动的加载信息配置举例,3.4 驱动注册表配置,本地驱动的加载信息配置,3.4 驱动注册表配置,本地驱动的加载信息配置举例,3.4 驱动注册表配置
8、,本地驱动的加载信息配置举例,3.4 驱动注册表配置,本地驱动与流式驱动的加载信息配置的对比,目 录,3.1 驱动程序的分类 3.2 设备管理器 3.3 驱动程序的加载机制 3.4 驱动注册表配置 3.5 流接口驱动及实例,3.5 流接口设备驱动及实例,什么叫驱动程序,驱动程序的作用,3.5 流接口设备驱动及实例,3.5 流接口设备驱动及实例,Windows CE流接口驱动简介,3.5 流接口设备驱动及实例,流接口驱动开发工具,3.5 流接口设备驱动及实例,流接口驱动体系结构,文件系统,设备管理器,流接口驱动,硬件平台,应用程序,3.5 流接口设备驱动及实例,XXX_Init() XXX_Op
9、en() XXX_Read() XXX_Write() XXX_PreClose() XXX_Close(),XXX_PreDeinit() XXX_Deinit() XXX_Seek() XXX_IOControl() XXX_PowerDown() XXX_ PowerUp(),流接口函数简介,流接口函数简介,3.5 流接口设备驱动及实例,流接口函数简介-XXX_Init,3.5 流接口设备驱动及实例,流接口函数举例-XXX_Init,DWORD SMP_Init( LPCTSTR pContext,DWORD dwBusContext )/ Implement device contex
10、t initialization code here.LEDInit();return 0x1; ,3.5 流接口设备驱动及实例,流接口函数简介-XXX_Open,3.5 流接口设备驱动及实例,流接口函数举例-XXX_Open,DWORD SMP_Open( DWORD hDeviceContext,DWORD AccessCode, DWORD ShareMode ) / Implement open context initialization code here.return 0x2; ,3.5 流接口设备驱动及实例,流接口函数简介-XXX_Read,3.5 流接口设备驱动及实例,流接口
11、函数举例-XXX_Read,DWORD SMP_Read ( DWORD hOpenContext, LPVOID pBuffer, DWORD Count ) / Implement the code to read from the stream device here. uchar *pReadBuffer; / 映射地址空间 pReadBuffer = MapPtrToProcess(pBuffer, GetCallerProcess(); *pReadBuffer=2; /* 返回读取数据 值为2,给应用程序*/ return 0x1; /* 返回读取的字节数 */ ,3.5 流接口
12、设备驱动及实例,流接口函数简介-XXX_Write,3.5 流接口设备驱动及实例,流接口函数举例-XXX_Write,DWORD SMP_Write ( DWORD hOpenContext, LPVOID pBuffer, DWORD Count ) / Implement the code to write to the stream device here. uchar *pWriteBuffer,Data; / 映射地址空间, 获取应用程序地址空间数据指针 pWriteBuffer = MapPtrToProcess(pBuffer, GetCallerProcess();Data=*
13、pWriteBuffer; /* 保存应用程序传递过来的数据 */ return 0x1; ,3.5 流接口设备驱动及实例,流接口函数简介-XXX_PreClose,3.5 流接口设备驱动及实例,流接口函数举例-XXX_PreClose,BOOL SMP_PreClose(DWORD hOpenContext ) / Implement the code to PreClose from the stream device here.return TRUE; ,3.5 流接口设备驱动及实例,流接口函数简介-XXX_Close,3.5 流接口设备驱动及实例,流接口函数举例-XXX_Close,B
14、OOL SMP_Close(DWORD hOpenContext ) / Implement code to close the open context here. return TRUE; ,3.5 流接口设备驱动及实例,3.5 流接口设备驱动及实例,流接口函数举例-XXX_PreDeinit,BOOL SMP_PreDeinit(DWORD hOpenContext ) / Implement code to close the open context here.return TRUE; ,3.5 流接口设备驱动及实例,流接口函数简介-XXX_Deinit,3.5 流接口设备驱动及实例
15、,流接口函数举例-XXX_Deinit,BOOL SMP_Deinit(DWORD hOpenContext ) / Implement code to deinit the open context here.return TRUE; ,3.5 流接口设备驱动及实例,流接口函数简介-XXX_Seek,3.5 流接口设备驱动及实例,流接口函数举例-XXX_Seek,DWORD SMP_Seek( DWORD hOpenContext, long Amount, WORD Type ) / Implement code to seek the open context here.return T
16、RUE; ,3.5 流接口设备驱动及实例,流接口函数简介-XXX_ IOControl,BOOL XXX_IOControl(DWORD hOpenContext, DWORD dwCode,PBYTE pBufIn,DWORD dwLenIn, PBYTE pBufOut,DWORD dwLenOut,PDWORD pdwActualOut ),hOpenContext: 设备驱动的句柄 dwCode:操作码 pBufIn:输入缓冲区 dwLenIn:输入缓冲区的大小 pBufOut:输出缓冲区 dwLenOut:输出缓冲区的大小 pdwActualOut:实际输出的字节数 返回值:true
17、 意味着成功 false意味着失败 功能:设备IO控制操作函数,3.5 流接口设备驱动及实例,流接口函数举例-XXX_ IOControl,DWORD SMP_IOControl(DWORD hOpenContext, DWORD dwCode,PBYTE pBufIn,DWORD dwLenIn, PBYTE pBufOut,DWORD dwLenOut,PDWORD pdwActualOut) / Implement code to handle advanced driver actions here. switch(dwCode)case LED_IOCTL_SET:WriteData
18、(*pBufIn);break; return TRUE; ,3.5 流接口设备驱动及实例,流接口函数简介-XXX_ PowerDown,3.5 流接口设备驱动及实例,流接口函数举例-XXX_PowerDown,DWORD SMP_PowerDown( DWORD hDeviceContext ) / Implement power down management code here.return TRUE; ,3.5 流接口设备驱动及实例,流接口函数简介-XXX_ PowerUp,3.5 流接口设备驱动及实例,流接口函数举例-XXX_PowerUp,DWORD SMP_PowerUp( DW
19、ORD hDeviceContext ) / Implement power up management code here.return TRUE; ,3.5 流接口设备驱动及实例,流接口驱动工作原理,3.5 流接口设备驱动及实例,流驱动举例-LED数码管分类,3.5 流接口设备驱动及实例,流驱动举例-LED数码管原理,A,B,C,D,E,F,G,DP,vcc,共阳LED数码管原理,3.5 流接口设备驱动及实例,a,b,c,dp,d,e,f,g,a,b,c,d,e,f,g,dp,vcc,LED数码管显示2原理,0,0,1,0,0,1,0,1,0:低电平,1:高电平,流驱动举例-LED数码管原
20、理,3.5 流接口设备驱动及实例,流驱动举例-LED数码管使用条件,1、段与小数点要使用限流电阻,、使用电流:静态:总电流 80mA(每段 10mA);动态:平均电流 4-5mA 峰值电流 100mA,、使用电压:根据发光二极管的手册,3.5 流接口设备驱动及实例,流驱动举例-XSBASE270的LED数码管硬件设计总图(1),3.5 流接口设备驱动及实例,流驱动举例-XSBASE270的LED数码管硬件设计总图(2),3.5 流接口设备驱动及实例,74HC574芯片结构介绍,74HC574的内部结构由八个锁存器构成,3.5 流接口设备驱动及实例,74HC574芯片功能介绍,输入,输出,D,O
21、E,CLOCK,Q,L,L,L,L,H,H,H,X,X,无效,X=Dont Care,H=高电平,L=低电平,74HC574是由上升沿触发并将数据锁存,3.5 流接口设备驱动及实例,数码管硬件电路分析与介绍,74HC574在电路中起着数据缓冲并对数据锁存,以及信号增强作用. C24电容在这里起着滤波作用 R58和R59排阻在这里作为限流电阻,保护数码管,以防电压过高,电流过大. LED-CS2作为一个地址,控制数码管的工作. 三极管在这里作为一个可控开关,通过基极控制数码管的电源状态.,3.5 流接口设备驱动及实例,数码管的基地址与偏移地址,数码管的基地址的片选是B-CS4,数码管的偏移地址是
22、(CBA),即(A)BA20, (B)BA21和(C)BA22.,3.5 流接口设备驱动及实例,数码管的基地址计算,数码管的基地址计算,3.5 流接口设备驱动及实例,数码管的偏移地址计算,3.5 流接口设备驱动及实例,数码管的物理地址计算,LED4,LED3,LED2,LED1,物理地址=基地址+偏移地址,3.5 流接口设备驱动及实例,数码管的流驱动实现与讲解-编写makefile,!INCLUDE $(_MAKEENVROOT)makefile.def,Makefile的内容,在$(_PLATFORM)Xsbase270SrcDriver路径下创建一个LED文件夹,在该文件夹里再创建一个文件
23、,名为makefile.实现makefile的内容: %_MAKEENVROOT%是环境变量,指向Wince600PublicCommonOakMisc 文件夹. Makefile在驱动中作用:为 Nmake.exe 提供默认的预处理指令、命令、宏、和其它表达式.,3.5 流接口设备驱动及实例,数码管的流驱动实现与讲解-编写sources文件,TARGETNAME=LED TARGETTYPE=DYNLINK RELEASETYPE=PLATFORMDEFFILE=LED.defTARGETLIBS=$(_COMMONSDKROOT)lib$(_CPUINDPATH)coredll.lib $
24、(_COMMONOAKROOT)lib$(_CPUINDPATH)ceddk.lib DLLENTRY=DllMain INCLUDES=incSOURCES=LED.c,sources的内容,指定驱动程序 DLL的入口函数,包含的inc文件夹里的文件,包含coredll.lib库,包含ceddk.lib库,定义所使用的源代码文件,定义包含 DLL 的导出的 .def 文件,指定 Nmake.exe 放置目标文件的目录,构建的文件类型为DLL,目标文件的名字为LED,3.5 流接口设备驱动及实例,数码管的流驱动实现与讲解-编写LED.def文件,LIBRARY LEDEXPORTS LED_I
25、nitLED_DeinitLED_OpenLED_CloseLED_ReadLED_WriteLED_SeekLED_IOControlLED_PowerDownLED_PowerUp,LED.def的内容,在$(_PLATFORM)Xsbase270SrcDriver LED路径下创建一个文件,名为LED.def.实现LED.def的内容. LED.def文件主要的作用:导出流接口函数.,3.5 流接口设备驱动及实例,数码管的流驱动实现与讲解-编写LED.c文件,#include #include #include #define LED_IOCTL_SET 0x00000001 #defi
26、ne LIGHT_IOCTL_SET 0x00000002#define LED_BASEADDR1 0x10200000 #define LED_BASEADDR2 0x10300000 #define LED_BASEADDR3 0x10400000#define LIGHT_BASEADDR 0x10500000,包含的头文件,定义数码管物理地址,定义LED_IOControl() 操作码,3.5 流接口设备驱动及实例,数码管的流驱动实现与讲解-编写LED.c文件,/*0 00111111 1 00000110 2 01011011 3 01001111 4 01100110 5 011
27、01101 6 01111101 7 00000111 8 01111111 9 01101111 */ #define BIT7 (0x17) #define BIT15 (0x115)BYTE NumData10=0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F;USHORT *v_pLEDBaseAddr3; USHORT *v_pLightBaseAddr = NULL;,定义数码管片选使能位,数码管二进制字形表,定义数码管字形表变量,定义数码管虚拟地址变量,3.5 流接口设备驱动及实例,BOOL LEDInit(void) PHYSI
28、CAL_ADDRESS ioPhysicalBase = LED_BASEADDR1, 0 ;v_pLEDBaseAddr0=MmMapIoSpace(ioPhysicalBase,0x400,FALSE);ioPhysicalBase.QuadPart = LED_BASEADDR2;v_pLEDBaseAddr1=MmMapIoSpace(ioPhysicalBase,0x400,FALSE);ioPhysicalBase.QuadPart = LED_BASEADDR3;v_pLEDBaseAddr2=MmMapIoSpace(ioPhysicalBase,0x400,FALSE); W
29、RITE_PORT_USHORT(v_pLEDBaseAddr1,0xffff); WRITE_PORT_USHORT(v_pLEDBaseAddr2,0xffff); return TRUE; ,这里通过函数MmMapIoSpace将数码管的物理地址转化为虚拟地址.这是由于MMU已经起来了,WinCE系统只能通过虚拟地址来操作硬件.,WRITE_PORT_USHORT函数是由CEDDK.lib库提供的.主要实现向特定的地址写数值.这里操作数码管,暂时不用.关闭数码管.,数码管初始化-编写LEDInit函数,3.5 流接口设备驱动及实例,extern BOOL DllMain(HANDLE h
30、instDLL, DWORD dwReason, LPVOID lpvReserved) BOOL bRet = FALSE;switch(dwReason)case DLL_PROCESS_ATTACH:DEBUGMSG(1,(TEXT(“DLL_PROCESS_ATTCHn“);bRet = TRUE;break;default:bRet = TRUE; return bRet; ,DllMain函数是流驱动的入口函数,一般在流驱动加载的时候,笫一个被调用.DLL_PROCESS_ATTACH参数: 意味着该DLL被加载到虚拟地址空间的当前进程.,数码管的流驱动入口实现-编写DllMain
31、函数,3.5 流接口设备驱动及实例,DWORD LED_Init(DWORD dwContext) DEBUGMSG(1, (TEXT(“+Waveform Initrn“);if(!LEDInit()return FALSE; ,一旦DllMain被调用完之后,系统紧接着调用LED_Init函数初始化硬件.而硬件的初始化又放在LEDInit函数来实现.,数码管的流接口函数实现-编写LED_Init函数,3.5 流接口设备驱动及实例,DWORD LED_Open(DWORD hDeviceContext, DWORD AccessCode, DWORD ShareMode) return TR
32、UE; ,数码管的流接口函数实现-编写LED_Open函数,3.5 流接口设备驱动及实例,DWORD LED_Write(DWORD hOpenContext, LPCVOID pSourceBytes, DWORD NumberOfBytes) return TRUE; ,数码管的流接口函数实现-编写LED_Write函数,3.5 流接口设备驱动及实例,DWORD LED_Read(DWORD hOpenContext, LPCVOID pBuffer, DWORD Count) return TRUE; ,数码管的流接口函数实现-编写LED_Read函数,3.5 流接口设备驱动及实例,vo
33、id LED_PowerDown (DWORD hDeviceContext) return; ,数码管的流接口函数实现-编写LED_PowerDown函数,3.5 流接口设备驱动及实例,void LED_PowerUp (DWORD hDeviceContext) return; ,数码管的流接口函数实现-编写LED_PowerUp函数,3.5 流接口设备驱动及实例,DWORD LED_Seek(DWORD hOpenContext, long Amount, DWORD Type) return TRUE; ,数码管的流接口函数实现-编写LED_Seek函数,3.5 流接口设备驱动及实例,
34、BOOL LED_Close ( DWORD hOpenContext) return TRUE; ,数码管的流接口函数实现-编写LED_Close函数,3.5 流接口设备驱动及实例,BOOL LED_IOControl(DWORD hOpenContext, DWORD dwCode, PBYTE pBufIn,DWORD dwLenIN, PBYTE pBufOut,DWORD dwLenOut, PDWORD pdwActualOut) INT buf=*(INT*)pBufIn; USHORT Data; ,数码管的流接口函数实现-编写LED_IOControl函数,3.5 流接口设备
35、驱动及实例, switch(dwCode)case LED_IOCTL_SET:buf=buf%10000;Data=NumDatabuf/1000;buf=buf%1000;Data|=NumDatabuf/1008; WRITE_PORT_USHORT(v_pLEDBaseAddr1,(Data|BIT7|BIT15);buf=buf%100;Data=NumDatabuf/10;buf=buf%10;Data|=NumDatabuf8;WRITE_PORT_USHORT(v_pLEDBaseAddr2,(Data|BIT7|BIT15); break; return TRUE; ,数码管
36、的流接口函数实现-编写LED_IOControl函数,LED4,LED3,LED2,LED1,确定LED1所要显示的数值,确定LED2所要显示的数值,向左移8位,是因为LED2在高八位,v_pLEDBaseAddr1为LED1和LED2的虚拟地址.这里一旦被调用完成,LED1和LED2就显示数据出来,确定LED3和LED4所要显示的数值,使LED3和LED4显示出数据来,这里数据取反,是因为数码管是共阳的.,3.5 流接口设备驱动及实例,BOOL LED_Deinit(DWORD hDeviceContext) int i=0;for(i=0;i3;i+)MmUnmapIoSpace(v_pLEDBaseAddri,0);v_pLEDBaseAddri = NULL;if (v_pLightBaseAddr) MmUnmapIoSpace(v_pLightBaseAddr,0);v_pLightBaseAddr = NULL;return TRUE; ,数码管的流接口函数实现-编写LED_Deinit函数,Thank you view reading 谢谢观阅,