IAR編譯器ICF文件深入學習


每一個芯片型號,都配置了專用的ICF文件,ICF主要作用就是定義內存位置、內存大小和堆棧大小。

其作用不言而喻!!

 

【關鍵字:define  symbol

define symbol __ICFEDIT_intvec_start__ = 0x08000000;
/*-Memory Regions-*/
define symbol __ICFEDIT_region_ROM_start__   = 0x080000EC ;
define symbol __ICFEDIT_region_ROM_end__     = 0x0807FFFF;
define symbol __ICFEDIT_region_RAM_start__   = 0x20000000;
define symbol __ICFEDIT_region_RAM_end__     = 0x2000FFFF;
/*-Sizes-*/
define symbol __ICFEDIT_size_cstack__   = 0x800;
define symbol __ICFEDIT_size_heap__     = 0x800;
/**** End of ICF editor section. ###ICF###*/

 symbol是符號申明,__ICFEDIT_region_ROM_start__就是符號名字,  0x080000EC是值。

一般出現在ICF文件開頭,凡是通過 symbol申明的符號,都會在ICF文件后面會使用到。

 

為了說明這一點,如下倆張圖片加深影響:

    

  所以,define symbol是什么呢?其實你把它當成C里面的#define   AAA    (xxx)就可以了,簡不簡單?

 

 

【關鍵字:define memory

define memory mem with size = 4G;

定義芯片的最大編址空間,對於32位的單片機,都是4G,2的32次方剛好是4G,如果你的芯片是64位的,這個值有點大了!

define memory mem with size每一個字母都是IAR專用的,知道是最大編址范圍就OK了,基本改動概率為0.這個mem名字

可以改一下,但要記住與后面的名字一致,要不然后找不到MEM!

 

【關鍵字:define region】 

define region ROM_region   = mem:[from __ICFEDIT_region_ROM_start__   to __ICFEDIT_region_ROM_end__];
define region RAM_region   = mem:[from __ICFEDIT_region_RAM_start__   to __ICFEDIT_region_RAM_end__];
define region是關鍵字,  ROM_region是名字,  mem是上面定義的最大編址空間,[from _xxx_  to  _xxx_]是連續的存儲區域
,一般是指ROM RAM,在芯片手冊可以找到信息。



【關鍵字:define block】 
define block CSTACK     with alignment = 8, size = __ICFEDIT_size_cstack__     { };
define block PROC_STACK with alignment = 8, size = __ICFEDIT_size_proc_stack__ { };
define block HEAP       with alignment = 8, size = __ICFEDIT_size_heap__       { };
define block是關鍵字,HEAP是地址塊的名字,后面的with alignment = ,alignment= 是啥?with算是系統關鍵字
alignment,size等等是參數表,可以當做C++類的成員數據進行看待。EWARM_DevelopmentGuide.ENU使用
文檔的P-507頁中,有官方最詳細的說明,以下是官方例程:

不管怎么樣,我們有得到一些信息,定義一個block內存塊是比較復雜,但我們常用的堆和棧屬於內存塊。

 

 

【關鍵字:define section】  
do not initialize  { section .noinit };
do not initialize  { section USB_PACKET_MEMORY };

place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec };
section這個關鍵字,暫時叫它內存段吧,這個在類似STM32的ICF中,好像都是配合其它指令進行使用的,

下面看一下官方的使用:

 

 

 

 




【關鍵字:
初始化與不初始化

  

 

 

 

 

 

 這方面還是太復雜了,EWARM_DevelopmentGuide.ENU使用文檔的P-511頁中,有官方最詳細的說明.

 

【關鍵字:place at與place in

我們來看一下,官方譯文:

place at 指令將段和塊放置在特定地址或一個區域的開始或結束。
同一個地址不能用於兩個不同的信息也不可能使用空白區域指示。
如果放置在一個區域中,則段和塊將放置在任何其他區域之前,或塊放置在同一區域中,並在指令中放置一個位置。

 

 place in 指令將段和塊放置在特定區域中。 段 塊將以任意順序放置在該區域中。

 

  

 最后加入scmRTOS內的STM32用ICF文件:

