STM32的三种Boot模式的差异
摘要:在我们学习STM32F103XX系列的,一般都是通过串口或者ST-Llink直接烧录到Falsh中。但有些是时候想直接调试硬件,那么如何进行烧录程序呢?-----此次通过学习将介绍将程序烧到SRAM中。
一、 STM32启动配置
在STM32F10xxx里,可以通过BOOT[1:0]引脚选择三种不同启动模式。
BOOT1 | BOOT0 | 启动模式 | 说明 |
---|---|---|---|
X | 0 | 主闪存存储器 | 主闪存存储器被选为启动区域 |
0 | 1 | 系统存储器 | 系统存储器被选为启动区域 |
1 | 1 | 内置SRAM | 内置SRAM被选为启动区域 |
在系统复位后,SYSCLK的第4个上升沿,BOOT引脚的值将被锁存。
用户可以通过设置BOOT1和BOOT0引脚的状态,来选择在复位后的启动模式。
在从待机模式退出时,BOOT引脚的值将被被重新锁存;因此,**在待机模式下BOOT引脚应保持为需要的启动配置。**在启动延迟之后,CPU从地址0x0000 0000
获取堆栈顶的地址,并从启动存储器的0x0000 0004
指示的地址开始执行代码。
因为固定的存储器映像,代码区始终从地址0x0000 0000
开始(通过ICode和DCode总线访问),而数据区**(SRAM)**始终从地址0x2000 0000
开始(通过系统总线访问)。Cortex-M3的CPU始终从ICode总线获取复位向量,即启动仅适合于从代码区开始(典型地从Flash启动)。STM32F10xxx微控制器实现了一个特殊的机制,系统可以不仅仅从Flash存储器或系统存储器启动,还可以从内置SRAM启动。
根据选定的启动模式,主闪存存储器、系统存储器或SRAM可以按照以下方式访问:
- 从主闪存存储器启动:主闪存存储器被映射到启动空间(
0x0000 0000
),但仍然能够在它原有的地址(0x0800 0000
)访问它,即闪存存储器的内容可以在两个地址区域访问,0x0000 0000
或0x0800 0000
。 - 从系统存储器启动:系统存储器被映射到启动空间(
0x0000 0000
),但仍然能够在它原有的地址(互联型产品原有地址为0x1FFF B000
,其它产品原有地址为0x1FFF F000
)访问它。 - 从内置SRAM启动:只能在
0x2000 0000
开始的地址区访问SRAM。
注意: 当从内置SRAM启动,在应用程序的初始化代码中,必须使用NVIC的异常表和偏移寄存器,从新映射向量表之SRAM中。
以上皆来源《STM32F10xxx参考手册》–2.4启动配置章节
二、 内置SRAM简介
一般情况下,我们在MDK 中编写工程应用后,调试时都是把程序下载到芯片的内部FLASH 运行测试的,代码的CODE
及RW-data
的内容被写入到内部FLASH
中存储。但在某些应用场合下却不希望或不能修改内部FLASH 的内容,这时就可以使用RAM 调试功能了,它的本质是把原来存储在内部FLASH 的代码(CODE 及RW-data 的内容
)改为存储到SRAM中(内部SRAM或外部SDRAM均可
),芯片复位后从SRAM中加载代码并运行。
STM32F10xxx内置64K
字节的静态SRAM
。它可以以字节、半字(16位)或全字(32位)
访问。SRAM的起始地址是0x2000 0000
。
把代码下载到RAM中调试有如下优点:
- 下载程序非常快。RAM 存储器的写入速度比在内部FLASH 中要快得多,且没有擦除过程,因此在RAM上调试程序时程序几乎是秒下的,对于需要频繁改动代码的调试过程,能节约很多时间,省去了烦人的擦除与写入FLASH 过程。另外,STM32 的内部FLASH 可擦除次数为1 万次,虽然一般的调试过程都不会擦除这么多次导致FLASH 失效,但这确实也是一个考虑使用RAM的因素。
- 不改写内部FLASH 的原有程序。
- 对于内部FLASH 被锁定的芯片,可以把解锁程序下载到RAM上,进行解锁。
相对地,把代码下载到RAM中调试有如下缺点:
- 存储在RAM上的程序掉电后会丢失,不能像FLASH 那样保存。
- 若使用STM32 的内部SRAM 存储程序,程序的执行速度与在FLASH 上执行速度无异,但SRAM空间较小。
- 若使用外部扩展的SRAM 存储程序,程序空间非常大,但STM32读取外部SRAM 的速度比读取内部FLASH 慢,这会导致程序总执行时间增加,因此在外部SRAM中调试的程序无法完美仿真在内部FLASH 运行时的环境。另外,由于STM32 无法直接从外部SRAM中启动且应用程序复制到外部SRAM的过程比较复杂(下载程序前需要使STM32 能正常控制外部SRAM),所以在很少会在STM32 的外部SRAM中调试程序。
具体介绍请参考学习《零死角玩转STM32——F103指南者》第44章在SRAM中调试代码
三、 例程验证
具体实验步骤参考《零死角玩转STM32——F103指南者》44.4实验:在内部SRAM 中调试
此博客将介绍的是串口下载的SRAM的步骤,且在实验最后并没有完美呈现出串口输出地址,也可以说是失败案例。如想直接通过串口成功读出代码地址请阅读**《零死角玩转STM32——F103指南者》44.4实验:在内部SRAM 中调试**
3.1 硬件设置
将跳线设置为BOOT[1:1]
3.2 创建工程调试版本
3.3 配置分散加载文件
新建SRAM-test.srt
文件并进行添加路径,编写内容代码:
; *************************************************************
; *** Scatter-Loading Description File generated by uVision ***
; *************************************************************
LR_IROM1 0x08000000 0x00080000 { ; load region size_region
ER_IROM1 0x08000000 0x00080000 { ; load address = execution address
*.o (RESET, +First)
*(InRoot$$Sections)
.ANY (+RO)
.ANY (+XO)
}
RW_IRAM1 0x20000000 0x00010000 { ; RW data
.ANY (+RW +ZI)
}
}
3.5 配置中断向量表
system_stm32f10x.c
文件中配置SystemInit 函数
- 代码如下:
void SystemInit (void)
{
/* ..其它代码部分省略 */
/* 配置向量表添加的偏移地址 ----*/
#ifdef VECT_TAB_SRAM
SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */
#else
SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */
#endif
}
直接在
system_stm32f10x.c
快捷查找Ctrl+F
SystemInit函数
3.6 修改FLASH 下载配置
3.7 实验结果
可以通过串口将程序烧录到SRAM中,但按下复位键串口输出不到任何信息。根据《零死角玩转STM32——F103指南者》44.4实验:在内部SRAM 中调试得出
通过继续阅读,使用Dubegger可以进行串口调试输出代码地址。
以上流程皆参考《零死角玩转STM32——F103指南者》44.4实验:在内部SRAM 中调试,如有侵权,立即删除。同时也特别感谢野火提供的资料学习。
与之前C语言程序里全局变量、局部变量、堆、栈等概念的对比验证了主函数地址入口确实发生了改变。代码入口地址为0x20000145。显然代码进入了SRAM中调试
四、 总结
通过学习SRAM,使我了解并掌握了通过SRAM进行代码调试的工作,也对一些Flash锁死有了一定的了解,但通过串口实现还是有许多各种各样的困难,且无法通过串口输出代码入口地址,所以推荐大家直接进行Debugger进行验证。
五、 参考资料
1.《零死角玩转STM32——F103指南者》44.4实验:在内部SRAM 中调试
2.STM32 BOOT模式配置以及作用
3.stm32的程序在ROM和RAM中是如何运行的/在哪里执行的?
4.STM32的map文件详细教程
5.STM32烧录程序方式
6.《STM32F10xxx参考手册》–2.4启动配置章节