打印
[开发工具]

关于 STM32CubeIDE 链接脚本的小问题

[复制链接]
660|11
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
1. 概述
越来越多的客户在使用 STM32CubeIDE 作为集成开发工具。 STM32CubeIDE 在编译代码的
时候, 用到了链接脚本。 通常情况下,
STM32CubeIDE 会自动生成默认的链接脚本。 但是有些
情况下, 例如, 用户程序需要定义一些特别的段来放置代码或者数据的时候,我们就需要修改链
接脚本文件。
最近有客户在修改链接脚本后,编译没有出现问题。 但是编译之后生成的
BIN 文件很大,导
致无法烧录到
Flash 中。结合这个问题,本文详细分析一下它的原因以及解决办法。  

使用特权

评论回复
沙发
菜鸟的第一步|  楼主 | 2021-11-4 10:57 | 只看该作者
2. 问题描述
使用 STM32CubeIDE 创建工程的时候,在项目工程目录文件夹下生成后缀为 ld 的链接脚本
文件,程序的编译和链接都会依赖链接脚本文件。 如下图所示,
STM32H743VIT6 RAM 空间
被包含
6 块,每块 RAM 的起始地址是独立的, 如果客户需要把指定特定的 RAM 区域放置数据
或者代码的时候,需要手动修改链接脚本文件。




客户在使用 STM32H743VIT6 进行应用开发的时候, 需要在 0x24000000 以及
0x30000000 的 RAM 空间定义两个未初始化的数组。所以客户修改了 ld 链接脚本文件,添加两个 SECTIONS 分别定位在 0x24000000 和 0x30000000 位置,同时在代码中使用__attribute__
关键字指定数组在对应的 SECTIONS 中。
依照客户的问题描述,我们首先修改链接脚本,添加两个 SECTIONS 分别为
ram_at_0x24000000 和 ram_at_0x30000000,参考如下。

同时在源代码中添加两个数组,分别定位在添加的 SECTIONS 中,参考如下。

编译修改之后的工程,是可以正常运行的,但是我们发现当把 ELF 目标文件转为 BIN 文件
之后,产生的 BIN 文件非常的大。 这就导致如果使用 BIN 文件进行下载的话,是无法下载成功
的, 因为 BIN 文件的大小以及超出了 Flash 的存储空间。由下图 BIN 文件属性我们可以看到 BIN
文件的大小为 650M。

那么是什么原因导致产生的 BIN 文件这么大呢? 文件就出在 ld 链接脚本文件这里。

使用特权

评论回复
板凳
菜鸟的第一步|  楼主 | 2021-11-4 10:58 | 只看该作者
3. 问题分析
BIN 文件是最纯粹的二进制机器代码, 或者说是"顺序格式"。按照 assembly code 顺序翻译
binary machine code,内部没有地址标记。 Bin 是直接的内存映象表示,二进制文件大小即为
文件所包含的数据的实际大小。
BIN 文件就是直接的二进制文件,一般用编程器烧写时从 00
始,而如果下载运行,则下载到编译时的地址即可。
STM32CubeIDE 依赖链接脚本文件生成目标 ELF 文件,生成 ELF 目标文件之后,
STM32CubeIDE 会依赖 GNU Objcopy 工具把 ELF 文件转为 BIN 文件。这个过程简单一点来
说,就是提取
ELF 文件中的代码段以及可加载数据段按照地址信息顺序生成 BIN 文件。
所以,如果
BIN 文件很大,那说明可加载的代码段和数据段很大。在我们的测试项目中,
代码段是固定的; 现在
BIN 文件很大,说明是数据段过大导致的。
通过查看编译产生的
list 文件,我们可以清楚的看到每个段的大小。  


从上图的 Sections Map 中,每个 Section 会有几个关键的参数和类型。 Size 为每个
Section 的大小, VMA 是指 Section 在程序运行时候的地址, LMA 是指 Section 在 Flash 中的加
载地址。 通常情况下从 Flash 执行的程序, Code 段 VMA 和 LMA 是一样的。 Data 段的 VMA 会
放在 RAM 中, LMA 会放在 Flash 中,所以 Data 段的 VMA 和 LMA 通常不一样。 在每个段的类
型中,还有一个关键的属性是 LOAD,如果定义了 LOAD 属性,那说明这个段是需要写入 Flash
中的。
GNU Objcopy 工具生成 BIN 文件的过程,实际上就是把 ELF 文件中各个定义了 LOAD 属
性的 SECTION 按照 LMA 的先后顺序提取出来,写入 BIN 文件中。 SECTION 的地址如果不是连
续的, 则会填充 DUMMY 数据。所以 BIN 文件的大小为最大 LMA 加上对应的 SECTION 的
Size。
结合上图, 该工程最终生成的 BIN 文件大小为 0x30000000+0x4000 -0x8000000 =
671105024 和图 4 的文件属性显示的大小是一致的。


使用特权

评论回复
地板
菜鸟的第一步|  楼主 | 2021-11-4 10:59 | 只看该作者
4. 问题解决
根据上面章节分析的原因, BIN 文件过大是新增加的两个 SECTIONS 导致的。 如图 5
示,
ram_at_0x24000000 段和 ram_at_0x30000000 段都具有 LOAD 属性,所以 GNU Objcopy
工具认为该段是需要加载到 Flash 中的。 如果修改该段的属性为 NOLOAD,则可解决这个问
题。
参考
The GNU Linker 文档第 73 页,指定 SECTION 的类型为 NOLOAD。最终修改后的链
接脚本文件如下所示
  


依赖修改后的链接脚本编译得到的目标 ELF 文件,查看其段描述,可以知道新添加的段的
属性不再为 LOAD。 GNU Objcopy 工具在进行 BIN 文件生成的时候,也不会加载这两个段。 所
以, 最终得到的 BIN 文件只包含有效的代码段和数据段,大小为 24428 字节。


使用特权

评论回复
5
菜鸟的第一步|  楼主 | 2021-11-4 11:00 | 只看该作者
5. 小结
本文通过一个具体的问题阐述了 BIN 文件的产生过程,同时对链接脚本的格式做了一
个简单的介绍。
STM32 用户后期如果遇到变量无需加载却导致 BIN 文件过大的问题,可
依照该方法进行处理
  

使用特权

评论回复
6
skyred| | 2021-11-4 13:34 | 只看该作者
好复杂~~~

使用特权

评论回复
7
磨砂| | 2021-12-2 12:08 | 只看该作者
请问什么叫做连接脚本

使用特权

评论回复
8
wowu| | 2021-12-2 12:10 | 只看该作者
这种脚本可以手动更改吗

使用特权

评论回复
9
xiaoqizi| | 2021-12-2 12:11 | 只看该作者
一般不会涉及到这个脚本吧

使用特权

评论回复
10
木木guainv| | 2021-12-2 12:15 | 只看该作者
真是从来没有接触过

使用特权

评论回复
11
tpgf| | 2021-12-2 12:15 | 只看该作者
生成脚本的目的是什么呀

使用特权

评论回复
12
晓伍| | 2021-12-2 12:35 | 只看该作者
看着很是深奥啊

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

57

主题

426

帖子

1

粉丝