目录

一、作用分析

二、详细解析

1. APPLICATION_ADDRESS 指向的是 Application 的起始地址

2. 读取 Application 起始地址的第一个 32 位数据

3. 判断 MSP 是否有效

三、为什么需要这个判断?

防止 Bootloader 误跳转

四、总结

该判断的作用

改进建议


一、作用分析

#define APPLICATION_ADDRESS  0x08004000

这句话的作用是 检查 Application 是否有效,避免 Bootloader 误跳转到一个空的或无效的地址。

二、详细解析

1. APPLICATION_ADDRESS 指向的是 Application 的起始地址

(*(__IO uint32_t*)APPLICATION_ADDRESS)

这个地址存储的是 Application 的向量表,向量表的 第 0 个地址 代表 栈顶指针(MSP,Main Stack Pointer)


2. 读取 Application 起始地址的第一个 32 位数据

(*(__IO uint32_t*)APPLICATION_ADDRESS)

这段代码的含义是:

  • 访问 0x08004000 地址处的 前 4 字节(即 Application 的 MSP)。
  • STM32 的 Flash 以 字(Word,32-bit) 为单位存储数据,因此 (*(__IO uint32_t*)APPLICATION_ADDRESS) 读取的就是 Application 的栈指针初始值

3. 判断 MSP 是否有效

((*(__IO uint32_t*)APPLICATION_ADDRESS) & 0x2FFE0000) == 0x20000000

这个判断的逻辑:

  1. (*(__IO uint32_t*)APPLICATION_ADDRESS) & 0x2FFE0000
    • 取出 MSP(栈指针)高 16 位,因为 MSP 必须是 SRAM 地址,所以我们关注高位是否落在 SRAM 范围内。
  2. 0x2FFE0000 是一个掩码,检查 MSP 是否在有效范围:
    • STM32F103 的 SRAM 地址范围是 0x20000000 ~ 0x2001FFFF(20KB)。
    • 任何有效的栈指针(MSP)应该在这个范围内。
    • 0x2FFE0000 是为了确保最高位是 0x20000000,以此判断 MSP 是否合理。

三、为什么需要这个判断?

防止 Bootloader 误跳转

如果 Flash 里没有写入 Application0x08004000 处的数据可能是:

  • 默认状态 0xFFFFFFFF(Flash 擦除后默认值)。
  • 错误数据(如果刷写失败)。
  • 随机无效数据

假如没有这个判断:

  • JumpAddress = *(__IO uint32_t*) (APPLICATION_ADDRESS + 4);
    → 可能会取到 0xFFFFFFFF 之类的无效值,导致 MCU 进入 HardFault(硬件错误中断)

四、总结

该判断的作用

  • 检查 Application 是否存在,防止 Bootloader 跳转到一个无效的 Flash 位置。
  • 保证 Application 代码的完整性,防止 MSP 指针错误导致程序崩溃。

改进建议

如果想更严格,可以额外检查 Reset 入口地址(0x08004004 处) 是否在 Flash 有效区域:

uint32_t appStack = *(__IO uint32_t*) APPLICATION_ADDRESS;
uint32_t appEntry = *(__IO uint32_t*) (APPLICATION_ADDRESS + 4);

if (((appStack & 0x2FFE0000) == 0x20000000) &&
    (appEntry >= 0x08004000 && appEntry <= 0x0801FFFF)) {
    // 跳转到 Application
}

这样可以防止 appEntry 也是 0xFFFFFFFF 这种无效数据导致 MCU 崩溃。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