国产日韩欧美一区二区三区三州_亚洲少妇熟女av_久久久久亚洲av国产精品_波多野结衣网站一区二区_亚洲欧美色片在线91_国产亚洲精品精品国产优播av_日本一区二区三区波多野结衣 _久久国产av不卡

?

Linux系統(tǒng)中PCI設(shè)備DMA 數(shù)據(jù)傳輸?shù)膶崿F(xiàn)

2012-09-20 08:19:28譚欽紅張際生李文杰
關(guān)鍵詞:輸入輸出外設(shè)寄存器

譚欽紅,張際生,李文杰,徐 沛

(重慶郵電大學(xué)信號與信息處理重點實驗室,重慶 400065)

0 引言

Linux作為開源操作系統(tǒng),因其良好的可擴(kuò)展性和網(wǎng)絡(luò)應(yīng)用的可靠性,受到眾多領(lǐng)域開發(fā)者的青睞。目前在各種嵌入式設(shè)備,大型交換設(shè)備及PC機(jī)上均可看見它的身影。同時,Linux系統(tǒng)還具有支持多種總線標(biāo)準(zhǔn)的特點,其中包括外設(shè)組件互連標(biāo)準(zhǔn)(peripheral component interconnection,PCI)總線。PCI總線是目前計算機(jī)系統(tǒng)中應(yīng)用最為廣泛的一種總線標(biāo)準(zhǔn),它不依賴于任何一種處理器架構(gòu),支持總線控制技術(shù),配合存儲器直接存取(direct memory acess,DMA)技術(shù)可使總線上的智能設(shè)備取得對總線的控制權(quán),進(jìn)而使智能設(shè)備具有與系統(tǒng)內(nèi)存自主進(jìn)行高速數(shù)據(jù)傳輸?shù)哪芰?。本文重點介紹Linux系統(tǒng)中基于PCI總線接口技術(shù)的DMA數(shù)據(jù)傳輸?shù)膶崿F(xiàn)機(jī)制。

1 DMA簡介

在DMA傳輸方式出現(xiàn)之前,程序控制輸入輸出和中斷控制輸入輸出是應(yīng)用較多的兩種傳輸控制方式。由于程序控制輸入輸出方式需要CPU反復(fù)測試外部設(shè)備的狀態(tài),CPU在大量時間處于查詢和等待的狀態(tài)下,使得整個計算機(jī)系統(tǒng)的效率十分低下,現(xiàn)已不再使用。在中斷控制輸入輸出的方式中,CPU向輸入輸出設(shè)備發(fā)出讀寫一個數(shù)據(jù)字的命令后即可轉(zhuǎn)入其他工作,而由外設(shè)獨立完成輸入輸出操作。當(dāng)輸入輸出操作完成后,設(shè)備再向CPU發(fā)出中斷請求,這時CPU才暫停當(dāng)前操作來響應(yīng)中斷,并再次向輸入輸出設(shè)備發(fā)出讀寫命令。雖然中斷控制輸入輸出方式減少了CPU的等待時間,但是輸入輸出設(shè)備每傳送完一個數(shù)據(jù)字都需要向CPU發(fā)出一次中斷請求,CPU需要中斷一次當(dāng)前工作并進(jìn)行保護(hù)現(xiàn)場操作,以便中斷響應(yīng)后可以繼續(xù)執(zhí)行之前的工作[1]。這樣,在連續(xù)傳送一個數(shù)據(jù)塊的過程中,CPU反復(fù)多次被中斷,并花費很多時間去處理中斷,整個系統(tǒng)效率的提高依舊受到了限制。

DMA是一種允許外圍設(shè)備直接從內(nèi)存存取數(shù)據(jù)而無需CPU全程參與的硬件機(jī)制,常用在需要高速大批量數(shù)據(jù)傳輸?shù)南到y(tǒng)中。整個DMA數(shù)據(jù)傳輸操作在“DMA控制器”的控制下進(jìn)行,CPU只需在數(shù)據(jù)傳輸開始和結(jié)束時做出相應(yīng)處理,傳輸過程中則可處理其他進(jìn)程[2]。這一機(jī)制使得CPU和輸入輸出設(shè)備處于并行操作的狀態(tài),大大提高了系統(tǒng)的效率。

