STM32启动详细流程分析(一)

news2024/11/15 8:40:17

 

问题提出

大家不妨设想一下,cpu 的工作是什么,cpu 是没有主观意识的,它只会按照特定的指令执行相应的操作,用专业术语来说就是:取指 -> 译码 -> 执行,译码和执行肯定是在 cpu 内部进行操作的,并且前提是已经取到了指令。那现在问题来了,指令在哪?

cpu上电复位后执行的第一步操作就是取指令

  • 问题1:指令存储在何处

我们在电脑上编写的程序最终是要烧写到芯片内部的 FLASH中(此处特指STM32)。

  • 问题2:如何将可执行文件烧写至 FLASH 上

STM32 的启动方式有很多种,从主存 FLASH 启动,从 system memory 启动,从 SRAM 中启动。

  • 问题3:从 SRAM 中启动,为什么需要重新设置中断向量表

接下来,我们将围绕这三个问题进行解答

猜想

既然 cpu 上电复位后第一步操作就是取指令,那么这个指令肯定是存储在掉电不丢失的存储介质上(rom、flash)。

  • 猜想1:指令存储在掉电不丢失的存储介质上

我们最终生成的、cpu可以执行的可执行文件肯定是要通过某种外设将用户程序烧写到 FLASH 上,这一点肯定是毋庸置疑的,因为 cpu 与外围设备进行数据交互的时候是通过外设控制器来进行的。

  • 猜想2:通过某种外设将可执行文件烧写至 FLASH 上

STM32 的 FLASH 基地址为 0X0800 0000 ,SRAM 基地址为 0X2000 0000。可不可能是因为这两个存储介质的地址不同,所以才要重新设置中断向量表。

因为我们都知道,中断向量表的首地址就是程序的入口地址。

  • 猜想3:可能与基地址有关

实验验证

实验前必备知识

1. XIP设备

eXecute In Place,即芯片内执行,指应用程序可以直接在 flash 闪存内运行,不必再把代码读到系统 RAM中。在我们的印象里,应用程序必须要从硬盘中加载到内存当中才可以被运行,但实际上应用程序是可以直接在flash 闪存运行的,也就是说,cpu 可以直接从 flash 中取出指令。对于 STM32 而言,它是有 XIP 设备的。

STM32F1 内存图

 

如上图所示,FLASH、SYSTEM MEMORY、OPTION BYTES 都是STM32内部的XIP设备。

F1 内存图信息不是很全,再看下 F4 的内存图。

STM32F4内存图:

 

我们可以看到,不论是 F1 还是 F4,XIP 设备都属于内存图中的 BLOCK0 区域内。

这样我们大概就知道了 STM32 内部的 XIP 设备在 0x0000 0000 ~ 0x1FFF FFFF 内。

上述的内存图是通过映射的方式将芯片的框图进行映射得到的,也就是说,上述这幅图是为了开发人员更好地面向芯片编程而抽象出来的一幅图。我们先来看下面这副图

STM32F1框图:

 

STM32F4框图:

 

对比两幅框图可以看出,F4 比 F1 复杂很多,特别体现在外设上,架构还是差不多的。

 

红色箭头所指向的就是译码电路。

如果你学过微机原理,那么你肯定知道,外设是通过译码电路连接到地址总线上,每一个外设都有其相对应的内存范围,当 cpu 发出的地址信息处于某一个外设的地址范围内,就选中了该外设,cpu就可以与该外设进行数据交互。

一个外设对应一个内存范围,那所有的外设结合起来,是不是就是对应一张图了。

2. STM32 启动配置

在 STM32F10xxx 里,可以通过 BOOT[1:0] 引脚选择三种不同启动模式。

 

在系统复位后,SYSCLK 的第 4 个上升沿, BOOT 引脚的值将被锁存。用户可以通过设置 BOOT1 和 BOOT0 引脚的状态,来选择在复位后的启动模式。

