精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

關(guān)于attribute(section)在GCC和ARMGCC中的使用

jf_L18yujSQ ? 來(lái)源:小飛哥學(xué)嵌入式 ? 2023-04-15 17:09 ? 次閱讀

簡(jiǎn)介

__attribute__ 是gcc編譯器支持的一個(gè)編譯特性(arm編譯器也支持此特性,比如我們常用的keil就是用的ARMGCC編譯器),也就是通過(guò)給函數(shù)或者變量聲明屬性值,以便讓編譯器能夠?qū)σ幾g的程序進(jìn)行優(yōu)化處理。

而對(duì)于 section 這個(gè)關(guān)鍵字,我們可以通過(guò)它將指定的變量定義到指定的輸入段中。

section 屬性指定變量必須放置在特定數(shù)據(jù)部分中,通常,ARM 編譯器將其生成的對(duì)象放在 .data 和 .bss 等部分中。但是,您可能需要其他數(shù)據(jù)部分,或者您可能希望變量出現(xiàn)在特殊部分中,例如,映射到特殊硬件。

如果使用 section 屬性,則只讀變量將放置在 RO 數(shù)據(jù)部分中,讀寫變量將放置在 RW 數(shù)據(jù)部分中,除非您使用 zero_init 屬性。在這種情況下,變量放置在 ZI 部分中。

/*inROsection*/
constintdescriptor[3]__attribute__((section("descr")))={1,2,3};
/*inRWsection*/
longlongrw_initialized[10]__attribute__((section("INITIALIZED_RW")))={5};
/*inRWsection*/
longlongrw[10]__attribute__((section("RW")));
/*inZIsection*/
longlongaltstack[10]__attribute__((section("STACK"),zero_init));

用法詳解

先來(lái)看一段代碼(摘自CSDN,如有侵權(quán),聯(lián)系刪除):

#include

#defineSEC__attribute__((__section__("ss"),aligned(sizeof(void*))))