實現(xiàn)DMA傳送主要有以下4步基本操作。

1)外設(shè)發(fā)出DMA請求;

2)CPU響應(yīng)DMA請求并將總線控制權(quán)交給DMA控制器,系統(tǒng)轉(zhuǎn)到DMA工作方式;

3)執(zhí)行DMA傳輸;

4)傳輸完成,將總線控制權(quán)交還CPU。

在進(jìn)行以上4步操作前,還需要向系統(tǒng)申請一條DMA通道,通道的申請一般在外設(shè)打開時完成,在外設(shè)關(guān)閉時予以釋放。當(dāng)外設(shè)需傳輸數(shù)據(jù)時,系統(tǒng)應(yīng)開辟一塊數(shù)據(jù)緩存區(qū)用于數(shù)據(jù)的存放,同時該緩存區(qū)還需被映射成外設(shè)可直接訪問的DMA緩存區(qū)。當(dāng)傳輸完成時,外設(shè)通過一個中斷函數(shù)通知CPU數(shù)據(jù)已傳輸完畢,并釋放對總線的控制權(quán)。

2 Linux系統(tǒng)中PCI設(shè)備驅(qū)動

PCI總線是目前應(yīng)用極為廣泛的一種計算機(jī)總線標(biāo)準(zhǔn),通過PCI總線與系統(tǒng)相連的設(shè)備統(tǒng)稱為PCI設(shè)備,具體的PCI設(shè)備可以是網(wǎng)絡(luò)設(shè)備、字符設(shè)備或者USB主機(jī)控制器等。Linux系統(tǒng)采用pci_dev結(jié)構(gòu)體來對每一個PCI設(shè)備做出描述,該結(jié)構(gòu)體對應(yīng)一個配置寄存器[3],其空間結(jié)構(gòu)如圖1所示。

盡管PCI配置寄存器包含眾多內(nèi)容,但有些配置寄存器是要求的,有些則是可選的。常常用到的有制造商標(biāo)識(verdor id)和設(shè)備標(biāo)識(device id),它們由制造商寫入設(shè)備,在系統(tǒng)初始化時被讀取,用來供驅(qū)動程序查找對應(yīng)的設(shè)備。在Linux系統(tǒng)中,有一條指向所有PCI設(shè)備的鏈表pci_devices。PCI設(shè)備描述結(jié)構(gòu)體pci_dev通過global_list成員將自身鏈接到這條全局的PCI設(shè)備鏈表上,這樣驅(qū)動程序就能迅速地查找到對應(yīng)的PCI設(shè)備了。

圖1 PCI配置寄存器Fig.1 PCI configuration register

Linux系統(tǒng)用pci_driver結(jié)構(gòu)體來統(tǒng)一定義PCI設(shè)備驅(qū)動,它是pci_dev設(shè)備描述結(jié)構(gòu)體的成員函數(shù),其部分代碼如下所示。

盡管pci_driver結(jié)構(gòu)體中成員函數(shù)較多,但驅(qū)動開發(fā)人員往往只需關(guān)心里面幾個重要成員,其中就有 name,id_table,probe。name 代表適用于該 PCI設(shè)備的驅(qū)動程序的名字,該名稱可由lspci命令查看。id_table用于表示驅(qū)動所支持的成員設(shè)備列表,該列表由probe成員調(diào)用[4]。當(dāng)Linux內(nèi)核啟動并完成對所有PCI設(shè)備的掃描、登錄和分配資源等初始化操作時,就會建立起系統(tǒng)中所有PCI設(shè)備的拓?fù)浣Y(jié)構(gòu),probe函數(shù)將負(fù)責(zé)具體硬件的探測工作并保存配置信息,繼而加載設(shè)備驅(qū)動程序。pci_driver結(jié)構(gòu)體的實現(xiàn)形式如下。

