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)
匹配任意文件的代码段。
关于技术交流
此处后的文字已经和题目内容无关,可以不看。
qq群:825695030
微信公众号:嵌入式的日常
如果上面的文章对你有用,欢迎打赏、点赞、评论。