icf是链接配置文件(Linker configuration file)后缀名。
stm32固件库中存放路径为:
STM32F0xx_StdPeriph_Lib_V1.5.0\Projects\STM32F0xx_StdPeriph_Templates\EWARM\
如下图所示:;
文件配置内容有:
- ROM地址空间、大小和sections
- RAM地址空间、大小和sections
- 中断向量表地址空间
- 堆地址空间和大小
- 栈地址空间和大小
举例如下:
- ROM地址空间、大小和sections
/*-Memory Regions-*/ define symbol __ICFEDIT_region_ROM_start__ = 0x08000000 ; define symbol __ICFEDIT_region_ROM_end__ = 0x0800FFFF;
- RAM地址空间、大小和sections
define symbol __ICFEDIT_region_RAM_start__ = 0x20000000; define symbol __ICFEDIT_region_RAM_end__ = 0x20001FFF;
- 中断向量表地址空间
/*-Specials-*/ define symbol __ICFEDIT_intvec_start__ = 0x08000000;
- 堆地址空间和大小
define symbol __ICFEDIT_size_heap__ = 0x100;
- 栈地址空间和大小
/*-Sizes-*/ define symbol __ICFEDIT_size_cstack__ = 0x200;
以上几部分本来由ICF editor编辑的,在代码中也有禁止编辑的提示,完整代码如下:
/*###ICF### Section handled by ICF editor, don't touch! ****/
/*-Editor annotation file-*/
/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\cortex_v1_0.xml" */
/*-Specials-*/
define symbol __ICFEDIT_intvec_start__ = 0x08000000;
/*-Memory Regions-*/
define symbol __ICFEDIT_region_ROM_start__ = 0x08000000 ;
define symbol __ICFEDIT_region_ROM_end__ = 0x0800FFFF;
define symbol __ICFEDIT_region_RAM_start__ = 0x20000000;
define symbol __ICFEDIT_region_RAM_end__ = 0x20001FFF;
/*-Sizes-*/
define symbol __ICFEDIT_size_cstack__ = 0x200;
define symbol __ICFEDIT_size_heap__ = 0x100;
/**** End of ICF editor section. ###ICF###*/
这些起始、结束地址、大小也可以在IAR工程中进行配置,配置地方如下截图:
对于每个芯片器件,iar有默认的icf目录对应每一种器件,但是可以由用户自行配置,勾选Override default之后即可覆盖默认icf文件。
- 默认icf配置文件如下截图所示:
配置不同数据块有大有小,由小到大为section、block、region 。
将section放在block里,将block放在region里。
以下region配置代码ROM和RAM的大小:
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__];
以下block配置代码定义了堆和栈的大小:
define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { };
define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { };
以下代码定义了region的读写属性,以及包含的block,ROM为只读,RAM为读写并包含CSTACK和HEAP:
place in ROM_region { readonly };
place in RAM_region { readwrite, block CSTACK, block HEAP };
IAR链接过程
1、链接需要的文件
2、完成RAM中的代码和变量的初始化。初始化指令可以让链接器产生额外的代码能够copy ROM中的内容到RAM中。每个通过copy完成初始化的段被分成了两个段,一个在ROM,一个在RAM。如果没有人工初始化的话。链接器回自动产生启动代码来完成初始化。
3、通过 icf文件的段放置指令来决定每个section存放的位置。
4、生成最终的包含可执行映像和调试信息的最终文件。
5、最后生成map文件,包括了各个section的的在存储器中的最终地址,global symbol的地址和用到的存储器和库汇总。
完整icf文件注释,以stm32f051_flash.icf为例
/*###ICF### Section handled by ICF editor, don't touch! ****/
/*-Editor annotation file-*/
/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\cortex_v1_0.xml" */
/*-Specials-*/
/* 符号常量定义,定义中断向量表地址 */
define symbol __ICFEDIT_intvec_start__ = 0x08000000;
/*-Memory Regions-*/
/* 符号常量定义,ROM和RAM的起始结束地址 */
define symbol __ICFEDIT_region_ROM_start__ = 0x08000000 ;
define symbol __ICFEDIT_region_ROM_end__ = 0x0800FFFF;
define symbol __ICFEDIT_region_RAM_start__ = 0x20000000;
define symbol __ICFEDIT_region_RAM_end__ = 0x20001FFF;
/*-Sizes-*/
/* 符号常量定义,定义栈和堆的大小 */
define symbol __ICFEDIT_size_cstack__ = 0x200;
define symbol __ICFEDIT_size_heap__ = 0x100;
/**** End of ICF editor section. ###ICF###*/
/* 定义可编址的存储空间 */
define memory mem with size = 4G;
/* 定义ROM region和RAM 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__];
/* 导出符号常量,在.c .h源文件中可使用 */
export symbol __ICFEDIT_region_RAM_start__;
export symbol __ICFEDIT_region_RAM_end__;
/* 定义栈block和堆block的大小,8字节对齐 */
define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { };
define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { };
/* section处理,RW类型数据复制到RAM中,即启动时数据初始化 */
initialize by copy { readwrite };
/* .noinit类型的section不需要初始化 */
do not initialize { section .noinit };
/* 定义中断向量表地址及属性,属于section,只读,放在ROM中,需要初始化 */
place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec };
/* 定义ROM_region region只读,放在ROM中 */
place in ROM_region { readonly };
/* 定义RAM_region,读写属性,放在RAM中,包括block CSTACK和block HEAP */
place in RAM_region { readwrite,
block CSTACK, block HEAP };
添加额外的region
- 比如我要添加另一个名为ROM2的ROM区域,大小是256bytes,起始地址是0x80000.
define region ROM = Mem:[from 0x80000 size 0x100];
- 放置section
define region CONST_region = Mem:[from 0x100 size 0x100];
place in CONST_region{readonly section .rodata}
/* 这段语句相当于一个标志位,使的以 ILOADER 声明的代码放在如下空间内,具体声明方式如下:
#pragma location = "ILOADER"
__root const unsigned char RBL_Code[] = {
0x00, 0x04, 0x00, 0x20, 0x85, 0x2C, 0x00, 0x08, 0x9D, 0x2C, 0x00, 0x08, 0x9F, 0x2C, 0x00, 0x08,
0xA1, 0x2C, 0x00, 0x08, 0xA3, 0x2C, 0x00, 0x08, 0xA5, 0x2C, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA7, 0x2C, 0x00, 0x08,
};
*/
define region ILOADER_region = mem:[from 0x08000000 to 0x08003FFF];
place in ILOADER_region { readonly section ILOADER };