注:xxx前綴由驅(qū)動開發(fā)人員自行命名以示區(qū)分。

在Linux系統(tǒng)中,PCI驅(qū)動只是為了輔助設(shè)備本身的驅(qū)動,是所有PCI設(shè)備自身驅(qū)動在系統(tǒng)中的接口,真正操作設(shè)備驅(qū)動程序入口是pci_driver結(jié)構(gòu)體中的probe成員函數(shù)。probe函數(shù)中包括設(shè)備的打開、關(guān)閉、中斷號獲取、申請I/O端口、計時等函數(shù),這些成員函數(shù)即是設(shè)備自身驅(qū)動的實現(xiàn)[5]。以下為probe函數(shù)部分示例。

3 DMA存取方式的實現(xiàn)

3.1 DMA通道的申請與釋放

在使用DMA方式傳輸數(shù)據(jù)前,需要向系統(tǒng)申請一個DMA通道,該通道的申請在外設(shè)的打開函數(shù)中實現(xiàn)。雖然現(xiàn)在大部分外設(shè)均支持DMA功能,但在申請DMA通道之前,最好先判定設(shè)備是否支持該功能。外設(shè)的打開函數(shù)如下。

打開函數(shù)中,dma_set_mask()用來判斷設(shè)備是否具備DMA功能,內(nèi)核默認(rèn)設(shè)備能對任何32位地址進(jìn)行DMA操作,該地址位寬可由驅(qū)動開發(fā)人員指定,例如此處用0xffffff表示設(shè)備只限定于對24位地址進(jìn)行DMA操作;request_irq()成員函數(shù)用來向系統(tǒng)注冊中斷號。其中xxx_inerrupt為中斷的實現(xiàn)函數(shù)。flag為中斷模式,當(dāng)選擇中斷為共享模式時,用dev_id來區(qū)分是哪個設(shè)備發(fā)出的中斷申請;request_dma()成員函數(shù)用來申請DMA通道。其中channel為DMA通道編號,可選為0-7。name用來標(biāo)識使用該通道的設(shè)備,可以在用戶空間查看。一般來說,中斷注冊函數(shù)應(yīng)該在DMA通道申請之前被執(zhí)行,在DMA通道釋放之前被注銷[6]。在此將中斷注冊函數(shù)放在打開函數(shù)中對應(yīng)的是PCI網(wǎng)絡(luò)設(shè)備驅(qū)動模式,其他PCI設(shè)備中斷注冊函數(shù)亦可在初始化函數(shù)中實現(xiàn)。

當(dāng)設(shè)備關(guān)閉時,需相應(yīng)地釋放中斷資源和DMA通道,設(shè)備的關(guān)閉函數(shù)如下。

和打開函數(shù)相反,設(shè)備關(guān)閉函數(shù)是先注銷中斷資源而后釋放DMA通道。中斷注銷函數(shù)為free_irq(),DMA通道釋放函數(shù)為free_dma()。整個DMA通道的申請與釋放流程如圖2所示。

圖2 DMA通道申請與釋放Fig.2 DMA channel applications and release

3.2 DMA數(shù)據(jù)傳輸流程

3.2.1 緩存區(qū)映射

使用DMA方式傳輸數(shù)據(jù)時,需要開辟一塊內(nèi)存區(qū)域用于CPU與外設(shè)交互數(shù)據(jù),這塊內(nèi)存區(qū)域被稱為DMA緩存區(qū)。Linux2.6內(nèi)核中能夠用于分配DMA緩存區(qū)的函數(shù)有3個:kmalloc(),get_free_pages()和 pci_alloc_consistent()[7]。在這里采用 get_free_pages()函數(shù)作為緩存區(qū)分配手段,該函數(shù)有2個參數(shù):flags,order。flag參數(shù)稱為分配優(yōu)先級,常常使用的有GFP_KERNEL或者GFP_ATOMIC;order參數(shù)是請求的緩沖頁面大小,該參數(shù)是一個以2為底數(shù)的對數(shù)。以下為get_free_pages()函數(shù)的具體實現(xiàn)。

