文章目录

  • 一、三种BOOT模式的对比
    • 1、内部 FLASH 启动方式
    • 2、内部 SRAM 启动方式
    • 3、系统存储器启动方式
  • 二、BOOT模式下代码运行后所在地址分析
    • 1、从内部 FLASH 启动
    • 2、从内部 SRAM 启动
      • (1) 配置中断向量表
      • (2)修改FLASH下配置
  • 三、总结

一、三种BOOT模式的对比

CM-3 内核在离开复位状态后的工作过程如下:

  1. 从地址 0x00000000 处取出栈指针 MSP 的初始值,该值就是栈顶的地址。
  2. 从地址 0x00000004 处取出程序指针 PC 的初始值,该值指向复位后应执行的第一条指令。


上述过程由内核自动设置运行环境并执行主体程序,因此它被称为自举过程。

虽然内核是固定访问 0x000000000x00000004 地址的,但实际上这两个地址可以被重映射到其它地址空间。以 STM32F103 为例,根据芯片引出的 BOOT0 及 BOOT1 引脚的电平情况,这两个地址可以被映射到内部 FLASH、内部 SRAM以及系统存储器中。

不同的映射配置如下图:

内核在离开复位状态后会从映射的地址中取值给栈指针 MSP 及程序指针 PC,然后执行指令,我们一般以存储器的类型来区分自举过程,例如内部 FLASH 启动方式、内部SRAM 启动方式以及系统存储器启动方式。

1、内部 FLASH 启动方式

  • 当芯片上电后采样到 BOOT0 引脚为低电平时, 0x00000000 和 0x00000004 地址被映射到内部 FLASH的首地址 0x080000000x08000004

  • 因此,内核离开复位状态后,读取内部 FLASH 的0x08000000 地址空间存储的内容,赋值给栈指针 MSP,作为栈顶地址,再读取内部FLASH 的 0x08000004 地址空间存储的内容,赋值给程序指针PC,作为将要执行的第一条指令所在的地址。具备这两个条件后,内核就可以开始从 PC指向的地址中读取指令执行了。

2、内部 SRAM 启动方式

  • 类似地,当芯片上电后采样到 BOOT0 和 BOOT1 引脚均为高电平时,0x00000000和 0x00000004地址被映射到内部 SRAM 的首地址 0x200000000x20000004,内核从SRAM 空间获取内容进行自举。

  • 在实际应用中,由启动文件 starttup_stm32f10x.s 决定了 0x00000000 和0x00000004地址存储什么内容,链接时,由分散加载文件.sct决定这些内容的绝对地址,即分配 到内部 FLASH 还是内部SRAM。

  • 这种模式可以用于程序调试。 假如只修改了代码中一个小小的地方,然后就需要重新擦除整个Flash,比较的费时,可以考虑从这个模式启动代码(也就是STM32的内存中),用于快速的程序调试,等程序调试完成后,在将程序下载到SRAM中。

3、系统存储器启动方式

  • 当芯片上电后采样到 BOOT0 引脚为高电平,BOOT1 为低电平时,内核将从系统存储器的 0x1FFFF0000x1FFFF004 获取 MSP 及 PC 值进行自举。

  • 这种模式启动的程序功能由厂家设置。系统存储器是芯片内部一块特定的区域,用户不能访问,ST 公司在芯片出厂前就在系统存储器中固化了一段代码,也就是我们常说的ISP程序,这是一块ROM,出厂后无法修改

  • 因而使用系统存储器启动方式时,内核会执行该代码,该代码运行时,会为 ISP 提供支持(In System Program),如检测 USART1/2、CAN2 及 USB 通讯接口传输过来的信息,并根据这些信息更新自己内部 FLASH 的内容,达到升级产品应用程序的目的,因此这种启动方式也称为 ISP 启动方式

  • 一般来说,我们选用这种启动模式时,是为了从串口下载程序,因为在厂家提供的BootLoader中,提供了串口下载程序的固件,可以通过这个BootLoader将程序下载到系统的Flash中。但是这个下载方式需要以下步骤:

  1. 将BOOT0设置为1,BOOT1设置为0,然后按下复位键,这样才能从系统存储器启动BootLoader;
  2. 最后在BootLoader的帮助下,通过串口下载程序到Flash中;
  3. 程序下载完成后,又需要将BOOT0设置为GND,手动复位,这样,STM32才可以从Flash中启动,可以看到,利用串口下载程序还是比较的麻烦,需要跳帽跳来跳去的,非常的不注重用户体验。