在启动延迟之后, CPU 从地址 0x0000 0000 获取堆栈顶的地址,并从启动存储器的 0x0000 0004 指示的地址开始执行代码。(这里先不验证,在之后的博客中会进行验证,但你需要记住,后面用的上)

因为固定的存储器映像,代码区始终从地址 0x0000 0000 开始(通过 ICode 和 DCode 总线访问),而数据区(SRAM)始终从地址 0x2000 0000 开始(通过系统总线访问)。Cortex-M3 的 CPU 始终从 ICode 总线获取复位向量,即启动仅适合于从代码区开始(典型地从 Flash 启动)。STM32F10xxx 微控制器实现了一个特殊的机制,系统可以不仅仅从 Flash 存储器或系统存储器启动,还可以从内置 SRAM 启动。

根据选定的启动模式,主闪存存储器、系统存储器或 SRAM 可以按照以下方式访问:

  • 从主闪存存储器启动:主闪存存储器被映射到启动空间(0x00000000),但仍然能够在它原有的地址(0x08000000)访问它,即闪存存储器的内容可以在两个地址区域访问, 0x00000000 或 0x08000000

  • 从系统存储器启动:系统存储器被映射到启动空间(0x00000000),但仍然能够在它原有的地址(互联型产品原有地址为 0x1FFFB000 ,其它产品原有地址为 0x1FFFF000 )访问它。

  • 从内置 SRAM 启动:只能在 0x20000000 开始的地址区访问 SRAM(当从内置 SRAM 启动,在应用程序的初始化代码中,必须使用 NVIC 的异常表和偏移寄存器,重新映射向量表到 SRAM 中)。

一般情况下都是从主闪存模式启动的,也就是用户代码被烧写到 0x08000000 地址处。

内嵌的自举程序 (Bootloader)

内嵌的自举程序存放在系统存储区,由 ST 在生产线上写入,用于通过可用的串行接口对闪存存储器进行重新编程,也就是这个自举程序在出厂的时候就已经固化了。大家可以想一下内嵌的自举程序的作用是什么?想不出来也没关系,后面会讲到。

如果想要详细了解这个自举程序到底干了什么,可以看下官方文档:

STM32 microcontroller system memory boot mode

3. 可执行文件的形成过程

STM32 | hex文件、bin文件、axf文件的区别?

大家可以看下这篇博文,写的还是挺不错的!描述了最终烧写到STM32中的可执行代码的形成过程。

4. 三种复位

  • 硬件复位

顾名思义通过硬件给系统一个复位,比如在电路板上设计一复位电路,通过按下按键就可以给系统实现一个复位,而无论系统在执行什么样的程序。复位后初始化一些配置芯片,硬件复位的作用区域一般是全局的。

  • 软件复位

是通过软件给系统一个复位信号,如低电平或许是高电平(具体看系统设置)来实现复位操作软件复位一般是一些块结构复位。

  • 上电复位

系统在上电的瞬间就执行复位操作, 上电复位里面包括硬件复位和软复位的操作,硬件复位和软复位是从上电复位里面的某点开始的启动操作。

复位需要初始化CPU系统,包括CPU和内存等。

验证猜想

1. 验证猜想-1

对于猜想1,其实不需要验证。代码肯定是要存储在掉电不丢失的存储介质上,否则,每次重新上电都要重新烧写程序,这是与事实相反的。而在实验前必备知识中,我们了解到 STM32 内部的 XIP 设备,那不就是代码存储的地方吗?并且也在 STM32 启动方式中详细地描述了代码存储位置。

  • 如果从主FLASH启动,用户代码存储在0X 0800 0000

  • 如果从 SYSTEM MEMORY 启动,里面存储的是 Bootloader,是芯片出厂的时候就已经固化好了的,可以从中读数据,但是不可以向其中写数据,它的作用就是:将用户程序通过可用的外设烧写到指定的地址处,然后启动 STM32

  • 如果从 SRAM 启动,用户代码存储在 0X2000 0000

2. 验证猜想-2

