STM32G0xx如何自动配置链接脚本Flash地址无需手动修改
实现STM32G0双备份镜像自动切换链接地址的可行方案
核心误区说明
不要尝试在startup.s启动文件中配置Flash运行地址,这个操作完全无效。
Cortex-M架构MCU的程序运行地址是链接阶段由链接器确定的:链接器会按照指定的Flash起始地址,计算所有函数跳转、常量访问、向量表的绝对地址,直接写入最终生成的二进制文件中。启动文件是二进制已经生成完成、CPU开始执行程序后才会运行的代码,此时所有地址已经固定,在启动文件里修改地址既无法改变已经写死在二进制里的跳转地址,还会直接导致程序跑飞。
无需手动修改链接脚本的落地方法
方法1:单链接脚本+编译传参,自动适配两个镜像地址
把原有链接脚本里固定写死的Flash起始地址改成可传入的变量,不需要维护两份不同的链接脚本。修改后的链接脚本MEMORY段示例如下:MEMORY { RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 8K FLASH (rx) : ORIGIN = APP_FLASH_BASE, LENGTH = 32K }编译两个不同地址的镜像时,直接通过编译参数给链接器传入对应的地址值即可,全程不需要打开链接脚本修改:
- 编译0x08001000地址的镜像时,给链接器加参数
--defsym APP_FLASH_BASE=0x08001000 - 编译0x08004800地址的镜像时,给链接器加参数
--defsym APP_FLASH_BASE=0x08004800
如果使用ARM GCC工具链(STM32CubeIDE默认环境),参数加在链接选项的-Wl,后面即可;如果使用Keil MDK,直接在对应目标的Linker Misc配置栏填入参数即可。
- 编译0x08001000地址的镜像时,给链接器加参数
方法2:工程内配置双编译目标,一键切换输出
所有主流嵌入式开发环境(Keil MDK、IAR、STM32CubeIDE)都支持在同一个工程下创建多个独立的编译目标:- 两个目标共用全部业务代码、启动文件,不需要重复维护代码
- 给两个目标分别配置不同的链接参数(和方法1的传参逻辑配合),或者分别指定对应地址的链接脚本
- 需要生成哪个地址的镜像,直接在IDE里选中对应目标点编译即可,不需要手动改任何配置。
必要注意事项
两个镜像的代码中,必须在系统初始化阶段把SCB->VTOR向量表偏移寄存器配置为当前镜像的实际Flash起始地址,否则中断触发时会跳转到默认地址的向量表,导致程序运行异常。
内容的提问来源于stack exchange,提问作者Malek
相关产品推荐
相关产品推荐

