scatter文件的写法.pdf
《scatter文件的写法.pdf》由会员分享,可在线阅读,更多相关《scatter文件的写法.pdf(80页珍藏版)》请在一课资料网上搜索。
1、scatter 文件的写法程序总有两种状态:运行态和静止态。当系统掉电的时候程序需要被保存在非易失性的存储器中,且这个时候程序的排放是按照地址依次放的,换句话说:我才懒得管它怎么放,只要不掉就行。当系统上电后,CPU 就要跑起来了,CPU 属于高速器件,存储器总是不怎么能跟得上,既然跟不上那么我们就尽量缩短它们之间的差距,那留下一条路,那就是尽量提高存储器的读取速度,存储器类型决定其速度的水平,那么尽量放在速度高的存储器就成为首选解决方案。那么我们就把要执行的程序暂时拿到速度较快的 RAM中。那么拿的过程就牵涉到程序的加载了。这就是要解决的问题。一个映像文件由域(region)、输出段(out
2、put sections)和输入段(input sections)组成。不要想得太复杂,其实他们之间就是包含与被包好的关系。具体关系是这样的:映像文件 域 输出段 输入段输入段:输入段:输入段就是我们写的代码+初始化的数据+应该被初始化为 0 的数据+没有初始化的数据,用英文表示一下就是:RO(ReadOnly),RW (ReadWrite),ZI(ZeroInitialized),NOINIT(Not Initialized)。ARM 连接器根据各个输入段不同的属性把相同的拿再一起组合一下就成为了输出段。请看看平时写的东东:AREARESET, CODE, READONLYAREADSEG1
3、, DATA, READWRITEAREAHEAP, NOINIT, READWRITE看出其属性没?输出段:输出段:为了简化编译过程和更容易取得各种段的地址,那么把多个同属性的输入段按照一定的规律组合在一起,当然这个输出段的属性就和它包含的输入段的属性一样咯。输入段的排放规律就是:最先排放 RO 属性的输入段,然后是 RW 属性段,最后是 ZI 或 NOINIT 段。域:域:为什么还要加一层域,我的理解是由于代码的功能不同,那么我们有必要把不同功能的代码分类放。我们可以把需要高速执行的代码放在一起、把对速度要求不高的放在一起、把执行频率高的放在一起,把执行频率低的放在一起.那么按照这种方式放
4、的代码就可以根据其具体需要放在不同的存储器中了。这样可以提高程序执行速度。一个域中包含 13 个输出段。映像文件:映像文件:我暂时把映像文件理解成烧到存储器中的文件,由 N 个域组成。这些域其实可以看做是独立的模块,只是他们按照一定的顺序(这个顺序还是:RO+RW+ZI)被捆绑在一起,这样才方便烧写到非易失存储器中去。好了,了解了映像文件的组成,那么来看看映像文件是怎么跑起来的。映像文件就是有 N 节车厢的火车,车厢(域)里装着要送到不同站(不同类型的存储器)的货物。到相应的站了,那么就把相应的车厢拿下来。指挥拿这个的就是 scatter 文件。拿下货物车厢后,我们就解开它,把里面的品牌为 R
5、O 的货物提取出来,按照 scatter 的指示发给某个地址,然后再先后把品牌为 RW和 ZI 的货物发到 scatter 指定的地址。看看这个加深理解:LOAD_ROM10X00000000; 从火车上取出来时的地址(如:成都站)EXEC_ROM10 x40000000PROGRAM.O(+RO);把品牌 RO 的货物发给 0 x40000000去RAM10 x80000000PROGRAM.O(+RW,+ZI);把品牌 RW,ZI 的货物依次发给 0 x80000000.其他的段也可以这样依葫芦画瓢。scatter 的原理就介绍这样,其中的语法和规则要多写多把代码的地址拖出来看才能体会。不
6、过都是很简单的,生活中的小常识就能解决这些问题。为什么?因为设计这些规则的工程师的灵感就是源自生活。嘿嘿.享受把代码随处放的乐趣吧,.enjoy.scatterloadingscatterloading实际的嵌入式系统中,ADS 提供的缺省存储器映射是不能满足要求的。用户的目标硬件通常有多个存储器设备位于不同的位置,并且这些存储器设备在程序装载和运行时可能还有不同的配置。Scatterloading 可以通过一个文本文件来指定一段代码或数据在加载和运行时在存储器中的不同位置。这个文本文件 scatterfile 在命令行中由-scatter 开关指定,例如:armlink_scattersca
7、t.scffilel.ofile2.0在 scatterfile 中可以为每一个代码或数据区在装载和执行时指定不同的存储区域地址,Scatlertoading 的存储区块可以分成二种类型:装载区:当系统启动或加载时应用程序的存放区。执行区:系统启动后,应用程序进行执行和数据访问的存储器区域,系统在实时运行时可以有一个或多个执行块。映像中所有的代码和数据都有一个装载地址和运行地址(二者可能相同也可能不同,视具体情况而定)。在系统启动时,C 函数库中的_main 初始化代码会执行必要的复制及清零操作,使应用程序的相应代码和数据段从装载状态转入执行状态。1.scatter 文件语法scatter 文
8、件是一个简单的文本文件,包含一些简单的语法。My_Region 0 x0000 0 x1000the context of region每个块由一个头标题开始定义,头中至少包含块的名字和起始地址,另外还有最大长度和其他一些属性选项。块定义的内容包括在紧接的一对花括号内,依赖于具体的系统情况。一个加载块必须至少含有一个执行块;实践中通常有多个执行块。一个执行块必须至少含有一个代码或数据段;这些通常来自源文件或库函数等的目标文件;通配符号*可以匹配指定属性项中所有没有在文件中定义的余下部分。2.简单分散加载样例图 8 所示样例中,只有一个加载块,包含了所有的代码和数据,起始地址为 0。这个加载块一
9、共对应两个执行块。一个包含所有的 RO 代码和数据,执行地址与装载地址相同;同时另一个起始地址为0 x10000 的执行块,包含所有的 RW 和 ZI 数据。这样当系统开始启动时,从第一个执行块开始运行(执行地址等于装载地址),在执行过程中,有一段初始化代码会把装载块中的一部分代码转移到另外的执行块中。下面是这个 scatter 描述文件,该文件描述了上述存储器映射方式。LOAD_ROM 0 x4000EXE_ROM 0 x0000 0 x4000;Rootregion+RO;AllcodeandconstantdataRAM 0 x10000 0 x8000*+RW,+ZI;Allnon-c
10、onstantdata3.在分散文件中放置对象在大多数应用中,并不是像前例那样,简单地把所有属性都放在一起,用户需要控制特定代码和数据段的放置位置。这可以通过在 scatter 文件中对单个目标文件进行定义实现,而不是只简单地依靠通配符。为了覆盖标准的连接器布局规则,我们可以使用+FIRST 和+LAST 分散加载指令。典型的例子是在执行块的开始处放置中断向量表格:LOAD_ROM 0 x0000 0 x4000EXEC_ROM 0 x0000 0 x4000vectors.oVect,+FIRST*+RO;moreexecregions.在这个 scatter 文件中,保证了 vextors
11、.o 中的 Vect 域被放置于地址0 x0000。4.RootRegion(根区)根区是一个执行块,它的加载地址与执行地址是一致的。每个 scatter 文件至少有一个根区。分散加载有一个限制:创建执行块的代码和数据(即完成复制和清零的代码和数据)无法自行复制到另一个位置。因此,在根区中必须含有下面的部分:_main.o,包含复制代码/数据的代码;连接器输出变量$Table 和 ZISection$Table,包含被复制代码/数据的地址。由于上面两个部分的属性是只读的,因此他们被*+RO通配符语法匹配。如果*+RO被用在了非根区中,则在根区中必须显式地指明另一个 RO 区域。下面是一个例子:
12、LOAD_ROM 0 x0000 0 x4000EXE_ROM 0 x0000 0 x4000;rootregion_main.o+RO;copyingcode*Region$Table;RO/RWaddressestocopy*ZISection$Table;ZIaddressestozeroRAM 0 x10000 0 x8000*+RO;allotherROsections*+RW,+ZI;allRWandZIsectionsScatterScatter 文件编写文件编写ScatterScatter 文件编写文件编写一个映像文件中可以包含多个域(region),在加载和运行映像文件时,每
13、个域可以有不同的地址。每个域可以包括多达 3 个输出段,每个输出段是由若干个具有相同属性的输入段组成。这样在生成映像文件时,ARM 链接器就需要知道下述两个信息。分组信息决定各域中的输出段是由哪些输入段组织而成;定位信息决定各域在存储空间中的起始地址。根据映像文件中地址映射的复杂程度,有两种方法来告诉 ARM 链接器这些相关的信息。对于映像文件中地址映射关系比较简单的情况,可以使用命令行选项;对于映像文件中地址映射关系比较复杂的情况,可以使用一个 scatter 配置文件。Scatter 文件又称为分散加载文件,将重点讲解如何编写 scatter文件。1 1、ScatterScatter 文件
14、结构文件结构Scatter 文件是一个文本文件,使用 BNF 语法来描述 ARM 链接器生成映像文件时所需要的信息。具体来说,在 scatter 文件中可以指定下列信息:各个加载时域的加载时起始地址、最大尺寸和属性;每个加载时域包含的输出段;各个输出段的运行时起始地址、最大尺寸、存储访问特性和属性;各个输出段中包含的输入段。一个 Scatter 文件包含若干个加载域,一个加载域包含若干个输出段,一个输出段由若干个具有相同属性的输入段组成,其结构如图 1 所示。图 1 Scatter 文件结构示意图 加载时域的描述加载时域的描述加载时域包括名称、起始地址、属性、最大尺寸和一个运行时域的列表。使用
15、 BNF 语法描述,加载时域的格式如下所示:Load_namebase_designatorattributemax_sizeLoad_name运行时域名称,它除了唯一地标识一个运行时域外,还用来构成链接器生成的链接符号;base_designator 用来表示本加载时域的起始地址,它可以有两种格式表示:起始地址或偏移量;attribute本加载时域的属性,其可能的取值为下面之一,默认的取值为 ABSOLUTE:oPI位置无关属性;oRELOC重定位;oABSOLUTE绝对地址;max_size 最大尺寸,如果本加载时域的实际尺寸超过了该值,链接器将报告错误。默认的取值为0 xFFFFFFFF
16、。 输出段的描述输出段的描述输出段包括名称、起始地址、属性、最大尺寸和一个输入段的集合。使用 BNF 语法描述,输出段的格式如下所示:output_namebase_designatorattributemax_sizeoutput_name 输出段的名称,它用来唯一地标识一个输出段,还用来构成链接器生成的链接符号。base_designator 用来表示本输出段的起始地址,它可以有两种格式:起始地址值或偏移量。attribute表示本输出段的属性,其可能的取值如下所示:oPI位置无关属性oRELOC重定位oABSOLUTE绝对地址oFIXED固定地址oUNINIT未初始化的数据max_siz
17、e指定本输出段的最大尺寸。 输入段的描述输入段的描述输入段里描述了一个文本字符串的模式,匹配该模式的输入段都将被包含在当前域中。模式中可以使用匹配符,符号*代表零个或者多个字符,符号?代表单个字符。进行匹配时,所有字符是大小写无关的。下面介绍一些使用 scatter 文件配置映像文件地址映射模式的例子。在本例中,映像文件包括一个加载时域和 3 个连续的输出段,这种模式适合于那些将其他程序加载到 RAM 中的程序,如操作系统的引导程序和 Angel 等。例子一个简单的 scatter 文件Load_10 x4000;定义加载时域的名称为 Load_1,起始地址为 0 x4000ER_RO+ 0;
18、输出段名 ER_RO,地址偏移量 0,所以起始地址为0 x4000 *( + RO) ;通配符*,包含了所有的 RO 属性的输入段,它们被连续放置ER_RW+ 0;输出段名称 ER_RW,起始地址为前一个输出段的结束地址加偏移量 0 *( +RW) ;本输出段包含所有的 RW 属性的输入段,它们被连续放置ER_ZI 0 x5000;输出段名称 ER_ZI,起始地址为 0 x5000 *( +ZI) ;本输出段包含了所有的 ZI 属性的输入段,它们被连续放置按照例 scatter 文件的描述,ARM 链接器会生成相应的映像文件地址映射关系,如图 2 所示。图 2 程序运行时地址映射关系2 2、固
19、定时域、固定时域任何一个映像文件都需要指定一个初始入口点(initial entry point),它是影响文件运行时的入口点。初始入口点必须位于一个固定域中,所谓固定域是指该域的加载时地址和运行时地址是相同的。如果初始入口点不是位于一个固定域中,ARM 链接器在链接时会产生下面的错误信息。L6203E:Entry point (0 x0000 0000) lies within non-root region 32 bit RAM使用 scatter 文件时,可以有下面两种方法来设置固定域。 设置输出段地址设置输出段地址第 1 种方法是设定一个加载域中第 1 个输出段的运行地址,使其和该加载
20、域的加载地址相同。这样该输出段就是一个固定域。例 1 就使用这种方法确定固定域。其中,加载域 LR_1 的起始地址为 0 x8000,输出段 ER_RO 的起始地址指定为 0 x8000,与加载域 LR_1 的起始地址相同,因此,输出段 ER_RO 是一个固定域,并且是映像文件的初始入口点。例 1 指定固定域LR_1 0 x08000;加载域 LR_1 的起始地址为 0 x8000ER_RO 0 x08000;输出段 ER_RO 的起始地址为 0 x8000*( +RO);包含了所有的 RO 数据,包含初始入口点;其他部分内容 设置输出段属性设置输出段属性第 2 种方法通过将某个输出段的属性设
21、置成 FIXED。例 2 指定固定域LR_1 0 x8000;加载时域 LR_1 的起始地址为 0 x8000ER_RO0 x8000*( +RO);除了 init.o 之外的其他 RO 数据ER_INIT 0 x9000 FIXED;设置输出段属性为 FIXED,确定固定域init.o( +RO);本输出段包含了 init.o,包含映像文件的初始入口点;其他部分内容3 3、一个实际系统的例子、一个实际系统的例子在一个嵌入式设备中,为了保持好的性价比,通常在系统中存在多种存储器。在一个实际的 ARM开发板中,可能包括片内 Flash、RAM 和片外 Flash、RAM。在本例中,我们假设用 A
22、RM 芯片构造了一个嵌入式系统,包含了 8KB 片内 Flash 存储器、16KB 片内 RAM 存储器、起始地址为 0 x80000000 的片外 Flash和起始地址为 0 x81000000 的片外 RAM,其地址空间分配关系如图 3 所示。在这样的 ARM 系统中,我们编写了程序,并且按照例 3 中的分散加载文件对映象文件的地址进行分配。分配后的地址映像关系如图 4 所示。图 3 ARM 系统中的地址空间图 4 地址映像关系从图 4 中可以看出:可执行代码都放在片外 Flash 中,并且 Vectors 向量表放在片外 Flash 的起始地址上;Startup 目标文件的数据放置在片内
23、 RAM 中,堆栈放在片内 RAM 的顶端;其他数据放置在片外RAM 中,堆空间紧跟其后。例 3 片外 Flash 启动程序的 scatter 文件ROM_LOAD0 x80000000;定义加载区名称 ROM_LOAD,起始地址0 x80000000ROM_EXE0 x80000000;定义执行代码空间,起始地址与加载域地址相同Startup.o (vectors,+First);首先放置 Startup.o 文件的向量表vectors* ( +RO);后面地址空间放置其他 RO 属性代码IRAM0 x40000000;定义数据空间Startup.o ( +RW, +ZI)STACKS0 x
24、40004000UNINIT;定义堆栈空间stack.o ( +ZI)ERAM0 x81000000;定义数据空间* ( +RW, +ZI);剩下未指定空间的所有数据HEAP + 0UNINIT;定义堆空间heap.o ( +ZI)armlink 中的 scatter fileScatter file (分散加载描述文件)用于 armlink 的输入参数,他指定映像文件内部各区域的 download 与运行时位置。Armlink 将会根据 scatter file 生成一些区域相关的符号,他们是全局的供用户建立运行时环境时使用。(注意:当使用了 scatter file 时将不会生成以下符号:
25、Image$RW$Base,Image$RW$Limit,Image$RO$Base,Image$RO$Limit,Image$ZI$Base,Image$ZI$Limit)二 什么时候使用 scatter file当然首要的条件是你在利用 ADS 进行项目开发,下面我们看看更具体的一些情况。1 存在复杂的地址映射:例如代码和数据需要分开放在在多个区域。2 存在多种存储器类型:例如包含 Flash,ROM,SDRAM,快速 SRAM。我们根据代码与数据的特性把他们放在不同的存储器中,比如中断处理部分放在快速 SRAM 内部来提高响应速度,而把不常用到的代码放到速度比较慢的 Flash 内。3
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- scatter 文件 写法
