嵌入式系统引导程序-Bootloader
·
1.Bootloader是什么?
Bootloader(引导加载程序)就像你手机、电脑或其他智能设备的“启动向导”。当你按下开机键时,这个“向导”是第一个被唤醒的程序,它的任务是把设备从“关机状态”一步步引导到“正常工作状态”。
举个栗子🌰:
想象你刚买了一台新电脑,第一次开机时,屏幕会先显示品牌Logo,接着检查硬件(比如内存、硬盘),最后才进入Windows系统——这个过程就是Bootloader在幕后操控的。
在STM32中,bootloader的主要作用就是用来进行OTA升级。让嵌入式设备维护更加便捷。
2.硬件平台
本次实验主要使用
- STM32F407VET6主控(512KB Flash/192KB RAM)
- ESP8266模块
- 外置Flash W25Q128(128Mbit(16MB),采用 SPI 接口)
3.实验内容
bootloader:
上电后 2000 ms内,输入小写字母 w,进入BOOTLOADER命令行
[1]擦除A区
[2]串口IAP下载A区程序
[3]设置OTA版本号
[4]查询OTA版本号
[5]向外部Flash下载程序
[6]使用外部Flash中的程序
[7]重启
[8]ESP32wifi连接
[9]设置服务器连接信息
采用串口交互。可存储0-10(11个)程序,每个程序最大64K。其中0号程序为OTA更新专用区域。
4.实验规划
1.逻辑规划

