??? 摘? 要: 通過(guò)使用DMA方式訪(fǎng)問(wèn)程序存儲(chǔ)區(qū)并實(shí)現(xiàn)程序的搬移,克服C6000指令系統(tǒng)的缺陷;并對(duì)C6000的C語(yǔ)言運(yùn)行環(huán)境和仿真器變量初始化過(guò)程進(jìn)行研究,采用自編程自初始化的方法,確保程序加載" title="加載">加載后能正常運(yùn)行。?
??? 關(guān)鍵詞: 引導(dǎo)裝載? DMA? DSP
?
??? DSP系統(tǒng)的引導(dǎo)裝載(Bootload)是指系統(tǒng)加電時(shí),DSP將一段存儲(chǔ)在外部的非易失性存儲(chǔ)器的代碼搬移到內(nèi)部的高速存儲(chǔ)器單元中執(zhí)行。這樣既利用了外部的存儲(chǔ)單元擴(kuò)展DSP本身有限的ROM資源,又充分發(fā)揮了DSP內(nèi)部資源的效能。盡管用戶(hù)代碼可直接掩膜到內(nèi)部ROM中,但一方面受容量和價(jià)格的限制,另一方面則不具有擴(kuò)展性和不易升級(jí)。FLASH是一種高密度、非易失性的電可擦寫(xiě)存儲(chǔ)器,十分適合低功耗、小尺寸和高性能的便攜式系統(tǒng)。除了可以采用專(zhuān)用的硬件編程器把代碼灌入FLASH中,也可以利用現(xiàn)成的DSP通過(guò)軟件編程實(shí)現(xiàn)同樣的功能,因此對(duì)整個(gè)系統(tǒng)的軟件升級(jí)很方便。?
??? TMS320C6000系列是TMS320系列產(chǎn)品中的新一代高性能DSPs芯片。由于其結(jié)構(gòu)上(如圖1)的特殊性,與C54系列的引導(dǎo)方式有很大差別。本文以C6202為例,介紹如何實(shí)現(xiàn)DSP正常的ROM引導(dǎo)。?
?
?
1 C6202的ROM引導(dǎo)模式?
??? C6202有兩種存儲(chǔ)器映射方式MAP0和MAP1。通過(guò)擴(kuò)展總線(xiàn)的XD[4:0]利用上拉/下拉電阻進(jìn)行復(fù)位時(shí)的芯片啟動(dòng)模式設(shè)置。本文將存儲(chǔ)器映射方式設(shè)置為MAP1,即地址0處的存儲(chǔ)器在內(nèi)部,芯片自加載方式為8bit ROM方式,如圖2的硬件連接。?
?
?
??? 設(shè)置完芯片加載方式后,ROM加載的具體過(guò)程是:位于外部CE1空間的ROM(即圖2中的FLASH)中的程序首先通過(guò)DMA[2]搬入地址0處,盡管加載過(guò)程是在芯片復(fù)位信號(hào)被釋放后才開(kāi)始的,但是當(dāng)芯片開(kāi)始復(fù)位時(shí),就開(kāi)始準(zhǔn)備上述傳輸了。用DMA進(jìn)行的這一加載過(guò)程是一個(gè)單幀的數(shù)據(jù)塊傳輸,數(shù)據(jù)塊的大小為64KB。EMIF[2]會(huì)根據(jù)芯片自加載方式的設(shè)置將相鄰的8bit或16bit數(shù)據(jù)合為32bit指令。傳輸完成后,CPU退出復(fù)位狀態(tài),開(kāi)始執(zhí)行地址0處的指令。?
2 硬件設(shè)計(jì)?
??? 本文僅給出DSP(TMS320C6202)與一片F(xiàn)LASH(AMD29VF040)的連接圖,如圖2。由DSP的相關(guān)輸出管腳控制FLASH的擦除和讀寫(xiě)。C6202的EMIF含有四個(gè)CE空間寄存器,由于ROM加載程序是從CE1空間搬入的,因此DSP的/CE1與FLASH的片選/CE相連。圖2中只用到DSP的低8位數(shù)據(jù)線(xiàn),如果自加載方式設(shè)置為16位或32位,可以通過(guò)DSP最低兩位EA1和EA0的譯碼BE[3:0]片選,或者選用16bit或32bit的FLASH。?
3 軟件設(shè)計(jì)?
??? 由于C6000的特殊結(jié)構(gòu),可以實(shí)現(xiàn)8條并行指令同時(shí)執(zhí)行,除非對(duì)硬件結(jié)構(gòu)非常了解的專(zhuān)業(yè)人員,才能充分利用硬件資源,將匯編語(yǔ)言的高效率發(fā)揮出來(lái)。若對(duì)實(shí)時(shí)性要求不是很高,采用C語(yǔ)言編程完全可以滿(mǎn)足需要,且C6000的優(yōu)化器優(yōu)化效率很高。這樣可以降低編程工作量,縮短開(kāi)發(fā)周期,可移植性好。本文以通用的C語(yǔ)言編程為例,介紹DSP對(duì)FLASH編程以實(shí)現(xiàn)正常的ROM引導(dǎo)。?
3.1 系統(tǒng)初始化?
??? 在運(yùn)行C語(yǔ)言前,必須建立C運(yùn)行時(shí)間環(huán)境[3](C runtime environment),確保C程序的正常運(yùn)行。運(yùn)行時(shí)間支持源程序庫(kù)(runtime-support source library)rts.src包含一個(gè)boot.asm模塊可以實(shí)現(xiàn)此功能。在連接器命令中使用-c或-cr選項(xiàng),且將rts6200.lib作為其中一個(gè)連接文件,連接器自動(dòng)調(diào)用boot.asm模塊產(chǎn)生c_int00函數(shù)。在硬件復(fù)位中斷產(chǎn)生以及系統(tǒng)工作時(shí),先執(zhí)行此函數(shù)。?
??? 函數(shù)c_int00完成下面三個(gè)初始化任務(wù):?
??? (1)建立堆棧并初始化堆棧指針;?
??? (2)初始化全局變量;?
??? (3)運(yùn)行主函數(shù)。?
3.2 初始化變量?
??? 在程序運(yùn)行前,全局變量必須初始化。編譯器建立了.cinit段用來(lái)初始化全局變量和靜態(tài)變量。?
3.2.1 .cinit段?
??? 在.cinit段內(nèi)有不同長(zhǎng)度的初始化記錄,每一個(gè)必須初始化的變量在.cinit段內(nèi)都有一個(gè)對(duì)應(yīng)的記錄。如圖3。?
?
?
??? 每個(gè)記錄包含三部分:需要被初始化的變量的長(zhǎng)度、變量的地址和變量初始值。?
3.2.2 運(yùn)行時(shí)初始化變量?
??? 若在連接器中使用-c選項(xiàng),則在程序開(kāi)始運(yùn)行時(shí),函數(shù)c_int00初始化變量。具體過(guò)程如下:仿真器加載程序時(shí),根據(jù).cmd文件的定位,將.cinit段拷貝到C6202的程序存儲(chǔ)區(qū)或數(shù)據(jù)存儲(chǔ)" title="數(shù)據(jù)存儲(chǔ)">數(shù)據(jù)存儲(chǔ)區(qū),并且用指針指向加載后的初始化表的首地址。當(dāng)程序開(kāi)始運(yùn)行時(shí),函數(shù)c_int00中的引導(dǎo)程序自動(dòng)識(shí)別初始化表中的數(shù)據(jù)格式,初始化.bss段中對(duì)應(yīng)的變量,完成初始化過(guò)程。如圖4。
?
?
3.2.3 加載時(shí)初始化變量?
??? 若在連接器中使用-cr選項(xiàng),連接器在.cinit段首設(shè)置STYP_COPY位。當(dāng)仿真器加載程序時(shí),加載器會(huì)判斷這一位,識(shí)別目標(biāo)文件中.cinit內(nèi)的初始化記錄格式并初始化.bss中的變量,而不是先將.cinit段拷貝到DSP的內(nèi)存區(qū)域。如圖5。?
?
?
3.3 燒寫(xiě)" title="燒寫(xiě)">燒寫(xiě)FLASH?
??? 要想實(shí)現(xiàn)DSP ROM的正常加載,必須將程序存儲(chǔ)區(qū)中的指令數(shù)據(jù)正確地寫(xiě)到FLASH里。圖1中可以看出,訪(fǎng)問(wèn)片內(nèi)程序存儲(chǔ)器" title="程序存儲(chǔ)器">程序存儲(chǔ)器只有兩個(gè)途徑:CPU訪(fǎng)問(wèn)和DMA訪(fǎng)問(wèn)。CPU訪(fǎng)問(wèn)片內(nèi)程序存儲(chǔ)器是通過(guò)程序取指單元實(shí)現(xiàn)的,然后完成指令分配和指令譯碼。C6000沒(méi)有提供任何對(duì)片內(nèi)程序存儲(chǔ)器操作的指令,因此不可能直接使用指令取出程序區(qū)的內(nèi)容或者將數(shù)據(jù)寫(xiě)入程序區(qū)中。但是DMA可以訪(fǎng)問(wèn)片內(nèi)數(shù)據(jù)存儲(chǔ)區(qū)、片內(nèi)程序存儲(chǔ)區(qū)、片內(nèi)集成外設(shè)、外接存儲(chǔ)器等,可以在沒(méi)有CPU參與的情況下完成映射存儲(chǔ)空間中數(shù)據(jù)的搬移。因此,可以編寫(xiě)一個(gè)燒寫(xiě)FLASH的程序。在數(shù)據(jù)存儲(chǔ)區(qū)開(kāi)辟一個(gè)緩存區(qū),使用DMA方式將程序區(qū)的內(nèi)容讀到這個(gè)緩存區(qū),然后再使用指令將緩存區(qū)的內(nèi)容燒寫(xiě)到FLASH內(nèi)(具體的命令字和程序與C54類(lèi)似)。如圖6。?
?
?
??? 為了保證DSP ROM加載后C運(yùn)行環(huán)境正常,全局變量或者靜態(tài)變量必須初始化。這比使用仿真器加載程序要復(fù)雜。解決這個(gè)問(wèn)題,最簡(jiǎn)單的方法就是:將燒寫(xiě)FALSH的程序(不能含有全局變量和靜態(tài)變量)和主程序" title="主程序">主程序編在一起,在連接器中選擇-cr選項(xiàng),用仿真器加載編譯連接后的程序會(huì)自動(dòng)初始化主程序中的變量。將DSP的PC指針直接跳轉(zhuǎn)到燒寫(xiě)FALSH程序處,按照前面的方法使用DMA方式把主程序燒寫(xiě)到FLASH內(nèi)部,再把已經(jīng)初始化的變量燒寫(xiě)到FLASH的其他位置,不能覆蓋已經(jīng)寫(xiě)入的數(shù)據(jù)。另外,在主程序內(nèi)要自己編寫(xiě)一個(gè)自加載函數(shù),完成加載器的功能,即把固化在FLASH內(nèi)部的變量值讀入.cmd文件所定位的.bss中,實(shí)現(xiàn)脫機(jī)運(yùn)行時(shí)變量的初始化。?
??? 筆者在實(shí)驗(yàn)中遇到了C6202 ROM加載的問(wèn)題,通過(guò)對(duì)DSP內(nèi)部功能單元的研究,發(fā)現(xiàn)采用DMA方式訪(fǎng)問(wèn)程序存儲(chǔ)區(qū),實(shí)現(xiàn)了程序塊的搬移,克服了C6000指令系統(tǒng)的缺陷;對(duì)C6000的C語(yǔ)言運(yùn)行環(huán)境進(jìn)行研究,發(fā)現(xiàn)仿真器進(jìn)行變量初始化的過(guò)程,采用自編程自初始化的方法,確保程序加載后能正常運(yùn)行。?
參考文獻(xiàn)?
1 Texas Instruments.TMS320C6000 CPU and Instruction Set?Reference Guide. 2000?
2 Texas Instruments. TMS320C6000 Peripherals Reference?Guide.2001?
3 Texas Instruments. TMS320C6000 Optimizing C Compiler?User's Guide. 2001?
4 任麗香,馬淑芬,李方慧.TMS320C6000系列DSps的原理與應(yīng)用.北京:電子工業(yè)出版社,2001?
5 趙訓(xùn)威.基于TMS320C6200系列DSP芯片的應(yīng)用與開(kāi)發(fā).北京:人民郵電出版社,2002