文档库 最新最全的文档下载
当前位置:文档库 › scatter分析

scatter分析

问题分析:

分散加载描述文件是一个文本文件,它向链接器描述目标系统的存储器映射。如果通过命令行使用链接器,则描述文件的扩展名并不重要。分散加载文件指定:

1)每个加载区的加载地址和最大尺寸;

2)每个加载区的属性;

3)从每个加载区派生的执行区;

4)每个执行区的执行地址和最大尺寸;

5)每个执行区的输入节。

从描述文件的格式中就可以看出加载区、执行区和输入节的层次关系。

问题解答:

程序正确编译生成目标文件以后, 就会链接成可执行的文件, 这个过程中要用到分散加载文件, 它决定可执行的代码在存储器中存放的位置, 这在复杂的程序(例如VIVI对Linux内核的引导)中是很重要的. 下面是一个简单的分散加载文件的例子:

; *************************************************************
; *** Scatter-Loading Description File generated by uVision ***
; *************************************************************
;Run in Flash

LR_ROM1 0x00000000 { ; load region
ER_ROM1 0x00000000 0x0200000 { ; load address = execution address
*.o (RESET, +First)
*(InRoot$$Sections)
.ANY (+RO)
}
RW_RAM1 0x30000000 0x4000000 { ; RW data
.ANY (+RW +ZI)
}
RW_IRAM1 0x40000000 0x00001000 {
.ANY (+RW +ZI)
}
}
在上面的例程中, 代码从地址0x00000000处开始存放,并且将RESET程序段放在最开始处, 而可读写的数据从地址0x30000000处开始存放. 分散加载文件的段的名字(例如LR_ROM1, ER_ROM1等)可以是任意的名字。





ADS分散加载文件语法:
;加载域书写格式:
;加载域名称 起始地址 属性(可省略) 最大长度(可省略)
;
;加载域起始地址:可以使用绝对地址和偏移地址
;加载域属性: ABSOLUTE:绝对地址,默认属性,不允许加载域互相重叠
; PI:位置无关,允许加载域互相重叠
; RELOG:重定位,允许加载域互相重叠,执行域没有本属性但可以继承加载域的属性
; OVERLAY:覆盖,允许加载域互相重叠,可以在相同地址上建立多个执行域,ADS不支持本属性
;加载域包含1个或多个执行域

;执行域书写格式:执行域名称 起始地址 属性(可省略) 最大长度(可省略)
;
;执行域起始地址:可以使用绝对地址和偏移地址,使用偏移地址(要求可以被4整除的数)的执行域不能指定属性
;执行域属性:
; ABSOLUTE:绝对地址,默认属性,不允许执行域互相重叠
; FIXED:固定地址,加载和执行都是同一地址,必须使用绝对地址或0偏移地址
; PI:位置无关,允许执行域互相重叠
; OVERLAY:覆盖,允许执行域互相重叠
; UNINIT:未初始化,ZI

段将不会被初始化为0,仅仅保留了内存单元,而没有将各初始写入内存单元,或者将内存单元初始化为0

;执行域包含1个或多个输入段

;输入段书写格式:包括模块描述和段描述
;
;模块描述:指定包含模块的文件(包括目标文件.o和库文件.LIB)搜索范围,可以使用通配符*和?
; *.o(所有目标文件)
; *(所有目标文件和库文件)
; .ANY(所有文件)不论放在文件哪个位置,本描述被最后解析,相当于“剩下的所有文件”
;
;模块:汇编用AREA声明的段,例如AREA StackBottom, DATA, NOINIT
; C中指定段:#pragma arm section rwdata = "SRAM",zidata = "SRAM"
;
;段描述:包括属性描述和段名描述
;
;属性描述:(+ 属性)
; RO:只读代码段+数据段,也可表达为TEXT
; RO-CODE:只读代码段
; RO-DATA:只读数据段
; RW:读写代码段+数据段,也可表达为DATA
; RW-CODE:读写代码段
; RW-DATA:读写数据段
; ZI:初始化为0的数据段,也可表达为BSS
; ENTRY:包含入口点的输入段
;伪属性:FIRST:放在最前
; LAST:放在最后
;
;段名描述:(输入段名)只能用在汇编语言中


