ota的时候在app写flash和在bootload写flash有什么区别?
App 写 Flash
典型流程:
App 正常运行
→ 下载固件
→ 写入备用分区
→ 重启
→ Bootloader 验证并切换
优点:
可以继续使用网络、USB、UI 等完整功能。
Bootloader 可以做得很小。
如果有真正的双 Bank 或外部 Flash,下载体验较好。
可以边下载边写备用区。
风险:
App 正在 Flash 中运行,擦写同一 Flash Bank 可能让 CPU 暂停。
中断函数也通常位于 Flash,擦除时可能无法执行。
必须把关键擦写代码搬到 RAM。
App 如果已经损坏,OTA 功能也可能无法工作。
App 权限更大,漏洞可能被利用来改写可执行分区。
写当前正在运行的 App0 基本不可行,必须使用备用区。
看门狗、USB中断和掉电恢复更复杂。
Bootloader 写 Flash
流程:
App 请求进入升级模式
→ 重启到独立 Bootloader
→ Bootloader 接收并写入固件
→ 验证签名
→ 启动新 App
优点:
Bootloader 不运行在被擦写的 App 分区中。
App 即使损坏也能进入恢复模式。
写 Flash、验签、回滚逻辑集中在较小代码中。
攻击面更小,App 不需要拥有改写可执行分区的能力。
掉电恢复和 A/B 回滚更容易证明正确。
不受 App 中复杂任务和中断干扰。
缺点:
Bootloader 必须包含 USB、传输、Flash、Hash 和签名代码。
升级期间普通 App 功能不可用。
Bootloader 自己升级更困难,必须保持稳定。
用户界面和诊断能力通常不如 App 丰富。
推荐的 Flash 布局是:
Bootloader:独立区域
App0:当前执行/新固件分区
App1:旧固件备份分区
这个布局对应的升级过程:
- App0 → App1,先备份旧固件
- 擦除 App0
- Bootloader 把新固件写入 App0
- 验证 CRC、SHA-256、Ed25519
- 试启动
- 失败则 App1 → App0 回滚
如果让 App0 自己擦写 App0,相当于运行中的程序删除自己,非常危险。即使擦写 App1,仍要处理同一 Flash Bank 擦除暂停、RAM 执行、中断和后续分区切换问题。
哪种方式最好
取决于硬件:
单 Bank MCU、工业控制、安全要求高
推荐:
App 只发起升级
Bootloader 接收、写入、验签和回滚
这是当前项目更合适的方案。
真正双 Bank 或具有外部 Flash
推荐混合方案:
App 下载并写入非活动 Bank/外部 Flash
Bootloader 验签、切换和回滚
这样兼顾下载体验与启动安全。
不推荐
App 直接覆盖正在运行的自身分区
除非有完整 RAM Updater、严格中断控制和额外恢复机制,否则掉电或异常很容易变砖。
结论:当前由 Bootloader 写 Flash 更安全。App 负责选择文件、验证、关停业务并请求升级;Bootloader 负责真正修改可执行 Flash、验签和回滚,这是更合理的职责分离。
为什么双 Bank 或具有外部 Flash推荐混合方案?双 Bank 的好处是什么?
双 Bank 的核心价值是:CPU 可以继续从 Bank A 运行,同时擦除或写入 Bank B。
单 Bank 的问题
单 Bank 中,即使划分了 App0、App1,它们仍共享同一个 Flash 读写硬件:
同一个 Flash Bank
├── App0
└── App1
当 App 从 App0 运行,同时擦除 App1 时:
Flash 可能暂时不能读取。
CPU 取指可能停顿。
位于 Flash 的中断函数无法及时执行。
USB、看门狗和实时控制可能受影响。
关键擦写代码可能需要搬到 RAM。
“两个分区”不等于“真正的双 Bank”。
真正双 Bank
Bank A:正在运行的旧固件
Bank B:正在下载的新固件
两个 Bank 具有相对独立的读写路径,因此通常支持 Read-While-Write:
CPU 从 Bank A 读取并运行
同时擦除、写入 Bank B
这样 App 可以利用现有的 USB、网络、文件系统和 UI 下载固件,而不需要让 Bootloader 承担复杂传输功能。
推荐的混合方案
App 负责下载
- App 正常运行在 Bank A
- 下载新固件到 Bank B
- 分块校验并支持断点续传
- 验证完整 SHA-256 和签名
- 写入“候选固件准备完成”标志
- 重启
Bootloader 负责启动安全 - 再次验证 Bank B 的签名
- 原子切换到 Bank B
- 标记为试运行
- 新固件确认健康
- 失败则切回 Bank A
职责关系:
App:复杂但不掌握最终启动决定
Bootloader:简单,只负责验签、切换、确认和回滚
双 Bank 的具体好处
- 当前固件始终保留
下载和写入失败时,Bank A 完全没有被修改:
Bank A:有效旧固件
Bank B:不完整候选固件
断电后直接继续启动 Bank A。
- 升级停机时间短
文件可以在 App 正常运行时下载。重启后 Bootloader 只需要:
验证 → 切换 → 启动
不需要在 Bootloader 中等待整个文件传输。
- 容易回滚
新固件试运行失败:
Bank B → 启动失败
Bank A → 仍然保留,直接切回
通常不需要重新复制完整固件。
-
支持断点续传
下载进度可以保存在 Bank B 的元数据中。断线后继续写剩余部分,不必破坏当前运行固件。 -
Bootloader 更小
Bootloader 不必包含完整的网络、USB文件传输、TLS或复杂UI,只保留:
镜像验证
Bank 选择
试启动计数
回滚
最小恢复接口
Bootloader 越小,越容易审计和保证可靠性。
- 可以进行原子切换
某些 MCU 支持 Bank Swap 或地址重映射:
启动前:0x08000000 → Bank A
切换后:0x08000000 → Bank B
只修改少量启动配置或元数据,不需要复制几百 KB 固件。
外部 Flash 为什么也适合混合方案
外部 Flash 可以作为下载暂存区:
App 正常运行
→ 下载完整固件到外部 Flash
→ 校验签名
→ 重启 Bootloader
→ Bootloader 从外部 Flash 写入内部 Flash
优点是 App 不需要边接收边覆盖内部执行区域,而且能够先获得一个完整、已验签的候选镜像。
但外部 Flash 不完全等于双 Bank:
如果 MCU 不能直接从外部 Flash 启动,Bootloader仍要复制到内部 Flash。
复制期间掉电必须支持恢复或重新复制。
只有一个内部 App 分区时,旧固件可能无法继续保留。
外部 Flash 本身也要做完整性和访问保护。
总结:双 Bank 最大的好处不是单纯“有两份空间”,而是旧固件可以继续安全运行,新固件在另一个独立 Bank 中完整写入,最后由 Bootloader做一次很小的原子切换。

浙公网安备 33010602011771号