Keil scatter分散加载

一、分散加载描述语法

分散加载描述语法使用标准的的BNF符号

下表总结了用于描述分散加载描述语法的BNF符号。

Symbol Description
" Quotation marks indicate that a character that is normally part of the BNF syntax is used as a literal character in the definition. The definition B"+"C, for example, can only be replaced by the pattern B+C. The definition B+C can be replaced by, for example, patterns BCBBC, or BBBC.
A ::= B Defines A as B. For example, A::= B"+" | C means that A is equivalent to either B+or C. The ::= notation defines a higher level construct in terms of its components. Each component might also have a ::= definition that defines it in terms of even simpler components. For example, A::= B and B::= C | D means that the definition A is equivalent to the patterns C or D.
[A] Optional element A. For example, A::= B[C]D means that the definition A can be expanded into either BD or BCD.
A+ Element A can have one or more occurrences. For example, A::= B+ means that the definition A can be expanded into B, BB, or BBB.
A* Element A can have zero or more occurrences.
A | B Either element A or B can occur, but not both.
(A B) Element A and B are grouped together. This is particularly useful when the | operator is used or when a complex pattern is repeated. For example, A::=(B C)+ (D | E) means that the definition A can be expanded into any of BCD, BCEBCBCDBCBCEBCBCBCD, or BCBCBCE.

scatter文件的组件和组织

分散文件包含一个或多个加载区。每个加载区可以包含一个或多个执行区。下图显示了典型分散文件的组件和组织:

二、分散加载文件语法(引用自http://blog.163.com/yaochen_good/blog/static/5673636320131523020888/
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   xxx, CODE, READONLY

三、分散加载文件示例

; load region size_region
LR_IROM 0x20001000 (40*1024)                   
{
  ; load address = execution address
  ER_IROM 0x20001000              
  {

   *.o (RESET, +First)

   *(InRoot$$Sections)
   .ANY (+RO)
  }

;RESET是一个段名,一般在启动文件如startup.s中指定,表明该文件是系统启动的第一个文件。一般启动文件中会有ENTRY指示,该指令声明程序的入口点。

  ; RW data
  RW_IRAM_DEVICE_PRE_KERNEL_1 +0
  {
  *.o(.init_PRE_KERNEL_1*)
  }
  RW_IRAM_DEVICE_PRE_KERNEL_2 +0
  {
*.o(.init_PRE_KERNEL_2*)
  }
  RW_IRAM_DEVICE_POST_KERNEL +0
  {
*.o(.init_POST_KERNEL*)
  }
  RW_IRAM_DEVICE_APPLICATION +0
  {
*.o(.init_APPLICATION*)
  }
  RW_IRAM_DEVICE_END +0
  {
  }

  RW_IRAM_DEVICE_BUSY +0
  {
*.o(.device_BUSY)
  }
  RW_IRAM_DEVICE_BUSY_END +0
  {
  }
  RW_IRAM__net_buf_pool_area +0
  {
*.o(._net_buf_pool.static.*)
  }
  RW_IRAM__mem_pool_area +0
  {
*.o(._k_mem_pool.static.*)
  }
  RW_IRAM_SHELL_CMD_START +0
  {
*.o(.shell_)
  }
  RW_IRAM_SHELL_CMD_END +0
  {
  }
  RW_IRAM2 +0
  {
   .ANY (+RW)
  }

  RW_IRAM3 +0
  {
   .ANY (+ZI)
  }
  RW_STACK +0 UNINIT
  {
.ANY (STACK)
  }

}

四、scatter和Linker-defined symbols

1) Linker-defined symbols符号生成

链接器为image的每个区域生成不同类型的区域相关符号。

类型是:

执行域: Image$$和Load$$,

加载域: Load$$LR$$

如果您正在使用分散文件,则会为分散文件中的每个区域生成这些符号。
如果您未使用分散加载,则会为默认区域名称生成符号。详情请参考: http://www.keil.com/support/man/docs/armlink/armlink_pge1362065954807.htm

2) 符号使用

可以将Linker-defined symbols导入到C或C ++源代码中。它们是外部符号,你必须使用它们的地址。

唯一不需要&操作符的情况是使用数组声明的时候,例如extern char symbol_name[];.
以下示例显示如何获取Linker-defined symbols的值
导入一个 linker-defined symbol
extern unsigned int Image$$ER_ZI$$Limit;
config.heap_base = (unsigned int) &Image$$ER_ZI$$Limit;
导入一个ZI output section定义的符号
extern unsigned int Image$$ER_ZI$$Length;
extern char Image$$ER_ZI$$Base[];

memset(Image$$ER_ZImage$$RW_IRAM_DEVICE_PRE_KERNEL_1$$Base[];

3) 使用scatter文件中的Linker-defined symbols

extern struct device Image$$RW_IRAM_DEVICE_PRE_KERNEL_1$$Base[];
extern struct device Image$$RW_IRAM_DEVICE_PRE_KERNEL_2$$Base[];
extern struct device Image$$RW_IRAM_DEVICE_POST_KERNEL$$Base[];
extern struct device Image$$RW_IRAM_DEVICE_APPLICATION$$Base[];
extern struct device Image$$RW_IRAM_DEVICE_END$$Base[];
static struct device *config_levels[] = {
Image$$RW_IRAM_DEVICE_PRE_KERNEL_1$$Base,
Image$$RW_IRAM_DEVICE_PRE_KERNEL_2$$Base,
Image$$RW_IRAM_DEVICE_POST_KERNEL$$Base,
Image$$RW_IRAM_DEVICE_APPLICATION$$Base,
/* End marker */
Image$$RW_IRAM_DEVICE_END$$Base,

};

4) 更多详情,请参考: http://www.keil.com/support/man/docs/armlink/armlink_pge1362065951495.htm

猜你喜欢

转载自blog.csdn.net/u012408797/article/details/80258851