新聞中心

EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > 基于嵌入式Linux 系統(tǒng)的高速設(shè)備驅(qū)動(dòng)程序?qū)崿F(xiàn)

基于嵌入式Linux 系統(tǒng)的高速設(shè)備驅(qū)動(dòng)程序?qū)崿F(xiàn)

作者: 時(shí)間:2012-03-24 來(lái)源:網(wǎng)絡(luò) 收藏

圖2 改進(jìn)的設(shè)備驅(qū)動(dòng)流程圖

2.2 的進(jìn)一步改進(jìn)

基于以上幾點(diǎn),為了能夠在Linux中實(shí)現(xiàn)的數(shù)據(jù)通信,對(duì)結(jié)構(gòu)作出進(jìn)一步改進(jìn)的設(shè)計(jì)。

在設(shè)備的實(shí)現(xiàn)上,采用生產(chǎn)者-消費(fèi)者模型與循環(huán)緩存相結(jié)合的結(jié)構(gòu)。將從硬件設(shè)備到核心態(tài)內(nèi)存的DMA傳輸看作生產(chǎn)者,而從核心態(tài)內(nèi)存搬移到用戶態(tài)的數(shù)據(jù)傳輸過(guò)程看作消費(fèi)者;同時(shí)為DMA傳輸分配的核心態(tài)內(nèi)存采用循環(huán)鏈的結(jié)構(gòu)。

在驅(qū)動(dòng)程序中,將read()函數(shù)作為設(shè)備讀操作的主函數(shù),實(shí)現(xiàn)消費(fèi)者的功能。當(dāng)read()每次被調(diào)用時(shí),從DMA緩存鏈中讀取當(dāng)前指針?biāo)傅膬?nèi)存數(shù)據(jù),通過(guò)copy_to_user()函數(shù),將數(shù)據(jù)傳出核心態(tài),復(fù)制到用戶態(tài)內(nèi)存,以便后續(xù)的數(shù)據(jù)處理。

而在驅(qū)動(dòng)程序中,Irq_service()函數(shù)實(shí)現(xiàn)生產(chǎn)者的功能,當(dāng)有中斷產(chǎn)生后,系統(tǒng)進(jìn)入Irq_service(),表明一次DMA的傳輸結(jié)束,并且在Irq_service()中,設(shè)置下一次DMA傳輸?shù)膮?shù),包括DMA傳輸?shù)臄?shù)據(jù)大小、DMA傳輸?shù)哪繕?biāo)內(nèi)存。之后,調(diào)用interrupt_sleep_on()函數(shù),使得系統(tǒng)進(jìn)入進(jìn)程調(diào)度,等待下一次DMA的操作完成。一旦完成,就會(huì)產(chǎn)生中斷并重復(fù)以上的過(guò)程。因此,作為生產(chǎn)者的Irq_service()函數(shù),只要初始化后,就會(huì)在中斷的觸發(fā)下不斷被調(diào)用。換句話說(shuō),只要有數(shù)據(jù)到達(dá)硬件設(shè)備,就會(huì)不斷將其通過(guò)DMA的方式讀入到核心態(tài)的循環(huán)緩存中。我們可以將DMA緩存在允許的情況下,開的大一些,因?yàn)楫?dāng)接收的數(shù)據(jù)呈現(xiàn)一種突發(fā)的狀態(tài)時(shí),較小的緩沖池可能由于不能及時(shí)地將數(shù)據(jù)取走而溢出,造成數(shù)據(jù)的丟失。

與此同時(shí),還有個(gè)問(wèn)題必須注意,即當(dāng)read()函數(shù)將緩存池中的數(shù)據(jù)都搬完之后,仍然沒有DMA的輸入。此時(shí),read()繼續(xù)讀取的話,顯然會(huì)造成數(shù)據(jù)的錯(cuò)誤,因此采用信號(hào)量是必須的。當(dāng)信號(hào)量表明,DMA的緩存已空時(shí),若應(yīng)用程序調(diào)用read()進(jìn)行讀數(shù)據(jù)的話,將不做任何操作,并返回已讀數(shù)據(jù)量為0。當(dāng)信號(hào)量表明DMA的緩存為滿時(shí),將DMA讀入的數(shù)據(jù)丟棄,并設(shè)置buff_full = 0。

