Wince串口分析

来源:互联网 发布:淘宝 一元起拍入口 编辑:程序博客网 时间:2024/06/10 17:42

Wince的串口模型是固定的,其网络协议是符合ISO/OS模型的,在典型的应用中,serialAPI与间接通过TAPI或直接与ActiveSync交互,组成CE网络的一部分。其实整个驱动模型是相当复杂的,好在驱动仅仅使用到SerialAPI这一层,在这个层次上串口的行为相对比较简单。在WinCE中,串口驱动模型是作为Stream来实现的(即:流设备驱动)。

串口驱动本身分为PDD层和MDD层:

MDD层提供了框架性的实现,负责提供OS所需的的基本实现,它为上层的设备管理器提供标准的流驱动接口(COM_XXX),而PDD层是针对串口硬件的相应操作,PDD层主要实现了HWOBJ结构以及结构中关于串口硬件的函数指针,在MDD层和PDD层之间有一个DSSI的接口,这个接口是人为设定的,在串口驱动中这个接口主要指的是HWOBJ结构体,PDD层会传给MDD层一个HWOBJ结构体指针,这样MDD层就可以通过HWOBJ来调用PDD层的函数来操控串口硬件了,在实际的开发中我们只需要实现MDD层的相关函数就可以对串口进行操作了。

具体函数分析:

数据结构

1.HWOBJ结构体:

typedef struct __HWOBJ 
{  
    ULONG BindFlags;  
    DWORD dwIntID;  
    PHW_VTBL pFuncTbl; 
} HWOBJ, *PHWOBJ; 
BindFlags:用于控制MDD层如何来处理IST,具体值如下:          
                  THREAD_IN_PDD:MDD层不处理,中断在PDD层处理。            
                  THREAD_AT_INIT:在驱动初始化的时候,MDD层启动IST。            
                  THREAD_AT_OPEN:在驱动被Open的时候,MDD层启动IST。 
dwInitID: 系统的中断号 ,

pFuncTbl: 指向一个PHW_VTBL结构,该结构中包含一个函数指针列表,这些函数指针指向串口硬件操作函数,用于操作串口,

2.PHW_VTBL结构体定义了一系列指向串口硬件的指针:

typedef struct __HW_VTBL    {
    PVOID (*HWInit)(ULONG Identifier, PVOID pMDDContext, PHWOBJ pHWObj);
    BOOL (*HWPostInit)(PVOID pHead);
    ULONG (*HWDeinit)(PVOID pHead);
    BOOL (*HWOpen)(PVOID pHead);
    ULONG (*HWClose)(PVOID pHead);
    INTERRUPT_TYPE (*HWGetIntrType)(PVOID pHead);
    ULONG (*HWRxIntrHandler)(PVOID pHead, PUCHAR pTarget, PULONG pBytes);
    VOID (*HWTxIntrHandler)(PVOID pHead, PUCHAR pSrc, PULONG pBytes);
    VOID (*HWModemIntrHandler)(PVOID pHead);
    VOID (*HWLineIntrHandler)(PVOID pHead);
    //ULONG (*HWGetRxBufferSize)(PVOID pHead); // orginal MDD
    ULONG (*HWGetRxBufferSize)(PVOID pHead, PULONG pBufaddr); // tcc modify
    BOOL (*HWPowerOff)(PVOID pHead);
    BOOL (*HWPowerOn)(PVOID pHead);
    VOID (*HWClearDTR)(PVOID pHead);
    VOID (*HWSetDTR)(PVOID pHead);
    VOID (*HWClearRTS)(PVOID pHead);
    VOID (*HWSetRTS)(PVOID pHead);
    BOOL (*HWEnableIR)(PVOID pHead, ULONG BaudRate);
    BOOL (*HWDisableIR)(PVOID pHead);
    VOID (*HWClearBreak)(PVOID pHead);
    VOID (*HWSetBreak)(PVOID pHead);
    BOOL (*HWXmitComChar)(PVOID pHead, UCHAR ComChar);
    ULONG (*HWGetStatus)(PVOID pHead, LPCOMSTAT lpStat);
    VOID (*HWPreDeinit)(PVOID pHead);
    VOID (*HWGetModemStatus)(PVOID pHead, PULONG pModemStatus);
    VOID (*HWGetCommProperties)(PVOID pHead, LPCOMMPROP pCommProp);
    VOID (*HWPurgeComm)(PVOID pHead, DWORD fdwAction);
    BOOL (*HWSetDCB)(PVOID pHead, LPDCB pDCB);
    BOOL (*HWSetCommTimeouts)(PVOID pHead, LPCOMMTIMEOUTS lpCommTO);
    BOOL    (*HWIoctl)(PVOID pHead, DWORD dwCode,PBYTE pBufIn,DWORD dwLenIn,
                       PBYTE pBufOut,DWORD dwLenOut,PDWORD pdwActualOut);
    } HW_VTBL, *PHW_VTBL;

