在IrDA驅(qū)動(dòng)程序中主要實(shí)現(xiàn)了s_r_read()、s_r_write()、siLopen()、sir_close()、siLioctl()及sir_handle_irq()中斷處理程序六個(gè)函數(shù)。相應(yīng)的接口結(jié)構(gòu)如下所示:
static struct file_operations siLfops={
ioctl: sir ioctl,
read: siread,
write: sir_write,
open: slr_open,
release:sir close
1.2.1 sir_handle_irq函數(shù)
用戶空間進(jìn)程通過接口函數(shù)進(jìn)入到內(nèi)核,內(nèi)核再調(diào)用驅(qū)動(dòng)程序相應(yīng)的I/O函數(shù)。IrDA驅(qū)動(dòng)程序是字符類型的驅(qū)動(dòng)程序,我們用中斷的方式實(shí)現(xiàn)內(nèi)核與設(shè)備之間的數(shù)據(jù)傳輸。當(dāng)驅(qū)動(dòng)程序在啟動(dòng)后設(shè)備就掛起自己,直到串口完成操作并發(fā)出一個(gè)中斷請(qǐng)求(IRQ)。當(dāng)IRQ產(chǎn)生時(shí),注冊(cè)的中斷處理程序sir_handlejrq得以運(yùn)行。在Sir_handle_irq中,程序通過相應(yīng)的寄存器操作得到接收的數(shù)據(jù),并將數(shù)據(jù)存入到一個(gè)內(nèi)部緩沖中。
1.2.2 sir open和sir_cIose函數(shù)
sir_open函數(shù)的主要功能就是遞增使用計(jì)數(shù)和設(shè)備初始化操作。這里把設(shè)置并初始化sitsang板上的紅外設(shè)備放在了sir_open函數(shù)中,這樣在每次打開IrDA設(shè)備時(shí),紅外設(shè)備都會(huì)被正確地設(shè)置,確保了紅外硬件的正常工作。另外,把申請(qǐng)?jiān)O(shè)備中斷號(hào)的工作也放到了Sir_open函數(shù)中,這樣IrDA設(shè)備所占用的中斷號(hào),在沒有使用IrDA設(shè)備時(shí)也可以被其它設(shè)備共享。
static int sir sopen(struct inode*inode,struet *filp){
計(jì)數(shù)器加1;
申請(qǐng)?jiān)O(shè)備中斷號(hào);
設(shè)置Sitsang板上的紅外設(shè)備并初始化;
}
sir_close()函數(shù)所作的工作與sir_open()的正好相反,計(jì)數(shù)器減1,注銷設(shè)備中斷號(hào)。
1.2.3 sir_ioctl函數(shù)
由于所使用的紅外收發(fā)器HSDL-3200只能以半雙工方式進(jìn)行紅外通信,所以就需要命令進(jìn)行接收和發(fā)送狀態(tài)的轉(zhuǎn)換。ioctl函數(shù)的主要功能就是對(duì)硬件設(shè)備進(jìn)行控制,因此在sir—ioctl函數(shù)中實(shí)現(xiàn)了這一功能。
static int siLioctl(stmctiTlode*inode,structfile*mp,unsigned_int cmd,unsignedlogarg){
swltell(cmd){
case接收:
設(shè)置接收寄存器;
break:
case發(fā)送:
設(shè)置發(fā)送寄存器;
break;
default:
}
}
1.2.4 sir_read和sir_write函數(shù)
這兩個(gè)函數(shù)主要完成讀取應(yīng)用程序傳送給內(nèi)核設(shè)備文件的數(shù)據(jù)和回送應(yīng)用程序請(qǐng)求的數(shù)據(jù),并把數(shù)據(jù)從內(nèi)核傳送到硬件和從硬件讀取數(shù)據(jù)的通信過程。這也是在整個(gè)驅(qū)動(dòng)程序中最重要的部分。
當(dāng)用戶調(diào)用read()函數(shù)時(shí),內(nèi)核相應(yīng)地調(diào)用sir_read()函數(shù)。在Sir_read()中,通過判斷硬件寄存器是否有新數(shù)據(jù)到來而決定是否從設(shè)備讀取數(shù)據(jù),然后使用內(nèi)核提供的copy touser(void*to,const void*from,unsigned long count)函數(shù)將數(shù)據(jù)返回應(yīng)用程序。write()函數(shù)的實(shí)現(xiàn)與read()函數(shù)的實(shí)現(xiàn)過程正好相反。在sir_write()中,通過調(diào)用copy_from user_form_user(void*to,const void*from,unsigned long count,)函數(shù)來完成把數(shù)據(jù)從用戶的應(yīng)用程序傳送給硬件設(shè)備。
1.2.5實(shí)現(xiàn)模式
設(shè)備驅(qū)動(dòng)程序的主體完成了,現(xiàn)在要把驅(qū)動(dòng)程序嵌入內(nèi)核。實(shí)現(xiàn)Llnux下IrDA設(shè)備驅(qū)動(dòng)功能主要有兩種形式:一是通過內(nèi)核來進(jìn)行加載,需要用戶在./etc/rc.d/目錄中定義的初始啟動(dòng)腳本中寫入命令,當(dāng)內(nèi)核啟動(dòng)的時(shí)候,就開始加載IrDA設(shè)備驅(qū)動(dòng)程序,內(nèi)核啟動(dòng)完成之后,IrDA驅(qū)動(dòng)功能也隨即實(shí)現(xiàn)了,但是增大了內(nèi)核;第二是通過模塊加載的形式。比較兩者,第二種形式更加靈活,在此著重對(duì)模塊加載形式進(jìn)行討論。模塊設(shè)計(jì)是Llnux中特有的技術(shù),它使Linux內(nèi)核功能更容易擴(kuò)展。采用模塊來設(shè)計(jì)Linux設(shè)備驅(qū)動(dòng)程序會(huì)很輕松,并且能夠形成固定的模式。任何人只要依照這個(gè)模式去設(shè)計(jì),都能設(shè)計(jì)出優(yōu)良的設(shè)備驅(qū)動(dòng)程序。
先簡(jiǎn)要概述一下基于模塊加載的設(shè)備驅(qū)動(dòng)程序的設(shè)計(jì)步驟。首先每一個(gè)可裝配的設(shè)備驅(qū)動(dòng)程序都必須有init_module和cleanup module兩個(gè)函數(shù),裝載和卸載設(shè)備時(shí)內(nèi)核自動(dòng)調(diào)用這兩個(gè)函數(shù)。前者在insmod的時(shí)候執(zhí)行,后者在rmmod的時(shí)候執(zhí)行。通過模塊加載命令insmod來把IrDA設(shè)備驅(qū)動(dòng)程序插入到內(nèi)核之中。在init_module中,除可以對(duì)硬件設(shè)備進(jìn)行檢查和初始化外,還必須調(diào)用reglster_*’函數(shù)將設(shè)備登記到系統(tǒng)中。本例中是通過register_chrdev來登記的,如果是塊設(shè)備或網(wǎng)絡(luò)設(shè)備則應(yīng)該用reglstei_blkdev和register_netdev來登記。registeT_chrdev的主要功能是將設(shè)備名和結(jié)構(gòu)flle operatioons登記到系統(tǒng)的設(shè)備控制塊中。最后可以通過執(zhí)行模塊卸載命令rmmod,調(diào)用IrDA驅(qū)動(dòng)程序中的cleanup_module()函數(shù),來對(duì)IrDA驅(qū)動(dòng)程序模塊卸載,具體實(shí)現(xiàn)過程如圖l所示。

