国产精品久久久久影院,成人午夜福利视频,国产精品久久久久高潮,国产精品 欧美 亚洲 制服,国产精品白浆无码流出

歷史上的今天

今天是:2024年12月20日(星期五)

正在發(fā)生

2019年12月20日 | 痞子衡嵌入式:ARM Cortex-M文件那些事(2)- 鏈接文件(.icf)

發(fā)布者:pi26 來源: eefocus關(guān)鍵字:ARM  Cortex-M文件  鏈接文件 手機看文章 掃描二維碼
隨時隨地手機看文章

  在前一節(jié)課源文件(.c/.h/.s)里,痞子衡給大家系統(tǒng)地介紹了source文件,source文件是嵌入式工程里典型的input文件,那么還有沒有其他類型的input文件?既然痞子衡這么提問了,那答案肯定是有啦。今天痞子衡要講的linker文件就屬于另一種input文件。


  linker文件顧名思義就是嵌入式工程在鏈接階段所要用到的文件,source文件在編譯過程完成之后(此時已經(jīng)是機器可識別的二進制機器碼數(shù)據(jù)),需要再經(jīng)過鏈接器從而將二進制數(shù)據(jù)有序組織起來形成最終的二進制可執(zhí)行文件,該二進制文件最終會被下載進芯片內(nèi)部非易失性存儲器里。linker文件就是用來指示鏈接器如何組織編譯生成的二進制數(shù)據(jù)。


  linker文件是跟IDE息息相關(guān)的,本文以IAR EWARM為例介紹linker文件,其他IDE下的linker文件可觸類旁通。


一、 嵌入式系統(tǒng)中的section

  在講linker文件之前,痞子衡必須先跟大家理清一個嵌入式系統(tǒng)中很重要的概念-section。那么什么是section?我們寫的C或者匯編source文件里都是各種應(yīng)用代碼,這些代碼按功能可以分為很多種類,比如常量、變量、函數(shù)、堆棧等,而相同類型的代碼的集合便是一個section,鏈接器在鏈接時組織數(shù)據(jù)的基本單元便是section。那么一個典型的嵌入式系統(tǒng)中到底有多少種section呢?下面列出了IAR里默認(rèn)的所有section,那些常見section在后續(xù)介紹linker文件里會被提到。


//常見Section

.bss                 // Holds zero-initialized static and global variables.

CSTACK               // Holds the stack used by C or C++ programs.

.data                // Holds static and global initialized variables.

.data_init           // Holds initial values for .data sections when the linker directive initialize is used.

HEAP                 // Holds the heap used for dynamically allocated data.

.intvec              // Holds the reset vector table

.noinit              // Holds __no_init static and global variables.

.rodata              // Holds constant data.

.text                // Holds the program code.

.textrw              // Holds __ramfunc declared program code.

.textrw_init         // Holds initializers for the .textrw declared section.


//較冷僻Section

.exc.text            // Holds exception-related code.

__iar_tls.$$DATA     // Holds initial values for TLS variables.

.iar.dynexit         // Holds the atexit table.

.init_array          // Holds a table of dynamic initialization functions.

IRQ_STACK            // Holds the stack for interrupt requests, IRQ, and exceptions.

.preinit_array       // Holds a table of dynamic initialization functions.

.prepreinit_array    // Holds a table of dynamic initialization functions.

Veneer$$CMSE         // Holds secure gateway veneers.


//更冷僻Section

.debug               // Contains debug information in the DWARF format

.iar.debug           // Contains supplemental debug information in an IAR format

.comment             // Contains the tools and command lines used for building the file

.rel or .rela        // Contains ELF relocation information

.symtab              // Contains the symbol table for a file

.strtab              // Contains the names of the symbol in the symbol table

.shstrtab            // Contains the names of the sections.

Note:上述section的詳細(xì)解釋請查閱IAR軟件安裝目錄下IAR SystemsEmbedded Workbench xxxarmdocEWARM_DevelopmentGuide.ENU.pdf文檔里的Section reference一節(jié)。


