前言:本文測試編譯器為arm-none-eabi-gcc 2018-q4-major [gcc-8-branch revision 267074]
==================================================================
GCC可以對部分代碼設(shè)置不同的編譯選項,在編譯時使用其指明的選項,而不用編譯命令里指定的參數(shù)。
有幾種方法可以實現(xiàn)該功能。
1. 使用#pragma指令
參數(shù)值可以是數(shù)字,也可以是字符串。數(shù)字就是優(yōu)化級別,以O(shè)開頭的字符串也被認為是一個優(yōu)化級別(例如(“O1”)(“-O1”)和(“1”)是相同的作用),其他的字符串選項如果沒有-前綴,編譯器自動添加-f,例如("unroll-loops")代表-funroll-loops。
該指令最小的作用域為函數(shù),也就是說無法在函數(shù)內(nèi)部使用,但可以作用于多個函數(shù)。
具體實現(xiàn):
Function Specific Option Pragmas,在特定代碼前保存當(dāng)前的編譯選項,然后對特定的代碼使用指定編譯選項,最后再恢復(fù)之前保存的編譯選項。
1 #pragma GCC push_options2 #pragma GCC optimize ("O0")3 ...your code...4 #pragma GCC pop_options
1 #pragma GCC push_options2 #pragma GCC optimize ("unroll-loops")3 ...your code...4 #pragma GCC pop_options
1 #pragma GCC push_options2 #pragma GCC optimize ("-funroll-loops")3 ...your code...4 #pragma GCC pop_options
1 ......2 #pragma GCC unroll 23 for(i=0;i<N;i++)4 {5 ......6 }7 ......
注:#pragma GCC unroll n
You can use this pragma to control how many times a loop should be unrolled.
It must be placed immediately before a for, while or do loop or a #pragma
GCC ivdep, and applies only to the loop that follows. n is an integer constant
expression specifying the unrolling factor. The values of 0 and 1 block any
unrolling of the loop.
2. 使用__attibute__屬性
參數(shù)值可以是數(shù)字,也可以是-開頭的字符串。數(shù)字就是優(yōu)化級別。以-O開頭的字符串也被認為是一個優(yōu)化選項(例如(“O1”)(“-O1”)和(“1”)是相同的作用),其他的字符串選項如果沒有-前綴,編譯器自動添加-f,例如("unroll-loops")代表-funroll-loops。
該選項作用于單個函數(shù),需要在函數(shù)開頭添加選項屬性。
#define OPTIMIZE_ZERO __attribute__ ((__optimize__ ("-O0")))#define OPTIMIZE_UNROLL __attribute__ ((__optimize__ ("-funroll-loops")))#define OPTIMIZE_UNROLL_ZERO __attribute__ ((__optimize__ ("unroll-loops","O0")))#define SECTION_ITCM __attribute__ ((section (".itcm")))#define SECTION_DTCM __attribute__ ((section (".dtcm")))int test_int[4] SECTION_DTCM; OPTIMIZE_ZERO int main(void) { ...... } OPTIMIZE_UNROLL_ZERO int test(void) { ...... } SECTION_ITCM int sec_tcm(void) { ...... }
注:-funroll-loops選項用于循環(huán)展開。
3. 修改Linker腳本
對于指定目標文件,如果我們想讓該文件中所有的text/data/bss等段內(nèi)容放置在指定地址,應(yīng)該怎么實現(xiàn)?
第一種方法,可以用本文第二段中的__attribute__屬性,對文件中的每個函數(shù)或者變量加上指定前綴,然后在Linker腳本安排好對應(yīng)的Section即可,這樣雖然可以滿足需求但是稍顯繁瑣。
查閱GCC的文檔,沒有找到使用#pragma指令對多個函數(shù)或者變量設(shè)置Section屬性的辦法,因此第二種辦法需要從Linker文件下手。
GCC使用的Linker腳本為LD文件,從文件中摘出.text段分配關(guān)系為例:
.text : { . = ALIGN(4); *(.text) /* .text sections (code) */ *(.text*) /* .text* sections (code) */ *(.rodata) /* .rodata sections (constants, strings, etc.) */ *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ *(.glue_7) /* glue arm to thumb code */ *(.glue_7t) /* glue thumb to arm code */ *(.eh_frame) KEEP (*(.init)) KEEP (*(.fini)) . = ALIGN(4); _etext = .; /* define a global symbols at end of code */ } >FLASH
上述的LD文件內(nèi)容指定了所有文件的.text和.text*段放置在FLASH所在基地址。
其中*符號為多字符通配符,加入.text*是因為如果編譯器開啟-ffunction-sections選項,會給所有的函數(shù)生成單獨的text段,例如main函數(shù)會生成.text.main段,加入.text*就可以覆蓋這些text段。
假如我們想把目標文件中test.o這個文件從中取出來放在另外的FLASH2地址,可以這么實現(xiàn):
(1)在FLASH段的描述中使用EXCLUDE_FILE把該文件排除:
.text : { . = ALIGN(4); *(EXCLUDE_FILE(*test.o) .text) /* .text sections (code) */ *(EXCLUDE_FILE(*test.o) .text*) /* .text* sections (code) */ *(.rodata) /* .rodata sections (constants, strings, etc.) */ *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ *(.glue_7) /* glue arm to thumb code */ *(.glue_7t) /* glue thumb to arm code */ *(.eh_frame) KEEP (*(.init)) KEEP (*(.fini)) . = ALIGN(4); _etext = .; /* define a global symbols at end of code */ } >FLASH
(2)在FLASH2段的描述中填入該文件text段:
.text_back : { . = ALIGN(4); *test.o(.text) /* .text sections (code) */ *test.o(.text*) /* .text* sections (code) */ . = ALIGN(4); } >FLASH2
上一篇:使用 openssl 生成證書(含openssl詳解)
下一篇:沒有了!