2.3.4 函数库tyLib

tyLib函数在ttyDrv库与底层硬件操作之间建立了一个收发缓冲区,当上层函数需要接收数据时并不是直接读取硬件的接收寄存器,而是调用函数tyRead读取tyLib的缓冲区,同样在发送数据时也是通过调用tyWrite函数将数据发送给tyLib的缓冲区中。

tyLib负责对缓冲区进行管理,包括在轮询和中断模式下自动从串口控制器中读写数据,当接收缓冲区占用了一定的空间之后,调用上层回调函数将接收缓冲区的数据取走等等,另外在不同的模式下,还要完成对接收缓冲区的数据进行重新组织等任务。

当前tyLib库的接收缓冲区管理主要实现了line模式和raw模式的缓冲区管理。所谓line模式就想当我们的中断输入,只有在按下回车键以后,计算机才进行相应的动作,否则只是在屏幕上进行显示,如果在动作前按下了退格、CTRL-X、CTRL-C等等按键,那么还要重新对新输入的line进行修改等等。这在利用串口连接终端的情况下是十分有用的。

在raw模式下,计算机每次指示读取相应的字符,并不对其中的含义进行解释,读取完毕后就根据缓冲区的情况决定是否调用回调函数将接收缓冲区的数据取走。


1. STATUS tyDevInit下面分析tyLib库中的各个函数。

    (

    FAST TY_DEV_ID pTyDev,

    int rdBufSize,

    int wrtBufSize,

    FUNCPTR txStartup

    )

用指定的参数初始化tty设备描述符。tty设备描述符是一个数据结构TY_DEV的变量而不是硬件设备,该结构变量在函数调用前已经创建,因此这里只需要进行初始化就行了,而不用重新创建。

2.3.3 函数库ttyDrv.c

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

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

2.1 概述

在早期的计算机系统中,串口是最为常见的也较为简单的外部通信接口,只是现在随着各种方便快捷的外部接口如USB接口、以太网接口的出现,串口的应用逐渐减少。但是串口因为调试简单在许多数据量不大的场合依然较为流行。除了简单的通信功能之外,对于一些简单的计算机系统如单板机等等,由于缺少键盘和显示器,则可以借助串口对目标机中操作系统的运行情况进行监控等等。下图为Tornado开发软件通过串口对目标机上运行的VxWorks操作系统进行监控的结构原理图。

VxWorks UART Driver

图2.1 Tornado通过串口对vxWorks操作系统进行监控

如第一章所述,设备的驱动程序分为与硬件相关部分和硬件无关部分,硬件无关部分实现了一系列通用的数据接口,而硬件相关部分则负责具体的硬件实现。其中硬件无关部分实现是create、remove、open、close、read、write、ioctl等7个通用的函数接口。

2.3 串口驱动程序函数库分析

为了进一步加深对IO设备管理数据结构的理解,本节将分别对函数库ioLib、iosLib进行分析。

2.3.1 函数库ioLib

ioLib库为上层提供了7个基本的函数接口:creat(), remove(), open(), close(), read(), write()以及ioctl()。上层用户只需要对这7个函数进行操作就能够完成对硬件的访问。下面一次分析ioLib库中各个函数库的功能。


1. int creat

    (

    const char *name,

    int        flag

    )

该函数提供了一个与设备无关的通用接口,用于创建一个文件(可以是普通的磁盘文件也可以是抽象的设备文件),该文件的路径为name,创建完毕后自动打开,打开的参数为flag。该函数的正常返回值为文件描述符,否则将会返回ERROR。

对照图2.8,该函数根据设备的名称,从链表中找到该设备对应的设备号drmNum(该数值即为函数返回的文件描述符),然后以此为下标就可以找到该类设备的de_create函数指针,从而找到该设备的create函数。

为了实现应用层程序的平台无关性,操作系统为应用层提供了一套标准的接口函数,这些接口函数在所有的平台上都保持一致,只是随着平台的变化,底层驱动或接近驱动部分操作系统中间层可能会随着调整。这样可以使用户程序独立于具体的硬件平台,增加了应用层开发的效率,避免了重复编码。通用操作系统GPOS(General Purpose Operating System)比如Unix,Linux,将这套提供给应用层的标准接口函数从操作系统中独立出来,专门以标准库的形式存在,增加了应用程序的平台无关性,平台之间的差别完全被操作系统屏蔽。

和Unix,Linux类似,VxWorks也对应用层提供了一套标准文件操作接口函数,实际上与GPOS提供接口类似,我们将其称作为标准I/O 库,VxWorks 下由ioLib.c 文件提供。ioLib.c 文件提供如下标准接口函数:creat、open、unlink、remove、close、rename、read、write、ioctl、lseek、readv、writev 等。VxWorks 操作系统区别于GPOS的一个很大不同点是:VxWorks 不区分用户态和内核态,用户层程序可以直接对内核函数进行调用,而无须使用陷阱指令之类的机制,以及存在使用权限上的限制。因此VxWorks 提供给应用层的接口无须通过外围库的方式,而是直接以内核文件的形式提供。用户程序可以直接使用ioLib.c 文件定义的如上这些函数,这些函数名称与GPOS标准库下的函数名一致,是VxWorks 对标准库的模拟。

VxWorks的I/O系统给应用程序提供了简单、统一、与下列设备无关的接口:

  • 面向终端的字符设备或者通信线路设备;
  • 随机访问块设备,例如硬盘;
  • 虚拟设备,例如管道和套接字;
  • 用于监控和控制的数据或者模拟I/O设备;
  • 访问远程设备的网络设备。

在VxWorks系统中,应用程序通过文件来访问I/O设备,一个文件通常代表以下两类设备:

  • 无结构的原始(raw)设备,比如串口通信通道,用于任务间通信的管道设备;
  • 包含文件系统的的有结构的、可随机访问设备上的逻辑文件;

例如下面的文件: