GD32/STM32启动过程
文章目录
- 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的启动过程还是比较重要的,总结归纳为以下:
硬件启动:
①BOOT0和BOOT1两个引脚的电平决定STM32从哪里启动程序
②从零地址处开始加载程序
软件:
③初始化MSP主堆栈栈顶地址和PC指针
④初始化中断向量表
⑤运行systemInit初始化时钟…
⑥调用C库函数_main初始化用户堆栈,从而最终调用main函数