2 基于MC68HC908AP64紅外發(fā)射器的設(shè)計(jì)
2.1 紅外發(fā)射器的硬件設(shè)計(jì)
為了可以檢測(cè)Sitsang板端的IrDA設(shè)備能否正常工作,設(shè)計(jì)了一個(gè)IrDA發(fā)射器。發(fā)射器的體積為l3cm×10cm,安裝靈活方便。在發(fā)射器上有一個(gè)撥位開關(guān),可以用來設(shè)置發(fā)射不同的碼值。紅外收發(fā)器選用具有半雙工功能的HSDL-3200。
單片機(jī)的可靠性和片上資源是選擇的關(guān)鍵。如一片單片機(jī)的資源不足,還要另加其它芯片,就會(huì)給系統(tǒng)的可靠性、外型體積、造價(jià)帶來很多負(fù)面的影響。MC68HC908AP64單片機(jī)對(duì)程序安全運(yùn)行有較全面的保護(hù)。與其它的MCU相比,最重要的是它內(nèi)部集成有UART單元及其接口,支持IrDA標(biāo)準(zhǔn),有紅外接口可以直接與紅外收發(fā)體系連接?梢灾苯域(qū)動(dòng)HSDL_3200,片上的其它資源包含了發(fā)射器的全部需要,并且廉價(jià)低功耗。所以選用其作為發(fā)射器的主控芯片電路如圖2所示。

