使用场景
我们常用的项目开发流程中很少会使用到BootLoader,但是在需要持续更新迭代的项目中,使用BootLoader能够极大地提高用户的使用体验。
比如我曾经购买的示波器OSC509,PCB上有烧录通孔,但是对于普通用户而言,想要更新程序就要找烧录排针,还是十分麻烦的。所以这台示波器采用sd卡更新程序,只要在sd卡中放入新版本的程序,在接下来的启动中就会自动将该程序(bin文件)下载到单片机的flash中,同时删除sd卡中的bin文件。
当时只知道Linux中有uBoot,现在知道stm32也可以通过这样的方式启动。
原理
启动方式
单片机具有Boot0和Boot1脚,在正点原子或者野火的学习板上我们可以通过跳线帽选择启动方式: 三种启动方式
1、第一种方式(boot0 = 0):Flash memory启动方式 启动地址:0x08000000 是STM32内置的Flash,一般我们使用JTAG或者SWD模式下载程序时,就是下载到这个里面,重启后也直接从这启动程序。基本上都是采用这种模式。
2、第二种方式(boot0 = 1;boot1 = 0):System memory启动方式 启动地址:0x1FFF0000从系统存储器启动,这种模式启动的程序功能是由厂家设置的。一般来说,这种启动方式用的比较少。系统存储器是芯片内部一块特定的区域,STM32在出厂时,由ST在这个区域内部预置了一段BootLoader, 也就是我们常说的ISP程序, 这是一块ROM,出厂后无法修改。一般来说,我们选用这种启动模式时,是为了从串口下载程序,因为在厂家提供的BootLoader 中,提供了串口下载程序的固件,可以通过这个BootLoader将程序下载到系统的Flash中。但是这个下载方式需要以下步骤:
- 将BOOT0设置为1,BOOT1设置为0,然后按下复位键,这样才能从系统存储器启动BootLoader。
- 最后在BootLoader的帮助下,通过串口下载程序到Flash中
- 程序下载完成后,又有需要将BOOT0设置为GND,手动复位,按照第1种启动方式的流程启动。
3、第三种方式(boot0 = 1;boot1 = 1):SRAM启动方式。 启动地址:0x20000000 内置SRAM,既然是SRAM,自然也就没有程序存储的能力了,这个模式一般用于程序调试。假如我只修改了代码中一个小小的 地方,然后就需要重新擦除整个Flash,比较的费时,可以考虑从这个模式启动代码(也就是STM32的内存中),用于快速的程序调试,等程序调试完成后,在将程序下载到SRAM中。
从flash启动
无论如何单片机都是从0x0000_0000的位置开始运行的,其中最重要的就是PC和SP,PC指的是当前运行的位置,SP指向当前使用RAM的堆栈栈顶。
我们知道在keil中的魔法棒工具栏中可以选择ROM(即flash)和RAM的起始地址和大小, ROM和RAM的地址选择 当单片机刚上电的时候,会根据Boot0和Boot1的状态选择启动方式,比如选择启动方式1(从flash启动),就会将图中0x0800_0000处的flash内容复制到0x0000_0000处开始运行。
下面的表格是刚上电时单片机ROM中的状态,此时已将flash内容映射到0x0000_0000:
指针 | 地址 | 功能 |
0x0000_0000 | __initial_sp | |
PC – > | 0x0000_0004 | Reset Handler |
0x0000_0008 | NMI_Handler | |
… | … | … |
启动流程: (1)初始化堆栈指针SP=_initial_sp。 (2)初始化PC指针,令其=Reset_Handler。 (3)初始化中断向量表。 (4)配置系统时钟。 (5)调用C库函数_main初始化用户堆栈,从而最终调用main函数。
; Reset handler Reset_Handler PROC EXPORT Reset_Handler [WEAK] IMPORT __main IMPORT SystemInit LDR R0, =SystemInit BLX R0 LDR R0, =__main BX R0 ENDP
已知以上内容,那么我们如何更改程序每次启动所使用的应用程序呢? 我们在单片机中的flash中烧录两个程序,而程序的关键就在于ROM和RAM,ROM保存的是程序(函数的集合)和一些确定的(静态)变量,RAM保存一些动态的变量,那么我们就能描述出一个程序是怎么样的了。
所以,IAP的关键在于两个程序中的切换,在单片机启动的时候根据BootLoader的内容设置BootLoader程序的SP -> BL堆栈栈顶, PC -> BL的reset_handler,一直运行下去,直到切换到应用程序。 上述BL的SP和PC设置是单片机在启动文件startup_stm32f103xe.s中设置的,但由于BL和App程序很难做到在flash中完全连接在一起,这俩程序是独立的,也就是分开来进行烧录的,互不影响,所以切换到App的时候需要我们手动设置PC和SP的指向,接着完全交由单片机运行。
代码示例:Bootloader_v1.0 — Code Library From HawkJ v1.0 文档 (hawkj02.github.io)
发表回复