二、解析linker文件

  知道了section概念,那便可開始深入了解linker文件,什么是linker文件?linker文件是按IDE規(guī)定的語法寫成的用于指示鏈接器分配各section在嵌入式系統(tǒng)存儲器中存放位置的文件。大家都知道嵌入式系統(tǒng)存儲器主要分為兩類:ROM(非易失性),RAM(易失性),所以相應(yīng)的這些section根據(jù)存放的存儲器位置不同也分為兩類屬性:readonly, readwrite。實際上linker文件的工作就是將readonly section放進ROM,readwrite section放進RAM。


  那么到底該如何編寫工程的linker文件呢?正如前面所言,linker文件也是有語法的,而且這語法是由IDE指定的,所以必須要先掌握IDE制定的語法規(guī)則,linker文件語法規(guī)則相對簡單,最常用的關(guān)鍵字就是如下8個:


// 動詞類關(guān)鍵字

define                // 定義各種空間范圍、長度

initialize            // 設(shè)置section初始化方法

place in              // 放置section于某region中(具體地址由鏈接器分配)

place at              // 放置section于某絕對地址處


// 名詞類關(guān)鍵字

symbol                // 各種空間范圍、長度的標(biāo)識

memory                // 整個ARM內(nèi)存空間的標(biāo)識

region                // 在整個ARM內(nèi)存空間中劃分某region空間的標(biāo)識

block                 // 多個section的集合塊的標(biāo)識

Note:上述linker語法的詳細(xì)解釋請查閱IAR軟件安裝目錄下IAR SystemsEmbedded Workbench xxxarmdocEWARM_DevelopmentGuide.ENU.pdf文檔里的The linker configuration file一節(jié)。


  到這里我們已經(jīng)可以開始愉快地寫linker文件了,是不是有點按捺不住了?來吧,只需要三步走,Let's do it。


  此處假設(shè)MCU物理空間為:ROM(0x0 - 0x1ffff)、RAM(0x10000000 - 0x1000ffff),痞子衡要寫的linker要求如下:


中斷向量表必須放置于ROM起始地址0x0,且必須256字節(jié)對齊

STACK大小為8KB,HEAP大小為1KB,且必須8字節(jié)對齊

SATCK必須放置在RAM起始地址0x10000000

其余section放置在正確的region里,具體空間由鏈接器自動分配


2.1 定義物理空間

  第一步我們先定義3塊互不重疊的空間ROM_region、RAM_region、STACK_region,其中ROM_region對應(yīng)的是真實的ROM空間,RAM_region和STACK_region組合成真實的RAM空間。


// 定義物理空間邊界

define symbol __ICFEDIT_region_ROM_start__ = 0x00000000;

define symbol __ICFEDIT_region_ROM_end__   = __ICFEDIT_region_ROM_start__ + (128*1024 - 1);

define symbol __ICFEDIT_region_RAM_start__ = 0x10000000;

define symbol __ICFEDIT_region_RAM_end__   = __ICFEDIT_region_RAM_start__ + (64*1024 - 1);

define symbol __ICFEDIT_intvec_start__     = __ICFEDIT_region_ROM_start__;


// 定義堆棧長度

define symbol __ICFEDIT_size_cstack__      = (8*1024);

define symbol __ICFEDIT_size_heap__        = (1*1024);


// 定義各region具體空間范圍

define memory mem with size = 4G;

define region ROM_region    = mem:[from __ICFEDIT_region_ROM_start__ to __ICFEDIT_region_ROM_end__];

define region STACK_region  = mem:[from __ICFEDIT_region_RAM_start__ to  __ICFEDIT_region_RAM_start__ + __ICFEDIT_size_cstack__ - 1];

define region RAM_region    = mem:[from __ICFEDIT_region_RAM_start__ + __ICFEDIT_size_cstack__  to __ICFEDIT_region_RAM_end__];


2.2 定義section集合

  第二步是自定義section集合塊,細(xì)心的朋友可以看到右邊花括號里包含的都是上一節(jié)介紹的系統(tǒng)默認(rèn)section,我們會把具有相同屬性的section集合成到一個block里,方便下一步的放置工作。


// 定義堆棧塊及其屬性

