Keil uVision中生成的Scatter-Loading描述文件

stm32wle5xx_flash.sct

; *************************************************************
; *** Scatter-Loading Description File generated by uVision ***
; *************************************************************

LR_IROM1 0x08000000 0x00040000  {    ; load region size_region
  ; FLASH
  ER_IROM1 0x08000000 0x00040000  {  ; load address = execution address
   *.o (RESET, +First) ;从所有.o文件中抽取RESET段放在最开始的地方
   *(InRoot$$Sections)
   .ANY (+RO) ;所有.o文件的只读数据段
  }
  ; Non-backup SRAM1
  RW_IRAM1 0x20000000 0x00008000  {  ; RW data
   .ANY (+RW +ZI)
  }
  ; Backup SRAM2
  RW_IRAM2 0x20008000 EMPTY 0x00008000  {  ; to be modified accordingly to user project. Can be NoInit data for backup usage, RW, ZI region, etc...
  }
}

分散加载文件(scatter file)是一个文本文件,它的作用是可以描述ARM链接器生成映像文件所需要的信息。

如果不使用 scatter file 文件来指定,那么 ARM 链接器会按照默认的方式来生成映像文件,但是对于某些应用场景来说,我们希望能够将一些数据放在指定的位置,这个时候,分散加载文件就发挥其作用了。

ARM Cortex-M4系列芯片的启动流程:
在这里插入图片描述
MCU运行到main函数之前所做的操作,简而言之,主要做了如下三个工作:

  • 堆栈以及堆的初始化
  • 定位中断向量表
  • 调用Reset_Handler

分散加载操作是在__main()函数内部完成的,紧接着,就运行C语言运行环境初始化&C Library的初始化。

Code: 为程序代码部分
RO-Data: 表示程序定义的常量及const型数据
RW-Data:表示已经初始化的静态变量,变量有初值
ZI-Data: 表示未初始化的静态变量,变量无初值

因为分散加载的机制是将不同代码放在不同的存储空间,因此还需要了解代码的映像文件的基本概念。

ARM映像文件其实就是源文件经过编译器生成的目标文件.obj和相应的C/C++运行时库经过连接器的处理后,生成的.axf格式的映像文件,它可以直接烧录到目标设备的ROM中直接运行或加载后运行。

段的概念_重定位的引入

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
可读可写的全局变量保存在RAM中
可读不可写常量保存在ROM中

段的概念

  • 代码段
  • 只读数据段
  • 可读可写的数据段
  • BSS段
char g_Char = 'A';  //可读可写,不能放在ROM上,应该放在RAM里
const char g_Char2 = 'B'; //只读变量,可以放在ROM上
int g_A = 0; //初始值为0,不需要放在ROM上
int g_B; //没有初始化,初始值为0,不需要保存在ROM上

所以,程序分为这几个段:

  • 代码段(RO-CODE):就是程序本身,不会被修改
  • 可读可写的数据段(RW-DATA):有初始值的全局变量、静态变量,需要从ROM上复制到内存
  • 只读数据段(RO-DATA):可以放在ROM上,不需要复制到内存
  • BSS段或ZI段:初始值为0的全局变量或静态变量,没必要放在ROM上,使用之前清零就可以;未初始化的全局变量或静态变量,没必要放在ROM上,使用之前清零就可以
  • 局部变量:保存在栈中,运行时生成
  • 堆:一块空闲空间,使用malloc函数来管理它,malloc函数可以自己写

重定位

保存在ROM上的全局变量的值,在使用前要复制到内存,这就是数据段重定位。
要把代码移动到其它为止,这就是代码重定位。

如果不在链接地址上,就需要重定位,除了BSS段不需要重定位,使用前把BSS段对应的空间清零即可。

谁来做重定位?

程序本身:把自己复制到链接地址去
在这里插入图片描述
一开始,程序可能并不位于它的链接地址上,为什么它可以执行重定位的操作?
因为重定位的代码是使用位置无关码写的

位置无关码:这段代码在任何位置都可以运行,跟它所在的位置无关

怎么写出位置无关码:

  • 跳转:使用相对跳转指令,不能使用绝对跳转指令
    只能使用branch指令(比如bl main)
  • 不要访问全局变量、静态变量
  • 不使用字符串

怎么做重定位和清除BSS段

核心:复制
复制的三要素:源、目的、长度
怎么知道代码段/数据段保存在哪里?(加载地址)
怎么知道代码段/数据段被复制到哪里?(链接地址)
怎么知道代码段/数据段的长度?

在Keil中使用散列文件(Scatter file)描述
在GCC中使用链接脚本(Link Script)描述

加载地址和链接地址

程序运行时,应该位于它的链接地址处,因为:

  • 使用函数地址时使用的是函数的链接地址
  • 访问全局变量、静态变量时,用的是变量的链接地址

在这里插入图片描述
在这里插入图片描述
一个加载域里有三个可执行域

目的长度
0x080000000x080000000x00040000
紧随上一个之后0x200000000x00008000
紧随上一个之后0x200080000x00008000
  • 16
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

饼干饼干圆又圆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值