DSP常見編譯錯誤_第1頁
DSP常見編譯錯誤_第2頁
DSP常見編譯錯誤_第3頁
DSP常見編譯錯誤_第4頁
DSP常見編譯錯誤_第5頁
已閱讀5頁,還剩22頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

1、1. DSP編程技巧到底有什么好資料?話說專門深入講解這個的資料并不是太多,因為大部分DSP書籍都是講解算法或者寄存器是怎么使用的,那盡量羅列一下(如有遺漏請在評論區(qū)補充),有:(1)DSP C2000程序員高手進階這本書是當年筆者學習DSP的時候看了好幾遍的,講的非常深入、透徹,可惜早就賣光了并且沒有再版。需要的網(wǎng)友可以考慮去圖書館看看,圖書館里最不缺少的就是老版本的書籍了。(2)EEPW牛人業(yè)話我們EEPW首頁的牛人業(yè)話里,已經(jīng)有大量這方面的總結(jié)了,鏈接太多就不一一列舉了,請到(3)官方資料最權(quán)威的當然還是官方資料,特別是TMS320C28x Optimizing C/C+ Co

2、mpiler Users Guide和TMS320C28x Assembly Language Tools Users Guide。不足之處就在于,它們都像教科書,嚴謹有余,活潑不足,特別是初入門的人看起來會比較累。(4)參加一些培訓好的培訓一般都是要付費的,這個要根據(jù)自己的實際情況進行取舍了。2. 答疑解惑哪家強?經(jīng)驗的積累,除了自己努力的自學之外,有時候一些難關(guān)還是得有別人的幫助才行,可能你花3天搞不定的問題,他一看就想起來是什么原因了。如果是企業(yè)客戶,那直接聯(lián)系官方技術(shù)支持,很容易就搞定了?;蛘咭部梢匀ス俜秸搲釂?,然后等待解答。對于廣大網(wǎng)友來說,直接獲得技術(shù)支持可能有一定的難度。我們E

3、EPW的論壇的人氣充足,對問題的響應(yīng)速度也是迅雷不及掩耳的,所以有關(guān)DSP的問題盡可以到前面這兩個無關(guān)具體技術(shù),但是能起到 “源頭”的作用。接下來就是具體的技術(shù)問題了,有幾十個,我們慢慢來看吧。3. 作為入門者,創(chuàng)建一個最基本的工程需要做哪些事情?最簡單的入門方法是從現(xiàn)有的例子上入手,比如購買開發(fā)板的話,一般都會附送十幾到幾十個上手用的例子工程,把它們研究一遍,基本上入門這關(guān)就過了。對于C2000 DSP的學習來說,先到TI網(wǎng)站上搜索ControlSUITE軟件下載安裝,里面的入門視頻、工程例子和所有的文檔資料都是一應(yīng)俱全的。如果你買書籍來入門的話,和教編程的書籍一樣,大部分都還是以“Hell

4、o world”作為第一個程序入手,然后運行程序顯示在調(diào)試窗口中的。4. 一個定點的C28x起始工程最少需要哪些文件和選項?1) 編譯器選項:-v28 -ml -mt -g -pdr w2) 包含main()函數(shù)的一個.c或者.cpp程序3) 實時運行支持庫文件rts2800_ml.lib4) 鏈接文件(.cmd)和頭文件:一個小的入門工程,一般從別的工程里把它們復制過來就好了,比如可以從ControlSUITE軟件的目錄下找到對應(yīng)器件的。5. 一個浮點的C28x起始工程最少需要哪些文件和選項(啟用浮點支持)?1) 編譯器選項:-v28 -float_support=fpu32 -ml -mt

5、 -g -pdr -w2) 包含main()函數(shù)的一個.c或者.cpp程序3) 實時運行支持庫文件rts2800_fpu32.lib4) 鏈接文件(.cmd)和頭文件:一個小的入門工程,一般從別的工程里把它們復制過來就好了,比如可以從ControlSUITE軟件的目錄下找到對應(yīng)器件的。6. 包含CLA和VCU的器件,其入門工程需要哪些額外選項?新器件層次不窮,短短幾年時間,包含控制律加速器(CLA)和VCU加速器(用來執(zhí)行高效 Viterbi、復雜算術(shù)運算,16 位快速傅里葉變換 (FFT) 和 CRC 算法)的器件已經(jīng)有幾十種了,而且像CLA、VCU這些技術(shù)還在快速地升級中,如果要在代碼中用

6、到這些特性,就需要添加-cla_support=cla0和-vcu_support=vcu0這樣的選項。7. 編譯器選項有那么多中,典型的配置有哪些?C28x編譯器的選項非常多,我們用了很長的篇幅來講解它們。作為典型配置的話,對于C28x的CPU來說(通常我們把DSP的架構(gòu)劃分為CPU+外設(shè),更復雜的則還有FPU、CLA、VCU等額外單元),常用的選項如表1所示。注:如果一個選項沒有別名,則代表在使用它的時候直接使用全名,如表1的第二列那樣的形式。8. 含有CLA加速器的CPU必備的編譯器選項?除了問答4、5、7提到的選項之外,CLA CPU對編譯器也有一定的要求,如表2所示。表2

