嵌入式VxWorks的多串口共享中断的驱动程序设计

时间:2022-10-22 09:28:46

嵌入式VxWorks的多串口共享中断的驱动程序设计

摘要:该文介绍了嵌入式VxWorks操作系统的串行设备驱动程序的结构,分析了VxWorks启动过程中串行设备驱动的实现,设计了一个基于VxWorks操作系统的多串口共享中断的驱动程序,并且实现了将串口驱动程序以模块的方式动态加载到VxWorks操作系统中。

关键词:VxWorks操作系统;串口驱动程序;共享中断

中图分类号:TP316文献标识码:A文章编号:1009-3044(2009)33-9544-03

The Design of Driver for Multi Serial Sharing IRQ Based on VxWorks System

LIU Wei,TAO Ying

(Department of Information Engineering, Jiangxi Vocational College of Finance and Economics, Jiujiang 332000, China)

Abstract: This paper introduces the structure of serial port driver on the VxWorks system, then the achievement of the driver of serial driver is analyzed. The driver for multi serial sharing IRQ based on VxWorks system is designed, and loading VxWorks system with the module of the driver is achieved.

Key words: VxWorks system; serial port driver; sharing IRQ

VxWorks操作系统是美国Wind River公司开发的一种嵌入式实时操作系统,由于其高可靠性、强实时性以及可裁减性,广泛应用于航空航天、军事、民用通信和工业控制等领域。

在某大型控制系统中,我们需要开发一个具有4路串口通讯、1路CAN通讯以及2路以太网通讯的多种通讯方式并存的通讯设备。考虑到通讯能力以及通讯的实时性要求,CPU选用盛博公司PC104+总线的Pentium III处理器,串口选用具有PC104总线接口的4路串口扩展板,采用VxWorks操作系统来实现以上需求。由于每种通讯方式都采用中断方式触发,而系统硬件提供的中断源是有限的,针对这种情况,为了节省系统的中断资源,本文设计了一个基于VxWorks的多串口共享中断的驱动程序,并对该驱动程序的功能进行了长时间测试验证。

1 串行设备驱动的结构

在VxWorks操作系统中,串行设备作为一种特殊的字符型设备,操作系统为其提供一个简单、统一、独立于设备的接口,在应用层对于串行设备的任何操作都可以视为对一个文件的操作,而具体的实现是通过串行设备的驱动程序来完成。

在VxWorks中串行设备驱动采用3层抽象的软件结构,即I/O系统、虚拟设备ttyLib或tyLib以及硬件驱动,其结构示意图如图1所示。在VxWorks中,I/O系统并不直接与具体的硬件驱动进行交互,而是将驱动程序中与硬件无关的部分放在虚拟设备ttyLib中实现,再利用虚拟设备ttyLib与I/O系统进行通讯,使得I/O系统独立于具体的硬件驱动,而驱动程序的开发者只需要实现系统所提供的接口并且将其挂载到虚拟设备ttyLib就能完成具体串行设备驱动的设计,从而保证驱动代码的可复用性和接口的统一性。

2 串行设备驱动的实现

VxWorks在启动过程中对串行设备驱动的实现主要包括两部分:串口的初始化和串行设备的创建。串口的初始化主要包括初始化串口设备,分配串口所需的资源以及完成串口中断程序的系统挂接;串行设备的创建包括tty驱动的初始化和对tty设备的创建,即建立起I/O系统与硬件驱动层的联系。

2.1 串口的初始化

sysInit()作为VxWorks操作系统启动的入口程序会调用第一个C程序函数usrInit(),完成用户定义系统的初始化工作,而串口的硬件初始化是在usrInit()函数的子函数sysHwInit()中完成。对于VxWorks现有的Intel8250驱动(Tornado目录/target/src/drv/sio/i8250Sio.c),sysHwInit()还会调用sysSerial.c文件下的sysSerialHwInit(),sysSerialHwInit()函数主要对串行设备的设备描述符进行初始化,在初始化过程中还会调用底层的i8250HrdInit()对串行设备的端口进行初始化。在完成系统硬件和VxWorks内核的初始化以后,系统会启动一个函数名为usrRoot()的任务,usrRoot()作为VxWorks操作系统的根任务调用sysClkConnect()对系统时钟中断进行配置,而具体的工作是由sysClkConnect()的子函数sysHwInit2()完成,其中sysHwInit2()会调用sysSerialHwInit2()来完成串行设备的中断挂接。

2.2 串行设备的创建

在usrRoot()中通过调用ttyDrv()完成tty驱动的初始化,而ttyDrv()则调用iosDrvInstall()将tty驱动添加到系统的驱动程序列表中,并且完成与I/O系统层的各系统操作函数的连接。tty虚拟设备层与底层硬件驱动的连接则是通过ttyDevCreate()来完成,并实现各个串行设备的创建。

3 多串口共享中断的驱动程序开发

串口扩展板选用的是盛博的A3-CSD板卡,采用PC104总线接口,集成了4路16C554兼容的光电隔离异步串行口,每个串行口能独立控制发送与接受,且具有16字节FIFO以减少中断请求次数,此外该扩展板还具有一个串口中断状态指示寄存器,可以指示产生中断的串口。根据上述硬件配置,可以在现有Intel8250驱动的基础上进行改进来完成多串口共享中断的驱动程序设计。

3.1 串口设备的初始化

