CM3/4启动流程

CM3/4启动流程

  • 1. 启动模式
  • 2. 启动流程

1. 启动模式

复位方式有三种:上电复位硬件复位软件复位
当产生复位,并且离开复位状态后,CM3/4 内核做的第一件事就是读取下列两个 32 位整数的值:

  • 从地址 0x0000 0000 处取出堆栈指针 MSP 的初始值,该值就是栈顶地址。
  • 从地址 0x0000 0004 处取出程序计数器指针 PC 的初始值,该值指向复位后执行的第一条指令(复位向量)。
    在这里插入图片描述

  上述过程中,内核是从 0x0000 0000 和 0x0000 0004 两个的地址获取堆栈指针 SP 和程序计数器指针 PC。事实上,0x0000 0000 和 0x0000 0004 两个的地址可以被重映射到其他的地址空间。例如:我们将 0x0800 0000 映射到 0x0000 0000,即从内部 FLASH 启动,那么内核会从地址 0x0800 0000 处取出堆栈指针 MSP 的初始值,从地址 0x0800 0004 处取出程序计数器指针PC 的初始值。CPU 会从 PC 寄存器指向的地址空间取出的第 1 条指令开始执行程序,就是开始执行复位中断服务程序 Reset_Handler。将 0x0000 0000 和 0x0000 0004 两个的地址重映射到其他地址空间,就是启动模式选择。
  启动模式(也称自举模式)有三种,如下图所示:
在这里插入图片描述
  根据 BOOT 引脚的电平 [0:低电平;1:高电平;x:任意电平,即高低电平均可] 选择启动模式,这两个 BOOT 引脚根据外部施加的电平来决定芯片的启动地址。(0 和 1 的准确电平范围可以查看 F4 系列数据手册 I/O 特性表,但我们最好是设置成 GND 和 VDD 的电平值)
  复位后,在 SYSCLK 的第四个上升沿锁存 BOOT 引脚的值。复位后,用户可以通过设置 BOOT0 [专用引脚] 和 BOOT1 [与 PB2 引脚共用] 引脚来选择需要的自举模式。一旦完成对 BOOT1 的采样,相应 GPIO 引脚即进入空闲状态,可用于其它用途。
  器件退出待机模式时,还会对 BOOT 引脚重新采样。因此,当器件处于待机模式时,这些引 脚必须保持所需的自举模式配置。这样的启动延迟结束后,CPU 将从地址 0x0000 0000 获 取栈顶值,然后从始于 0x0000 0004 的自举存储器开始执行代码。


1. 内部FLASH启动方式:
  当芯片上电后采样到 BOOT0 引脚为低电平时,0x00000000 和 0x00000004 地址被映射到内部 FLASH 的首地址 0x08000000 和 0x08000004。因此,内核离开复位状态后,读取内部 FLASH的 0x08000000 地址空间存储的内容,赋值给栈指针 MSP,作为栈顶地址,再读取内部 FLASH的 0x08000004 地址空间存储的内容,赋值给程序指针 PC,作为将要执行的第一条指令所在的地址。完成这两个操作后,内核就可以开始从 PC 指向的地址中读取指令执行了。

2. 内部 SRAM 启动方式:
  类似于内部 Flash,当芯片上电后采样到 BOOT0 和 BOOT1 引脚均为高电平时,地址0x00000000 和 0x00000004 被映射到内部 SRAM 的首地址 0x20000000 和 0x20000004,内核从SRAM 空间获取内容进行自举。在实际应用中,由启动文件 starttup_stm32f407xx.s 决定了0x00000000 和 0x00000004 地址存储什么内容,链接时,由分散加载文件(sct)决定这些内容的绝对地址,即分配到内部 FLASH 还是内部 SRAM。

3. 系统存储器启动方式:也称为 ISP 启动方式
  当芯片上电后采样到 BOOT0=1,BOOT1=0 的组合时,内核将从系统存储器的 0x1FFFF000及 0x1FFFF004 获取 MSP 及 PC 值进行自举。系统存储器是一段特殊的空间,用户不能访问,ST 公司在芯片出厂前就在系统存储器中固化了一段代码。因而使用系统存储器启动方式时,内核会执行该代码,该代码运行时,会为 ISP(In System Program)提供支持,在 STM32F4 上最常见的是检测 USART1 传输过来的信息,并根据这些信息更新自己内部 FLASH 的内容,达到升级产品应用程序的目的,因此这种启动方式也称为 ISP 启动方式。

2. 启动流程

  以前 ARM7/ARM9 内核的控制器在复位后,CPU 会从存储空间的绝对地址0x00000000 取出第一条指令执行复位中断服务程序的方式启动,即固定了复位后的起始地址为 0x00000000(PC =0x00000000),同时中断向量表的位置也是固定的。而 CM3/4内核复位后的起始地址和中断向量表的位置可以被重映射,重映射的方法是通过3 种启动模式来选择的(如上)


在这里插入图片描述

