每一個芯片型號,都配置了專用的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 ===