7、CLA CPU必備的編譯器選項9. “大內(nèi)存模型”和“小內(nèi)存模型”的區(qū)別是什么?C28x一般使用大內(nèi)存模型,假設(shè)數(shù)據(jù)可以存放在存儲單元的任何可用空間中。小內(nèi)存模型的提出其實針對的是基于C27x模式CPU的代碼,它默認數(shù)據(jù)是存放在低64k存儲空間范圍內(nèi)的,除非使用far關(guān)鍵字進行特別指明。現(xiàn)在的DSP器件片上存儲空間普遍比較大,顯然使用大內(nèi)存模型更為合理。10. 什么是“統(tǒng)一內(nèi)存模型”?統(tǒng)一內(nèi)存模型“-unified_memory”指在“統(tǒng)一的內(nèi)存模式”下產(chǎn)生代碼。顧名思義,就是把所有的存儲空間定義為一個整體,不管它是片上的SRAM、ROM、OTP還是使用XINTF接口的外部的存儲單元

8、,通常把外設(shè)的寄存器也映射到數(shù)據(jù)存儲空間中。這樣編譯器在編譯時就可以使用PREAD/PWRITE/MAC等指令來處理大部分的內(nèi)存復制memcpy調(diào)用和結(jié)構(gòu)體的分配。11. 實時運行庫RTS的作用是什么?在計算機程序設(shè)計領(lǐng)域,運行時庫是一種被編譯器用來實現(xiàn)編程語言內(nèi)置函數(shù),以提供該語言程序運行時(執(zhí)行)支持的一種特殊的計算機程序庫。這種庫一般包括基本的輸入輸出或是內(nèi)存管理等支持。在DSP的編程中,它們的作用是用來建立C/C+代碼運行的環(huán)境,主要包括以下幾個方面:1) ANSI/ISO C/C+標準庫。2) C的輸入輸出I/O庫。3) 為主機的操作系統(tǒng)提供底層的I/O支持。4) DSP的

9、啟動程序_c_int00(可參考12. RTS中函數(shù)的描述從哪里可以找到?在問答11中,RTS包含了四大類內(nèi)容。前面兩者因為是標準C/C+的內(nèi)容,并沒有在TI的文檔中給出額外的說明;此外,C+ STL庫和它們的API的使用也沒有TI官方文檔。此時我們可以參考標準C/C+的書籍、資料、網(wǎng)頁等。如果希望最權(quán)威的參考,可以查閱TI提供的參考鏈接:1) The Standard C+ Library: A Tutorial and Reference, Nicolai M. Josuttis, Addison-Wesley, ISBN 0-201-37926-02) The C+ Programmin

10、g Language (Third or Special Editions), Bjarne Stroustrup, Addison-Wesley, ISBN 0-201-88954-4 or 0-201-70073-5.3) C+ online reference at 4) C代碼的靜態(tài)檢查工具/當然,作為DSP的開發(fā)人員,高效保質(zhì)地完成代碼工作才是最重要,上面那些書籍、鏈接,請慢慢研究吧。14. 從哪里可以找到RTS庫文件?通常情況下,隨CCS軟件安裝而提供的RTS庫文件都位于CCS安裝目錄中,編譯器Codegen對應(yīng)的子目錄中。例如,在新版本的C

11、CS6.x中,C28x的編譯器位于CCS安裝目錄下面的toolscompilerc2000_6.2.5lib中(根據(jù)編譯器版本的不同,倒數(shù)第二個目錄名字會有相應(yīng)的變化)。在老版本的CCS中,RTS庫文件被默認安裝到操作系統(tǒng)的程序目錄中,例如C:Program FilesTexas InstrumentsC2000 Code Generation Tools 5.2.4。對于其它一些特殊的庫,例如FPU快速運行支持庫FastRTS,則在下載安裝了FastRTS安裝包之后,位于其安裝目錄之下的lib文件夾中,例如FPUfastRTSV100librts2800_fpu32_fast_supplem

12、ent.lib。如果安裝了controlSuite軟件,則可以通過它內(nèi)置的說明或者搜索功能找到對應(yīng)的庫文件。15. RTS庫那么多,我們應(yīng)該使用哪一個?隨著器件類型、特性的不斷發(fā)展,現(xiàn)在在CCS安裝目錄下叫RTSxxx.lib的文件已經(jīng)非常非常多了,那么到底哪些是適合我們使用的呢?對于C28x器件,總結(jié)如表3所示。表3 C28x DSP使用的實時運行支持庫16. 已經(jīng)啟用了rts2800_fpu32_eh.lib ,為什么還要用rts2800_fpu32_fast_supplement.lib?在含有FPU的器件上,如果在不啟用-float_support=fpu32編譯器選項的情況下使用浮點

13、數(shù)編程,那么它的運算還是CPU來執(zhí)行的,執(zhí)行效率就和從定點CPU上直接使用浮點運行進行編程一樣低;啟用了-float_support=fpu32編譯器選項之后,浮點數(shù)的加法、減法、乘法等操作則有FPU來完成,執(zhí)行效率自然要高出很多。使用rts2800_fpu32_fast_supplement.lib庫的目的,則是為了調(diào)用DSP的ROM中的數(shù)學表快速計算一些數(shù)學函數(shù),包括atan、atan2、cos、division、isqrt、sin、sincos、sqrt等。如果不使用rts2800_fpu32_fast_supplement.lib庫來完成這些數(shù)學運算,則編譯器默認情況下是使用標準C/C

