在嵌入式开发中,我们经常需要将Bootloader和应用程序的HEX文件合并成一个完整的固件镜像。这个需求在量产烧录、OTA升级等场景中尤为常见。传统的手动合并方式不仅效率低下,还容易出错,特别是当两个HEX文件的地址范围存在冲突时。
我最近在开发一个基于ARM Cortex-M的物联网设备时,就遇到了这样的需求。经过多次实践和优化,我总结出了一套稳定可靠的HEX文件合并方案,使用srec_cat工具配合批处理脚本实现自动化合并,同时具备地址冲突检测功能。这套方案已经在多个实际项目中验证,效果良好。
srec_cat是SRecord工具集中的一个核心组件,专门用于处理各种格式的二进制文件,包括Intel HEX、Motorola S-record等。它的主要特点包括:
提示:可以从官方SourceForge仓库获取最新版本的srec_cat.exe,建议下载1.64或更高版本以获得最佳兼容性。
在实际项目中,我通常会在工程根目录下创建tools文件夹存放这类工具,这样既方便团队共享,也便于版本管理。
Intel HEX文件是一种文本格式的二进制表示,每行包含以下关键信息:
code复制:LLAAAATTDD...DDCC
其中:
当合并两个HEX文件时,我们需要特别关注地址范围是否重叠。典型的Bootloader和应用程序的地址分配如下:
| 模块 | 起始地址 | 结束地址 | 大小 |
|---|---|---|---|
| Bootloader | 0x08000000 | 0x08003FFF | 16KB |
| Application | 0x08004000 | 0x0801FFFF | 112KB |
srec_cat工具在合并HEX文件时,会执行以下关键操作:
合并命令的核心参数说明:
code复制srec_cat.exe
-disable-sequence-warning # 抑制地址顺序警告
boot.hex -Intel # 第一个输入文件及格式
app.hex -Intel # 第二个输入文件及格式
-o merged.hex -Intel # 输出文件及格式
完整的批处理脚本包含以下几个功能模块:
batch复制@echo off
REM =======================================================
REM Hex File Merger with Address Conflict Detection
REM Usage: MergeHex.bat [boot.hex] [app.hex] [output.hex]
REM =======================================================
pushd "%~dp0"
set BOOT_HEX=bootloader.hex
set APP_HEX=app.hex
set OUTPUT_HEX=BootAndApp.hex
if not "%~1"=="" set BOOT_HEX=%~1
if not "%~2"=="" set APP_HEX=%~2
if not "%~3"=="" set OUTPUT_HEX=%~3
这段代码实现了:
注意:
%~dp0表示批处理文件所在目录,这种写法可以确保脚本在任何位置被调用时都能正确找到相关文件。
脚本通过以下方式增强健壮性:
batch复制if not exist "srec_cat.exe" (
echo ERROR: srec_cat.exe not found!
popd
pause
exit /b 1
)
if errorlevel 1 (
echo.
echo ========== MERGE FAILED ==========
echo Possible cause: Address conflict between Boot and App.
echo Check that their memory regions do NOT overlap.
echo ==================================
popd
pause
exit /b 1
)
这种设计可以捕获以下常见错误:
在Keil中集成合并脚本的步骤如下:

关键配置要点:
IAR的集成方式略有不同:

IAR特有的注意事项:
对于NXP S32平台:

S32平台的特殊考虑:
当需要合并多个应用模块时,可以采用以下方法:
batch复制srec_cat.exe -disable-sequence-warning \
boot.hex -Intel \
app1.hex -Intel \
app2.hex -Intel \
-o full_image.hex -Intel
注意事项:
常见的地址冲突及解决方法:
| 冲突类型 | 表现症状 | 解决方案 |
|---|---|---|
| 完全重叠 | 合并失败,错误提示明显 | 调整链接脚本中的地址分配 |
| 部分重叠 | 可能合并成功但运行时异常 | 使用srec_info检查详细地址范围 |
| 边界误差 | 间歇性错误 | 在链接脚本中添加保留区域 |
对于大型HEX文件,可以采用以下优化措施:
-obs=16参数增加缓冲区大小在某智能家居项目中,我们采用以下方案:
合并脚本关键部分:
batch复制set BOOT_HEX=Bootloader_V1.2.hex
set APP_HEX=Application_A_V2.5.hex
set OUTPUT_HEX=Factory_Image_V2.5.hex
srec_cat.exe -disable-sequence-warning ^
"%BOOT_HEX%" -Intel ^
"%APP_HEX%" -Intel ^
-fill 0xFF 0x08000000 0x08108000 ^
-o "%OUTPUT_HEX%" -Intel
这个案例中,我们添加了-fill参数确保未使用区域被正确填充,避免Flash编程错误。
在要求高可靠性的工业场景中,我们实现了双应用程序镜像:
合并脚本需要处理更复杂的地址关系:
batch复制srec_cat.exe ^
boot.hex -Intel ^
-exclude -within main_app.hex -Intel -overlap backup_app.hex -Intel ^
main_app.hex -Intel ^
backup_app.hex -Intel ^
-o full_image.hex -Intel
这个案例使用了-exclude和-within参数确保备份镜像不会意外覆盖主镜像区域。
问题现象:合并后的HEX文件比预期小很多。
可能原因:
解决方案:
srec_info检查输入文件地址范围-fill参数填充空白区域问题现象:合并大型HEX文件耗时过长。
优化建议:
-obs=64Keil特有问题:
IAR特有问题:
基于实际项目经验,可以考虑以下增强功能:
版本校验:自动检查HEX文件中的版本信息是否兼容
batch复制for /f "tokens=2 delims==" %%G in ('findstr "APP_VERSION" %APP_HEX%') do (
set APP_VER=%%G
)
自动填充:确保Flash空白区域被正确填充
batch复制srec_cat.exe ... -fill 0xFF 0x08000000 0x08040000 ...
日志记录:保存每次合并的详细日志
batch复制echo %DATE% %TIME% Merged %BOOT_HEX% + %APP_HEX% >> merge_log.txt
CRC校验:添加整个镜像的CRC校验值
batch复制srec_cat.exe ... -crop 0x08000000 0x08040000 -fill 0xFF -crc32-l-e 0x0803FFFC ...
这些增强功能可以根据项目实际需求选择性实现,逐步构建更完善的自动化工具链。