define block CSTACK    with alignment = 8, size = __ICFEDIT_size_cstack__   { };

define block HEAP      with alignment = 8, size = __ICFEDIT_size_heap__     { };


// 定義section集合塊

define block Vectors with alignment=256 { readonly section .intvec };

define block CodeRelocate               { section .textrw_init };

define block CodeRelocateRam            { section .textrw };

define block ApplicationFlash           { readonly, block CodeRelocate };

define block ApplicationRam             { readwrite, block CodeRelocateRam, block HEAP };


  有朋友可能會疑問,為何要定義CodeRelocate、CodeRelocateRam這兩個block?按道理說這兩個block對應(yīng)的section可以分別放進ApplicationFlash和ApplicationRam,那為何多此一舉?仔細(xì)上過痞子衡前一節(jié)課source文件的朋友肯定就知道答案了,在那節(jié)課里介紹的startup.c文件里有一個叫init_data_bss()的函數(shù),這個函數(shù)會完成初始化CodeRelocateRam塊的功能,它找尋的就是CodeRelocate段名字,這個名字比系統(tǒng)默認(rèn)的textrw名字看起來更清晰易懂。


2.3 安置section集合

  第三步便是處理放置那些section集合塊了,在放置集合塊之前還有initialize manually語句,為什么會有這些語句?還是得結(jié)合前面提及的startup.c文件里的init_data_bss()函數(shù)來說,這個函數(shù)是開發(fā)者自己實現(xiàn)的data,bss段的初始化,所以此處需要通知IDE,你不需要再幫我做初始化工作了。


// 設(shè)置初始化方法

initialize manually { readwrite };

initialize manually { section .data};

initialize manually { section .textrw };

do not initialize   { section .noinit };


// 放置section集合塊

place at start of ROM_region { block Vectors };

//place at address mem:__ICFEDIT_intvec_start__ { block Vectors };

place in ROM_region          { block ApplicationFlash };

place in RAM_region          { block ApplicationRam };

place in STACK_region        { block CSTACK };


  當(dāng)然如果你希望IDE幫你自動初始化data,bss,textrw段,那么可以用下面語句替換initialize manually語句。


initialize by copy { readwrite, section .textrw };

  設(shè)置好初始化方法后,便是放置section集合塊了,放置方法主要有兩種,place in和place at,前者用于指定空間塊放置(不指定具體地址),后者是指定具體地址放置。


  至此一個基本的linker文件便大功告成了,是不是so easy?


番外一、自定義section

  有耐心看到這里的朋友,痞子衡必須得放個大招獎勵一下,前面講的都是怎么處理系統(tǒng)默認(rèn)段,那么有沒有可能在代碼里自定義段呢?想象一下你有這樣的需求,你需要在你的應(yīng)用里開辟一塊1KB的可更新的數(shù)據(jù)區(qū),你想把這個數(shù)據(jù)區(qū)指定到地址0x18000 - 0x183ff的范圍內(nèi),你需要在應(yīng)用里定義4 Byte的只讀config block常量指向這個可更新數(shù)據(jù)區(qū)首地址(這段config block只會被外部debugger或者bootloader更新),如何做到?


// C文件中

/////////////////////////////////////////////////////

// 用@操作符指定變量myConfigBlock[4]放進自定義.myBuffer section

const uint8_t myConfigBlock[4] @ ".myBuffer" = {0x00, 0x01, 0x02, 0x03};


// Linker文件中

/////////////////////////////////////////////////////

// 自定義指定的mySection_region,并把.myBuffer放到這個region

define region mySection_region = mem:[from  0x0x18000 to 0x183ff];

place at start of mySection_region { readonly section .myBuffer };

  上面做到了將代碼中的常量放入自定義段?,那么怎么將代碼中的函數(shù)也放進自定義段呢?繼續(xù)看下去


// C文件中

/////////////////////////////////////////////////////

// 用#pragma location指定函數(shù)myFunction()放進自定義.myTask section

#pragma location = ".myTask"

void myFunction(void)

{

    __NOP();

}


// Linker文件中

/////////////////////////////////////////////////////

