嵌入式软件开发之: 映像文件存储器映射调整
如何在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文件指定上面的代码在内存中的放置位置。如果代码和数据段的名称相同,则首先放置代码段。
FLASH 0x10000000 0x2000000
{
FLASH 0x10000000 0x2000000
{
init.o (Init, +First) ; 放置初始化代码
* (+RO) ;
}
RAM 0x0000
{
vectors.o (Vect, +First) ; 放置向量表
* (+RW,+ZI) ;
}
DUMP 0x08000000
{
dump.o (foo) ;
}
}
通过上面的Scatter文件,将init中的初始化段放在0x10000000地址,并将除foo外的只读数据func1和c[]放在该初始段的后面;接下来的执行域RAM放置向量表;最后的DUMP域放置由#pragma指定的段dump。
3.在代码映像中保留空白域
可以在Scatter中使用 EMPTY 属性为栈保留一个空白存储器块。该存储块不构成载入区的一部分,但指定在执行时使用。由于它创建为虚 ZI区,所以 armlink 使用以下符号访问它:
· Image$$region_name$$ZI$$Base;
· Image$$region_name$$ZI$$Limit;
· Image$$region_name$$ZI$$Length。
如果指定的长度为负值,则Image$$region_name$$ZI$$Limit被视为域的结束地址。它是绝对地址,不是相对地址。下面例子显示了如何在Scatter文件中预留一个空白区域。
LOADREGION 0x700000 ; 加载域的起始地址在0x700000
{ ;
STACK 0x7000000 EMPTY –0x10000 ; 该域的结束地址为0x700000,因为其长度为负
;
region
;
{
; 预留空白区放置栈
}
HEAP +0 EMPTY 0x10000 ; 栈的起始地址在上个预留区域介绍地址
;
;
{
; 预留空白区域放置堆
}
; rest of scatter description...
}
在上面的例子中定义了一个执行域STACK 0x7000000 EMPTY -0x10000,它从地址 (0x7000000-0x1000)开始,在地址0x7000000结束。
在此示例中,链接程序生成符号:
Image$$STACK$$ZI$$Base = 0x6ff0000
Image$$STACK$$ZI$$Limit = 0x7000000
Image$$STACK$$ZI$$Length = 0x1000
Image$$HEAP$$ZI$$Base = 0x7000000
Image$$HEAP$$ZI$$Limit = 0x7010000
Image$$HEAP$$ZI$$Length = 0x1000
EMPTY属性仅适用于执行区。如果在载入区定义中使用EMPTY属性,则链接程序生成警告信息并忽略该属性。链接程序检查用于EMPTY区的地址空间不与任何其他执行区重叠。
4.使用OVERLAY关键字
在ARM以前的编译器中,没有提供地址空间的重叠管理。如果有运行时域地址空间重叠,需要用户自己提供地址空间重叠的管理机制。但在RVDS的编译器中,提供了运行时域属性关键字OVERLAY,用户可以
- 基于DSP的导弹仿真器嵌入式组件设计(04-30)
- 为嵌入式软件建立统一软件系统框架的方法详介(05-23)
- 在VIM中实现对嵌入式软件的调试(08-06)
- 基于仿真的嵌入式软件白盒覆盖测试系统设计(08-26)
- 嵌入式软件运行剖面建模及测试用例生成(11-06)
- 嵌入式软件与硬件的集成测试过程研究(11-16)