buffer=get_free_pages(unsigned int flags,unsigned int order);

如果分配成功,函數(shù)將返回緩存區(qū)第一頁的起始地址,該地址是一個虛擬地址,無法被外設(shè)所訪問。所以采用DMA方式使外設(shè)讀寫緩存區(qū)內(nèi)時,都要將該緩存區(qū)地址映射成總線地址。對于PCI設(shè)備來說,緩存區(qū)的映射有兩種方式:流DMA映射、一致DMA映射。驅(qū)動開發(fā)人員被建議使用流DMA映射而不是一致DMA映射。原因是一致DMA映射具有更長的存活周期,它會占用的一些相關(guān)的寄存器,但只在初期使用它們一次;此外,在一些硬件上,某些可以用于流式DMA映射上的優(yōu)化手段不能被運用在一致性DMA映射上。流DMA映射實現(xiàn)函數(shù)如下。

dma_addr_t dma_map_single(struct device*dev,void*buffer,size_t size,enum dma_data_drection diretion);

該函數(shù)返回緩存區(qū)buffer的總線地址,同時將總線的控制權(quán)交給外設(shè)。函數(shù)中,size表示待發(fā)送數(shù)據(jù)的大小。diretion表示數(shù)據(jù)的傳輸方向,常用的選項有:DMA_TO_DEVICE表示數(shù)據(jù)發(fā)送到外設(shè);DMA_FROM_DEVICE表示數(shù)據(jù)來自于外設(shè)。

3.2.2 數(shù)據(jù)傳輸實現(xiàn)

將總線控制權(quán)交給外設(shè)后,外設(shè)就可以從緩存區(qū)讀寫數(shù)據(jù)了。外設(shè)一般擁有2個及其以上獨立DMA通道,每個通道包括1個DMA控制器和1個雙向的FIFO。大多數(shù)DMA控制器具有一個相似的架構(gòu),如圖3所示,它有1個DMA緩存區(qū)的開始地址和1個記錄待傳輸數(shù)據(jù)位字節(jié)數(shù)的計數(shù)寄存器。隨著每次的傳輸,DMA控制器增加其地址寄存器數(shù)值和減小計數(shù)寄存器數(shù)值。當(dāng)計數(shù)寄存器減小到0時,DMA控制器產(chǎn)生一個中斷,并準(zhǔn)備下一次傳輸[8]。

為了更好地說明問題,以PCI9080芯片為例,說明外設(shè)發(fā)送數(shù)據(jù)到緩存區(qū)的過程。PCI9080是一款32位/33 MHz的通用PCI總線控制器專用芯片,它符合PCI總線規(guī)范2.2版本,突發(fā)傳輸速率可達(dá)132 MByte/s,支持主模式、從模式、DMA傳輸模式。芯片提供了2個獨立的DMA數(shù)據(jù)通道,配備有支持外設(shè)與CPU存儲器之間零等待狀態(tài)突發(fā)傳輸?shù)碾p向FIFO。PCI9080以其強(qiáng)大的功能為PCI總線接口的開發(fā)提供了一種簡潔的方法,設(shè)計者只需設(shè)計好本地總線接口控制電路,即可實現(xiàn)PCI總線與系統(tǒng)內(nèi)存間的高速數(shù)據(jù)傳輸。PCI9080與PCI總線、本地總線及DMA傳輸之間的關(guān)系如圖4所示。

鑒于PCI9080的2個DMA數(shù)據(jù)通道傳輸原理一致,此處僅介紹如何利用DMA數(shù)據(jù)通道0實現(xiàn)PCI總線側(cè)到本地總線側(cè)的數(shù)據(jù)傳輸過程,實現(xiàn)傳輸?shù)闹饕a如下描述,代碼中所涉及到的部分DMA配置寄存器說明如表1所示。

