【STM32】sct 分散加载文件的格式与应用

本文围绕STM32的分散加载文件(sct)展开,介绍了其格式,包括加载区和执行域描述、输入节区用法。还说明了通过MDK配置选项和手动两种方式修改sct文件的方法,并给出自动分配变量到指定SRAM空间、优先使用内部SRAM并分配堆区到指定空间的实例。

简介

当工程按默认配置构建时,MDK 会根据我们选择的芯片型号,获知芯片的内部FLASH 及内部 SRAM 存储器概况,自动生成一个以工程名命名的后缀为*.sct 的分散加载文件(Linker Control File,scatter loading),链接器根据该文件的配置分配各个节区地址,生成分散加载代码,因此我们通过修改该文件可以定制具体节区的存储位置

一般情况下,不需要编写分散加载文件,由编译器自动生成,将某些数据放到默认位置。但是在某些场合,希望将某些数据放在指定的位置。

例如可以设置源文件中定义的所有变量自动按地址分配到外部 SRAM,这样就不需要再使用关键字“attribute”按具体地址来指定了;

复杂内存映射:如果必须将代码和数据放在多个不同的内存区域中,则需要使用详细指令指定将哪些数据放在哪个内存空间中。

不同类型的内存:许多系统都包含多种不同的物理内存设备,如闪存、 ROM、 SDRAM 和快速 SRAM。分散加载描述可以将代码和数据与最适合的内存类型相匹配。例如,可以将中断代码放在快速 SRAM 中以缩短中断等待时间,而将不经常使用的配置信息放在较慢的闪存中。

位于固定位置的函数:可以将函数放在内存中的固定位置,即使已修改并重新编译周围的应用程序。

使用符号标识堆和堆栈:链接应用程序时,可以为堆和堆栈位置定义一些符号。

利用它还可以控制代码的加载区与执行区的位置,例如可以把程序代码存储到单位容量价格便宜的 NAND-FLASH 中,但在NAND-FLASH 中的代码是不能像内部 FLASH 的代码那样直接提供给内核运行的,这时可通过修改分散加载文件,把代码加载区设定为 NAND-FLASH 的程序位置,而程序的执行区设定为 SRAM 中的位置,这样链接器就会生成一个配套的分散加载代码,该代码会把NAND-FLASH 中的代码加载到 SRAM 中,内核再从 SRAM 中运行主体代码,大部分运行Linux 系统的代码都是这样加载的

sct文件的格式

在这里插入图片描述
在默认的 sct 文件配置中仅分配了 Code、RO-data、RW-data 及 ZI-data 这些大区域的地址,链接时各个节区(函数、变量等)直接根据属性排列到具体的地址空间。

sct 文件中主要包含描述加载域及执行域的部分,一个文件中可包含有多个加载域,而一个加载域可由多个部分的执行域组成。同等级的域之间使用花括号“{}”分隔开,最外层的是加载域第二层“{}”内的是执行域

在这里插入图片描述
在这里插入图片描述

; *************************************************************
; *** Scatter-Loading Description File generated by uVision ***
; *************************************************************
 
LR_IROM1 0x08000000 0x00020000  {
   
       
	//定义一个加载域,域地址0x08000000,域大小为0x00020000
    //load region size_region 所有代码需要下载到0x08000000 开始的区域中,且这个区域大小只有0x00020000 
  ER_IROM1 0x08000000 0x00020000  {
   
     
	//load address = execution address 第一个运行时域必须和加载域起始地址相同,其大小一般也相同
    //只能是只读的代码段和只读数据段
   *.o (RESET, +First)        //启动代码的首次执行地址,RO执行域名称为ER_IROM1, 
    //将 RESET 段最先加载到本域的起始地址外
    //首次执行的地址为RESET标号所表示的地址,RESET 存储的是向量表
    //对应启动文件中的AREA    RESET, CODE, READONLY
   *(InRoot$$Sections)     //稍后文件中会单独讲到
   .ANY (+RO) //加载所有匹配目标文件的只读属性数据,包含:Code、 RW-Code、 RO-Data。
  }
  RW_IRAM1 0x20000000 0x00005000  {
   
     
    //再定义一个运行时域,域基址0x20000000 
	//RW data 执行域是以0x20000000 开始的长度为0x00004000  一段区域
   .ANY (+RW +ZI)    //其中包括的是哪些文件
  }
}

加载区描述

加载域名 (基地址 | ("+" 地址偏移)) [属性列表] [最大容量]
{
   
   
	执行区域描述
}
LR_IROM1 0x08000000 0x00080000  {
   
       ; load region size_region
......
}

加载域名:名称,在 map 文件中的描述会使用该名称来标识空间。如本例中只有一个加载域,该域名为 LR_IROM1。
基地址+地址偏移:这部分说明了本加载域的基地址,可以使用+号连接一个地址偏移,算进基地址中,整个加载域以它们的结果为基地址。如本例中的加载域基地址为 0x08000000,刚好是 STM32 内部 FLASH 的基地址。
属性列表:属性列表说明了加载域的是否为绝对地址、N 字节对齐等属性,该配置是可选的。本例中没有描述加载域的属性。
最大容量:最大容量说明了这个加载域可使用的最大空间,该配置也是可选的,如果加上这个配置后,当链接器发现工程要分配到该区域的空间比容量还大,它会在工程构建过程给出提示。本例中的加载域最大容量为 0x00080000,即 512KB,正是本型号 STM32 内部 FLASH 的空间大小。

执行域

执行域名 (基地址 | "+" 地址偏移) [属性列表] [最大容量 ]
{
   
   
///输入节区描述
}

执行域的格式与加载域是类似的,区别只是输入节区的描述有所不同

输入节区描述 .o .ANY (+RO)等的用法

配合加载域及执行域的配置,在相应的域配置“输入节区描述”即可控制该节区存储到域中

 //除模块选择样式部分外,其余部分都可选选填
 模块选择样式"("输入节区样式","
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值