微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > 嵌入式软件开发之: 映像文件存储器映射调整

嵌入式软件开发之: 映像文件存储器映射调整

时间:08-30 来源:3721RD 点击:

入段的存储器属性相匹配的存储器访问属性(如果有);

· input_section_pattern。

13.4.3 Scatter文件典型用法

1.创建启动域

所谓启动域就是加载地址和执行地址相同的域。系统执行的初始入口点必须要在启动域中,否则链接器将报告以下错误。

Entry point (0x00000000) lies within non-root region ER_ROM

在Scatter文件中确定启动域可以使用下面两种方法。

① 使用ABSOLUTE设置执行区属性,并且对第一个执行区及其所在的加载区使用相同的地址。为确保执行域地址和加载域地址相同,可以将加载域的起始地址和执行域的起始地址设为相同的值或者将第一个执行域的地址偏移量设为0。

下面的例子,指定了一个启动域。

BOOT 0x0000 ;加载域的起始地址在0x0

{

EXER 0x0000 ;指定加载域和执行域的地址相同

{

* (+RO) ;必须将启动域包含在内

}

;其他执行域

}

② 使用FIXED执行域属性,确保指定域的载入地址和执行地址相同。

下面的例子显示了使用FIXED属性,将执行域的起始地址固定在ROM中。

BOOT 0x0000 ;加载域的起始地址在0x0

{

EXER 0x0000 ;指定加载域和执行域的地址相同

{

* (+RO) ;必须将启动域包含在内

}

EXER_INIT 0x8000 FIXED

{

init.o(+RO)

}

}

③ 如果使用分散加载,负责创建执行域的代码和数据不能将其自身复制到另一位置,因此启动域必须包含以下内容。

· _main.o和_scatter*.o:包含复制代码和数据的代码。

· Region$$Table和ZISection$$Table段:包含要复制代码和数据的地址。

· _dc*.o:执行代码压缩。

可以使用armlinker产生的InRoot$$Sections符号放置启动代码。因为这些代码被定义为只读属性,所有如果Scatter文件中包含了"* (+RO)",则表示启动域中包含了这些代码。或者显式的使用InRoot$$Sections符号在Scatter文件中对以上代码进行配置。

下面的例子显示了如何在Scatter文件中使用InRoot$$Sections链接符号,放置启动域。

LOADREG 0x8000 ;

{

ROOT 0x8000

{

* (InRoot$$Sections) ;放置启动域

}

OTHER 0x100000

{

* (RO,+RW,+ZI)

}

;其他Scatter文件描述

}

2.为执行域确定固定地址

可以在执行区分散加载描述中使用FIXED属性来创建根区,该根区在固定地址载入和执行。

FIXED可以用于在单一加载域内(因此通常用于单个ROM设备)创建多个根区。

例如,使用FIXED属性将函数或数据块(如常数表或校验和)放在ROM中的固定地址,这样就可以使用指针很方便的对其进行访问。

下面的例子显示了如何放置单个目标内容。

LOADREG1 0x0 0x10000

{

EXECREG1 0x0 0x1000 ;启动域,包含初始化代码

{ ;将初始化代码放在0x0地址

init.o (Init, +FIRST)

* (+RO) ;随后排放余下的只读数据

}

RAM 0x400000 0x2000 ;将可读可写数据放在0x400000地址

{

* (+RW +ZI)

}

DATABLOCK 0x4FF00 FIXED 0xFF ;执行域放在 0x4FF00地址

{ ;限制该域的最大长度为 0xFF

data.o(+RO-DATA) ;将只读数据放在0x1FF00 和 0x1FFFF之间

}

}

通过上面的Scatter文件,可以将初始化代码放在0x0处,其后是其他RO代码和除了data.o对象中的RO数据之外的所有RO数据;所有全局的RW变量放在RAM中0x400000处;最好将data.o的RO-DATA只读数据表放在地址0x4FF00处,并指定其最大长度为0xFF。

上例将代码或数据对象放在其各自的源文件中,然后放置目标文件域,这些操作方式是ARM公司建议的标准编码方式。为方便起见,可以使用编译指示#pragma和分散载入描述文件放置已命名的域。下面的例子创建模块dump.c并显式命名域。

// file dump.c

int a = 10; // 放入数据域

short b[100]; // 放入bss段

int const c[3] = {1,2,3}; // 放入.constdata段

int func1(int a) {return a*1;} // 放入.text段

#pragma arm section rwdata = "foo", code ="foo"

int x = 5; // 在foo的数据域

char *s = "abc"; // s3在code段, "abc" 在 .constdata

int func2(int x) {return x+1;} // 放入foo的.text段

#pragma arm section code, rwdata // 返回

使用下面的Scatter文

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top