摘要: 本文以基于ARM7TDMI内核的S3C44B0X芯片的串口驱动为例,分析了 VxWorks串口驱动的层次和机理,研究了tty驱动和底层SCC驱动的工作原理。结合S3C44B0X芯片的串口驱动程序,给出了VxWorks串口驱动程序设计方法和注意事项。
关键词: VxWorks;串口驱动;tty设备

引言

VxWorks的程序开发者经常需要解决串口驱动问题,这是BSP和上层应用程序开发必不可少的基本步骤,特别是对于板级支持包(BSP)和上层应用程序的开发,掌握串口驱动的原理和开发串口驱动程序就显得尤为重要。VxWorks串口通信由串行通信控制器SCC(Serial Communication Controller)控制,和标准I/O库通信的是tty驱动,再由tty驱动和底层SCC驱动通信。本文研究VxWorks串口驱动特性,并以S3C44B0X为例,给出开发VxWorks串口驱动的步骤和实现方法。

串口设备层次与tty驱动

串口的层次

VxWorks串行设备的层次采用了3层抽象的软件结构:标准I/O库(ioLib)->tty库(ttyDrv/tyLib)—>底层SCC驱动(xxDrv),如图1所示。从图中可看出串行设备的驱动xxDrv并不是直接和I/O system交互的,中间存在一个ttyDrv(包括tyLib)。实际上,内核启动时在驱动程序表中安装的不是xxDrv的函数,而是ttyDrv/tyLib提供的函数。串口tty驱动(ttyDrv/tyLib)使I/O系统独立于具体SCC驱动,保证了代码可复用和统一界面。SCC驱动(xxDrv/yyDrv)处理和底层硬件有关的部分。因此,在编写串口驱动时需要了解串口tty驱动的原理以及串口输入输出过程。在此基础上,根据VxWorks的程序执行流程和具体的MCU芯片的特点,修改底层SCC驱动代码。

VxWorks SW Structure

图1 VxWorks串口软件结构

串口tty驱动

创建tty设备包括驱动程序初始化和创建设备两步,这两步都在usrRoot()中完成。创建完tty设备后,用户可以调用ioLib中的write()、read()函数对串口进行读、写操作。

驱动程序初始化

初始化ttyDrv()函数是一个虚拟的驱动,既管理着和I/O的交互,又管理着和底层硬件驱动的交互。它调用iosDrvInstall( )将ttyDrv和tyLib中的函数安装到系统的驱动程序表中。ttyDrv负责着ttyOpen、ttyIoctl的接入,而tyLib负责着tyRead、tyWrite的接入。

创建设备

创建设备函数ttyDevCreate()主要分配并初始化设备描述结构,调用tyDevInit( )进行tyLib库初始化,初始化selectLib(),创建输入输出环形缓冲,创建信号量,调用iosDevAdd()加设备到设备列表,以中断方式启动串口通道。它还进行的另一个重要操作是安装了tyLib设备提供的输入输出回调函数tyITx()和tyIRd(),以便给底层SCC驱动负责调用。

tty输入输出

当tty设备创建后,用open()打开相应的串口,open函数返回的文件句柄就是设备的标识fd,依据串口打开时的读、写标志,可以对串口进行读、写操作。用户程序的基本I/O读写请求由tyLib的tyWrite( )和tyRead( )实现,这两个函数在ttyDrv( )初始化tty时安装到驱动程序表中,如图2所示。

VxWorks Input and Output

图2 VxWorks输入输出

底层SCC驱动—S3C44B0X串口驱动的实现

VxWorks串口驱动的编写主要集中在target/config/bsname/目录下的sysLib.c、sysSerial.c、s3c44b0xsio.c、config.h,target/config/all等文件。编写串口驱动主要需要做以下几个方面的工作。

设备初始化

确定系统要支持的串行通道的个数,初始化数据结构XX_CHAN,编写SCC初始化代码(对处理器串行I/O端口的初始化,RESET串口控制器)。

(1) 定义系统中串口驱动相关的参数:具体在config.h 中定义。

#define INCLUDE_TTY_DEV                          /* 定义tty设备*/
#define INCLUDE_SERIAL                            /* 定义串口*/
#define NUM_TTY                 N_SIO_CHANNELS   /*定义串口通道数*/
#define CONSOLE_TTY            0              /*作为控制台的通道为COM0*/
#define CONSOLE_BAUD_RATE    115200            /*设定控制台串口波特率*/

如果系统还定义串口为WDB连接下载通道,还要进行如下的相关配置:

#define WDB_COMM_TYPE         WDB_COMM_SERIAL /* WDB为串口模式 */
#define WDB_TTY_CHANNEL       1               /*WDB下载通道COM1  */
#define WDB_TTY_BAUD          115200         /* WDB连接通道的串口波特率*/
#define WDB_TTY_DEV_NAME     "/tyCo/1"    /*定义WBD通道在tty中的设备名*/

