WINCE官方提供的串口驱动PDD层代码简单分析

来源:互联网 发布:为什么要使用域名 编辑:程序博客网 时间:2024/06/04 19:22

WINCE官方提供的串口驱动PDD层代码简单分析

作者:FLandY1982(flandy1982@sina.com)

日期:2010-1-11

版本:1.0

修改:

转载请注明出处:http://blog.csdn.net/FLandY1982/archive/2010/01/11/5175162.aspx

 

注意:

1.关于MDD层的代码详细分析,可以参考文章:http://blog.csdn.net/FLandY1982/archive/2009/12/24/5070059.aspx

2.文中所引用的代码, 都在目录%WINCEROOT%/PUBLIC/COMMON/OAK/DRIVERS/SERIAL/

3.开发者在实现PDD层时, 可以直接继承CSerialPdd类, 然后对相关的接口进行实现和重载,也可以直接实现PDD层函数, 如果是直接实现PDD层函数本文第1章内容可以不用阅读。

 

1. PDD层代码简单分析

PDD层的主要包含了以下2个类:CSerialPDDPowerUpCallback CSerialPDD, 下面简单的分析这2个类的作用。

1.1 CSerialPDDPowerUpCallback

CSerialPDDPowerUpCallback 类用于串口电源上电时的处理。

在调用CSerialPDD::Init()后会创建一个CSerialPDDPowerUpCallback类型的对象

CSerialPDD::PowerOn()函数中会调用此对象的SignalCallBack()函数, 这样RunThread就开始运行, 进而通过调用CSerialPDD::NotifyPDDInterrupt()进行后续处理, 包括调用

CeEventHasOccurred (NOTIFICATION_EVENT_RS232_DETECTED, NULL) 通知系统有串口被探测到.

以及调用SerialEventHandler()进行MDD层上的处理.

更详细的细节可以参考微软的源代码:

%WINCEROOT%/PUBLIC/COMMON/OAK/DRIVERS/SERIAL/SERPDDCM/cserpdd.cpp

%WINCEROOT%/PUBLIC/COMMON/OAK/INC/cserpdd.h

2.2 CSerialPDD

CSerialPDD 是串口PDD层的关键,实现对硬件的操作,开发者开发的驱动就是继承这个类,并实现重载相关的函数来完成特定设备的PDD功能的。

这个类抽象了以下这些接口:

//  Tx Function.

    virtual BOOL    InitXmit(BOOL bInit) = 0;

    virtual void    XmitInterruptHandler(PUCHAR pTxBuffer, ULONG *pBuffLen) = 0;

    virtual void    XmitComChar(UCHAR ComChar) = 0;

    virtual BOOL    EnableXmitInterrupt(BOOL bEnable)= 0;

    virtual BOOL    CancelXmit() = 0 ;

//  Rx Function.

    virtual BOOL    InitReceive(BOOL bInit) = 0;

    virtual ULONG   ReceiveInterruptHandler(PUCHAR pRxBuffer,ULONG *pBufflen) = 0;

    virtual ULONG   CancelReceive() = 0;

//  Modem

    virtual BOOL    InitModem(BOOL bInit) = 0;

    virtual void    ModemInterruptHandler()= 0; // This is Used to Indicate Modem Signal Changes.

    virtual ULONG   GetModemStatus() = 0;

    virtual void    SetDTR(BOOL bSet)= 0;

    virtual void    SetRTS(BOOL bSet)= 0;

    virtual BOOL    IsCTSOff() {  return ((GetModemStatus() & MS_CTS_ON)==0) ; };

    virtual BOOL    IsDSROff() {  return ((GetModemStatus() & MS_DSR_ON)==0) ; };

//  Line Function

    virtual BOOL    InitLine(BOOL bInit) = 0;

    virtual void    LineInterruptHandler() = 0;

    virtual void    SetBreak(BOOL bSet) = 0 ;   

    virtual BOOL    SetBaudRate(ULONG BaudRate,BOOL bIrModule) = 0;

    virtual BOOL    SetByteSize(ULONG ByteSize) = 0;

    virtual BOOL    SetParity(ULONG Parity)= 0;

    virtual BOOL    SetStopBits(ULONG StopBits)= 0;

    以上这些接口都是纯虚函数, 在实现PDD层时, 必须实现这些接口.

当然不需要的功能你可以简单的用类似virtual BOOL func() {;} 的形式来实现。

其他的非纯虚函数的虚函数也可以被用户重载, 以实现自己特定的功能。

    我们知道PDD层的函数为如下函数:

GetSerialObject

This function returns a pointer to a HWOBJ structure. The structure contains the function pointers and parameters for the hardware interface functions of the relevant lower layer.

HWClearBreak

This function clears an RS-232 line break condition.

HWClearDTR

This function clears the Data Terminal Ready (DTR) signal.

HWClearRTS

This function clears the Request to Send (RTS) signal.

HWClose

This function closes the device initialized by the HWInit function.

HWDeinit

This function is called by the upper layer to de-initialize the hardware when a device driver is unloaded.

HWDisableIR

This function disables the infrared (IR) serial interface.

