You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GCC链接脚本中VMA与LMA不同导致Cortex-M4函数运行异常求助

Cortex-M4使用AT>指定LMA后函数执行触发HardFault问题解决

问题场景

使用类似STM32的Cortex-M4芯片,计划将高频调用函数放入FAST_FLASH区域优化性能,编写了带AT> FLASH的GCC链接脚本:

.flash_zw0 : ALIGN(4)
{
    *(.flash_ex)
} >FAST_FLASH AT> FLASH

编译后.map文件显示函数已归入指定段,但执行该段函数时直接进入HardFault。移除AT>配置后程序运行正常,但此时生成的bin文件因FAST_FLASH与FLASH地址跨度大而体积超标,无法完成升级。

芯片MEMORY配置如下:

MEMORY
{
FAST_FLASH (rx) : ORIGIN = 0x08014000, LENGTH = 48k
FAST_FLASH_1 (rx) : ORIGIN = 0x08020000, LENGTH = 128k
FLASH_0 (irx)   : ORIGIN = 0x0807f800, LENGTH = 2k
FLASH (rx)      : ORIGIN = 0x08080000, LENGTH = 512K
RAM (xrw)       : ORIGIN = 0x20000000, LENGTH = 96K
}

根本原因

使用AT> FLASH时,链接器为.flash_zw0段设置了两个地址:

  • VMA(虚拟内存地址):FAST_FLASH的起始地址0x08014000,是CPU执行函数时访问的地址
  • LMA(加载内存地址):FLASH区域的地址,是bin文件中该段实际存储的位置

但Cortex-M4的启动流程只会自动将RAM段(如.data)从LMA复制到VMA,Flash段不会自动执行复制操作。此时FAST_FLASH的VMA区域没有有效代码,CPU跳转到该地址执行时读取到非法指令,直接触发HardFault。

解决方案

需要手动实现LMA到VMA的代码复制,确保函数执行前FAST_FLASH区域已加载有效代码:

1. 修改链接脚本导出段信息

在链接脚本中添加全局符号,导出.flash_zw0段的VMA起始/结束地址,以及LMA起始地址:

.flash_zw0 : ALIGN(4)
{
    __flash_zw0_start = .;  /* VMA起始地址 */
    *(.flash_ex)
    __flash_zw0_end = .;    /* VMA结束地址 */
} >FAST_FLASH AT> FLASH

__flash_zw0_load_start = LOADADDR(.flash_zw0);  /* LMA起始地址 */

2. 添加代码复制逻辑

在系统初始化阶段(SystemInit之后、main函数之前),添加复制代码,将FLASH中LMA区域的内容复制到FAST_FLASH的VMA区域。

C语言实现示例:

/* 声明链接脚本导出的全局符号 */
extern uint32_t __flash_zw0_start;
extern uint32_t __flash_zw0_end;
extern uint32_t __flash_zw0_load_start;

void copy_fast_flash_sections(void)
{
    uint32_t *src_addr = &__flash_zw0_load_start;
    uint32_t *dest_addr = &__flash_zw0_start;
    const uint32_t *dest_end = &__flash_zw0_end;

    /* 按字复制内容,确保对齐 */
    while (dest_addr < dest_end)
    {
        *dest_addr++ = *src_addr++;
    }
}

在启动文件中调用该函数,比如在Reset_Handler的末尾、跳转到main之前执行。

3. 处理Flash写保护

如果FAST_FLASH区域默认开启写保护,需要先调用芯片的Flash解锁API(类似STM32的HAL_FLASH_Unlock()),完成复制后再重新上锁,避免后续操作出错。

验证步骤

  1. 复制完成后,通过调试工具查看FAST_FLASH区域(0x08014000开始)的内容,确认与FLASH中LMA区域的代码一致
  2. 执行.flash_ex段的函数,确认不再触发HardFault
  3. 生成bin文件,检查体积是否符合升级要求

内容的提问来源于stack exchange,提问作者Vermouth贝尔摩德

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 04:46:16