启动模式:
M3/M4内核复位后,做的第一件事:
1、从地址0X00000000处取出堆栈指针MSP的初始值,该值就是栈顶地址;即把第一个地址处保存的值作为栈顶地址赋值为MSP;
2、从地址0X00000004处取出程序计数器指针PC的初始值,该值是复位向量;即把第二个地址处(32位单片机,第二个地址就是04)保存的数据作为中断向量表的复位向量(Reset_Handler)赋值给程序计数器指针PC;
芯片厂商可以把0X00000000和0X00000004地址映射到其他地址来决定从存储器哪个位置启动,从而引申出如下几种启动方式;
启动模式选择引脚:BOOT0和BOOT1,通过对引脚电平的控制可以实现STM32从系统存储器,主闪存FLASH或者内置SRAM启动;在系统复位后的第四个时钟上升沿采样锁存判定;
三种启动方式的差异需要先了解STM32F10X系统内存结构,如下:
0X00000000~0X07FFFFFF:boot选择区域,程式都是从0地址开始执行,通过BOOT设置映射到相应位置执行程式;
0X08000000~0X0801FFFF:主闪存区域,内置FLASH位置;BOOT配置为0X时程序跳转到这个位置开始启动;这个部分就是我们用户自己编写程序通过STLINK下载保存的地方;
0X1FFFF000~0X1FFFF7FF:系统存储器区域;BOOT配置为10时程序跳转到这个位置开始启动;这个部分是STM32出厂就带有的BOOTLOADER程序,用于串口下载的引导程序,用户可以通过串口下载程序,通过BOOTLOADER引导后将程序同样保存到主闪存内;所以执行系统存储器启动,就是执行串口下载,将程序下载到FLASH里;一般理解为串口下载程序的办法,当程序下载完成后,BOOT引脚还是要变更成主闪存启动,因为程序已经保存到FLASH里;系统存储器并不是启动程序的一种方式,而是下载程序的一种方式,程序还是保存在FLASH里,需要从FLASH启动程序才能使STM32正常运行;
0X1FFFF800~0X1FFFF88F:选项字节,存放一些独立于用户代码的配置参数,STM32出厂已设定;不会因为掉电或者用户下载程序而丢失;
0X20000000~0X3FFFFFFF:SRAM区域,BOOT配置为11时程序跳转到这个位置启动;一般为程序员调试程序用途,在不擦除FLASH的情况下,修改部分代码内容后调试;掉电丢失;
0X40000000~0X40023400:外设寄存器地址,也是存储器的一部分,操作这个寄存器就可以操作对应外设;
0XE0000000~0XE0100000:M3/4内核的外设寄存器地址;
启动流程:
第一步:RESET复位
第二步:从0X00000000位置开始启动程序,由于BOOT配置,可映射到其他启动位置;按正常flash启动方式来说,则映射到0X00000000获取MSP值(栈顶地址),和0X00000004获取PC值(指向Reset_Handler,在STM32的启动文件中);
第三步:调用用户自己编写的main函数;
启动文件说明:
1、初始化MSP;
2、初始化PC;
3、设置堆栈大小,Heap_Size(堆)、Stack_Size(栈)
4、初始化中断向量表;__Vectors定义
DCD __initial_sp ; Top of Stack就是在获取栈顶指针MSP
5、调用初始化函数;可选的,如调用Systeminit函数;
6、调用__main函数,标准C库函数,执行一系列设置;
7、调用用户自己编写的main函数;
Reset_Handler函数说明
汇编语言:
Reset_Handler PROC
EXPORT Reset_Handler [WEAK] //标明Reset_Handler函数是全局属性,可被外部调用
IMPORT __main //申明要调用来自外部的__main函数
IMPORT SystemInit //申明要调用来自外部的SystemInit函数
LDR R0, =SystemInit //将SystemInit函数的地址写到R0寄存器
BLX R0
/*BLX reg是跳转到由寄存器reg给出的地址,并根据REG的LSB切换处理器;状态还要把转移前的下条指令地址保存到LR。这行代码就是实现调用SystemInit函数运行,运行之后跳到下一条指令执行*/
LDR R0, =__main //同上
BX R0 //同上
ENDP
/*EXPORT:标明全局属性,可被外部使用*/
/*IMPORT:申明来自外部文件,类extern*/
/*PROC:定义子程序*/
/*ENDP:表示子程序结束*/
/*WEAK:弱定义,表示用户可以在其他地方重新定义这个函数,此时这里的这个函数失效*/
栈(Stack):
编译器自动分配和释放,存放函数参数、局部变量等;函数变量多,嵌套关系复杂时就要加大栈
堆(Heap):
程序员分配和释放,如malloc、calloc、realloc等
流程图解:实际指针地址可能因为工程文件大小不同会有差异,主要说明启动过程的执行方案;
参考:
1、全是干货 | STM32启动过程及启动模式详解【非常重要】_哔哩哔哩_bilibili