《電子技術(shù)應(yīng)用》
您所在的位置:首頁(yè) > 可編程邏輯 > 業(yè)界動(dòng)態(tài) > DSP編程技巧之:不得不看的編譯指示

DSP編程技巧之:不得不看的編譯指示

2015-09-18
關(guān)鍵詞: DSP 編程技巧

  編譯指示(Pragma Directives)可能是所有的預(yù)處理指令中最復(fù)雜的了,它的作用是設(shè)定編譯器的狀態(tài)或者是指示編譯器完成一些特定的動(dòng)作,。#pragma指令對(duì)編譯器給出了如何處理特定的函數(shù),、對(duì)象和代碼段的方法,在保持與C/C++語(yǔ)言完全兼容的情況下,給出主機(jī)(比如C28x)或操作系統(tǒng)(比如DSP/BIOS)專有的特征。這些編譯指示的使用較為復(fù)雜,,但是我們還必須要了解它們,因?yàn)樗鼈兪浅绦蛑斜夭豢缮俚臇|西,,例如#pragma DATA_SECTION ( symbol , " section name ");這樣的,。但是往往講解它們的資料又不多(因?yàn)榇蟛糠仲Y料集中在入門指南上面),所以在此我們就總結(jié)一下針對(duì)C28x編譯器的pragma指令,,再遇到它們的時(shí)候就不會(huì)一頭霧水了,。
  1. CHECK_MISRA
  它的作用與在編譯器選項(xiàng)中使用--check_misra是相同的,都是對(duì)特定源文件使能MISRA-C:2004規(guī)則檢查(汽車工業(yè)軟件可靠性聯(lián)會(huì)),,使用方法是:
  #pragma CHECK_MISRA (" {all|required|advisory|none|rulespec} ");
  其中的rulespec是具體MISRA中的規(guī)則,,使用方法請(qǐng)參考DSP編程技巧之12-揭開(kāi)編譯器神秘面紗之代碼規(guī)范MISRA-C。
  2. CLINK
  CLINK指令可用于某段代碼或者某個(gè)數(shù)據(jù)符號(hào),,使用之后會(huì)在包含被作用符號(hào)的段中產(chǎn)生一個(gè).clink指示,,表明在條件鏈接的情況下,如果這個(gè)段沒(méi)有被其它任何段引用的話,,這個(gè)段可以被移除,,從而減小鏈接輸出文件的尺寸。使用方法是:
  #pragma CLINK (symbol )
  3. CODE_ALIGN
  CODE_ALIGN用來(lái)沿著特定的對(duì)齊參數(shù)constant來(lái)對(duì)齊函數(shù)(從而可以讓CPU更快尋址,,更快執(zhí)行指令),。當(dāng)我們希望函數(shù)從特定的邊界開(kāi)始的時(shí)候,這個(gè)指令非常有用。參數(shù)constant必須是2的冪(偶數(shù)對(duì)齊),,使用方法是:
  C代碼: #pragma CODE_ALIGN ( func, constant );
  C++代碼: #pragma CODE_ALIGN ( constant );
  注:在本文中,,在C和C++代碼中,指令使用方法一樣時(shí),,不分別寫出,,如不一樣則分C代碼和C++代碼分別寫出。C代碼中的#pragma指令一般需指定函數(shù)名,,也即其作用域;C++代碼中的#pragma指令一般不帶有函數(shù)名,,其作用域?yàn)榫o鄰該指令后面的函數(shù);下同。
  4. CODE_SECTION
  CODE_SECTION是較為常見(jiàn)的指令,,默認(rèn)情況下,,代碼被存放在.text段中,使用此指令則用來(lái)指定并改變某段代碼所分配的段,,其使用方法是:
  C代碼: #pragma CODE_SECTION (symbol , "section name ")
  C++代碼: #pragma CODE_SECTION (" section name ")
  例如:
  char bufferA[80];
  char bufferB[80];
  #pragma CODE_SECTION(funcA, "codeA")
  char funcA(int i);
  char funcB(int i);
  void main()
  {
  char c;
  c = funcA(1);
  c = funcB(2);
  }
  char funcA (int i)
  {
  return bufferA[i];
  }
  char funcB (int j)
  {
  return bufferB[j];
  }

  5. DATA_SECTION
  DATA_SECTION可能是使用最多的pragma指令了,,它用來(lái)定義存儲(chǔ)某個(gè)符號(hào)所使用的段,使用方法是:
  C代碼: #pragma DATA_SECTION ( symbol , " section name ");
  C++代碼: #pragma DATA_SECTION (" section name ");
  例如:
  #pragma DATA_SECTION(bufferB, "my_sect")
  char bufferA[512];
  char bufferB[512];
  6. 與診斷信息有關(guān)的Pragma
  診斷信息一般包括:提醒,,警告,,錯(cuò)誤和不提示等幾個(gè)級(jí)別,使用與診斷信息有關(guān)的Pragma和使用相關(guān)的編譯器選項(xiàng)的結(jié)果是一樣的,,其使用方法以及們的對(duì)應(yīng)關(guān)系如下:
  Pragma對(duì)應(yīng)的編譯器選項(xiàng)
  有關(guān)診斷信息的含義,,請(qǐng)參考DSP編程技巧之7---揭開(kāi)編譯器神秘面紗之預(yù)處理與診斷。
  7. FAST_FUNC_CALL
  使用這個(gè)指令,,會(huì)在編譯時(shí)調(diào)用快速匯編指令FFC,,而不是傳統(tǒng)的CALL指令來(lái)完成函數(shù)的跳轉(zhuǎn),其使用方法是:
  #pragma FAST_FUNC_CALL ( func );
  它的使用范圍是受限的:僅限于調(diào)用返回LB *XAR7指令的匯編程序,。例如:
  ;匯編程序
  _add_long:
  ADD ACC, *-SP[2]
  LB *XAR7
  //調(diào)用匯編的C程序
  #pragma FAST_FUNC_CALL (add_long);
  long add_long(long, long);
  void foo()
  {
  long x, y;
  x = 0xffff;
  y = 0xff;
  y = add_long(x, y);
  }
  除此之外,,如果使用該指令,編譯器會(huì)輸出警告信息,,并忽略其指示。
  8. FUNC_EXT_CALLED
  在我們啟用程序級(jí)別的優(yōu)化選項(xiàng)時(shí)(-O3),,所有未直接或者簡(jiǎn)介被main函數(shù)調(diào)用的函數(shù)都將被優(yōu)化掉,,但是這些函數(shù)也有可能被我們定義的某些匯編代碼使用到,所以使用FUNC_EXT_CALLED可以在編譯時(shí)保留這些代碼,,其使用方法是:
  C代碼: #pragma FUNC_EXT_CALLED ( func );
  C++代碼: #pragma FUNC_EXT_CALLED;

  9. FUNCTION_OPTIONS
  使用這個(gè)選項(xiàng)可以在編譯C/C++代碼中的某些函數(shù)時(shí),,使用額外的編譯器的命令行選項(xiàng),實(shí)現(xiàn)與在命令行中輸入相關(guān)的命令同樣的效果,。其使用方法是:
  C代碼: #pragma FUNCTION_OPTIONS ( func, "additional options" );
  C++代碼: #pragma FUNCTION_OPTIONS( "additional options" );
  10. INTERRUPT
  使用這個(gè)選項(xiàng)可以在C代碼中直接操作中斷,,其使用方法是:
  C代碼: #pragma INTERRUPT ( func );
  C++代碼: #pragma INTERRUPT ;
  被該指令直接操作的函數(shù)將使用IRP(中斷返回指針)來(lái)返回值。
  在使用FPU時(shí),中斷分為兩種:高優(yōu)先級(jí)中斷HPI和低優(yōu)先級(jí)中斷LPI,,其中HPI使用快速的上下文存儲(chǔ)機(jī)制,,不能被嵌套,LPI則與普通的C28x中斷機(jī)制一樣,,并且可以被嵌套,。此時(shí)可以增加第二個(gè)參數(shù)來(lái)控制:
  C代碼: #pragma INTERRUPT ( func , {HPI|LPI} );
  C++代碼: #pragma INTERRUPT ( {HPI|LPI} );
  在DSP/BIOS和SYS/BIOS HWI對(duì)象中,不能使用INTERRUPT指令,,因?yàn)镠wi_enter/Hwi_exit宏和Hwi解包器已經(jīng)包含了該函數(shù),,此時(shí)使用該指令會(huì)產(chǎn)生負(fù)面的效果。
  11. MUST_ITERATE
  使用這個(gè)指令的情況下,,我們確信某個(gè)for循環(huán)能夠執(zhí)行指定的次數(shù),。使用這個(gè)指令能夠幫助編譯器確定循環(huán)的次數(shù)和最佳的實(shí)現(xiàn)方式,從而減小代碼的尺寸,。其使用方法是:
  #pragma MUST_ITERATE ( min, max, multiple );
  min是循環(huán)的最小次數(shù),,max是最大執(zhí)行次數(shù),multiple則是循環(huán)次數(shù)的整數(shù)倍,,如果這其中某個(gè)參數(shù)不存在,,則可以省略,例如:
  #pragma MUST_ITERATE(5); /* 最少循環(huán)5次 */
  #pragma MUST_ITERATE(5, , 5); /* max參數(shù)省略;循環(huán)次數(shù)是5的倍數(shù)次(至少1倍) */
  pragma MUST_ITERATE(8, 48, 8);
  /* 循環(huán)此時(shí)可能為8, 16, 24, 32, 40, 48 */
  12. NO_HOOKS
  該指令阻止在調(diào)用函數(shù)時(shí)自動(dòng)產(chǎn)生進(jìn)入鉤子和退出鉤子,,使用方法是:
  C代碼: #pragma NO_HOOKS ( func );
  C++代碼: #pragma NO_HOOKS;


  13. RESET_MISRA
  顧名思義,,這個(gè)指令會(huì)把MISRA-C:2004規(guī)則檢查恢復(fù)到它原先的設(shè)定狀態(tài)。例如,,某條規(guī)則在命令行里被使能,,但是在某段代碼中被屏蔽了(某些原因?qū)е滤鼰o(wú)法通過(guò)規(guī)則檢查),使用該指令會(huì)規(guī)則檢查重新使能,。使用方法是:
  #pragma RESET_MISRA (" {all|required|advisory|rulespec} ")
  14. RETAIN
  使用這個(gè)指令,,可以避免某些符號(hào)在條件鏈接時(shí)被優(yōu)化掉,從而在輸出文件中保留它,。使用方法是:
  #pragma RETAIN ( symbol )
  這個(gè)指令與我們的第二條,,CLINK的效果是整好相反的。
  15. SET_CODE_SECTION與SET_DATA_SECTION
  這兩條指令用來(lái)設(shè)置其后所有聲明的段,。使用方法是:
  C代碼: #pragma SET_CODE_SECTION ("section name")
  C++代碼: #pragma SET_DATA_SECTION ("section name")
  例如:
  #pragma SET_DATA_SECTION("mydata")
  int x;
  int y;
  #pragma SET_DATA_SECTION()
  其中的x和y都被會(huì)放入我們指定的段mydata中,,直到我們使用空參數(shù)SET_DATA_SECTION(),之后的代碼或數(shù)據(jù)才會(huì)被放入默認(rèn)的段之中,。
  16. UNROLL
  UNROLL是“攤開(kāi)”的意思,,這個(gè)指令與for/while相關(guān),意思是把n次的循環(huán)給展開(kāi),,從而有個(gè)n份同樣的代碼,。循環(huán)展開(kāi),是一種犧牲程序的尺寸來(lái)加快程序的執(zhí)行速度的優(yōu)化方法??梢允謩?dòng)編程完成,,也可由編譯器自動(dòng)優(yōu)化完成。循環(huán)展開(kāi)通過(guò)將循環(huán)體代碼復(fù)制多次實(shí)現(xiàn),。循環(huán)展開(kāi)能夠增大指令調(diào)度的空間,,減少循環(huán)分支指令的開(kāi)銷。循環(huán)展開(kāi)可以更好地實(shí)現(xiàn)數(shù)據(jù)預(yù)取技術(shù),。其使用方法是:
  #pragma UNROLL( n );
  只有在編譯器認(rèn)為n是安全的(即展開(kāi)之后確實(shí)都能執(zhí)行),,才能執(zhí)行此操作。

本站內(nèi)容除特別聲明的原創(chuàng)文章之外,,轉(zhuǎn)載內(nèi)容只為傳遞更多信息,,并不代表本網(wǎng)站贊同其觀點(diǎn)。轉(zhuǎn)載的所有的文章,、圖片,、音/視頻文件等資料的版權(quán)歸版權(quán)所有權(quán)人所有。本站采用的非本站原創(chuàng)文章及圖片等內(nèi)容無(wú)法一一聯(lián)系確認(rèn)版權(quán)者,。如涉及作品內(nèi)容,、版權(quán)和其它問(wèn)題,請(qǐng)及時(shí)通過(guò)電子郵件或電話通知我們,,以便迅速采取適當(dāng)措施,,避免給雙方造成不必要的經(jīng)濟(jì)損失。聯(lián)系電話:010-82306118,;郵箱:[email protected],。