(2) 初始化数据结构:编写串行设备根据具体的串行设备定义自己的设备描述符xx_ DEV 结构。对于串行设备具体的成员主要是一个S3C44B0_CHAN结构, 表示设备的通道。

(3)SCC初始化代码:SCC驱动分两步如图3所示,描述了VxWorks中有关串口初始化的顺序,其中ttyDrv( )及ttyDevCreate( )涉及的I/O系统提供的一般化代码,不需要修改。用户需要修改的是涉及S3C44B0X芯片的串口数据结构devParas[ ], 设置USART发送接收的中断号、向量号、寄存器基地址等。

VxWorks UART 
 Initialization

图3 VxWorks串口初始化过程

系统在内核启动之前,在usrInit( )中进行第一步初始化后,串口SCC被复位,禁止中断,串口能通过查询方式访问,实现系统级调试如下。

sysHwInit():处理器I/O端口的初始化,在sysHwInit ()函数中调用portInit()函数设置相应的串行I/O端口;需要注意的是对S3C44B0X芯片而言partB和partF都有一位对UART2的设置选项,只能选其一设成选择UART2端,否则将无法用WDB下载VxWorks映像。

s3c44b0DevInit():初始化串口功能指针pChan->sio.pDrvFuncs = &s3c44b0SioDrvFuncs;再对串口芯片的ULCON、UFCON、UMCON进行设定采用8位数据、禁止FIFO和AFC;调用s3c44b0Ioctl()选择串口通讯模式为轮询方式,并初始化波特率。系统激活内核之后,在根任务usrRoot( )中进行第二步初始化,使串口可以以中断方式实现对tty库的底层支持。

sysHwInit2():调用intLibInit初始化intVecTable; s3c44b0DevInit( )初始化中断驱动,调用intConnect()将sysClkInt()、sysAuxClkInt()的入口地址写入intVecTable, sysSerialHwInit2()函数连接串口中断。

sysSerialHwInit2():通过intConnect()把串口的中断处理程序s3c44b0xIntTx、s3c44b0xIntRcv连接到相应的中断向量;由intEnable()开启两个中断;调用s3c44b0xDevInit2()对_UCON寄存器赋值完成对串口的最终配置由轮询模式转换为中断模式。

编写设备中断服务程序(ISR)

串口中断处理是当有数据发送、接收时,硬件产生中断,然后执行相应的中断服务程序进行处理,这样CPU不必像轮询方式那样花费大量的时间查询外部设备的工作状态,有效的提高CPU的使用效率并使系统具有较高的实时性能。这里主要编写与中断处理相关的数据输入输出部分中断处理的驱动程序。发送数据部分的驱动是一个启动发送的函数s3c44b0xTxStartup()和一个发送输出中断的ISRs3c44b0xTxInt()。

① s3c44b0xTxStrartup()当用户要向设备写数据时, 就调用了tyWrite。tyWrite将数据写入到数据输出环后, 调用s3c44b0xTxStrartup()启动设备的数据发送。这里只需向串口缓冲区写入一个字节,然后开启发送中断;后续字节又发送中断处理程序来处理。

② s3c44b0xTxInt()在中断模式下,当设备输出完毕后, 设备就会产生一个中断表示可以接收下一个字符, 这时调用中断处理程序s3c44b0xTxInt()来完成剩下的数据发送工作。

接收数据部分的驱动与输出驱动类似由一个s3c44b0xRxInt()组成。该中断处理函数在收到数据时,向寄存器的数据通过回调函数写入驱动程序的环形缓冲区中。通过上述的工作就可以完成对VxWorks串口驱动程序的编写。

结语

对于VxWorks串口驱动开发而言,应当注意以下问题:掌握VxWorks的启动流程和I/O系统层次与组织结构;要对硬件环境的物理地址、寄存器地址及其含义清楚;理解串口设备的软硬件工作原理。在串口调试过程中的主要问题一般集中在起始时I/O端口进行初始化是否正确,对串口设备寄存器的值设置是否符合软件要求、能否正常使硬件工作,连接ISR程序以及中断优先级的设置和中段处理函数的编写。

参考文献:

  1. Wind River Inc.Tornado BSP Developer''s Kit for VxWorks User''s Guide[P].Tornado 2.0.Edition 1.1999
  2. Wind River Inc. VxWorks BSP Reference [P]. Tornado 2.2.Edition 1.2000
  3. 周启平. VxWorks下设备驱动程序及BSP开发指南 [M]. 中国电力出版社 . 2004.9
  4. 陈智育. VxWorks程序程序开发实践[M].北京:人民邮电出版社,2004.5