2. 内存区域与布局控制
链接脚本通过 MEMORY 命令描述芯片的物理内存区域,通过 SECTIONS 命令描述各输出段的摆放规则。本章介绍两者的语法与 KF32 的区域划分。
2.1 MEMORY 命令
MEMORY 用于声明目标芯片的内存区域(名称、起始地址、长度),供后续段布局通过 > region 引用。以 KF32A158MQVSF(512K PFlash / 64K RAM / 32K DFlash)为例,链接脚本的 MEMORY 配置如下:
MEMORY
{
flash : ORIGIN = 0x00000000, LENGTH = 512K /* chip flash */
ram : ORIGIN = 0x10000000, LENGTH = 64K /* chip ram */
da_mem : ORIGIN = 0x00200000, LENGTH = 32K /* Flash Data Limit */
mode_mem : ORIGIN = 0x0C001420, LENGTH = 0x00000004 /* mode config*/
pro_mem : ORIGIN = 0x0C001000, LENGTH = 0x00000004 /* protect config */
}
2.1.1 区域职责说明
编程相关空间为代码 flash 和变量 ram;其余空间用于定义 HEX 文件内容下的地址偏移与大小:
| 区域 | 起始地址 | 长度 | 职责 |
|---|---|---|---|
flash | 0x00000000 | 512K | PFlash:程序代码与常量运行空间(VMA),同时承载 .data 初值的装载区(LMA) |
ram | 0x10000000 | 64K | 变量、堆栈运行空间;前 32K 为低功耗保持区(以产品规格书为准) |
da_mem | 0x00200000 | 32K | DFlash:数据存储区域 |
mode_mem | 0x0C001420 | 4 | 模式配置区域(.debugormode 段) |
pro_mem | 0x0C001000 | 4 | 加密保护区域(.protectmode 段) |
2.2 SECTIONS 与布局控制
SECTIONS 中每个输出段的配置格式为:
输出段名 (修饰符): { 输入段规则 } > 运行区域 [AT > 装载区域]
> region:指定输出段的运行地址 VMA;AT > region:指定输出段的装载地址 LMA(未指定时 LMA = VMA);(NOLOAD):标记该段不装载,不占用 HEX 内容。
链接脚本的整体布局框架如下:
SECTIONS
{
.text : { … } > flash /* 代码、常量、C++ 函数表 */
.data : { … } > ram AT > flash /* 已初始化数据,初值存 flash */
.bss (NOLOAD) : { … } > ram /* 未初始化数据 */
.heap (NOLOAD) : { … } > ram /* 堆 */
.stack (NOLOAD) : { … } > ram /* 栈,锚定 RAM 顶部 */
.flashdata : { … } > da_mem /* Flash Data */
.debugormode : { … } > mode_mem /* 模式配置字 */
.protectmode : { … } > pro_mem /* 加密保护配置字 */
… /* 调试段收集与 /DISCARD/ 丢弃 */
}
2.2.1 输入段匹配规则
段配置格式为 文件名(输入段),其中 * 为通配符:
| 写法 | 含义 |
|---|---|
*(.text*) | 匹配任意文件中以 .text 起始的段 |
vector.o(.text*) | 仅匹配 vector.o 文件下的 .text 起始段 |
KEEP (*(.init_array*)) | 匹配且豁免死段优化(--gc-sections) |
SORT(.init_array.*) | 按段名排序后依次并入(保证构造优先级) |
备注
编译器默认按函数/变量拆分段(-ffunction-sections / -fdata-sections),每个函数或变量拥有独立段名(如 .text.main、.data.foo)。因此自定义数据段名匹配规则必须以 * 结尾(如 *(.UserRAMData*)),函数代码段则不需要。
2.2.2 定位计数器与符号赋值
脚本中 = 运算里的 . 为当前定位计数器,符号 = . 将当前地址记录到符号中,供 startup 代码与调试分析使用。为 . 或符号赋绝对地址时,需注意 LLD 的绝对地址语义;仅做相对推进(. = . + 长度;)不受影响(见 4.1 定位计数器 . 的语义)。