2.3.3 函数库ttyDrv.c

前面主要分析了vxWorks系统IO设备管理的通用数据结构及其操作,这个通用接口既适用于串口类设备、又适用于网络设备等等。对于串口这类设备来说,其驱动又有其独有的要求,如收发缓存的管理,波特率的设置等等。同样,作为串口驱动的部分,也可以分为与硬件相关部分和与硬件无关部分。

VxWorks操作系统的串口驱动与硬件无关部分主要有两个函数库来实现,一是ttyDrv函数库,主要用于7个通用函数中的5个函数的具体实现,另一个是tyLib函数库,主要用于处理收发缓冲区的处理。另一方面,从结构TYCO_DEV来看,tyLib的主要数据结构TY_DEV变量包含在结构TYCO_DEV,因此其层次关系可以用图2.12所示。

VxWorks UART Driver

图2.12 函数库ttyDrv与tyLib的层次关系

函数库ttyDrv主要通过结构SIO_CHAN访问底层函数,在结构TYCO_DEV中有一个SIO_CHAN结构变量指针,该变量指针指向底层的操作函数。如图13所示。

VxWorks UART Driver

图2.13 ttyDrv库与底层库的函数接口

首先分析ttyDrv函数库,这个函数库比较简单,直接分析各个函数。

1. STATUS ttyDrv (void)

函数ttyDrv主要调用了函数iosDrvInstall完成了7个函数的安装,对串口来说,系统并不要完全安装这7个函数,比如delete函数,如果操作系统不要求delete串口驱动,那么这个函数也就不需要了。实际上ttyDrv函数主要安装了基本操作函数,如图2.14。

VxWorks UART Driver

图2.14 函数ttyDrv主要安装的函数

这些函数中有ttyOpen、ttyClose、ttyIoctl是由函数库ttyDrv.C提供的,其他函数如tyRead、tyWrite则是由函数库tyLib提供的。


2. STATUS ttyDevCreate

    (

    char *      name,

    SIO_CHAN * pSioChan,

    int         rdBufSize,

    int         wrtBufSize

    )

这个函数为一个tty设备创建了一个TYCO_DEV数据结构并进行初始化(包括硬件的初始化)。其中pSioChain是底层串行通道描述符(SIO_CHAN结构变量)的地址。rdBufSize和wrtBufSize为读写缓冲区的大小。

ttyDevCreate函数在执行过程中调用了函数tyDevInit对tyLib库进行了初始化。注意调用函数tyDevInit的最后一个参数ttyStartup,这个函数对底层操作函数(pSioChan)->pDrvFuncs->txStartup进行了封装,也就是说只有函数ttyDrv直接与底层硬件操作函数向关联,而tyLib库则完全被保护在了硬件无关层(参见图2.12)。

ttyDevCreate()函数操作的数据结构如图2.15所示。同时它指定了串口的处理模式为中断模式(另一种为轮询模式)。

VxWorks UART Driver

图2.15 ttyDevCreate()函数操作的数据结构

注意这个函数和ioLib库中的create函数是完全不同的概念,该函数的调用应该在create之前。



3. LOCAL int ttyOpen

    (

    TYCO_DEV * pTyCoDev,

    char     * name,

    int flags,

    int         mode

    )

打开一个ttyDrv串行设备。所谓打开设备就是使其处于准备收发数据的状态,对i8250串口控制芯片来说就是设定计算机准备接收(DTR)和请求发送数据(RTS)的状态。

注意:每调用一次函数ttyOpen,该pTyCoDev->tyDev.numOpen就会自动加1,表明该设备打开的次数。



4. LOCAL int ttyClose

    (

    TYCO_DEV * pTyCoDev

    )

关闭一个ttyDrv设备。所谓关闭设备就是就是关闭其收发数据就绪的状态。

注意:每调用一次函数ttyClose,pTyCoDev->tyDev.numOpen就会自动减1,表明该设备打开的次数。



5. LOCAL int ttyIoctl

    (

    TYCO_DEV * pTyCoDev,

    int request,

    void * arg

    )

对硬件设备的控制操作。

request是一个比较广义的操作,包含的种类繁多,而且对同样的操作,对不同的函数库来说,参数也可能会有所不同,如波特率设置,在ttyDrv库request为FIOBAUDRATE,这个参数在iosLib.h中定义,而在sioLib库中该参数为SIO_BAUD_SET,因此需要进行参数的转换;另一方面sioIoCtl函数和tyIoCtl函数处理的职责是不同的,因此需要首先尝试调用sioIoCtl函数,如果无此操作则尝试tyIoCtl函数。



6. LOCAL void ttyStartup

    (

    TYCO_DEV *pTyCoDev

    )

发送数据函数。直接调用底层的发送函数。

在函数ttyDrv中调用iosDrvInstall函数安装了两个函数tyRead和tyWrite,这两个函数并在函数库ttyDev中,而是在tyLib库中。主要完成收发缓冲区的处理,下面要进行tyLib库的分析。