2. 启动模式与 BootROM:Boot 引脚配置、系统存储器启动、内置 BootLoader 行为分析
好,咱们正式开始第二讲。上一章我们把多核架构的硬件基础聊透了,这一章要解决一个更实际的问题:芯片上电后,第一行代码到底从哪里来?
说白了,就是启动模式的选择。STM32 给了你几种不同的“入口”,通过几个引脚的电平状态来决定。我刚开始接触 STM32H7 的时候,就因为在启动模式上栽过跟头——板子焊好,程序死活跑不起来,最后发现是 BOOT 引脚电平没拉对。嗯,这种坑踩一次就够了。
2.1 Boot 引脚配置:硬件的“第一选择”
STM32 的启动模式,是通过 BOOT0 和 BOOT1(部分型号是 nBOOT1 或 BOOT2)这两个引脚的电平组合来决定的。你想想看,芯片刚上电,Flash 里还没程序,或者程序跑飞了,总得有个“安全网”吧?Boot 引脚就是干这个的。
以最常见的 STM32H7 系列为例,它的启动模式选择如下:
| BOOT0 | BOOT1 | 启动区域 | 说明 |
|---|---|---|---|
| 0 | X | 主 Flash | 正常用户程序启动,最常用 |
| 1 | 0 | 系统存储器 | 内置 BootLoader,用于串口/DFU 下载 |
| 1 | 1 | SRAM | 调试或临时运行代码用 |
这里要注意,不同系列的 STM32,BOOT1 的对应关系可能不一样。比如 STM32F1 系列,BOOT1 是复用在 PB2 引脚上的,而 H7 系列则有独立的 nBOOT1 选项字节。查手册时一定要看对应型号的 “Boot mode selection” 章节。
2.2 系统存储器启动:内置 BootLoader 的秘密
当 BOOT0=1、BOOT1=0 时,芯片会从 系统存储器(System Memory) 启动。这块区域是 ROM,出厂时已经烧录了一段固件——也就是我们常说的 内置 BootLoader。
这段 BootLoader 是 ST 官方写的,用户不能修改。它的主要作用是什么?说白了,就是给你一个“后门”,通过串口、USB、CAN 等接口来下载用户程序。你想想看,如果 Flash 里的程序把芯片搞死了,或者新板子第一次烧录,总得有个办法把代码写进去吧?
内置 BootLoader 支持的外设接口,不同型号差异很大。我整理了一个常用对照表:
| 接口 | STM32F1/F4 | STM32H7 | STM32L4 |
|---|---|---|---|
| USART | ✓ | ✓ | ✓ |
| USB DFU | 部分支持 | ✓ | ✓ |
| CAN | ✗ | ✓ | ✗ |
| I2C | ✓ | ✓ | ✓ |
| SPI | ✓ | ✓ | ✓ |
2.3 内置 BootLoader 行为分析:从复位到等待命令
好,现在我们来深入看看,当芯片从系统存储器启动后,BootLoader 到底干了些什么。
它的执行流程大致如下:
- 初始化硬件: 配置系统时钟、复位所有外设、初始化堆栈。
- 检测启动引脚: 再次确认 BOOT 引脚状态,确保是从系统存储器启动。
- 配置选定的通信外设: 根据芯片型号,初始化 USART1、USART3、USB OTG、CAN 等接口。
- 发送启动信息: 通过选定的接口发送 0x7F(0x7F 是 BootLoader 的握手信号)。
- 等待主机命令: 进入循环,等待上位机(如 STM32CubeProgrammer)发送命令。
这个流程里,有一个关键点:BootLoader 会先检测各通信接口,看哪个接口有数据过来。它并不是同时监听所有接口,而是按优先级顺序轮询。比如 H7 系列,会先检测 USART1,再检测 USART3,然后是 USB DFU,最后是 CAN。
下面我用一个简单的流程图,把整个启动模式选择到 BootLoader 执行的过程串起来:
2.4 实战技巧:如何判断当前是从哪个模式启动的
在实际调试中,你可能会遇到一个问题:我怎么知道芯片当前是从 Flash 启动的,还是从 BootLoader 启动的?
我一般用两种方法:
- 看 PC 指针: 在调试器里暂停程序,查看 PC(程序计数器)的值。如果 PC 在 0x0800xxxx 范围内,说明是从 Flash 启动;如果在 0x1FFFxxxx(系统存储器地址),说明在 BootLoader 里。
- 看串口输出: 如果芯片进入了 BootLoader,它会通过串口发送 0x7F。你用串口助手抓一下,看到 0x7F 就说明 BootLoader 在等你。
2.5 避坑指南:BootLoader 常见故障
最后,我总结几个我在项目中遇到过的 BootLoader 相关故障,希望能帮你少走弯路:
- 故障 1:进入 BootLoader 后串口无响应
我曾经遇到过,板子进入系统存储器模式后,串口发数据没反应。后来发现是串口引脚被其他外设占用了。BootLoader 使用的串口引脚是固定的(比如 USART1 的 PA9/PA10),如果这些引脚被复用成其他功能,BootLoader 就无法正常工作。 - 故障 2:USB DFU 枚举失败
前面提到了,H7 的 USB DFU 需要精确的 48MHz 时钟。如果你的板子没有外部晶振,或者晶振频率不对,USB 就无法枚举。解决办法:要么加外部晶振,要么用 HSI 并校准。 - 故障 3:下载完成后程序不运行
有时候用 BootLoader 下载完程序,复位后程序没跑起来。检查一下你的程序起始地址对不对。BootLoader 下载时,默认会把程序写入 Flash 的起始地址(0x08000000)。如果你的程序链接脚本里定义了别的地址,那肯定跑不起来。
嗯,这一章的内容就到这里。启动模式看似简单,但它是整个系统运行的基石。搞懂了 Boot 引脚和 BootLoader 的行为,你就能在芯片“不听话”的时候,知道从哪里下手去查。