<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > stm32函數(shù)放入段section中

          stm32函數(shù)放入段section中

          作者: 時(shí)間:2016-12-03 來源:網(wǎng)絡(luò) 收藏
          關(guān)鍵字,__attribute__((section)).

          對于這樣一個(gè)需求,不管你寫多少個(gè)硬件底層初始化函數(shù),我都能通過固定的循環(huán)進(jìn)行執(zhí)行,是不動(dòng)的一個(gè)狀態(tài),這種實(shí)現(xiàn)方式,可以通過以下介紹的方式操作。

          本文引用地址:http://www.ex-cimer.com/article/201612/325186.htm

          思路,有兩種辦法,一種是指定一個(gè)段,這個(gè)段需要固定,然后,在這個(gè)段之間的區(qū)域?qū)⒑瘮?shù)寫入進(jìn)去。一種是直接將函數(shù)一直寫入,編譯器知道寫的函數(shù)有多少個(gè),調(diào)用編譯器得到的函數(shù)個(gè)數(shù)來操作,對于寫的函數(shù)個(gè)數(shù)同樣靈活。

          第一種辦法:

          指定段的辦法。

          操作示例:

          先定義一個(gè)函數(shù)類型。

          typedef int (*MyFun)(void);

          #define INIT_FUN(fn,level)

          const MyFun __myFun_##fn __attribute__((section(".myFun."level))) = fn

          讓其在初始化動(dòng)作的時(shí)候,寫入一個(gè)段中,在程序上看起來是一個(gè)text文本段了。

          這里有一個(gè)知識點(diǎn),如果這樣寫的話,后期程序遍歷的時(shí)候,發(fā)現(xiàn)在程序上無法執(zhí)行初始化的操作,根源是在map文件中:

          Section Cross References

          startup_stm32f10x_hd.o(RESET) refers to startup_stm32f10x_hd.o(STACK) for __initial_sp

          startup_stm32f10x_hd.o(RESET) refers to startup_stm32f10x_hd.o(.text) for Reset_Handler

          startup_stm32f10x_hd.o(RESET) refers to stm32f10x_it.o(.text) for NMI_Handler

          startup_stm32f10x_hd.o(.text) refers to system_stm32f10x.o(.text) for SystemInit

          startup_stm32f10x_hd.o(.text) refers to entry.o(.ARM.Collect$$$$00000000) for __main

          main.o(.text) refers to printf1.o(i.__0printf$1) for __2printf

          main.o(.text) refers to usart1.o(.text) for USART1_Config

          main.o(.text) refers to main.o(.myFun.0) for __myFun_init_begin

          main.o(.text) refers to main.o(.myFun.7) for __myFun_init_end

          main.o(.myFun.0) refers to main.o(.text) for init_begin

          main.o(.myFun.0s) refers to main.o(.text) for init_fun1

          main.o(.myFun.2) refers to main.o(.text) for init_fun2

          main.o(.myFun.7) refers to main.o(.text) for init_end

          Removing Unused input sections from the image.

          Removing startup_stm32f10x_hd.o(HEAP), (512 bytes).

          Removing main.o(.myFun.0s), (4 bytes).

          Removing main.o(.myFun.2), (4 bytes).

          Removing core_cm3.o(.emb_text), (32 bytes).

          Removing dadd.o(.text), (330 bytes).

          Removing dmul.o(.text), (226 bytes).

          Removing ddiv.o(.text), (222 bytes).

          Removing dfixul.o(.text), (48 bytes).

          Removing cdrcmple.o(.text), (40 bytes).

          Removing depilogue.o(.text), (194 bytes).

          10 unused section(s) (total 1612 bytes) removed from the image.

          剛開始建立了,但是在程序上沒有使用,就給刪除了段。

          那么這個(gè)緣由肯定是由于編譯器動(dòng)了手腳,因此,查看Arm Development Tool可以查到,在RealView Linker User Guide這個(gè)欄目下的Section elimination下的unused section elimination中有相關(guān)的敘述:

          Unused section elimination

          RealView Compilation Tools for ?Vision Linker User Guide

          Version 4.0

          Home > Using the Basic Linker Functionality > Section elimination > Unused section elimination

          Unused section elimination removes unreachable code and data from the final image. This optimization can be controlled by the--remove,--no_remove,--first,--last, and--keeplinker options and, indirectly, with--entry. Use the--info unusedlinker option to instruct the linker to generate a list of the unused sections that have been eliminated.

          Unused section elimination is suppressed in those cases that might result in the removal of all sections.

          An input section is retained in the final image under the following conditions:

          • if it contains an entry point
          • if it is referred to, directly or indirectly, by a non-weak reference from an input section containing an entry point
          • if it is specified as the first or last input section by the--firstor--lastoption (or a scatter-loading equivalent)
          • if it is marked as unremovable by the--keepoption.

          Note

          Compilers will normally collect functions and data together and emit one section for each category. The linker can only eliminate a section if it is entirely unused.

          里面談到了map文件最后移除了未用到的段。但是可以通過加—keep字段進(jìn)行保留,讓其最后不再刪除。

          對于本例程的用法是:

          --keep=__myFun*

          當(dāng)然了,按照map文件的提示,是將used文件變?yōu)閡nused,進(jìn)而刪除了,那么可以做一個(gè)操作:

          #define INIT_FUN(fn,level)

          const MyFun __myFun_##fn __attribute__((section(".myFun."level))) __attribute__((used)) = fn

          就是加: __attribute__((used))變?yōu)轱@示的使用了這個(gè)段,那它就不會(huì)被刪除了吧,測試可行?。∑鋵?shí)這個(gè)在linux上可以找到相關(guān)的參考。

          內(nèi)核版本linux3.0.1.。

          在main.c(init)這個(gè)文件中,

          有:

          extern initcall_t __initcall_start[], __initcall_end[], __early_initcall_end[];

          static void __init do_initcalls(void)

          {

          initcall_t *fn;

          for (fn = __early_initcall_end; fn < __initcall_end; fn++)

          do_one_initcall(*fn);

          }

          在init.h中有:

          typedef int (*initcall_t)(void);

          在vmlinux.lds.h中有:

          #define INIT_CALLS

          VMLINUX_SYMBOL(__initcall_start) = .;

          INITCALLS

          VMLINUX_SYMBOL(__initcall_end) = .;

          #define INITCALLS

          *(.initcallearly.init)

          VMLINUX_SYMBOL(__early_initcall_end) = .;

          *(.initcall0.init)

          *(.initcall0s.init)

          *(.initcall1.init)

          *(.initcall1s.init)

          *(.initcall2.init)

          *(.initcall2s.init)

          *(.initcall3.init)

          *(.initcall3s.init)

          *(.initcall4.init)

          *(.initcall4s.init)

          *(.initcall5.init)

          *(.initcall5s.init)

          *(.initcallrootfs.init)

          *(.initcall6.init)

          *(.initcall6s.init)

          *(.initcall7.init)

          *(.initcall7s.init)

          很簡單,寫的函數(shù)在段.initcall0.init-----initcall7s.init中,那么遍歷的時(shí)候,框頭框尾,中間函數(shù)明顯就能調(diào)用到。

          然后在init.h中有

          #define __init __section(.init.text)

          #define __initdata __section(.init.data)

          #define __exitdata __section(.exit.data)

          #define __exit_call __used __section(.exitcall.exit)

          同樣在段上加了一個(gè)__used修飾。猜測來的,所以加上了__attribute__((used))

          上代碼:

          static int init_begin(void)

          {

          printf("----fun init start---rn");

          return 0;

          }

          INIT_FUN(init_begin,"0");

          static int init_fun1(void)

          {

          printf("----fun init fun1---rn");

          return 0;

          }

          INIT_FUN(init_fun1,"0s");

          static int init_fun2(void)

          {

          printf("----fun init fun2---rn");

          return 0;

          }

          INIT_FUN(init_fun2,"2");

          static int init_end(void)

          {

          printf("----fun init end---rn");

          return 0;

          }

          INIT_FUN(init_end,"7");

          上面一系列函數(shù)中:

          init_begin函數(shù)和init_end屬于框頭框尾,遍歷時(shí)候,就作為邊界即可

          于是,就形成:

          const MyFun *vMyFun;

          for( vMyFun = &__myFun_init_begin; vMyFun <= &__myFun_init_end; vMyFun ++)

          {

          (*vMyFun)();

          }

          從而達(dá)到效果。

          第二種辦法:

          只有段的概念,不用計(jì)算多少個(gè)函數(shù),由編譯器來動(dòng)作即可。

          typedef int (*FunInit)(void);

          #define INIT_FUNCTION(func)

          FunInit __Fun_##func __attribute__((section("mySection"))) = func

          void InitFun1(void)

          {

          printf("InitFun1 initrn");

          }

          INIT_FUNCTION(InitFun1);

          void InitFun2(void)

          {

          printf("InitFun2 init rn");

          }

          INIT_FUNCTION(InitFun2);

          extern int mySection$$Base;

          extern int mySection$$Length;

          FunInit *initFunc = (FunInit *)&mySection$$Base;

          int count = (int)(&mySection$$Length)/sizeof(FunInit);

          while(count--) {

          (*initFunc)();

          initFunc++;

          }

          就這樣,可以遍歷整個(gè)段中定義好的函數(shù)了。

          代碼下載:

          http://download.csdn.net/detail/wit_yuan/9010727中關(guān)于section的部分。



          關(guān)鍵詞: stm32函數(shù)段sectio

          評論


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

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();