摘要:簡要分析了目前Linux BSP開發(fā)存在的缺陷,通過分析兩個不同版本嵌入式Linux的Ac97聲卡驅(qū)動程序的異同,針對不同處理器提出了一種基于Linux的BSP標(biāo)準(zhǔn)#65377;在此基礎(chǔ)上,實現(xiàn)了一套基于XML的Linux BSP標(biāo)準(zhǔn)化配置工具,實現(xiàn)了基于圖形界面的Linux BSP生成方式,提高了嵌入式Linux BSP的開發(fā)效率#65377;
關(guān)鍵詞:Linux板級支持包標(biāo)準(zhǔn);Linux板級支持包配置工具; SLOT驅(qū)動開發(fā); WEDGE驅(qū)動開發(fā)
中圖分類號:TP31681文獻標(biāo)志碼:A
文章編號:10013695(2007)04010803
板級支持包(BSP)是在嵌入式系統(tǒng)中頻繁使用的一個概念#65377;BSP是介于操作系統(tǒng)與系統(tǒng)硬件之間的一個抽象層,確切地說是操作系統(tǒng)的一部分#65377;通常所指的BSP包括啟動代碼和系統(tǒng)相關(guān)的驅(qū)動及程序[1]#65377;BSP的作用是使硬件對于操作系統(tǒng)變得透明,從而使嵌入式系統(tǒng)和其應(yīng)用程序能夠運行在不同的硬件平臺上#65377;
BSP的開發(fā)處在整個系統(tǒng)開發(fā)的初期,BSP部分在硬件和操作系統(tǒng)#65380;上層應(yīng)用程序之間,所以要求BSP程序員對硬件#65380;軟件和操作系統(tǒng)都要有一定的了解,這樣才能做好BSP編程#65377;由于設(shè)計實現(xiàn)的復(fù)雜性,在設(shè)計特定BSP時很少從零開始,而是采用以下兩種快捷方法:①以經(jīng)典BSP為參考,在設(shè)計BSP時,首先選擇與應(yīng)用硬件環(huán)境最為相似的參考設(shè)計#65377;針對具體應(yīng)用的特定環(huán)境對參考設(shè)計的BSP進行必要的修改和增加,就可以完成簡單的BSP設(shè)計[2]#65377;②使用操作系統(tǒng)提供的BSP模板#65377;很多操作系統(tǒng)都提供相應(yīng)的BSP模板(一組需要編寫的文件),根據(jù)模板的提示也可以逐步完成特定BSP的設(shè)計[3,4]#65377;
這兩種BSP開發(fā)方法也存在著不足#65377;它不僅要求設(shè)計人員了解BSP的各個組成部分及所對應(yīng)的文件和相關(guān)參數(shù)的具體含義,還要求具備比較全面的軟硬件知識#65377;直接修改相關(guān)文件容易造成代碼的不一致性,增加軟件設(shè)計上的隱形錯誤,從而增加系統(tǒng)調(diào)試和代碼維護的難度#65377;隨著底層硬件功能的日益復(fù)雜,開發(fā)BSP所涉及的內(nèi)容也越來越多,這種原始方法的不足之處也越來越突出#65377;進行BSP設(shè)計方法和工具的創(chuàng)新成為一個日益突出的問題[5]#65377;
解決這個問題的一個可行辦法是設(shè)計實現(xiàn)一種具有圖形界面的BSP開發(fā)設(shè)計向?qū)?65377;由該向?qū)е笇?dǎo)設(shè)計者逐步完成BSP的設(shè)計和開發(fā),并最終由向?qū)上鄳?yīng)的BSP文件,而不再由設(shè)計人員直接對源文件進行修改#65377;這樣不僅可以大大縮短BSP的開發(fā)周期,系統(tǒng)的調(diào)試和維護也會變得簡單#65377;因此,這種方法成了嵌入式BSP開發(fā)的一種趨勢#65377;
本文提出了一種基于Linux的BSP標(biāo)準(zhǔn)(LBS)#65377;在LBS的基礎(chǔ)上,實現(xiàn)了一套Linux BSP配置工具(LBC),并用XML書寫了參考配置文件(CRF)#65377;LBC能夠從圖形界面讀入用戶配置,根據(jù)參考配置文件,自動生成特定系統(tǒng)的Linux BSP代碼#65377;
1Linux標(biāo)準(zhǔn)BSP結(jié)構(gòu)
當(dāng)前,Linux BSP的開發(fā)通常基于兩種方法,即使用Linux BSP模板,或者修改已經(jīng)存在的經(jīng)典Linux BSP#65377;一個新的Linux BSP一旦開發(fā)完成,就以Patch的形式發(fā)布#65377;這種開發(fā)模式的最大缺點是Linux BSP代碼的復(fù)用率很低#65377;
例如,Intel為其XScale PXA255 Sitsang板開發(fā)了某個設(shè)備的Linux 2.6內(nèi)核的驅(qū)動;開發(fā)完成后,發(fā)布了一個補丁:260sitsangdriverX.patch#65377;現(xiàn)在Motorola也要為它的DragonBall MX1 Ads板開發(fā)該相同硬件的Linux 2.6內(nèi)核的驅(qū)動#65377;由于處理器不同,它無法使用Intel的補丁,因而不得不重復(fù)Intel的工作#65377;為了解決這個問題,提高Linux BSP代碼的復(fù)用率,本文設(shè)計開發(fā)了一個Linux BSP標(biāo)準(zhǔn)結(jié)構(gòu),并完成了相應(yīng)的Linux BSP配置工具,由此可以自動生成Linux BSP代碼#65377;
以Ac97聲卡驅(qū)動程序為例,通過分析它在不同處理器(Intel的XScale PXA255和Motorola的MX1)下BSP代碼的不同來證明本文的設(shè)想#65377;
實際上,Linux內(nèi)核已經(jīng)在Arch目錄下提供了對不同處理器的支持#65377;比如Arch下有一個叫machepxa10db的目錄提供了對Pxa處理器的支持,對Ads開發(fā)板處理器的支持也可以在目錄machsa1100下找到#65377;但遺憾的是這種支持不夠完全,不同的處理器還是需要為同一個設(shè)備開發(fā)不同的驅(qū)動,因為該設(shè)備在不同CPU內(nèi)的Controller需要不同的驅(qū)動#65377;本文要做的就是自動生成對CPU Controller的驅(qū)動#65377;
圖1#65380;2分別是XScale PXA255 Sitsang和DragonBall MX1 Ads板的Ac97驅(qū)動的部分函數(shù)調(diào)用圖#65377;Sitsang和Ads基本上在標(biāo)準(zhǔn)內(nèi)核的Ac97驅(qū)動上增加了兩部分的內(nèi)容,即對Processor的Controller驅(qū)動和對板子上音頻解碼芯片(Codec)的驅(qū)動#65377;當(dāng)然,本文關(guān)心的是Processor的Controller驅(qū)動,它的相關(guān)函數(shù)在Sitsang中均以pxa開頭,在Ads中都以sa1111開頭#65377;
圖1XScale PXA255的Ac97驅(qū)動部分函數(shù)關(guān)系圖
圖2DragonBall MX1 的Ac97驅(qū)動部分函數(shù)關(guān)系圖
從圖1#65380;2中可以發(fā)現(xiàn),Ac97驅(qū)動在XScale和DragonBall下的函數(shù)調(diào)用結(jié)構(gòu)是相似的,基本上都完成了register_sound_dsp#65380;register_sound_mixer以及ac97_probe_codec這幾個函數(shù)功能#65377;對CPU的Ac97 Controller的驅(qū)動通常所實現(xiàn)的幾個功能,包括Controller的Init#65380;對Controller寄存器的讀寫等,所對應(yīng)的幾個函數(shù)也是類似的,如Sitsang的pxa_ac97_init#65380;pxa_ac97_read#65380;pxa_ac97_write分別對應(yīng)Ads的sa1111_ac97_cs42xx_init#65380;cs42xx_ac97_read_reg#65380;cs42xx_ac97_write_reg,而且絕大多數(shù)代碼都是一樣的#65377;其相同的代碼完全可以重用,相似的結(jié)構(gòu)則可以將其標(biāo)準(zhǔn)化#65377;
將XScale和DragonBall的Ac97代碼的區(qū)別分成兩類:①諸如聲卡電源設(shè)置,將聲卡電源控制寄存器置位,只是簡單改動一行或者幾行代碼;②諸如XScale的pxa_ac97_read函數(shù)和DragonBall的cs42xx_ac97_read_reg函數(shù),實現(xiàn)相似功能,但函數(shù)體的具體實現(xiàn)有些差別#65377;以此可以制定出一個Linux的標(biāo)準(zhǔn)BSP結(jié)構(gòu),分別處理這兩種情況,并開發(fā)一個配置工具Linux BSP Configure(LBC)#65377;當(dāng)要具體開發(fā)某個Linux BSP時,只需用LBC配置成相應(yīng)的體系結(jié)構(gòu),則該體系結(jié)構(gòu)的Linux BSP代碼自動可以生成#65377;
2基于XML的BSP配置工具實現(xiàn)
2.1SLOT驅(qū)動開發(fā)及XML標(biāo)志
仍然以Ac97驅(qū)動在XScale和DragonBall架構(gòu)下的代碼為例,對第1章中提出的Ac97代碼在XScale和DragonBall兩種CPU架構(gòu)下的兩種情況的區(qū)別,針對其中第①種區(qū)別提出了一種稱為SLOT驅(qū)動開發(fā)的方法來使其標(biāo)準(zhǔn)化#65377;
例如對Ac97電源控制寄存器的設(shè)置,XScale是在文件pxaac97.c中設(shè)置SITSANG_PCR_RW =~( SITSANG_PCR_AUDIO_ON ),DragonBall是在文件sa1111ac97.c中設(shè)置ADS_CPLD_PCON =~(ADS_PCON_AUDIO_ON | ADS_PCON_AUDIOPA_ON)#65377;兩者都是在執(zhí)行Init入口函數(shù)不久后,在Register dsp#65380;Register mixer#65380;Probe codec之前執(zhí)行#65377;可見,XScale和DragonBall兩者設(shè)置Ac97電源控制寄存器的語句,在代碼中處于相似的位置,完成相似的功能,使用相似的語句實現(xiàn),于是就可以用本文的配置工具來將其標(biāo)準(zhǔn)化#65377;把Ac97電源控制的語句做成一個SLOT,用本文的配置工具,根據(jù)配置的具體體系結(jié)構(gòu)來生成該體系結(jié)構(gòu)下的Ac97電源控制寄存器置位語句#65377;圖3為該SLOT在函數(shù)流程圖中的位置#65377;
圖3SLOT驅(qū)動開發(fā)
圖3中,當(dāng)前處理器配置為XScale PXA255時,本文的配置工具就會在圖中的SLOT位置自動填寫SITSANG_PCR_RW =~( SITSANG_PCR_AUDIO_ON )這一語句,生成XScale的Ac97電源置位語句;而當(dāng)處理器配置成DragonBall MX1時,就在SLOT處自動生成DragonBall的Ac97電源置位語句ADS_CPLD_PCON =~(ADS_PCON_AUDIO_ON | ADS_PCON_AUDIOPA_ON)#65377;
用XML來書寫參考配置文件(CRF)#65377;CRF包含了不同體系結(jié)構(gòu)的驅(qū)動代碼,需要專門的編程人員維護#65377;SLOT驅(qū)動開發(fā)的CRF文件如下:
本文的配置工具將會根據(jù)讀入的配置文件,按照這個參考配置文件生成相應(yīng)的具體代碼#65377;
2.2WEDGE 驅(qū)動開發(fā)及XML標(biāo)志
對本文第1章中提出的Ac97代碼在XScale和DragonBall架構(gòu)下差異的第②種情況,兩個函數(shù)pxa_ac97_read和cs42xx_ac97_read_reg實現(xiàn)相同的功能:讀取聲卡寄存器,但其代碼存在著差別#65377;雖然是整個函數(shù)的差別,但采用的處理方法是類似的#65377;由于代碼的差別量相對較多,稱之為WEDGE驅(qū)動開發(fā)#65377;
這兩個函數(shù)的聲明如下:
可以看出,它們不僅函數(shù)名相似,而且有相似的參數(shù)和相同的返回值#65377;分析函數(shù)體還可以發(fā)現(xiàn),它們實現(xiàn)的功能也是一樣的#65377;函數(shù)pxa_ac97_read的核心語句是val=*reg_addr,用來返回參數(shù)reg中提供的偏移值指向的地址的值;函數(shù)cs42xx_ac97_read_reg的核心語句是val=ACSDR >> 4,它也是用來返回參數(shù)reg提供的值所指向的偏移地址的值#65377;通過對比,標(biāo)準(zhǔn)化這些函數(shù)是可行的#65377;與SLOT方法類似,將這類函數(shù)做成一個WEDGE#65377;當(dāng)讀入用戶配置時,用配置工具在WEDGE處生成相應(yīng)的函數(shù)#65377;
WEDGE開發(fā)的CRF用XML表示如下:
2.3配置工具(LBC)
用C語言書寫本文的Linux BSP Configuration#65377;LBC要完成的工作包括讀入配置文件,然后根據(jù)參考配置文件(見第21#65380;22節(jié)) 生成相應(yīng)體系結(jié)構(gòu)的BSP代碼#65377;由于所生成的很多BSP代碼要寫入到同一個文件中,為了避免多次打開#65380;關(guān)閉同一個文件,將LBC生成的代碼先寫入一個臨時文件,這個臨時文件的代碼將按照要寫入的文件名組織#65377;
例如:
這樣,LBC生成的所有代碼都將先寫入該臨時文件相應(yīng)的文件名下,如LBC生成的那些將要寫入文件pxaac97.c的代碼都寫在該文件“/*pxaac97.c*/”和“/*pxaac97.c ends*/”所括的代碼段內(nèi)#65377;當(dāng)所有的BSP代碼生成完畢,LBC再將該臨時文件下的代碼分別寫入各文件,這樣每個文件只要打開讀寫#65380;關(guān)閉一次即可#65377;
3結(jié)束語
本文提出了一種Linux BSP標(biāo)準(zhǔn)的解決方案#65377;通過分析兩種不同處理器下Ac97驅(qū)動代碼的差異,找出了它們的共同點;最后得出一個結(jié)論:可以將它們標(biāo)準(zhǔn)化#65377;實現(xiàn)了一個自動生成Linux BSP代碼的配置工具,這種方案可以有效改進Linux BSP的開發(fā)速度,并提高Linux BSP代碼的復(fù)用率#65377;當(dāng)然,這并不意味著普通用戶就可以用該方案完全靠自己生成想要的Linux BSP,因為賴以自動生成BSP代碼的參考配置文件需要專門的程序員來維護#65377;但無論如何,這些程序員的開發(fā)工作將變得更加簡單和快捷#65377;
本文中所涉及到的圖表、注解、公式等內(nèi)容請以PDF格式閱讀原文。