在线时间5116 小时
UID3441752
注册时间2017-11-21
NXP金币1100297
TA的每日心情 | 开心 2025-7-11 08:53 |
|---|
签到天数: 301 天 连续签到: 2 天 [LV.8]以坛为家I
管理员
  
- 积分
- 43459
- 最后登录
- 2026-4-15
|
复习MDK链接加载程序过程
例子:各种数据所存放的段
在随意一个MDK工程的listings文件夹中都会生成一个map文件,最底下会有链接信息,可知ROM会包括Code ,RO Data以及RW Data段。其中,前面两个段容易理解,代码段和只读数据段自然是存放在flash中。
问1:但是,RW?为什么数据段信息也存放在flash中?
答1:RW段包含所有已经在代码中初始化的所有变量。在程序编译的时候把数据存放到FLASH中,然后在程序运行的时候,会把RW段数据复制到在分散加载文件中指定的地址空间上
问2:这个动作是怎么发生的?谁来执行它?硬件还是软件?什么时候执行?
答2:这个动作在启动文件的复位中断Reset_Handler中,在SystemInit函数执行完成之后会跳转到_main函数执行。然后在_main函数会完成RW段的重定位以及ZI段的清零,再跳转到main函数中运行
分散加载文件简介
i.MX-RT开发为什么需要自定义分散加载文件
由于RT1052没有内置flash,需要外界FLASH以实现程序的存放。再加上外扩RAM的存在,每个板子设计的flash和ram容量大小都不相同,使得在程序链接以及运行时必须根据这些信息以实现程序的链接以及初始化。也就是把不同的代码数据放在不同的存储空间,而且,在程序链接时,会包含有各种各样的域,标准的,自定义的域。
需要使用到自动以分散加载文件的情况:
复杂的内存映射:不同区域存放不同数据和代码
不同类型的内存:把需求不同的数据放置于不同的位置,ITCM,SDRAM,OCRAM
内存映射I/O:把某些数据字节准确放置于某个内存,以便能够访问内存映射的外围设备,比如初始化SDRAM
位于固定位置的函数:比如一些固定属性的函数列表
使用符号标识堆和堆栈:可以在堆或者栈中定义一些自定义的符号。
加载文件语法
首先,分散加载的语法遵循 Backus-Naur Form规范.
基本概念
加载时域:域所在的flash地址空间
运行时域:程序运行时域所在的空间
加载时域:一个加载时域可以包含多个运行时域
load_region_name :为本加载时域的名称,名称可以按照用户意愿自己定义,该名称中只有前 31 个字符有意义
base_address:表示本加载时域中的对象在连接时的起始地址,地址必须是字对齐的
+offset:表示本加载时域中的对象在连接时的起始地址是在前一个加载时域的结束地址后偏移量 offset 字节处。本加载时域是第一个加载时域,则它的起始地址即为 offset, offset 的值必须能被 4 整除
attribute_list:指定本加载时域内容的属性
ABSOLUTE:绝对地址;PI:与位置无关;RELOC:可重定位;OVERLAY:覆盖;NOCOMPRESS:不能进行压缩
max_size:指定本加载时域的最大尺寸。如果本加载时域的实际尺寸超过了该值,连接器将报告错误, 默认取值为 0xFFFFFFFF;
execution_region_description:表示运行时域,后面有个+号,表示其可以有一个或者多个运行时域
运行时域语法
exec_region_name:为本加载时域的名称,名称可以按照用户意愿自己定义,该名称中只有前31个字符有意义;
base_address:表示本加载时域中的对象在连接时的起始地址,地址必须是字对齐的;
+offset:表示本加载时域中的对象在连接时的起始地址是在前一个加载时域的结束地址后偏移量offset 字节处,offset的值必须能被4整除。
attribute_list: 指定本加载时域内容的属性:
ABSOLUTE:绝对地址;
PI:与位置无关;
RELOC:可重定位;
OVERLAY:覆盖;
FIXED:固定地址。区加载地址和执行地址都是由基址指示符指定的,基址指示符必须是绝对基址,或者偏移为 0。
ALIGNalignment:将执行区的对齐约束从4增加到alignment。alignment必须为2的正数幂。如果执行区具有base_address,则它必须为alignment对齐。如果执行区具有offset,则链接器将计算的区基址与alignment边界对齐;
EMPTY:在执行区中保留一个给定长度的空白内存块,通常供堆或堆栈使用。
ZEROPAD:零初始化的段作为零填充块写入ELF文件,因此,运行时无需使用零进行填充;
PADVALUE:定义任何填充的值。如果指定 PADVALUE,则必须为其赋值;
NOCOMPRESS:不能进行压缩;
UNINIT:未初始化的数据。
max_size:指定本加载时域的最大尺寸。如果本加载时域的实际尺寸超过了该值,连接器将报告错误,默认取值为0xFFFFFFFF
length:如果指定的长度为负值,则将 base_address 作为区结束地址。它通常与EMPTY 一起使用,以表示在内存中变小的堆栈。
input_section_description:指定输入段的内容。
输入段描述
module_select_pattern:目标文件滤波器,支持使用通配符“”与“?”。其中符号“”代表零个或多个字符,符号“?”代表单个字符。进行匹配时所有字符不区分大小写。当module_select_pattern与以下内容之一相匹配时,输入段将与模块选择器模式相匹配:
包含段和目标文件的名称;
库成员名称(不带前导路径名);
库的完整名称(包括路径名)。如果名称包含空格,则可以使用通配符简化搜索。例如,使用*libname.lib 匹配 C:\lib dir\libname.lib。
nput_section_attr:属性选择器与输入段属性相匹配。每个input_section_attr的前面有一个“+”号。如果指定一个模式以匹配输入段名称,名称前面必须有一个“+”号。可以省略紧靠“+”号前面的任何逗号。 选择器不区分大小写。可以识别以下选择器:
RO-CODE;
RO-DATA;
RO,同时选择 RO-CODE 和 RO-DATA;
RW-DATA;
RW-CODE;
RW,同时选择 RW-CODE 和 RW-DATA;
ZI;
ENTRY:即包含 ENTRY 段。
可以识别以下同义词:
CODE 表示 RO-CODE;
CONST 表示 RO-DATA;
TEXT 表示 RO;
DATA 表示 RW;
BSS 表示 ZI。
可以识别以下伪属性:
FIRST;
LAST。
使用FIRST和LAST去标志一个运行域的第一个段个最后一个段
通过使用特殊模块选择器模式.ANY 可以将输入段分配给执行区,而无需考虑其父模块。可以使用一个或多个.ANY 模式以任意分配方式填充运行时域。在大多数情况下,使用单个.ANY 等效于使用*模块选择器。
分散加载文件分析
目的:能看懂一个分散加载文件。
上面介绍了三个分散加载文件的语法,现在先不直接上RT1052复杂的分散加载文件,先来个简单的STM32F103C8T6的分散加载文件,分散加载文件主要由一个加载时域和多个运行时域组成。
下面来分析RT1052的分散加载文件
工程配置:RT1052的分散加载文件当然是要自己写啦。
FLASH和SRAM分析
作者:weixin_42264572 文章出处:点击
|
|