14、+數(shù)學庫里的函數(shù)來完成這些運算的,效率自然不能和查找ROM中的數(shù)學表一樣迅速。那么CCS為什么不附帶安裝FastRTS庫呢?這可能和在定點DSP的使用中,IQmath庫也不是附帶安裝是通用的道理吧,其它相類似的,一些信號處理函數(shù)庫,例如FFT、IFFT等也不是CCS安裝的時候附帶的,需要自己去下載安裝支持程序。17. 如何把RTS庫添加到工程文件中?如果使用命令行腳本的方式添加庫文件,則使用-l <庫文件名>來添加即可。在圖形化界面下,填加RTS庫文件的選項在不同版本的CCS中是不一樣的,在此把它們一一列出。在CCS6.x和5.x版本下:在工程管理器中的工程名上點擊右鍵,選擇&qu

15、ot;properties",然后切換到如下視圖。在CCS4.x版本下:在CCS3.3版本以及更低的版本下:針對比CCS3.3更古老的版本:如果不習慣使用Eclipse樣式的開發(fā)環(huán)境,或者某些仿真器不兼容CCS4.x以及以上版本,或者你還在使用最古老的TMS320VC33這樣的芯片,否則至少應(yīng)該升級到CCS3.3這樣的版本了。18. 在對庫文件進行修改,或者使用不同版本的編譯器時,如何重新編譯庫文件?在編譯器版本不低于6.0.2的情況下,我們可以直接使用編譯器提供的工具來重新編譯RTS庫文件,即Mklib程序。如需使用此工具,請參考它的幫助說明文檔。在編譯器版本低于6.0.2的情況下

16、,我們需要進入編譯器codegen的庫文件目錄中,找到rtssrc.zip這個文件并解壓,然后根據(jù)其中rtssrc_zip_README.txt里面描述的步驟進行庫文件的重新編譯。22. 除了使用編譯器的優(yōu)化選項之外,還可以使用什么方法提高程序的性能?編譯器的優(yōu)化選項,只能在代碼滿足眾多選項的要求時,才能得到較好的優(yōu)化效果。在我們編程的時候,首先要做到心里有數(shù),盡可能使用一些高效的編程方式,例如使用右移操作代替除以2的倍數(shù)的操作,可以大幅度地減少代碼運行時間等。這些技巧很多是與C/C+的熟練使用所相關(guān)的。此外,根據(jù)器件的特點,例如是否包含F(xiàn)PU、CLA等,把特定的代碼放在不同的區(qū)域執(zhí)行,也能起

17、到提高程序性能的效果;根據(jù)代碼對性能的要求,把它們運行在不同的位置,例如RAM快于Flash,F(xiàn)lash又快于XINTF等;在器件包含數(shù)學表的情況下,使用內(nèi)建的數(shù)序函數(shù)庫,而不是標準的C數(shù)學庫等。在此我們可以給出一些提示:1) 代碼運行在Flash中一定要使能預讀緩沖區(qū),并配置適當?shù)牡却隣顟B(tài)。一般在各個器件的頭文件與外設(shè)示例包里都有對應(yīng)的例子。2) 把時間關(guān)鍵的代碼和/常數(shù)數(shù)組等從Flash復制到RAM中運行在RAM中運行時,最大的指令周期比Flash中運行時要高,其執(zhí)行速度也要快出不少,所以可以根據(jù)需要把實時性能要求較高的程序復制到RAM中運行,具體的方法和實例可以參考 an Applica

18、tion from Internal Flash Memory on the TMS320F28xxx DSP。3) 評估代碼和數(shù)據(jù)的存儲地址的劃分,并根據(jù)需要修改鏈接文件i. 如果某段代碼和它所讀取的數(shù)據(jù)位于同一個物理內(nèi)存區(qū)間中,則因為它們使用相同的地址總線等資源,無法同時訪問,造成了資源的沖突,這會降低程序的性能,所以最好把代碼和數(shù)據(jù)保存在不同的內(nèi)存區(qū)間中。ii. 等待狀態(tài)(wait)會降低系統(tǒng)性能,因為CPU會執(zhí)行過多的無用狀態(tài)且在此期間無法處理別的任務(wù):當CPU讀取或者訪問存儲單元或者外設(shè)的時候,該存儲器或者外設(shè)有可能在CPU默認分配的時間內(nèi)無法完成數(shù)據(jù)的傳輸,此時就需要在C

19、PU的ready信號中插入等待狀態(tài),直到數(shù)據(jù)傳輸完成才能讓CPU繼續(xù)執(zhí)行別的任務(wù)。C28x器件上,大部分的SARAM都是零等待的,但是在C2833x器件中,有一些模塊卻不是,例如某些Flash/OTP的訪問等。iii. 如果在代碼中大量使用兩個數(shù)據(jù)緩沖區(qū),則把兩個數(shù)據(jù)緩沖區(qū)存放在不同的RAM模塊中有可能會提高代碼的性能,因為大量讀寫同一塊RAM區(qū)間會產(chǎn)生更多的流水線停滯,造成性能的降低。4) 使用編譯器中的統(tǒng)一內(nèi)存模式-unified_memory此模式把所有的存儲空間定義為一個整體,這樣編譯器在編譯時就可以使用RPT與PREAD指令來處理大部分的內(nèi)存復制調(diào)用和結(jié)構(gòu)體的分配。5) 使用Flas

