sct文件的编写与使用
参考资源
1. 分散加载文件浅释.pdf。(周立功工程技术笔记)
1. DUI0377G_02_mdk_armlink_user_guide.pdf(在keil的帮助文档中可以找到)
我们都知道,编译器在生成可执行文件时,先将每个.c文件编译成.o文件(此过程叫编译),然后将很多个.o文件链接成可执行文件(此过程叫链接)。在链接的过程中,会用到一个描述文件,用来指定链接时的行为。这个描述文件叫做链接文件,如linux下的.ld文件,keil中的分散加载文件(.sct文件)。这篇文章就是介绍.sct文件的使用。
keil 中使用自定义的.sct文件
默认的,在keil中编译程序时,会自动的生成.sct文件(默认在生成.o、.hex文件的目录下)。但是,默认的.sct文件很多时候不能满足我们的编程需求。比如在STM32F429上,有两个RAM区域。其中0x10000000起始的64k是CCM内存,DMA不能访问。如果直接使用这片区域(也就是在魔术棒->target选项->IRAM中勾选了它),当DMA访问的内存在这片区域时,那么会遇到程序进入硬件错误中断。这时候就应该使用自定义的.sct文件进行链接修饰,从而达到目的。
魔术棒(option for target)->linker选项
去掉Use Memory Layout from Target Dialog选项。
此时下面的Scatter File部分便可以操作。选择自己的.sct文件或者点击Edit对已有文件进行操作。
编辑完此文件,需要重新编译程序。
下面是笔者的sct文件
; *************************************************************
; *** Scatter-Loading Description File generated by uVision ***
; *************************************************************
LR_IROM1 0x08020000 0x000E0000 { ; load region size_region
ER_IROM1 0x08020000 0x000E0000 { ; load address = execution address
*.o (RESET, +First)
*(InRoot$$Sections)
.ANY (+RO)
}
RW_IRAM1 0x20000000 0x00020000 { ; RW data
.ANY (+RW +ZI)
}
RW_IRAM2 0x10000000 0x00010000 {
main.o (+RW +ZI) ;笔者修改的,将main.c中的所有变量放到ccm中
config.o (+RW +ZI) ;笔者修改的,将config.c中的所有变量放到ccm中
}
}
分散加载文件.sct
语法
一个分散加载文件由一个或者多个加载域
(load regions)组成。每个加载域
由一个或者多个执行域
(execution regions)组成。执行域
中又包含很多个输入段描述
(Input section description)。关系图如下
上图中的sct文件包含两个加载域。每个加载域中又都包含两个执行域。每个执行域中包含一个输入段描述。
分散加载文件使用;
作为注释符。
什么是加载域
加载域的组成如下:
语法格式
load_region_name (base_address | (+offset)) [attribute_list] [max_size]
{
execution_region
}
名称(name): 加载域的名称,用户自定义。
起始地址: 本加载域的起始地址。分两种表达格式
base_address:直接指明本加载域的起始地址。
+offset:表示此加载域的起始地址为前一个加载域的结束地址+offset字节。offset必须字对齐。
属性(attribute_list)(可选): 用于指定加载域的特征。具体值如下
ABSOLUTE: 绝对地址。默认属性。
PI: 与位置无关。
RELOC: 可重定位。
OVERLAY: 覆盖。
NOCOMPRESS: 不能进行压缩。
加载域大小(max_size)(可选)
指定加载域的最大范围。默认取值0xFFFFFFFF.
一个或者多个执行域.
执行域的组成见执行域的介绍。
example
LR_IROM1 0x08020000 0x000E0000 { ;加载域
ER_IROM1 0x08020000 0x000E0000 {;执行域1
*.o (RESET, +First)
.ANY (+RO)
}
RW_IRAM1 0x20000000 0x00020000 {;执行域2
.ANY (+RW +ZI)
}
}
什么是执行域
执行域描述了可执行文件在执行时内存(RAM+ROM)的分配。
执行域的组成类似加载域,如下:
语法格式
exec_region_name (base_address | (+offset)) [attribute_list] [max_size | Length]
{
input section descriptions
}
名称(name): 执行域的名称,用户自定义。
起始地址: 本执行域的起始地址。分两种表达格式
base_address:直接指明本执行域的起始地址。
+offset:表示此执行域的起始地址为前一个执行域的结束地址+offset字节。offset必须字对齐。
属性(attribute_list)(可选): 用于指定加载域的特征。具体值如下
ABSOLUTE: 绝对地址。默认属性。
PI: 与位置无关。
RELOC: 可重定位。
OVERLAY: 覆盖。
NOCOMPRESS: 不能进行压缩。
加载域大小(max_size)(可选)
指定加载域的最大范围。默认取值0xFFFFFFFF.
一个或者多个输入段描述.
输入段描述的组成见输入段描述的介绍。
什么是输入段描述
语法格式
目标文件过滤器 [+属性]
输入段描述的组成如下:
目标文件过滤器。支持通配符*、?。不区分大小写。如main.o,user*.o等。可匹配的文件可以为目标文件名、库名(不带前导路径名)、库完整路径名。
可以使用*.o匹配所有的目标文件。用*匹配所有文件,包括目标文件和库。
可以使用.ANY进行任意的匹配。它的优先级低于*.
属性,不区分大小写:
RO-CODE, 同义词有CODE
RO-DATA, 同义词有CONST
RO 即RO-CODE + RO-DATA,同义词有TEXT
RW-DATA
RW-CODE
RW 即RW-DATA + RW-CODE,同义词有DATA
ZI, 同义词有BSS
ENTRY 即包含ENTRY的段。
FIRST
LAST
example:
*.o (RESET, +First) 任何目标文件中的RESET段放在起始位置。
.ANY (+RW +ZI) 匹配任意文件的数据段。
.ANY (+RO) 匹配任意文件的代码段。