你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

工程师笔记|关于STM32CubeIDE链接脚本的小问题

[复制链接]
STMCU-管管 发布时间:2021-11-29 14:28
越来越多的客户在使用STM32CubeIDE作为集成开发工具。STM32CubeIDE在编译代码的时候,用到了链接脚本。通常情况下,STM32CubeIDE会自动生成默认的链接脚本。但是有些情况下,例如,用户程序需要定义一些特别的段来放置代码或者数据的时候,我们就需要修改链接脚本文件。
1 o- M* {% z% Y0 C$ D2 V3 T/ t2 t
8 q5 ^6 e; i! K9 Y, z
最近有客户在修改链接脚本后,编译没有出现问题。但是编译之后生成的BIN文件很大,导致无法烧录到Flash中。结合这个问题,本文详细分析一下它的原因以及解决办法。
! C; A" g( w0 e3 {; j3 w2 I8 @& c; `
问题描述
; O7 y3 J# [/ Z2 A: U$ x5 `
4 c- F  Q; j7 ?. m
0 k' X3 I: l% V: r8 O6 H' f
使用STM32CubeIDE创建工程的时候,在项目工程目录文件夹下生成后缀为ld的链接脚本文件,程序的编译和链接都会依赖链接脚本文件。如下图所示,STM32H743VIT6的RAM空间被包含6块,每块RAM的起始地址是独立的,如果客户需要把指定特定的RAM区域放置数据或者代码的时候,需要手动修改链接脚本文件。4 |) H0 c. V* S- x. Z+ s9 z, j
14.png
Figure 1 Memory Mapping for STM32H43
8 V. h4 y! ]2 m4 k, U2 C2 @7 t+ V1 N
客户在使用STM32H743VIT6进行应用开发的时候,需要在0x24000000 以及0x30000000的RAM空间定义两个未初始化的数组。所以客户修改了ld链接脚本文件,添加两个SECTIONS分别定位在0x24000000和0x30000000位置,同时在代码中使用__attribute__关键字指定数组在对应的SECTIONS中。
' }8 K, u) j1 A: I( U! }0 v) M* V4 a4 z: X( ^
依照客户的问题描述,我们首先修改链接脚本,添加两个SECTIONS分别为ram_at_0x24000000和ram_at_0x30000000,参考如下。( w8 c; |! x, @; Z% g  J/ g2 g
15.png
Figure 2 Id链接脚本文件
& Q/ J* B4 a  X1 G4 @! e2 j! L( s
同时在源代码中添加两个数组,分别定位在添加的SECTIONS中,参考如下。
9 b8 l+ g+ ], \/ |
16.png
Figure 3 定义数组参考代码
- B1 m; M- u  H/ j9 a2 D% ~
9 Q4 b* v) p  u0 B7 @