20、h和外部存儲器如果代碼需要在Flash或外部存儲器中運行,則在編譯時開啟-me選項。它將禁止編譯器使用快速分支指令(SBF/BF),轉(zhuǎn)而使用普通的跳轉(zhuǎn)指令(SB/B)。BF指令在默認情況下是被啟用的,它能夠?qū)⑻D(zhuǎn)分支使用的指令周期從7個降低到4個,在零等待狀態(tài)的SAM中執(zhí)行時,快速分支指令的預讀特性使得它較為高效,但是在非零等待的存儲器中執(zhí)行時,SBF/BF的預讀反而造成了性能的下降,此時需要人為地對預讀和等待進行規(guī)劃。6) 使用內(nèi)聯(lián)函數(shù)在編譯時開啟內(nèi)聯(lián)函數(shù)功能,則編譯器會自動把多次調(diào)用的函數(shù)進行內(nèi)聯(lián),大大減少函數(shù)調(diào)用和返回操作所帶來的開銷。當然,根據(jù)“空間換時間”的原則,開啟內(nèi)聯(lián)會增加一定的

21、代碼尺寸。23. 為什么一個char類型的數(shù)組中,每個元素都占用了16bit的地址?這是因為在C28x上,字節(jié)(byte)和字(word)是等價的:也就是說它們都是16位或者說16比特(bit)寬的,即sizeof(int) = sizeof(char) = 1。24. sizeof(int) = sizeof(char) = 1貌似與ANSI標準是相違背的?在ANSI/ISO的C定義中,sizeof操作符以字節(jié)形式給出了其操作數(shù)的存儲大小。ANSI/ISO還規(guī)定,sizeof操作符取char的值時,返回值為1。因為TMS320C28x中的字節(jié)是16位的,char也是16位的,所以sizeof

22、的結(jié)果符合ANSI標準的。作為補充,選16位,而不是8位或者別的什么位數(shù)作為char的寬度,主要是為了統(tǒng)一尋址的便利,雖然在某種程度上說這增加了一定的存儲器空間占用,或者說浪費了一些空間,因為它們在存儲空間中制造了一些空洞。25. 如果char是16位的,那么如何高效地訪問8位的值?可以使用_byte()和_mov_byte()這樣的編譯器內(nèi)聯(lián)函數(shù)。請參考26. 編譯結(jié)果提示undefined symbols,名字中包含$符號,怎么破?名字中帶美元符號的函數(shù),例如FS$MPY, FS$TOL等,都是RTS庫里的內(nèi)置函數(shù),編譯器提示我們這些函數(shù)未定義,表明我們沒有把對應(yīng)的RTS庫給加入到工程中,

23、例如MPY是數(shù)學函數(shù),需要添加相關(guān)的數(shù)學庫,例如FPU數(shù)學庫等。27. 鏈接器提示“_c_int00 is not defined”,怎么破?在 rts2800_ml.lib、rts2800_fpu32.lib等待,這些RTS庫的具體區(qū)別在答疑解惑的第15條中已經(jīng)有對比了(28. 新版本的編譯器中,printf()/sprintf()函數(shù)貌似要使用更多的棧?這是因為printf()函數(shù)被重新修改了,以支持多個級別的printf格式說明符支持和修正,以減少代碼大小和總內(nèi)存大小(包括bss)。printf由sprintf()間接調(diào)用,它使用一個400個元素的大小的局部數(shù)組。為了保存一致性,prin

24、tf()一直都在使用這么大的內(nèi)存空間,而編譯器也在盡量避免使用malloc()進行內(nèi)存分配。與老版本所不同的的是,此數(shù)組以前是靜態(tài)的,而現(xiàn)在它被保存在.bss,而不是棧中;這樣做的目的是,如果用戶使用C I/O,則他們往往會在使用合適尺寸的棧的同時盡量減小.bss的使用。29. 如果不需要printf()/sprintf()的全部特性,怎么樣才能減小代碼體積?初學者往往使用printf打印“Hello World”這樣的方式來完成第一個DSP編程的程序,這種方法雖然是非常直觀明了的,感覺起來功能也是非常簡單的,但是一編譯結(jié)果發(fā)現(xiàn)提示棧的空間不夠,或者有“program will not fit

25、 into available memory”之類的錯誤。這是因為標準的printf()/sprintf()提供了非常多的特性支持,造成了在DSP上實現(xiàn)時,產(chǎn)生的代碼尺寸非常大。此時我們可以根據(jù)需要調(diào)整不同級別的格式格式限定符,例如通過鏈接器的選項,我們可以指定-printf_support=full, minimal或者nofloat, full為默認參數(shù),表示支持所有的格式;nofloat不支持對浮點類型的數(shù)據(jù)的輸入/打印,包括%a,%A, %f, %F,%g,%G,%e和%E,支持其它的字符、定點格式等;minimal:對數(shù)據(jù)格式的最小支持,只包含了不指定數(shù)據(jù)寬度和精度標志的整形、字符型

26、或者字符串,即只支持%,%d,%o,%c,%s和%x格式。其詳細含義可參考此外,如果不去指定鏈接器選項,我們也可以修改printf函數(shù)默認對應(yīng)的源程序_printfi.c來實現(xiàn)類似的效果,它的路徑一般在編譯器的庫函數(shù)目錄下,例如ticcsv6toolscompilerc2000_6.2.5libsrc。在此路徑下,有3個printf函數(shù)對應(yīng)的c程序,它們與鏈接器選項的對應(yīng)關(guān)系如下表所示。由此我們也可以看出,支持全部格式的printf的源程序的大小,達到了最小格式支持下源程序大小的23倍還要多。30. CCS編譯器是否支持任何工業(yè)標準?1) 所有的TI DSP支持的C語言標準:C89