HWEnableIR

This function enables the infrared (IR) serial interface.

HWGetCommProperties

This function retrieves the current properties of the communications device.

HWGetIntrType

This function returns the current interrupt type.

HWGetModemStatus

This function retrieves the modem status.

HWGetRxBufferSize

This function returns the maximum number of bytes that the hardware buffer can hold, not including the padding, stop, and start bits.

HWGetRxStart

This function returns the start of the hardware-receive buffer.

HWGetStatus

This function specifies the hardware status API.

HWInit

This function initializes a serial device.

HWIoctl

This function executes device I/O control (IOCTL) routines.

HWLineIntrHandler

This function handles line interrupts for serial port devices.

HWModemIntrHandler

This function handles the modem interrupt. In the serial port upper layer implementation available in Microsoft Windows CE 3.0 and later, this function replaces the HWOtherIntrHandler function.

HWOpen

This function is called by the upper layer to open the serial device.

HWOtherIntrHandler

In Windows CE 3.0 and later, this function has been replaced with the new function HWModemIntrHandler.

HWPostInit

This function performs necessary operations after it initializes all data structures and prepares the serial IST to begin handling interrupts. It is called by the upper layer.

HWPowerOff

This function notifies the platform-dependent driver that the hardware platform is about to enter suspend mode. It is called by the model device driver (MDD).

HWPowerOn

This function notifies the platform-dependent driver that the hardware platform is resuming from suspend mode. It is called by the MDD.

HWPurgeComm

This function purges the communications device.

HWPutBytes

This function writes bytes to hardware. The driver calls this function.

HWReset

This function resets the hardware API.

HWRxIntrHandler

This function handles serial port interrupts.

HWSetBreak

This function sets the line break condition on the transmit line.

HWSetCommTimeouts

This function sets the communications time-out events in response to a call to the SetCommTimeouts function.

HWSetDCB

This function sets the device control block.

HWSetDTR

This function sets the Data Terminal Ready (DTR) signal.

HWSetRTS

This function sets the Request to Send (RTS) signal.

HWTxIntrHandler

This function handles the transmit interrupt for serial port devices.

HWXmitComChar

This function transmits a single character.

   

更具体的细节可以参考:MSDN帮助 ms-help://MS.WindowsCE.500/wceddk5/html/wce50grfserialportdriverfunctions.htm

    微软用一堆SerXXXXX()的函数封装了CSerialPdd相关的操作,来完成PDD功能。

2. PDDMDD层的交互

2.1 PDD层的函数是如何能够被MDD层所调用

1.2节介绍的那一堆SerXXXXX()函数会被记录到一个函数指针表里,真是通过这个函数指针表来实现与MDD层的交互的。此函数指针表是HW_VTBL类型的, 在微软的代码里是命名为IoVTbl的函数指针表。

    MDD层通过调用 GetSerialObject(DWORD DeviceArrayIndex)函数来获取一个HWOBJ结构的指针, 这个结构包含以下成员:

    ULONG  BindFlags; // Flags controlling MDD behaviour.  Se above.

    DWORD   dwIntID;   // Interrupt Identifier used if THREAD_AT_INIT or THREAD_AT_OPEN

    PHW_VTBL   pFuncTbl;

    其中pFuncTbl正是指向我们之前说到的 IoVTbl 函数指针结构的地址.

这样MDD层就可以通过->pFuncTbl.DDSIFunction()来对特定的硬件做特定的操作了.

2.2 GetSerialObject函数

这个函数的原型是:PHWOBJ GetSerialObject(DWORD DeviceArrayIndex) ,它是连接MDDPDD层的关键函数, 也是实现多端口驱动的关键, 这个函数允许一个MDD层连接多个PDD层。

MDD层的COM_Init函数中,驱动会通过查询DeviceArrayIndex键值, 得到我们需要打开的是普通串口或者是其他种类的串口设备。

而正是这个数值决定了GetSerialObject是返回哪个串口的PHWOBJ指针, PHWOBJ包含了pFuncTbl,这个正是前一节说到的PDD层函数指针表,通过这个函数表我们就可以实现对相应的串口设备进行操作。(串口有可能是标准的串口,也有可能是红外设备)

 

2.3 CreateSerialObject 函数

如果开发者选择直接继承微软CSerialPdd类来实现串口的PDD层,还要实现CreateSerialObjectDeleteSerialObject函数。

MDD层的COM_Init函数被调用时,驱动会通过查询注册表来得到相关参数并调用PDD层的HWInit函数,HWInit函数又会调用CreateSerialObject来初始化串口设备,在关闭串口以后DeleteSerialObject函数会被调用。

3. 其他

3.1 COM_Init函数如何被调用

此函数通常是由Device.exe进程调用的, 而此函数的参数Identifier 是一个指向注册表HKEY_LOCAL_MACHINE/Drivers/Active.下的一个键值,这也是决定驱动如何操作硬件的关键。

对于使用ActivateDeviceEx函数调用的情况,请参照MSND, http://msdn.microsoft.com/en-us/library/aa447677.aspx

3.2 相关代码段: