一、问题背景

在基于 GD32F103(Cortex-M3) 的 IAP 升级方案中,系统采用 Bootloader + APP 的 Flash 分区架构:

  • Bootloader 位于 Flash 起始地址 0x08000000
  • APP 位于 Flash 地址 0x08005000
  • 通过 Bootloader 跳转方式进入 APP 程序运行

在实际测试中发现:

APP 程序可以正常跳转并执行 main(),但所有中断(如 SysTick、外设中断)均无法进入。


二、问题现象

  • Bootloader 运行正常
  • 跳转到 APP 后:
    • 主循环可执行
    • 外设初始化正常
    • 中断函数不响应

该问题在 IAP 场景下具有较强的迷惑性。


三、问题原因分析

1. Keil 中 IROM1 的作用被误解

在 APP 工程中已将 Keil 的 IROM1 起始地址设置为 0x08005000,但该设置:

  • 仅影响链接阶段
  • 决定代码在 Flash 中的存放位置
  • 不会影响 CPU 运行时中断向量表的位置

2. Cortex-M3 中断向量表机制

  • 中断向量表地址由 SCB->VTOR(Vector Table Offset Register) 决定
  • MCU 上电或复位后,VTOR 默认指向:

    0x08000000

  • 在 IAP 场景中:
    • APP 实际运行在 0x08005000
    • 若未重新设置 VTOR
    • 中断仍从 Bootloader 的向量表取入口地址

3. “能进 main 但不进中断”的本质原因

  • main() 是通过 Bootloader 手动设置 MSP 和 PC 跳转执行的
  • 中断入口是由 NVIC 根据 VTOR 自动查表
  • 两者机制不同,导致:
    • 主程序可运行
    • 中断入口地址错误,无法进入 APP 的中断服务函数

四、问题定位结论

问题根因:APP 程序未将中断向量表重定位到自身的 Flash 起始地址(VTOR 未正确设置)。


五、解决方案

1. 在 APP 工程中的system_gd32f10x.c文件中添加一个宏定义

#define VECT_TAB_OFFSET  (uint32_t)0x5000            /* vector table base offset */

因为在这个c文件中存在下面这个函数

#ifdef VECT_TAB_SRAM
    nvic_vector_table_set(NVIC_VECTTAB_RAM, VECT_TAB_OFFSET);
#else
    nvic_vector_table_set(NVIC_VECTTAB_FLASH, VECT_TAB_OFFSET);
#endif
}


2. Bootloader 与 APP 的职责划分

  • Bootloader:
    • 负责升级、校验、跳转
    • 不负责 APP 的中断向量表设置
  • APP:
    • 负责自身运行环境初始化
    • 包括时钟、中断、VTOR 设置

六、最终结果

  • APP 程序中断功能恢复正常
  • IAP 架构运行稳定
  • 系统符合 Cortex-M 工程规范及工业实践

七、经验总结

  1. IROM1 设置 ≠ VTOR 设置
  2. IAP 架构下,APP 必须独立完成中断向量表重定位
  3. “能跳转但不进中断”是 IAP 中非常典型的问题现象
  4. 建议统一在 SystemInit() 中完成 VTOR 配置,避免遗漏

八、一句话总结

在 IAP 架构中,APP 中断失效的根本原因是未正确重定位中断向量表(SCB->VTOR),而非程序跳转或链接地址错误。

备注:该问题是学习过程中遇到的实际问题,该文由AI辅助整理

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