4. 通信协议基础
各位工程师,大家好。欢迎来到第四讲。
上一章我们聊了刷写协议和底层通信,今天咱们把目光聚焦到刷写的“弹药”上——也就是那些要被写进 ECU 的固件文件。
你可能会想,不就是个文件吗?拖进去就完了。但实际项目中,我见过太多因为文件格式搞错、地址映射对不上、校验失败导致刷写变砖的案例。说白了,不懂文件结构,你连刷写失败的原因都查不出来。
4.1 三大主流格式:S19、HEX、BIN
目前汽车电子领域,最常见的固件分发格式就这三种。它们各有各的脾气,咱们一个一个说。
| 特性 | Motorola S19 (SREC) | Intel HEX | Binary (BIN) |
|---|---|---|---|
| 存储形式 | ASCII 文本 | ASCII 文本 | 纯二进制 |
| 可读性 | 高,可用记事本打开 | 高,可用记事本打开 | 低,需专用工具查看 |
| 地址信息 | 每行自带地址 | 每行自带地址 | 无地址,从0开始 |
| 校验机制 | 行校验 + 文件结束校验 | 行校验 | 无内置校验 |
| 典型应用 | 飞思卡尔/NXP 系列 MCU | Intel/Infineon 系列 MCU | Bootloader 原始镜像、加密固件 |
我个人习惯,在项目初期调试阶段,尽量用 S19 或 HEX。为什么?因为出错了你能直接看文本,定位问题快。BIN 文件虽然体积最小,但一旦地址错了,你连错在哪都不知道。
4.2 S19 文件格式深度拆解
S19 文件,也叫 Motorola S-record。每一行都以大写字母 'S' 开头,后面跟一个数字表示记录类型。
典型行结构:
S1137FF0 00 112233445566778899AABBCCDDEEFF 7E
我来拆解一下这行:
- S1:记录类型。S1 表示 16 位地址的数据记录。S2 是 24 位地址,S3 是 32 位地址。S0 是文件头,S5 是记录计数,S8/S9 是文件结束。
- 13:本行字节数(十六进制)。这里 0x13 = 19 字节,包括地址、数据和校验。
- 7FF0:起始地址。这里是 0x7FF0。
- 00...FF:实际数据,共 16 字节。
- 7E:校验和。计算方式:对本行所有字节(不包括 'S' 和类型号)求和,取低 8 位,再取反。
4.3 Intel HEX 文件格式深度拆解
Intel HEX 格式,每行以冒号 ':' 开头。结构类似,但细节不同。
典型行结构:
:10 7FF0 00 112233445566778899AABBCCDDEEFF 7E
拆解如下:
- 10:本行数据长度(字节)。这里是 16 字节。
- 7FF0:起始地址。
- 00:记录类型。00 是数据记录,01 是文件结束,02 是扩展段地址,04 是扩展线性地址。
- 11...FF:数据。
- 7E:校验和。计算方式:对本行所有字节(不包括冒号)求和,取低 8 位,取反,再加 1(即补码)。
4.4 BIN 文件:最纯粹,也最危险
BIN 文件就是数据的原始二进制转储。没有地址,没有校验,没有文件头。你给它什么,它就写什么。
它的优点是体积最小,解析速度最快。缺点是,你必须事先知道这个 BIN 文件应该烧录到哪个起始地址。
使用场景:
- Bootloader 本身(通常固定地址)。
- 经过加密或压缩后的固件包。
- 量产时的最终镜像(已包含完整地址映射)。
核心原则: 使用 BIN 文件时,刷写工具必须明确配置 目标起始地址 和 长度。配置错了,后果很严重。
4.5 地址映射与数据段:理解你的内存布局
文件格式只是外壳,真正的核心是地址映射。一个固件文件,通常包含多个数据段:
- 代码段 (.text):存放可执行指令。
- 常量段 (.rodata):存放常量、字符串。
- 初始化数据段 (.data):存放已初始化的全局变量。
- BSS 段 (.bss):存放未初始化的全局变量(通常不包含在固件文件中,由启动代码清零)。
在 S19 或 HEX 文件中,这些段可能分散在不同的地址区域。比如,代码在 0x8000-0x8FFF,常量在 0x9000-0x90FF。
刷写工具需要做的,就是:
- 解析文件,提取出每一段数据的 起始地址 和 长度。
- 将这些数据段,按照地址顺序,发送给 ECU 的刷写服务。
- ECU 的 Bootloader 根据接收到的地址,将数据写入对应的 Flash 扇区。
下面这张图,展示了从固件文件到 Flash 存储的完整映射流程。
4.6 校验机制:你的最后一道防线
刷写过程中,数据在传输时可能出错。校验就是用来发现这些错误的。
常见的校验方式:
- 行校验:S19 和 HEX 文件自带,用于验证每一行数据在传输过程中是否被篡改。
- CRC 校验:刷写协议(如 UDS 的 0x31 服务)通常会在整个文件传输完成后,要求 ECU 计算一个 CRC32 或 CRC16,与工具端计算的对比。不一致则刷写失败。
- Flash 读取回验:刷写完成后,工具可以读取 Flash 内容,与原始文件逐字节对比。这是最笨但最可靠的方法。
4.7 实战:如何快速判断一个文件格式
拿到一个固件文件,第一件事就是判断它是什么格式。我一般这么做:
- 用文本编辑器(如 Notepad++)打开。
- 看第一行第一个字符:
- 如果是 'S',那就是 S19。
- 如果是 ':',那就是 HEX。
- 如果是乱码或二进制,那就是 BIN。
- 对于 BIN 文件,需要从文件名或项目文档中确认起始地址。