3. STM32启动流程与复位调试

STM32从上电到执行用户main()函数,中间经历了一条由硬件与固件共同决定的固定路径。理解这条路径,是定位"程序不跑""跑飞""复位反复发生"等问题的前提。本节围绕复位类型、启动模式选择与启动异常定位展开,重点说明每种复位会保留或清除哪些状态,以及BOOT引脚如何决定CPU取指的第一条指令来自哪里。

一、三类复位的区别与影响范围

STM32的复位源可以归为三类,它们的触发条件与影响范围差异很大,调试时必须先分清是哪一类。

上电复位(Power-on Reset)由VDD上电或掉电触发,通过内部POR/PDR电路产生。它复位整个芯片,包括备份域之外的几乎所有逻辑。上电复位后,备份域寄存器(RTC、BKP)内容通常丢失,除非VBAT独立供电且备份域未被复位。

系统复位(System Reset)是范围最广的常规复位,可由NRST引脚低电平、看门狗(IWDG/WWDG)、软件复位(NVIC_SystemReset())、低功耗管理复位、选项字节加载复位等触发。系统复位会复位所有寄存器,但不复位备份域,也不复位RCC_BDCR中的RTC配置。因此系统复位后,RTC仍在走时,备份寄存器内容保留。

备份域复位(Backup Domain Reset)只影响备份域,包括RTC、BKP寄存器和RCC_BDCR。它由软件置位RCC_BDCR的BDRST位,或VBAT/VDD上电时触发。备份域复位不会影响CPU和外设,常用于需要重新初始化RTC的场景。

调试时,第一步应读取RCC_CSR寄存器中的复位标志位,判断本次复位来源。常见标志包括PINRSTF(NRST引脚)、PORRSTF(上电/掉电)、SFTRSTF(软件)、IWDGRSTF(独立看门狗)、WWDGRSTF(窗口看门狗)、LPWRRSTF(低功耗)。这些标志在系统复位后保留,读取后需手动清除,否则下次无法区分。

if (RCC_GetFlagStatus(RCC_FLAG_IWDGRST) != RESET) {
    // 本次复位由独立看门狗触发
    RCC_ClearFlag();   // 清除标志,避免下次误判
}

二、启动模式与BOOT引脚

复位释放后,CPU从地址0x0000_0000取MSP初值,从0x0000_0004取复位向量。这个"0地址"实际映射到哪里,由BOOT引脚在复位采样时刻的电平决定。

以STM32F1为例,BOOT0与BOOT1组合决定三种启动模式:BOOT0=0时从主Flash启动;BOOT0=1、BOOT1=0时从系统存储器启动(内置Bootloader,用于串口下载);BOOT0=1、BOOT1=1时从内嵌SRAM启动。对于F4、H7等只有BOOT0的型号,BOOT0=0为主Flash,BOOT0=1为系统存储器,SRAM启动需通过选项字节配置。

关键点在于:BOOT引脚只在复位释放的瞬间被采样。采样完成后,引脚可作它用。如果BOOT0悬空或上电时被外设拉高,芯片可能进入Bootloader而非用户程序,表现为"程序不运行"。因此BOOT0必须通过电阻明确拉低或拉高,不能悬空。

STM32复位源与启动模式选择 复位源 上电复位 POR/PDR 系统复位 NRST/IWDG/SW 备份域复位 BDRST RCC_CSR 标志位 复位释放瞬间 采样 BOOT0 / BOOT1 决定 0x0000_0000 映射 ⚠ 悬空 = 不确定 启动模式 BOOT0=0 → 主Flash 用户程序正常运行 BOOT0=1,BOOT1=0 → 系统存储器 内置Bootloader,串口下载 BOOT0=1,BOOT1=1 → SRAM 调试用,掉电丢失 复位释放后的启动流程 取MSP初值 0x0000_0000 取复位向量 0x0000_0004 执行Reset_Handler 汇编启动文件 SystemInit() 时钟/向量表 main() 用户代码 启动异常定位:检查BOOT引脚电平 → 读RCC_CSR复位标志 → 确认向量表偏移 → 验证MSP初值 注:不同系列BOOT引脚数量与选项字节配置存在差异,以对应参考手册为准

三、启动异常定位方法

当程序"不运行"时,按以下顺序排查效率最高。

第一步:确认BOOT引脚电平。用万用表或示波器测量复位释放瞬间BOOT0的实际电平。若BOOT0被外部电路拉高,芯片进入Bootloader,用户程序不会执行。常见错误是BOOT0通过10kΩ上拉后忘记下拉,或调试器复位时驱动了BOOT0。

第二步:读取复位标志。在main()开头读取RCC_CSR,判断是否发生了看门狗复位或低功耗复位。若IWDGRSTF置位,说明程序在初始化完成前未及时喂狗,应检查看门狗超时时间与初始化顺序。

第三步:检查向量表偏移。如果使用了Bootloader+APP的双区方案,APP必须设置SCB->VTOR为APP起始地址。若VTOR未设置,中断会跳转到Bootloader的向量表,导致HardFault。同时需确认链接脚本中Flash起始地址与APP实际烧录地址一致。

第四步:验证MSP初值。用调试器查看0x0000_0000处的值,它应指向SRAM末尾(如0x2000_5000)。若该值异常(如0xFFFFFFFF),说明Flash未正确烧录或读保护生效。

调试小技巧:在Reset_Handler的第一条指令处设置断点,若无法命中,说明CPU未从主Flash取指,应优先检查BOOT引脚与选项字节。若命中但进入HardFault,则问题在时钟配置或向量表。
注意:系统复位不会清除备份域。若RTC配置错误导致反复复位,仅靠系统复位无法恢复,需执行备份域复位(置位RCC_BDCR.BDRST)后重新配置RTC。