木子剑
生命不熄,学习不止!

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

posted on 2021-12-08 11:30  木子剑  阅读(6584)  评论(0编辑  收藏  举报