这些对串口的操作包括初始化,打开,关闭,加载,注销等操作,很多设置是针对9针串口(DCD,RXD,TXD,DTR,GND,DSR,RTS,CTS,DELL)的,相对于我们常用的3针串口(RXD,TXD,GND),9针串口大多用于modem模式,这些函数的具体功能在MSDN上是可以查到的。

3.typedef struct __HW_INDEP_INFO {
CRITICAL_SECTIONTransmitCritSec1;// @field Protects tx action
CRITICAL_SECTIONReceiveCritSec1;       // @field Protects rx action


PHWOBJ pHWObj; // @field Represents PDD object.
    PVOID         pHWHead;// @field Device context for PDD.
    
HANDLE hSerialEvent; // @field Serial event, both rx and tx
HANDLE hReadEvent; // @field Serial event, both rx and tx
HANDLE hKillDispatchThread; // @field Synchonize thread end
HANDLE hTransmitEvent; // @field transmit event, both rx and tx
HANDLE pDispatchThread; // @field ReceiveThread 
ULONG Priority256;   // @field CeThreadPriority of Dispatch Thread.
ULONG DroppedBytesMDD;// @field Record of bytes dropped by MDD.
ULONG DroppedBytesPDD;// @field Record of bytes dropped by PDD.
ULONG RxBytes;   // @field Record of total bytes received.
ULONG TxBytes;   // @field Record of total bytes transmitted.
ULONG TxBytesPending;// @field Record of total bytes awaiting transmit.
ULONG TxBytesSent;// @field Record of bytes sent in one transmission
DCB DCB;// @field DCB (see Win32 Documentation.
COMMTIMEOUTS CommTimeouts; // @field Time control field. 
DWORD OpenCnt;// @field Protects use of this port 
DWORD KillRxThread:1;// @field Flag to terminate SerialDispatch thread.
DWORD XFlow:1;// @field True if Xon/Xoff flow ctrl.
DWORD StopXmit:1;// @field Stop transmission flag.
DWORD SentXoff:1;// @field True if XOFF sent.
DWORD DtrFlow:1;// @field True if currently DTRFlowed
DWORD RtsFlow:1;// @field True if currently RTSFlowed
DWORD           fAbortRead:1;   // @field Used for PURGE
        DWORD           fAbortTransmit:1;// @field Used for PURGE
DWORD Reserved:24;// @field remaining bits.
ULONG        fEventMask;// @field Sum of event mask for all opens
RX_BUFFER_INFORxBufferInfo;// @field rx buffer info.
TX_BUFFER_INFOTxBufferInfo;// @field tx buffer info.

    LIST_ENTRY      OpenList;       // @field Head of linked list of OPEN_INFOs    
CRITICAL_SECTION OpenCS;  // @field Protects Open Linked List + ref counts

    PHW_OPEN_INFO   pAccessOwner;   // @field Points to whichever open has acess permissions
} HW_INDEP_INFO, *PHW_INDEP_INFO;

这个结构体是独立于串口硬件的头信息,这个结构体定义了一系列与串口操作有关的变量接收,发送缓存,字节数,事件等等,具体功能要参见源码中的实现。

MDD层:

下面正式介绍与我们开发密切相关的MDD层驱动模型,串口驱动的MDD层实现是标准的流驱动,包括:

1.COM_Init (ULONG Identifier):

    它是该驱动的初始化函数,通过硬件抽象接口HWInit初始化硬件。如果驱动被设备管理器加载,参数Identifier包含一个注册表键值在“HKEY_LOCAL_MACHINE\Drivers\Active”的路径下。

2.COM_Deinit(void):

当驱动被称被卸下的时候该事件启动,用作与COM_Init相反的操作。停止在MDD中的所有IST,释放内存资源和临界区等系统资源。

