基于微處理器和UDAl34l的嵌入式音頻系統(tǒng)設(shè)計(jì)
設(shè)備驅(qū)動(dòng)程序是操作系統(tǒng)內(nèi)核和機(jī)器硬件之間的接口,為應(yīng)用程序屏蔽了硬件細(xì)節(jié)。設(shè)備驅(qū)動(dòng)是內(nèi)核的一部分,主要完成以下功能:設(shè)備初始化和釋放;設(shè)備管理,包括實(shí)時(shí)參數(shù)設(shè)置及提供對(duì)設(shè)備的操作接口;讀取應(yīng)用程序傳送給設(shè)備文件的數(shù)據(jù)并回送應(yīng)用程序請(qǐng)求的數(shù)據(jù);檢測(cè)和處理設(shè)備出現(xiàn)的錯(cuò)誤。
音頻設(shè)備驅(qū)動(dòng)程序主要通過對(duì)硬件的控制實(shí)現(xiàn)音頻流的傳輸,同時(shí)向上層提供標(biāo)準(zhǔn)的音頻接口。筆者設(shè)計(jì)的音頻接口驅(qū)動(dòng)向上提供2個(gè)標(biāo)準(zhǔn)接口:數(shù)字音頻處理(Digital Sound Processing-DSP),負(fù)責(zé)音頻數(shù)據(jù)的傳輸即播放數(shù)字化聲音文件和錄音操作等;混音器(MIXER),負(fù)責(zé)對(duì)輸出音頻進(jìn)行混音處理,如音量調(diào)節(jié)、高低音控制等。這2個(gè)標(biāo)準(zhǔn)接口分別對(duì)應(yīng)設(shè)備文件dev/dsp和dev/mixer。
整個(gè)音頻驅(qū)動(dòng)的實(shí)現(xiàn)分為初始化、打開設(shè)備、DSP驅(qū)動(dòng)、MIXER驅(qū)動(dòng)和釋放設(shè)備等部分。
4.1 初始化、打開設(shè)備
設(shè)備初始化主要完成對(duì)UDAl34l音量、采樣頻率、L3接口等的初始化,并且注冊(cè)設(shè)備。通過函數(shù)audio_init(void)完成以下具體功能:
· S3C2410控制端口(GPBl-GPB3)的初始化;
· 為設(shè)備分配DMA通道;
· UDAl34l的初始化;
· 注冊(cè)audio設(shè)備和mixer設(shè)備。
· 打開設(shè)備由打開函數(shù)open()完成以下功能;
· 設(shè)置好ⅡS和L3總線;
· 準(zhǔn)備好聲道、采樣寬度等參數(shù)并通知設(shè)備;
· 根據(jù)采樣參數(shù)計(jì)算出緩沖區(qū)大小;
· 分配相應(yīng)大小的DMA緩沖區(qū)供設(shè)備使用。
4.2 DSP驅(qū)動(dòng)的實(shí)現(xiàn)
DSP驅(qū)動(dòng)實(shí)現(xiàn)了音頻數(shù)據(jù)的傳輸即播放和錄音的數(shù)據(jù)傳輸。同時(shí)提供ioctl對(duì)UDA134l中的DAC和ADC采樣率進(jìn)行控制。采樣率的控制主要是讀寫UDAl34l內(nèi)的采樣率控制寄存器,所以驅(qū)動(dòng)的主要部分就是控制音頻數(shù)據(jù)的傳輸。
驅(qū)動(dòng)中通過結(jié)構(gòu)static audio_state來描述整個(gè)音頻系統(tǒng)的狀態(tài),其中最主要的是2個(gè)數(shù)據(jù)流結(jié)構(gòu)audio_in和audio_out。這2個(gè)數(shù)據(jù)流結(jié)構(gòu)分別描述輸入音頻流和輸出音頻流的信息。通過對(duì)audio_in和audio_out的操作分別實(shí)現(xiàn)音頻的輸入和輸出(音頻的播放和錄音),本驅(qū)動(dòng)的主要內(nèi)容是數(shù)據(jù)流結(jié)構(gòu)的設(shè)計(jì)和實(shí)現(xiàn)。該結(jié)構(gòu)應(yīng)該包含音頻緩沖區(qū)的信息、DMA的相關(guān)信息、所用到的信號(hào)量及FIFO的入口寄存器的地址。
為了提高系統(tǒng)的吞吐量,系統(tǒng)使用DMA技術(shù)直接將需要回放或錄制的聲音存放在內(nèi)核的DMA緩存區(qū)中,由于S3C2410的DMA控制器沒有內(nèi)置的DMA存儲(chǔ)區(qū)域,因而驅(qū)動(dòng)程序必須在內(nèi)存內(nèi)為音頻設(shè)備分配DMA緩存區(qū)。緩沖區(qū)設(shè)置是否合理非常關(guān)鍵。以write()函數(shù)為例,因?yàn)橐纛l數(shù)據(jù)量通常較大,而緩存太小容易造成緩存溢出,所以要采用較大的緩沖區(qū)。而要填充大的緩沖區(qū),CPU就要一次處理大量的數(shù)據(jù),這樣處理數(shù)據(jù)時(shí)間較長(zhǎng),容易造成延遲。筆者采用多個(gè)緩存的機(jī)制,將緩沖區(qū)分為多個(gè)數(shù)據(jù)段。數(shù)據(jù)段的個(gè)數(shù)和大小分別在數(shù)據(jù)流結(jié)構(gòu)中指定。這樣把大的數(shù)據(jù)段分為幾個(gè)小段處理,每處理一小段數(shù)據(jù)就可以通過DMA發(fā)送出去。read函數(shù)也是如此,DMA每發(fā)來一小段數(shù)據(jù)就可以處理,不用等到大緩沖區(qū)都填滿才處理數(shù)據(jù)。這里還提供了ioctl接口給上層調(diào)用,這樣上層可以根據(jù)音頻數(shù)據(jù)的精度即數(shù)據(jù)流量來調(diào)整緩沖區(qū)數(shù)據(jù)段的大小和個(gè)數(shù),以取得最好的傳輸效果。
4.3 MIXER驅(qū)動(dòng)的實(shí)現(xiàn)
MIXER驅(qū)動(dòng)只控制混音效果,并不執(zhí)行讀寫操作,所以MIXER的文件操作結(jié)構(gòu)只實(shí)現(xiàn)了1個(gè)ioctl調(diào)用,提供給上層設(shè)置CODEC的混音效果。驅(qū)動(dòng)中主要實(shí)現(xiàn)了1個(gè)結(jié)構(gòu)體struct UDAl34l_codec。該結(jié)構(gòu)體描述了CODEC的基本信息,主要是實(shí)現(xiàn)了CODEC寄存器的讀寫函數(shù)和混音的控制函數(shù)。MIXER文件操作結(jié)構(gòu)中的ioctl就是調(diào)用U-DAl341_codec中的混音控制函數(shù)來實(shí)現(xiàn)的。
4.4 設(shè)備的卸載
設(shè)備的卸載由注銷函數(shù)close()來完成。注銷函數(shù)使用注冊(cè)時(shí)得到的設(shè)備號(hào),同時(shí)釋放驅(qū)動(dòng)程序使用的各種系統(tǒng)資源,如DMA和緩沖區(qū)等。
5 結(jié)束語
該系統(tǒng)已經(jīng)在基于S3C2410的開發(fā)平臺(tái)上得到了實(shí)現(xiàn),可以順利進(jìn)行音頻的播放和采集,并取得良好的效果。
linux操作系統(tǒng)文章專題:linux操作系統(tǒng)詳解(linux不再難懂)
評(píng)論