每一个芯片型号,都配置了专用的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 ===