3.COM_Open(HANDLE pContext, DWORD AccessCode, DWORD ShareMode):

COM_Oepn在CreateFile后被调用,用于以读/写模式打开设备,并初始化所需要的空间/资源等,创建相应的实例。Open操作完成后,驱动就进入了工作状态。

4.COM_Close(DWORD pContext):

COM_Close释放COM_Open所使用的系统资源,停止IST线程,恢复驱动状态。

5.COM_Read(HANDLE pContext, PUCHAR pTargetBuffer,

    ULONG BufferLength, PULONG pBytesRead):

COM_Read是获取串口所接收到数据的操作,在前面的IST中没有看到对RX buffer进行修改Read标记的操作,也就是这儿来完成的。

6.COM_Write(HANDLE pContext, PUCHAR pSourceBytes,

   ULONG NumberOfBytes):

COM_Write是与COM_Read相对应的操作,是写串口数据的。应用程序调用WriteFile函数写串口的时候,该函数被调用。在程序的开始,同样也是参数检查,内容与COM_Read一致。其中pContext参数是COM_Open函数返回的Handle。pSourceBytes指向一个Buffer,该Buffer包含要写入串口的数据。NumberOfBytes表示要写入串口的数据的大小。

7.COM_PowerUp/ COM_PowerDown (HANDLE pContext):

这两个函数的调用都由CE的电源事件来引发,MDD并没有对这两个函数进行处理,仅仅是将其传递给PDD。

8.COM_IOControl (DWORD dwOpenData, DWORD dwCode, PBYTE pBufIn, DOWRD dwLenIn, PBYTE pBufOut, DWORD dwLenOut, PDWORD pdwActualOut):

该函数主要实现了一些串口的IO控制,他会被应用层的一些串口函数调用来获得或者设置串口的状态。

PDD层:

实际上,在PDD层的主要工作就2个:一是控制硬件;二是和上层打好关系。先说上层接口,上层用了GetSerialHead()来获得接口,所以PDD里面要实现GetSerialHead()的函数,并且将接口返回给上层。

GetSerialObject( DWORD DeviceArrayIndex )

{

    PHWOBJ pSerObj;

    pSerObj=(PHWOBJ)LocalAlloc( LPTR ,sizeof(HWOBJ) );

    if ( !pSerObj )

        return (NULL);

    pSerObj->BindFlags = THREAD_IN_PDD;

    pSerObj->dwIntID = DeviceArrayIndex;

    pSerObj->pFuncTbl = (HW_VTBL *) & IoVTbl;

    return (pSerObj);

}

PDD层的函数主要是实现了对串口硬件的操作,函数不少,可以参考以下列表

序号

函数

说明

1

GetSerialObject

返回一个指向HWOBJ结构的指针,该结构包含了相关硬件接口函数的函数指针

2

HWClearBreak

清除串口中断状态,用于串口从中断状态恢复

3

HWClearDTR

设置串口的DTR管脚为低

4

HWClearRTS

设置串口的RTS管脚为低

5

HWClose

关闭由HWInit函数初始化的设备

6

HWDisableIR

禁用串口的红外模式

7

HWEnableIR

启用串口的红外模式

8

HWGetCommProperties

重新获得当前串口设备的硬件属性

9

HWGetIntrType

获得当前的中断类型

10

HWGetModemStatus

获得Modem的状态

11

HWGetRxBufferSize

获得串口硬件接收Buffer的大小

12

HWGetRxStart

返回硬件接收Buffer的起始位置

13

HWGetStatus

获得硬件状态信息

14

HWInit

初始化串口硬件设备

15

HWIoctl

执行I/O控制

16

HWLineIntrHandler

线路状态信息中断处理函数

17

HWOpen

打开串口设备

18

HWPowerOff

串口硬件进入Suspend模式

19

HWPowerOn

串口硬件从Suspend模式恢复到工作模式

20

HWSetDCB

设置串口硬件设备信息

21

HWSetDTR

设置串口的DTR管脚为高

22

HWSetRTS

设置串口的RTS管脚为高

23

HWPurgeComm

清除串口硬件buffer的信息

24

HWPutBytes

通过写数据到硬件中来直接发送数据

25

HWReset

复位串口硬件

26

HWRxIntrHandler

接收数据中断处理函数

27

HWSetBreak

设置串口为中断状态,停止发送接收数据

28

HWTxIntrHandler

串口发送中断处理函数



原创粉丝点击