頻譜儀多種內核間通信機制的方案設計
Linux操作系統將所有的設備(而不僅是存儲器里的文件)都看成文件,以操作文件的方式訪問設備。應用程序不能直接操作硬件,而是使用統一的接口函數調用硬件驅動程序。在設計的驅動程序中,首先要根據驅動程序的功能完成file_operations結構中的函數實現,不需要的函數接口可以直接在file_operations結構中初始化為NULL。而file_operations結構變量會在驅動程序初始化時注冊到系統內部。當操作系統對設備操作時,就會調用驅動程序注冊的file_operations結構中相應的函數指針。
對于Linux驅動的注冊有兩種方式:一種是直接編譯到內核中,在系統啟動時即對設備進行注冊;另一種是以模塊的方式注冊設備,需要在系統啟動后用命令對設備進行注冊。后一種方式在系統開發期使用比較方便,不用在每次修改驅動程序后和內核一起進行編譯,只需要將模塊編譯成后綴為,ko的模塊文件,就可下載到開發板中直接使用。在本課題中,使用的是模塊注冊的方式,在項目開發期間可大大縮短開發時間。
4 Linux設備驅動的實現
對于編寫一個Linux設備的驅動程序,大致的流程如下:
①查看原理圖、數據手冊,了解設備的操作方法。
②實現驅動程序的初始化,比如向內核注冊這個驅動程序,這樣應用程序傳入文件名時,內核才能找到相應的驅動程序。
③設計所要實現的操作,比如open、close、read、write等函數。
④實現中斷服務(不是必須的)。
⑤編譯該驅動程序到內核中,或者用insmod命令加載。
⑥測試驅動程序。
4.1 HPI設備驅動程序實現
4.1.1 物理地址到虛擬地址的映射
寫Linux設備驅動的第一步,是完善頭文件中的宏定義,除了各種參數的定義外,主要是實現硬件寄存器的物理地址到虛擬地址的映射。對于硬件寄存器的操作,其實就是對其物理地址進行讀寫操作。而Linux系統提供了一種內存管理機制,在這種機制下,程序可以使用比真實物理地址大得多的地址空間,稱為虛擬地址。Linux系統中程序的操作部是使用虛擬地址,所以要完成物理地址到虛擬地址的映射。本課題采用ioremap函數的方法,如下:
#define AT91C_SMC_CSR2*(volatile unsigned long*)ioremap(0xFFFFFF78.4)
對于ioremap函數,就是將物理地址0xFFFFFF78開始的4字節的地址映射到虛擬地址空間中,返回值即4字節虛擬地址的首地址,賦給宏定義的變量名AT91C_SMC_CSR2。對宏定義的操作即對物理地址的操作。
4.1.2 HPI驅動的初始化
首先是對HPI硬件的初始化以及中斷初始化。對于HPI,主要是重置DSP,已完成時序的同步。設置SMC(靜態存儲控制器),因為ARM跟DSP的HPI通信是使用PIO線復用。最后向DSP發送握手信號,表示初始化完成。對于中斷的初始化,使用:
request_irq(AT91C_ID_IRQ0,handler,SA_INTERRUPT,”irqO”,NULL);
此函數向內核注冊中斷,包括中斷號和中斷處理函數handler。
對于HPI設備的注冊,為HPI設備分配系統未使用的254作為主設備號,0為次設備號。通過register_chrdev_region函數向內核注冊。函數cdev_init是初始化設備,其實就是建立設備與file_operations結構的對應關系。最后將設備加入內核。代碼如下:

上述的代碼都是在驅動模塊的hpi_init函數中實現。在HPI驅動被加載到內核時就完成了一系列初始化。
4.1.3 file_operations結構中函數的實現
設計驅動的大部分工作就是實現file_operations結構中的函數。代碼如下:

其中,“.owner=THIS_MODULE”表示結構屬于本模塊,然后是open、read等各函數的對應關系。由于初始化在hpi_init函數中實現,所以open函數并沒有特別的操作,主要是在終端輸出信息。函數release主要是申請中斷資源的釋放,使用free_irq函數。下面主要講解read函數,write函數與之類似,不再詳述。
評論