第四讲:刷写流程概览——从规范到实战

大家好,欢迎来到第四讲。

上一讲我们聊了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诊断服务用得最多。

典型流程如下:

  1. 切换到编程会话(0x10 02)
  2. 安全访问解锁(有些OEM要求再次解锁)
  3. 写入指纹信息(0x2E服务,记录刷写者信息)
  4. 擦除Flash区域(0x31 01 FF 00,例程控制擦除)
  5. 请求下载(0x34服务,告诉ECU我要发数据了)
  6. 传输数据(0x36服务,分块发送S19/HEX/BIN数据)
  7. 请求退出传输(0x37服务,结束数据传输)
  8. 校验完整性(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行,写出每行的地址和数据长度。相信我,动手做一遍,比看十遍都管用。