STM32 单片机启动流程

刚接触ARM的cortex-m系列单片机时,被告知一切都从main() 函数开始,要将程序写在main()函数中。而仿真时也貌似是从main() 函数开始的,以STM32F103为例。

后来了解到全局变量是在main()函数之前初始化的。MDK默认情况下勾选下面选项,跳过了启动的汇编部分代码,直接进入了main() 函数.

实际起始位置

在cortex-m系列中,中断向量表存放在 Flash 开始部分,Flash中第一个字存放栈顶指针,第二个字存放复位中断服务函数入口地址,其他中断服务函数入口地址依次存放在Flash中。

MCU上电后,会将Flash中的第一个字加载到R13 MSP寄存器中,第二个字加载到R15 PC寄存器中。

从上图可以看出ARM规定了M3,M4内核要从地址0x0000 0000读取中断向量表,而STM32设置Flash地址到0x0800 0000怎么办?

STM32将地址0x0800 0000开始的内容重映射到首地址0x0000 0000中,这样就解决了从0x0000 0000读取中断向量表的问题。
下图可以看出STM32F105实际读出的0x0000 0000和0x0800 0000内容一样

R13:栈顶指针寄存器SP

SP寄存器有两个,MSP或者PSP,PSP是为了RTOS特意设置的,如果使用RTOS,则在RTOS的任务中就是使用的PSP,在中断服务函数中则使用MSP。如果不使用RTOS,则默认一直使用MSP。

在MCU中,RAM只是负责暂存数据,真正的运算是在寄存器中完成的,例如要对两个变量进行加法运算,就需要将两个变量的值从RAM中取出存入寄存器中,然后操作寄存器进行计算,最后将计算结果存入RAM中。因此常说的在进入子函数或者中断服务函数时需要保存现场,其实也就是保存寄存器中的值,将寄存器值PUSH在栈中。

SP寄存器指向栈顶地址,因此随着PUSH和POP,SP寄存器会跟着自动变化。

MSP寄存器存放栈顶指针,栈中存放局部变量、函数参数以及进入子函数、中断服务函数前寄存器的值,当从子函数或者中断服务函数中跳出时,会从栈中POP寄存器值,也就是恢复现场,确保程序可以正常执行。平时尽量不让使用递归就是为了防止多次调用自身,多次保存现场导致栈溢出。

入栈和出栈操作由编译器自动生成代码,但是入栈时默认只会将R0-R3入栈,如果中断服务函数过于复杂,则编译器也会将R4-R11入栈,这也就是为什么中断服务函数尽量简短的原因之一。

R15:程序计数寄存器PC

PC寄存器指向当前的程序地址。如果修改它的值,就能改变程序的执行流(很多高级技巧就在这里面)

上电时将中断向量表中的第二个字加载到PC寄存器中,也就是让程序跳转到复位中断服务函数中。


不过复位中断服务函数是一个汇编函数。

复位中断服务函数中调用了SystemInit()函数,该函数主要作用是设置中断向量表的偏移地址。也就是说中断向量表位置是可变的,当使用BOOT后,就需要在APP修改该偏移地址。

接着复位中断服务函数跳转到__main()函数中,__main()和我们平时说的main()函数是有区别的。


RAM掉电会丢失数据,在上电后,RAM中的数据是不确定的,在运行main()函数之前需要将RAM中的数据初始化,也就是下图左边到右边的过程,将flash中的RW数据加载到RAM中,并将RAM中的ZI段数据进行初始化操作。MDK中__main()函数帮我们自动完成了这个操作,也就是所谓的准备C语言环境,C语言环境准备好之后会跳到 main() 函数。

最后,其实还少说了一个,在上电后会根据boot0,boot1 的状态确定自举空间的位置,如果从系统存储器自举(系统bootLoad,出厂时,官方固化在单片机中的一段代码,用户无法修改的。在STM32中,常用的串口下载,DFU就是系统bootLoad中的功能),系统bootLoad执行完毕后才是我们上面说的哪些,文章中的图大部分来自《Cortex-M3 权威指南》

