STM32启动过程,FLASH地址为啥不是0x0?
在 STM32 微控制器中,程序起始地址看似不符合预期(例如 FLASH 基地址为 0x08000000 而非 0x0),这一现象主要源于 ARM Cortex-M 架构的特殊设计和 STM32 的存储器映射机制。以下是详细解释:
1. Cortex-M 的向量表重定位机制
Cortex-M 处理器(如 STM32 采用的)在复位后,会从地址 0x00000000 处读取初始栈顶指针(MSP),并从地址 0x00000004 处获取复位向量(即程序入口地址)。但 STM32 的 FLASH 实际物理地址是 0x08000000,这就产生了地址不一致的问题。
解决方案:
STM32 通过存储器映射机制,将 FLASH 的内容映射到地址 0x0 处。当 CPU 访问 0x0 地址时,实际上访问的是 0x08000000 处的 FLASH 内容。这种映射是硬件自动完成的,对软件透明。
2. STM32 的存储器映射
STM32 的存储器空间被划分为多个区域,典型映射如下:
- 0x0000 0000 ~ 0x1FFF FFFF:系统存储器(SRAM、引导程序等)
- 0x0800 0000 ~ 0x08FF FFFF:主 FLASH 存储器
- 0x2000 0000 ~ 0x200F FFFF:SRAM
- 0x4000 0000 ~ 0x5FFF FFFF:外设寄存器
关键机制:
- 系统存储器映射:复位后,0x0 地址默认映射到 FLASH(0x08000000),因此程序可以从 0x0 开始执行。
- Boot 引脚配置:通过设置 BOOT0/BOOT1 引脚,可以改变 0x0 地址的映射,例如映射到系统存储器(用于 ISP 下载)或 SRAM(用于调试)。
3. 向量表地址寄存器(VTOR)
Cortex-M 允许通过VTOR 寄存器动态重定位向量表。默认情况下,VTOR 指向 0x0,即映射后的 FLASH 起始地址。如果需要(例如在 IAP 升级时),可以通过代码修改 VTOR 指向 SRAM 中的新向量表:
SCB->VTOR = 0x20000000; // 将向量表重定位到SRAM (0x20000000)
4. 为什么 FLASH 物理地址是 0x08000000?
- 历史原因:ARM 架构早期(如 ARM7/ARM9)采用冯・诺伊曼架构,程序和数据共用地址空间,0x0 通常是实际的起始地址。
- Cortex-M 的改进:Cortex-M 采用哈佛架构,程序和数据有独立的总线,允许更灵活的存储器映射。STM32 将 FLASH 放在 0x08000000 是为了给系统存储器(如引导程序)留出空间。
- 兼容性:通过映射机制,Cortex-M 保持了与传统 ARM 架构的启动流程兼容性(仍从 0x0 读取向量表)。
5. 启动流程示例
当 STM32 复位时:
- CPU 从0x00000000(实际映射到 0x08000000)读取栈顶指针。
- 从0x00000004(实际为 0x08000004)读取复位向量(即
Reset_Handler
函数地址)。 - 执行
Reset_Handler
,初始化系统时钟、外设,并跳转到main()
函数。
总结
- 地址 0x0 是逻辑起始地址:CPU 通过映射机制访问 0x0,实际对应 FLASH 的物理地址 0x08000000。
- 映射可配置:通过 BOOT 引脚或 VTOR 寄存器,可以改变 0x0 地址的映射目标。
- 设计目的:这种机制兼顾了启动兼容性和系统灵活性,允许 STM32 支持多种启动模式(如从 FLASH、SRAM 或系统存储器启动)。
理解这一机制对 STM32 开发至关重要,特别是在处理中断向量表、IAP 升级或多应用分区时。
更多内容全在下方专栏
全网最受欢迎的嵌入式笔试专栏
笔试专栏包含全部最新的笔试必考考点,非常适合在找工作面经薄弱的同学
3000+订阅还会涨价,提前订阅提前享受,持续更新中。
专栏链接:https://www.nowcoder.com/creation/manager/columnDetail/mPZ4kk
#嵌入式笔面经分享#