// 把.myTask放到mySection_region

place in mySection_region { readonly section .myTask };


  看起來大功告成了,最后還有一個注意事項,如果myConfigBlock在代碼中并未被引用,IDE在鏈接的時候可能會忽略這個變量(IDE認(rèn)為它沒用,所以優(yōu)化了),那么怎么讓IDE強制鏈接myConfigBlock呢?IAR留了個后門,在options->Linker->Input選項卡中的Keep symbols輸入框里填入你想強制鏈接的對象名(注意是代碼中的對象名,而非linker文件中的自定義段名)即可。


Note:關(guān)于番外內(nèi)容的更多細(xì)節(jié)請查閱IAR軟件安裝目錄下IAR SystemsEmbedded Workbench xxxarmdocEWARM_DevelopmentGuide.ENU.pdf文檔里的Pragma directives一節(jié)。


  至此,嵌入式開發(fā)里的linker文件痞子衡便介紹完畢了

關(guān)鍵字:ARM  Cortex-M文件  鏈接文件 引用地址:痞子衡嵌入式:ARM Cortex-M文件那些事(2)- 鏈接文件(.icf)

上一篇:痞子衡嵌入式:ARM Cortex-M文件那些事(1)- 源文件(.c/.h/.s)
下一篇:Ubuntu安裝ARM架構(gòu)GCC工具鏈最簡單辦法

推薦閱讀

今天,在整個業(yè)界擁有極高聲譽,但日益衰落的MIPS指令集,終于在新東家WaveComputing的手里正式宣布開源。在MIPS經(jīng)過多次賣身,最后屈身于AI初創(chuàng)公司,RISC-V開源指令集日益流行的今天,這個結(jié)果的確在筆者意料之中,雖然MIPS開源整個指令集架構(gòu)屬于迫不得已,但已經(jīng)非常清楚的表明,在開源軟件已經(jīng)統(tǒng)治整個行業(yè)的時代,開源硬件的大潮也已經(jīng)來臨,指令集...
翻譯自——Spectrum Terabee公司利用紅外邊界技術(shù)實現(xiàn)二維距離傳感和三維深度制圖的間接飛行時間技術(shù)。 最先進的傳感器模塊技術(shù)是Terabee創(chuàng)新的三維ToF相機,它可以捕獲深度數(shù)據(jù)跨越三維空間。深度感知與飛行時間(TOF)感器是很敏感的,對眼睛完全安全,它可在室內(nèi)工作,甚至在低光或完全黑暗下運行。 該技術(shù)為諸如人員統(tǒng)計、數(shù)字庫存監(jiān)視和房間占用監(jiān)視...
環(huán)球晶 11 月 30 日宣布以 45 億美元并購世創(chuàng)電子(Siltronic AG),這已經(jīng)是今年以來第 7 樁重大半導(dǎo)體并購案;總計今年以來,全球半導(dǎo)體產(chǎn)業(yè)的并購金額已經(jīng)接近 1,300 億美元,超越 2015 年時的高峰,再次刷新歷史新高紀(jì)錄。根據(jù) IC Insights 統(tǒng)計,2015 年全球半導(dǎo)體產(chǎn)業(yè)總并購金額為 1,077 億美元,而今年光是加總前 6 大規(guī)模半...
已經(jīng)發(fā)布的兩款安卓旗艦SoC雖然對應(yīng)的終端還非常稀少,可紙面規(guī)格以及初步跑分上的口水戰(zhàn)已然火熱。從架構(gòu)參數(shù)來看,天璣9000采用臺積電4nm、支持LPDDR5X內(nèi)存、藍牙5.3、雙卡多制式雙通等,算是優(yōu)勢。驍龍8 Gen1這邊,則有著更強大的獨門Adreno GPU、4倍提升的AI算力、首發(fā)3單元18bit ISP以及全制式頻段萬兆5G網(wǎng)絡(luò)等。不過,業(yè)內(nèi)人士手機晶片達人給出消...

史海拾趣

問答坊 | AI 解惑

國產(chǎn)手機前途調(diào)查

