问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

GD32/STM32启动过程详解

创作时间:
作者:
@小白创作中心

GD32/STM32启动过程详解

引用
CSDN
1.
https://blog.csdn.net/Yin_w/article/details/139102806

GD32/STM32启动过程

本文以STM32F407为例简单介绍其启动过程。

一、系统架构

STM32F407的系统架构如图所示:

  • I-Code总线(指令总线):内核通过此总线获取指令。此总线访问的对象是包含代码的存储器(内部 Flash/SRAM 或通过 FSMC 的外部存储器)。
  • D-Code总线(数据总线):内核通过此总线进行立即数加载和调试访问。此总线访问的对象是包含代码或数据的存储器(内部Flash 或通过 FSMC 的外部存储器)。
  • S-Code总线(系统总线):此总线用于访问位于外设或 SRAM 中的数据。也可通过此总线获取指令(效率低于 ICode)。此总线访问的对象是112 KB、 64 KB 和 16 KB 的内部 SRAM、包括 APB 外设在内的 AHB1 外设、 AHB2 外设以及通过 FSMC 的外部存储器。

代码区(code area):从0x00000000开始,通过指令总线(ICode Bus)和数据总线(DCode Bus)对Flash中代码进行访问。
数据区(SRAM):从0x20000000开始,通过系统总线(System Bus)进行访问。

二、自举配置

所谓的自举模式(Boot Mode):就是根据BOOT0和BOOT1两个引脚的电平决定STM32从哪里启动程序。存储器采用固定的存储器映射,代码区域起始地址为 0x0000 0000(通过 ICode/DCode 总线访问),而数据区域起始地址为 0x2000 0000(通过系统总线访问)。 Cortex™-M4FCPU 始终通过 ICode 总线获取复位向量,这意味着只有代码区域(通常为 Flash)可以提供自举空间。 三种不同的自举模式BOOT0和BOOT1配置情况,如表 3 所示

自举过程:复位后在 SYSCLK 的第四个上升沿锁存 BOOT 引脚的值。复位后,用户可以通过设置BOOT1 和 BOOT0 引脚来选择需要的自举模式。

  1. 采用主Flash启动时,启动延迟结束CPU 将从地址 0x0000 0000 获取栈顶值,然后从始于 0x0000 0004 的自举存储器开始执行代码,而且Flash区被映射到0x08000000区,所以我们看到的是从0x0800 0000开始运行的。
  2. 如果器件从 SRAM 自举,在应用程序初始化代码中,需要使用 NVIC 异常及中断向量表和偏移寄存器来重新分配 SRAM 中的向量表。
  3. 如果从系统存储器启动程序,是通过内部的只读存储器(ROM),其中存放了一个串行引导加载器(serial bootloader),它可以通过串口、USB或者CAN等接口来接收外部的程序,并将其写入主闪存或者外部的存储器设备。

注意:BOOT0 为专用引脚,而 BOOT1 则与 GPIO 引脚共用。一旦完成对 BOOT1 的采样,相应GPIO 引脚即进入空闲状态,可用于其它用途。器件退出待机模式时,还会对 BOOT 引脚重新采样。因此,当器件处于待机模式时,这些引脚必须保持所需的自举模式配置。

排查该类问题可通过复位观察复位地址是在哪个区,在参考BOOT定义,判断是否是BOOT电平给错了或者代码加载区域错了

三、启动文件

启动文件startup_stm32f40xx.s中Reset复位代码如下:

来看一看复位后又干什么:

系统复位后,处理器首先读取向量表中的前两个字(8 个字节),第一个字存入 MSP,第二个字为复位向量,也就是程序执行的起始地址。

硬件这时自动从0x0800 0000位置处读取数据赋给栈指针SP,然后自动从0x0800 0004位置处读取数据赋给PC,完成了复位操作,

SP= 0x2000 1B10,PC = 0x0800 01A5。初始化SP、PC紧接着就初始化向量表,

当然这个值和映射后的地址0x08000000中的值也是一样的,如果是其他自举模式,复位后的地址里的值是不一样的,可以去排查0x20000000地址处的值看一下。当从flash中启动时SP在地址0x08000000中存储,PC的值在地址0x08000004中存储。但仍可以在原地址中被访问。这也就是所谓的映射。

再说说PC取出来的值0x080001A4和内存中存储的值0x080001A5为什么不一样?,末尾的1变成了0这个是由于内存对齐造成的,因为cortex-m3核PC的LSB一定读回0,因此指令至少是半字对齐的(《cortex-m3编程手册》)。LDR R0, =SystemInit 将函数SystemInit的入口地址传给R0,从反汇编窗口可以看到指令被写成LDR r0, [pc,#36],表明SystemInit的入口地址在存放在PC指针偏移36处,即: 0x08000022C(+0x4)+0x24=0x08000254(因为CM3内部使用了指令流水线,读PC时返回的值是当前指令的地址+4《Cortex™-M3权威指南》)下一条指令在0x0800022E处。

四、启动流程

在没有Boot loader时候整个MCU从复位开始启动如图

个人总结的MCU下电后整个启动流程如图所示:

总结

关于STM32的启动过程还是比较重要的,总结归纳为以下:

硬件启动:

  1. BOOT0和BOOT1两个引脚的电平决定STM32从哪里启动程序
  2. 从零地址处开始加载程序

软件:

  1. 初始化MSP主堆栈栈顶地址和PC指针
  2. 初始化中断向量表
  3. 运行systemInit初始化时钟
  4. 调用C库函数_main初始化用户堆栈,从而最终调用main函数
© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号