找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

1913

积分

0

好友

255

主题
发表于 15 小时前 | 查看: 1| 回复: 0

对于车载控制器这类已经下线并完成封装的产品,无论是在供应商还是客户手中进行测试,通常只能通过控制器内置的客户引导程序来刷新应用程序。如果需要更新引导程序本身,就必须借助一些特殊方法。

规范与背景

整车厂的规范通常只涉及应用程序的刷新,而没有针对引导程序自更新的规范。这是因为规范面向量产车,售后环节只负责应用程序的升级,不涉及(也不允许)对引导程序的升级。

因此,引导程序的自更新只存在于项目开发阶段,并由供应商自行设计方案。本文将详细分析五种引导程序自更新方式的原理、优势与不足。

方式一:依赖二级启动程序更新

在某些软件架构中,存在两级引导程序:启动引导程序 和客户引导程序。其中, 仅负责检查CPU最小系统,与具体项目的外围电路无关。它独立于客户需求,由供应商自行维护。

程序启动顺序是: -> -> 应用程序。因此,可以在 中增加刷新逻辑来更新 。通常情况下, 运行以更新应用程序;在特殊情况下,程序启动后可以一直停留在 中,执行对 的更新。

优点:

  1. 逻辑结构简单清晰,软件分工明确。
  2. 一次性刷新完成,操作简便。

缺点:

  1. 需要在 中占用较大的Flash空间来存放刷新逻辑。项目量产后又要禁止此功能,造成资源浪费。
  2. 软件分为三级启动,结构复杂,开发和维护成本较高。对于不需要 的控制器是一种负担。
  3. 如果 自身也需要更新怎么办?按照此策略,难道还需要做一个 ?显然不现实。

两级Boot(SB+CB)架构下的自更新流程

方式二:借助RAM运行重启程序进行更新

在没有 的情况下,程序启动顺序是 -> 应用程序。当需要刷新 时:

  1. 首先将一个“重启”程序下载到闲置的RAM中。
  2. 然后在RAM环境中运行该“重启”程序。
  3. “重启”程序负责下载并更新 到Flash中。

优点:

  1. 不需要额外的Flash空间。“重启”程序运行仅需少量RAM,应用程序设计时预留的RAM空间可临时用来保存该程序。
  2. RAM擦写速度极快,因此下载“重启”程序的过程会非常迅速。

缺点:
在 更新过程中,如果CPU意外掉电,重新上电后RAM中的“重启”程序内容将全部丢失,而 区域可能已被部分擦写而损坏。这将导致程序无法正常启动,控制器“变砖”,只能开盖使用JTAG等工具重新烧写程序,涉及复杂的网络通信协议与调试流程。

通过RAM ReBoot更新CB流程图

方式三:RAM加载完整更新包(方式二的改进)

此方式是对方式二的改进:

  1. 将“重启”程序和新的 作为一个完整更新包,一同下载到RAM中。
  2. 运行RAM中的“重启”程序。
  3. 该程序擦除Flash中的旧 区域,并将RAM中完整的新 复制到Flash中。
  4. 最后,执行重新上电复位,RAM中的内容自动丢失,程序从新的 开始运行。

优点:

  1. 相比方式二,减少了一次与上位机的通信和下载步骤(因为“重启”程序和新CB已绑定在一起)。
  2. 相比方式二, 的更新完全在CPU内部执行,不受外部通信干扰,耗时更短,可靠性更高。

缺点:

  1. 相比方式二,需要更大的RAM空间来存储“重启”程序+新 。
  2. 与方式二相同,在 更新阶段掉电后,控制器仍有“变砖”风险。

RAM加载完整更新包流程图

方式四:借助应用程序的Flash空间

此方式的核心是利用应用程序占用的Flash空间作为临时操作区,更新过程分为三步:

  1. 运行旧的 ,擦除原应用程序区域,将“重启”程序下载到该区域。
  2. 运行“重启”程序,擦除旧的 ,刷入新的 。
  3. 运行新的 ,将原应用程序刷回其所属区域。

优点:

  1. 不需要额外的Flash或RAM资源,完全利用现有空间。
  2. 稳定可靠。通过优化设计(见后文附录),可以保证在任何步骤突然掉电后,重新上电仍能继续操作,控制器不会“刷死”。
  3. 对 稍加改造即可成为“重启”程序,开发速度快。

缺点:

  1. 步骤繁多。为更新 ,必须先擦除应用程序,最后还要恢复应用程序,至少涉及三次完整的刷新操作。对不熟悉流程的操作者容易造成混乱。
  2. 整体刷新时间较长,因为需要完成两次 和一次应用程序的烧写。

借助App Flash空间进行Boot自更新流程图

