新聞中心

EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > DSP編程技巧之:編譯流程與處理器選項(xiàng)

DSP編程技巧之:編譯流程與處理器選項(xiàng)

作者: 時(shí)間:2016-12-21 來(lái)源:網(wǎng)絡(luò) 收藏

  在我們有關(guān)DSP的論壇、博客和一些互動(dòng)活動(dòng)中,網(wǎng)友經(jīng)常會(huì)問(wèn)一些有關(guān)“編程技巧”的問(wèn)題。

本文引用地址:http://butianyuan.cn/article/201612/332375.htm

  關(guān)于編程技巧的定義,也沒(méi)有一個(gè)統(tǒng)一的標(biāo)準(zhǔn),例如實(shí)現(xiàn)一個(gè)很復(fù)雜的多層嵌套的指針設(shè)計(jì)算是一種編程熟練的體現(xiàn)吧;又或者用C/C++的高級(jí)特性做了很復(fù)雜的功能,但是編譯器不能完全支持,例如某種內(nèi)存的動(dòng)態(tài)重分配方法,這時(shí)對(duì)編譯器特性的熟悉就顯得很重要了。

  接下來(lái)我們就聊一聊巧里面有關(guān)編譯技巧的一些問(wèn)題,具體的分類包括編譯器的選項(xiàng)、代碼的優(yōu)化、庫(kù)文件的使用、代碼實(shí)現(xiàn)標(biāo)準(zhǔn)、實(shí)時(shí)運(yùn)行環(huán)境等等;了解了這些具體的問(wèn)題,對(duì)于解決在編譯和鏈接程序的時(shí)候經(jīng)常遇到的讓人摸不著頭腦的警告和錯(cuò)誤也是很有幫助的;因?yàn)槌绦虻恼Z(yǔ)法錯(cuò)誤很容易被編譯器發(fā)現(xiàn)并定位到具體的代碼中,而鏈接器輸出的那些莫名其妙的警告是很難定位的,如果理解了編譯流程中各個(gè)環(huán)節(jié)的作用所在,就有了對(duì)癥下藥的入口。編譯器主要以TI的CCS編譯器為例,目標(biāo)器件為28系列,相比6000系列的,28系列的要稍微簡(jiǎn)單一些。

  首先要了解一下基于CCS開發(fā)的一個(gè)完整流程,以免“只見樹木,不見森林”:

  因?yàn)楹苌儆形臋n把它們的具體漢語(yǔ)含義講清楚,所以在此我們要用通俗的語(yǔ)言描述一下各個(gè)部分:

  1. 在這個(gè)流程中,與我們編程效率直接相關(guān)的就是C/C++編譯器了(如果沒(méi)有使用匯編直接編寫的話),它的直接用途是將C/C++代碼編譯為針對(duì)DSP匯編指令集的匯編代碼。

  目前的C和C++語(yǔ)言標(biāo)準(zhǔn)有好幾個(gè)版本,CCS的編譯器目前支持的版本包括:

  C語(yǔ)言的C89和C99版本的ISO標(biāo)準(zhǔn)(C99部分支持,主要是與C89一樣的特性):通俗的講就是我們學(xué)過(guò)的C語(yǔ)言里常用的功能都是支持的,除了一些多字節(jié)字符和一些極少數(shù)的特性等。不清楚的可以參考Kernighan和Ritchie編寫的C語(yǔ)言書籍《The C Programming Language》第二版。

  C++語(yǔ)言的2003版本的的ISO標(biāo)準(zhǔn): 可以參考Ellis和Stroustrup編寫的經(jīng)典書籍《The Annotated C++ Reference Manual》。同時(shí)也支持一部分的嵌入式C++特性。因?yàn)镃++的特性眾多,而許多并不適用于這樣一種嵌入式的環(huán)境,所以不支持的特性相比C要多一些。

  2. 匯編器的作用是將匯編語(yǔ)言代碼轉(zhuǎn)換為機(jī)器語(yǔ)言(目標(biāo)文件),這里的匯編代碼包括前面由C/C++生成的匯編代碼和我們直接編寫的匯編代碼。

  3. 鏈接器是作用是把所有的庫(kù)文件、目標(biāo)文件等鏈接成為一個(gè)可執(zhí)行的目標(biāo)文件,其中包含程序的機(jī)器代碼和數(shù)據(jù),以及其他用來(lái)鏈接和加載該程序所需的信息(在TI DSP上是COFF格式,通俗地講就是.out二進(jìn)制文件),同時(shí)根據(jù)內(nèi)存地址的分配對(duì)各目標(biāo)文件進(jìn)行重定位,并解析外部參考,例如在一個(gè)源程序里引用另一個(gè)源程序中定義的變量就可以理解為外部參考,假如一個(gè)目標(biāo)文件引用了一個(gè)未定義的符號(hào)symbol,則鏈接器搜索其他目標(biāo)文件中定義的全局符號(hào),找到匹配的符號(hào)修補(bǔ)指令。否則報(bào)告一個(gè)錯(cuò)誤;所以有時(shí)候編譯所有程序完成在鏈接的時(shí)候會(huì)提示xxx symbol為定義,說(shuō)明對(duì)應(yīng)的文件沒(méi)有加到工程里面?! ?. 歸檔器archiver:也可以叫壓縮器,看一下我們常用的壓縮軟件winrar的全稱winrar archiver就不難理解了。

  5. 實(shí)時(shí)支持庫(kù):包括標(biāo)準(zhǔn)C和C++的運(yùn)行支持函數(shù)、編譯器公用程序函數(shù)、浮點(diǎn)運(yùn)算函數(shù)和C編譯器支持的I/O函數(shù),

  6. 十六進(jìn)制轉(zhuǎn)換程序:把編譯、鏈接等步驟生成的可執(zhí)行文件,轉(zhuǎn)換為十六進(jìn)制文件,例如.HEX格式,然后可以燒寫到EEPROM、FLASH等外部存儲(chǔ)器之中。

  7. 絕對(duì)列表器:讀取目標(biāo)文件并輸出.abs文件,通過(guò)匯編.abs文件可產(chǎn)生含有絕對(duì)地址的列表文件,從而使得我們不用手工費(fèi)時(shí)費(fèi)力地去創(chuàng)建列表文件。這本來(lái)不就是軟件該做的事情嗎:-D

  8. 交叉引用列表:與3中外部參考解析相關(guān)的,它用目標(biāo)文件產(chǎn)生參照列表文件,可顯示符號(hào)及其定義,以及符號(hào)所在的源文件。

  9. C/C++命名還原工具:C/C++編譯器會(huì)將程序中的變量名、函數(shù)名轉(zhuǎn)換成內(nèi)部名稱,這個(gè)過(guò)程被稱作Name Mangling,反過(guò)程被稱作Name Demangling,即命名還原工具。內(nèi)部名稱包含了變量或函數(shù)的更多信息,例如編譯器看到?g_var@@3HA,就知道這是:int g_var。具體的還原規(guī)則一般是不開放給我們用戶的,只要編譯器知道就行了。

  10. 調(diào)試工具:例如我們電腦上裝的CCS軟件,讓我們可以用斷點(diǎn)、圖形窗口等進(jìn)行軟件的調(diào)試。

  此外,并沒(méi)有明確列在前面的流程中,但是隱含在流程中,或者我們也有可能會(huì)用到的工具或者流程包括:

  1. 優(yōu)化工具:在編譯時(shí)對(duì)代碼進(jìn)行優(yōu)化的工具,可以根據(jù)我們期望的優(yōu)化級(jí)別,進(jìn)行從不優(yōu)化到直至CPU寄存器級(jí)別的優(yōu)化。

  2. 反編譯器:可以對(duì)目標(biāo)文件進(jìn)行解碼,顯示對(duì)應(yīng)的匯編語(yǔ)言。在CCS的調(diào)試模式下,我們可以打開disassembler窗口,然后單步運(yùn)行,就能看到一條條的匯編指令是如何執(zhí)行的了。

  3. 加載器:把可執(zhí)行的二進(jìn)制文件復(fù)制到DSP的內(nèi)存中,并運(yùn)行啟動(dòng)程序,使得程序從程序入口處開始運(yùn)行,這個(gè)入口地址可能是地址0,也可能是帶有一個(gè)偏移量的地址,這個(gè)具體的值我們可以以后再具體討論。

  4. 其它:補(bǔ)充一下名詞的定義,包括:

  符號(hào):在整個(gè)編譯、鏈接的過(guò)程中都會(huì)使用到符號(hào)symbol的概念,簡(jiǎn)單地理解,符號(hào)就是指一些變量、函數(shù)名字等。

  庫(kù)文件:多個(gè)目標(biāo)文件的壓縮包,包含了所有目標(biāo)文件定義的全局符號(hào)的索引。在源程序中如果找不到某些符號(hào)的定義,鏈接器從嘗試從庫(kù)里面提取出對(duì)應(yīng)的目標(biāo)文件,然后鏈接到可執(zhí)行文件里。

  也許你已經(jīng)熟練使用了CCS好多年,可是當(dāng)某一天出現(xiàn)一個(gè)與cl2000有關(guān)的錯(cuò)誤的時(shí)候,突然間也摸不著頭腦了;例如使用老版本的還不支持C2000 FPU的CCS來(lái)編譯28335的程序,cl2000就會(huì)提示你各種不支持然后報(bào)錯(cuò)不運(yùn)行了。Cl2000.exe是神馬?

  Cl2000.exe就是和我們的程序編譯密切相關(guān)的編譯器了,使用的方法是:

  cl2000 [編譯器選項(xiàng)] [需要編譯的文件] [--運(yùn)行鏈接器 [鏈接器選項(xiàng)] 目標(biāo)文件]]

  使用方法看起來(lái)很復(fù)雜,還好CCS已經(jīng)幫我們調(diào)用它了(或者說(shuō)CCS就是一個(gè)框架,它完成的編譯、調(diào)試、鏈接等功能幾乎都需要調(diào)用一些別的exe來(lái)執(zhí)行,所以你可能體會(huì)過(guò)升級(jí)了一些庫(kù)文件、編輯器版本等,界面文件等卻不需要進(jìn)行任何的更改),這些句子會(huì)顯示在工程的屬性里面。當(dāng)然如果你想親自體驗(yàn)一把,也可以在ccs安裝目錄下面的toolscompilerc2000_6.1.5bin下面找到它,即cl2000.exe,然后用命令行的方式運(yùn)行起來(lái))。舉個(gè)簡(jiǎn)單例子:

  cl2000 -v28 symtab.c file.c seek.asm --run_linker --library=lnk.cmd

  --output_file=myprogram.out  在上面的例子中,如果需要編譯的文件,例如幾個(gè).c或者.asm找不到,CCS就會(huì)提示xxx.c或者xxx.asm找不到或者未定義了;或者你改了目標(biāo)文件的名字,例如改成了a.out,但是加載程序到DSP中的時(shí)候卻仍然使用更改前的b.out,自然有可能出現(xiàn)預(yù)料之外的結(jié)果了:在以前幫助網(wǎng)友解決問(wèn)題的時(shí)候,確實(shí)出現(xiàn)過(guò)這樣的狀況。

  明白了編譯器的調(diào)用方法之后,我們就更進(jìn)一步,揭開編譯器中形形色色選項(xiàng)的神秘面紗,從此看到編譯器提示的形形色色的警告和錯(cuò)誤不再用發(fā)怵。

  具體說(shuō)來(lái),編譯器的選項(xiàng)有多大20個(gè)大類,超過(guò)一百個(gè)具體的選項(xiàng)。當(dāng)然這些選項(xiàng)是有輕重之分的,有的是必須用到的,例如支持一下FPU等功能;有的則是不常接觸的,例如MISRA這樣的汽車工業(yè)軟件可靠性檢查,只有在對(duì)軟件進(jìn)行標(biāo)準(zhǔn)化時(shí)才會(huì)用到。所以我們首先看一下最常用的選項(xiàng),例如處理器的選項(xiàng),它們的意義在于定義了在編譯程序時(shí)CPU的模式。補(bǔ)充一點(diǎn)是,cl2000的幫助里看到的選項(xiàng)都是很長(zhǎng)的名字,在CCS里面為了書寫方便(因?yàn)檫x項(xiàng)框就那么點(diǎn)面積啊),一般用別名來(lái)代替;沒(méi)有別名的則直接使用選項(xiàng)名字。



關(guān)鍵詞: DSP編程技

評(píng)論


技術(shù)專區(qū)

關(guān)閉