这一章在干嘛? 分析 STM32F407 上电启动过程:启动模式选择(BOOT0/BOOT1)→ 启动文件 `startup_stm32f407xx.s` 里做了什么(堆栈初始化、中断向量表、Reset_Handler)→ MAP 文件怎么看(代码段、只读段、RAM 占用)。
9.1 启动模式
STM32F407 通过 BOOT0/BOOT1 引脚选择启动源:
| BOOT1 | BOOT0 | 启动源 | 典型用途 |
| x | 0 | 主 Flash | 正常运行 |
| 0 | 1 | 系统存储器(ST 固化 bootloader) | 串口下载 |
| 1 | 1 | 内置 SRAM | 调试 |
开发板默认 BOOT0=0(Flash 启动),所以无需改动。
原书图 9.1.1:BOOT 引脚选择启动模式
9.2 启动文件分析
startup_stm32f407xx.s(汇编)核心流程:
- 栈初始化:
Stack_Size EQU 0x00000400 → 1 KB 栈空间; - 堆初始化:
Heap_Size EQU 0x00000200 → 512 B 堆; - 中断向量表:第一个字是栈顶指针;第二个字是 Reset_Handler 地址;
- Reset_Handler:① 调用 SystemInit(配置 FPU / 向量表偏移)② 调用 __main → 最终进入 main。
原书图 9.2.1:启动文件结构图
为什么 main 前要调 SystemInit? 默认外部晶振未起,PLL 未配,主频不是 168 MHz,所以必须先配时钟。
9.3 MAP 文件分析
MAP 文件 = 链接器输出,记录了:
- 代码段 (Code/RO):Flash 占用
Code + RO Data - 数据段 (RW):RAM 占用
RW Data + ZI Data(ZI = 0 Init)
看 MAP 的方法:
- 找到 main.c 里调用了哪些库函数;
- 用
Unmangled Symbols Sorted by Name 看全局变量位置; - 用
Image Symbol Table 看每个函数的 Flash 地址。
例:发现 SPI 没用却占 8 KB Flash → 是没用到的 HAL_SPI 模块被链进来了,去工程里删掉 stm32f4xx_hal_spi.c。
原书图 9.3.1:MAP 文件示例
RAM 不够怎么办? 看 ZI 大小;优化:减少大数组、把大缓冲移到外扩 SRAM、调小 HAL 库缓冲。
🧠 小测验BOOT0=0 时从哪里启动?
主 Flash,运行用户程序。
Reset_Handler 做了哪两件事?
调 SystemInit 配置系统时钟,调 __main 进入 main。
MAP 文件 Code 段代表什么?
Flash 占用,包括函数和常量。