27、(ISO/IEC 9899:1990,或者叫NSI X3.159-1989)C99 (ISO/IEC 9899:1999). 不完全支持。2) 不支持的C語言標準:C11 (ISO/IEC 9899:2011)3) 支持的C+標準:C+98 (ISO/IEC 14882:1998)C+03 (本質(zhì)是C+98的bug修復)4) 不支持的C+標準:C+ TR1C+11 (ISO/IEC 14882:2011)5) IEEE-754 (ISO/IEC/IEEE 60559)標準:TI的ARM和DSP的C/C+編譯器支持32位和64位的二進制浮點數(shù)運算,能夠支持IEEE754標準中大部分特性。6) M

28、ISRA-CMISRA C是由汽車產(chǎn)業(yè)軟件可靠性協(xié)會(MISRA,motor industry software reliability association)提出的C語言開發(fā)標準,在控制有關(guān)的代碼中是非常有用的標準,具體使用方法可參考7) 其它標準在工業(yè)領(lǐng)域中,safety安全特性在一些應(yīng)用場合中已經(jīng)是要求必須具備的功能了,相關(guān)的標準包括IEC61508、TÜV認證等。目前已經(jīng)有一部分包含硬件safety特性的DSP器件了;如果使用軟件來實現(xiàn)這些特性,則目前還需要我們自己來編寫代碼以支持這樣的特征。31. CCS編譯器對GCC擴展的支持如何?GNU編譯器結(jié)合GCC支持許多標準AN

29、SI/ISO C/C+所不支持的特性。在開源應(yīng)用和Linux等開發(fā)中,GCC的編譯器gcc和g+等都被廣泛使用。所以為了保證對GCC工具所開發(fā)的代碼的兼容性,TI的編譯器也支持某些GCC的擴展特性。目前支持的一些特性基本都包含在GCC4.3中,可查看:/onlinedocs/gcc-4.3.6/gcc/C-Extensions.html。32. 如何了解有關(guān)編譯/代碼產(chǎn)生工具的已知問題,并獲得最新進展?老外喜歡用IBM的ClearQuest系統(tǒng)來報告bug并分享解決方案,我們可以使用TI提供的開放鏈接避開老舊的“傳統(tǒng)”bug的最好辦法當然是定期升級編譯器和開發(fā)

30、環(huán)境了。通過配置,新版本的CCS在啟動后會自動檢測升級并自動升級,這也簡化了我們對開發(fā)環(huán)境的維護工作。33. 鏈接文件中包含那么多個段,有什么快速識別的方法?把下面這個例子記牢就好了:/ Global variables x & y => .ebss/ Initial values 2 & 7 => .cinit/int x = 2;int y = 7;void main()long z; / Local variable => .stackz = x + y; / Code => .text34. 為什么我們需要鏈接文件.cmd?為何編譯器不能自動分配

31、存儲空間并進行內(nèi)存管理?在操作系統(tǒng)存在的情況下,這些工作確實不需要我們花費太多的心思。但是在嵌入式的DSP處理中,這樣做的主要原因是處理能力和存儲空間是十分有限的,必須要我們進行一定的介入,例如我們需要考慮的因素包括:1) 運行速度:在RAM中比在Flash中快,在Flash中又比在外部存儲器(使用XINTF)中快。2) 代碼是否需要存儲在非易失的存儲器中(例如Flash)?3) 任務(wù)是否是時間關(guān)鍵的?例如需要把某個時間關(guān)鍵的ISR被保存在Flash中,然后運行時復制到RAM里。4) 一些RAM可被DMA模塊所訪問,而另一些則不行。5) 使用單獨的物理RAM模塊來避免資源的沖突。例如,在C20

32、00 DSP中,RAM模塊都是在單個機器周期內(nèi)只能訪問一次的SARAM(Single-access RAM)。6) 資源是否位于外部存儲器中?7) 代碼是否需要保存在包含緩存或者預讀的存儲器中以提高性能?在C2000DSP中,我們幾乎見不到緩存或者預讀的概念,它們一般出現(xiàn)在包括ARM處理器的器件中。8) 存儲器在程序空間、數(shù)據(jù)空間中是否具有等待狀態(tài)?9) 是否有需要被代碼安全模塊CSM所保護的代碼?CSM并不能保護所有的代碼空間。以上這些因素,在我們編程時也是需要特別關(guān)注,甚至是較為頭疼的事情,顯然讓編輯器去自動實現(xiàn)它們,在目前階段是不可能的(除非編譯器的算法有一天能實現(xiàn)一定程度的人工智能)。