除此以外,我們還必須對(duì)Linux驅(qū)動(dòng)進(jìn)行以下步驟的操作:設(shè)備的注冊(cè)和注銷、設(shè)備的打開和釋放。通過(guò)register_chrdev()函數(shù)向系統(tǒng)注冊(cè)設(shè)備的設(shè)備號(hào),在設(shè)備使用結(jié)束后,可以使用unregister_chrdev()從內(nèi)核注銷設(shè)備,釋放主設(shè)備號(hào)。在設(shè)備注冊(cè)之后,由open()函數(shù)打開設(shè)備,close()釋放設(shè)備。在驅(qū)動(dòng)的初始化中,需要對(duì)DMA進(jìn)行首次設(shè)置,以及緩存的分配。我們可以調(diào)用 get_free_pages()函數(shù)進(jìn)行內(nèi)存頁(yè)面的分配,它會(huì)給DMA分配內(nèi)存中連續(xù)的頁(yè)面,這對(duì)于DMA是必須的,因?yàn)镈MA操作的物理地址是連續(xù)的。在內(nèi)存分配之后,我們進(jìn)行中斷的配置,通過(guò)調(diào)用函數(shù)request_irq()。接著調(diào)用request_dma() 函數(shù)對(duì)DMA進(jìn)行申請(qǐng)注冊(cè)。

最后,有一點(diǎn)不得不引起我們的重視,即DMA一致性問(wèn)題。DMA一致性的問(wèn)題是指當(dāng)進(jìn)行數(shù)據(jù)DMA方式讀入時(shí),由于沒有經(jīng)過(guò)CPU的處理,因此 CPU的CACHE會(huì)認(rèn)為該地址的內(nèi)存沒有被重寫過(guò),而實(shí)際該內(nèi)存所存儲(chǔ)的數(shù)據(jù)已被改變;當(dāng)CPU需要處理該內(nèi)存的數(shù)據(jù)時(shí),由于認(rèn)為數(shù)據(jù)沒有改變,會(huì)直接調(diào)用CACHE內(nèi)的數(shù)據(jù),造成數(shù)據(jù)錯(cuò)誤,一般表現(xiàn)為數(shù)據(jù)的重復(fù)。在實(shí)際操作中,我們可以通過(guò)禁用該內(nèi)存的CACHE功能,來(lái)避免錯(cuò)誤。在新版的Linux 內(nèi)核中提供dma_alloc_coherent()和dma_free_coherent()函數(shù)進(jìn)行DMA一致性內(nèi)存的分配。

以上就是我們針對(duì)驅(qū)動(dòng)改進(jìn)的程序代碼結(jié)構(gòu)。該驅(qū)動(dòng)程序結(jié)構(gòu)通過(guò)將核心態(tài)的DMA操作與數(shù)據(jù)到拷貝以及用戶態(tài)上數(shù)據(jù)的處理獨(dú)立開來(lái),依靠信號(hào)量進(jìn)行相互的制約,可以有效的避免DMA操作的頻繁性和大數(shù)據(jù)量處理的較長(zhǎng)時(shí)間之間的矛盾。驅(qū)動(dòng)程序的流程如圖2所示。

3 應(yīng)用實(shí)例

下面我們以視頻會(huì)議系統(tǒng)為例,介紹基于以上結(jié)構(gòu)的高速設(shè)備驅(qū)動(dòng)程序的實(shí)現(xiàn)。

