参考资料
1.https://blog.csdn.net/weixin_42328389/article/details/120656722
2.https://space.bilibili.com/678329477/channel/seriesdetail?sid=427350
3.https://blog.csdn.net/CynalFly/article/details/114757347
4.https://blog.csdn.net/qq_39400113/article/details/116051401
5.https://blog.csdn.net/tianshi_1988/article/details/51084516
本文主要回答关于STM32是如何运行的,为什么是main函数的疑问。
启动文件:告诉MCU如何找到并执行main函数,STM32F4的启动文件为《startup_stm32f407xx.s》
启动文件完成的主要工作:
1.设置堆栈指针SP = _initial_sp
2.设置PC指针 = Reset_Handler
3.配置系统时钟
4.配置外部SRAM用于程序变量等数据存储(可选)
5.调用C库中的_main函数,最终调用main函数
上述知识点见《Cortex M3与M4权威指南》的4.8 Reset and reset sequence
STM32的启动方式:
BOOT0引脚状态 | BOOT1引脚状态 | 启动模式 | 使用情景 |
0 | X | 从Flash中启动 | 正常运行时选择这种模式 |
1 | 0 | 从系统存储器启动 | 做ISP下载时用 |
1 | 1 | 从内嵌SRAM中启动 | 调试用,一般很少使用 |
存储器映射(memory map):把整个MCU内以外的存储器、外设等所有模块全部进行统一的编址,即使用地址来描述各个模块的位置。
STM32是32位单片机,地址总线是32位的,故可以寻址的空间大小为2^32B=4GB。
《Cortex M3与M4权威指南》中,预先定义好的存储器映射(半导体厂家大范围定义),ST在该基础上所做的存储器定义
上电后,CPU从地址0开始执行
存储器重映射:解决 从地址0开始执行程序 与 三种启动方式下程序存放地址不同的问题
从Flash中启动时,芯片上电后,0x0800 0000地址被映射到0地址处
从系统存储器启动时,芯片上电后,0x1FFF 0000地址被映射到0地址处。开始执行厂家提供的BootLoader,将程序下载到系统的Flash中。
注意:程序下载好后,要重新设定BOOT引脚电平,让程序从Flash中启动
从内嵌SRAM中启动时,芯片上电后,0x2000 0000地址被映射到0地址处
STM32属于小端模式:较高的有效字节存储在较高的存储器地址,较低的有效字节存储在较低的存储器地址。
中断向量表位于代码段的最前面,其内存放中断服务程序的入口地址。
借用硬汉的图,
上图解释:1.启动方式为从Flash中启动,上电后从0x8000 0000地址开始读取内容(此时还未开始执行程序);
2.开始四个字节是堆栈栈顶指针的地址,0x2000 26B0(小端模式),MSP寄存器的值为0x2000 26B0
3.后四个字节的内容(0x0800019D)装入程序计数器PC中.
4.CPU从PC寄存器指向的物理地址取出第一条指令开始执行。也就是开始执行复位中断服务程序Reset_Handler。
跳转到了另外的地址上开始执行程序,避开了中断向量表中的下一个中断
触发中断时,是从中断向量表中获取对应中断函数的入口地址,转到对应的地址执行,我们所编写的是中断服务函数中的内容
5. 调用__mian函数,__main函数是由编译器自动创建的,无法找到。当编译器发现定义了main函数,那么就会自动创建__main。可以用在线调试的方式来查看。
__main函数最后会跳转到main函数
6.回到熟悉的main函数。
突然想到的问题:如何判断当前CPU是大端的,还是小端的?
方法1:使用联合体 union
方法2:强制类型转换
标签:函数,启动,存储器,STM32,地址,main,过程 From: https://www.cnblogs.com/xing-2/p/17107385.html