表1 相關(guān)DMA寄存器Tab.1 DMA registers

設(shè)計中采用PCI9080的DMA工作方式,在該工作方式下,PCI9080為PCI總線的主控設(shè)備,同時也是Local總線的控制者,2條總線間的數(shù)據(jù)傳輸通過設(shè)置其DMA控制器相關(guān)寄存器得以實現(xiàn)。以上述過程為例,可以分為如下6個步驟:1)設(shè)置方式寄存器(DMA_MODE)。PCI9080有兩種傳輸方式:0表示塊傳輸(適用于連續(xù)的源、目的存儲空間),1表示聚/散傳輸;2)設(shè)置 Local地址寄存器(DMA_LADR)。設(shè)置Local總線側(cè)地址空間;3)設(shè)置PCI地址寄存器(DMA_PADR)。設(shè)置PCI總線側(cè)地址空間;4)設(shè)置傳輸計數(shù)寄存器(DMA_SIZE)。以字節(jié)為單位設(shè)置傳輸數(shù)據(jù)量;5)設(shè)置命令/狀態(tài)寄存器(DMA_CSR)。設(shè)置DMA傳輸方向;6)設(shè)置命令/狀態(tài)寄存器(DMA_CSR)。啟動DMA傳輸操作,并讀該寄存器返回傳輸狀態(tài)。

啟動DMA傳輸操作后,PCI9080輸出LW/R#=1,表明本次DMA操作為寫,即傳輸方向為PCI-to-Local。隨后PCI9080將向CPU發(fā)送總線控制申請信號(LHOLD=1),CPU若發(fā)現(xiàn)總線空閑,則產(chǎn)生一個響應(yīng)信號(LHOLDA=1),表示允許PCI9080控制總線,同時向CPU輸出 LBE[3:0]#=0h,表明本次傳輸使用的總線寬度為32位。PCI9080檢測到LHOLDA=1后,輸出ADS#=0用于通知CPU本地總線上的地址即將有效,并從下一個時鐘開始發(fā)送數(shù)據(jù)。CPU接收到ADS#=0后,獲取PCI9080發(fā)送的地址,同時發(fā)出READY#=0信號,通知PCI9080開啟數(shù)據(jù)傳輸。DMA傳輸(PCI-to-Local)方向信號時序圖見圖5所示。

圖5 PCI-to-Local方向信號時序圖Fig.5 PCI-to-Local the direction of signal timing diagram

在傳輸啟動后的每一個時鐘周期里,PCI9080每傳輸一個數(shù)據(jù),其內(nèi)部傳輸計數(shù)寄存器便自動減1,直至計數(shù)寄存器減為0,并輸出BLAST#=0,表明這時傳輸?shù)氖亲詈笠粋€數(shù)據(jù)。隨后PCI9080釋放對總線的控制權(quán)并向主機(jī)發(fā)出一個中斷請求,從而觸發(fā)中斷服務(wù)例程執(zhí)行。至此,一次完整的PCI設(shè)備DMA數(shù)據(jù)發(fā)送流程完畢,其過程如圖6所示。

圖6 數(shù)據(jù)發(fā)送流程Fig.6 Sending data process

4 分析及結(jié)論

為驗證DMA方式在外設(shè)與系統(tǒng)內(nèi)存間的數(shù)據(jù)傳輸性能,進(jìn)行了多次傳輸測試。結(jié)果表明DMA存取技術(shù)以其高速大批量的傳輸特性,能很好地匹配PCI總線功能,大大提高了數(shù)據(jù)吞吐量,減少了CPU在數(shù)據(jù)傳輸操作中的參與程度,同時也減少了對CPU的占用時間,提高了系統(tǒng)的整體效率。

