第四讲:刷写流程概览——从规范到实战
大家好,欢迎来到第四讲。
上一讲我们聊了CANoe的基础环境搭建。今天要讲的内容,可以说是整个刷写课程的核心骨架——刷写流程。说白了,就是ECU怎么从“老软件”变成“新软件”的完整过程。
我刚开始接触刷写时,觉得不就是把文件发过去吗?后来被现实狠狠教育了一回。有一次,因为忽略了预编程阶段的一个握手时序,导致整批ECU刷写失败,差点耽误项目节点。从那以后,我对刷写流程的敬畏心就上来了。
4.1 OEM刷写规范——你的“圣经”
每个主机厂都有自己的刷写规范。宝马有BWM Standard,大众有VW 80000,吉利有GEEA规范。这些文档,说白了就是OEM告诉供应商:“你得按我的规矩来刷。”
我个人习惯,拿到一个新项目的第一件事,不是看原理图,而是先翻刷写规范。为什么?因为刷写规范里藏着很多“坑”。
刷写规范通常包含以下核心内容:
- 诊断会话切换规则:什么时候切扩展会话,什么时候切编程会话
- 安全访问算法:种子和密钥的生成方式
- 刷写时序要求:每个步骤的超时时间,比如P2CAN_Server最大值
- 数据块大小限制:比如单帧最多发多少字节,多帧传输的块大小
- 刷写顺序:先刷应用还是先刷Bootloader,能不能跳过某些步骤
我记得有一次,某OEM的规范里写了一句“刷写完成后需等待100ms再发送TesterPresent”。就这一句话,我们团队没注意,结果刷写完成后ECU直接进入了休眠模式。嗯,这种细节,规范里到处都是。
我的建议:拿到规范后,先画一张流程图。把每个步骤、每个超时、每个条件判断都标出来。这张图,就是你写自动化脚本的蓝图。
4.2 刷写三阶段:预编程、主编程、后编程
刷写流程,几乎所有OEM都遵循一个通用框架:预编程 → 主编程 → 后编程。你想想看,这就像做手术:术前准备、手术操作、术后恢复。一个都不能少。
4.2.1 预编程阶段——准备工作
预编程的目的很简单:让ECU进入一个“可以安全刷写”的状态。
具体做什么呢?我列一下典型步骤:
- 诊断会话切换:从默认会话切换到扩展会话(0x10 03)
- 安全访问解锁:发送种子请求,计算密钥,解锁ECU(0x27服务)
- 禁用故障码存储:通过0x85服务或0x28服务,告诉ECU“别记录故障了,我要刷你了”
- 检查刷写条件:比如电压是否正常、点火开关是否在ON档
这里有个坑,我必须要说。我曾经遇到过,预编程阶段的安全访问解锁,有些ECU要求必须在扩展会话下进行,有些则要求在编程会话下。你如果搞混了顺序,ECU会直接返回NRC 0x22(条件不满足)。所以,一定要看规范里的会话状态机图。
警告:预编程阶段如果失败,不要直接重试。先检查ECU是否已经进入了某种“锁死”状态。有些ECU在连续3次安全访问失败后,会锁定一段时间。这时候你硬刷,只会浪费时间。
4.2.2 主编程阶段——核心操作
主编程阶段,就是真正把数据写进ECU Flash的过程。这个阶段,UDS诊断服务用得最多。
典型流程如下:
- 切换到编程会话(0x10 02)
- 安全访问解锁(有些OEM要求再次解锁)
- 写入指纹信息(0x2E服务,记录刷写者信息)
- 擦除Flash区域(0x31 01 FF 00,例程控制擦除)
- 请求下载(0x34服务,告诉ECU我要发数据了)
- 传输数据(0x36服务,分块发送S19/HEX/BIN数据)
- 请求退出传输(0x37服务,结束数据传输)
- 校验完整性(0x31 01 FF 01,例程控制校验)
我个人习惯,在主编程阶段,每发送一个数据块后,都检查一下ECU的响应。不要等到全部发完再检查。为什么?因为如果中间某块数据写失败了,你后面发的全是白费功夫。
这里展示一段简单的CANoe CAPL代码,用于发送0x34请求下载:
// 请求下载示例
byte requestData[8];
requestData[0] = 0x34; // 服务ID
requestData[1] = 0x00; // 数据格式:不压缩、不加密
requestData[2] = 0x44; // 地址长度和内存大小长度
requestData[3] = 0x00; // 起始地址高字节
requestData[4] = 0x80; // 起始地址中字节
requestData[5] = 0x00; // 起始地址低字节
requestData[6] = 0x00; // 数据长度高字节
requestData[7] = 0x10; // 数据长度低字节(256字节)
// 发送请求
output(can1, requestData, 8);
这段代码很简单,但实际项目中,地址和长度都是从S19文件里解析出来的。后面我们会专门讲怎么解析刷写文件。
4.2.3 后编程阶段——收尾工作
刷写完成不代表结束。后编程阶段,我们要让ECU恢复正常工作状态。
典型步骤:
- 启用故障码存储(恢复0x85或0x28的设置)
- 清除故障码(0x14服务,把刷写过程中产生的临时故障码清掉)
- 复位ECU(0x11服务,让ECU以新软件启动)
- 验证软件版本(0x22服务,读取刷写后的软件版本号)
嗯,这里要注意。复位ECU后,不要马上发诊断请求。ECU启动需要时间,有些ECU启动要好几秒。你如果立刻发请求,ECU还没准备好,会返回NRC 0x78(请求正确接收,但响应待定)。
避坑指南:我曾经在项目里,后编程阶段复位后,等了2秒就发版本读取请求。结果ECU还在启动中,直接没响应。后来我改成等待5秒,并加上重试机制,问题就解决了。所以,复位后的等待时间,宁长勿短。
4.3 刷写文件格式——S19、HEX、BIN
刷写文件,就是你要写进ECU的“新软件”。常见的格式有三种:S19、HEX、BIN。它们本质上都是二进制数据的载体,只是编码方式不同。
| 格式 | 特点 | 适用场景 |
|---|---|---|
| S19(Motorola S-record) | 文本格式,每行以S开头,包含地址、数据、校验和 | NXP、Infineon等主流MCU,OEM规范中最常见 |
| HEX(Intel HEX) | 文本格式,每行以冒号开头,包含记录类型、地址、数据 | Intel架构MCU,部分日系车厂使用 |
| BIN(Binary) | 纯二进制,没有地址信息,只有原始数据 | 需要配合地址映射表使用,较少直接用于刷写 |
我个人最喜欢S19格式。为什么?因为它每行都带地址和校验和,解析起来很方便。而且大多数OEM的刷写规范,都明确要求使用S19格式。
举个例子,S19文件的一行数据长这样:
S214 0000 12345678 9ABCDEF0 11223344 55667788 5A
解析一下:
- S2:记录类型,表示24位地址
- 14:本行数据长度(20字节,包括地址、数据、校验和)
- 0000:起始地址(高字节)
- 12345678 9ABCDEF0 ...:实际数据(16字节)
- 5A:校验和
你想想看,如果我用BIN格式,没有地址信息,我怎么知道这段数据要写到Flash的哪个位置?所以,刷写自动化中,解析S19文件是基本功。
重点:刷写文件解析的核心,就是提取出“地址-数据”对。然后按照地址顺序,通过0x34/0x36服务,把数据发送给ECU。后面我们会专门用一节课,手把手教你写S19解析器。
4.4 本章小结
好,我们来捋一捋今天的内容:
- OEM刷写规范是刷写的“法律”,必须逐条遵守
- 刷写三阶段:预编程(准备)、主编程(写数据)、后编程(收尾)
- 刷写文件格式:S19最常用,HEX次之,BIN较少
下一讲,我们会深入预编程阶段,手把手教你实现安全访问解锁。那一步,可是刷写自动化的第一个拦路虎。咱们下节课见。
课后练习:找一份你项目中的S19文件,手动解析前5行,写出每行的地址和数据长度。相信我,动手做一遍,比看十遍都管用。