voidfunc_1(inta,intb)
{
printf("%s%d%d
",__func__,__LINE__,a+b);
}
voidfunc_2(inta,intb)
{
printf("%s%d%d
",__func__,__LINE__,a*b);
}

//編譯器會(huì)自動(dòng)提供__start_ss,__stop_ss標(biāo)志段ss的起止地址
externsize_t__start_ss;
externsize_t__stop_ss;

typedefstruct
{
void(*p)(int,int);
}node_t;

//結(jié)構(gòu)體變量a位于自定義段ss
SECnode_ta={
.p=func_1,
};
SECnode_tb={
.p=func_2,
};
intmain(intargc,char**argv)
{
inta=3,b=4;
node_t*p;
//遍歷段ss,執(zhí)行node_t結(jié)構(gòu)中的p指向的函數(shù)
for(p=(node_t*)&__start_ss;pp(a,b);
a+=1;
b+=2;
}
}

來(lái)看一下運(yùn)行的結(jié)果:

poYBAGQ6aiyAGKAiAACaDdW4qbM210.jpg

1、section關(guān)鍵字可以將變量定義到指定的輸入段中,

#defineSECTION(level)__attribute__((used,__section__(".fn_cmd."level)))
#defineCMD_START_EXPORT(func,func_s)conststructCMD_LISTcmd_fn_##funcSECTION("0.end")={func,func_s}
CMD_START_EXPORT(start_fun,"start_fun");

conststructCMD_LISTcmd_fn_##funcSECTION("0.end")={func,func_s}

conststructCMD_LISTcmd_fn_funcSECTION("0.end")={start_fun,start_fun}

conststructCMD_LISTcmd_fn_func__attribute__((used,__section__(".fn_cmd.""0.end")))={start_fun,start_fun}

這個(gè)時(shí)候再來(lái)看會(huì)發(fā)現(xiàn)其實(shí)就是定義了一個(gè)struct CMD_LIST 類型的變量,變量的名字是cmd_fn_start_fun,并且這個(gè)變量被放到了我們所希望的一個(gè)輸入段.fn_cmd.0.end中了

typedefvoid(*fun)();
structCMD_LIST
{
funfuns;
constINT8*cmd;
};

2、使用section將變量放到我們自定義的輸入段中有什么意義呢?

#defineSECTION(level)__attribute__((used,__section__(".fn_cmd."level)))
#defineCMD_START_EXPORT(func,func_s)conststructCMD_LISTcmd_fn_##funcSECTION("0.end")={func,func_s}
#defineCMD_EXPORT(func,func_s)conststructCMD_LISTcmd_fn_##funcSECTION("1")={func,func_s}
#defineCMD_END_EXPORT(func,func_s)conststructCMD_LISTcmd_fn_##funcSECTION("1.end")={func,func_s}

當(dāng)這幾個(gè)宏被調(diào)用時(shí)將會(huì)產(chǎn)生名為cmd_fn_xx的變量,并且這個(gè)變量根據(jù)被調(diào)用的宏來(lái)把這個(gè)變量放到相應(yīng)的輸入段。例如CMD_START_EXPORT這個(gè)宏,這個(gè)宏其實(shí)上面已經(jīng)講過(guò)了,調(diào)用這個(gè)宏的時(shí)候會(huì)產(chǎn)生一個(gè)名為cmd_fn_xx的變量,并且把這個(gè)變量放到了我們自定義的輸入段.fn_cmd.0.end中了。

其他兩個(gè)宏的其實(shí)也是差不多的,不同之處就是輸入段有些區(qū)別。言歸正傳,現(xiàn)在繼續(xù)來(lái)講如何使用section將不同的函數(shù)放到我們想要的輸入段中,并且獲得他們的起始地址和結(jié)束地址。

我們可以在每個(gè)XXX_Init函數(shù)后面都調(diào)用宏CMD_EXPORT,在調(diào)用這個(gè)宏時(shí)編譯器會(huì)將XXX_init這個(gè)函數(shù)加入到輸入段中,由于變量在輸入段中的地址是連續(xù)的,并且順序先按 section 名 01234排一遍,section 內(nèi)再按函數(shù)名稱排。

所以可以按照輸入段中順序來(lái)逐個(gè)調(diào)用這些初始化函數(shù)來(lái)完成系統(tǒng)的初始化。具體實(shí)現(xiàn)我會(huì)根據(jù)我的一個(gè)自定義命令行的應(yīng)用來(lái)進(jìn)行部分的說(shuō)明。

/*命令函數(shù)段起始位置*/
intcmd_start(void)
{
return0;
}
CMD_START_EXPORT(cmd_start,"intcmd_start(void)");

/*命令函數(shù)段結(jié)束位置*/
intcmd_end(void)
{
return0;
}
CMD_END_EXPORT(cmd_end,"intcmd_end(void)");

voidtest(void)
{
printf("helloworld
");
}
CMD_EXPORT(test,"voidtest(void)");

voiddemo(void)
{
printf("helloworld
");
}
CMD_EXPORT(demo,"voiddemo(void)");

先定義start和end函數(shù)并且分別使用CMD_START_EXPORT和CMD_END_EXPORT來(lái)將其放到輸入段.fn_cmd.0.end和.fn_cmd.1.end中,按照上面的說(shuō)明輸入段.fn_cmd.0.end是排在輸入段.fn_cmd.1.end前面的,而使用的CMD_EXPORT這個(gè)宏對(duì)應(yīng)的輸入段.fn_cmd.1是排在.fn_cmd.0.end和.fn_cmd.1.end之間的,這里可以看一下編譯產(chǎn)生的.map會(huì)更加的形象一些。具體在MAP文件的位置如下所示

cmd_fn_cmd_start0x080042f0Data8serialcmd.o(.fn_cmd.0.end)
cmd_fn_test0x080042f8Data8application.o(.fn_cmd.1)
cmd_fn_demo0x08004300Data8application.o(.fn_cmd.1)
cmd_fn_cmd_end0x08004308Data8serialcmd.o(.fn_cmd.1.end)

typedefvoid(*fun)();
structCMD_LIST
{
funfuns;
constINT8*cmd;
};

conststaticstructCMD_LIST*CmdList;
staticUINT8CmdSize=0;

/*命令函數(shù)初始化*/
voidSerialCmdInit(void)
{
conststructCMD_LIST*cmd_ptr;
CmdList=&cmd_fn_cmd_start;
CmdList++;
for(cmd_ptr=CmdList;cmd_ptrfun)();
*/
CmdSize++;
}
}

其中cmd_fn_cmd_start是在.fn_cmd.0.end這個(gè)輸入段中的,而各個(gè)要執(zhí)行的函數(shù)是在.fn_cmd.1這個(gè)輸入段中的,cmd_fn_cmd_end作為結(jié)束的標(biāo)志在.fn_cmd.1.end輸入段中。

其余的就不做過(guò)多講解了,從上面的.map文件中的地址很容易就可以看出在得到了起始地址和結(jié)束地址之后怎樣一個(gè)個(gè)遍歷這些函數(shù)。

然而上述功能只能對(duì) GCC 平臺(tái)有效, 如果是 ARMCC 或是其他平臺(tái), 因?yàn)榫幾g器不同, 方法可能不一樣, 為了跨平臺(tái), 就不得不添加平臺(tái)檢測(cè)的宏, 比如將下面的代碼替換獲取 myfun_section 所在的內(nèi)存區(qū)間部分即可支持 ARMCC 平臺(tái)。

#ifdef__ARMCC_VERSION/*ARMCCompiler*/
externtest_command_tmyfun_section$$Base;
externtest_command_tmyfun_section$$Limit;
test_command_t*myfun_section_begin=&(myfun_section$$Base);
test_command_t*myfun_section_end=&(myfun_section$$Limit);
#elifdefined(__GNUC__)
externtest_command_t__start_myfun_section;
externtest_command_t__stop_myfun_section;
test_command_t*myfun_section_begin=&__start_myfun_section;
test_command_t*myfun_section_end=&__stop_myfun_section;
#else
#error"Theplatformisnotsupported"
#endif

結(jié)語(yǔ)

以上就是關(guān)于attribute(section)在GCC和ARMGCC中的使用。






審核編輯:劉清

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • ARM
    ARM
    +關(guān)注

    關(guān)注

    134

    文章

    9054

    瀏覽量

    366827
  • GNU
    GNU
    +關(guān)注

    關(guān)注

    0

    文章

    143

    瀏覽量

    17479
  • CMD命令
    +關(guān)注

    關(guān)注

    0

    文章

    28

    瀏覽量

    8300
  • gcc編譯器
    +關(guān)注

    關(guān)注

    0

    文章

    78

    瀏覽量

    3363

原文標(biāo)題:鮮為人知的__attribute__((__section__(section_name))),你知道怎么用嗎?

文章出處:【微信號(hào):小飛哥玩嵌入式,微信公眾號(hào):小飛哥玩嵌入式】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    pads提示警告:Section *DEL_ATTRIBUTE*

    第一次從pads logic向pads layout中導(dǎo)入原理圖的時(shí)候沒(méi)有提示警告,但是我第一次的基礎(chǔ)上再重復(fù)一次的時(shí)候就會(huì)提示很多的警告類似于:Line 6 , Section
    發(fā)表于 08-27 13:53

    __ATTRIBUTE__ 你知多少?

    , transparent_union, unused, deprecated 和 may_alias 。使用__attribute__ 參數(shù)時(shí),你也可以參數(shù)的前后都加上“__” (兩個(gè)下劃線),例如
    發(fā)表于 09-05 11:12

    section的使用方法

    無(wú)論是GNU還是ARM的編譯器,都支持__attribute__所指定的編譯屬性,這里著重講解一下KEIL環(huán)境下__attribute__se
    發(fā)表于 11-25 08:10

    attribute用法section部分的資料大合集

    轉(zhuǎn)載:http://blog.sina.com.cn/s/blog_5e11a56a0100c8h5.html###1. gcc的__attribute__編譯屬性要了解Linux Kernel代碼
    發(fā)表于 11-25 08:25

    來(lái)了解一下GNU C __attribute__機(jī)制

    不存在普通符號(hào),則使用弱符號(hào)。更多的__attribute__屬性可以參考GCC手冊(cè),我們需要使用到編譯器一些高級(jí)特性的時(shí)候,可以在手冊(cè)查找。
    發(fā)表于 03-03 15:49

    怎么理解RTT#define UNUSED __attribute__((unused))這個(gè)語(yǔ)句呢

    ){UNUSED rt_uint32_t iir;而UNUSED的定義,rtdef.h:#ifdef __CC_ARM /* ARM Compiler */#include#define SECTION
    發(fā)表于 03-29 09:27

    MounRiver keil的定位語(yǔ)句無(wú)法使用是為什么?

    由于從F轉(zhuǎn)到V,keil變?yōu)镸ounRiver,用gcc編譯器。原先keil的定位語(yǔ)句無(wú)法使用了。1、keil地址0x08005400位置定位一個(gè)變量用于存放程序版本號(hào):#define
    發(fā)表于 06-15 07:47

    請(qǐng)問(wèn)GCC支持attribute at屬性嗎?

    MAP您好,GCC目前不支持attribute at屬性,需要通過(guò)section屬性和LD來(lái)實(shí)現(xiàn)類似功能,編譯顯示RAM也超出了,您使用的是哪款芯片,以及具體的用法及程序可以到郵箱:yangy@wch.cn 。詳細(xì)溝通下。你好,
    發(fā)表于 07-18 08:59

    關(guān)于鏈接腳本(ld)的使用中段(section)被優(yōu)化的問(wèn)題求解

    USER_SECTION_NAME__attribute__((section("user_section_name_tab")))#define USER_SECTION__attribu
    發(fā)表于 03-08 07:56

    GCCSTUDIO的使用方法(WINAVR及AVR_STUDIO)

    GCCSTUDIO的使用方法(WINAVR及AVR_STUDIO),感興趣的可以看看。
    發(fā)表于 07-25 18:26 ?38次下載

    關(guān)于GCC的分析,想進(jìn)一步了解GCC的朋友可以看看

    關(guān)于GCC的分析,想進(jìn)一步了解GCC的朋友可以看看
    發(fā)表于 10-25 08:40 ?5次下載
    <b class='flag-5'>關(guān)于</b><b class='flag-5'>GCC</b>的分析,想進(jìn)一步了解<b class='flag-5'>GCC</b>的朋友可以看看

    __attribute__((section(x))) 使用詳解

    無(wú)論是GNU還是ARM的編譯器,都支持__attribute__所指定的編譯屬性,這里著重講解一下KEIL環(huán)境下__attribute__se
    發(fā)表于 11-16 18:06 ?8次下載
    __<b class='flag-5'>attribute</b>__((<b class='flag-5'>section</b>(x))) 使用詳解

    attribute 用法 section 部分

    attribute 用法 section 部分
    發(fā)表于 11-16 18:21 ?87次下載
    <b class='flag-5'>attribute</b> 用法 <b class='flag-5'>section</b> 部分

    C語(yǔ)言中的__attribute__宏定義之section屬性

    __attribute__所指定的編譯屬性,這里著重講解一下KEIL 環(huán)境下__attribute__section的使用方法。一、
    發(fā)表于 11-16 18:21 ?47次下載
    C語(yǔ)言中的__<b class='flag-5'>attribute</b>__宏定義之<b class='flag-5'>section</b>屬性

    __attribute__((section(“section_name“)))使用方法

    __attribute__((section("section_name")))使用方法內(nèi)容待補(bǔ)充?。。?!
    發(fā)表于 11-16 19:06 ?12次下載
    __<b class='flag-5'>attribute</b>__((<b class='flag-5'>section</b>(“<b class='flag-5'>section</b>_name“)))使用方法