33、所以在現(xiàn)階段,我們需要使用鏈接器命令文件cmd去描述每個段所需要使用的內(nèi)存情況。如果我們沒有把某一個特殊的或者自定義的段給指定到特定的存儲空間中,則此時鏈接器會自動把它給分配到一個可用的存儲空間里,這有可能會影響到程序的執(zhí)行效果。所以我們要開啟編譯器的-w選項,這樣在在未定義的輸出段被創(chuàng)建時,開發(fā)環(huán)境的控制臺窗口中會產(chǎn)生相關(guān)的警告信息。35. 雖然可用的存儲空間看起來比section的長度要大,但是鏈接器為何提示“placement fails for object”?這種情況一般是因為段的空間的分配是并不是我們想象中的連續(xù)的一個緊挨一個,而是被編譯器給“分塊”管理了。在內(nèi)存地址分配時,一個段

34、需要完全適配到頁(page)中,或者從頁的邊界開始連續(xù)分配;為了滿足這個要求,段在分配到頁中時,可能無法完全利用某些頁,導致內(nèi)存地址中產(chǎn)生了間隙(hole),使得實際所需要的內(nèi)存空間超過了根據(jù)變量大小計算出來的理論值。編譯器這樣做的目的是為了優(yōu)化數(shù)據(jù)頁(DP)寄存器的加載,達到減小代碼尺寸和優(yōu)化程序性能的目的。例如,針對一個數(shù)組,如果數(shù)組的長度小于64字(words),則編譯器僅需安全地加載DP一次就可以訪問數(shù)組的全部元素;如果數(shù)組長度大于64字,則在訪問每64字的數(shù)組元素時,編譯器僅需加載一次DP,當然如果訪問多個64字的數(shù)組元素則仍需要多次加載DP。舉例說明:在cmd里定義:RAMM1 :

35、 origin = 0x000400, length = 0x000400 /* on-chip RAM block M1 */commbuf : > RAMM1 PAGE = 1在main.c里定義以下幾個變量#pragma DATA_SECTION(sendT, "commbuf")Uint16 sendT260;#pragma DATA_SECTION(receT, "commbuf")Uint16 receT260;#pragma DATA_SECTION(CntPPR, "commbuf")Uint32 CntPPR2

36、50;表面上共需260+260+250*2=1020,commbuf正好放得下.但ccs提示空間不夠:(run placement fails for object "commbuf", size 0x474 (page 1).Available ranges: RAMM1 size: 0x400 unused: 0x400 max hole: 0x400)產(chǎn)生錯誤的原因是根據(jù)DP加載的原則,page被劃分為64word的小單元,而數(shù)組被存儲在連續(xù)的、整塊的單元上,未使用到的空間不會再分配給其它數(shù)組或者變量使用。所以16位260長度的數(shù)組實際占用了64*5=320 (64*

37、4=256<260),32位500的長度實際占用了64*8=512,占用的總長度為:320*2+512=1152=0x480。按照CCS的提示,commbuf占用空間是320*2+500=1140=0x474,但是事實上32位數(shù)組占據(jù)的最后那個page已經(jīng)無法被別的變量使用了,所以如果還有新的變量出現(xiàn)的話,會提示RAMM1塊缺少的地址更多。根據(jù)我們的需要,可以在每次之間內(nèi)存讀取操作之前都加載DP,這樣就可以禁用上面的“分塊”管理特性了。這樣做雖然可以減小內(nèi)存地址空間中的“間隙”,但是每一次訪問內(nèi)存都需要加載DP,反而大大地增加了代碼的尺寸,實在是得不償失(看起來很少有人會這么做)。我們可

38、以通過啟用編譯器的-disable_dp_load_opt,或者叫-md選項來實現(xiàn)這一方法。確認某個段是否被編譯器給分塊管理的方法就是使用.bss和.usect指令,具體內(nèi)容請參考36. 鏈接器提示“placement fails for object '.text'”,我們?nèi)绾螢?text分配更多的內(nèi)存?.text段中包含包含所有可執(zhí)行的代碼,以及編譯器編譯產(chǎn)生的常量。如果我們的代碼比較大,超過了cmd文件中默認分配的空間,則.text無法適配到內(nèi)存空間中,就會產(chǎn)生上面的錯誤。通常有三種方法可以來為其分配更多的空間。方法一:修改cmd這個我們已經(jīng)提到過,請參考方法二:分割.t

39、ext,把它平均分配到多個內(nèi)存區(qū)域中這個方法比較直觀,前提是幾個內(nèi)存區(qū)域的總長度要滿足要求。例如:.text : >> FLASHA | FLASHC | FLASHD, PAGE = 0方法三:完整分割法這個名字有點古怪,它本質(zhì)仍然是把.text分割,目標區(qū)域也可以有多個,但是當?shù)谝粋€區(qū)域就滿足要求時,則只把它分配到第一個區(qū)域中,剩余的目前區(qū)域?qū)嶋H上未被使用到。在實際編程實現(xiàn)時,這些方法仍然存在一定的限制,包括:1. 在包含控制律加速器CLA 的Piccolo器件中,只有特定的內(nèi)存區(qū)域可被CLA所使用。2. 在含有DMA的器件中,并不是所有的內(nèi)存都可被DMA所訪問。3. 一般情況

