这一章在干嘛?

分析 STM32F407 上电启动过程:启动模式选择(BOOT0/BOOT1)→ 启动文件 startup_stm32f407xx.s 里做了什么(堆栈初始化、中断向量表、Reset_Handler)→ MAP 文件怎么看(代码段、只读段、RAM 占用)。

9.1 启动模式

9.2 启动文件分析

9.3 MAP 文件分析

9.1 启动模式

STM32F407 通过 BOOT0/BOOT1 引脚选择启动源:

BOOT1BOOT0启动源典型用途
x0主 Flash正常运行
01系统存储器(ST 固化 bootloader)串口下载
11内置 SRAM调试

开发板默认 BOOT0=0(Flash 启动),所以无需改动。

原书图 9.1.1:BOOT 引脚选择启动模式原书图 9.1.1:BOOT 引脚选择启动模式

9.2 启动文件分析

startup_stm32f407xx.s(汇编)核心流程:

  1. 栈初始化Stack_Size EQU 0x00000400 → 1 KB 栈空间;
  2. 堆初始化Heap_Size EQU 0x00000200 → 512 B 堆;
  3. 中断向量表:第一个字是栈顶指针;第二个字是 Reset_Handler 地址;
  4. Reset_Handler:① 调用 SystemInit(配置 FPU / 向量表偏移)② 调用 __main → 最终进入 main。

原书图 9.2.1:启动文件结构图原书图 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 的方法:

  1. 找到 main.c 里调用了哪些库函数;
  2. Unmangled Symbols Sorted by Name 看全局变量位置;
  3. Image Symbol Table 看每个函数的 Flash 地址。

例:发现 SPI 没用却占 8 KB Flash → 是没用到的 HAL_SPI 模块被链进来了,去工程里删掉 stm32f4xx_hal_spi.c。

原书图 9.3.1:MAP 文件示例原书图 9.3.1:MAP 文件示例

RAM 不够怎么办? 看 ZI 大小;优化:减少大数组、把大缓冲移到外扩 SRAM、调小 HAL 库缓冲。