摘要:該文介紹了嵌入式VxWorks操作系統(tǒng)的串行設(shè)備驅(qū)動程序的結(jié)構(gòu),分析了VxWorks啟動過程中串行設(shè)備驅(qū)動的實(shí)現(xiàn),設(shè)計(jì)了一個(gè)基于VxWorks操作系統(tǒng)的多串口共享中斷的驅(qū)動程序,并且實(shí)現(xiàn)了將串口驅(qū)動程序以模塊的方式動態(tài)加載到VxWorks操作系統(tǒng)中。
關(guān)鍵詞:VxWorks操作系統(tǒng);串口驅(qū)動程序;共享中斷
中圖分類號:TP316文獻(xiàn)標(biāo)識碼: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操作系統(tǒng)是美國Wind River公司開發(fā)的一種嵌入式實(shí)時(shí)操作系統(tǒng),由于其高可靠性、強(qiáng)實(shí)時(shí)性以及可裁減性,廣泛應(yīng)用于航空航天、軍事、民用通信和工業(yè)控制等領(lǐng)域。
在某大型控制系統(tǒng)中,我們需要開發(fā)一個(gè)具有4路串口通訊、1路CAN通訊以及2路以太網(wǎng)通訊的多種通訊方式并存的通訊設(shè)備。考慮到通訊能力以及通訊的實(shí)時(shí)性要求,CPU選用盛博公司PC104+總線的Pentium III處理器,串口選用具有PC104總線接口的4路串口擴(kuò)展板,采用VxWorks操作系統(tǒng)來實(shí)現(xiàn)以上需求。由于每種通訊方式都采用中斷方式觸發(fā),而系統(tǒng)硬件提供的中斷源是有限的,針對這種情況,為了節(jié)省系統(tǒng)的中斷資源,本文設(shè)計(jì)了一個(gè)基于VxWorks的多串口共享中斷的驅(qū)動程序,并對該驅(qū)動程序的功能進(jìn)行了長時(shí)間測試驗(yàn)證。
1 串行設(shè)備驅(qū)動的結(jié)構(gòu)
在VxWorks操作系統(tǒng)中,串行設(shè)備作為一種特殊的字符型設(shè)備,操作系統(tǒng)為其提供一個(gè)簡單、統(tǒng)一、獨(dú)立于設(shè)備的接口,在應(yīng)用層對于串行設(shè)備的任何操作都可以視為對一個(gè)文件的操作,而具體的實(shí)現(xiàn)是通過串行設(shè)備的驅(qū)動程序來完成。
在VxWorks中串行設(shè)備驅(qū)動采用3層抽象的軟件結(jié)構(gòu),即I/O系統(tǒng)、虛擬設(shè)備ttyLib或tyLib以及硬件驅(qū)動,其結(jié)構(gòu)示意圖如圖1所示。在VxWorks中,I/O系統(tǒng)并不直接與具體的硬件驅(qū)動進(jìn)行交互,而是將驅(qū)動程序中與硬件無關(guān)的部分放在虛擬設(shè)備ttyLib中實(shí)現(xiàn),再利用虛擬設(shè)備ttyLib與I/O系統(tǒng)進(jìn)行通訊,使得I/O系統(tǒng)獨(dú)立于具體的硬件驅(qū)動,而驅(qū)動程序的開發(fā)者只需要實(shí)現(xiàn)系統(tǒng)所提供的接口并且將其掛載到虛擬設(shè)備ttyLib就能完成具體串行設(shè)備驅(qū)動的設(shè)計(jì),從而保證驅(qū)動代碼的可復(fù)用性和接口的統(tǒng)一性。
2 串行設(shè)備驅(qū)動的實(shí)現(xiàn)
VxWorks在啟動過程中對串行設(shè)備驅(qū)動的實(shí)現(xiàn)主要包括兩部分:串口的初始化和串行設(shè)備的創(chuàng)建。串口的初始化主要包括初始化串口設(shè)備,分配串口所需的資源以及完成串口中斷程序的系統(tǒng)掛接;串行設(shè)備的創(chuàng)建包括tty驅(qū)動的初始化和對tty設(shè)備的創(chuàng)建,即建立起I/O系統(tǒng)與硬件驅(qū)動層的聯(lián)系。
2.1 串口的初始化
sysInit()作為VxWorks操作系統(tǒng)啟動的入口程序會調(diào)用第一個(gè)C程序函數(shù)usrInit(),完成用戶定義系統(tǒng)的初始化工作,而串口的硬件初始化是在usrInit()函數(shù)的子函數(shù)sysHwInit()中完成。對于VxWorks現(xiàn)有的Intel8250驅(qū)動(Tornado目錄/target/src/drv/sio/i8250Sio.c),sysHwInit()還會調(diào)用sysSerial.c文件下的sysSerialHwInit(),sysSerialHwInit()函數(shù)主要對串行設(shè)備的設(shè)備描述符進(jìn)行初始化,在初始化過程中還會調(diào)用底層的i8250HrdInit()對串行設(shè)備的端口進(jìn)行初始化。在完成系統(tǒng)硬件和VxWorks內(nèi)核的初始化以后,系統(tǒng)會啟動一個(gè)函數(shù)名為usrRoot()的任務(wù),usrRoot()作為VxWorks操作系統(tǒng)的根任務(wù)調(diào)用sysClkConnect()對系統(tǒng)時(shí)鐘中斷進(jìn)行配置,而具體的工作是由sysClkConnect()的子函數(shù)sysHwInit2()完成,其中sysHwInit2()會調(diào)用sysSerialHwInit2()來完成串行設(shè)備的中斷掛接。
2.2 串行設(shè)備的創(chuàng)建
在usrRoot()中通過調(diào)用ttyDrv()完成tty驅(qū)動的初始化,而ttyDrv()則調(diào)用iosDrvInstall()將tty驅(qū)動添加到系統(tǒng)的驅(qū)動程序列表中,并且完成與I/O系統(tǒng)層的各系統(tǒng)操作函數(shù)的連接。tty虛擬設(shè)備層與底層硬件驅(qū)動的連接則是通過ttyDevCreate()來完成,并實(shí)現(xiàn)各個(gè)串行設(shè)備的創(chuàng)建。
3 多串口共享中斷的驅(qū)動程序開發(fā)
串口擴(kuò)展板選用的是盛博的A3-CSD板卡,采用PC104總線接口,集成了4路16C554兼容的光電隔離異步串行口,每個(gè)串行口能獨(dú)立控制發(fā)送與接受,且具有16字節(jié)FIFO以減少中斷請求次數(shù),此外該擴(kuò)展板還具有一個(gè)串口中斷狀態(tài)指示寄存器,可以指示產(chǎn)生中斷的串口。根據(jù)上述硬件配置,可以在現(xiàn)有Intel8250驅(qū)動的基礎(chǔ)上進(jìn)行改進(jìn)來完成多串口共享中斷的驅(qū)動程序設(shè)計(jì)。
3.1 串口設(shè)備的初始化
每個(gè)串口設(shè)備都需要有一個(gè)的描述自身屬性的結(jié)構(gòu)體I8250_CHAN_EX,即設(shè)備描述符,且結(jié)構(gòu)體的第一個(gè)成員必須為指向SIO_DRV_FUNCS結(jié)構(gòu)的指針,該結(jié)構(gòu)體還包含描述16C554芯片各個(gè)端口的信息以及提供給高層協(xié)議的回調(diào)函數(shù)。在系統(tǒng)啟動過程中通過調(diào)用sysSerialHwInitEx()完成對該結(jié)構(gòu)體的初始化并且將自定義的全局指針數(shù)組pi8250ChanEx[4]中各元素分別指向4個(gè)串口的I8250_CHAN_EX結(jié)構(gòu)體,初始化過程中會調(diào)用i8250HrdInitEx()將串口驅(qū)動程序的設(shè)備操作入口函數(shù)安裝到SIO_DRV_FUNCS結(jié)構(gòu)中,然后調(diào)用sysSerialHwInitEx2()完成串口中斷的系統(tǒng)連接。其中sysSerialHwInitEx2()的實(shí)現(xiàn)代碼為:
void sysSerialHwInitEx2 (void)
{
int i;
for (i = 0; i < N_UART_CHANNELS_EX; i++)
if (i8250ChanEx[i].int_vec)
{/*將四個(gè)串口設(shè)備的中斷服務(wù)程序i8250ShareIntEx ()連接到同一中斷*/
(void) intConnect (INUM_TO_IVEC (i8250ChanEx[i].int_vec),
i8250ShareIntEx, (int)i8250ChanEx[i] );
if (sysBp)
sysIntEnablePIC (devParasEx[i].intLevel);/*中斷使能*/
}}
其中,宏N_UART_CHANNELS_EX表示串口設(shè)備的個(gè)數(shù),i8250ChanEx結(jié)構(gòu)的成員變量int_vec表示該串口的系統(tǒng)中斷號,這里每個(gè)i8250ChanEx結(jié)構(gòu)的int_vec項(xiàng)值都是相同的。
3.2 串口驅(qū)動程序的入口點(diǎn)函數(shù)編寫
編寫串口設(shè)備驅(qū)動程序需要完成串口設(shè)備的入口點(diǎn)函數(shù),這些函數(shù)包括控制命令函數(shù)i8250IoctlEx(),啟動發(fā)送循環(huán)函數(shù)i8250StartupEx(),輪詢方式輸入函數(shù)i8250PRxCharEx(),輪詢方式輸出函數(shù)i8250PTxCharEx(),回調(diào)安裝函數(shù)i8250CallbackInstallEx(),單串口中斷服務(wù)函數(shù)i8250IntEx(),多串口共享中斷服務(wù)函數(shù)i8250ShareIntEx()等函數(shù)。這里只列出多串口共享中斷服務(wù)函數(shù)i8250ShareIntEx(),其余函數(shù)可以參考i8250Sio.c文件的各相應(yīng)函數(shù)。
void i8250ShareIntEx (I8250_CHAN_EX*pChan)
{
FASTintoldlevel;
oldlevel = intLock(); /*關(guān)閉系統(tǒng)中斷*/
IntStatus = sysInByte(UART_INT_STATUS); /*讀串口中斷狀態(tài)指示寄存器* /
while(( IntStatus 0x0F) != 0x00 )/*判斷是否有串口中斷產(chǎn)生*/
{
if (IntStatus COM0_ INT _FLAG)
i8250IntEx(pi8250ChanEx[0]);/*串口1產(chǎn)生了中斷*/
……………
if (IntStatus COM3_ INT _FLAG)
i8250IntEx(pi8250ChanEx[3]);/*串口4產(chǎn)生了中斷*/
}
intUnlock(oldlevel); /*開啟系統(tǒng)中斷*/
}
其中,全局變量pi8250ChanEx為I8250_CHAN_EX結(jié)構(gòu)的指針數(shù)組,分別指向4個(gè)串口設(shè)備所對應(yīng)的I8250_CHAN_EX結(jié)構(gòu),宏UART_INT_STATUS表示串口中斷狀態(tài)指示寄存器地址。
在進(jìn)入i8250ShareIntEx()后首先關(guān)閉系統(tǒng)中斷,通過查詢串口中斷狀態(tài)指示寄存器來判斷產(chǎn)生中斷的串口設(shè)備,然后將產(chǎn)生此中斷的串口描述符結(jié)構(gòu)體,即pi8250ChanEx[4]中對應(yīng)的元素,作為參數(shù)傳遞給單串口中斷服務(wù)函數(shù)i8250IntEx(),最后重新開啟系統(tǒng)中斷。
3.3 以模塊加載串口驅(qū)動程序
在config.h中加入#undefINCLUDE_TTY_DEV,執(zhí)行下面的代碼后生成一個(gè)o格式的串口驅(qū)動的庫文件8250SioEx.o,然后在應(yīng)用程序中利用loadModule()將8250SioEx.o動態(tài)加載到內(nèi)存中運(yùn)行。
sysSerialHwInitEx();/*初始化串口設(shè)備*/
sysSerialHwInitEx2(); /*串口中斷的系統(tǒng)掛接*/
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);/*創(chuàng)建tty設(shè)備*/
}
}
其中sysSerialChanExGet()返回一個(gè)描述串口設(shè)備的I8250_CHAN_EX結(jié)構(gòu)體。
4 結(jié)束語
本文詳細(xì)分析了串行設(shè)備驅(qū)動程序的結(jié)構(gòu)以及在VxWorks啟動過程中串行設(shè)備驅(qū)動程序的加載過程,設(shè)計(jì)了一個(gè)多串口共享中斷的驅(qū)動程序,利用該驅(qū)動程序?qū)?個(gè)串口同時(shí)進(jìn)行了連續(xù)10小時(shí)的數(shù)據(jù)收發(fā)測試,4個(gè)串口都能穩(wěn)定地發(fā)送和接收數(shù)據(jù)。此外,在測試過程中發(fā)現(xiàn)在進(jìn)入多串口共享中斷服務(wù)函數(shù)后需要將系統(tǒng)中斷關(guān)閉,待執(zhí)行完中斷處理后再開啟系統(tǒng)中斷,否則會引起串口工作的不穩(wěn)定。
參考文獻(xiàn):
[1] 周啟平.VxWorks下設(shè)備驅(qū)動程序及BSP開發(fā)指南[M].北京:中國電力出版社,2004.
[2] 陳智育,溫彥軍,陳琪.VxWorks程序開發(fā)實(shí)踐[M].北京:人民郵電出版社,2004.
[3] VxWorks programmer’s guide version 2.0[Z].Wind River System Inc,1999.
[4] TL16C550 asynchronous communications element[Z].1998.
[5] 王學(xué)龍.嵌入式VxWorks系統(tǒng)開發(fā)與應(yīng)用[M].北京:人民郵電出版社,2003.
[6] 張軍.基于Vxworks實(shí)時(shí)操作系統(tǒng)的串口通信程序設(shè)計(jì)與實(shí)現(xiàn)[J].微計(jì)算機(jī)信息,2006(2):98-99.