二、BOOT模式下代码运行后所在地址分析

1、从内部 FLASH 启动

BOOT0,B00T1都接低电平

测试代码

#include "led.h"
#include "delay.h"
//#include "key.h"
#include "sys.h"
#include "usart.h"
#include <stdio.h>
#include <stdlib.h>int k1 = 1;        //已初始化全局int型变量k1
int k2;            //未初始化全局int型变量k2
static int k3 = 2; //已初始化静态全局int型变量k3
static int k4;     //未初始化静态全局int型变量k4int main(void){    delay_init();            //延时函数初始化    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级uart_init(115200);     //串口初始化为115200LED_Init();               //LED端口初始化//KEY_Init();          //初始化与按键连接的硬件接口while(1){static int m1 = 2;      //已初始化静态局部int型变量m1static int m2;          //未初始化静态局部int型变量m2int i1;              //未初始化局部int型变量i1int i2;             //未初始化局部int型变量i2char *p;                //未初始化局部char型指针变量pchar str[10] = "hello"; //已初始化局部char型数组strchar *var1 = "123456";  //已初始化局部char型指针变量var1char *var2 = "abcdef";  //已初始化局部char型指针变量var2int *p1 = malloc(4);    //已初始化局部int型指针变量p1int *p2 = malloc(4);    //已初始化局部int型指针变量p2printf("栈区-变量地址\r\n");printf("未初始化局部int型变量i1       :0x%p\r\n", &i1);printf("未初始化局部int型变量i2       :0x%p\r\n", &i2);printf("未初始化局部char型指针变量p   :0x%p\r\n", &p);printf("已初始化局部char型数组str     :0x%p\r\n", str);//test();printf("\n堆区-动态申请地址\r\n");printf("已初始化局部int型指针变量p1   :0x%p\r\n", p1);printf("已初始化局部int型指针变量p2   :0x%p\r\n", p2);printf("\n.bss段地址\r\n");printf("未初始化全局int型变量k2       :0x%p\r\n", &k2);printf("未初始化静态全局int型变量k4   :0x%p\r\n", &k4);printf("未初始化静态局部int型变量m2   :0x%p\r\n", &m2);printf("\n.data段地址\r\n");printf("已初始化全局int型变量k1       :0x%p\r\n", &k1);printf("已初始化静态全局int型变量k3   :0x%p\r\n", &k3);printf("已初始化静态局部int型变量m1   :0x%p\r\n", &m1);printf("\n常量区地址\r\n");printf("已初始化局部char型指针变量var1:0x%p\r\n", var1);printf("已初始化局部char型指针变量var2:0x%p\r\n", var2);printf("\n代码区地址\r\n");printf("程序代码区main函数入口地址    :0x%p\r\n", &main);free(p1);free(p2);        }
}

连接电脑和开发板

输出结果

此外,通过查询应用程序编译时产生的.map后缀文件,也可以了解程序存储到了哪些区域


打开 map 文件后,查看文件最后部分的区域,可以看到一段以“Memory Map of the image”开头的记录(若找不到可用查找功能定位)

这一段是即工程的 ROM 存储器分布映像,在 STM32芯片中,ROM 区域的内容就是指存储到内部 FLASH 的代码。

2、从内部 SRAM 启动

BOOT0 和 BOOT1 引脚均为高电平

(1) 配置中断向量表

  • 由于 startup_stm32f10x.s 文件中的启动代码不是指定到绝对地址的,经过它由链接器决定应存储到内部 FLASH 还是SRAM,所以 SRAM 版本工程中的启动文件不需要作任何修改

  • 重点在于启动文件定义的中断向量表被存储到内部 FLASH 和内部 SRAM 时,这两种情况对内核的影响是不同的,内核会根据它的“向量表偏移寄存器 VTOR”配置来获取向 量表,即中断服务函数的入口。VTOR寄存器是由启动文件中 Reset_Handle 中调用的库函数SystemInit 配置的

  • 代码中根据是否存储宏定义 VECT_TAB_SRAM 来决定 VTOR 的配置,默认情况下代码中没有定义宏VECT_TAB_SRAM,所以 VTOR 默认情况下指示向量表是存储在内部FLASH 空间的。

  • 由于本工程的分散加载文件配置,在启动文件中定义的中断向量表会被分配到 SRAM空间,所以我们要定义这个宏,使得 SystemInit函数修改 VTOR 寄存器,向内核指示向量表被存储到内部 SRAM 空间了。

在“Options for Target-> c/c++ ->Define”框中输入宏VECT_TAB_SRAM

配置完成后重新编译工程,即可生成存储到 SRAM 空间地址的代码指令。

(2)修改FLASH下配置


  • 把“Download Function”中的擦除选项配置为“Do not Erase”。这是因为数据写入到内部SRAM中不需要像FLASH那样先擦除后写入。在本工程中,如果我们不选择“Do not Erase”的话,会因为擦除过程导致下载出错。

  • “RAM for Algorithm”一栏是指“编程算法”(Programming Algorithm)可使用的RAM空间,下载程序到FLASH时运行的编程算法需要使用RAM空间,在默认配置中它的首地址为Ox20000000,即内部SRAM的首地址,但由于我们的分散加载文件配置,0x20000000地址开始的32KB实际为虚拟ROM空间,实际的RAM空间是从地址Ox20008000开始的,所以这里把算法RAM首地址更改为本工程中实际作为RAM使用的地址。若编程算法使用的RAM地址与虚拟ROM空间地址重合的话,会导致下载出错。

  • “Programming Algorithm”一栏中是设置内部FLASH的编程算法,编程算法主要描述了FLASH的地址、大小以及扇区等信息,MDK根据这些信息把程序下载到芯片的FLASH中,不同的控制器芯片一般会有不同的编程算法。由于MDK没有内置SRAM的编程算法,所以我们直接在原来的基础上修改它的基地址和空间大小,把它改成虚拟ROM的空间信息。

输出结果

三、总结

若使用STM32的内部SRAM存储程序,程序的执行速度与在FLASH上执行速度无异,但SRAM空间较小。若使用外部扩展的SRAM存储程序,程序空间非常大,但 STM32读取外部SRAM的速度比读取内部 FLASH 慢,这会导致程序总执行时间增加,因此在外部 SRAM中调试的程序无法完美仿真在内部FLASH运行时的环境。另外,由于STM32无法直接从外部SRAM中启动且应用程序复制到外部 SRAM的过程比较复杂(下载程序前需要使 STM32能正常控制外部SRAM),所以在很少会在STM32的外部 SRAM中调试程序。