40、下,SRAM都是單個機器周期內(nèi)只能訪問一次,但是0等待狀態(tài)的。但在一些器件中,程序內(nèi)存控制是包含等待狀態(tài)的,例如在某些2833x器件中,DMA可訪問的數(shù)據(jù)空間是0等待狀態(tài)的,但是程序控制是1等待狀態(tài)的。這些SRAM空間更適合純數(shù)據(jù)訪問類型的使用。37. 在cmd文件中,可以把連續(xù)的Flash模塊組合為一個整體的區(qū)間嗎?答案是可以的。在Flash的燒寫中,可以在同一時間被燒寫的Flash的最小長度被稱為扇區(qū)(sector),所以通過把我們的代碼進行分區(qū)燒寫,就可以把它們對齊到扇區(qū)。Flash模塊結(jié)合的方法一:直接合并法以把兩個Flash扇區(qū)組和為一個段為例:合并前,兩個扇區(qū)的定義是:MEMORY

41、/ Individual sectors E and F called out in the MEMORY description/.FLASHF : origin = 0x310000, length = 0x008000 /* on-chip FLASH */FLASHE : origin = 0x318000, length = 0x008000 /* on-chip FLASH */.合并之后的Flash區(qū)間為:MEMORY/ Sectors E and F merged into one in the MEMORY description/.FLASH : origin = 0x31

42、0000, length = 0x010000 /* on-chip FLASH F & FLASH E */.方法二:反其道行之,把段分配到多個Flash模塊中,與問答36的方法二是一致的,例如:SECTIONS.text: *(.text) >> FLASHE| FLASHH38. 在cmd文件中,可以把相鄰的SARAM模塊組合為一個整體的區(qū)間嗎?答案是可以的,方法與Flash組合的方法一樣。雖然這樣做是完全沒有問題的,但需要牢記SARAM模塊都是單個機器周期內(nèi)只能訪問一次的,所以為了優(yōu)化程序的性能,最好把代碼給分區(qū)到不同的物理SARAM模塊中,這樣可以減少大量讀/寫操

43、作中的資源沖突。39. 對于DSP/BIOS的工程,如何了解鏈接的信息?DSP/BIOS 的配置工具生成一個cmd文件,規(guī)定如何連接所有 DSP/BIOS 生成的程序段,并且默認鏈接至所有 C/C+ 語言編譯程序生成的程序段。 當從 RAM 運行程序時,可能只需要這一個cmd文件就夠了。但在當從Flash中執(zhí)行時,很有可能需要生成且連接一個或多個自定義的程序段。此外,任何配置片載Flash控制寄存器(例如,F(xiàn)lash等待狀態(tài))的代碼不能從Flash執(zhí)行。我們也許需要從 RAM(而非Flash)中運行特定時間關(guān)鍵函數(shù)來大幅提升性能。 必須創(chuàng)建一個自定義cmd來處理這些我們定義的程序段。

44、可以參考Running an Application from Internal Flash Memory on the TMS320F28xx DSP這個文檔,其示例代碼在需要注意的是,這些文檔和程序與新版本的CCS中所包含SYS/BIOS并不是完全兼容的。此外,如果我們想使用第三方的操作系統(tǒng),例如VxWorks、us/OS、INTEGRITY等,則要根據(jù)這些RTOS的特點進行內(nèi)存的分配與管理。43. Error: option -include_path is missing its parameter 'dir',如何解決?本文引用地址:這個錯誤的發(fā)生往往是編譯器沒有能夠

45、正確地解析包含變量或者宏的頭文件的路徑。解決方法可以利用上圖中的Variables選項卡,點擊Add,把自定義的變量添加進去,此時CCS會檢查該編譯器變量是否符合標準。44. Error: unresolved symbols remain,如何解決?出現(xiàn)這個錯誤說明鏈接器在符號表中找不到相關(guān)的符號定義。在這個例子中,源程序example中使用了函數(shù)myfunc,但是在編譯生成的所有目標文件(.obj)或者所有的庫文件(.lib)中都找不到這個函數(shù)。解決的方法自然是找到這個函數(shù)從哪里來的?然后把它的源添加到工程中。在使用Stellarisware或者ControlSuite套件中的例子來創(chuàng)建我

46、們自己的工程時,如果忘了使用library選項把庫文件添加到鏈接器的路徑里,則經(jīng)常會出現(xiàn)此錯誤。這些庫文件包括:Stellarisware/Tivaware中的driverlib, grlib, usblib,ControlSuite中的driverlib, IQMath等等。那么接下來的步驟就是添加對應(yīng)的庫文件了。最直接的方法是在工程屬性里選擇,如下圖所示:此外,如果在C+代碼中引用C代碼的頭文件,如果這個頭文件是自定義的(而不是系統(tǒng)提供的),則最好在頭文件中添加extern "C" .以方便在C+代碼中方便使用#include來引用該頭文件。那么問題又來了:C編譯器不認

47、識extern "C"怎么辦?此時要使用#ifdef這樣的宏來在C中屏蔽它們,即:#ifdef _cplusplusextern "C" #endif45. Error: placement fails for section "xxx",如何解決?這個錯誤說明我們定義的段超過了指定存儲器區(qū)間的大小??梢詮囊韵聨讉€方面來解決此問題:1. 檢查棧和堆的長度,看看是不是給它們配置了過大的值,導致了在RAM中保存不下去?然后嘗試減小它們的長度。2. 嘗試使能或者增加編譯器的優(yōu)化級別,未經(jīng)優(yōu)化的代碼往往需要更多的存儲空間。3. 如果使用了I/

