链接脚本LinkerScript
链接脚本的作用
在嵌入式开发中,需要指定不同的段烧录到单片机的地址,这个过程由链接脚本指定。
一般来说链接脚本根据芯片的不同,设定不同的RAM和FLASH起始地址和长度。
除了指示链接的过程,还可以将地址变成变量,传递给启动文件,例如bss段和data段的起始位置和结束位置,能够让启动文件从flash中搬运data段到RAM中,以及初始化bss段的数据为0。
链接脚本和段
现在想象有一个RAM,知道其起始地址和长度,有一个FLASH,也知道其起始地址和长度。
那么链接脚本会将
- 所有的text段,包括中断向量表
- 只读数据段rodata
定位到FLASH的位置,尤其是中断向量表一定会被放在FLASH的起始位置,而且中断向量表的第一个位置一定是主栈指针,其实也就是RAM的结束位置。
并且将
- data数据段,写到Flash中,并且规定data段将写入到RAM的起始位置
- bss段,规定将bss段写到data段后面。
这样就得到了RAM的内存布局。那堆和栈呢?编译器并不知道程序需要使用多少堆,只能通过编译知道栈的深度。
链接脚本中设置了Min_Heap_Size和Min_Stack_Size两个变量,并且在bss段后面创建了这样的一个用户堆栈段,其作用就是剩下的内存是否能满足最小栈和最小堆的使用。
也就是说RAM中可以动态使用的内存就是在bss后面。
基本语法
1 | MEMORY |
使用MEMORY定义RAM和FLASH。
1 | SECTIONS |
使用SECTIONS定义一个段,其中
.
相当于一个指针,指向我们当前分配内存的位置。指针默认位置是0。使用ALIGN来使
.
指针4字节对齐。使用
*(section_name)
将这个段放在整个text的这个位置。*
是通配符,表示将所有的文件的.text
段都放在这里。如果需要指定某一个文件的某一个段,就将其名称制定出来file.o(.text)
。很多时候写一个段可能会给一个段起名,比如
.text.resethandler
,此时也可以用通配符(.text.*)
,也就是把所有.text
开头的段都囊括进去。最后使用一次ALIGN保证4字节对齐,不对齐则填充0。
PROVIDE命令用来定义一个变量,有点像汇编中的
.weak
,也就是如果在别的地方定义了这个变量,就会覆盖掉这里的定义,如果没有定义则使用这里的定义。>FLASH强制移动指针到FLASH中的空闲位置起点,也就说虽然指针默认为0,只需要写上
>FLASH
,在一开始就会把指针设为FLASH的起始位置。如果是在RAM中也是一样的道理。
源文件和链接文件
链接文件很多时候可以向源文件提供一些变量。
比如在stm32的链接脚本中提供了data段的起始地址结束地址,还有bss段的起始地址还有结束地址。
在这里就可以实现将所有剩余的RAM纳入动态内存的管理,以实现操作系统的动态内存管理。
- Title: 链接脚本LinkerScript
- Author: HarderHeng
- Created at : 2025-03-07 12:10:00
- Updated at : 2025-03-07 15:50:59
- Link: https://harderheng.life/2025/03/07/链接脚本LinkerScript/
- License: This work is licensed under CC BY-NC-SA 4.0.