每个串口设备都需要有一个的描述自身属性的结构体I8250_CHAN_EX,即设备描述符,且结构体的第一个成员必须为指向SIO_DRV_FUNCS结构的指针,该结构体还包含描述16C554芯片各个端口的信息以及提供给高层协议的回调函数。在系统启动过程中通过调用sysSerialHwInitEx()完成对该结构体的初始化并且将自定义的全局指针数组pi8250ChanEx[4]中各元素分别指向4个串口的I8250_CHAN_EX结构体,初始化过程中会调用i8250HrdInitEx()将串口驱动程序的设备操作入口函数安装到SIO_DRV_FUNCS结构中,然后调用sysSerialHwInitEx2()完成串口中断的系统连接。其中sysSerialHwInitEx2()的实现代码为:

void sysSerialHwInitEx2 (void)

{

int i;

for (i = 0; i < N_UART_CHANNELS_EX; i++)

if (i8250ChanEx[i].int_vec)

{/*将四个串口设备的中断服务程序i8250ShareIntEx ()连接到同一中断*/

(void) intConnect (INUM_TO_IVEC (i8250ChanEx[i].int_vec),

i8250ShareIntEx, (int)&i8250ChanEx[i] );

if (sysBp)

sysIntEnablePIC (devParasEx[i].intLevel);/*中断使能*/

}}

其中,宏N_UART_CHANNELS_EX表示串口设备的个数,i8250ChanEx结构的成员变量int_vec表示该串口的系统中断号,这里每个i8250ChanEx结构的int_vec项值都是相同的。

3.2 串口驱动程序的入口点函数编写

编写串口设备驱动程序需要完成串口设备的入口点函数,这些函数包括控制命令函数i8250IoctlEx(),启动发送循环函数i8250StartupEx(),轮询方式输入函数i8250PRxCharEx(),轮询方式输出函数i8250PTxCharEx(),回调安装函数i8250CallbackInstallEx(),单串口中断服务函数i8250IntEx(),多串口共享中断服务函数i8250ShareIntEx()等函数。这里只列出多串口共享中断服务函数i8250ShareIntEx(),其余函数可以参考i8250Sio.c文件的各相应函数。

void i8250ShareIntEx (I8250_CHAN_EX*pChan)

{

FASTintoldlevel;

oldlevel = intLock(); /*关闭系统中断*/

IntStatus = sysInByte(UART_INT_STATUS); /*读串口中断状态指示寄存器* /

while(( IntStatus & 0x0F) != 0x00 )/*判断是否有串口中断产生*/

{

if (IntStatus & COM0_ INT _FLAG)

i8250IntEx(pi8250ChanEx[0]);/*串口1产生了中断*/

……………

if (IntStatus & COM3_ INT _FLAG)

i8250IntEx(pi8250ChanEx[3]);/*串口4产生了中断*/

}

intUnlock(oldlevel); /*开启系统中断*/

}

其中,全局变量pi8250ChanEx为I8250_CHAN_EX结构的指针数组,分别指向4个串口设备所对应的I8250_CHAN_EX结构,宏UART_INT_STATUS表示串口中断状态指示寄存器地址。

在进入i8250ShareIntEx()后首先关闭系统中断,通过查询串口中断状态指示寄存器来判断产生中断的串口设备,然后将产生此中断的串口描述符结构体,即pi8250ChanEx[4]中对应的元素,作为参数传递给单串口中断服务函数i8250IntEx(),最后重新开启系统中断。

3.3 以模块加载串口驱动程序

在config.h中加入#undef INCLUDE_TTY_DEV,执行下面的代码后生成一个o格式的串口驱动的库文件8250SioEx.o,然后在应用程序中利用loadModule()将8250SioEx.o动态加载到内存中运行。

sysSerialHwInitEx();/*初始化串口设备*/

sysSerialHwInitEx2(); /*串口中断的系统挂接*/

if (N_UART_CHANNELS_EX > 0)

{

ttyDrv();

for (int i = 0;i < N_UART_CHANNELS_EX;i++)

{

sprintf (tyName, "%s%d", "/tyCo/", i);

(void) ttyDevCreate (tyName, sysSerialChanExGet (i), 512, 512); /*创建tty设备*/

}

}

其中sysSerialChanExGet()返回一个描述串口设备的I8250_CHAN_EX结构体。

4 结束语

本文详细分析了串行设备驱动程序的结构以及在VxWorks启动过程中串行设备驱动程序的加载过程,设计了一个多串口共享中断的驱动程序,利用该驱动程序对4个串口同时进行了连续10小时的数据收发测试,4个串口都能稳定地发送和接收数据。此外,在测试过程中发现在进入多串口共享中断服务函数后需要将系统中断关闭,待执行完中断处理后再开启系统中断,否则会引起串口工作的不稳定。

参考文献:

[1] 周启平.VxWorks下设备驱动程序及BSP开发指南[M].北京:中国电力出版社,2004.

[2] 陈智育,温彦军,陈琪.VxWorks程序开发实践[M].北京:人民邮电出版社,2004.

[3] VxWorks programmer’s guide version 2.0[Z].Wind River System Inc,1999.

[4] TL16C550 asynchronous communications element[Z].1998.

[5] 王学龙.嵌入式VxWorks系统开发与应用[M].北京:人民邮电出版社,2003.

[6] 张军.基于Vxworks实时操作系统的串口通信程序设计与实现[J].微计算机信息,2006(2):98-99.

上一篇:反向连接型远程控制系统研究及防范 下一篇:基于个性化学习系统的协同过滤算法改进