《電子技術(shù)應(yīng)用》
您所在的位置:首頁 > 嵌入式技術(shù) > 設(shè)計應(yīng)用 > 嵌入式Linux下PCI設(shè)備驅(qū)動的設(shè)計與實(shí)現(xiàn)
嵌入式Linux下PCI設(shè)備驅(qū)動的設(shè)計與實(shí)現(xiàn)
來源:微型機(jī)與應(yīng)用2011年第12期
袁愛平
(長沙民政職業(yè)技術(shù)學(xué)院 軟件學(xué)院, 湖南 長沙410004)
摘要: PCI局部總線具有使用方便、數(shù)據(jù)傳輸率高等特點(diǎn),已成為計算機(jī)必備的一種接口。Linux是一種日趨成熟完善的操作系統(tǒng),越來越多的軟硬件廠商開始使用Linux平臺開發(fā)自己的產(chǎn)品,因而對基于該平臺的設(shè)備驅(qū)動程序的需求也愈來愈多。介紹了Linux驅(qū)動程序開發(fā)的一般方法,并實(shí)現(xiàn)了流媒體數(shù)據(jù)緩存PCI卡在Linux環(huán)境下的驅(qū)動程序。
Abstract:
Key words :

摘   要: PCI局部總線具有使用方便、數(shù)據(jù)傳輸率高等特點(diǎn),已成為計算機(jī)必備的一種接口。Linux是一種日趨成熟完善的操作系統(tǒng),越來越多的軟硬件廠商開始使用Linux平臺開發(fā)自己的產(chǎn)品,因而對基于該平臺的設(shè)備驅(qū)動程序的需求也愈來愈多。介紹了Linux驅(qū)動程序開發(fā)的一般方法,并實(shí)現(xiàn)了流媒體數(shù)據(jù)緩存PCI卡在Linux環(huán)境下的驅(qū)動程序。
關(guān)鍵詞: Linux操作系統(tǒng); PCI總線; 設(shè)備驅(qū)動; 流媒體數(shù)據(jù)緩存卡

    隨著通用處理器和嵌入式技術(shù)的迅猛發(fā)展,越來越多的電子設(shè)備需要由處理器控制。目前大多數(shù)CPU和外部設(shè)備都會提供PCI總線的接口,PCI總線已成為計算機(jī)系統(tǒng)中一種應(yīng)用廣泛、通用的總線標(biāo)準(zhǔn)[1]。Linux因其開放源代碼以及穩(wěn)定的性能,越來越受到廣大用戶青睞。同時,基于Linux內(nèi)核的嵌入式操作系統(tǒng)應(yīng)用勢頭強(qiáng)勁,開發(fā)基于Linux的設(shè)備驅(qū)動程序,具有很強(qiáng)的實(shí)用性和可移植性[2]。
1 PCI總線概述
    PCI(Peripheral Component Interconnect)總線,即外部設(shè)備互連,是現(xiàn)在流行的一種連接PC和外圍設(shè)備的總線結(jié)構(gòu)[3]。PCI提供了一組完整的總線接口規(guī)范,可以在33 MHz時鐘頻率、32 bit數(shù)據(jù)總線寬度的條件下達(dá)到峰值132 Mb/s的傳輸速率;它能支持一種稱為線性突發(fā)的數(shù)據(jù)傳輸模式,可確??偩€不斷滿載數(shù)據(jù);采用總線主控與同步操作,顯著改善PCI的性能;PCI獨(dú)立于處理器的結(jié)構(gòu),用戶可隨意增添外圍設(shè)備,以擴(kuò)展電腦系統(tǒng)而不必?fù)?dān)心在不同時鐘頻率下會導(dǎo)致性能下降。
2 PCI設(shè)備驅(qū)動程序的設(shè)計與實(shí)現(xiàn)
 Linux中將設(shè)備分成字符設(shè)備、塊設(shè)備和網(wǎng)絡(luò)設(shè)備三種類型,通過主設(shè)備號和從設(shè)備號實(shí)現(xiàn)對設(shè)備的描述。其中主設(shè)備號描述控制該設(shè)備的驅(qū)動程序,即驅(qū)動程序與主設(shè)備號一一對應(yīng),從設(shè)備號用來區(qū)分同一個驅(qū)動程序控制的不同設(shè)備[5]。
 PCI設(shè)備屬于字符設(shè)備。本設(shè)計采用模塊方式實(shí)現(xiàn)PCI卡驅(qū)動程序。驅(qū)動程序主要由設(shè)備注冊和注銷、設(shè)備探測和移除、設(shè)備中斷處理和系統(tǒng)調(diào)用等函數(shù)組成。