* {3 E6 E% u9 Y编译修改之后的工程,是可以正常运行的,但是我们发现当把ELF目标文件转为BIN文件之后,产生的BIN文件非常的大。这就导致如果使用BIN文件进行下载的话,是无法下载成功的,因为BIN文件的大小以及超出了Flash的存储空间。由下图BIN文件属性我们可以看到BIN文件的大小为650M。5 j: [- J8 t( ~0 P& y
17.png
Figure 4 BIN文件大小! }, `& i, M, Q/ k2 N- q2 K& q
9 a6 G8 D5 b+ j3 I6 }2 {+ p7 }0 N
那么是什么原因导致产生的BIN文件这么大呢?文件就出在ld链接脚本文件这里。
; \3 Y* ]1 F) e  L5 v- _! |+ \2 {% z& v$ U
问题分析
) I. \5 b8 T; u
$ A2 N# O  u$ m) \7 Q- U
9 {8 {$ k+ U! u6 d% F% w  m
BIN文件是最纯粹的二进制机器代码, 或者说是"顺序格式"。按照assembly code顺序翻译成binary machine code,内部没有地址标记。BIN是直接的内存映象表示,二进制文件大小即为文件所包含的数据的实际大小。BIN文件就是直接的二进制文件,一般用编程器烧写时从00开始,而如果下载运行,则下载到编译时的地址即可。/ n! F9 \5 ]# K$ x) R
+ [" \/ N" p! I+ \
STM32CubeIDE依赖链接脚本文件生成目标ELF文件,生成ELF目标文件之后,STM32CubeIDE会依赖GNU Objcopy工具把ELF文件转为BIN文件。这个过程简单一点来说,就是提取ELF文件中的代码段以及可加载数据段按照地址信息顺序生成BIN文件。4 k  C" C; f; J2 a( w
  y4 d" k4 B, S* s
所以,如果BIN文件很大,那说明可加载的代码段和数据段很大。在我们的测试项目中,代码段是固定的;现在BIN文件很大,说明是数据段过大导致的。; [2 k) O  v. `4 E

5 ?& m9 D( e; c1 R7 Y

6 r7 L5 P: J+ E# M: J' e通过查看编译产生的list文件,我们可以清楚的看到每个段的大小。# c6 T' W, q* e2 o
18.png
Figure 5 Sections Map
0 O6 r9 ]+ z9 s  Z
  Y, x  e- o" z4 U, @* F从上图的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中的。' J8 m" i6 R( p  x( e0 [

$ T  W! X4 k; n& p/ J) iGNU Objcopy工具生成BIN文件的过程,实际上就是把ELF文件中各个定义了LOAD属性的SECTION按照LMA的先后顺序提取出来,写入BIN文件中。SECTION的地址如果不是连续的,间隔部分则会填充DUMMY或指定的数据。所以BIN文件的大小为最大LMA加上对应的SECTION的Size。1 y2 ?2 j, k6 u0 E% t" ]
: n% O5 Q  X( e7 n# Y
结合上图,该工程最终生成的BIN文件大小为 0x30000000+0x4000 -0x8000000 =  671105024 和图4的文件属性显示的大小是一致的。: G: w% w% o# a3 S6 |" a, b

# P) Y/ P  {( q! S6 Y6 x  D问题已分析' _8 r9 i) @6 v/ I/ }- H
$ D* k  ~9 N7 U  d+ B1 f1 o9 T: P
问题解决
5 E  V8 g/ m. P2 q" E! J* a3 H
. U4 ~+ \& w1 Z

0 P/ j$ a8 K& z
▼查收解决方法▼

: V- p' p: Q- ~9 E2 r7 H) h2 {
% ~/ [& j7 |+ x' q  t, s* ?1 o
根据上面章节分析的原因,BIN文件过大是新增加的两个SECTIONS导致的。如图5所示,ram_at_0x24000000 段和ram_at_0x30000000段都具有LOAD属性,所以GNU Objcopy工具认为该段是需要加载到Flash中的。如果修改该段的属性为NOLOAD,则可解决这个问题。
! x9 w( ~. h0 k5 s4 I+ V
3 c$ B0 o1 W6 {8 r3 `
; W: {- k( c* N7 J
参考 The GNU Linker 文档第73页,指定SECTION的类型为NOLOAD。最终修改后的链接脚本文件如下所示。
; v8 W/ F+ S6 L; m) L; ^
19.png
Figure 6 更新后的链接脚本2 Y) i; g9 k+ A9 @/ v$ {5 R7 A
' F0 t- Y2 e6 |% V4 x  f$ |+ c, r
依赖修改后的链接脚本编译得到的目标ELF文件,查看其段描述,可以知道新添加的段的属性不再为LOAD。GNU Objcopy工具在进行BIN文件生成的时候,也不会加载这两个段。所以,最终得到的BIN文件只包含有效的代码段和数据段,大小为24428字节。8 K" \! L- E8 O$ N2 |# u/ B
20.png
Figure 7 更新后的段描述; ^  d6 r0 {- \! l' z0 c
" h: O/ \$ U# m+ S& `5 |/ V6 f
问题总结
+ q+ ^; Z1 o" r+ Q$ J
: `9 ^' |% U9 b+ J) R. k
1 S) C& X* \) W, S
本文通过一个具体的问题阐述了BIN文件的产生过程,同时对链接脚本的格式做了一个简单的介绍。STM32用户后期如果遇到变量无需加载却导致BIN文件过大的问题,可依照该方法进行处理。
8 O/ g' E9 h) ]' Z2 n- V
. [1 ^' X7 e8 z/ L5 v2 u0 L, ~
收藏 2 评论0 发布时间:2021-11-29 14:28

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版