猜一猜,今年中國手機市場新機型的最低售價紀(jì)錄是誰創(chuàng)造的?是波導(dǎo)嗎?還是TCL?抑或是動輒要搞“低價風(fēng)暴”的奧克斯?答案都不對,是摩托羅拉,全球和中國手機市場的第二大玩家。其在今年下半年上市的低價手機C117售價已從上市初的不足600元,大幅 ...…

查看全部問答∨

生物傳感技術(shù)關(guān)愛“弱勢群體”,有望用于車載監(jiān)控

Exmovere有限公司日前宣布推出一種滿足老年人醫(yī)療監(jiān)護需要,基于網(wǎng)絡(luò)的生物傳感器手表服務(wù)。 該公司總裁David Bychkov表示,Exmocare手表能夠監(jiān)護老年人的脈搏、心率可變性和皮膚電導(dǎo)系數(shù)。Exmocare手表還能夠通過內(nèi)建的加速度計來監(jiān)測受治療 ...…

查看全部問答∨

怎樣辨別視頻線的好壞——大家談

有的網(wǎng)友工程作了好幾年,仍然對這個問題還不能較好的把握。這是一個看來“問題不大”但又很重要的工程實際問題;真正的檢測還需要專門的設(shè)備和儀器。而這些設(shè)備和儀器又是設(shè)計和工程單位不具備的。工程鑒別視頻線的好壞,希望大家集思廣益。這里先 ...…

查看全部問答∨

關(guān)于rtems

各位大牛,誰有下面兩個插件? rtemscentre.javaxcomm 和rtemscentre.mysqlconnectorjava…

查看全部問答∨

EVB連接*.cdb數(shù)據(jù)庫問題?

Private Sub Command1_Click()       Dim cnMobileSales As ADOCE.Connection       Dim strPath As String       Dim rs As ADOCE.Recordset       Set cnM ...…

查看全部問答∨

加載鏡像啟動CE后,無法顯示硬盤,如何能顯示?

小弟新手,剛剛接觸wince。我把PLATFORM里的File   Systems   and   Data   Store加上Fat   File   System及CD/UDFS   File   System,并在Storage   D ...…

查看全部問答∨

STM32F103RB在固件庫V1.3.2下的USART2串口收發(fā)數(shù)據(jù)出錯

前天發(fā)貼是因為USART1接收數(shù)據(jù)不一致引起。經(jīng)過ST_ARM的指點:所用固件庫版本太低,應(yīng)升級?,F(xiàn)在我已安裝好最新的固件庫:STM32F10x_StdPeriph_Lib_V3.1.2 USART1的問題解決了,可以設(shè)置:波特率1200,1個起始位,9位數(shù)字,1個EVEN校驗,一 ...…

查看全部問答∨

比較單元

請問ev的比較單元的的定時器選哪一個是不是可以設(shè)置.在哪個寄存器中設(shè)置呢?我看了一個例子,好像涉及到的寄存器都沒有看到這個設(shè)置選項,那它的時鐘預(yù)定標(biāo)用采用的什么呢?…

查看全部問答∨

陣列式LED顯示屏控制系統(tǒng)

陣列式LED顯示屏控制系統(tǒng) 通過上兩篇針對LED顯示屏控制系統(tǒng)學(xué)習(xí)之后,也有不少朋友提問我說陣列式LED顯示屏控制系統(tǒng)的工作原理及應(yīng)用是怎樣的,本文小編就針對陣列式LED顯示屏控制系統(tǒng)進行詳細(xì)的講解,感興趣的朋友可以多關(guān)注一下。    陣 ...…

查看全部問答∨
小廣播
設(shè)計資源 培訓(xùn) 開發(fā)板 精華推薦

最新單片機文章

 
EEWorld訂閱號

 
EEWorld服務(wù)號

 
汽車開發(fā)圈

 
機器人開發(fā)圈

電子工程世界版權(quán)所有 京ICP證060456號 京ICP備10001474號-1 電信業(yè)務(wù)審批[2006]字第258號函 京公網(wǎng)安備 11010802033920號 Copyright ? 2005-2025 EEWORLD.com.cn, Inc. All rights reserved