嵌入式固件升级框架详解与实战经验

嵌入式固件升级(Firmware Update)是什么?

固件升级是指在设备不拆解、不更换芯片的前提下,为了修复Bug、增加新功能或提升性能,通过软件方式更新嵌入式系统固件。

对嵌入式产品而言,固件升级机制可以保持产品生命周期期间的生命力。

单片机有三种烧录方式:

  1. ICP(In Circuit Programing)在电路编程;
    使用仿真器(如 J-Link、ST-Link)经 SWD/JTAG 接口进行编程,常用于开发调试阶段或产线烧录。
    特点是可靠、快速,但是依赖仿真器,而正版仿真器的采购成本一般也较高。
  2. ISP(In System Programing)在系统编程;
    芯片出厂前通常会自带一小段ROM Bootloader,可通过 UART/SPI/I²C 等接口与上位机交互,实现系统内烧录。
    进入方式通常需拉高或拉低特定引脚。
    特点是开发者无法修改ROM Bootloader逻辑,灵活性较差,烧录速度也比不上ICP,ISP常用于量产烧录或后期维护。
    在某些调试场景下,比如上电后立即关闭SWD,会导致无法重新烧录,芯片变砖,就需要该种方式作为最后的救命手段。调试建议:初始化中可加 1~2 秒延时,避免出现该极端场景。
  3. IAP(In applicating Programing)在应用编程;
    本文所说的固件升级主要是基于 IAP(In-Application Programming)机制的实现。通过软件在运行时实现 Flash 擦写与编程。
    程序通常分为两部分:
  • Bootloader(引导程序):负责通信、下载、校验与切换;
  • APP(应用程序):正常业务逻辑运行部分。
    要实现 IAP,开发者需先考虑以下条件是否满足:
  • 芯片是否具备通信接口(UART / SPI / I²C / BLE / Wi-Fi)
  • ROM / RAM 空间是否充足
  • ROM 是否支持在线擦写

什么时候需要固件升级功能?

如果产品功能需要频繁迭代更新或远程维护,那么就需要在设计阶段考虑固件升级,同时也要考虑硬件成本、研发成本和测试成本。

固件升级功能的使用者可分为三类:开发人员、维护人员和用户。

如果只是开发调试阶段需要更新软件,可只做仿真器烧录;如果需要长期维护产品,则应预留Bootloader;如果是联网设备,则建议考虑OTA。

常见的升级方式

无论哪种方式,核心流程都是一致的:
跳转 → 握手 → 下载 → 校验 → 切换/回滚

升级流程详解

以终端与PC上位机交互升级为例:

1.跳转机制

进入Bootloader有两种方式,一种是复位,每次复位先执行Bootloader;一种是从APP应用程序使用跳转指令跳转到Bootloader,这种需要设计一定的触发条件,比如通过上位机指令等。

系统启动后首先运行 Bootloader。Bootloader 决定:

  • 是否进入升级模式;
  • 还是直接跳转到 APP。
    判断方法通常有两种:
  • 超时等待:上电后在 1s 内未收到升级信号则跳转 APP;简单但影响开机速度;
  • 升级标志位:上位机设置标志位,Bootloader 检查后进入升级模式。
    推荐做法:标志位 + 校验结合,可提升升级可靠性。

2.握手阶段

升级前,终端需与上位机确认状态和版本信息,例如:

上位机:准备就绪?------------------------------------------------------终端:准备就绪

终端:当前我是v1.0版本,你是什么版本?------------------------上位机:我是v1.2版本

终端:请求升级至1.2版本,固件信息?-----------------------------上位机:固件名、固件大小、校验值

这一过程称为握手(Handshake),主要目的是:

  • 确认通信正常;
  • 校验版本信息;
  • 确定升级包信息。

3.下载阶段

握手完成后开始传输固件数据。

一般为分包下载:

终端:请发送第0包固件数据------------------------上位机:第0包数据

......

终端:请发送第Z包固件数据------------------------上位机:第Z包数据

接收数据,还需要将固件数据写入flash,需要选择升级策略:

模式特点单Bank占用空间少,但失败可能"变砖"双Bank安全可靠,支持回滚,但占用Flash更大

RAM建议:至少预留 2~3 倍单包大小的缓冲区,因为要在 RAM 中缓存接收数据、进行校验和 Flash 对齐写入,若包太大或 RAM 太小会影响速度与可靠性。

若下载过程同时保存当前包序号到flash,那么当系统掉电或通信中断,可通过该包序号实现断点续传;同时,在 Bootloader 启动阶段检测该标志,可自动恢复下载流程或清除异常状态,提高升级效率。

4.校验阶段

固件接收完成后进行完整性校验。

常用校验方法有CRC或者SHA校验,对于 MCU 通信型升级(UART、SPI等),CRC足够;对于 OTA 或安全性较高场景,建议 SHA + 签名机制。。

调试建议:写入完毕后从Flash回读再校验,避免边写边算导致误差。

5.切换与回滚

校验成功后,Bootloader将更新固件有效标志位,并在下次重启时跳转到新APP。

