STM32的启动地址是0x08000000还是0x00000000?

一、先看总结

  1. 基于ARM内核的芯片代码区都是从0x00000000开始执行的,但是通过boot启动模式选择从不同的地址进行重映射到0x0000 0000执行。
  2. 0x08000000中存放的并不是main()函数的地址,是STM32中的主FLASH(用户代码空间)的起始地址。
  3. 上电后执行复位程序,先执行SystemInit()函数初始化系统时钟,然后执行main()函数。

二、内容详解

先看有哪些启动模式,通常通过BOOT1、BOOT0的引脚状态来确定启动模式

  • MCU常用启动模式默认选择主闪存存储器的启动模式,即将0x08000 000~0x081FF FFF (注根据STM32型号不同,FLASH大小也不同)空间地址重映射至0x00000000-0x001 F FFFF,启动时CPU就是从重映射的地址读取指令
  • 系统存储器启动模式,即MCU启动后将0x1FFF 0000~0x1FFF 7A0F的地址重映射至0x0000 0000-0x000 7A0F,0x1FFF 0000~0x1FFF 7A0F这段空间储存的为STM32出厂自带的Bootloader程序,该模式下常见的是使用FlyMCU

进行程序下载。

  • 内置SRAM启动模式,即只能在0x20000000开始的地址区访问SRAM

接下来让我们看看如何通过keil来查看STM32芯片的主FLASH大小和RAM大小

  • 选择芯片型号

  • 创建工程后,点击魔术棒查看

这里选的是STM32F429BITx芯片

红色部分中:IROM1为片上程序存储器,即常说的主FLASH,该处理器Flash大小为2MB,即0x80000 地址区间为0x800 0000~0x081F FFFF

蓝色部分中:IRAM1为片上数据存储器,即常说的RAM,对该处理器RAM大小为256KB,即0x30000 + 0x10000 = 0x40000 = 256KB

根据上诉描述来理解什么是重映射

对于CPU来说它是永远从0x00000000地址去加载执行程序的,然后单片机会通过Boot管脚的配置去将Main FLASH(0x0800 0000)重映射或者芯片出厂自带的Bootloader(0x1FFF 0000)重映射,故而代码是下载到 0x80000000 往后的存储空间中,却说运行又是从 0x00000000地址运行的。

疑问:下载时,能不能使用 0x0000 0000 地址来下载?

答:这个不行,因为下载时,0x0000 0000 - 0x001F FFFF 还没有被重映射到 flash 上,只能使用 0x0800 0000 来下载。

若STM32从0x8000 0000开始重映射到0x00000000地址,那么单片机的启动流程是怎样的?

  • 初始化栈顶指针

从0x0800 0000读取栈顶地址,并将该地址存入MSP中。

栈顶地址的值为0x2000 xxxx,工程所生成bin文件的前两个字节即为栈顶地址。

从0x2000 0000到0x2000 xxxx即为程序所运行的范围,该段内存分布为:RW段、ZI段:其中RW段为可读写的非0数据段,ZI段包括了0数据段、堆区、栈区。

  • 跳转至复位中断(Reset_Handler(void))

从0x0800 0004读取中断向量表的首地址(即复位中断入口地址),装入PC程序计数器,跳转执行

  • 系统时钟设置(在复位中断程序内被调用)

进行系统时钟的初始化,该函数内含VTOR寄存器设置,即中断向量偏移设置:

SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET;

产品IAP由bootloader跳转app程序时,需要设置中断向量偏移

  • 跳转至标准库_main()程序

LDR R0,=_main

该部分主要进行两部分工作:

数据段加载:把RW段(初始化为非0值的全局变量)从Flash搬运到SRAM中

开辟堆栈:依照启动文件所设置的堆栈大小初始化堆栈区域;

该处需要注意:如果编译勾选了using micro_lib,程序则采用单区存放堆栈的方式;否则,采用双区存储的方式,分别初始化堆区、栈区。

  • 进入C文件中的main函数
  • 流程图

三、再次总结

  1. 基于ARM内核的芯片代码区都是从0x00000000开始执行的,但是通过boot启动模式选择从不同的地址进行重映射到0x0000 0000执行。
  2. 0x08000000中存放的并不是main()函数的地址,是STM32中的主FLASH(用户代码空间)的起始地址。
  3. 上电后执行复位程序,先执行SystemInit()函数初始化系统时钟,然后执行main()函数。

附总内存映射图:

  • 13
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值