基本概念
section與section屬性
section是包含數據段或者代碼段可放置在存儲器內的最小邏輯單位,section即可放在RAM也可放在ROM內。在通常的嵌入式應用中,放置在RAM中的section沒有任何內容,只是佔有該存儲空間。section具有如下屬性:
編譯器內部自定義section即屬性
iar中關於block的概念
The block directive defines a named set of sections. By defining a block you can create
empty blocks of bytes that can be used。
通過系統icf文件模板對堆棧快的定義
define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { };
可以看出,block定義的是一個地址快,對於大括號裏可以放置不同的section。創建一個block的目的在於能夠得到一個地址,大小等詳細信息的存儲空間。通常用來組織sections。也可以向STACK block一樣,像內存要了這麼一個空間,至於我要幹什麼編譯器你就不要管了。
IAR鏈接過程
- 決定哪些模塊需要包含到應用程序中。目標文件提供的模塊通常包含進去。
- 選擇鏈接目標文件用到的標準庫文件。
- 決定目標文件哪些section需要包含進來,沒有用到的自然不會包含進來。當然也可以通過特殊的編譯器指令如__root來使section鏈接到目標文件(及時程序中沒有用到)。
- 完成RAM中的代碼和變量的初始化。初始化指令可以讓鏈接器產生額外的代碼能夠copy ROM中的內容到RAM中。每個通過copy完成初始化的段被分成了兩個段,一個在ROM,一個在RAM。如果沒有人工初始化的話。鏈接器回自動產生啓動代碼來完成初始化。
- 通過 lcf文件的段放置指令來決定每個section存放的位置。
- 生成最終的包含可執行映像和調試信息的最終文件。在重定位輸入文件中,每個用到的section的內容是通過文件中的重定位信息和放置塊時的地址計算出來的。
- 最後生成map文件,包括了各個section的的在存儲器中的最終地址,global symbol的地址和用到的存儲器和庫彙總。
下圖是鏈接過程圖
icf文件
一個標準的icf文件內容
1、可編址的存儲空間(memory)
2、不同的存儲地址區域(region)
3、不同的地址塊(block)
4、已創建的section
5、section的存儲空間中的放置
icf示例
示例爲Energy Micro公司EFM32單片機EFM32G289F128提供的icf文件。EFM32G280F128單片機基於Cortex-M3內核。flash:128K, RAM:16K,
/* ---定義可編址的存儲空間 ---*/
define memory Mem with size = 4G;
/*--- 不同的存儲地址區域---*/
define region ROM = Mem:[from 0x00000 size 0x20000-1];
define region RAM = Mem:[from 0x20000000 size 0x4000-1];
/*--- 不同的地址塊:堆與棧 ---*/
define block CSTACK with size = 0x200, alignment = 8 { };
define block HEAP with size = 0x100, alignment = 8 { };
/* ---section 處理 ---*/
do not initialize { section .noinit };
initialize by copy { readwrite };
/* section的存儲空間中的放置 */
place at start of ROM { readonly section .cstartup };
place in ROM { readonly };
place in RAM { readwrite,
block STACK,
block HEAP }; /* Place .data, .bss, and .noinit and STACK */
編寫自己一個section
假如系統要存儲許多關鍵參數,我們把它們存儲在一個指定的ROM空間。
1、在icf文件定義自己的region,即參數存儲的固定位置
define symbol __ICFEDIT_region_MYREGION_start__ = (0X0001F000);
define symbol __ICFEDIT_region_MYREGION_end__ = (0x0001f000+0x00000FFF-1);
define region My_region = mem:[from __ICFEDIT_region_MYREGION_start__ to __ICFEDIT_region_MYREGION_end__];
2、在函數中聲明自己的section和定義變量或函數
變量
#pragma section ="MY_SECTION"
const char *pMyval = "password"; //---只能是全局變量
或者
#pragma section ="MY_SECTION"
#pragma location = "MY_SECTION"
const int alpha; //----只能是全局變量
—————————————————————————–
函數
void f(void) @ "MY_SECTION";
viod g(void) @ "MY_SECTION"
{
}
或者
#pragma location="MY_SECTION"
void h(void)
3、在icf文件中放置 MY_SECIOTN
place in My_region {
readonly section MY_SECTION,
};
4、在程序中獲得MY_SECTION的地址
char *p
#pragma section ="MY_SECTION"
p = __section_begin("MY_SECTION");