3. 生产文件与固件交付物

在 Silicon Labs 器件的量产环节,烧录工位真正“吃进去”的不是源代码,也不是 .out 调试文件,而是一组经过格式转换、地址裁剪、版本标识和校验确认的生产文件。理解这些文件的内部结构,是判断“烧录失败到底是文件问题还是硬件问题”的前提。本节围绕四种最常见的交付格式展开,并给出可直接落地的版本管理与交付包规范。

一、四种格式的本质差异:记录方式与地址表达

HEX、S37、BIN、GBL 的差别,核心只有两点:是否携带地址信息,以及是否携带校验与元数据。

  • BIN(Raw Binary):纯粹的字节流,没有任何地址、长度、校验字段。烧录时必须由工具额外指定起始地址(如 0x00000000 或 Bootloader 应用区偏移)。优点是体积最小、解析最快;缺点是地址信息完全依赖外部约定,一旦偏移填错,固件会被写到错误区域且工具不会报错。
  • HEX(Intel HEX):ASCII 文本,按行组织,每行以 : 开头,包含字节数、16 位地址、记录类型(00 数据 / 01 结束 / 02 扩展段地址 / 04 扩展线性地址 / 05 起始线性地址)和校验和。地址是自描述的,因此可以表达非连续段(如 Flash 主体 + 用户信息区 + 校准页)。
  • S37(Motorola S-Record):同样是 ASCII 文本,记录以 S0/S1/S2/S3(数据,地址宽度递增)、S7/S8/S9(结束)标识。S3 支持 32 位地址,在 EFR32 这类大地址空间器件上比 S1/S2 更常用。与 HEX 相比,S37 的地址字段更直观,但工具链支持度略低。
  • GBL(Gecko Bootloader File):Silicon Labs 自有格式,本质是带 GBL 头 + 应用信息区(App Info)+ 加密/签名封装的容器。它面向 OTA 与 Bootloader 升级场景,头部包含版本、类型(Application / Bootloader / 加密密钥等)、签名算法标识,因此 GBL 不只是“数据搬运”,还承担了版本识别与安全校验职责。

下面这张图对比了四种格式在“地址自描述、校验能力、版本元数据、典型使用场景”四个维度上的差异,可作为选型时的快速参照。

生产固件格式能力对比 维度 / 格式 BIN HEX S37 GBL 地址自描述 否(需外部指定) 是(扩展线性地址) 是(S3 32位) 是(头部声明) 行/块校验 无 每行校验和 每行校验和 CRC + 签名 版本元数据 无 无(可注释) 无(可注释) 有(App Info) 典型场景 产线快速烧录 调试/多段烧录 第三方烧录器 OTA / Bootloader 选型要点: 产线固定偏移烧录 → BIN 最快;多区域/含校准页 → HEX 或 S37; 需要版本识别与安全升级 → GBL,且必须与 Bootloader 公钥/密钥匹配。

二、从 .out 到生产文件的转换与地址裁剪

以 Simplicity Studio / GCC 工具链为例,编译产物通常是 .out(ELF)。转换为生产文件时,关键动作是按区域裁剪,而不是整片导出。EFR32 典型 Flash 布局中,Bootloader 占 0x00000000 起的一段,应用从 0x00004000 或更高偏移开始,用户信息区(User Data / MFG 区)位于 Flash 末尾附近。

# 生成 HEX(保留地址信息,便于多段烧录)
arm-none-eabi-objcopy -O ihex app.out app.hex

# 生成 BIN(必须指定应用区起始地址)
arm-none-eabi-objcopy -O binary app.out app.bin

# 生成 S37(S3 记录,32 位地址)
arm-none-eabi-objcopy -O srec --srec-forceS3 app.out app.s37

# 生成 GBL(使用 Simplicity Commander,需指定应用信息与签名密钥)
commander gbl create app.gbl --app app.bin --sign key.pem

这里有一个极易踩坑的点:BIN 的起始地址必须与链接脚本中的 FLASH_ORIGIN 一致。若链接脚本把应用放在 0x00004000,而烧录脚本按 0x00000000 写入 BIN,结果是 Bootloader 被应用覆盖,设备上电后无法进入升级流程,且烧录工具会显示“成功”。因此产线脚本中,BIN 的烧录地址应作为参数显式配置,并与版本包中的 flash_map.json 对应。

三、固件版本管理:让每一片板子可追溯

版本管理不是给文件改个名字,而是建立“版本号 → 源码提交 → 构建产物 → 烧录记录”的链路。推荐做法:

  1. 版本号采用 主版本.次版本.修订号+构建号,例如 1.4.2+20240612,构建号可用 Git 短哈希或日期。
  2. 在应用信息区(App Info)或固定 Flash 地址写入版本结构体,包含版本号、构建时间、Git 哈希、硬件兼容型号。GBL 的 App Info 天然支持这一机制,OTA 时 Bootloader 可据此拒绝降级或拒绝不匹配的硬件版本。
  3. 每次发布生成唯一的 manifest.json,记录各文件的 SHA-256,产线烧录后回读校验,比对哈希值。
建议在产线烧录后增加一步“回读比对”:读取 Flash 中应用区前 256 字节与版本结构体,与 manifest 中的哈希和版本号比对。这一步能拦截绝大多数因文件错配导致的批量事故。

四、生产文件包内容与交付规范

一个可直接交付给产线或代工厂的生产包,应包含以下内容,且目录结构固定、命名可解析:

文件/目录作用关键要求
app.hex / app.bin / app.s37应用固件本体三者内容一致,仅格式不同;BIN 需配套地址说明
bootloader.hexBootloader 固件与应用区地址不重叠
app.gblOTA 升级包签名密钥与设备内公钥匹配
mfg_data.hex制造信息区(序列号、校准值)按工位动态生成,不可预先固化
flash_map.json各区域起始地址与长度与链接脚本、烧录脚本三方一致
manifest.json版本号、哈希、构建信息含 SHA-256,供回读校验
README.txt烧录顺序与工具版本注明 Commander / 烧录器固件版本

交付规范上还有三条硬性约定:其一,文件包只读冻结,发布后不得原地修改,任何变更必须升版本号重新出包;其二,禁止交付 .out 或含调试符号的 ELF,避免源码信息与调试接口被滥用;其三,GBL 与 BIN 不可混用同一烧录脚本,GBL 需经 Bootloader 解析,直接按 BIN 方式写入会导致头部被当作代码执行。

常见事故:代工厂收到 HEX 与 BIN 两个文件,误将 BIN 按 0x00000000 烧录,导致 Bootloader 被覆盖。防范措施是在 README 中明确“BIN 仅用于应用区,起始地址 0x00004000”,并在 manifest 中标注每个文件的适用烧录地址。

把格式、地址、版本、校验四件事在交付包里一次性说清楚,产线才能做到“拿到包就能烧、烧完能验证、出问题能追溯”。这也是后续烧录工位脚本设计与测试治具开发的基础输入。