STM32的三种BOOT模式相关推荐

  1. STM32的三种Boot模式的差异

    STM32的三种Boot模式的差异 一. STM32启动配置 二. 内置SRAM简介 三. 例程验证 3.1 硬件设置 3.2 创建工程调试版本 3.3 配置分散加载文件 3.5 配置中断向量表 3. ...

  2. STM32的三种Boot模式地址分配

    STM32的三种Boot模式地址分配 一.STM32的三种Boot模式 1.主闪存存储器 2.系统存储器 3.内置SRAM 二.三种模式地址分配验证 主闪存存储器 系统存储器 三.汇编程序完成每间隔1 ...

  3. 浅谈STM32的三种Boot模式的差异以及用汇编语言设计一个LED灯程序

    STM32的三种Boot模式的差异 1.三种方式的比较 用汇编程序完成LED的程序 1.三种方式的比较 所谓启动,一般来说就是指我们下好程序后,重启芯片时,SYSCLK的第4个上升沿,BOOT引脚的值 ...

  4. 浅谈STM32的三种Boot模式

    文章目录 一.关于BOOT模式的介绍 二.实际例子进行分析 三.分析上电启动流程 四.小结 五.参考资料 一.关于BOOT模式的介绍 所谓启动,一般来说就是指我们下好程序后,重启芯片时,SYSCLK的 ...

  5. 探究 STM32 的三种 BOOT(启动) 模式并实例验证

    目录 一.什么是 Boot 模式 二.实例验证 三.总结 四.参考资料 说明 STM32 的三种 Boot 模式的差异,并在之前第11-12周"C语言各种变量的存储地址"作业代码基 ...

  6. STM32三种BOOT模式

    探究STM32三种BOOT模式 简介 一.三种BOOT模式比较 二.开发BOOT模式选择 三.实验项目 (1)实验要求 (2)实验过程 a.STM32内置的Flash启动--最常用 b.从系统存储器启 ...

  7. STM32单片机的启动模式 三种BOOT模式介绍

    在绘制32单片机时,参考别人的原理图对单片机的启动方式BOOT有疑问, 这里写目录标题 自己的理解和应用 一.三种BOOT模式启动的介绍 二.自己开发BOOT模式的选择 官方的文档介绍 自己的理解和应 ...

  8. STM32三种BOOT模式介绍

    一.三种BOOT模式介绍 所谓启动,一般来说就是指我们下好程序后,重启芯片时,SYSCLK的第4个上升沿,BOOT引脚的值将被锁存.用户可以通过设置BOOT1和BOOT0引脚的状态,来选择在复位后的启 ...

  9. STM32三种BOOT模式的差异

    文章目录 前言 三种BOOT模式 主闪存存储器 系统存储器 内置SRAM 烧录程序验证 主要代码 主闪存存储器烧录验证 系统存储器烧录验证 内置SRAM烧录验证 前言 本篇文章分析了3种BOOT模式下 ...

最新文章

  1. 如何理解jdk8通过行为参数化传递代码
  2. sed、cut和awk命令的使用
  3. poj 1015 Jury Compromise_dp
  4. linux中lvs命令详解,LVS之三:ipvsadm常用管理命令介绍 | 旺旺知识库
  5. 头条一面竟然问我Maven?
  6. 投巧解决JavaScript split方法出现空字符的问题
  7. 渗透测试入门8之端口渗透
  8. GPU Raycasting的两种实现方法
  9. datatables页面合并两个列_python实现多个excel合成合并为一个excel
  10. hadoop合并日志_【hadoop】24.MapReduce-shuffle之合并
  11. $$\int_0^{nh}x(x-h)\cdots (x-nh)dx=h^{n+2}\int_0^nx(x-1)\cdots (x-n)dx$$
  12. @transactional注解原理_《Spring源码解析(十二)》深入理解Spring事务原理,告别面试一问三不知的尴尬...
  13. Kubernetes详解(二)——Kubernetes结构与资源对象
  14. java实现二分查找
  15. 为Linux发行版安装simsun.ttf
  16. Tools - Blender快捷键大全
  17. 如何设置局域网内的固定IP地址?
  18. 向前迈进!走入GC世界:G1 GC原理深入解析
  19. Java的triangle方法_java三角形类Triangle用法代码解析
  20. winscp是什么软件_文件传输软件WinSCP的使用

热门文章

  1. 计算机学院的师弟师妹们,请不要去餐馆打工了
  2. windows命令行工具连接mysql数据库报ERROR 2003 (HY000): Can‘t connect to MySQL server on ‘localhost:3306‘ (10061)
  3. redis的雪崩和穿透
  4. POI中设置Excel单元格格式样式(居中,字体,边框,背景色、列宽、合并单元格等)
  5. 关于iOS 10从2017年1月1日起苹果不允许我们通过这个方法跳过ATS的方法
  6. AEJoy —— 表达式之闪烁光标的打字机效果(二)【JS】
  7. 华为鸿蒙arm,华为亮大招:鸿蒙系统+5G万物互联+1亿 掌握ARM架构修改
  8. 让云助力企业数字化转型
  9. Google Play In-app Billing
  10. pdf怎么拆分成几个部分?怎么拆分pdf中的一部分?