WinCE5.0 SMDK2410 BSP的串口驱动由两个文件组成.一个在BSP目录下的/SRC/DRIVERS/SERIAL/ser_smdk2410.cpp,另一个在/WINCE500/PUBLIC/COMMON/OAK/CSP/ARM/SAMSUNG/S3C2410X/SERIAL/pdds3c2410_ser.cpp,为了实现BSP的完整性,并方便修改,在移植到GEC2410的时候,将该目录下的所有文件放到BSP目录下,特别的对于串口驱动,我把pdds3c2410_ser.cpp同样也放到BSP目录/SRC/DRIVERS/SERIAL/下,只需修改下source文件,将pdds3c2410_ser.cpp加入编译文件即可.
SOURCES= ser_smdk2410.cpp /
pdds3c2410_ser.cpp
其实在WinCE6.0的DEVICEEMULATOR BSP下就是采用这样的目录文件结构.
接下来我们就进入正题.
一. 驱动结构
串口驱动是个流接口驱动,其中流接口函数,比如COM_Init,COM_Open,COM_Read,COM_Write等实现在MDD库com_mdd2.lib中(/WINCE500/PUBLIC/COMMON/OAK/DRIVERS/SERIAL/COM_MDD2/mdd.c),同样还有一个PDD的库serpddcm.lib(/WINCE500/PUBLIC/COMMON/OAK/DRIVERS/SERIAL/SERPDDCM/cserpdd.cpp),这个实际上相当于PDD COMMON层,也是平台无关的.
BSP目录下的SERIAL驱动实际上是真正的PDD层,与实际硬件平台相关的代码.
这里先简单分析下MDD,PDD COMMON和PDD的结构,三者是如何联系的.
MDD(mdd.c)实现了COM_**的流接口函数,中间调用了PDD COMMON层的函数,而PDD COMMON又调用PDD的函数.其中前两者的联系在COM_Init中的:
pSerialHead是HW_INDEP_INFO结构的指针,相当于串口设备的句柄,定义在serpriv.h.里面包含串口设备各项信息.
pHWObj是HWOBJ结构的指针.HWOBJ是HW_INDEP_INFO成员,被称作硬件相关数据.在serhw.h中定义如下:
其中pFuncTbl指向的函数指针数组HW_VTBL就是PDD COMMON层(cserpdd.cpp)中实现的各个函数,如SerInit,SerOpen等,如下代码所示:
COM_Init通过调用GetSerialObject来获得相应PDD的HWOBJ结构,GetSerialObject是MDD连接PDD的关键函数,而DeviceArrayIndex对应的就是串口的端口序号,一个端口序号对应一个UART端口,也对应一个串口驱动程序PDD层运行时代码,这个值可以从注册表中DeviceArrayIndex项获得.
COM_Init函数调用GetSerialObject将DeviceArrayIndex传递到HWOBJ的dwIntID成员再传给CreateSerialObject函数.这样COM_Init通过适用不同的参数调用GetSerialObject就可以获得同一平台上同时存在不同串口的PDD对象,可以使多个PDD对象共享一个MDD.
以下是GetSerialObject的代码,位于cserpdd.cpp,获得了PDD COMMON中的HW_VTBL结构的函数指针,同时将DeviceArrayIndex传递给dwIntID.
COM_Init中的:
pHWHead = pSerialHead->pHWObj->pFuncTbl->HWInit(Identifier, pSerialHead, pSerialHead->pHWObj);
pSerialHead->pHWHead = pHWHead;
HWInit实际上调用的就是cserpdd.cpp中的SerInit,它将调用CreateSerialObject函数来获得串口驱动的PDD层.实际上就是返回PDD中需要实现的串口类的指针.
CreateSerialObject定义在PDD层,这里是Ser_smdk2410.cpp中的代码:
这里的CPdd2410Serial1和CPdd2410Serial2就是PDD需要实现的两个类,分别对应UART0和UART1.下一篇我们就来详细看看串口驱动的PDD层.
关于MDD层更详细的内容,可以参考这篇文章:
http://nasiry.cnblogs.com/archive/2005/04/12/136175.html