实验前的必备知识中已经大概地描述了最终烧写到 STM32 中的可执行文件的形成过程,现在我们需要验证的就是如何将可执行文件烧写到指定的存储设备中去(假设是 FLASH,其实也可以是 SRAM

我第一次使用 Flymcu(串口下载软件的时候),我脑海里就有一个疑问,就是这个软件到底是怎样使得 STM32 将生成的代码烧写到内部 FLASH 上的。这真的是很不可思议!因为 STM32 上电复位后肯定是要执行代码的,可是我还没有给它代码呢,它怎么会运作呢?当时我真的很迷惑。

其实,STM32 出厂的时候 Bootloader(用于将用户程序下载到 STM32 内部指定地址处的固件(程序))就已经固化在了 System Memory 上了,可读写无效。

从 STM32 启动配置一节中我们知道,可以通过对 BOOT1 和 BOOT0 引脚上高低电平的改变从而实现 STM32 启动方式的不同。

 

如上所说,Bootloader 存储在 Sytem Memory 上,如果想要让 Bootloader 运行(将用户程序下载到指定内存地址处),那启动模式肯定是要选择以系统存储器的方式启动。

BOOT1 = 0    BOOT0 = 1 -> 系统存储器模式

因此,外部电路的设计的目的就是要能够达到能够对 BOOT1 和 BOOT0 引脚上高低电平改变的能力

接下来,我们就以正点原子的原理图(探索者)为例,来看下 STM32 外部的电路到底是如何设计的,以及Flymcu 到底是怎样控制 BOOT1 和 BOOT0 引脚上高低电平改变从而达到具有使得 STM32 从系统存储器启动的的神奇能力。

 

如上图所示,这就是正点原子探索者一键下载电路。

一键下载电路涉及到模电知识,下面这篇文章写的还不错,并且还描述了CH340G芯片引脚的作用和功能。

stm32一键下载电路(下一篇文章)

从上图我们可以知道,Flymcu 肯定是通过 usb 线将数据或指令写入 CH340G 内(CH340 D + CH340 D- )然后CH340G 根据来自 usb 的指令进行相应的工作。

CH340G在此电路中的工作就两个:

  • 与STM32进行数据交互

  • 控制BOOT0和RESET高低电平的变化

特别注意:正点原子探索者BOOT0和BOOT1引脚默认都是接地

 

BOOT0、BOOT1是通过跳线帽和地进行连接的

现在我们知道了,控制 BOOT1 和 BOOT0 引脚上高低电平改变是 CH340G 的作用,而 CH340G 是严格按照来自Flymcu 的指令进行的,所以,控制 BOOT1 和 BOOT0 引脚上高低电平改变的幕后黑手就是 Flymcu

注意:向 FLASH 中烧写程序不仅仅只有串口,由于硬件平台的限制,因此分析串口下载。

问题来了,那 Flymcu 到底干了什么,它是如何将用户程序烧写的 STM32 内部指定地址处?

以跑马灯为例,看下Flymcu烧写程序过程中输出的信息。

 

  • DTR 电平置低:复位

  • RTS 电平置高:进入 Bootloader

  • 延时 100ms :有谁能够告诉我为什么

  • DTR 电平置高:释放复位

  • RTS 维持高 :此时开始运行 Bootloader

  • 开始连接 :Flymcu 要与 STM32 连接肯定是要发送特定的指令,并且当 STM32 接收到预先约定好的指令时,也会发送特定的回复。(和接头的性质差不多)

注意:STM32 从 Bootloader 启动到能够与外部设备进行数据交互需要一定的时间,因此连接需要一定的时间

  • 读出关于芯片相关的数据

  • 读出选项字节

  • 进行全片擦除,去除写保护,再次重启 Bootloader(有大佬能告诉我为什么)

  • 编写程序,从 0x0800 0000 处开始运行

上述的过程中,大家比较疑惑的地方就是,Flymcu 发送给 STM32 的指令到底是什么,这个指令肯定是事先就确定好的,在这个文档中提及到了。

stm32 microcontroller system memory boot mode

这个手册中的内容大家可以自己详细地去看下,内容不多,我就粗略地说一下必要的知识点。

硬件连接需要(文档中的第35页)

通过串口与外部设备进行数据交互时STM32外部电路设计。

 

通过 DFU 与外部设备进行数据交互时 STM32 外部电路设计

 

还有其他的连接方式,我想表述的意思就是:

Bootloader 与外部设备进行数据交互的方式有很多种,不仅仅只有串口,只是由于硬件平台有限(正点原子只有通过串口下载的接口(调试接口除外))而根据不同的交互方式,STM32 外部的电路设计又大不相同。

Bootloader启动流程

 

从启动流程中我们就可以得到Flymcu发送给STM32的特定连接指令为:0x7F。

STM32F40xxx/41xxx devices bootloader version

通过版本信息中红色画线部分可以得知,当 Bootloader 接收到相应的命令之后,就会连续发送两个 response。我们这个时候再看下 Flymcu 中的输出信息,

通过红色画线部分可以看出,Flymcu 接收到两个来自 Bootloader 的信息。

此时,接头成功!!!!!

接头成功后肯定就可以进行数据交互了!!!

因此,我们最初的猜想是正确的:即 STM32 通过某种外设将可执行文件烧写至 FLASH 上(也可以是 SRAM)

验证猜想-3

博客当中已经多次提及到,STM32 不仅可以从 FLASH 上启动,还可以从 SRAM 上启动。并且在STM32启动配置中有一个小提示:从 SRAM 中启动,需要重新设置中断向量表。

中断向量表的设置是用户在用户程序中自己实现的!!!

要验证这个猜想,可以从 SRAM 中启动,但是不设置中断向量表,看一下会出现什么情况。

 

由于正点原子的电路设计(因为我使用的就是正点原子的探索者开发板),使得无法通过串口进行 SRAM 启动,只能通过调试接口下载程序。

注意:SRAM是掉电数据就会丢失的存储器介质,因此使用时(前提是已经掉电)要重新下载程序从 SRAM 中启动的最主要的目的是用来调试程序,产品中的用户程序肯定都是存储在 FLASH 上的,不然每次掉电后用户程序都没了!!!

如何通过调试接口将用户程序下载到 SRAM 处,可以参考一下下面两篇博文:

  • STM32 内部 SRAM 调试程序

  • 在 SRAM 中调试代码

假设你现在已经实现了能够通过调试接口将用户程序下载到 SRAM 处,那么接下来,我们来验证一下。如果没有重新设置中断向量表会出现什么结果。

得出结论,总结归纳

对于最开始提出的三个猜想,现在可以得出结论:

  • 指令存储在掉电不丢失的存储介质上

  • STM32 通过某种外设将可执行文件烧写至掉电不丢失的存储介质上

  • 中断向量表的首地址就是程序的入口地址

注意: 通过串口下载程序,实际上是 Flymcu(上位机)与 STM32 内置的 Bootloader 进行数据交互,但两者直接需要特定的硬件环境(CH340G(USB转串口芯片))

注意: 内存图中的 reserved 有些是不使用,有些是不能用(有其他重要的作用:可读写忽略),不可以修改其值

看完这篇博客,你的脑海里必须得有一个流程的框架:

  • 用户面向单片机编写用户代码(C,C++,ASM)

  • 用户代码通过交叉编译工具链生成单片机可以执行的可执行文件(HEX,BIN,AXF)

  • 上位机:各种烧写工具(不局限于 Flymcu (因为 Bootloader 与外部设备进行数据交互不仅仅只是通过USART)))与单片机内部的 Bootloader 进行数据交互(目的是将可执行文件下载到指定的存储地址处)

