zoukankan      html  css  js  c++  java
  • Scatter文件编写

    (和《ARM嵌入式应用技术基础》186-190页一模一样)
     
    Scatter文件编写
     
        一个映像文件中可以包含多个域(region),在加载和运行映像文件时,每个域可以有不同的地址。每个域可以包括多达3个输出段,每个输出段是由若干个具有相同属性的输入段组成。这样在生成映像文件时,ARM链接器就需要知道下述两个信息。
    • 分组信息    决定各域中的输出段是由哪些输入段组织而成;
    • 定位信息    决定各域在存储空间中的起始地址。
        根据映像文件中地址映射的复杂程度,有两种方法来告诉ARM链接器这些相关的信息。对于映像文件中地址映射关系比较简单的情况,可以使用命令行选项;对于映像文件中地址映射关系比较复杂的情况,可以使用一个scatter配置文件。Scatter文件又称为分散加载文件,将重点讲解如何编写scatter文件。
    1、Scatter文件结构
        Scatter文件是一个文本文件,使用BNF语法来描述ARM链接器生成映像文件时所需要的信息。具体来说,在scatter文件中可以指定下列信息:
    • 各个加载时域的加载时起始地址、最大尺寸和属性;
    • 每个加载时域包含的输出段;
    • 各个输出段的运行时起始地址、最大尺寸、存储访问特性和属性;
    • 各个输出段中包含的输入段。
        一个Scatter文件包含若干个加载域,一个加载域包含若干个输出段,一个输出段由若干个具有相同属性的输入段组成,其结构如图1所示

     

     图1 Scatter文件结构示意图
        ① 加载时域的描述
        加载时域包括名称、起始地址、属性、最大尺寸和一个运行时域的列表。使用BNF语法描述,加载时域的格式如下所示:

    Load_name      base_designator         attribute      max_size
    {
    ……
    }

    • Load_name   运行时域名称,它除了唯一地标识一个运行时域外,还用来构成链接器生成的链接符号;
    • base_designator 用来表示本加载时域的起始地址,它可以有两种格式表示:起始地址或偏移量; 
    • attribute   本加载时域的属性,其可能的取值为下面之一,默认的取值为ABSOLUTE:
    •     PI          位置无关属性;
    •     RELOC       重定位;
    •     ABSOLUTE    绝对地址; 
    • max_size 最大尺寸,如果本加载时域的实际尺寸超过了该值,链接器将报告错误。默认的取值为0xFFFFFFFF。
        ② 输出段的描述
        输出段包括名称、起始地址、属性、最大尺寸和一个输入段的集合。使用BNF语法描述,输出段的格式如下所示:

    output_name     base_designator     attribute       max_size
    {
    ……
    }

    • output_name 输出段的名称,它用来唯一地标识一个输出段,还用来构成链接器生成的链接符号。
    • base_designator 用来表示本输出段的起始地址,它可以有两种格式:起始地址值或偏移量。
    • attribute   表示本输出段的属性,其可能的取值如下所示:
    •     PI          位置无关属性
    •     RELOC       重定位
    •     ABSOLUTE    绝对地址
    •     FIXED       固定地址
    •     UNINIT      未初始化的数据
    • max_size    指定本输出段的最大尺寸。
        ③ 输入段的描述
        输入段里描述了一个文本字符串的模式,匹配该模式的输入段都将被包含在当前域中。模式中可以使用匹配符,符号"*"代表零个或者多个字符,符号"?"代表单个字符。进行匹配时,所有字符是大小写无关的。
        下面介绍一些使用scatter文件配置映像文件地址映射模式的例子。在本例中,映像文件包括一个加载时域和3个连续的输出段,这种模式适合于那些将其他程序加载到RAM中的程序,如操作系统的引导程序和Angel等。
        例子    一个简单的scatter文件 

    Load_1   0x4000             ;定义加载时域的名称为Load_1,起始地址为0x4000
    {
             ER_RO    + 0     ;输出段名ER_RO,地址偏移量0,所以起始地址为0x4000
              { *( + RO) }       ;通配符*,包含了所有的RO属性的输入段,它们被连续放置
             ER_RW    + 0     ;输出段名称ER_RW,起始地址为前一个输出段的结束地址加偏移量0
              { *( +  RW) }      ;本输出段包含所有的RW属性的输入段,它们被连续放置
    ER_ZI 0x5000       ;输出段名称ER_ZI,起始地址为0x5000
              { *( +  ZI) }      ;本输出段包含了所有的ZI属性的输入段,它们被连续放置
    }

        按照例 scatter文件的描述,ARM链接器会生成相应的映像文件地址映射关系,如图2所示。

     

     图2 程序运行时地址映射关系
     
    2、固定时域
        任何一个映像文件都需要指定一个初始入口点(initial entry point),它是影响文件运行时的入口点。初始入口点必须位于一个固定域中,所谓固定域是指该域的加载时地址和运行时地址是相同的。如果初始入口点不是位于一个固定域中,ARM链接器在链接时会产生下面的错误信息。
        L6203E:Entry point (0x0000 0000) lies within non-root region 32 bit RAM
        使用scatter文件时,可以有下面两种方法来设置固定域。
     
        ① 设置输出段地址
        第1种方法是设定一个加载域中第1个输出段的运行地址,使其和该加载域的加载地址相同。这样该输出段就是一个固定域。
        例1就使用这种方法确定固定域。其中,加载域LR_1的起始地址为0x8000,输出段ER_RO的起始地址指定为0x8000,与加载域LR_1的起始地址相同,因此,输出段ER_RO是一个固定域,并且是映像文件的初始入口点。
        例1 指定固定域

    LR_1 0x08000                ;加载域LR_1的起始地址为0x8000
    {
         ER_RO 0x08000          ;输出段ER_RO的起始地址为0x8000
         {
    *( +  RO)          ;包含了所有的RO数据,包含初始入口点
         }
         ;其他部分内容
    }

        ② 设置输出段属性
        第2种方法通过将某个输出段的属性设置成FIXED。
        例2指定固定域

    LR_1 0x8000                 ;加载时域LR_1的起始地址为0x8000
    {
         ER_RO    0x8000
         {
             *( +  RO)          ;除了init.o之外的其他RO数据
         }
         ER_INIT 0x9000 FIXED   ;设置输出段属性为FIXED,确定固定域
         {
         init.o( +  RO)         ;本输出段包含了init.o,包含映像文件的初始入口点
         }
         ;其他部分内容
    }

     
    3、一个实际系统的例子
        在一个嵌入式设备中,为了保持好的性价比,通常在系统中存在多种存储器。在一个实际的ARM开发板中,可能包括片内Flash、RAM和片外Flash、RAM。在本例中,我们假设用ARM芯片构造了一个嵌入式系统,包含了8KB片内Flash存储器、16KB片内RAM存储器、起始地址为0x80000000的片外Flash和起始地址为0x81000000的片外RAM,其地址空间分配关系如图3所示。
        在这样的ARM系统中,我们编写了程序,并且按照例3中的分散加载文件对映象文件的地址进行分配。分配后的地址映像关系如图4所示。

                                                             

     图3 ARM系统中的地址空间                                                             图4 地址映像关系
        从图4中可以看出:可执行代码都放在片外Flash中,并且Vectors向量表放在片外Flash的起始地址上;Startup目标文件的数据放置在片内RAM中,堆栈放在片内RAM的顶端;其他数据放置在片外RAM中,堆空间紧跟其后。
        例3 片外Flash启动程序的scatter文件

    ROM_LOAD  0x80000000                 ;定义加载区名称ROM_LOAD,起始地址0x80000000
    {
         ROM_EXE  0x80000000              ;定义执行代码空间,起始地址与加载域地址相同
        {
            Startup.o (vectors,  +First)     ;首先放置Startup.o文件的向量表vectors
            * ( +RO)               ;后面地址空间放置其他RO属性代码
     
         IRAM  0x40000000                     ;定义数据空间
        {   Startup.o ( +RW, +ZI)   }
     
    STACKS  0x40004000  UNINIT           ;定义堆栈空间
        {    stack.o ( +ZI)    }
     
        ERAM  0x81000000                     ;定义数据空间
        {   * ( +RW, +ZI)      }             ;剩下未指定空间的所有数据
       
        HEAP + 0  UNINIT                     ;定义堆空间
        {     heap.o ( +ZI)    }

  • 相关阅读:
    移动硬盘无法识别提示需要格式化的解决办法
    Cassandra 入门(资料收集)
    [转] NoSQL生态系统
    软件项目实施问题收集(LastUpdatedOn:20141117)
    Sql server 收缩日志
    关于重构需要了解的一些原则
    C#定时任务采用线程和队列实现
    [转]我是如何带领团队开发项目的
    ASP.NET MVC 多套皮肤解决方案
    Mysql 问题汇总(不断更新中...)
  • 原文地址:https://www.cnblogs.com/liuchengchuxiao/p/4171427.html
Copyright © 2011-2022 走看看