为什么需要Scatter文件:
制定存储器映射(memory map)的方法基本上有二种,一是在link时使用命令行选项,并在程序执行前利用linker pre-define symbol使用汇编语言制定section的段初始化,二是使用scatter file,即采用“分散加载机制”。以上二种方法依应用程序的复杂度而定,一针对简单的情况,二针对复杂的情况。
手机属于复杂的情况,必须使用scatter file。
Scatter文件语法:
scatter文件是一个简单的文本文件,包含一些简单的语法(分号后面的内容是注释):
My_Region 0x0000 0x1000 ;区域名称 区起始地址 区长度
{
the context of region ;区内容
}
每个区由一个头标题开始定义,头中至少包含区的名字和起始地址,另外还有最大长度和其他一些属性选项。区定义的内容包括在紧接的一对花括号内,依赖于具体的系统情况。
一个加载区必须至少含有一个执行段;实践中通常有多个执行段。
一个执行区必须至少含有一个代码或数据段;这些通常来自源文件或库函数等的目标文件;通配符号*可以匹配指定属性项中所有没有在文件中定义的余下部分。
简单分散加载样例
图8所示样例中,只有一个加载区,包含了所有的代码和数据,起始地址为0。这个加载区一共对应两个执行段。一个包含所有的RO代码和数据,执行地址与装载地址相同;同时另一个起始地址为0x10000的执行段,包含所有的RW和ZI数据。这样当系统开始启动时,从第一个执行段开始运行(执行地址等于装载地址),在执行过程中,有一段初始化代码会把装载区中的一部分代码转移到另外的执行段中。
下面是这个scatter描述文件,该文件描述了上述存储器映射方式。
LOAD_ROM 0x4000
{
EXE_ROM 0x0000 0x4000
{
*〈+RO〉 ;所有代码、常量数据
}
RAM 0x10000 0x8000
{
*〈+RW,+ZI〉 ;所有非常量数据
}
}
在分散文件中放置对象
在大多数应用中,并不是像前例那样,简单地把所有属性都放在一起,用户需要控制特定代码和数据段的放置位置。这可以通过在scatter文件中对单个目标文件进行定义实现,而不是只简单地依靠通配符。
为了覆盖标准的连接器布局规则,我们可以使用+FIRST和+LAST分散加载指令。典型的例子是在执行段的开始处放置中断向量表格:
LOAD_ROM 0x0000 0x4000
{
EXEC_ROM 0x0000 0x4000
{
vectors.o〈Vect,+FIRST〉
*〈+RO〉
}
;moreexecregions...
}
在这个scatter文件中,保证了vextors.o中的Vect域被放置于地址0x0000。
一个实际的Scatter.txt详细分析
ROM 0x00 0x800000 ;名字为ROM的区,起始地址是0x00,区的长度是0x800000。区的名字是唯一的;MTK平台对第一个区的大小限制是8Mbytes
{
ROM 0x00 FIXED 0x3D8000 ;名称为ROM的执行段,该名称在所有执行段中是唯一的。段的起始地址是0x00,长度固定为0x3D8000.
{
bootarm.obj (C$$code,+First) ; First指把代码放到本段的起始地址处,C$$code的含义可能是一个块的名字.
*.obj (LEADING_PART,+First) ;含义应该是:把后缀名为.obj的文件的LEADING_PART块放到紧挨前面(即bootarm.obj的结尾处)的地方。
*.l (+RO) ;所有以.l为后缀的文件的可执行代码、常量放置在这里。
*bmt.lib (+RO) ;所有以bmt.lib结尾的文件的可执行代码、常量放置在这里。
*adaptation.lib (+RO)
*config.lib (+RO)
*custom.lib (+RO)
*drv.lib (+RO)
*fdm.lib (+RO)
*init.lib (+RO)
*kal.lib (+RO)
*l1_classb.lib (+RO)
*nucleus.lib (+RO)
*nucleus_int.lib (+RO)
*nucleus_debug.lib (+RO)
*stacklib.lib (+RO)
*sst.lib (+RO)
*tst.lib (+RO)
*mtkapp.lib (+RO)
*usb.lib (+RO)
;*j2me_hi.lib (+RO) ;这行语句被注释了,无效
*nvram.lib (+RO)
*nvram_sec.lib (+RO)
*ft.lib (+RO)
*irda.lib (+RO)
*fs.lib (+RO)
*media.lib (+RO)
*media_sec.lib (+RO)
*dsp_ram.lib (+RO)
;*plutommi.lib (+RO)
ScreenRotation.obj (+RO)
wingui.obj (+RO)
wgui_categories.obj (+RO)
;*media.lib (+RO)
png_decoder_sw.obj (PRIMARY_CODE) ; png_decoder_sw.obj文件中的PRIMARY_CODE块(可以是代码、数据)放在这里。
; *mmiresource.lib (+RO)
custNFBProgressImg.obj (+RO)
gui_wrapper.obj (+RO)
}
DYNAMIC_CODE2 0xA0018800 OVERLAY 0x2800 ;对照MT6228芯片的地址空间表,DYNAMIC_CODE2块将放在TCM中。
{
* (G3D_DYNAMIC_CODE, G3D_DYNAMIC_ZI) ;块G3D_DYNAMIC_CODE、G3D_DYNAMIC_ZI包含的代码、数据都放这。
}
DYNAMIC_CODE1 0xA001B000 OVERLAY 0x5000
{
* (AMR515_DYNAMIC_CODE, AMR515_DYNAMIC_ZI)
}
DYNAMIC_CODE3 0xA001B000 OVERLAY 0x5000
{
* (CTM_DYNAMIC_CODE, CTM_DYNAMIC_ZI)
}
DYNAMIC_CODE4 0xA001B000 OVERLAY 0x5000
{
* (G729_DYNAMIC_CODE, G729_DYNAMIC_ZI)
}
DYNAMIC_CODE5 0xA001B000 OVERLAY 0x5000
{
* (SBC_DYNAMIC_CODE, SBC_DYNAMIC_ZI)
}
PRIMARY_EXTSRAM 0x400000 FIXED 0x400000 ; 段的名字是PRIMARY_EXTSRAM,起始地址是0x400000,长度固定为0x400000。
{
*.l (+RW)
*bmt.lib (+RW)
*adaptation.lib (+RW) ;所有以adaptation.lib结尾的文件的可读写数据放到这里。
*config.lib (+RW)
*custom.lib (+RW)
*drv.lib (+RW)
*fdm.lib (+RW)
*init.lib (+RW)
*kal.lib (+RW)
*l1_classb.lib (+RW)
*nucleus.lib (+RW)
*nucleus_int.lib (+RW)
*nucleus_debug.lib (+RW)
*stacklib.lib (+RW)
*sst.lib (+RW)
*tst.lib (+RW)
*mtkapp.lib (+RW)
*usb.lib (+RW)
*j2me_hi.lib (+RW)
*nvram.lib (+RW)
*nvram_sec.lib (+RW)
*ft.lib (+RW)
*irda.lib (+RW)
*fs.lib (+RW)
*media.lib (+RW)
*media_sec.lib (+RW)
*dsp_ram.lib (+RW)
;*plutommi.lib (+RW) ;代码被注释了,无效
ScreenRotation.obj (+RW)
wingui.obj (+RW)
wgui_categories.obj (+RW)
; *mmiresource.lib (+RW)
custNFBProgressImg.obj (+RW)
gui_wrapper.obj (+RW)
; ZI chunk
* (+ZI) ;其他所有文件中的数据都放这,且开机时会把这些数据清零。
}