C++如何编写固件的分区Bootloader程序

夜静姑娘_9874

夜静姑娘_9874

2026-10-22

861人浏览

原创

bootloader需硬编码flash分区地址与校验逻辑,链接脚本中用memory明确划分区域,跳转前须重映射vtor、初始化msp并关中断,校验应覆盖完整镜像且参数可配置,升级需分包处理与超时恢复。

c++如何编写固件的分区bootloader程序

Bootloader必须自己管理Flash分区,不能依赖操作系统

裸机环境下没有文件系统或分区表概念,Bootloader 需硬编码每个固件段的起始地址、大小和校验方式。常见错误是照搬Linux下的/dev/mtd0思维,结果烧写后跳转失败——因为MCU根本不知道“分区”是什么,只认绝对地址。

实操建议:

C++14
C++14

C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。

下载
  • 在链接脚本(bootloader.ld)中用MEMORY明确划分区域,例如:
    MEMORY
    {
      bootloader (rx) : ORIGIN = 0x08000000, LENGTH = 32K
      app1       (rx) : ORIGIN = 0x08008000, LENGTH = 128K
      app2       (rx) : ORIGIN = 0x08028000, LENGTH = 128K
    }
  • 所有跳转目标地址必须与app1入口点(通常是复位向量偏移0x00处的__vector_table)严格对齐,检查app1的VECT_TAB_OFFSET是否设为0x8000
  • 避免用memcpy直接拷贝整个bin到Flash;先擦除目标扇区(注意最小擦除单位,如STM32是1KB/2KB/16KB),再按页(通常256B)编程

校验逻辑必须覆盖整个应用镜像,且位置可配置

很多Bootloader只校验前几个字节(比如CRC32头),但实际出问题常在中间段——比如OTA升级时Flash写入中断导致某一页失败,而头部仍完好,Bootloader误判为有效固件。

实操建议:

  • 校验范围应从应用入口向量开始,到镜像末尾(不含填充),长度由app1.bin实际大小决定,不是固定值
  • 把校验参数(算法、起始偏移、长度)存进Bootloader预留的配置区(如最后1KB Flash),而非硬编码在代码里,方便后续升级策略调整
  • 推荐用CRC32而非MD5:无依赖、计算快、适合资源受限场景;但注意初始化值(常用0xFFFFFFFF)和最终异或值(常再异或0xFFFFFFFF)需与生成工具一致

跳转前必须重映射中断向量表并关闭全局中断

直接typedef void (*func_ptr)(void)强转地址调用,大概率触发HardFault——因为新固件的中断向量表还在旧位置(0x08000000),而它期望在自己的基址(如0x08008000)。

实操建议:

  • 跳转前执行:
    SCB->VTOR = APP_BASE_ADDR; // 如0x08008000
    __set_MSP(*((uint32_t*)APP_BASE_ADDR)); // 初始化主栈指针
    __disable_irq();
  • 确保APP_BASE_ADDR与链接脚本中app1的ORIGIN完全一致,差一字节都会导致向量表错位
  • 不要在跳转前调用任何C库函数(如printf),它们可能依赖未初始化的运行时环境

串口/USB升级需处理分包边界和超时恢复

真实场景下,UART波特率低、线缆长、干扰大,read()返回的字节数往往小于请求长度,且可能卡死。直接循环read(1)效率低还易丢帧。

实操建议:

  • 定义固定包头(如0x55AA)、包长字段、校验字节;接收端严格按此解析,不依赖单次HAL_UART_Receive返回值
  • 每收到一个完整包,立即擦除对应Flash扇区并写入,而非攒满整个镜像再操作——断电时只丢失最后几KB,而非整包
  • 加入超时机制:连续2秒无新数据则进入空闲状态,等待命令(如'U'启动升级);避免因上位机异常导致Bootloader卡死
C++在这里只是提供类封装和RAII(比如Flash操作类自动擦除/写入/校验),但核心逻辑仍是C风格裸寄存器操作;真正容易被忽略的是向量表重映射时机和分包校验的粒度——这两处出问题,现象都是“能烧进去,但跑不起来”,查起来特别耗时间。

C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!

相关专题

更多
c++和c语言的区别有哪些
c++和c语言的区别有哪些

c++和c语言的区别:1、面向对象编程(OOP)支持不同;2、新增特性不同;3、标准库不同;4、编译方式不同;5、命名空间不同等等。想了解更多c++的相关内容,可以阅读本专题下面的文章。

2024.03.14

2248

9

c++和python学习顺序推荐
c++和python学习顺序推荐

一般建议先学习C++,再学习Python,因为这样可以逐步从较为底层的编程语言向更高级的语言过渡。想了解更多python的相关内容,可以阅读本专题下面的文章。

2024.03.14

1019

6

python和c++学习性价比分析
python和c++学习性价比分析

Python易于学习,广泛应用于Web开发、数据科学和人工智能等领域,但性能较低。C语言性能高,适用于对性能要求较高的场景,如游戏开发和系统编程,但学习曲线陡峭,错误处理复杂。想了解更多python的相关内容,可以阅读本专题下面的文章。

2024.03.14

447

5

c语言和c++一样吗
c语言和c++一样吗

c语言和c++是两种不同的编程语言,虽然有相似之处,但存在显著差异。c语言专注于过程式编程和系统级开发,以简洁、高效著称。c++作为c语言的超集,引入了面向对象编程,增强了代码组织和管理能力,但学习曲线也更陡峭。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.03.14

327

5

c语言和c++先学哪个好
c语言和c++先学哪个好

初学者选择学习c语言还是c++语言,需要根据个人学习目标、背景以及编程兴趣和预期应用方向来决定。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.03.14

406

5

c语言和c++的区别和联系
c语言和c++的区别和联系

c语言和c++是计算机科学领域应用广泛的编程语言。虽然它们有着相似的基础,但它们在语言类型、语法功能和内存管理方面存在着显著差异。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.03.14

580

5

c++软件中文更改教程
c++软件中文更改教程

对于 ide,可通过打开设置,找到语言设置,选择中文,并保存更改。对于非 ide 应用程序,可查找设置或选项,选择语言设置,更改为中文,并保存更改。想了解更多c++的相关内容,可以阅读本专题下面的文章。

2024.03.21

1409

9

python和java和c++学习性价比分析
python和java和c++学习性价比分析

Python以其易学性、丰富的库和活跃的社区而著称,适合数据科学、人工智能和Web开发。Java以其跨平台性、企业级应用开发和Android应用开发而闻名。C++以其底层控制能力、高效性能和游戏开发而著称。选择哪种语言取决于个人兴趣、职业方向和特定需求。想了解更多python和java和c++的相关内容,可以阅读本专题下面的文章。

2024.03.22

1217

7

c++和c语言学习顺序推荐
c++和c语言学习顺序推荐

对于初学者,建议先学习C语言,掌握编程基础后再转入C++,便于理解面向对象编程概念。有编程经验者可直接学习C++,快速接触高级编程技术。想了解更多c++和c语言的相关内容,可以阅读本专题下面的文章。

2024.03.25

1325

9

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C++ Core Guidelines
C++ Core Guidelines

共0课时 | 0人学习

C++ Reference
C++ Reference

共0课时 | 0人学习

C++ 官方标准说明
C++ 官方标准说明

共0课时 | 0人学习