驱动程序的基础知识
1、驱动程序的功能
为应用程序提供接口,上层应用程序无需知道这台机器上硬件是什么型号,只要调用系统的函数就可以实现相应的功能。而驱动程序就是和硬件打交道,为上层提供服务,实现对下层的操作。
2、何时编写驱动程序
操作系统没有内置支持的硬件(常见)一些第三方或者自制的硬件,操作系统没有相应的驱动
扩展已有的驱动 为了是想更多的功能
提供软件层面的服务 并不是所有的驱动都和硬件相关,有时候可以提供软件层面服务---伪驱动
3、驱动程序的模型
分层,为了实现复用,并且更好维护。
4、编写驱动程序的几个要素
了解驱动所针对的硬件(看好白皮书)
要了解目标操作系统下驱动的工作机制(如何加载、卸载、初始化、中断方式、DMA等)
了解驱动模型
wince驱动程序
1、wince驱动程序开发简介
驱动和操作系统一起启动,一起关闭,效率高,但是不灵活;另一种就是动态加载。
wince 驱动程序运行在用户态
和win32DLL一样,有以下优点:
用户态,比较稳定(不会影响到内核)
给驱动开发人员提供便利
2、wince驱动程序的宿主
device.exe外设
gwes.exe图形
filesys.exe文件
加载自己负责的相关方面的驱动
3、分层驱动和单体驱动
分层驱动也就是考虑到架构,将一些外设的共性抽象出来,作为不变的一层,提供中间层函数,而底层与硬件交互实现中间层的函数。这样简化底层,容易维护。
单体,就是把上面几层写到一起了,有时候比较方便。
4、驱动分类
wince支持很多驱动(分层、单体)---电池、鼠标、触摸屏、蓝牙、wifi、显卡。。。。。
5、实例
pb中有很多实例,特别是public目录下的,都是微软提供的一些公共的驱动程序,与平台无关的。
设备管理器
1、设备管理器简介
设备管理器主要职责:
管理驱动程序,加载、卸载、初始化,提供宿主进程,提供电源管理接口。负责IO管理
2、设备的初始化
device.exe启动后先初始化自身后,然后又枚举总线加载和初始化所有内置外设(递归遍历)。
3、设备的管理
名称:三个大写字母+“0-9”,\$device\COM7,\$bus\PCMCIA_0_0_0.
应用程序的通知:requestDeviceNotification()向设备管理器社情发送通知。
中断处理
1、wince中断的概念
大多数设备都会产生中断来请求操作系统服务,一般情况下,外设不占用cpu,只有当他工作时,才会通过中断来打断cpu当前的执行。
2、中断处理过程
首先硬件外设产生一个中断,然后跳转到中断处理程序处执行。中断处理程序位于操作系统内核中,是一段非常短小的代码,所有的硬件中断都会被中断处理程序捕获并处理
其次,中断处理程序调用自己已经注册的isr来决定如何处理这个硬件中断。isr是OAL中实现的,isr通常向内核返回一个值,内核根据isr的返回值决定如何处理中断。
最后,驱动程序中的IST将会开始运行。ist用关联的sysintr_XXX值来调用interuptDone()函数,通知内核已经完成对中断的处理。
3、中断服务例程ISR
isr是运行在内核中的一段代码,通常有OEM实现。isr工作过程如下:
1、调用PICGetCurrentInterrupt获取当前中断。
2、吐过中断是INTR_TMER0,那么更新CurMSec波爱吃时间,检查并确认是否已经注册了启动地址RebootHandler
3、如果中断是INTR_RTC,那么isr检查并确认闹钟是否过期
4、如果中断小于INTR_MAXIMUM,那么调用中断链NKCallIntrChain,并将他的返回值设为临时返回值。
5、如果中断链末包含中断,则通过OEMT燃烧lateIRQ映射当前硬件中断,并得到它返回的SYINTR值。通常OEMInit()函数中注册过该中断,则OEMT燃烧lateIRQ返回逻辑中断号,否则返回SUSINTR_NOP
6、调用PICEnableInterrupt,启用除当前中断以外的所有中断
7、完成恰当的中断,结束工作,通知PIC中断已完成。
4、中断服务线程IST
ist是一个普通的用户线程,它负责处理相应中断的大多数操作。操作系统通知ist有中断发生,ist开始工作。这是通过把中断号与一个win32的同步对象关联实现的。中断发生,操作系统引发逻辑中断关联的事件。
5、中断的延时和实时
isr延迟因素:
中段被关闭的时间
总线指令锁定处理器的时间
内核isr的执行时间加上导向isr的时间
ist延迟的因素:
isr延迟时间
isr执行时间
os执行系统调用时间
调度ist时间
访问物理内存
搞懂几个函数:
virtualAlloc()
virtualCopy()
MmMapIoSpace()
MmUnmapIoSpace()
DMA
1、简介
是一种快速传送数据的机制。可以从外部设备到内存,从内存到外部设备或者从一段内存到另一段内存。dma技术重要性在于,进行数据传输不需要cpu的参与,大大提高了cpu的利用率。
2、CEDDK函数
HalAllocateCommomBUffer()
HalFreeCommonBuffer()
HalTranslateSystemAddress()
3、内核函数
AllocPhysMem()
FreePhysMem()
使用驱动开发的库函数
1、CEDDK库
提供CEDDK的一个原因就是希望对驱动程序提供一层硬件抽象。当驱动程序访问硬件时,希望可尽量通过CEDDK函数访问,而不是直接对硬件进行读写操作。
另外就是它是一个动态链接库,提供大量的函数来完成驱动程序一些常用的操作,如,总线地址翻译,设备地址映射,dma缓冲设置,io处理等。
2、注册表
很多驱动的配置信息都放在了注册表中,这样有利于驱动程序的通用性。
流式驱动
1、简介
任何暴漏流式接口函数的驱动程序都可以被称为流式接口驱动
2、接口函数
XXX_Open()
XXX_Close()
XXX_Init()
XXX_Deinit()
XXX_Read()
XXX_Write()
XXX_Seek()
XXX_IOctrl()
XXX_PowerUp()
XXX_PoerDown()
XXX_PreClose()
XXX_PreDeinit()
3、工作原理
1、加载驱动程序。加载方式有两种:一种是系统启动时,设备管理器搜寻注册表HKEY_LOCAL_MACHINE\Drivers\BuiltIn键下面的子键,并逐一加载子键下的每一个驱动,此过程称为BusEnum;另外一种就是应用程序可调用ActivateDeviceExe()函数动态加载驱动程序。
2、设备管理器从注册表的dll键值中获取驱动程序所在的dll文件名。
3、设备管理器调用LoadDriver()函数吧dll加载到自己的虚拟地址空间。
4、注册表machine下drivers下active记录已经加载的驱动记录。
5、设备管理器调用驱动中的SMP_Init函数,并把上一步中添加的注册表项的完整路径作为SMP_Init()函数第一个参数传入驱动程序内。
6、在SMP_Init中,通常对硬件进行一些最基本得初始化操作。
7、调用CreateFile函数
8、设备管理器调用SMP_Open函数打开设备
9、成功打开后,然后读写
4、实现
4个步骤:
为流式接口驱动选择一个前缀
实现流式接口驱动DLL所必须的接口函数
编写DLL的导出函数定义文件.DEF
为驱动程序配置注册表
5、运行
编写应用程序
调用接口函数
查看运行状况
了解驱动所针对的硬件(看好白皮书)
里阿杰目标操作系统下驱动的工作机制(如何加载、卸载、初始化、中断方式、DMA等)
了解驱动模型
了解驱动所针对的硬件(看好白皮书)
里阿杰目标操作系统下驱动的工作机制(如何加载、卸载、初始化、中断方式、DMA等)
了解驱动模型