【32单片机学习】(11)STM32启动过程详解

news/2024/10/18 14:23:42/

目录

前言

一、系统架构

二、启动配置

三、启动流程

1.首先复位MCU,获取栈顶指针MSP和PC指针的内容

2.根据PC的值找到复位中断处理函数Reset_Handler

1.进入中断处理函数Reset_Handler

2.进入SystemInit函数

3._main函数

3.进入main函数

总结


前言

         通过查阅官方手册和对实际代码进行调试仿真,了解了STM32上电启动的具体过程,在此记录一下。


一、系统架构

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

        数据区(SRAM):从0x20000000开始,通过系统总线(System Bus)进行访问。

二、启动配置

         STM32系列可以有3种启动模式,由BOOT1与BOOT0的设置决定选择Flash、System memory还是SRAM作为启动空间。

●从主闪存存储器启动(Main Flash memory):主闪存存储器被映射到启动空间(0x0000 0000),但仍然能够在它原有的地址(0x0800 0000)访问它,即闪存存储器的内容可以在两个地址区域访问,0x0000 0000或0x0800 0000。

  从系统存储器启动(System memory):系统存储器被映射到启动空间(0x0000 0000),但仍然能够在它原有的 地址(互联型产品原有地址为0x1FFF B000,其它产品原有地址为0x1FFF F000)访问它。 

 ●从内置SRAM启动(Embedded SRAM):只能在0x2000 0000开始的地址区访问SRAM,启动后这个映射消失,需要重定位中断向量表。

STM32将0x00000000到0x0005FFFF的区域作为启动空间(boot space)的别名区。

三、启动流程

1.首先复位MCU,获取栈顶指针MSP和PC指针的内容

MCU上电后,自动执行

当程序编译完成之后,sp堆栈栈顶指针都已经确定。

 R13(SP堆栈指针)的值为0x20000868(MSP)存在地址为0x00000000中,R15(PC程序计数器)的值为0x08000420存在地址为0x00000004中,堆栈指针指向sram区,且堆栈必须建立在该区。

当从flash中启动时SP在地址0x08000000中存储,PC的值在地址0x08000004中存储。但仍可以在原地址中被访问。这也就是所谓的映射。

这即是手册中所说:主闪存存储器被映射到启动空间(0x0000 0000),但仍然能够在它原有的地址(0x0800 0000)访问它,即闪存存储器的内容可以在两个地址区域访问,0x0000 0000或0x0800 0000。

2.根据PC的值找到复位中断处理函数Reset_Handler

1.进入中断处理函数Reset_Handler

中断处理函数外部定义

中断向量表的作用参考STM32的中断向量表是干什么的?到底有什么用?它放在哪里?_ZDQ1431的博客-CSDN博客_stm32 中断向量

原地址0x00000004处的内容为0x0800022D,取出后的内容变为了0x0800022C,它把末位的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处。

2.进入SystemInit函数

MCU复位后,PC所指向的第一行代码

复位PC后,此时程序寻址到PC指针指示的地址0x0800022C处准备执行

BLX R0 将R0的值传给PC(必须保证加载到PC的数值是奇数(即LSB=1),传给PC后,PC的LSB读回0),调用SystemInit函数。

SystemInit这个函数里面开启了外部晶振,设置了锁相环PLL,关闭了所有中断,设置了时钟为72MHz,并且重定位中断向量表在0x08000000处(这句在Flash启动时可以不需要,因为能从0x00000000映射到0x08000000)。

3._main函数

__main()是编译系统提供的一个函数,负责完成库函数的初始化和初始化应用程序执行环境

STM32启动详细流程之__main_非常规自我实现的博客-CSDN博客

3.进入main函数

 从SystemInit函数返回后,用同样的方式调用C/C++标准实时库的__main函数,进行了一些处理(如用户堆栈初始化等)后,调用main函数,进入C语言环境。


总结

基于上面分析,可以总结STM32启动的大体过程。

1、上电复位,CPU从0x00000000处获取栈顶指针MSP(默认使用主堆栈),从0x00000004处获取程序计数器PC。

2、MSP指针必然指向SRAM区的,因为堆栈必须建立在该区。

3、根据PC的值找到复位中断处理函数Reset_Handler。

4、调用SystemInit函数。

5、调用__main函数,初始化运行环境和应用程序。

6、调用main函数,进入C语言环境。


http://www.ppmy.cn/news/733514.html

相关文章

golangci-lint检查项说明

golangci-lint 说明 集成各项golang的静态检查工具英文原版说明地址内容涉及到编码风格(style)、错误处理(error)、会导致代码(bugs)、检查测试代码(test)、metalinter、sql相关判…

go 自动文档生成 如何写高大上的 godoc(Go 文档)

做 Go 开发时,我们在开源项目的主页上我们经常可以看到这样的一个徽章: 点击徽章,就可以打开 godoc.org 的网页,网页中给出了这个开源项目所对应的 Go 文档。作为 Go 语言的新手,我一度以为,godoc.org 上面…

生物医学信号检测与处理2——生物传感器——2酶传感器+酶联免疫吸附分析法ELISA(部分)——第二次课学习笔记

酶传感器酶联免疫吸附分析法ELISA(部分) 1 课程重点概况2 重点内容梳理2.1 酶生物传感器2.1.1 酶传感器的检测原理2.1.2 酶的固定技术2.1.2.1 聚合物包埋2.1.2.2 表面吸附2.1.2.3 共价结合2.1.2.4 静电相互作用2.1.2.5 特定的共价作用2.1.2.6 生物特异性…

如何写高大上的 godoc(Go 文档)

godoc 命令和 golang 代码文档管理 https://www.jianshu.com/p/b9ce0cbaabd5 介绍 godoc 是 golang 自带的文档查看器,更多的提供部署服务go doc 和 godoc 在 golang 1.13 被移除了,可以自行安装 golang.org go1.13 godoc go get golang.org/x/tools…

【React...归纳】

React...归纳 npm不同版本 Nginx前端性能优化浏览器引擎分类事件对象同源浏览器内核属性用户行为对浏览器缓存的影响 CSRF/XSSCC攻击HTTP/HTTPSHTTP请求报文HTTP协议交互原理TLS组成部分http请求方法幂等操作http头部字段权重q-valuesgzip编码 WebSocketprompt组件Chrome DevTo…

视频图像批量处理脚本

1.单个文件夹下对图像进行批量裁剪 from PIL import Image import osdef update(input_img_path, output_img_path):image Image.open(input_img_path)cropped image.crop((38, 0, 580, 610)) # 裁剪坐标为 (x0, y0, x1, y1)cropped.save(output_img_path)dataset_dir XXX…

linux 更改文件格式

1.chmod 数字 文件名;r代表4 w代表2 x 代表1 ;要变更文件格式首先要文件属性为e- 。 2.还有一种方式也可以改文件格式。u,g,o分别代表用户,组,其他用户. 3. u,g,o可加“”可减“-”可等于“” 转载于:https://www.cnblogs.c…

win10系统修改文件后缀名

以.txt修改为.ini为例 win10系统不能直接看文件后缀名。我在安装SQL的时候需要添加一个后缀名为“.ini”的文件,捣鼓了半天,终于改好啦!分享给大家,可能不是最便捷的,但是有亲测有效! 1.桌面新建一个文件…