启动流程:【以代码下载到内部 FLASH 的情况举例】

  1. 当产生复位[上电复位、硬件复位、软件复位],并且离开复位状态后,从地址 0x0800 0000 处取出堆栈指针 MSP 的初始值,该值就是栈顶地址。 [小端:MSP=0x2000 0788]
  2. 从地址 0x0800 0004 处取出程序计数器指针 PC 的初始值,该值指向复位后执行的第一条指令。 [小端:PC=0x0800 01CD]


在这里插入图片描述
  因为 CM3/4 使用的是向下生长的满栈,所以 MSP 的初始值必须是堆栈内存的末地址加 1。举例来说,如果你的栈区域在 0x2000 0388‐0x2000 0787(1KB 大小)之间,那么 MSP 的初始值就必须是 0x2000 0788。
  向量表跟随在 MSP 的初始值之后——也就是第 2 个表目。
  R15 是程序计数器,在汇编代码中,可以使用名字“PC”来访问它。ARM 规定:PC 最低两位并不表示真实地址,最低位 LSB 用于表示是 ARM 指令(0)还是 Thumb 指令(1),因为 CM3 主要执行 Thumb 指令,所以这些指令的最低位都是 1(都是奇数)。因为 CM3 内部使用了指令流水线,读 PC 时返回的值是当前指令的地址+4。比如说:【0x1000: MOV R0, PC ; R0 = 0x1004】
  如果向 PC 写数据,就会引起一次程序的分支(但是不更新 LR 寄存器)。CM3/4 中的指令至少是半字对齐的,所以 PC 的 LSB 总是读回 0。然而,在分支时,无论是直接写 PC 的值还是使用分支指令,都必须保证加载到 PC 的数值是奇数(即 LSB=1),表明是在 Thumb 状态下执行。倘若写了 0,则视为转入 ARM 模式,CM3 将产生一个 fault 异常。
  正因为上述原因,使用 0x0800 01CD 来表达地址 0x0800 01CC。当 0x0800 01CD 处的指令得到执行后,就正式开始了程序的执行(即去到 C 的世界)。所以在此之前初始化 MSP 是必需的,因为可能第 1 条指令还没执行就会被 NMI 或是其它 fault 打断。MSP 初始化好后就已经为它们的服务例程准备好了堆栈。


详细启动流程:
1. 硬件复位

  • 初始化内核寄存器。
  • 设置程序计数器(PC)为 0x08000000(Flash的起始地址)。

2. 读取初始栈指针(SP)

  • 从Flash的起始地址(0x08000000)读取初始栈指针(SP)的值。
  • 栈指针用于初始化栈,栈通常位于RAM的顶部。

3. 读取复位向量

  • 从Flash的第二个字(0x08000004)读取复位处理程序(Reset_Handler)的地址。
  • 复位向量是复位处理程序的入口地址。

4. 执行复位处理程序

  • 设置堆和栈的起始地址。
  • 调用 SystemInit 函数(如果存在),配置外部 SRAM 作为数据存储器(可选)和 配置重映射的中断向量表地址(可选)。
  • 跳转到 __main 函数。
     1. 初始化 .data 段
      data 段存储已初始化的全局变量和静态变量。这些变量的初始值存储在Flash中,将这些值复制到RAM中。
       步骤1:获取 .data 段在Flash中的起始地址和大小。
       步骤2:将数据从Flash复制到RAM中的目标地址。
     2. 初始化 .bss 段
      .bss 段存储未初始化的全局变量和静态变量。将 .bss 段对应的RAM区域清零。清零步骤如下:
      步骤1:获取 .bss 段的起始地址和大小。
      步骤2:将对应内存区域清零。
     3. 设置堆和栈
      栈(Stack)用于存储局部变量和函数调用信息。栈的大小在启动文件中定义,通常位于RAM的顶部。
      堆(Heap)用于动态内存分配(如 malloc 和 free)。堆的大小也在启动文件中定义。
      __main 函数根据启动文件中的定义,初始化堆和栈的起始地址和大小。
     4. 调用用户的 main 函数
      在完成上述初始化工作后,__main 函数会跳转到用户的 main 函数,开始执行用户代码。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

快手短剧播放器uniapp如何引入与对接?

uniApp前端微短剧项目开源分享 开源地址:git开源下载地址 文章目录 快手短剧播放器uniapp如何引入与对接?1.引入短剧播放器2.创建文件kscomponents组件3.local-stream.js文件说明4.用户行为事件4.local-stream.ksml文件参考如下 快手短剧播放器uniapp如何…

.NET AI 开发人员库 --AI Dev Gallery简单示例--问答机器人