;周立功的例程总共三个分散加载文件mem_a.scf,mem_b.scf,mem_c.scf,区别是加载地址不一样
;具体加载哪个,在DebugInExram->ARM Linker->Scatter定义,链接类型选择Scattered

ROM_LOAD 0x0 ;ROM_LOAD 为加载域的名称,其后面的0x0 表示加载域的起始地址(存放程序代码的起始地址)
;image entry point一定要跟ROM_LOAD值一样
{
ROM_EXEC 0x00000000 ;ROM_EXEC 描述了执行域的地址,放在第一块位置定义
{
Startup.o (vectors, +First) ;从起始地址开始放置向量表(Startup.o 为Startup.s 的目标文件)
;+First表示Vector段放在最前面

* (+RO) ;接着放置其它代码(* 是通配符,类似WINDOW下搜索用的通配符)
}

IRAM 0x40000000 ;变量域IRAM ,内部RAM的起始地址为0x40000000
{

Startup.o (MyStacks) ;放置Startup.o (MyStacks)
}

STACKS_BOTTOM +0 UNINIT ;+0表示接着上一段,UNINIT 表示不初始化
{

Startup.o (StackBottom) ;放置AREA StackBottom, DATA, NOINIT
}

STACKS 0x40004000 UNINIT ;接着从0x40004000 开始,放置 AREA Stacks, DATA, NOINIT UNINIT 表示不初始化
{
Startup.o (Stacks)
}

ERAM 0x80000000 ;外部RAM从0x80000000开始为变量域
;如果片外RAM起始地址不为0x8000 0000,则需要修改mem_.scf文件
{
* (+RW,+ZI)
}
HEA

P +0 UNINIT ;+0表示接着上一段,UNINIT 表示不初始化
{
Startup.o (Heap) ;放置堆底, AREA Heap, DATA, NOINIT
}
HEAP_BOTTOM 0x80080000 UNINIT ;接着在外部0x80080000 放置堆顶
;这个地址是片外RAM 的结束地址,根据实际情况修改
{
Startup.o (HeapTop)
}
}

“PI” 属性使用示例:
LR_1 0x010000 PI ; 加载域起始地址0x010000.
{
ER_RO +0 ; 执行域从加载区继承PI属性
; 默认执行域起始地址是0x010000, 在此处可以被移动
{
*(+RO) ; 所有RO段.
}
ER_RW +0 ABSOLUTE ; PI属性被ABSOLUTE取代
{
*(+RW) ; RW被紧接着放置,不能移动
}
ER_ZI +0 ; ER_ZI执行域在ER_RW执行域后面
{
*(+ZI) ; 所有ZI段被连续放置
}
}

LR_1 0x010000 ; 加载域起始地址0x010000.
{
ER_RO +0 ; 执行域从加载区继承ABSOLUTE属性
; 默认执行域起始地址是0x010000, 在此处不能移动
{
*(+RO) ; 所有RO段.
}
ER_RW 0x018000 PI ; PI属性取代ABSOLUTE
{
*(+RW) ; RW被放置在0x018000,在此处可以被移动
}
ER_ZI +0 ; ER_ZI执行域在ER_RW执行域后面
{
*(+ZI) ; 所有ZI段被连续放置
}
}





ADS分散加载文件使用总结(lpc23xx)
文章发表于:2009-03-23 17:38


有如下分散加载文件:

ROM_LOAD 0x00000000 ;// Origination Point of Code (Code in Flash)
{
ROM_EXEC 0x00000000 ;// Origination Point of Executing
{
Startup.o (vectors, +First)
* (+RO)
}
IRAM 0x40000040 ;// Origination Point of Internal SRAM
{ ;// 0x40000000 ~ 0x4000003F for Vector
Startup.o (MyStacks)
}
STACKS_BOTTOM +0 UNINIT
{
Startup.o (StackBottom)
}
STACKS 0x40004000 UNINIT ;// End Point of Internal SRAM

{

Startup.o (Stacks)

}
{ERAM 0x81000000 ;// Origination Point of External SRAM
{
* (+RW,+ZI)
}
HEAP +0 UNINIT

Startup.o (Heap)
}
HEAP_BOTTOM 0x81800000 UNINIT ;// End Point of External SRAM
{
Startup.o (HeapTop)
}
}
其中, ROM_LOAD为加载区的名称,其后面的0x00000000表示加载区的起始地址(存放程序代码的起始地址),也可以在后面添加其空间大小,如“ROM_LOAD 0x00000000 0x20000”表示加载区起始地址为0x00000000,大小为128K字节;ROM_EXEC描述了