48、O代碼,則它們會顯著增加代碼尺寸,例如在很多小容量的器件上,一個printf()函數(shù)就能超過存儲容量了,此時可以使用printf()的最小格式,請參考4. 可以考慮修改cmd文件,以增加某個段所使用的存儲空間的長度;代價是別的存儲空間的長度會相應(yīng)減小,有可能導致新的placement fails 這樣的錯誤產(chǎn)生。具體可參考5. 嘗試精簡/優(yōu)化代碼,在不影響功能的情況下,使用一些編程技巧來減小代碼尺寸。例如,我們可以使用“空間換時間”,或者“時間換空間”的方法,在代碼尺寸和執(zhí)行速度上做一些折衷。比如對于一個滑動傅立葉變換(sDFT),我們既可以使用很大的數(shù)組來保存滑動值, 從而實現(xiàn)很高的運算速度

49、;也可以減少運算速度,每個周期只使用幾個點來完成計算,這樣可以極大地減小存儲空間的占用。6. 不到萬不得已,不要去考慮更換芯片。但是如果在產(chǎn)品開發(fā)的評估階段,存儲空間就已經(jīng)捉襟見肘了,則還是要提早考慮升級芯片的,不然以后再增加新的功能,或者哪怕是僅僅修正了一個小的bug,有可能就徹底放不進去了。46. Tag_Memory_Model attribute value of "1" that is different than one previously seen ("2"); combining incompatible files,是神馬意思?這個錯

50、誤表明鏈接器所鏈接的目標文件中存在不同的內(nèi)存模式,比如說有的目標文件使用了大內(nèi)存模式,而有的使用的是小內(nèi)存模式。修改的方法則是讓所有的文件在鏈接時都使用相同的內(nèi)存模式。事實上這種錯誤出現(xiàn)的場合并不算太多,主要出現(xiàn)在工程中引用了別人提供的某些obj文件或者庫文件的時候。在C2000上,新建工程的時候推薦大家統(tǒng)統(tǒng)使用大內(nèi)存模式(-ml)選項。47. Error: file grlib.lib" was built without VFP coprocessor support while a previously seen file was; combining incompatible

51、 files,是神馬意思?這個錯誤與上面那個錯誤的原因是類似的,表明鏈接器所鏈接的目標文件中存在不同的浮點支持模式。修改方法則是讓所有的目標文件和庫文件使用相同的浮點支持-float_support選項。48. 為什么編譯的時候總是提示W(wǎng)arning: creating output section "xxx" without a SECTIONS specification?在使用默認的cmd文件進行編程,而工程中有使用了某些cmd中未明確定義的段的時候,就會出現(xiàn)這個警告。因為沒有在cmd中定義這個段,所以鏈接器會使用默認的算法來創(chuàng)建和分配輸出段“XXX”;這樣雖然能保證

52、程序的工作,卻不被建議這樣做,因為它不利于內(nèi)存地址空間的有效分配和管理。通常來說,最好不要有任何的鏈接器警告,以消除程序運行時潛在的bug。49. 莫名其妙的gmake: Access is denied。在編譯程序的時候,編譯器會生成一系列的中間文件,包括obj、lib、asm等等,這個過程被一些帶有主動防御系統(tǒng)的殺毒軟件和安全軟件當作危險行為,因此就被禁止掉了,導致編譯失敗,如下圖所示:所以在編譯程序的時候,最好禁用安全軟件,不然即使是安全軟件沒有直接阻止編譯,也會跳出各種各樣的詢問信息,不勝其擾。50. Type 'xyz' or Symbol 'abc'

53、 could not be resolved。這些錯誤一般是由Eclipse CDT (C/C+開發(fā)工具)錯報出的,而不是由TI本身的編譯器所給出的。目前的解決方法是:從CCSv4的工程升級到CCSv5或者更高版本的時候,如果選擇的是project-導入工程,一般會有一定的兼容性問題,可能會產(chǎn)生這樣的錯誤。解決方案則是創(chuàng)建一個新的工作區(qū),然后把所有的源程序、庫文件、cmd文件等導入到新的工程中,重新配置工程選項,然后再編譯?;蛘吒纱嗪雎訡DT的語法錯誤,方法是在CCS中點擊Window->Preferences->General->Editors->Text Edito

54、rs->Annotations, 選擇C/C+ Indexer Markers,然后清除掉所有的選擇。51. Warning: build attribute vendor section TI missing in " : compatibility cannot be determined。是什么屬性丟失了?出現(xiàn)這個問題,說明使用的庫文件是由一個老版本的編譯/鏈接工具所創(chuàng)建的,在使用新版本的工具進行編譯/鏈接時,這個老的庫文件缺失了某些屬性,導致了這個警告的產(chǎn)生。在C2000 DSP的開發(fā)中,有幾個場合特別容易出現(xiàn)此警告:² 在新的編譯環(huán)境中,使用了一個老版本的IQmath庫文件。² 在測試時,使用了老版本的編譯器生成的Flash API。² 在使用高分

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論