DSP編程技巧之30---答疑解惑哪家強之(5)
答疑解惑哪家強?當屬我們EEPW最強。。。接下來(lái)繼續我們的答疑解惑。
本文引用地址:http://dyxdggzs.com/article/266820.htm29. 如果不需要printf()/sprintf()的全部特性,怎么樣才能減小代碼體積?
初學(xué)者往往使用printf打印“Hello World”這樣的方式來(lái)完成第一個(gè)DSP編程的程序,這種方法雖然是非常直觀(guān)明了的,感覺(jué)起來(lái)功能也是非常簡(jiǎn)單的,但是一編譯結果發(fā)現提示棧的空間不夠,或者有“program will not fit into available memory”之類(lèi)的錯誤。這是因為標準的printf()/sprintf()提供了非常多的特性支持,造成了在DSP上實(shí)現時(shí),產(chǎn)生的代碼尺寸非常大。
此時(shí)我們可以根據需要調整不同級別的格式格式限定符,例如通過(guò)鏈接器的選項,我們可以指定--printf_support=full, minimal或者nofloat, full為默認參數,表示支持所有的格式;nofloat不支持對浮點(diǎn)類(lèi)型的數據的輸入/打印,包括%a,%A, %f, %F,%g,%G,%e和%E,支持其它的字符、定點(diǎn)格式等;minimal:對數據格式的最小支持,只包含了不指定數據寬度和精度標志的整形、字符型或者字符串,即只支持%%,%d,%o,%c,%s和%x格式。其詳細含義可參考http://dyxdggzs.com/article/236048.htm。需要注意的是,如果--printf_support使用了不支持的格式,鏈接器并不能給出特定的實(shí)時(shí)運行庫的錯誤提示,在使用時(shí)要仔細檢查。
此外,如果不去指定鏈接器選項,我們也可以修改printf函數默認對應的源程序_printfi.c來(lái)實(shí)現類(lèi)似的效果,它的路徑一般在編譯器的庫函數目錄下,例如ticcsv6toolscompilerc2000_6.2.5libsrc。在此路徑下,有3個(gè)printf函數對應的c程序,它們與鏈接器選項的對應關(guān)系如下表所示。
由此我們也可以看出,支持全部格式的printf的源程序的大小,達到了最小格式支持下源程序大小的23倍還要多。
30. CCS編譯器是否支持任何工業(yè)標準?
1) 所有的TI DSP支持的C語(yǔ)言標準:
C89 (ISO/IEC 9899:1990,或者叫NSI X3.159-1989)
C99 (ISO/IEC 9899:1999). 不完全支持。
2) 不支持的C語(yǔ)言標準:
C11 (ISO/IEC 9899:2011)
3) 支持的C++標準:
C++98 (ISO/IEC 14882:1998)
C++03 (本質(zhì)是C++98的bug修復)
4) 不支持的C++標準:
C++ TR1
C++11 (ISO/IEC 14882:2011)
5) IEEE-754 (ISO/IEC/IEEE 60559)標準:
TI的ARM和DSP的C/C++編譯器支持32位和64位的二進(jìn)制浮點(diǎn)數運算,能夠支持IEEE754標準中大部分特性。
6) MISRA-C
MISRA C是由汽車(chē)產(chǎn)業(yè)軟件可靠性協(xié)會(huì )(MISRA,motor industry software reliability association)提出的C語(yǔ)言開(kāi)發(fā)標準,在控制有關(guān)的代碼中是非常有用的標準,具體使用方法可參考http://dyxdggzs.com/article/247057.htm。
7) 其它標準
在工業(yè)領(lǐng)域中,safety安全特性在一些應用場(chǎng)合中已經(jīng)是要求必須具備的功能了,相關(guān)的標準包括IEC61508、TÜV認證等。目前已經(jīng)有一部分包含硬件safety特性的DSP器件了;如果使用軟件來(lái)實(shí)現這些特性,則目前還需要我們自己來(lái)編寫(xiě)代碼以支持這樣的特征。
31. CCS編譯器對GCC擴展的支持如何?
GNU編譯器結合GCC支持許多標準ANSI/ISO C/C++所不支持的特性。在開(kāi)源應用和Linux等開(kāi)發(fā)中,GCC的編譯器gcc和g++等都被廣泛使用。所以為了保證對GCC工具所開(kāi)發(fā)的代碼的兼容性,TI的編譯器也支持某些GCC的擴展特性。目前支持的一些特性基本都包含在GCC4.3中,可查看:http://gcc.gnu.org/onlinedocs/gcc-4.3.6/gcc/C-Extensions.html。
32. 如何了解有關(guān)編譯/代碼產(chǎn)生工具的已知問(wèn)題,并獲得最新進(jìn)展?
老外喜歡用IBM的ClearQuest系統來(lái)報告bug并分享解決方案,我們可以使用TI提供的開(kāi)放鏈接https://cqweb.ext.ti.com/cqweb/#/SDo-Web/SDOWP&format=HTML&version=cqwj來(lái)報告bug、查看/分享解決方案等,其界面如下圖所示:
避開(kāi)老舊的“傳統”bug的最好辦法當然是定期升級編譯器和開(kāi)發(fā)環(huán)境了。通過(guò)配置,新版本的CCS在啟動(dòng)后會(huì )自動(dòng)檢測升級并自動(dòng)升級,這也簡(jiǎn)化了我們對開(kāi)發(fā)環(huán)境的維護工作。
33. 鏈接文件中包含那么多個(gè)段,有什么快速識別的方法?
把下面這個(gè)例子記牢就好了:
//
// Global variables x & y ==> .ebss
// Initial values 2 & 7 ==> .cinit
//
int x = 2;
int y = 7;
void main()
{
long z; // Local variable => .stack
z = x + y; // Code => .text
}
34. 為什么我們需要鏈接文件.cmd?為何編譯器不能自動(dòng)分配存儲空間并進(jìn)行內存管理?
在操作系統存在的情況下,這些工作確實(shí)不需要我們花費太多的心思。但是在嵌入式的DSP處理中,這樣做的主要原因是處理能力和存儲空間是十分有限的,必須要我們進(jìn)行一定的介入,例如我們需要考慮的因素包括:
1) 運行速度:在RAM中比在Flash中快,在Flash中又比在外部存儲器(使用XINTF)中快。
2) 代碼是否需要存儲在非易失的存儲器中(例如Flash)?
3) 任務(wù)是否是時(shí)間關(guān)鍵的?例如需要把某個(gè)時(shí)間關(guān)鍵的ISR被保存在Flash中,然后運行時(shí)復制到RAM里。
4) 一些RAM可被DMA模塊所訪(fǎng)問(wèn),而另一些則不行。
5) 使用單獨的物理RAM模塊來(lái)避免資源的沖突。例如,在C2000 DSP中,RAM模塊都是在單個(gè)機器周期內只能訪(fǎng)問(wèn)一次的SARAM(Single-access RAM)。
6) 資源是否位于外部存儲器中?
7) 代碼是否需要保存在包含緩存或者預讀的存儲器中以提高性能?在C2000DSP中,我們幾乎見(jiàn)不到緩存或者預讀的概念,它們一般出現在包括ARM處理器的器件中。
8) 存儲器在程序空間、數據空間中是否具有等待狀態(tài)?
9) 是否有需要被代碼安全模塊CSM所保護的代碼?CSM并不能保護所有的代碼空間。
以上這些因素,在我們編程時(shí)也是需要特別關(guān)注,甚至是較為頭疼的事情,顯然讓編輯器去自動(dòng)實(shí)現它們,在目前階段是不可能的(除非編譯器的算法有一天能實(shí)現一定程度的人工智能)。所以在現階段,我們需要使用鏈接器命令文件cmd去描述每個(gè)段所需要使用的內存情況。
如果我們沒(méi)有把某一個(gè)特殊的或者自定義的段給指定到特定的存儲空間中,則此時(shí)鏈接器會(huì )自動(dòng)把它給分配到一個(gè)可用的存儲空間里,這有可能會(huì )影響到程序的執行效果。所以我們要開(kāi)啟編譯器的-w選項,這樣在在未定義的輸出段被創(chuàng )建時(shí),開(kāi)發(fā)環(huán)境的控制臺窗口中會(huì )產(chǎn)生相關(guān)的警告信息。
c語(yǔ)言相關(guān)文章:c語(yǔ)言教程
c++相關(guān)文章:c++教程
評論