zoukankan      html  css  js  c++  java
  • Keil sct分散加载文件(转)

    首先介绍几个概念:

    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                                 // 恢复默认设置

    样例:

     简单存储器映射实例

    复制代码
    LOAD_ROM 0x0000 0x8000       //Name of load region, Start address for load region, Maximum size of load region
    {
        EXEC_ROM 0x0000 0x8000   //Name of first exec region, Start address for exec region, Maximum size of this region
        {
            *(+RO)               //Place all code and RO data into this exec region
        }
        RAM 0x10000 0x60000      //Start of second exec region
        {
            *(+RW, +ZI)          //Place all RW and ZI data into this exec region
        }
    }
    复制代码

    复杂存储器映射实例:

    复制代码
    LOAD_ROM_1 0x0000                //Start address for first load region
    {
        EXEC_ROM_1 0x0000            //Start address for first exec region
        {
            program1.o (+RO)         //Place all code and RO data from program1.o into this exec region
        }
        DRAM 0x18000 0x8000          //Start address for this exec region  Maximum size of this exec region
        {
            program1.o (+RW, +ZI)    //Place all RW and ZI data from program1.o into this exec region
        }
    }
    
    LOAD_ROM_2 0x4000                //Start address for second load region
    {
        EXEC_ROM_2 0x4000
        {
            program2.o (+RO)         //Place all code and RO data from program2.o into this exec region
        }
        SRAM 0x8000 0x8000
        {
            program2.o (+RW, +ZI)    //Place all RW and ZI data from program2.o into this exec region
        }
    }
    复制代码

    具体格式描述请参考资料: 分散加载描述文件

     一个具体的例子:

    复制代码
    ; *************************************************************
    ; *   Scatter-Loading Description File generated by uVision   *
    ; *************************************************************
    
    LR_IROM1 0x00000000 0x00080000  {       ; 第一个加载域,名字是LR_IROM1,起始地址0x00000000 大小是0x00080000
        ER_IROM1 0x00000000 0x00080000  {   ; 第一个运行时域,名字是ER_IROM1 起始地址0x00000000 大小事0x00080000
            *.o (RESET, +First)             ; IAP第一阶段在FLASH中运行
            *(InRoot$$Sections)             ; All library sections that must be in a root region
            .ANY (+RO)                      ; .ANY与*功能相似,用.ANY可以把已经被指定的具有RW,ZI属性的数据排除
        }
        RW_IRAM1 0x10000000 0x00010000  {   ; RW data
            .ANY(+RW +ZI)
        }
        RW_SDRAM1 0xA0000000 0x00800000  {  ; RW data
            STARTUP_LPC177X_8X.o (HEAP)     ;HEAP用来定位堆栈的底
            *.LIB(+RW +ZI)
        }
    }
    复制代码
  • 相关阅读:
    OK335x mksd.sh hacking
    Qt jsoncpp 对象拷贝、删除、函数调用 demo
    OK335xS 256M 512M nand flash make ubifs hacking
    Qt QScrollArea and layout in code
    JsonCpp Documentation
    Qt 4.8.5 jsoncpp lib
    Oracle数据库生成UUID
    freemarker得到数组的长度
    FreeMarker中if标签内的判断条件
    freemarker语法
  • 原文地址:https://www.cnblogs.com/linxw-blog/p/14968224.html
Copyright © 2011-2022 走看看