/*###ICF### Section handled by ICF editor, don't touch! ****/
/*-Specials-*/
define symbol __ICFEDIT_intvec_start__ = 0x08000000;
/*-Memory Regions-*/
define symbol __ICFEDIT_region_ROM_start__   = 0x080000EC ;
define symbol __ICFEDIT_region_ROM_end__     = 0x0807FFFF;
define symbol __ICFEDIT_region_RAM_start__   = 0x20000000;
define symbol __ICFEDIT_region_RAM_end__     = 0x2000FFFF;
/*-Sizes-*/
define symbol __ICFEDIT_size_cstack__   = 0x800;
define symbol __ICFEDIT_size_heap__     = 0x800;
/**** End of ICF editor section. ###ICF###*/


define memory mem with size = 4G;
define region ROM_region   = mem:[from __ICFEDIT_region_ROM_start__   to __ICFEDIT_region_ROM_end__];
define region RAM_region   = mem:[from __ICFEDIT_region_RAM_start__   to __ICFEDIT_region_RAM_end__];

define symbol __region_USB_PKG_RAM_start__  = 0x40006000;
define symbol __region_USB_PKG_RAM_end__    = 0x400063FF;
define region USB_PKG_RAM_region = mem:[from __region_USB_PKG_RAM_start__ to __region_USB_PKG_RAM_end__];



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

initialize by copy { readwrite };
do not initialize  { section .noinit };
do not initialize  { section USB_PACKET_MEMORY };

place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec };
place in USB_PKG_RAM_region
                      { readwrite data section USB_PACKET_MEMORY  };
place in ROM_region   { readonly };
place in RAM_region   { readwrite,
                        block CSTACK, block HEAP };

細細品味吧!!

一些文獻:  http://blog.chinaunix.net/uid-29630160-id-4671567.html  

 

時間:2021-12-11

再研究define block:

define block HEAP      with alignment = 8, size = __ICFEDIT_size_heap__     { };
define block是地址塊關鍵字,HEAP是這個地址塊的名字,with是關鍵字,緊接后面就是地址塊的參數,上例程中配置了倆個參數:8字節對齊,空間大小。
with后面的參數不止這些,還有其他的參數:

size = expr                    // 自定義地址塊的大小
minimum size = expr    // 指定塊大小的下限,該塊是最小值,即使它的內容不會需要這么大
maximum size = expr   // 指定一個塊的大小上限。
expanding size             // 該塊將擴展以使用該塊中的所有可用空間 放置它的內存范圍 
alignment = expr          // 最小對齊方式,如果塊中的任何部分的對齊方式都高於最小對齊方式,則該塊將采用該對齊方式。

end alignment = expr   // 指定塊末端的最小對齊方式.一個塊的結束地址由它的起始地址及其內容大小, 但如果使用該參數,則結束地址增加為如果需要,請遵守指定的對齊方式。

fixed order                   // 按指定順序放置節。 每個 擴展選擇器被添加到一個單獨的嵌套塊中, 並且這些塊按指定的順序保存。
alphabetical order       // 按部分名稱的字母順序放置部分。
static base [basename]  //  指定名為 basename 的靜態基將 放置在塊的開頭或中間 塊,適用於特定的靜態基礎。 啟動代碼必須確保保存靜態的寄存器 base 被初始化為正確的值。 如果只有一個 靜態基,名稱可以省略。

 

哪么大擴號{}內,又是配置什么參數呢? 官方資料沒有細講,只有這個:

 

 我們只有except  section-selectors 這個信息,如下是實例:

define block tbss { section .tbss, section .tbss.* };
define block tdata { section .tdata, section .tdata.* };
define block tls { block tbss, block tdata };
define block tdata_load { copy of block tdata };
section是內存段,這些是在哪里呢?應該是IDE工具的一些設置項。
嘗試理解,選擇器選用內存段tbss(IDE設置的)為block,這個block名為TBSS(ICF的名字),其他不能做為block了。

我們是可以簡單的認為,去選擇一個section,做為一個block,希望這個理解不要有誤區!!!


再研究【關鍵字:不初始化
和初始化一樣的套路,先看這些代碼:
do not initialize                           { 
section .non_init,
                           section .non_init.*,
section .*.non_init,
section .*.non_init.* };

我不清楚“ non_init ” “ non_init.* ”  “ *.non_init ”  “ *.non_init.* ”  有什么本質區別,反正這些段沒初始化!!

相對要初始化的  initialize by symbol __SEGGER_init_heap     { block heap  };

 === END ===


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM