Flipper Zero Unleashed 固件 OTA 更新机制与更新包构建实战指南
2026/9/13 19:39:01 网站建设 项目流程

Flipper Zero Unleashed 固件 OTA 更新机制与更新包构建实战指南

【免费下载链接】unleashed-firmwareFlipper Zero Unleashed Firmware项目地址: https://gitcode.com/GitHub_Trending/un/unleashed-firmware

本指南以 documentation/OTA.md 为核心,深入剖析 Flipper Zero(Unleashed Firmware)的 OTA(Over-The-Air)固件更新原理:从"从 RAM 执行代码"的特殊引导模式,到备份/int内部存储、烧写主固件与 Core2 无线协议栈、恢复配置的三阶段流程,再到 Update manifest 清单格式、错误码定位与更新包构建命令。读完本文,你将能够理解 OTA 更新的全部内部机制,掌握使用fbtscripts/update.py构建完整版、精简版、自定义无线协议栈版及部分更新包的方法,并学会根据[XX-YY]格式错误码快速定位更新失败原因。

为什么 OTA 需要"从 RAM 执行代码"的引导模式

Flipper 固件中存在一个特殊的引导模式:系统会将一个精心构造的系统镜像加载到 RAM 中,并把控制权移交给它。从 RAM 中执行的系统镜像对 Flipper 整个 Flash 存储拥有完整的写入权限——这是主固件从同一片 Flash 上运行时不可能做到的(代码正在执行的存储介质无法被同时安全改写)。

OTA 固件更新正是利用了这一引导模式,它还同时承担了对运行在第二颗 MCU 核心(Core2)上的无线电协议栈(Radio Stack)执行安装、卸载等操作的任务。这意味着 OTA 不仅要更新主固件,还要维护双核架构下 BLE 协议栈的版本一致性与安装地址正确性,这是 Flipper OTA 区别于普通单片机固件升级的核心特征。

OTA 更新三阶段流程

一次完整的 OTA 更新安装分为 3 个阶段:

阶段 1:备份内部存储(/int)

/int是 Flipper Flash 上的一块专用分区,占据固件代码未使用的全部剩余空间。由于新版本固件的体积可能不同,直接安装新固件会导致 Flash 重新分区,从而造成数据丢失。因此,在动固件之前,系统会先把当前/int中的配置备份成一个普通的 tar 归档文件保存到 SD 卡上。

在源码中,这一阶段由 applications/system/updater/util/update_task_worker_backup.c 实现,对应 update_task.h 中的UpdateTaskStageIntBackup阶段。备份前,更新任务还会检查内部存储的剩余空间:update_operation.c 中定义了UPDATE_MIN_INT_FREE_SPACE (2 * 4 * 1024),要求至少预留 2 个 LFS 页面(共 8KB)的空闲空间,否则更新会被拒绝(UpdatePrepareResultIntFull)。

阶段 2:执行设备更新

主固件将 updater 镜像——一种主固件的定制构建版本——加载到 RAM 并运行。Updater 按照 Update manifest 文件的描述,对系统 Flash 执行一系列操作:

  1. 无线协议栈(Radio Stack)处理:如果更新包捆绑了 Radio Stack 镜像,updater 会先将其版本与当前已安装的版本进行比较。版本不匹配时,updater 先执行协议栈卸载,再写入并安装新协议栈。安装动作本身由运行在 Core2 上的专有软件 FUS(STM32 无线固件升级服务)执行,并会引发一系列系统重启。
  2. Option Bytes 校验与修正:Option Bytes 是存放 Flipper MCU 底层配置的特殊内存区域,updater 会对照 manifest 中的参考值对其进行校验与纠正。
  3. 固件烧写:updater 加载要烧写的.dfu固件文件,先用 CRC32 校验其完整性,写入系统 Flash 后再次校验写入的数据。

阶段 3:恢复内部存储并更新资源

对 Flash 的操作完成后,系统重启进入新固件,并执行先前备份的/int内容恢复。如果更新包还包含额外的资源归档(Resources字段指定的 tar 包),则会将其解压到 SD 卡上。此外,如果 manifest 中带有Splashscreen字段,更新后还会安装更新完成后的开机动画(见 update_task.h 中的UpdateTaskStageSplashscreenInstall等阶段)。

Update manifest:更新包的"内容清单"

更新包自带一份描述其内容的 manifest 清单文件(默认名为update.fuf)。manifest 使用 Flipper File Format——一种由键值对组成的简单文本文件。设备端由 update_manifest.c 负责解析,其中定义了所有字段的键名常量(见该文件 第 7-20 行)。

必填字段(必须按以下顺序出现)

字段说明
Filetype常量字符串,必须为Flipper firmware upgrade configuration。解析时通过 update_manifest.c 第 58-60 行 与flipper_format_read_header读取并严格比较,不匹配则 manifest 无效
Versionmanifest 版本号,当前值为 2。设备端要求manifest_version >= UPDATE_OPERATION_MIN_MANIFEST_VERSION(2),更老的包会被判定为OutdatedManifestVersion(见 update_operation.h)
Info任意字符串,描述包内容,例如版本号r13.3_full
Target包所面向的硬件版本。生成时 update.py 会把-t f7这类参数剥掉首字母f后写入
Loader从 RAM 执行的 Stage 2 loader 的文件名,固定为updater.bin(见 update.py 第 92 行)
Loader CRCLoader 文件的 CRC32,注意以小端十六进制表示。生成逻辑见 update.py 第 180-181 行 的int2ffhex(逐字节倒序排列),设备端用flipper_format_read_hex读回并比较

可选字段

其余字段允许为空值;为空时 updater 跳过与之相关的全部操作。设备端解析这些可选字段的代码见 update_manifest.c 第 73-114 行。

字段说明
RadioSTM 提供的无线协议栈镜像文件名,生成时固定为radio.bin
Radio address协议栈的安装地址,由 STM 在 Release Notes 中给出。不指定时 update.py 第 126-131 行 会从镜像签名中读取默认 Flash 加载地址(get_flash_load_addr())并打印提示要求与 Release_Notes 核对
Radio version协议栈主版本、次版本、子版本,以及分支(branch)、发布(release)、栈类型(stack type),打包成 6 个十六进制字节。打包逻辑见 update.py 的copro_version_as_intmajor \| minor<<8 \| sub<<16 \| branch<<24 \| release<<32 \| stype<<40;设备端用 6 字节联合体UpdateManifestRadioVersion解析(见 update_manifest.h)
Radio CRC协议栈镜像的 CRC32
Resources要解压到 SD 卡的资源 tar 归档文件名,固定为resources.ths(Tar.Heatshrink 压缩格式,见 update.py 第 24-25 行)
OB reference / OB mask / OB write mask用于校验和纠正 Option Bytes 的参考值。生成时 update.py 第 191-200 行 从scripts目录下的 Option Bytes 数据文件(如scripts/ob.datascripts/ob_custradio.data)计算得到;文件注释明确警告:"NEVER EVER MESS WITH THESE VALUES, YOU WILL BRICK YOUR DEVICE"。设备端在 update_manifest.c 第 145-157 行 的update_manifest_has_obdata中对 mask 的一致性(值与其反码相等)以及参考值是否完全落在 compare mask 掩码位内做完整性检查

除上述字段外,源码中还存在Firmware.dfu固件文件名,固定为firmware.dfu)与Splashscreen(更新后开机动画splash.bin)两个键(见 update_manifest.c 第 11、20 行),后者在文档中被列为可选字段。

更新包的预检与"武装"机制

值得补充的是,manifest 并不是在重启后被立刻执行的。在正式重启进入 updater 之前,update_operation.c 的update_operation_prepare会做一整套预检:检查/int空闲空间、确认 manifest 文件存在且有效、核对 manifest 版本与硬件 Target(仅当设备硬件版本号非 0 时比较,预量产设备接受任意固件)、验证 Stage2 loader 存在且 CRC32 匹配,然后将 manifest 路径写入 SD 卡根目录的.fupdate指针文件(UPDATE_MANIFEST_POINTER_FILE_NAME)并设置 RTC 引导模式为FuriHalRtcBootModePreUpdate。重启后update_operation_is_armed(第 221-232 行)据此判断是否存在待执行的更新,失败时可用update_operation_disarm取消。

OTA 更新错误码定位表

OTA 更新流程被设计得尽可能防错:在任何有风险的操作开始前,都会先校验所有相关数据,避免设备停留在"部分更新"或变砖的状态。即使出错,updater 也允许重试失败的操作,并通过错误码报告当前状态。

错误码采用[XX-YY]格式:XX编码失败的操作阶段,YY携带该阶段中出错位置/进度的额外细节。以下为完整错误码表(与 documentation/OTA.md 及 update_task.h 的阶段枚举 一一对应):

阶段描述代码进度说明
加载更新 manifest113Updater 报告硬件版本不匹配
20无法获取已保存的 manifest 路径
30加载 manifest 失败
40不支持的更新包版本
50包与硬件目标不匹配
60缺少 DFU 文件
80缺少无线协议栈固件文件
备份配置20-100文件系统读/写错误
检查无线协议栈固件30-99读取协议栈固件文件错误
100CRC 不匹配
卸载无线协议栈固件40SHCI Delete 命令错误
80等待命令状态出错
写入无线协议栈固件50-100块读/写错误
安装无线协议栈固件610SHCI Install 命令错误
80等待命令状态出错
Core2 忙710无法启动 C2
20切换 C2 到 FUS 模式失败
30FUS 操作出错
50切换 C2 到协议栈模式失败
校验 Option Bytes8yyOption byte 代码
检查 DFU 文件90打开 DFU 文件出错
1-98读取 DFU 文件出错
99-100DFU 文件损坏
写 Flash100-100块读/写错误
校验 Flash110-100块读/写错误
恢复配置120-100文件系统读/写错误
更新资源13-150-100SD 卡读/写错误

阶段编号与源码中UpdateTaskStage枚举的顺序一致:UpdateTaskStageReadManifest(1)、UpdateTaskStageIntBackup(2)、UpdateTaskStageRadioImageValidate(3)、UpdateTaskStageRadioErase(4)、UpdateTaskStageRadioWrite(5)、UpdateTaskStageRadioInstall(6)、UpdateTaskStageRadioBusy(7)、UpdateTaskStageOBValidation(8)、UpdateTaskStageValidateDFUImage(9)、UpdateTaskStageFlashWrite(10)、UpdateTaskStageFlashValidate(11)、UpdateTaskStageIntRestore(12),而资源更新对应UpdateTaskStageResourcesFileCleanupUpdateTaskStageResourcesDirCleanupUpdateTaskStageResourcesFileUnpack(13-15)。

构建更新包

完整包(Full package)

构建包含固件、无线协议栈以及 SD 卡资源的完整更新包:

./fbt COMPACT=1 DEBUG=0 updater_package

COMPACT=1 DEBUG=0用于生成精简、无调试符号的发布固件。

精简包(Minimal package)

仅包含固件的最小更新包:

./fbt COMPACT=1 DEBUG=0 updater_minpackage

自定义更新捆绑包

默认更新包使用 Bluetooth Light 协议栈。如果你的固件版本支持其他协议栈,可以通过向fbt传入协议栈类型和二进制文件名来构建自定义捆绑包:

./fbt updater_package COMPACT=1 DEBUG=0 COPRO_OB_DATA=scripts/ob_custradio.data COPRO_STACK_BIN=stm32wb5x_BLE_Stack_full_fw.bin COPRO_STACK_TYPE=ble_full

注意:

  • COPRO_OB_DATA必须指向scripts目录下一个有效的、与你的协议栈类型匹配的 Option Bytes 参考数据文件。
  • 在某些情况下,还需要在命令行中添加COPRO_DISCLAIMER=...来确认你的操作意图——这对应 update.py 中的免责确认机制:当你捆绑非白名单协议栈类型(白名单为 BLE_FULL / BLE_LIGHT / BLE_BASIC,见 update.py 第 28-33 行)或内存布局可疑时,脚本会要求追加--I-understand-what-I-am-doing=yes(对应COPRO_DISCLAIMER)才会继续,否则会警告"你可能把设备砖化到需要 SWD 编程器才能修复的状态"。

构建部分更新包(Partial update packages)

直接调用scripts/update.py可以灵活定制包内容。例如,构建一个仅安装 BLE FULL 协议栈的包:

scripts/update.py generate \ -t f7 -d r13.3_full -v "BLE FULL 13.3" \ --stage dist/f7/flipper-z-f7-updater-*.bin \ --radio lib/stm32wb_copro/firmware/stm32wb5x_BLE_Stack_full_fw.bin \ --radiotype ble_full

update.py generate支持的关键参数(见 update.py 第 53-88 行):

参数说明
-d/--directory输出目录(必填)
-v/--version包的 Info 描述字符串(必填)
-t/--target硬件目标,如f7(必填)
--stageStage2 loader 文件(必填),即dist/f7/flipper-z-f7-updater-*.bin
--dfu要烧写的固件.dfu文件(可选,与 radio 至少有一个)
-r/--resources要打包为resources.ths的资源目录(可选)
--radio无线协议栈镜像(可选)
--radioaddr协议栈安装地址,十六进制(可选,默认从镜像签名推断)
--radiotype协议栈类型,如ble_full(提供--radio时必填)
--stackversion校验协议栈镜像内部签名版本是否匹配(可选)
--obdataOption Bytes 参考数据文件,用于生成 OB 三字段(可选)
--splash更新完成后播放的开机动画图片(可选)
--I-understand-what-I-am-doing非白名单协议栈/可疑布局的免责确认(可选)

生成过程中 update.py 还会做内存布局检查layout_check):当固件与协议栈地址都已知时,计算固件末尾到协议栈安装地址(FLASH_BASE = 0x8000000FLASH_PAGE_SIZE = 4KB)之间的保留区大小,若固件镜像与 C2 区域重叠或保留区过小则给出警告并要求免责确认;同时若 Stage2 loader 超过UPDATER_SIZE_THRESHOLD = 128KB,会提示旧固件无法加载。资源的打包采用 Tar + Heatshrink 压缩(窗口 13 / 前瞻 6,见 update.py 第 43-44 行),并限制单个资源文件名长度不超过 100 字符。

关于update.py generate的全部参数,可随时运行以下命令查看帮助:

scripts/update.py generate -h

小结

Flipper Zero 的 OTA 更新是一条完整的"备份 → 预检武装 → RAM 引导执行 → 协议栈/OB/固件处理 → 恢复配置"流水线:/int备份与恢复保证了跨版本重分区的数据安全;从 RAM 执行 updater 镜像赋予了对整片 Flash 的写权限;Update manifest 以 Flipper File Format 承载 loader、固件、协议栈、资源与 Option Bytes 的元数据,并支持字段级裁剪;[XX-YY]错误码与UpdateTaskStage枚举一一对应,让失败定位精确到阶段与进度。无论是发布固件还是为特殊无线协议栈定制包,fbt与 scripts/update.py 都提供了从完整包到部分包的完整构建能力。更多细节可继续阅读 documentation/OTA.md 及相关源码。

【免费下载链接】unleashed-firmwareFlipper Zero Unleashed Firmware项目地址: https://gitcode.com/GitHub_Trending/un/unleashed-firmware

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询