2.1 設(shè)備注冊和注銷
 使用一個設(shè)備之前,必須保證己經(jīng)對它進(jìn)行注冊,這項(xiàng)工作一般是在設(shè)備初始化時完成。設(shè)備初始化函數(shù)中調(diào)用函數(shù)register_chrdev()來注冊字符設(shè)備。流媒體數(shù)據(jù)緩存PCI卡驅(qū)動程序的注冊代碼如下:
 #define MAJOR_NUM 128
    register_chrdev(MAJOR_NUM,"pci_card",&pci_card_fops);
    將設(shè)備的主設(shè)備號設(shè)為128,設(shè)備名稱為pci_card。pci_card_fops是一個file_operations結(jié)構(gòu)指針,這個結(jié)構(gòu)是設(shè)備驅(qū)動程序所提供的入口點(diǎn)位置,在設(shè)備注冊時向系統(tǒng)進(jìn)行登記,以便系統(tǒng)在適當(dāng)時調(diào)用。pci_card_fops定義如下:
 static struct file_operations pci_card_fop={
          owner:THIS_MODULE,
          open:pic_card_open,
          release:pic_card_release,
          read:pic_card_read,
          write:pic_card_write,
          ioctl:pic_card_ioctl
 };
 當(dāng)不再使用此設(shè)備時,需調(diào)用unregister_chrdev()函數(shù)注銷驅(qū)動程序。
2.2 設(shè)備探測和移除
 在掃描到新的PCI設(shè)備后,系統(tǒng)需要調(diào)用設(shè)備驅(qū)動程序?qū)崿F(xiàn)的探測函數(shù)以查找與設(shè)備相匹配的PCI驅(qū)動。流媒體數(shù)據(jù)緩存PCI卡設(shè)備驅(qū)動的探測函數(shù)pic_card_probe()的主要實(shí)現(xiàn)代碼如下:
 pci_card = kmalloc(sizeof(struct pci_card),GFP_KERNEL);
                             //為設(shè)備實(shí)例分配存儲空間
 pci_enable_device(dev);                      //激活PCI設(shè)備
 spin_lock_init(pci_card ->lock);
                        //初始化特定設(shè)備實(shí)例的私有化數(shù)據(jù)
 pci_read_config_byte(dev,PCI_REVISION_ID,(u8*)&(pci_
 card ->rev_id));                  //讀取配置信息
 pci_card->mem_base=pci_resource_start(dev, 0);
                              //讀取I/O資源的配置信息
 pci_request_regions(dev,"pic_card");      //申請I/O區(qū)域
 pci_set_master(dev);                 //設(shè)置成總線主模式
 pic_card->mem_start=ioremap(pic_card->mem_base,
 pic_card->mem_size);              // I/O內(nèi)存映射
 設(shè)備移除函數(shù)主要完成釋放映射的虛擬地址、釋放I/O區(qū)域、關(guān)閉PCI設(shè)備和釋放為設(shè)備實(shí)例分配的內(nèi)核空間等功能。
2.3 中斷處理
 流媒體數(shù)據(jù)緩存卡驅(qū)動中的中斷處理程序主要負(fù)責(zé)識別中斷、響應(yīng)中斷和喚醒睡眠的進(jìn)程,中斷處理代碼如下:
 inl(pci_card->iobase+PCI_CARD_INT_STA); // 識別中斷
 outl(status&INT_MASK, pci_card->iobase + PCI_CARD_
INT_STA);                                         //響應(yīng)中斷
 wake_up_interruptible(&pci_card->wq);   //喚醒睡眠進(jìn)程