[1]劉秀萍,李艷芬.基于DMA方式的高速數(shù)據(jù)傳輸技術(shù)[J].導(dǎo)彈試驗技術(shù),2009,(02):61-63.LIU Xiu-ping,LI Yan-fen.High-speed data transfer technology based on DMA mode [J].Missile Test,2009,(02):61-63.

[2]朱紅星,苗克堅.Linux下PCI設(shè)備流式DMA驅(qū)動開發(fā)[J].微處理機(jī),2007,8(4):69-72.ZHU Hong-xing,MIAO Ke-jian.Linux PCI device under streaming DMA-driven development[J].Microprocessor,2007,8(4):69-72.

[3]BOVET Daniel P,CESATI Marco.深入了解 Linux 內(nèi)核[M].中國電力出版社,2007:31-45.BOVET Daniel P,CESATI Marco.Depth understanding of the Linux kernel[M].China Electric Power Press,2007:31-45.

[4]CORBET Jonathan,RUBINI Alessandro,HARTMAN Greq Kroah.Linux.Device.Drivers[M].O'Reilly Media inc,2005.

[5]董春橋,李凱.Linux系統(tǒng)PCI設(shè)備驅(qū)動程序開發(fā)[J].計算機(jī)測量與控制,2005,13(11):1289-1291.DONG Chun-qiao,LI Kai.PCI device driver development Linux system [J].Computer Measurement and Control,2005,13(11):1289-1291.

[6]馬萍,唐衛(wèi)華,李緒志.基于PCIExpress總線高速數(shù)采卡的設(shè)計與實現(xiàn)[J].微計算機(jī)信息,2008,24(9-1):116-118.MA Ping,TANG Wei-hua,LI Xu-zhi.PCIExpress high speed data acquisition card based on can bus-based design and realization [J].Micro-computer Information,2008,24(9-1):116-118.

[7]林乃響.DMA編程在Linux系統(tǒng)下的應(yīng)用[J].計算機(jī)與信息技術(shù),2006,(3):38-39.LIN Nai-xiang.Application of DMA programming under Linux systems[J].Computer and Information Technology,2006,(3):38-39.

[8]曹宗凱,胡晨,姚國良.DMA在內(nèi)存間數(shù)據(jù)拷貝中的應(yīng)用及其性能分析[J].電子器件,2007,30(01):311-313.CAO Zong-kai,HU Chen,YAO Guo-liang.DMA memory copy of data in application and performance analysis of[J].Electronic Devices,2007,30(01):311-313.

猜你喜歡
輸入輸出外設(shè)寄存器
Lite寄存器模型的設(shè)計與實現(xiàn)
Camtasia Studio高清視頻輸入輸出原理及方法
鐵路信號系統(tǒng)安全輸入輸出平臺
輸入輸出理論在大學(xué)英語聽說課堂中的教學(xué)探索
分簇結(jié)構(gòu)向量寄存器分配策略研究*
輸入輸出視角下高職英語教學(xué)研究
Microchip推出具備雙ADC外設(shè)的全新器件,擴(kuò)展其低成本8位PIC?單片機(jī)產(chǎn)品線
高速數(shù)模轉(zhuǎn)換器AD9779/AD9788的應(yīng)用
一種可重構(gòu)線性反饋移位寄存器設(shè)計
貼身呵護(hù) 必不可少的PSP外設(shè)
沁水县| 曲麻莱县| 庐江县| 凤冈县| 揭东县| 建湖县| 景泰县| 甘德县| 巫山县| 平安县| 临颍县| 陕西省| 津南区| 桐庐县| 东方市| 榆中县| 洛浦县| 乌拉特中旗| 天全县| 苍梧县| 荣昌县| 茶陵县| 莒南县| 平度市| 望城县| 林口县| 虹口区| 天气| 美姑县| 周宁县| 吉林省| 仁布县| 凤山县| 伊宁县| 荣成市| 兴文县| 林西县| 齐河县| 洪江市| 壤塘县| 安乡县|