1.命令行交互系统
- 串口中断接收与超时检测(2000ms内检测字符'w'触发)
- 菜单界面动态生成与用户输入解析
2.固件管理功能实现
- 功能[1] Flash擦除:STM32内部Flash扇区擦除(STM32 HAL库函数调用)
- 功能[2] 串口IAP下载:XModem协议实现固件传输与校验
- 功能[5]/[6] 外部Flash操作:SPI驱动W25Q128实现固件存储与加载
3.OTA版本控制
- 功能[3]/[4] 版本号管理:存放于W25Q128(结构体序列化)
- 固件完整性校验(CRC32算法实现)
4.网络通信模块
- 功能[8] ESP8266连接WiFi:AT指令集封装(STA模式配置)
- 功能[9] 服务器设置:TCP/IP参数存储与心跳包机制(JSON格式解析)
5.系统控制类功能
- 功能[7] 重启控制:软复位实现(NVIC_SystemReset)
2.内存规划
1.内部FLASH :
//32K 扇区0+扇区1 bootloader区域
FLASH_B_SADDR 0X08000000 //B区FLASH起始位置
FLASH_B_ENDDR 0X08007FFF //B区FLASH结束位置
//96K 扇区2+扇区3+扇区4 app区域
FLASH_A_SADDR 0X08008000 //A区FLASH起始位置
FLASH_A_ENDDR 0X0801FFFF //A区FLASH结束位置
2.外部W25Q128:
第0-11块 存储程序,一块64KB。 第159块存放OTA相关结构体。
/*---------------------------------------------------*/
/*--------------------- 结构体 -----------------------*/
/*---------------------------------------------------*/
typedef struct
{
uint32_t OTA_flag; //标志性的变量,若等于OTA_flag_cont定义的值时,表明需要0TA更新A区
uint32_t Fier_size[11]; //w25Q128中不同块中程序固件的长度,0号成员固定对应w25Q64中编码0的块,用于0TA
uint8_t OTA_ver[32]; //存放版本号 VER-1.0.1-2025/04/02-11:45
} OTA_Info;
typedef struct
{
uint8_t Updatabuff[FLASH_PAGE_SIZE]; // 更新A区时,用于保存从w25Q64中读取的数据
uint32_t w25q128_blockNum; //更新第几个程序,Fier_size[w25q128_blockNum] 要更新程序的长度
uint32_t Xmdoem_time; //协议规定的500ms
uint32_t Xmdoem_Rx_NUM; //协议接收包的个数
uint32_t Xmdoem_CRC16; //协议CRC
} UpdataA_cb;
5.部分代码
1.跳转APP程序
/******************************************************************************
* 函 数: LOAD_A
* 功 能: 程序跳转A分区
* 备 注: 1. 如果跳转直接运行A区程序
* 2. 失败则打印 ERROR
******************************************************************************/
void LOAD_A(void)
{
// boot_clear();
// 获取应用程序的起始地址(确保这个地址正确)
uint32_t app_address = FLASH_A_SADDR; // 例如 0x08004000
if ((*(uint32_t *)app_address >= 0x20000000) && (*(uint32_t *)app_address <= 0x2002FFFF))
{
typedef void (*pFunction)(void);
pFunction JumpToApp;
// 禁用中断
HAL_RCC_DeInit();
__disable_irq();
boot_clear();
// 设置主堆栈指针 (MSP)
__set_MSP(*(uint32_t*)app_address);
// 获取向量表地址(通常是 MSP + 4)
SCB->VTOR = app_address;
// 跳转到应用程序的入口(Reset_Handler)
JumpToApp = (pFunction)(*(uint32_t*)(app_address + 4));
JumpToApp();
}
else
printf("ERROR:跳转地址越界\r\n");
}
2.软重启
HAL_Delay(200);
HAL_NVIC_SystemReset(); // 复位
printf("MCU重启\r\n");
3.菜单功能实现
1.状态机
/*---------------------------------------------------*/
/*----------------- 宏定义 -------------------*/
/*---------------------------------------------------*/
//ota状态机
uint32_t Bootstaflag = 0;
#define Updata_A_FLAG 0x00000001 //事件1 需要更新 清除A区,从外部flash(w25q128)中拿取数据,存放到A区
#define menu_2_C_FLAG 0x00000002 //XMode 心跳C //菜单2事件
#define menu_2_DATA_FLAG 0x00000004 //DATA
#define menu_3_FLAG 0x00000008 //设置OTA版本号
#define menu_5_FLAG 0x00000010 //向外部flash下载程序
#define menu_5_xmodem 0x00000020 //向外部flash下载程序
#define menu_6_FLAG 0x00000040 //从外部 向 内部flash下载程序
#define menu_8_FLAG 0x00000080 //wifi连接
#define menu_9_FLAG 0x00000100 //服务器
#define menu_11_FLAG 0x00000200 //服务器
#define menu_8_1_FLAG 0x00000400 // 扫描wifi
#define menu_12_FLAG 0x00000800 //服务器
例如:
Bootstaflag |= menu_6_FLAG; //置位标志位
if (Bootstaflag & menu_6_FLAG) //置位标志位
{
//执行相关函数
}
2.设置OTA版本
if (Bootstaflag & menu_3_FLAG)
{
if (uartHandle->RxBuf_size == 26)
{
if (sscanf((char *)uartHandle->usart1_RxBuff1, "VER-%d.%d.%d-%d/%d/%d-%d:%d", &temp, &temp, &temp, &temp, &temp, &temp, &temp, &temp) == 8)
{
memset(OTA_Handle.OTA_ver, 0, 32);
memcpy(OTA_Handle.OTA_ver, uartHandle->usart1_RxBuff1, 26);
boot_w25q128_write();
printf("版本号正确 设置成功");
Bootstaflag &= ~menu_3_FLAG; //清除事件
Bootloader_InFo();
}
else
{
printf("版本格式化错误");
}
}
else
{
printf("版本长度错误");
}
}
6.实验现象
1.擦除A区

可以看到APP存储区域的值已被重置。擦除A区成功。
2.串口IAP下载A区程序


可以看到APP存储区域的值已经下载成功。
3.版本管理

4.外部Flash操作
1.向外部Flash下载程序


2.使用外部Flash中的程序

更多推荐
所有评论(0)