将可执行文件下载到指定存储地址处,然后还会继续等待上位机的 command,可以通过复位或上位机发送跳转到用户代码入口地址的命令执行用户程序。

这个流程的框架总结一句话就是:

可执行程序 -> cpu执行第一条用户代码的流程

至于 cpu 执行第一条用户代码之后的流程后面的博客会详细说明,但毋庸置疑的是,这是一个重要转折点,在这个点之后执行的是你自己编写的代码,你比较熟悉这个过程,但是在这个点之前,对大部分人来说都是都是比较陌生的,但是但你对这个过程了解之后,会对你的知识体系有非常大的提升。

希望这篇博客对你有所帮助。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/658704.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MySQL数据库增删改查及聚合查询SQL语句学习汇总

目录 数据库增删改查SQL语句 MySQL数据库指令 1.查询数据库 2.创建数据库 3.删除数据库 4.选择数据库 创建表table 查看所有表 创建表 查看指定表的结构 删除表 数据库命令进行注释 增删改查(CRUD)详细说明 增加 SQL库提供了关于时间的…

Python 查询 DynamoDB

文章目录 DynamoDB 简介Boto3简介安装和导入 Boto3将 Boto3 连接到 DynamoDB 使用 Boto3 在 DynamoDB 中创建表通过 Boto3 删除 DynamoDB 中的表通过 Boto3 列出 DynamoDB 中的表通过 Boto3 在 DynamoDB 中分页通过 Boto3 在 DynamoDB 中排序通过 Boto3 在 DynamoDB 中获取项目…