启动失败(如CRC错误或启动异常)时,若支持回滚机制(Rollback)则自动回退到上个版本,否则就滞留在Bootloader,等待下一次升级开始:

关于Bootloader和APP之间相互跳转,有几个注意事项:

跳转时应先关闭中断、重设堆栈指针(MSP)、并跳转至 APP 的 Reset_Handler,否则可能导致启动异常。

c 复制代码
typedef void (*pFunction)(void);
pFunction JumpToApplication;
uint32_t JumpAddress;

void IAP_JumpToApplication(void)
{
    __disable_irq();                                  //关闭中断
    JumpAddress = *(__IO uint32_t*) (APP_ADDRESS + 4);//获取Reset_Handler指针
    JumpToApplication = (pFunction) JumpAddress;
    __set_MSP(*(__IO uint32_t*) APP_ADDRESS);         //从设堆栈指针
    JumpToApplication();                              //跳转
}

在Bootloader中会用到某些外设,如看门狗、UART、定时器等,跳转到APP后,这些外设可能还会继续工作,进而影响产品功耗或者外设配置冲突,建议在跳转前可增加反初始化。

安全性设计要求

在OTA场景,固件升级必须考虑安全问题:

  • 签名验证,要确保固件来源可信
  • 加密传输,避免固件在空中被截获
  • 版本防降级,防止回刷旧固件,利用旧固件版本漏洞攻击
  • 校验完整性,防止传输过程损坏、错漏

扩展

嵌入式产品由于资源限制和应用场景不同,有时候不会固定Bootloader+APP、单双Bank这些选择。会有许多变种设计,咱们在此适当展开说说。

1.单Bank+差分升级

上位机不直接发送整包固件,而是发送旧版本与新版本的差异数据,设备端根据当前固件内容和补丁生成新固件。

该方案的Flash 占用居于单bank和双bank之间,带宽和功耗最低,升级速度最快,但实现复杂度也是最高的。

优点:

  • Flash 占用居于单Bank和双Bank之间(多出一块Patch区);
  • 带宽占用最低,适合 BLE / LoRa / NB-IoT 等低速物联网设备;
  • 升级速度快、功耗低;
    缺点:
  • 实现复杂度高,需保证差分算法与旧固件一致;
  • 无法像双Bank支持回滚;
  • 如果掉电或Patch损坏仍有变砖风险。

2.双bootloader

前面我们使用bootloader给APP升级,那要是bootloader也需要升级呢?

在一些高可靠性或多阶段升级场景中,会使用两个 Bootloader:主Bootloader 和 子Bootloader。

正常情况下,主Bootloader 负责设备启动与APP升级,当主Bootloader需要升级或者被破坏时,子Bootloader进行接管。

优点:

  • 解决"Bootloader自身无法自升级"的问题;
  • 增加了安全性,避免主Bootloader损坏后系统无法启动问题;
    缺点:
  • 增加Flash占用(双Bootloader本身需要空间);
  • 启动流程、跳转流程更加复杂,调试门槛高;

3.RAM运行bootloader

这种方式同样也可以解决bootloader的问题。

把Bootloader 加载到 RAM 中运行,从而可以自由擦写整个 Flash(包括自身所在区域)。

优点:

  • 允许完全自由地重写Flash布局(包括Bootloader区);
  • Flash利用率高,可实现Bootloader自升级而不需双Bootloader设计,适合Flash紧张的系统;
    缺点:
  • RAM 需足够大以容纳Bootloader;
  • 一旦RAM运行异常(如掉电),可能导致系统不可启动,比前面提及的变砖更加严重;

总结

嵌入式固件升级是一个看似简单,但实现难度较大的功能,对可靠性、安全性、成本控制、性能、系统架构设计都有着严格的要求。

相关推荐
明月清了个风2 个月前
工作笔记-----IAP的相关内容
arm开发·笔记·iap·嵌入式软件·程序升级
记录无知岁月8 个月前
【STM32】BootLoader和IAP详解
stm32·嵌入式硬件·iap·bootloader·中断向量
ShiinaKaze10 个月前
【MCU】微控制器的编程技术:ISP 与 IAP
单片机·嵌入式硬件·mcu·iap·isp
小白橘颂1 年前
STM32第二十四课:IAP离线系统升级
c语言·stm32·嵌入式硬件·iap·系统离线升级
ERIC-ZI1 年前
IAP程序升级 与 电脑BIOS 的关系
电脑·iap·flash·bios·程序升级·固件
MAR-Sky1 年前
CH552G使用IAP下载
c语言·开发语言·iap·isp
stark1898y1 年前
CH32V 系列 MCU IAP 使用函数形式通过传参形式灵活指定APP跳转地址
单片机·嵌入式硬件·mcu·iap·risc-v·ota
二十四画生9202 年前
单片机烧录方式 -- IAP、ISP和ICP
单片机·iap·bootloader
Rleco_2 年前
【嵌入式开发学习】__扒一扒单片机串口IAP原理
stm32·单片机·嵌入式硬件·物联网·串口·iap·版本升级