STM32的三种BOOT模式
文章目录
- 一、三种BOOT模式的对比
- 1、内部 FLASH 启动方式
- 2、内部 SRAM 启动方式
- 3、系统存储器启动方式
- 二、BOOT模式下代码运行后所在地址分析
- 1、从内部 FLASH 启动
- 2、从内部 SRAM 启动
- (1) 配置中断向量表
- (2)修改FLASH下配置
- 三、总结
一、三种BOOT模式的对比
CM-3 内核在离开复位状态后的工作过程如下:
- 从地址
0x00000000
处取出栈指针 MSP 的初始值,该值就是栈顶的地址。 - 从地址
0x00000004
处取出程序指针 PC 的初始值,该值指向复位后应执行的第一条指令。
上述过程由内核自动设置运行环境并执行主体程序,因此它被称为自举过程。
虽然内核是固定访问 0x00000000
和 0x00000004
地址的,但实际上这两个地址可以被重映射到其它地址空间。以 STM32F103
为例,根据芯片引出的 BOOT0 及 BOOT1 引脚的电平情况,这两个地址可以被映射到内部 FLASH、内部 SRAM以及系统存储器中。
不同的映射配置如下图:
内核在离开复位状态后会从映射的地址中取值给栈指针 MSP 及程序指针 PC,然后执行指令,我们一般以存储器的类型来区分自举过程,例如内部 FLASH 启动方式、内部SRAM 启动方式以及系统存储器启动方式。
1、内部 FLASH 启动方式
当芯片上电后采样到 BOOT0 引脚为低电平时, 0x00000000 和 0x00000004 地址被映射到内部 FLASH的首地址
0x08000000
和0x08000004
。因此,内核离开复位状态后,读取内部 FLASH 的0x08000000 地址空间存储的内容,赋值给栈指针 MSP,作为栈顶地址,再读取内部FLASH 的 0x08000004 地址空间存储的内容,赋值给程序指针PC,作为将要执行的第一条指令所在的地址。具备这两个条件后,内核就可以开始从 PC指向的地址中读取指令执行了。
2、内部 SRAM 启动方式
类似地,当芯片上电后采样到 BOOT0 和 BOOT1 引脚均为高电平时,0x00000000和 0x00000004地址被映射到内部 SRAM 的首地址
0x20000000
和0x20000004
,内核从SRAM 空间获取内容进行自举。在实际应用中,由启动文件 starttup_stm32f10x.s 决定了 0x00000000 和0x00000004地址存储什么内容,链接时,由分散加载文件.sct决定这些内容的绝对地址,即分配 到内部 FLASH 还是内部SRAM。
这种模式可以用于程序调试。 假如只修改了代码中一个小小的地方,然后就需要重新擦除整个Flash,比较的费时,可以考虑从这个模式启动代码(也就是STM32的内存中),用于快速的程序调试,等程序调试完成后,在将程序下载到SRAM中。
3、系统存储器启动方式
当芯片上电后采样到 BOOT0 引脚为高电平,BOOT1 为低电平时,内核将从系统存储器的
0x1FFFF000
及0x1FFFF004
获取 MSP 及 PC 值进行自举。这种模式启动的程序功能由厂家设置。系统存储器是芯片内部一块特定的区域,用户不能访问,ST 公司在芯片出厂前就在系统存储器中固化了一段代码,也就是我们常说的ISP程序,这是一块ROM,出厂后无法修改。
因而使用系统存储器启动方式时,内核会执行该代码,该代码运行时,会为 ISP 提供支持(In System Program),如检测 USART1/2、CAN2 及 USB 通讯接口传输过来的信息,并根据这些信息更新自己内部 FLASH 的内容,达到升级产品应用程序的目的,因此这种启动方式也称为 ISP 启动方式。
一般来说,我们选用这种启动模式时,是为了从串口下载程序,因为在厂家提供的BootLoader中,提供了串口下载程序的固件,可以通过这个BootLoader将程序下载到系统的Flash中。但是这个下载方式需要以下步骤:
- 将BOOT0设置为1,BOOT1设置为0,然后按下复位键,这样才能从系统存储器启动BootLoader;
- 最后在BootLoader的帮助下,通过串口下载程序到Flash中;
- 程序下载完成后,又需要将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模式相关推荐
- STM32的三种Boot模式的差异
STM32的三种Boot模式的差异 一. STM32启动配置 二. 内置SRAM简介 三. 例程验证 3.1 硬件设置 3.2 创建工程调试版本 3.3 配置分散加载文件 3.5 配置中断向量表 3. ...
- STM32的三种Boot模式地址分配
STM32的三种Boot模式地址分配 一.STM32的三种Boot模式 1.主闪存存储器 2.系统存储器 3.内置SRAM 二.三种模式地址分配验证 主闪存存储器 系统存储器 三.汇编程序完成每间隔1 ...
- 浅谈STM32的三种Boot模式的差异以及用汇编语言设计一个LED灯程序
STM32的三种Boot模式的差异 1.三种方式的比较 用汇编程序完成LED的程序 1.三种方式的比较 所谓启动,一般来说就是指我们下好程序后,重启芯片时,SYSCLK的第4个上升沿,BOOT引脚的值 ...
- 浅谈STM32的三种Boot模式
文章目录 一.关于BOOT模式的介绍 二.实际例子进行分析 三.分析上电启动流程 四.小结 五.参考资料 一.关于BOOT模式的介绍 所谓启动,一般来说就是指我们下好程序后,重启芯片时,SYSCLK的 ...
- 探究 STM32 的三种 BOOT(启动) 模式并实例验证
目录 一.什么是 Boot 模式 二.实例验证 三.总结 四.参考资料 说明 STM32 的三种 Boot 模式的差异,并在之前第11-12周"C语言各种变量的存储地址"作业代码基 ...
- STM32三种BOOT模式
探究STM32三种BOOT模式 简介 一.三种BOOT模式比较 二.开发BOOT模式选择 三.实验项目 (1)实验要求 (2)实验过程 a.STM32内置的Flash启动--最常用 b.从系统存储器启 ...
- STM32单片机的启动模式 三种BOOT模式介绍
在绘制32单片机时,参考别人的原理图对单片机的启动方式BOOT有疑问, 这里写目录标题 自己的理解和应用 一.三种BOOT模式启动的介绍 二.自己开发BOOT模式的选择 官方的文档介绍 自己的理解和应 ...
- STM32三种BOOT模式介绍
一.三种BOOT模式介绍 所谓启动,一般来说就是指我们下好程序后,重启芯片时,SYSCLK的第4个上升沿,BOOT引脚的值将被锁存.用户可以通过设置BOOT1和BOOT0引脚的状态,来选择在复位后的启 ...
- STM32三种BOOT模式的差异
文章目录 前言 三种BOOT模式 主闪存存储器 系统存储器 内置SRAM 烧录程序验证 主要代码 主闪存存储器烧录验证 系统存储器烧录验证 内置SRAM烧录验证 前言 本篇文章分析了3种BOOT模式下 ...
最新文章
- 如何理解jdk8通过行为参数化传递代码
- sed、cut和awk命令的使用
- poj 1015 Jury Compromise_dp
- linux中lvs命令详解,LVS之三:ipvsadm常用管理命令介绍 | 旺旺知识库
- 头条一面竟然问我Maven?
- 投巧解决JavaScript split方法出现空字符的问题
- 渗透测试入门8之端口渗透
- GPU Raycasting的两种实现方法
- datatables页面合并两个列_python实现多个excel合成合并为一个excel
- hadoop合并日志_【hadoop】24.MapReduce-shuffle之合并
- $$\int_0^{nh}x(x-h)\cdots (x-nh)dx=h^{n+2}\int_0^nx(x-1)\cdots (x-n)dx$$
- @transactional注解原理_《Spring源码解析(十二)》深入理解Spring事务原理,告别面试一问三不知的尴尬...
- Kubernetes详解(二)——Kubernetes结构与资源对象
- java实现二分查找
- 为Linux发行版安装simsun.ttf
- Tools - Blender快捷键大全
- 如何设置局域网内的固定IP地址?
- 向前迈进!走入GC世界:G1 GC原理深入解析
- Java的triangle方法_java三角形类Triangle用法代码解析
- winscp是什么软件_文件传输软件WinSCP的使用
热门文章
- 计算机学院的师弟师妹们,请不要去餐馆打工了
- windows命令行工具连接mysql数据库报ERROR 2003 (HY000): Can‘t connect to MySQL server on ‘localhost:3306‘ (10061)
- redis的雪崩和穿透
- POI中设置Excel单元格格式样式(居中,字体,边框,背景色、列宽、合并单元格等)
- 关于iOS 10从2017年1月1日起苹果不允许我们通过这个方法跳过ATS的方法
- AEJoy —— 表达式之闪烁光标的打字机效果(二)【JS】
- 华为鸿蒙arm,华为亮大招:鸿蒙系统+5G万物互联+1亿 掌握ARM架构修改
- 让云助力企业数字化转型
- Google Play In-app Billing
- pdf怎么拆分成几个部分?怎么拆分pdf中的一部分?