【设计模式与范式:行为型】63 | 职责链模式(下):框架中常用的过滤器、拦截器是如何实现的?

上一节课,我们学习职责链模式的原理与实现,并且通过一个敏感词过滤框架的例子,展示了职责链模式的设计意图。本质上来说,它跟大部分设计模式一样,都是为了解耦代码,应对代码的复杂性,让代码满足…

Ribbon LoadBalanced底层机制源码探秘

🍊 Java学习:社区快速通道 🍊 深入浅出RocketMQ设计思想:深入浅出RocketMQ设计思想 🍊 绝对不一样的职场干货:大厂最佳实践经验指南 📆 最近更新:2023年6月18日 🍊 点…

如何自己开发浏览器js插件

大家都知道在网页控制台编写的js脚本一刷新就没了下面教程教大家如何自己写一个js插件,此教程是小白在网上看到的的确认有效才发出来的,无需借助油猴。 最近工作需要小白研究了一下浏览器插件编写的过程下面分享给大家 步骤 在桌面创建一个文件夹&…

指针与数组---指针与一维数组的关系

C语言的高效得益于它指针功能的强大。然而C语言中的指针和数组的关系似乎很“纠结”,让人爱恨交织。指向数组的指针变量、指针数组等,似乎总是“你中有我,我中有你”。 目录 一、数组名的特殊意义及其在访问数组元素中的作用 二、指针运算…

Linux常用指令和知识(1)

目录 ls cd pwd 相对路径&绝对路径&特殊路径符 mkdir touch-cat-more cp-mv-rm which-find grep-wc 管道符 | echo 重定向符 tail 😶‍🌫️😘创作不易, 多多支持 前言: 我们学习的Linux命令, 其实他们的本体就是一个个…

ctf 逆向 专题题解

本文的目标是,记录一些不具备通用性的,或者比较进阶的题目。之前的另一篇文章则用于记录一些基础知识和通用性较强的基本手法。 文章目录 跨科题目buu fungame:reverse与pwn的结合reverseweb 反跟踪Easyhook:hook例题 vm类型总结一…

我的创作纪念日——512

机缘 没想到不知不觉在CSDN创作就512天了,想到一开始就仅仅想在CSDN记笔记,到现在成为一个小博主,认识到了很多志同道合的伙伴,中间创作我也曾经懒惰过,放弃过,但我一次又一次重新进行创作,虽然…

AcWing801: 二进制中1的个数(两种方法详解)

原题引出 方法一:使用lowbit 算法的时间复杂度为 O ( n l o g n ) O(nlogn) O(nlogn),使用lowbit操作,每次操作截取一个数字的最后一个1后面的所有位,每次减去lowbit得到的数字,直到数字减到0,就得到了最终…

【MySQL】选择专题(七)

