目录
一、前言
听到BootLoader大家一定很熟悉,在很多常见的系统中都会存在BootLoader。本文将介绍BootLoader的含义和简易实现,建议大家学习前掌握些原理基础。
二、BootLoader
Boot系统即设备启动时优先运行的程序,可以帮助我们选择进入哪一个系统。在电脑中,Boot系统也是十分重要的,系统的基础功能和引导功能都是有Boot实现的。
而Loader即载入系统,载入用户真正使用的系统。
系统上电后,先进入Boot程序,由Boot程序决定进入系统,还是等待用户指令。以单片机为例,假设其Flash为20K,那么我可以将其分为两个区域,一个区域用于存储Boot程序,一个区域用于存储应用程序(APP),而Boot程序只烧写一次,用户烧录APP程序时,仅擦除APP区域。
Boot程序作为独立的单片机程序,当然也可以完成擦除和写入Flash的功能,如果我们在Boot程序运行时,将APP对应的Flash信息发送给Boot程序,由Boot程序对Flash中的APP区的擦除和写入,那是不是同样能实现烧写程序的功能。
如果将发送方式改为蓝牙、WIFI等无线形式,是不是就能对APP程序实现远程烧写。既然远程烧写能够实现,那么远程升级的功能应运而生,这就是OTA(On The Air)。
三、BootLoader的实现
配置基础的STM32CUBEMX工程,此处选用芯片为STM32F103C8T6.
此处我只配置了一个串口(波特率256000,自定),用于输出调试信息,并使能DMA和中断。
打开项目工程。此处STM32F103C8T6的Flash为64K,其实地址为0x08000000,则Flash范围为0x0800 0000~0x0800 FFFF,此处我划Boot分区16K,APP分区48K,则Boot分区Flash范围为:0x0800 0000~0x0800 3FFF,Size = 0x4000。
按照下图配置。
如果你使用ST-Link或者其他烧写器的话,在Boot程序工程中要勾选全部擦除。
此时,我们让设备等待三秒,随后进入APP。
cpp
__asm void MSR_MSP(uint32_t addr)
{
MSR MSP, r0
BX r14;
}
void App_Loading(void)
{
APP_FUNC Jump;//定义一个函数指针
printf("\n%x\n",(*(uint32_t *)APP_ADDR)&0x2FFFFFFF);
// 栈顶地址是否合法
if(((*(uint32_t *)APP_ADDR)&0x2FFFFFFF) < (0x20000000+0x400 * RAM_SIZE))
{
printf("Start To APP");
//设置栈指针
MSR_MSP(APP_ADDR);
// 获取复位地址
Jump=(APP_FUNC)*(volatile uint32_t *)(APP_ADDR+4);
//设置栈指针
__set_MSP(*(volatile uint32_t *)APP_ADDR);
//关闭所有中断
__set_PRIMASK(1);
// 跳转至APP
Jump();
}
else{
printf("Address Not Found");
}
}
将程序烧写进单片机,Boot程序就已经下载完成了。
注意,使用printf函数需要重写fputc并且勾选MicroLib。
cpp
#include "stdio.h"
int fputc(int c, FILE* stream)
{
uint8_t ch[]={c};
HAL_UART_Transmit(&huart1,ch,1,0xffff);
return c;
}
四、APP程序
在自己定制的BootLoader中,APP的程序与日常使用的程序有些许不同,由于在BootLoader中我们更改了一些参数配置,为了能够顺利跳转到APP程序中。但这些配置需要恢复才能让APP程序正常运行。
使用STM32CUBEMX生成一个LED闪烁的程序,使用Keil打开工程。
先配置程序烧写区域,上述中Boot区域占16K,因此APP程序起始地址为0x0800 4000 ,APP程序48K,即Size = 0xC000。
有ST-LINK的情况下,需要设置烧写模式为仅擦除训选择区域,防止擦除Boot程序。
随后在main.c中main函数中添加这两条语句。
cpp
//SCB ->VTOR = FLASH_BASE | OFFSET;
SCB ->VTOR = FLASH_BASE | 0x4000;
__set_PRIMASK(0);
五、效果展示
将单片机程序烧写进板子后,打开串口助手,并观察效果。
观察到单片机顺利进入APP程序,并且实现了交替闪烁。
六、拓展
大家可以添加菜单模式,比如通过串口收到某个指令随后进入菜单模式,实现擦除或者其他操作。我实现了一小部分,大家可以看看。源码不需要积分。
本文仅帮助快速实现BootLoader,具体原理讲解将在另一篇博文进行。
BootLoader源工程:BootLoader
APP源工程:简易APP配套BootLoader