3. 生产烧录文件体系

在 nRF 系列芯片的量产烧录中,工程师最先接触到的往往不是烧录器,而是一堆后缀不同的文件:.hex、.bin、.elf、.s19、.srec。它们看起来都“装着固件”,但用途、信息量和烧录方式完全不同。如果混淆了这些格式,轻则烧录失败,重则把 SoftDevice 覆盖掉、把 Bootloader 写错地址,导致整批板子无法启动。本节从文件格式的本质出发,讲清楚每种格式的适用场景,再落到 nRF 生产烧录中最关键的一步:SoftDevice、Bootloader、Application、UICR 的合并与地址规划。

一、四种文件格式的本质区别

ELF(Executable and Linkable Format)是编译链接后的完整产物,包含代码、数据、符号表、调试信息、段(Section)布局等。它信息最全,但体积大、含调试信息,烧录器一般不直接烧 ELF,而是用它做调试、符号解析和生成其他格式。在 nRF Connect SDK / nRF5 SDK 中,build/zephyr/zephyr.elf 或 _build/nrf52840_xxaa.elf 就是链接结果,是后续所有格式的“源头”。

Bin(Binary)是纯二进制镜像,只包含连续的机器码字节,没有地址信息、没有校验、没有段描述。烧录时必须由烧录器或命令行显式指定起始地址,例如 nrfjprog --program app.bin --sectorerase 需要配合 --verify 和地址参数。Bin 的优点是紧凑、通用,缺点是“不知道自己该放在哪里”,一旦地址给错就会写错区域。

Intel HEX(.hex)是带地址的文本格式,每行以冒号开头,包含数据长度、地址、记录类型、数据和校验和。它支持不连续地址段,因此可以把多个段(如 SoftDevice 区、Application 区)放在同一个文件里。nRF5 SDK 默认输出的 nrf52840_xxaa.hex 就是 Intel HEX,nrfjprog 可直接烧录。

Motorola S-record(.s19/.srec)同样是带地址的文本格式,以 S0/S1/S2/S3 记录数据、S7/S8/S9 记录入口地址。它在汽车电子和部分产线工具中常见,nRF 工具链也支持,但 Nordic 生态中更常用 Intel HEX。两者核心差异在于记录头字符和地址宽度表达方式,功能上都能表达“地址+数据+校验”。

一句话记忆:ELF 是“带地图和注释的完整图纸”,Hex/S-record 是“带门牌号的快递单”,Bin 是“没有门牌号的裸包裹”。量产烧录优先用带地址的 Hex,需要指定地址或做差分升级时才用 Bin。

二、nRF 生产烧录的地址规划

nRF52/nRF53 系列 Flash 从 0x0000_0000 开始,SoftDevice、Bootloader、Application、UICR 各有固定或约定的地址区间。以 nRF52840(1 MB Flash)为例,典型布局如下:

区域典型起始地址大小示例说明
SoftDevice(S140)0x0000_0000约 0x26000协议栈,必须最先烧录,占用最低地址
Bootloader0x0002_6000约 0x2A000DFU 引导,紧接 SoftDevice 之后
Application0x0005_0000剩余空间用户应用,起始地址由链接脚本决定
Bootloader 设置/DFU 参数0x000F_F000 附近0x1000存放 DFU 状态、CRC、版本
UICR0x1000_10000x1000用户信息配置区,含 Bootloader 地址、寄存器配置

这些地址不是随意填的,而是由链接脚本(.ld 文件)和 SoftDevice 的 memory map 共同决定。例如 nRF5 SDK 中 ble_app_uart 的链接脚本会把 Application 起始地址设为 0x00026000 + Bootloader 大小,而 Bootloader 的起始地址又由 SoftDevice 的 sd_mbr_command 和 UICR 中的 NRF_UICR->NRFFW[0] 记录。生产烧录时,必须保证三个区域的地址不重叠、不越界。

三、合并文件:把多个 Hex 拼成一个

量产时最怕逐个烧录 SoftDevice、Bootloader、Application,既慢又容易漏。标准做法是用 mergehex 工具把多个 Intel HEX 合并成一个带完整地址信息的文件。例如:

mergehex -m s140_nrf52_7.3.0_softdevice.hex bootloader.hex application.hex -o production_full.hex

合并后的 production_full.hex 内部包含三段不连续地址的数据,烧录器按地址自动写入,不会互相覆盖。如果还需要写入 UICR(例如设置 NRF_UICR->PSELRESET 或 Bootloader 地址),可以再合并一个 uicr_settings.hex:

mergehex -m production_full.hex uicr_settings.hex -o production_final.hex

合并时要注意:地址重叠会报错。如果 Application 的起始地址低于 Bootloader 结束地址,mergehex 会提示冲突。此时应回到链接脚本检查 FLASH 起始地址和 RAM 设置,而不是强行合并。

常见坑:SoftDevice 必须烧录在最低地址,且不能被 Application 覆盖;Bootloader 的起始地址必须与 UICR 中记录的地址一致,否则 DFU 无法跳转;UICR 一旦写入,部分字段需要整片擦除才能修改,量产前务必确认配置值。

四、从 ELF 到量产 Hex 的完整链路

理解文件体系后,实际生产链路就清晰了:编译生成 ELF → 链接脚本确定各段地址 → 生成 Intel HEX → 用 mergehex 合并 SoftDevice/Bootloader/Application/UICR → 得到单一量产 Hex → 烧录器批量烧录 → 校验。下面这张图展示了各格式之间的转换关系与地址规划的核心约束。

nRF 生产烧录文件体系与地址规划 ELF 代码+符号+调试+段布局 Intel HEX (.hex) 地址+数据+校验,可分段 Motorola S-record S1/S2/S3 + S7/S8/S9 Bin (.bin) 纯二进制,无地址信息 objcopy 直接生成 objcopy -O srec objcopy -O binary mergehex 合并 SoftDevice.hex Bootloader.hex Application.hex UICR.hex 地址不重叠约束 → production_final.hex nRF52840 Flash 地址布局 SoftDevice (S140) 0x0000_0000 ~ 0x0002_6000 Bootloader 0x0002_6000 ~ 0x0005_0000 Application 0x0005_0000 ~ 0x000F_F000 Bootloader 设置 / DFU 参数 0x000F_F000 附近 UICR 0x1000_1000 低 高 生产烧录优先使用带地址的 Intel HEX;mergehex 合并时地址重叠会报错,需回查链接脚本与 SoftDevice memory map UICR 写入后部分字段需整片擦除才能修改,量产前务必确认配置值

五、生产文件检查清单

在把文件交给产线之前,建议按以下清单逐项确认,避免批量事故:

  • 格式确认:烧录器支持 Intel HEX 还是 S-record?nrfjprog 默认支持 HEX,若用第三方烧录器需确认格式兼容。
  • 地址核对:用 nrfjprog --readcode 或 hex2bin 查看合并后文件的地址范围,确认 SoftDevice 起始为 0x0,Application 起始不低于 Bootloader 结束地址。
  • UICR 检查:确认 NRF_UICR->NRFFW[0] 指向 Bootloader 起始地址,PSELRESET 等引脚配置与硬件一致。
  • 版本记录:在文件名或 UICR 中记录 SoftDevice 版本、Bootloader 版本、Application 版本,便于产线追溯。
  • 校验:烧录后执行 nrfjprog --verify,或读取 Flash 做 CRC 比对,确保写入内容与源文件一致。

掌握这套文件体系后,后续的自动化烧录脚本、产线工装和版本管理才有稳定的基础。文件格式选错、地址规划混乱,再快的烧录器也救不了批量返工。