文章目录 选择题选择题 在关系R ( R # , RN , S # )和S ( S # , SN , SD )中, R 的主码是R # , S 的主码是S #,则S#在R 中称为( A )。 A 外码 B 候选码 C 主码 D 超码 设关系R和S的属性个数分别为2和3,那么等价于( B )。 A. σ1<2(RS) B. σ1<4(RS) C. σ1<2(R…

我们世界中的计算机——从大师视角诠释计算常识

计算机和通信系统&#xff0c;以及由它们所实现的许多事物遍布我们周围。其中一些在日常生活中随处可见&#xff0c;比如笔记本电脑、手机和互联网。今天&#xff0c;在任何公共场所&#xff0c;都会看到许多人在使用手机查询交通路线、购物以及和朋友聊天。与此同时&#xff0…

【大数据】大数据相关概念

文章目录 大数据&#xff1a;一种规模大到在获取、存储、管理、分析方面大大超出了传统数据库软件工具能力范围的数据集合&#xff0c;具有海量的数据规模、快速的数据流转、多样的数据类型以及价值密度四大特征。Hadoop&#xff1a;是一个能够对大量数据进行分布式处理的软件框…

15-3.自定义组件的生命周期函数

目录 1 组件自身的生命周期函数 1.1 使用lifetimes声明生命周期函数 1.2 不使用lifetimes声明生命周期函数 2 组件所在页面的生命周期函数 1 组件自身的生命周期函数 created 组件实例刚刚被创建后执行&#xff0c;可以理解为 html模板刚刚搞好attached 组件被放入节…

万物的算法日记|第六天

笔者自述&#xff1a; 一直有一个声音也一直能听到身边的大佬经常说&#xff0c;要把算法学习搞好&#xff0c;一定要重视平时的算法学习&#xff0c;虽然每天也在学算法&#xff0c;但是感觉自己一直在假装努力表面功夫骗了自己&#xff0c;没有规划好自己的算法学习和总结&am…

DJ4-2 数据报网络和虚电路网络

目录 一、连接和无连接服务 二、数据报网络 1、数据报网络的转发表 2、数据报网络的特点 三、虚电路网络 (Virtual Circuits)* 1、虚电路网络的工作方式 2、虚电路网络的特点 一、连接和无连接服务 任何网络中的网络层只会提供两种服务之一&#xff0c;不会同时提供 数…

Mysql数据库之事务(山高水远,他日江湖再见)

文章目录 一、事务的概念二、事务的ACID特点1.原子性&#xff08;Atomicity&#xff09;2.一致性&#xff08;Consistency&#xff09;3.隔离性&#xff08;lsolation&#xff09;4.持久性&#xff08;Durability) 三、并发访问表的一致性问题和事务的隔离级别1.并发访问表的一…

融合模型stacking14条经验总结和5个成功案例(互联网最全,硬核收藏)_机器学习_人工智能_模型竞赛_论文参考

我看了很多关于融合模型stacking文章&#xff0c;很多作者倾向于赞美融合模型stacking&#xff0c;对其缺点轻描淡写&#xff0c;这容易误导初学者。一叶障目就是这意思。 我的很多学员喜欢用融合模型作为论文或专利创新点&#xff0c;这是一个热门技术。 最近有个同学在论文…

设计模式之单例模式笔记

设计模式之单例模式笔记 说明Singleton(单例)目录单例模式之饿汉式-静态成员变量写法测试类 单例模式之饿汉式-静态代码块写法测试类 单例模式之懒汉式-线程不安全写法和线程安全写法测试类 单例模式之懒汉式-双重检查锁方式(推荐使用的方式)单例模式之懒汉式-静态内部类方式(推…

Mysql数据库之存储引擎(羡慕她人,不如提升自己)

一、存储引擎概念 MySQL中的数据用各种不同的技术存储在文件中&#xff0c;每一种技术都使用不同的存储机制、索引技巧、锁定水平并最终提供不同的功能和能力&#xff0c;这些不同的技术以及配套的功能在MySQL中称为存储引擎。 存储引擎是MySQL将数据存储在文件系统中的存储方…