2.2 紅外發(fā)射器的軟件實(shí)現(xiàn)流程
發(fā)射器的軟件編程對(duì)產(chǎn)品的可靠性有很大影響。由于IrDA是異步半雙工的通信方式,在某一個(gè)時(shí)刻,IrDA收發(fā)器只可能呈現(xiàn)一種狀態(tài)。鑒于這種情況,設(shè)置IrDA收發(fā)器始終處于發(fā)射狀態(tài),而SitSang板上的IrDA收發(fā)器始終處于接收狀態(tài),這樣就不用切換收發(fā)狀態(tài),保證了系統(tǒng)的穩(wěn)定性。發(fā)射器和接收器之間的通信需要制定一套合理的通信協(xié)議來協(xié)調(diào)總通信。這里采用的是數(shù)據(jù)包通信方式。通信波特率為9600bps,通信數(shù)據(jù)是成幀發(fā)送的,每幀數(shù)據(jù)都可以設(shè)置自己的引導(dǎo)碼和數(shù)據(jù)。其中引導(dǎo)碼是用于同步每一幀數(shù)據(jù);數(shù)據(jù)是IrDA發(fā)射器撥位開關(guān)的值,可以自己隨意設(shè)定。當(dāng)紅外發(fā)射器和Sitsang板調(diào)通以后,也可以通過sir_ioctl函數(shù)來切換收發(fā)狀態(tài),達(dá)到雙方通信的目的。發(fā)射器的軟件流程如圖3所示。

結(jié)語(yǔ)
本文分析了設(shè)備驅(qū)動(dòng)程序在內(nèi)核中的實(shí)現(xiàn)方法,并講解了基于Intel的PXA255處理器的Sitsang平臺(tái)開發(fā)的驅(qū)動(dòng)程序設(shè)計(jì)和實(shí)現(xiàn)過程。其中結(jié)合Linux下一個(gè)現(xiàn)在使用廣泛的IrDA驅(qū)動(dòng)程序,詳細(xì)闡述了紅外模塊驅(qū)動(dòng)程序的設(shè)計(jì)和開發(fā)過程,最后從硬件和軟件兩個(gè)方面講述了基于MC68HC908AP64紅外發(fā)射器的設(shè)計(jì)和實(shí)現(xiàn)。雖然嵌入式Linux操作系統(tǒng)和傳統(tǒng)的嵌入式操作系統(tǒng)相比還不夠成熟完善,但是Linux本身所具有的優(yōu)越性使其在移動(dòng)設(shè)備的OS領(lǐng)域具有廣闊的應(yīng)用前景。





