WinCE串口驱动分析
时间:04-11
来源:
点击:
MDD部分
由于串口驱动由Device.exe直接调用,所以MDD部分是以完整的Stream接口给出的. 也就具备基于Stream接口的驱动程序所需的函数实现,包括COM_Init,COM_Deinit
,COM_Open,COM_Close ,COM_Read ,COM_Write, COM_Seek,, COM_PowerUp, COM_PowerDown, COM_IOControl几个基本实现。由于串口发送/接收的信息并不能定位,而仅仅是简单的传送,所以COM_Seek仅仅是形式上实现了一下。
COM_Init
COM_Init是该驱动的初始化函数,在设备管理器加载该驱动后首先调用,用于初始化所需的变量,硬件设备等资源。该过程分配代表设备硬件实例的数据结构,并通过硬件抽象接口HWInit初始化硬件。同时该函数会调用InterruptInitialize为接收内核中的逻辑中断创建相应事件并初始化临界区。该函数还需要得到硬件缓冲器的物理地址和获知该缓冲器的大小(该冲器最小为2K)。最后它将建立相应的缓冲作为接收的中介。下面我们来看这个函数的实现过程。
在函数中定义了两个重要的变量。pSerialHead和pHWHead.前者用于描述相应的串口的状态,后者则是对应硬件的数据抽象。首先为pSerialHead分配空间和初始化链表和临界区等数据并同时为接收和发送中断创建事件。然后再从注册表中获得当前的注册项值(由于device.exe是根据注册表键值来调用驱动的,当前键注册表项指的就是与上述键值在同一根下的注册项)。得到DeviceArrayIndex、Priority256键下的具体值后就可以调用GetSerialObject(在PDD中实现)来获得具体的HWObj对象,并通过该对象来调用硬件初始化函数了。(由于在这里已经对硬件进行了初始化,之后的返回都需要调用COM_Deinit来完成。)由于硬件初始化(实际的驱动初始化代码)已经得到执行这个时候就只有分配和初始化缓冲的工作需要做了。所以调用HWGetRxBufferSize(PDD代码)来获取PDD中设定的缓冲大小,并根据返回的具体值分配缓冲。最后如果BindFlags被设定为THREAD_AT_INIT就再调用StartDispatchThread启动分发线程(实际的IST)。这样就完成了系统初始化的操作。
COM_Deinit
当驱动被称被卸下的时候该事件启动,用作与COM_Init相反的操作。这个过程大致会释放驱动中所使用的资源,停止期间创建的线程等操作。具体说来,大致为停止在MDD中的所有IST,和释放内存资源和临界区等系统资源。同时还需调用HWDeinit来释放PDD中所使用到的系统资源。
COM_Open
COM_Oepn在CreateFile后被调用,用于以读/写模式打开设备,并初始化所需要的空间/资源等,创建相应的实例,为后面的操作做好准备。这里的代码相对比较容易,下面就简单讲一下。既然是初始化,肯定就免不了对参数的检查。首先检查通过COM_Init返回的pHead结构是否有效,这里虽然没有显式的在这两个函数之间传递参数,而是在设备管理器的内部传递这个参数的。
之后是检查文件系统传递过来的Open句柄中的Open模式是否有效,这个参数由应用程序产生,通过文件系统直接传递到驱动。之后就开始初始化的操作,在这里将会建立相应的HW_OPEN_INFO实体。下面和为该结构的定义。
typedef struct __HW_OPEN_INFO {
PHW_INDEP_INFO pSerialHead; // @field Pointer back to our HW_INDEP_INFO
DWORD AccessCode; // @field What permissions was this opened with
DWORD ShareMode; // @field What Share Mode was this opened with
DWORD StructUsers; // @field Count of threads currently using struct.
COMM_EVENTS CommEvents; // @field Contains all in…. handling
LIST_ENTRY llist; // @field Linked list of OPEN_INFOs
} HW_OPEN_INFO, *PH
结构中的第一个参数指向我们前面提到的HW_INDEP_INFO结构,第二个参数为操作权限码,也就是READ/WRITE这类的权限。第三个参数为共享模式,以确定是否支持独占。这两个参数都是与文件系统的内容对应的。而CommEvent则对应于本实例的事件。由于驱动架构支持多个OPEN操作实例的存在,所以这里维护了一个链表来联系这些结构。在这里由于IST的启动可以在COM_Init和COM_Open中进行,还有处理器启动IST的内容。准备好HW_OPEN_INFO结构后就可以调用HWOpen(PDD)来进行PDD所需的Open操作了。Open操作完成后调用HWPurgeComm(PDD)来处理(取消或等待)当前仍在通讯状态的任务。然后重置软件FIFO就基本完成了COM_Open的动作了。
事实上这里主要是对所需的数据结构进行处理,对于硬件的具体操作都留给PDD去做了,MDD所维护的仅仅是一个架构性的代码。Open操作完成后,驱动就进入了工作状态这个时候。
Top