资源及介绍接上篇 nuget引用以下组件 效果展示: 内存和cpu占有: 代码如下:路径换成自己的模型路径 模型请从上篇文尾下载 internal class Program{private static CancellationTokenSource? cts;private static IChatClient? model;privat…

如何构建多层决策树

构建一颗多层的决策树时,通过递归选择最佳划分特征(依据 信息增益 或 基尼系数)对数据集进行划分,直到满足停止条件(例如叶节点纯度达到要求或树的深度限制)。以下是基于 信息增益 和 基尼系数 的递推公式和…

VSCode 使用鼠标滚轮控制字体

一、 文件 | 首选项 | 设置 二、单击在 settings.json中编辑 "editor.mouseWheelZoom": true 注注注意:保存哦!ctrlS 三、测试 按住ctrl鼠标滚轮,控制字体大小

十年后LabVIEW编程知识是否会过时?

在考虑LabVIEW编程知识在未来十年内的有效性时,我们可以从几个角度进行分析: ​ 1. 技术发展与软件更新 随着技术的快速发展,许多编程工具和平台不断更新和改进,LabVIEW也不例外。十年后,可能会有新的编程语言或平台…

注册中心如何选型?Eureka、Zookeeper、Nacos怎么选

这是小卷对分布式系统架构学习的第9篇文章,第8篇时只回答了注册中心的工作原理的内容,面试官的第二个问题还没回答,今天再来讲讲各个注册中心的原理,以及区别,最后如何进行选型 上一篇文章:如何设计一个注册…

C++ 复习总结记录三

C 复习总结记录三 主要内容 1、类的六个默认成员函数 2、构造函数 3、析构函数 4、拷贝构造函数 5、赋值运算符重载 6、const 成员函数 7、取地址及 const 取地址操作符重载 一 类的六个默认成员函数 如果一个类中什么成员都没有,简称为空类。空类中并不是…

【简博士统计学习方法】第1章:4. 模型的评估与选择

4. 模型的评估与选择 4.1 训练误差与测试误差 假如存在样本容量为 N N N的训练集,将训练集送入学习系统可以训练学习得到一个模型,我们将这么模型用决策函数的形式表达,也就是 y f ^ ( x ) y\hat{f}(x) yf^​(x),关于模型的拟合…

计算机网络 (30)多协议标签交换MPLS

前言 多协议标签交换(Multi-Protocol Label Switching,MPLS)是一种在开放的通信网上利用标签引导数据高速、高效传输的新技术。 一、基本概念 MPLS是一种第三代网络架构技术,旨在提供高速、可靠的IP骨干网络交换。它通过将IP地址映…

【Java】JVM内存相关笔记

Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域。这些区域有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而一直存在,有些区域则是依赖用户线程的启动和结束而建立和销毁。 程序计数器&am…

鸿蒙 ArkUI实现地图找房效果

常用的地图找房功能,是在地图上添加区域、商圈、房源等一些自定义 marker,然后配上自己应用的一些筛选逻辑构成,在这里使用鸿蒙 ArkUI 简单实现下怎么添加区域/商圈、房源等 Marker. 1、开启地图服务 在华为开发者官网,注册应用&…

STM32-WWDG/IWDG看门狗

WWDG/IWDG一旦开启不能关闭,可通过选项字节在上电时启动硬件看门狗,看门狗计数只能写入不能读取。看门狗启用时,T6bit必须置1,防止立即重置。 一、原理 独立看门狗-超时复位 窗口看门狗-喂狗(重置计数器,…

基于JAVA+SSM的车辆运输管理

基于JAVASSM的车辆运输管理 前言 ✌全网粉丝20W,csdn特邀作者、博客专家、CSDN[新星计划]导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末附源码下载链接🍅 哈喽兄弟们&#…

【Linux系列】Vim 编辑器中的高效文本编辑技巧:删除操作

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

win10 VS2019上libtorch库配置过程

win10 VS2019上libtorch库配置过程 0 引言1 获取libtorch2 在VS上配置使用libtorch库3 结语 0 引言 💻💻AI一下💻💻   libtorch库是一个用于深度学习的C库,是PyTorch的官方C前端。它提供了用于构建和训练深度学习模…

通过gradle发布aar或jar携带sources-jar到maven nexus

找了很久,没有找到满意的。终于找到一个好的办法。 gradle7.x适用。比以前的写法简洁。 发布传统的jar工程 比如okhttp,fastjson等项目,纯java工程。 直接创建新文件publish.gradle: apply plugin: maven-publishProperties properties …

STM32-笔记38-I2C-oled实验

一、什么是I2C? I2C总线,全称Inter-Integrated Circuit(互连集成电路),是一种由Philips(现NXP半导体)公司在1980年代初开发的同步 串行 半双工通信总线。 二、有了串口通信为什么要使用I2C&…

【Linux系列】并发与顺序执行:在 Linux 脚本中的应用与选择

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

“AI 视频图像识别系统,开启智能新视界

咱老百姓现在的生活啊,那是越来越离不开高科技了,就说这 AI 视频图像识别系统,听起来挺高大上,实际上已经悄无声息地融入到咱们日常的方方面面,给咱带来了超多便利。 先讲讲安防领域吧,这可是 AI 图像识别的…

Burpsuite20241102macM1版安装

1、安装jdk11 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" brew update brew install openjdk11 echo export PATH"/opt/homebrew/opt/openjdk11/bin:$PATH" >> ~/.zshrc source ~/.zshrc j…