方式五:借助额外的独立Flash空间

相比方式四,此方式需要一块与 大小相当的额外独立Flash块(Block),更新分三步:

  1. 运行旧的 ,将“重启”程序刷入额外Flash块。
  2. 运行“重启”程序,更新Flash中的 。
  3. 运行新的 ,破坏/擦除额外Flash块中的“重启”程序(例如擦除其有效性标志)。

优点: 相比方式四,无需破坏和恢复应用程序,省去了这部分操作时间。
缺点: 相比方式四,需要额外的独立Flash空间,对硬件资源有要求。

借助额外Flash空间进行Boot自更新流程图

方案选择小结

从本质上,上述五种方法可归纳为三种思路:

  1. 依赖启动程序:当CPU的Flash资源非常充裕,且项目本身就需要两级 架构时,采用方式一最节省开发与操作时间。
  2. 借助RAM:在仅需单级 ,且可以接受因 刷新失败导致控制器“变砖”并需要开盖维修所带来的时间、人力、物料成本损耗时,方式二或方式三较为方便快捷。
  3. 借助Flash:在仅需单级 ,且不允许或不方便对控制器进行开盖操作,但可以接受更新步骤较多、耗时较长的情况下,方式四或方式五最为稳定可靠。

综上,工程师需要根据产品的整体软件架构、CPU资源情况、以及时间、人力、物料等成本因素,综合考虑选择一种最适合自身项目和产品的自更新方法。


附录:方式四防“变砖”机制的具体实现

方式四“不会刷死”的结论是有前提条件的,即控制器中至少有一个可用的引导程序(即使是部分损坏的)。这里引出一个核心问题:CPU如何判断哪个引导程序是好的,哪个是坏的?

背景:两级启动地址

许多支持Bootloader的单片机(如一些汽车级MCU)设计有两个或更多的启动地址。上电后,CPU按预定顺序检查这些启动地址对应扇区的有效性。如果BOOT_ID等标志合法,则从该地址开始执行;否则检查下一个启动地址。

典型的Boot扇区结构

考虑CPU具备两个启动地址的情况:

  • 场景A:仅启动地址1有效(应用程序区域为空),程序启动后自动进入 。
  • 场景B:仅启动地址2有效(例如用于不带 的测试),程序启动后自动进入应用程序。
  • 场景C:启动地址1和2均有效。程序优先从地址1启动,在 中检查应用程序有效后,通过跳转指令跳转到地址2,运行应用程序。

两级启动地址的三种有效状态

风险分析与对策

在方式四的步骤2(运行“重启”程序更新 )中,如果在擦除旧 后、写入新 完成前发生掉电,重新上电后,启动地址1的内容可能是一个不完整的 。CPU可能会尝试从这个损坏的 启动并运行出错,而不会跳转到启动地址2运行“重启”程序,从而导致无法继续更新的“变砖”状态。

更新过程中掉电导致变砖的风险场景

对策一:Boot有效性标志与启动地址重合
充分利用Flash的擦写特性(通常按块擦除,按字/字节写入)。调整 的刷新顺序:擦除成功后,先写入 的主体代码部分,最后一步才刷新启动地址1的有效性标志

这样,即使在更新主体代码过程中掉电,由于启动地址1的标志无效,CPU上电后会根据启动顺序,自动从有效的启动地址2(即“重启”程序)启动,从而可以继续完成 的刷新操作。当启动地址1的标志最终被成功写入后,下次上电CPU就会从新的 启动。

对策二:独立的Boot有效性标志与检查逻辑
将 分为两个段(Section)。第一个段 仅存放极少的启动自检逻辑。该逻辑会检查放置在 段末尾的一个独立有效性标志。

  • 如果该标志无效,则判定 不完整,程序控制跳转到启动地址2运行“重启”程序,继续更新。
  • 如果该标志有效,则判定 完整,程序跳转到 段继续执行。由于此时应用程序(即“重启”程序)的有效性标志是无效的,程序不会错误跳转,接下来便可安全地刷入新的应用程序。

此方法通过将风险集中在刷新很小的 段期间,大大降低了“变砖”概率。但在量产软件中,需要关闭“无效则跳转”的逻辑。

通过独立的有效性标志与检查逻辑防变砖

小结: 对策一简单可靠,经过实际项目验证,能有效满足稳定刷新控制器 的需求。

关于固件升级和设备管理的更多深入探讨,欢迎访问云栈社区与其他开发者交流。




上一篇:Linux I/O高效数据交互详解:从系统调用到零拷贝
下一篇:高效管理嵌入式技术团队的9个核心方法论
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-3-1 20:23 , Processed in 0.500048 second(s), 42 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表