2.4 系統(tǒng)調(diào)用
 用戶進(jìn)程利用系統(tǒng)調(diào)用對設(shè)備文件進(jìn)行諸如read/write操作時,系統(tǒng)調(diào)用通過設(shè)備文件的主設(shè)備號找到相應(yīng)的設(shè)備驅(qū)動程序,然后讀取這個數(shù)據(jù)結(jié)構(gòu)相應(yīng)的函數(shù)指針,接著把控制權(quán)交給該函數(shù)。流媒體數(shù)據(jù)緩存PCI卡的系統(tǒng)調(diào)用函數(shù)主要包括設(shè)備的打開、關(guān)閉、讀寫和控制等。
 在使用PCI設(shè)備之前,必須先打開所要使用的PCI設(shè)備。當(dāng)用戶在應(yīng)用程序中調(diào)用open()函數(shù)時,應(yīng)用程序就會自動進(jìn)入驅(qū)動程序中的pci_card_open()函數(shù)。pic_card_open()函數(shù)主要負(fù)責(zé)增加模塊的使用計數(shù),并根據(jù)pic_card_probe()讀到的中斷號申請中斷,注冊中斷處理程序。具體實(shí)現(xiàn)如下:
 MOD_INC_USE_COUNT
 request_irq(pci_card->irq,pci_card_interrupt,SA_SHIRQ,"pci_card",pci_card));
 在使用完P(guān)CI設(shè)備后,必須關(guān)閉PCI設(shè)備。當(dāng)用戶在應(yīng)用程序中調(diào)用close()函數(shù)時,應(yīng)用程序就會自動進(jìn)入驅(qū)動程序中的pci_card_release()函數(shù)。pci_card_release()函數(shù)的主要工作是釋放中斷和減少模塊的使用計數(shù)。
 用戶在應(yīng)用程序中調(diào)用read()函數(shù)和write()函數(shù)對設(shè)備文件進(jìn)行讀寫操作時,應(yīng)用程序就會自動進(jìn)入驅(qū)動程序中的pci_card_read()函數(shù)和pci_card_write()函數(shù)。pci_card_read()函數(shù)首先會阻塞在以pci_card->wq為隊頭的等待隊列上。當(dāng)流媒體數(shù)據(jù)緩存卡上的數(shù)據(jù)準(zhǔn)備好,即pci_card->state變?yōu)镽EADY時,pci_card_read()函數(shù)會被喚醒。函數(shù)被喚醒后,會先將數(shù)據(jù)從設(shè)備I/O內(nèi)存拷貝到內(nèi)核空間,再從內(nèi)核空間拷貝給用戶進(jìn)程,實(shí)現(xiàn)方式如下:
 wait_event_interruptible(pci_card->wq,pci_card->state==READY);
 memcpy_fromio(pbuf,pci_card->mem_start,count);
 copy_to_user(buf,pbuf,count));
 而pci_card_write()函數(shù)的主要工作是將數(shù)據(jù)從用戶進(jìn)程拷貝到內(nèi)核空間,再將內(nèi)核空間中的數(shù)據(jù)拷貝到設(shè)備I/O內(nèi)存,實(shí)現(xiàn)代碼如下:
 copy_from_user(pbuf,buf,count);
 memcpy_toio(pci_card->mem_start,pbuf,count);
 Linux是一種日趨成熟完善的操作系統(tǒng),PCI總線已成為計算機(jī)系統(tǒng)中一種應(yīng)用廣泛、通用的總線標(biāo)準(zhǔn)。本文針對流媒體數(shù)據(jù)緩存卡設(shè)備,結(jié)合PCI總線的特點(diǎn),開發(fā)實(shí)現(xiàn)了流媒體數(shù)據(jù)緩存PCI卡在Linux環(huán)境下的設(shè)備驅(qū)動程序,本文介紹的驅(qū)動原理同樣適用其他PCI設(shè)備的開發(fā)。
參考文獻(xiàn)
[1] 陳穎,唐超. 基于PCI總線驅(qū)動程序設(shè)計方法研究[J].微計算機(jī)信息,2008,12(1):272-274.
[2] 李善平,劉文峰,王煥龍. Linux與嵌入式系統(tǒng)[M].北京:清華大學(xué)出版社,2003.
[3] 宋有泉,高小鵬,龍翔. 嵌入式PCI網(wǎng)卡驅(qū)動程序的設(shè)計與優(yōu)化[J]. 計算機(jī)工程,2007,3(2):264-266.
[4] 王峰,張文軍,余松煜. PCI設(shè)備驅(qū)動程序中幾個關(guān)鍵問題的設(shè)計與實(shí)現(xiàn)[J]. 測控技術(shù),2002,21(8):58-60.
[5] 錢晨,徐榮華,王欽若. 基于Linux操作系統(tǒng)的設(shè)備驅(qū)動程序開發(fā)[J]. 微計算機(jī)信息,2004,20(9):131-133.
 

此內(nèi)容為AET網(wǎng)站原創(chuàng),未經(jīng)授權(quán)禁止轉(zhuǎn)載。