頻譜儀多種內(nèi)核間通信機(jī)制的方案設(shè)計(jì)
Linux操作系統(tǒng)將所有的設(shè)備(而不僅是存儲(chǔ)器里的文件)都看成文件,以操作文件的方式訪問(wèn)設(shè)備。應(yīng)用程序不能直接操作硬件,而是使用統(tǒng)一的接口函數(shù)調(diào)用硬件驅(qū)動(dòng)程序。在設(shè)計(jì)的驅(qū)動(dòng)程序中,首先要根據(jù)驅(qū)動(dòng)程序的功能完成file_operations結(jié)構(gòu)中的函數(shù)實(shí)現(xiàn),不需要的函數(shù)接口可以直接在file_operations結(jié)構(gòu)中初始化為NULL。而file_operations結(jié)構(gòu)變量會(huì)在驅(qū)動(dòng)程序初始化時(shí)注冊(cè)到系統(tǒng)內(nèi)部。當(dāng)操作系統(tǒng)對(duì)設(shè)備操作時(shí),就會(huì)調(diào)用驅(qū)動(dòng)程序注冊(cè)的file_operations結(jié)構(gòu)中相應(yīng)的函數(shù)指針。
對(duì)于Linux驅(qū)動(dòng)的注冊(cè)有兩種方式:一種是直接編譯到內(nèi)核中,在系統(tǒng)啟動(dòng)時(shí)即對(duì)設(shè)備進(jìn)行注冊(cè);另一種是以模塊的方式注冊(cè)設(shè)備,需要在系統(tǒng)啟動(dòng)后用命令對(duì)設(shè)備進(jìn)行注冊(cè)。后一種方式在系統(tǒng)開(kāi)發(fā)期使用比較方便,不用在每次修改驅(qū)動(dòng)程序后和內(nèi)核一起進(jìn)行編譯,只需要將模塊編譯成后綴為,ko的模塊文件,就可下載到開(kāi)發(fā)板中直接使用。在本課題中,使用的是模塊注冊(cè)的方式,在項(xiàng)目開(kāi)發(fā)期間可大大縮短開(kāi)發(fā)時(shí)間。
4 Linux設(shè)備驅(qū)動(dòng)的實(shí)現(xiàn)
對(duì)于編寫(xiě)一個(gè)Linux設(shè)備的驅(qū)動(dòng)程序,大致的流程如下:
①查看原理圖、數(shù)據(jù)手冊(cè),了解設(shè)備的操作方法。
②實(shí)現(xiàn)驅(qū)動(dòng)程序的初始化,比如向內(nèi)核注冊(cè)這個(gè)驅(qū)動(dòng)程序,這樣應(yīng)用程序傳入文件名時(shí),內(nèi)核才能找到相應(yīng)的驅(qū)動(dòng)程序。
③設(shè)計(jì)所要實(shí)現(xiàn)的操作,比如open、close、read、write等函數(shù)。
④實(shí)現(xiàn)中斷服務(wù)(不是必須的)。
⑤編譯該驅(qū)動(dòng)程序到內(nèi)核中,或者用insmod命令加載。
⑥測(cè)試驅(qū)動(dòng)程序。
4.1 HPI設(shè)備驅(qū)動(dòng)程序?qū)崿F(xiàn)
4.1.1 物理地址到虛擬地址的映射
寫(xiě)Linux設(shè)備驅(qū)動(dòng)的第一步,是完善頭文件中的宏定義,除了各種參數(shù)的定義外,主要是實(shí)現(xiàn)硬件寄存器的物理地址到虛擬地址的映射。對(duì)于硬件寄存器的操作,其實(shí)就是對(duì)其物理地址進(jìn)行讀寫(xiě)操作。而Linux系統(tǒng)提供了一種內(nèi)存管理機(jī)制,在這種機(jī)制下,程序可以使用比真實(shí)物理地址大得多的地址空間,稱為虛擬地址。Linux系統(tǒng)中程序的操作部是使用虛擬地址,所以要完成物理地址到虛擬地址的映射。本課題采用ioremap函數(shù)的方法,如下:
#define AT91C_SMC_CSR2*(volatile unsigned long*)ioremap(0xFFFFFF78.4)
對(duì)于ioremap函數(shù),就是將物理地址0xFFFFFF78開(kāi)始的4字節(jié)的地址映射到虛擬地址空間中,返回值即4字節(jié)虛擬地址的首地址,賦給宏定義的變量名AT91C_SMC_CSR2。對(duì)宏定義的操作即對(duì)物理地址的操作。
4.1.2 HPI驅(qū)動(dòng)的初始化
首先是對(duì)HPI硬件的初始化以及中斷初始化。對(duì)于HPI,主要是重置DSP,已完成時(shí)序的同步。設(shè)置SMC(靜態(tài)存儲(chǔ)控制器),因?yàn)锳RM跟DSP的HPI通信是使用PIO線復(fù)用。最后向DSP發(fā)送握手信號(hào),表示初始化完成。對(duì)于中斷的初始化,使用:
request_irq(AT91C_ID_IRQ0,handler,SA_INTERRUPT,”irqO”,NULL);
此函數(shù)向內(nèi)核注冊(cè)中斷,包括中斷號(hào)和中斷處理函數(shù)handler。
對(duì)于HPI設(shè)備的注冊(cè),為HPI設(shè)備分配系統(tǒng)未使用的254作為主設(shè)備號(hào),0為次設(shè)備號(hào)。通過(guò)register_chrdev_region函數(shù)向內(nèi)核注冊(cè)。函數(shù)cdev_init是初始化設(shè)備,其實(shí)就是建立設(shè)備與file_operations結(jié)構(gòu)的對(duì)應(yīng)關(guān)系。最后將設(shè)備加入內(nèi)核。代碼如下:
上述的代碼都是在驅(qū)動(dòng)模塊的hpi_init函數(shù)中實(shí)現(xiàn)。在HPI驅(qū)動(dòng)被加載到內(nèi)核時(shí)就完成了一系列初始化。
4.1.3 file_operations結(jié)構(gòu)中函數(shù)的實(shí)現(xiàn)
設(shè)計(jì)驅(qū)動(dòng)的大部分工作就是實(shí)現(xiàn)file_operations結(jié)構(gòu)中的函數(shù)。代碼如下:
其中,“.owner=THIS_MODULE”表示結(jié)構(gòu)屬于本模塊,然后是open、read等各函數(shù)的對(duì)應(yīng)關(guān)系。由于初始化在hpi_init函數(shù)中實(shí)現(xiàn),所以open函數(shù)并沒(méi)有特別的操作,主要是在終端輸出信息。函數(shù)release主要是申請(qǐng)中斷資源的釋放,使用free_irq函數(shù)。下面主要講解read函數(shù),write函數(shù)與之類似,不再詳述。
評(píng)論