在視頻會(huì)議系統(tǒng)中,AT91RM9200通過(guò)SPI接口與TI DM642 DSP芯片的McBSP接口相連進(jìn)行圖像數(shù)據(jù)的傳輸。由于數(shù)據(jù)吞吐量很大,采用一般結(jié)構(gòu)甚至是一般的DMA結(jié)構(gòu)的驅(qū)動(dòng)程序都無(wú)法滿足數(shù)據(jù)的接收要求,造成數(shù)據(jù)無(wú)法實(shí)時(shí)的數(shù)據(jù)處理。我們針對(duì)該系統(tǒng)的特點(diǎn),對(duì)驅(qū)動(dòng)程序按照以上結(jié)構(gòu)作出改進(jìn),不但大大減輕了ARM處理器的負(fù)荷,同時(shí)能夠有效的進(jìn)行大數(shù)據(jù)量的傳輸和處理。

表1 驅(qū)動(dòng)程序改進(jìn)前后對(duì)比表

測(cè)得碼率上限

性能測(cè)試描述

改進(jìn)前

1Mbps

當(dāng)碼率接近1Mbps時(shí),出現(xiàn)數(shù)據(jù)丟失

改進(jìn)后

10Mbps

當(dāng)碼率達(dá)到10Mbps時(shí),驅(qū)動(dòng)仍然能夠正常工作

在我們的系統(tǒng)中,由于SPI接口需要傳輸標(biāo)清的視頻壓縮圖像,碼率一般為2Mbps,原結(jié)構(gòu)的驅(qū)動(dòng)程序在碼率較高的情況下,會(huì)出現(xiàn)數(shù)據(jù)的丟失,而數(shù)據(jù)的丟失不但影響了當(dāng)前幀的圖像的質(zhì)量,而且同時(shí)會(huì)造成后面多幀圖像的質(zhì)量嚴(yán)重下降,因而無(wú)法滿足這樣高數(shù)據(jù)率傳輸?shù)男枰?。而?jīng)過(guò)改進(jìn)的驅(qū)動(dòng)程序經(jīng)過(guò)測(cè)試,至少可以承受10Mbps碼率的數(shù)據(jù)傳輸,驗(yàn)證證明該結(jié)構(gòu)的驅(qū)動(dòng)程序可以完全勝任高速設(shè)備的數(shù)據(jù)傳輸且經(jīng)過(guò)長(zhǎng)時(shí)間測(cè)試,性能可靠。

4 結(jié)束語(yǔ)

本文的創(chuàng)新點(diǎn)是提出了一種基于ARM芯片的高速數(shù)據(jù)傳輸?shù)脑O(shè)備驅(qū)動(dòng)實(shí)現(xiàn)方案。首先對(duì)驅(qū)動(dòng)程序程序的傳統(tǒng)結(jié)構(gòu)框架進(jìn)行了介紹。而在實(shí)際的應(yīng)用中,為了能夠適應(yīng)高速率的數(shù)據(jù)傳輸,針對(duì)ARM芯片以及Linux操作系統(tǒng)的特點(diǎn),對(duì)設(shè)備驅(qū)動(dòng)程序進(jìn)行了改進(jìn)。最后,以視頻會(huì)議系統(tǒng)為例,對(duì)該結(jié)構(gòu)的驅(qū)動(dòng)程序進(jìn)行實(shí)現(xiàn)、測(cè)試和驗(yàn)證,可完全勝任高速設(shè)備的數(shù)據(jù)傳輸且性能可靠。不僅如此,該結(jié)構(gòu)的設(shè)備驅(qū)動(dòng)程序同樣適合于系統(tǒng)的各種高速設(shè)備傳輸?shù)膽?yīng)用。

參考文獻(xiàn)

[1] Alessandro Rubini Linux Device Drivers 0'Reilly Assocoates,Inc. 1998.

[2] Karim Yagbmour Building Embedded Linux System 0'Reilly Media,Inc. 2004.

[3] Linux kernel, version 2.4.30

[4] 雷鋒成 方濱 李慧杰,嵌入式網(wǎng)絡(luò)數(shù)字圖像監(jiān)控系統(tǒng),微計(jì)算機(jī)信息.2006.9-2


上一頁(yè) 1 2 下一頁(yè)

評(píng)論


相關(guān)推薦

技術(shù)專區(qū)

關(guān)閉