STM32 单片机启动流程相关推荐

  1. STM32单片机启动流程分析

    本章内容 STM32单片机是如何执行自己的代码的? 官方给的启动流程图如下 启动地址 启动文件分析 堆栈定义 向量表 复位程序 中断服务程序 堆栈初始化 总结一下STM32从Flash的启动流程 ST ...

  2. [东拼西凑]STM32单片机启动流程及RAM和Flash的配置关系和堆栈溢出现象

    开头的话: 之前一直用现成的LED工程demo,改改就上,也没细究.直到做MQTT移植的时候,发现malloc始终出错,开始找问题,于是写本文.(前前后后摘抄.参考.改进本文,侵删) 一.STM32上 ...

  3. STM32单片机启动过程详解

    本文详细介绍STM32单片机启动的过程,既从上电Reset_Handle跳转到main()函数的过程.其中,会着重解释__main的汇编代码 STM32启动过程 1. 从Reset_Handler开始 ...

  4. 单片机启动流程(以STM32为例)

    ST公司都提供了现成的直接可用的启动文件,程序开发人员可以直接引用启动文件后直接进行C应用程序的开发.这样能大大减小开发人员从其它微控制器平台跳转至STM32平台,也降低了适应STM32微控制器的难度 ...

  5. 单片机断电后静态存储区里面还有数据吗_单片机启动流程和存储架构详解

    最近在给公司的ADAS DCU做内存分配(Memory Allocation),在这儿记录一下相关知识点,也算是给中文社区做贡献了. 目录: 1. ECU启动流程 2. 存储空间解析 3. TC397 ...

  6. STM32开发 -- 启动流程

    如需转载请注明出处:https://blog.csdn.net/qq_29350001/article/details/80586534 启动模式讲完了,我们知道是主闪存存储器启动的(主闪存存储器就是 ...

  7. STM32单片机启动文件startup_stm32f10x_hd.s详解

    启动文件源码如下: ; Amount of memory (in bytes) allocated for Stack ; Tailor this value to your application ...

  8. STM32的完整启动流程分析

    最近又写了一篇补充描述,适合与本文一起查阅.深入理解MCU启动原理 关于STM32的启动流程,网上有的资料在讨论几种boot模式,有的在回答启动文件的内容,在查阅了很多资料后,本文给出一个比较全面的总 ...

  9. 《嵌入式 - 深入剖析STM32》STM32 启动流程详解(GCC)

    开发环境: 处理器:STM32F103 GCC:10.3.1 对于我们常用的桌面操作系统而言,我们在开发应用时,并不关心系统的初始化,绝大多数应用程序是在操作系统运行后才开始运行的,操作系统已经提供了 ...

最新文章

  1. LINUX 查找tomcat日志关键词
  2. 有了这个 IDEA的兄弟,你还用 Navicat 吗?全家桶不香吗?
  3. Java社区领袖介绍平台支持选项
  4. NOIP2006提高组 能量项链
  5. 世界第一薄MacBook Air笔记本切菜演示(组图)
  6. 电脑休眠和睡眠的区别_关机、睡眠、休眠有啥区别?微软说非特殊情况不要关机...
  7. 【数据挖掘导论】——数据质量
  8. python学习浅谈(python2.x以及python3.x的区别、IDE)
  9. VC如何设置默认的调试程序
  10. gensim实现TF-IDF和LDA模型、sklearn实现聚类
  11. Java实现的快递柜管理系统(附上完整代码可用作期末课程设计)
  12. 【最优方案】合唱队形
  13. “天河一号”算一小时13亿人算340年
  14. 一度智信|拼多多店铺取名大全
  15. 树莓派编译ffmpeg支持x264硬解码播放视频
  16. 【C语言】求s = a + aa + aaa + aaaa + aa...a的值,其中a是一个数字
  17. 昨天,2017年诺贝尔物理学奖正式揭晓!
  18. 统信软件:第一份收入破亿的答卷
  19. IMU、角速度、线速度校正
  20. docker安装mysql远程不能访问_虚拟机中docker安装mysql远程无法访问

热门文章

  1. Android4.4.2KK竖屏强制更改为横屏的初步简略方案
  2. LCD正向扫描和反向扫描
  3. 专家:中国房地产泡沫崩溃时间就是今明二年
  4. React状态管理大乱斗,横向对比Dva,Rematch,Mirror
  5. 前端如何搭建一个成熟的脚手架
  6. FFmpeg 源码学习(一):avformat_open_input 源码分析
  7. GitLab10安装-部署-汉化-备份-升级
  8. 【java】 linux下利用nohup后台运行jar文件包程序
  9. 【沟通之道】头脑风暴-女人的心思你别猜
  10. ASP.NET MVC 学习6、学习使用Code First Migrations功能,把Model的更新同步到DB中