一、问题现象

STM32F429ZGTx 采用 IAP 双区方案:Bootloader 烧录在 0x08000000,APP 烧录在 0x08020000。跳转到 APP 后,串口只打印一次 "进入APP程序",之后再无输出。将 HAL_Delay(500) 注释掉后,printf 能持续打印。

[15:22:00.782]收←◆进入APP程序, uwTick:134353892(之后再无输出)

二、问题原因

HAL_Delay 基于 SysTick 中断实现,依赖全局变量 uwTick 递增。若 SysTick 中断无法进入,uwTick 永不递增,HAL_Delay 必然死循环。

根因在 Bootloader 跳转函数中:

void bootloader_jump_to_app(void)
{
  ...
  __disable_irq();         // 致命:PRIMASK = 1
  ...
  __set_MSP(app_stack_top);
  app_reset();             // 跳转,但 PRIMASK 仍为 1
}

跳转前用 __disable_irq() 关闭了全局中断(PRIMASK=1),跳转到 APP 后没有重新开启,导致 SysTick 中断永远无法进入,HAL_Delay 死循环。

另外,APP 的 main 函数中还有一个变量遮蔽 Bug:

uint32_t uwTick;    // 未初始化的局部变量,遮蔽了 HAL 库的全局 uwTick

打印出的 134353892 是栈上的随机垃圾值,并非真实 tick 数。

三、解决方案

1. 在 APP 端 HAL_Init() 之后调用 __enable_irq() 清除 PRIMASK:

HAL_Init();
__enable_irq();     // 关键!清除 Bootloader 遗留的 PRIMASK=1

2. 删除局部变量 uwTick,改用 HAL_GetTick() 获取真实 tick:

while (1) {
  printf("进入APP程序, uwTick:%lu\r\n", HAL_GetTick());
  HAL_Delay(500);
}

修改后的 main.c 关键片段:

int main(void)
{
  SCB->VTOR = 0x08020000U;     // 重定位向量表到 APP 区
  HAL_Init();
  __enable_irq();              // 修复点 1:重新使能全局中断
  SystemClock_Config();
  MX_GPIO_Init();
  MX_USART1_UART_Init();

  while (1) {
    printf("进入APP程序, uwTick:%lu\r\n", HAL_GetTick()); // 修复点 2
    HAL_Delay(500);
  }
}

四、验证结果

重新编译烧录后,串口正常持续输出,tick 值合理递增:

进入APP程序, uwTick:0
进入APP程序, uwTick:501
进入APP程序, uwTick:1002
进入APP程序, uwTick:1503
...

五、经验总结

5.1 Bootloader → APP 跳转的标准动作

  • 关闭所有外设、清除时钟使能(HAL_RCC_DeInit)
  • 关闭 SysTick(SysTick->CTRL = 0 等)
  • 清除所有 NVIC 中断使能位和挂起位
  • 设置 MSP(__set_MSP)
  • 重定位 VTOR(也可放到 APP 端做)
  • 明确全局中断的开关职责:要么 Bootloader 跳转前重新 __enable_irq(),要么 APP 入口处 __enable_irq(),二者必有其一

5.2 PRIMASK 在跨镜像跳转时的行为

__disable_irq() 本质是设置 PRIMASK = 1。CPU 复位会清零 PRIMASK,但函数跳转不会。跳转到 APP 是普通的函数调用,PRIMASK 保持原值,这就是很多老教程中"先 __disable_irq() 再跳转"会踩坑的原因。

5.3 变量遮蔽陷阱

uwTick、huart1 这类 HAL 库全局变量,在 main 里不要再起同名局部变量,否则会引发非常隐蔽的 Bug(编译器不报错,运行时数据是垃圾值)。建议用 HAL_GetTick()、HAL_GetTickFreq() 这类 API 而非直接访问内部变量。

Logo

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

更多推荐