首先介绍几个概念: 1.ARM映像文件ARM映像文件是一个层次性结构的文件,其中包含了域(region)、输出段(output section)和输入段(input section)。各部分关系如下: - 一个映像文件由一个或多个域组成
- 每个域包含一个或多个输出段
- 每个输出段包含一个或多个输入段
- 各输入段包含了目标文件中的代码和数据
输入段中包含了4类内容:代码、已经初始化的数据、未经初始化的存储区域、内容初始化成0的存储区域。每个输入段有相应的属性,可以为只读的(RO)、可读写的(RW)以及初始化成0的(ZI)。ARM连接器根据各输入段的属性将这些输入段分组,再组成不同的输出段以及域。 一个输出段中包含了一系列的具有相同的RO、RW和ZI属性的输入段。输出段的属性与其中包含的输入段的属性相同。在一个输出段内部,各输入段是按照一定的规则排序的,这个后面再补充。 一个域中包含了1~3个输出段,其中各输出段的属性各不相同。各输出段的排列顺序是由其属性决定的。其中,RO属性的输出段排在最前面,其次是RW属性的输出段,最后是ZI属性的输出段。一个域通常映射到一个物理存储器上,如ROM和RAM等。 2.ARM映像文件各组成部分的地址映射分散加载机制允许为链接器指定映像的存储器映射信息,可实现对映像组件分组和布局的全面控制。分散加载通常仅用于具有复杂存储器映射的映像(尽管也可用于简单映像),也就是适合加载和执行时内存映射中的多个区是分散的情况。 要构建映像的存储器映射,链接器必须有:描述节如何分组成区的分组信息、描述映像区在存储器映射中的放置地址的放置信息。 分散加载区域分两类: - 加载区:该映像文件开始运行前存放的区域,即当系统启动或加载时应用程序存放的区域。
- 执行区:映像文件运行时的区域,即系统启动后,应用程序进行执行和数据访问的存储器区域,系统在实时运行时可以有一个或多个执行块。
3.分散加载文件(即scatter file,后缀为.scf)分散加载文件是一个文本文件,通过编写一个分散加载文件来指定ARM连接器在生成映像文件时如何分配RO,RW,ZI等数据的存放地址。如果不用SCATTER文件指定,那么ARM连接器会按照默认的方式来生成映像文件,一般情况下我们是不需要使用分散加载文件的。 但在某些场合,我们希望把某些数据放在指定的地址处,那么这时候SCATTER文件就发挥了非常大的作用。而且SCATTER文件用起来非常简单好用。 举个例子:比如像LPC2378芯片具有多个不连续的SRAM,通用的RAM是32KB,可是32KB不够用,我想把某个.C中的RW数据放在USB的SRAM中,那么就可以通过SCATTER文件来完成这个功能。 分散加载文件的语法: load_region_name start_address | "+"offset [attributes] [max_size]{ execution_region_name start_address | "+"offset [attributes][max_size] { module_select_pattern ["(" ("+" input_section_attr | input_section_pattern) ([","] "+" input_section_attr | "," input_section_pattern)) * ")"] }} - load_region: 加载区,用来保存永久性数据(程序和只读变量)的区域;
- execution_region: 执行区,程序执行时,从加载区域将数据复制到相应执行区后才能被正确执行;
- load_region_name: 加载区域名,用于“Linker”区别不同的加载区域,最多31个字符;
- start_address: 起始地址,指示区域的首地址;
- +offset: 前一个加载区域尾地址+offset 做为当前的起始地址,且“offset”应为“0”或“4”的倍数;
- attributes: 区域属性,可设置如下属性:
PI 与地址无关方式存放;
RELOC 重新部署,保留定位信息,以便重新定位该段到新的执行区;
OVERLAY 覆盖,允许多个可执行区域在同一个地址,ADS不支持;
ABSOLUTE 绝对地址(默认); - max_size: 该区域的大小;
- execution_region_name:执行区域名;
- start_address: 该执行区的首地址,必须字对齐;
- +offset: 同上;
- attributes: 同上;
PI 与地址无关,该区域的代码可任意移动后执行;
OVERLAY 覆盖;
ABSOLUTE 绝对地址(默认);
FIXED 固定地址;
UNINIT 不用初始化该区域的ZI段; - module_select_pattern: 目标文件滤波器,支持通配符“*”和“?”;
*.o匹配所有目标,* (或“.ANY”)匹配所有目标文件和库。 - input_section_attr: 每个input_section_attr必须跟随在“+”后;且大小写不敏感;
RO-CODE 或 CODE
RO-DATA 或 CONST
RO或TEXT, selects both RO-CODE and RO-DATA
RW-DATA
RW-CODE
RW 或 DATA, selects both RW-CODE and RW-DATA
ZI 或 BSS
ENTRY, that is a section containing an ENTRY point.
FIRST,用于指定存放在一个执行区域的第一个或最后一个区域;
LAST,同上; - input_section_pattern: 段名;
汇编中指定段:
AREA vectors, CODE, READONLY
C中指定段:
#pragma arm section [sort_type[[=]"name"]] [,sort_type="name"]*
sort_type: code、rwdata、rodata、zidata
如果“sort_type”指定了但没有指定“name”,那么之前的修改的段名将被恢复成默认值。
#pragma arm section // 恢复所有段名为默认设置。
应用:
#pragma arm section rwdata = "SRAM",zidata = "SRAM"
static OS_STK SecondTaskStk[256]; // “rwdata”“zidata”将定位在“sram”段中。
#pragma arm section // 恢复默认设置
样例: 简单存储器映射实例
|