当前位置: 首页 > news >正文

【STM32】基于串口的bootloader

一、简单介绍

Bootloader 是嵌入式设备中负责引导和更新的关键程序。汽车的 ECU 在进行 OTA 升级时,Bootloader 负责下载、校验和写入新固件,确保出现异常时能回退到旧版本保障行车安全;手机系统更新依赖 Bootloader来刷机、验证签名并启动系统内核;电脑中的 BIOS 或 UEFI 同样是一类 Bootloader,用于初始化硬件并加载操作系统。通过统一的下载接口和安全机制,Bootloader 让设备可以远程维护、在线更新并防止恶意篡改,从而在降低生产和维护成本的同时,保证系统在整个生命周期中的稳定与安全。

归根结底,bootloader也是一个工程,和application性质相同

笔者实现的简易bootloader的作用主要有

  • 擦除现存app
  • 接收新的app固件
  • 烧写到flash中
  • 跳转到新app

二、开发思路

笔者是基于STM32F103CBT6开发,和常见的STM32F103C8T6相比,flash变成128kb

STM32单片机的flash启动模式下,启动地址总是0x8000000,这也是自己的bootloader的起始地址

bootloader大小为12616字节,需要12个page多一点点(0.32 page)

因此把判断标志放在page 12的开头,即地址0x08003400

App的起始地址为0x08003800,(page13的开头)

内存分布为

boot检测flag信号为true表明需要升级,擦除App并烧写新的固件;否则就表明不需要升级,直接跳转到App即可

三、实战开发

App工程需要设置起始地址,使用keil的话如下设置

system_stm32f1xx.c文件中设置向量表偏移地址

在App中只运行一个闪烁LED作为演示

boot工程起始地址就是0x8000000,就不需要偏移了

设置地址宏和升级请求标志

#define APP_START_ADDRESS 0x08003800
#define APP_REQUEST_ADDRESS 0x08003400updateReq = *(uint8_t*)(APP_REQUEST_ADDRESS);

判断是否需要升级

if (updateReq == 1 || updateReq == 0xFF)
{state = STATE_INIT;HAL_FLASH_Unlock();HAL_FLASHEx_Erase(&req, &error);
}
else
{state = STATE_JUMP;
}

在主循环内进行状态的切换

笔者制作了一个配套的上位机

上位机按下boot则发送由帧头0xAA+0x22222222+CRC组成的升级请求,App检测到后就设置标志位并复位

上位机按下flash则进行新固件的传输,在boot中进行接收和flash的写入

case STATE_FLASH:
{/*** flash code*/HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, APP_START_ADDRESS + flashPackCnt * 4, *(uint32_t*) (prx + 1));flashPackCnt++;/* flash finish, notify PC by sending 0x77 */tx[0] = 0x77;HAL_UART_Transmit_IT(&huart1, tx, 1);/* go to wait state for getting next data from PC*/HAL_UART_Receive_IT(&huart1, rx, 6);state = STATE_WAIT;if ((flashPackCnt) * 4 == dataSize){state = STATE_END;HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, APP_REQUEST_ADDRESS, 0);}break;
}

上位机发送0x20+四字节的固件包+CRC,单片机接收后发送0x77作为应答信号

烧写完毕后跳转到新的App中

case STATE_JUMP:
{deinitEverything();uint32_t stacktop = *((__IO uint32_t *)APP_START_ADDRESS);__set_MSP(stacktop);app_func_t app_func = (app_func_t)(*((__IO uint32_t *)(APP_START_ADDRESS + 4)));app_func();
}

升级完毕后调试读取内存,0x8003800处的内容和编译的App的hex内容一致

由于升级请求被擦除,下一次复位就直接跳转至App运行了

http://www.dtcms.com/a/395945.html

相关文章:

  • 【STM32】中断
  • how many penguins in ur linux你有几只企鹅呢?
  • windows1122h2怎么升级24h2
  • ansible-playbook的使用
  • Zabbix7 监控USG6300E 并发IPv4会话数
  • Qt中使用多线程的范式
  • c语言10:指针加减指针的那些事儿
  • 数据库成为突破口:勒索软件攻击始于暴露的Oracle服务器
  • PT100铂电阻高精度原理图设计,已量产(温度传感器)
  • 推荐 6 个本周 yyds 的 GitHub 项目。
  • 内存释放机制以及栈和堆(c++)
  • PCL基础:点云体积计算,若需更精确的体积估算,可采用 Alpha Shape 或 Marching Cubes 等方法重建表面后再进行积分计算。
  • OSPF实验-20250922
  • Python控制流概述
  • 【LLM学习】【Ollama】四、MCP
  • 5G RedCap模组:轻量化5G技术的商业化实现
  • 深入探索卷积神经网络:从基础到高级架构(二)
  • 什么是DeepSeek-V3.1-Terminus版本?
  • 【C语言代码】堵车问题
  • A Survey of Zero-Shot Learning: Settings, Methods, and Applications
  • Windows连接Linux做开发的安装和配置
  • 【C++】lambda表达式类型相关问题
  • HTML应用指南:利用GET请求获取全国大疆限飞区域shp图层信息
  • Nginx进阶(二)
  • VSCode+WSL+cpolar:打造跨平台的随身Linux开发舱
  • Redis高可用方案:主从复制、哨兵与集群
  • STM32_03_库函数
  • SGP30气体传感器详解 (STM32)
  • stm32 BootLoader之检查栈顶地址是否合法(否则无法跳转到APP程序)
  • PyTorch 神经网络工具箱学习总结