执行区的地址,放在第一块位置定义,其起始地址、空间大小与加载区起始地址、空间大小要一致。从起始地址开始放置向量表(即Startup.o(vectors,+First),其中Startup.o为Startup.s的目标文件),接着放置其他代码(即映像文件)(即 *(RO));变量区IRAM的起始地址为0x4000000040,放置Startup.o(MyStacks);变量区ERAM的起始地址为0x80000000,放置出Startup.o文件之外的其他文件的变量(即 *(+RW,+ZI));紧靠ERAM变量区之后的是系统堆空间(HEAP),放置描述为Startup.o(Heap);堆栈区STACKS使用片内RAM,由于ARM的堆栈一般采用满递减堆栈,所以堆栈区的起始地址设置为0x40004000,放置描述为Startup.o(Stacks)

2.使用地址不连续的内存(LPC2368)

Lpc2368一共有56K的RAM,其中通用Ram32K,地址为0x40000000~0x40007fff;8KB的USB专用RAM,地址0x7fd00000~0x7fd01ffff;16KB Ethernet专用RAM,地址为0x7fe00000~0x7fe03fff;以上的USB和Ethernet专用RAM也可用做通用RAM,需要做如下设置:(1)target.c中将USB和Ethernet功能打开,需要设置PCONP寄存器,详见Datasheet。(2)设置分散加载文件,分配这两段内存。

在DebugInRam模式下,有如下分散加载文件:

ROM_LOAD 0x40000000
{
ROM_EXEC 0x40000000 //加载映像文件(通用RAM首地址)
{
Startup.o (vectors, +First)
* (+RO)
}
IRAM 0x40007000 //用户堆栈
{
Startup.o (MyStacks)
}
STACKS 0x40008000 UNINIT //系统堆栈
{
Startup.o (Stacks)
}
ERAM 0x7fe00000 /*变量,放置与Ethernet专用RAM首地址*/
{
* (+RW,+ZI)
}
HEAP +0 UNINIT
{
Startup.o (Heap)
}
}

3.分散使用Flash地址(LPC2368)

项目中,要求将片内Flash起始几个扇区空出来留作他用,或者当用到的Flash地址不连续的时候,都可用以下方法来编写分散加载文件:

ROM_LOAD 0x00000000
{
ROM_EXEC 0x00000000 /*中断向量表*/
{
Startup.o (vectors,+First)
}
。。。
}
ROM_LOAD1 0x00004000 //加载映像文件,从第四个扇区开始
{
ROM_EXEC1 0x00004000
{
* (+RO)
}
}
值得注意的是,中断向量表必须放在flash起始地址处,否则无法启动。根据以上分散加载文件编译生成的Hex文件会有两个,分别如下:

Hex1:
:020*********FA
:1000000018F09FE518F09FE518F09FE518F09FE5C0
。。。

Hex2:
:020*********FA
:1040000090808FE20F0098E8080080E0081081E0BF
。。。

可以看出,生成的两段Hex文件的起始地址是不同的,其中一段为中断向量表;另一段为用户映像文件。

4.固定变量内存地址

嵌入式开发中,有时会需要在同一片内的不同段程序(比如Bootloader

和主程序间)间传递数据,这时候往往需要固定变量地址。一般来言,C语言编写的程序,变量地址是由C编译器来分配内存的,程序员无法实现知道变量地址。而ADS中的分散加载文件可以告知编译器,固定某些变量的地址,如下:

ROM_LOAD 0x00000000
{
ROM_EXEC 0x00000000
{
Startup.o (vectors, +First)
* (+RO)
}
RAM 0x40000000 UNINIT //Mfile.c中的所有变量地址从0x40000000开始
{
Mfile.O(+RW,+ZI)
}
IRAM 0x40000010
{
Startup.o (MyStacks)
* (+RW,+ZI)
}
HEAP +0 UNINIT
{
Startup.o (Heap)
}
STACKS 0x40004000 UNINIT
{
Startup.o (Stacks)
}
}


上述分散加载文件固定了Mfile.c中变量的起始地址,以这种方法,可以固定任何全局变量的地址,以便其被其他系统访问。


相关文档
相关文档 最新文档