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

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

[复制链接]
STMCU-管管 发布时间:2021-11-29 14:28
越来越多的客户在使用STM32CubeIDE作为集成开发工具。STM32CubeIDE在编译代码的时候,用到了链接脚本。通常情况下,STM32CubeIDE会自动生成默认的链接脚本。但是有些情况下,例如,用户程序需要定义一些特别的段来放置代码或者数据的时候,我们就需要修改链接脚本文件。
1 z6 E- A5 q* n0 Z. S1 K" r1 {; F
$ r, h# C% P! w$ b5 h: t
5 ~5 x4 I/ m4 i# w: q! C
最近有客户在修改链接脚本后,编译没有出现问题。但是编译之后生成的BIN文件很大,导致无法烧录到Flash中。结合这个问题,本文详细分析一下它的原因以及解决办法。
! z: T: s6 P0 ~+ ^( q5 f5 j
3 @/ [4 a( a. J4 i3 K  Q1 x问题描述
3 u" U8 U+ b/ H3 b
0 W5 _& q/ c( m+ N8 l
7 H9 {  u* o4 k% T& {3 ]+ y
使用STM32CubeIDE创建工程的时候,在项目工程目录文件夹下生成后缀为ld的链接脚本文件,程序的编译和链接都会依赖链接脚本文件。如下图所示,STM32H743VIT6的RAM空间被包含6块,每块RAM的起始地址是独立的,如果客户需要把指定特定的RAM区域放置数据或者代码的时候,需要手动修改链接脚本文件。7 {- k+ c( f% G
14.png
Figure 1 Memory Mapping for STM32H43! y+ K4 z3 j) \

4 a2 g$ a8 Y0 _$ B( d- v客户在使用STM32H743VIT6进行应用开发的时候,需要在0x24000000 以及0x30000000的RAM空间定义两个未初始化的数组。所以客户修改了ld链接脚本文件,添加两个SECTIONS分别定位在0x24000000和0x30000000位置,同时在代码中使用__attribute__关键字指定数组在对应的SECTIONS中。
- q% e9 h. p1 Z# i0 ?; j8 e# C4 o" Z! G" Y  _8 p
依照客户的问题描述,我们首先修改链接脚本,添加两个SECTIONS分别为ram_at_0x24000000和ram_at_0x30000000,参考如下。
; q6 v' ]7 H: w9 W8 \: s
15.png
Figure 2 Id链接脚本文件
9 S2 `, t1 m. Q2 Y. Q- @- c: l) i7 g& U! e. x9 l
同时在源代码中添加两个数组,分别定位在添加的SECTIONS中,参考如下。
; ?9 C, E8 a( c# S% P. M
16.png
Figure 3 定义数组参考代码$ f( c. B  w4 H" A: w  R  \

9 t  n2 L  t% w$ x: w5 M
( @& x7 i# y! E/ u1 _; s7 g- M
编译修改之后的工程,是可以正常运行的,但是我们发现当把ELF目标文件转为BIN文件之后,产生的BIN文件非常的大。这就导致如果使用BIN文件进行下载的话,是无法下载成功的,因为BIN文件的大小以及超出了Flash的存储空间。由下图BIN文件属性我们可以看到BIN文件的大小为650M。; o' ~2 m) ~6 @
17.png
Figure 4 BIN文件大小  V0 r& j/ _& {) q' s  C
3 Y  }$ a9 w' Z3 d5 y/ A, z
那么是什么原因导致产生的BIN文件这么大呢?文件就出在ld链接脚本文件这里。
1 G3 u4 O; |6 e* N7 m. f" b$ o& _
问题分析5 M- b3 k) R  M2 ^" P. g
- b. [6 o% o6 A8 B5 R/ Z1 m; C
+ Y1 q' `6 E" ?; L8 Z. w$ ]
BIN文件是最纯粹的二进制机器代码, 或者说是"顺序格式"。按照assembly code顺序翻译成binary machine code,内部没有地址标记。BIN是直接的内存映象表示,二进制文件大小即为文件所包含的数据的实际大小。BIN文件就是直接的二进制文件,一般用编程器烧写时从00开始,而如果下载运行,则下载到编译时的地址即可。
5 c+ k4 Z  I! X3 Y' L$ l& [$ ]" v- g. t! }$ B3 O7 {
STM32CubeIDE依赖链接脚本文件生成目标ELF文件,生成ELF目标文件之后,STM32CubeIDE会依赖GNU Objcopy工具把ELF文件转为BIN文件。这个过程简单一点来说,就是提取ELF文件中的代码段以及可加载数据段按照地址信息顺序生成BIN文件。
$ ^* \4 S: D7 h; B! G5 w% y
$ a, ?, H" ^5 B- _+ m3 \5 l6 j所以,如果BIN文件很大,那说明可加载的代码段和数据段很大。在我们的测试项目中,代码段是固定的;现在BIN文件很大,说明是数据段过大导致的。
1 `( S2 o  E$ d
" N( h2 `+ M  Z2 D
7 F9 A% e# u: I0 O7 U2 I  Y
通过查看编译产生的list文件,我们可以清楚的看到每个段的大小。
) h  `5 y6 M7 k! k6 h9 z' D3 |
18.png
Figure 5 Sections Map. i* }! s! W& V/ q2 F/ i" @3 F$ y
1 }( j3 I) j9 E- y, k- g
从上图的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中的。
+ z9 H7 h% N5 P+ i6 A0 c: A7 h+ E/ B5 o9 Z, @6 v6 R1 e/ P
GNU Objcopy工具生成BIN文件的过程,实际上就是把ELF文件中各个定义了LOAD属性的SECTION按照LMA的先后顺序提取出来,写入BIN文件中。SECTION的地址如果不是连续的,间隔部分则会填充DUMMY或指定的数据。所以BIN文件的大小为最大LMA加上对应的SECTION的Size。4 ]2 d" Y. m$ Z) \( V

4 }1 b/ N) f. k/ |# T结合上图,该工程最终生成的BIN文件大小为 0x30000000+0x4000 -0x8000000 =  671105024 和图4的文件属性显示的大小是一致的。
! r# I. x' m1 p6 b4 Q6 |/ ~) `2 x
1 s( j, k/ Q6 ^* s2 r' Z& Z问题已分析7 b( s6 \  q7 X; j* Y

/ W% Q+ [# u1 w% {问题解决
  i) n' N5 `+ L' {7 ^% T, Y: I$ n1 S+ ?% I$ U. ?' j
" b4 T7 l( Z* Y8 [  y3 e
▼查收解决方法▼

7 d+ k. X' S% r8 M

7 \  k! [2 _% g% o* m8 C根据上面章节分析的原因,BIN文件过大是新增加的两个SECTIONS导致的。如图5所示,ram_at_0x24000000 段和ram_at_0x30000000段都具有LOAD属性,所以GNU Objcopy工具认为该段是需要加载到Flash中的。如果修改该段的属性为NOLOAD,则可解决这个问题。
: ~0 X" u0 r* y: g- G# k$ Z" b5 ~
5 _. g9 q6 T( u" ^. ?
* Y3 K" A9 Q6 h
参考 The GNU Linker 文档第73页,指定SECTION的类型为NOLOAD。最终修改后的链接脚本文件如下所示。
3 d7 `7 V' x+ s7 L( s- M* U4 f8 T
19.png
Figure 6 更新后的链接脚本
( b8 O- K$ k1 |9 V6 E- H1 \- b+ P7 H$ w- c# t& s! s  K' o0 K
依赖修改后的链接脚本编译得到的目标ELF文件,查看其段描述,可以知道新添加的段的属性不再为LOAD。GNU Objcopy工具在进行BIN文件生成的时候,也不会加载这两个段。所以,最终得到的BIN文件只包含有效的代码段和数据段,大小为24428字节。( E- n2 d( s* R* h2 S4 P8 J- P% \2 O
20.png
Figure 7 更新后的段描述2 j9 r0 A2 f& d4 P- |0 S9 {% Z
6 T  V; |' L) u- a
问题总结
9 Y/ \; ?1 J) Y  Y6 H% R
% f4 R" h2 ?# M- @

  z2 @3 u; T* a5 v" o+ p本文通过一个具体的问题阐述了BIN文件的产生过程,同时对链接脚本的格式做了一个简单的介绍。STM32用户后期如果遇到变量无需加载却导致BIN文件过大的问题,可依照该方法进行处理。6 I6 k; W& Z+ V' ^& F( g

0 X/ X/ V4 W" M& s2 m  k
收藏 2 评论0 发布时间:2021-11-29 14:28

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版