启动模式
首先从芯片的启动模式讲起,如下图所示 这是STM32的三种启动方式
- BOOT0拉低,BOOT1任意,芯片从Main Flash memory(0x08000000)启动
- BOOT0拉高,BOOT1拉低,芯片从系统存储System Memory启动
- BOOT0拉高,BOOT1拉高,芯片从SRAM(0x20000000)启动
STM32的部分存储区域见下图(为方便讲解,仅截取部分)
烧录方式(ISP ICP IAP的区别)
启动方式的不同,使得STM32的烧录方式也有了更多的选择,这里扩展谈一下ISP,ICP,IAP吧
ISP:boot0=1 boot0=0,系统从System Memory启动,此处是ST公司在芯片出厂时固化好的一块程序,也可以叫做BootLoader或ISP程序,通过此程序,可以将串口下载进板子的固件程序(hex文件)写入到Main memory中,然后再将Boot0拉低,重启即可运行Main memory出的代码。
ICP:Boot0=0,BOOT1=x,系统直接从Main memory启动,通过JTAG或SWD可以直接将代码烧录到Main memory
IAP:将Mian memory分成两部分,第一部分可以再写一个bootloader程序,它的作用是通过有线或者无线的方式获取外部的固件升级包,然后再写入到第二部分的flash中,重定位中断向量表的地址和更改PC指向,这样可以自动实现板子程序的自动升级
中断向量表
启动方式不同,决定了芯片是从Flash(0x08000000),还是SRAM(0x20000000)或者是其它地方启动,然而处理器不会去费力去这些地址,它最开始是去0x00000000这个地方找东西,硬件电路会把flash的东西或者SRAM的东西映射到0x00000000这个地方 所以,知道0x00000000这个地方有什么是理解芯片启动的第一步,如下图 0x00000000的地方有个MSP(Main stack pointer)的初始值,保存了栈顶地址,系统一上电的第一件事就是去把栈的位置找到,因为在后面复位处理过程中,可能会产生NMI或者HardFault的异常,处理异常肯定需要用到栈哒 后面就是到复位向量了,这里保存的是Reset Handler的地址,PC会直接跳转到这个地方进行复位处理,但这个复位处理需要做些啥呢?这就需要看芯片的启动文件了,stm32的话对应得就是这个: 这个文件可以去读一读,对应着这里所说的中断向量表 直接上Reset_Handler 不需要太多汇编知识应该也能看懂,复位处理里面只做了两个操作
- 调用SystemInit函数
- 调用__mian这个函数
下面就对这两个函数所做的事情进行介绍
SystemInit
上面是从STM32的系统文件里截取SystemInit函数的一部分代码,可以看出大部分是和时钟配置相关的,最后还将中断向量表的位置设置到了0x08000000(存储程序的Flash的起始地址),
__main
注意这个__main不是主程序里的main函数,这是C库里面的,当然,在执行到__main的最后,将会跳转到main()函数,执行主程序。 再来看看__main里做了什么,如下图 可以知道里面主要调用了__scatterload和__rt_entry,分别介绍下它们的作用
__scatterload:根据分散加载文件把RW数据拷贝到RAM空间,然后在RAM空间分配ZI数据的空间,这样便建立好运行时的存储空间。
__rt_entry:负责初始化C库,还设置应用程序的堆和栈,初始化库函数等操作
接下来便跳转到main(),执行应用程序
芯片启动流程到此结束
如果还需要理解更深刻的话,可以再去看看keil生成的map文件,具体操作可以参考下方链接https://blog.csdn.net/ybhuangfugui/article/details/75948282
|