1. 引言
上一篇做了stm32系统启动流程的整理分析,中间遇到stm32启动模式的选择和原理。中间也遇到一些不理解的地方,于是着手做了实验,在这里记录一下。
2. 三种启动模式
目前stm32支持3种启动模式。
BOOT0 | BOOT1 | 启动模式 | 启动地址 |
---|---|---|---|
0 | x | flash | 0x0800 0000 |
1 | 0 | 系统存储器 | 0x1FF00000 |
1 | 1 | RAM | 0x2000 0000 |
从flash和系统存储器启动,系统都会做一个地址的映射。
STM32把从0x00000000到0x0005FFFF的区域作为启动空间(boot space)的别名区。
比如从flash启动,这种情况下,访问0x0 地址 和 0x0800 0000,是完全一样的。
所以在启动后,cotex-M3从0x0地址取MSP,从0x4取PC,就是从0x8000000和0x08000004取。是等价的。
但是,RAM启动是个例外,
即使我们选择了RAM启动,我们也无法通过0x0来访问0x2000 0000。
那RAM究竟是怎么启动的?
3. RAM启动
3.1 原理
首先,我们已知的,当boot0 = 1,boot1 = 1时,即RAM启动时,cotex-m3一定是从0x0取msp,从0x4取pc,而且启动之后0x2000 0000和 0x0是没有映射在一起的。
所以,我们可以有两种推测:
- 系统没有做0x2000 0000到0x0的映射,而是通过系统的内部方式在启动时把0x2000 0000和0x20000004的值赋给了SP和PC。
- 系统在上电时刻做了0x2000 0000到0x0的映射,启动后(取完MSP和PC),断开了这个映射,之后两段空间独立开。
这个我暂时没有找到什么资料说明,但是二者达到的效果是一样的,我个人更倾向于第二种,好记一点。
截个实际的图,可以看出二者确实是不一样的。
3.2 实验步骤
3.2.1 新建一个RAM的project Item
找一个简单的,可以在flash上稳定运行的工程,新建一个RAM启动使用的project Item。
建立这个Item的意义在于,在这里修改的配置,全局宏等,不会影响到flash的那个配置,二者是独立是,而且切换十分方便。
切换之后就会看到左边的工程名不一样了。
除了配置相关,所有添加的代码文件都是公用一套。
3.2.2 修改ROM和RAM地址
之前flash下载的配置大家应该都很熟悉了,
这里我们切换为RAM下载。
先看一下编译文件的大小。
打开map文件
可以看出
生成的bin文件是5884字节大小。
所以,我们给ROM分配的空间大于5884即可。
这里还遇到一个坑,这个最后说。
3.2.3 debug选项卡设置
去掉Load Application at startup
加载一个CpuRam.ini,这个文件我也是网上找的。
/*----------------------------------------------------------------------------
* Name: Dbg_RAM.ini
* Purpose: RAM Debug Initialization File
* Note(s):
*----------------------------------------------------------------------------
* This file is part of the uVision/ARM development tools.
* This software may only be used under the terms of a valid, current,
* end user licence from KEIL for a compatible version of KEIL software
* development tools. Nothing else gives you the right to use this software.
*
* This software is supplied "AS IS" without warranties of any kind.
*
* Copyright (c) 2008-2011 Keil - An ARM Company. All rights reserved.
*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------
Setup() configure PC & SP for RAM Debug
*----------------------------------------------------------------------------*/
FUNC void Setup (void) {
SP = _RDWORD(0x20000000); // Setup Stack Pointer
PC = _RDWORD(0x20000004); // Setup Program Counter
_WDWORD(0xE000ED08, 0x20000000); // Setup Vector Table Offset Register
}
FUNC void OnResetExec (void) { // executes upon software RESET
Setup(); // Setup for Running
}
load %L incremental
Setup(); // Setup for Running
g, main
3.2.4 添加全局宏VECT_TAB_SRAM
VECT_TAB_SRAM主要用于在systemInit的时候重设中断向量表。
3.2.5 配置Utilies选项卡
3.2.6 修改硬件boot引脚电平
把Boot0和BOOT1接高电平。
3.2.7 debug模式运行
RAM启动没法load flash这样烧写进去,也没法断电重启。
主要就是在debug模式下运行。
进入debug后可以单步,可以全速,可以reset。
网上有些帖子说他们没法reset我倒是没遇到,都是可以正常跑的。
跑起来有时候会不太稳定,报错从debug模式退出,不过也能用。
看图跑了挺久都在跑。
4. 遇到的坑
之前做RAM启动的时候,每次一跑进SystemInit就进入硬件异常,弄得我十分郁闷,感觉就是一压栈就异常,但是我跟踪MSP又确实是按我想的变化,就很郁闷,找了大半天发现原因。
之前在 stm32中文手册中看到这一段,
我测试用的stm32f103,我以为RAM都是64k,即0x2000 0000~0x20010000,所以ROM分的是0x2000 0000~0x2000 8000 ,ram分的是0x2000 8000 ~ 0x 2001 0000。
实际根本不是这样,stm32f103c8t6 ram只有20k,所以一对SP操作就异常,访问了非法地址。
改小之后就正常了。