4、刷写流程概览:预编程、主编程、后编程三个阶段
刷写流程,说白了就是给ECU换“脑子”的过程。我做了这么多年OTA测试,发现很多新手一上来就盯着主编程阶段猛看,结果预编程和后编程的坑一个接一个踩。今天咱们就把这三个阶段掰开揉碎了讲清楚。
4.1 为什么非要分三个阶段?
你想想看,ECU在车上不是孤立的。它连着CAN总线,跟其他节点有通信,内部还在跑应用逻辑。如果你直接往Flash里写数据,搞不好就把系统搞崩了。
所以标准刷写流程(ISO 14229-1里定义的)把整个过程拆成三个阶段:
- 预编程(Pre-Programming):让ECU“准备好”被刷
- 主编程(Main Programming):真正传输数据
- 后编程(Post-Programming):让ECU“恢复工作”
我个人习惯把这三个阶段比喻成做手术:预编程是麻醉和消毒,主编程是动刀,后编程是缝合和苏醒。缺一个都不行。
4.2 预编程阶段:让ECU“安静下来”
这个阶段的目标很简单——让ECU停止正常通信,进入可编程模式。
典型步骤:
- 诊断会话切换:从默认会话切到编程会话(0x10 03)
- 安全访问:发送种子-密钥挑战(0x27),验证刷写工具权限
- 禁用DTC记录:用0x85服务关掉故障码存储,避免刷写过程中误报
- 停止通信:用0x28服务让ECU停止发送应用报文
避坑指南:我曾经遇到过一台ECU,预编程时安全访问通过了,但禁用DTC时返回了NRC 0x22(条件不满足)。查了半天才发现,原来是ECU内部有个看门狗没喂,导致状态机卡住了。所以预编程阶段一定要检查每个步骤的响应码。
4.3 主编程阶段:真正的数据传输
这是最核心的阶段,也是CANoe仿真里最耗时的部分。主编程又细分为几个子步骤:
典型流程:
- 请求下载(0x34):告诉ECU我要写数据了,数据长度是多少
- 传输数据(0x36):分块发送刷写文件内容,每块通常256字节或1KB
- 请求退出传输(0x37):告诉ECU数据发完了
- 检查编程完整性(0x31 01 02 02):让ECU校验CRC或签名
- ECU复位(0x11 01):硬复位,让新程序跑起来
我的经验:传输数据时,CANoe的CAPL脚本里一定要加超时处理。我记得有一次客户现场,网络抖动导致一帧数据丢了,ECU一直等下一帧,结果整个刷写卡了30秒。后来我在脚本里加了0x36响应的超时重传机制,问题就解决了。
4.4 后编程阶段:让ECU“恢复工作”
刷写完成后,ECU不能就这么“裸奔”着。后编程阶段要做三件事:
- 重新启用DTC记录:用0x85服务恢复故障码存储
- 恢复通信:用0x28服务让ECU重新发送应用报文
- 切换回默认会话:从编程会话切回默认会话(0x10 01)
嗯,这里要注意:有些ECU在后编程阶段还需要做编程依赖检查。比如你刷了发动机ECU,可能还需要刷变速箱ECU,两者版本要匹配。我见过一个项目,因为后编程阶段没做版本一致性检查,结果刷完车抖得跟筛子似的。
4.5 ECU升级状态机
刷写过程本质上是一个有限状态机。每个阶段对应一个状态,状态之间通过诊断请求触发跳转。
典型状态机:
| 状态 | 触发条件 | 说明 |
|---|---|---|
| IDLE | 上电/复位 | ECU正常运行应用 |
| PRE_PROG | 0x10 03 + 安全访问通过 | 预编程完成,准备刷写 |
| MAIN_PROG | 0x34请求下载 | 正在传输数据 |
| POST_PROG | 0x11 01复位后 | 后编程恢复操作 |
| COMPLETED | 后编程完成 | 刷写成功,ECU重启 |
重要提醒:状态机里最容易出问题的是“异常跳转”。比如主编程阶段突然收到一个0x10 01(切回默认会话),ECU该怎么处理?标准做法是拒绝并返回NRC 0x22。但有些ECU实现有bug,会直接跳回IDLE状态,导致刷写中断。所以CANoe仿真里一定要覆盖这些异常场景。
4.6 刷写文件格式:S19、HEX、BIN
刷写文件就是你要写进ECU Flash里的二进制数据。常见的格式有三种:
S19(Motorola S-record)
- 文本格式,每行以'S'开头
- 包含地址、数据、校验和
- 我最早做飞思卡尔芯片时,用的全是S19格式
HEX(Intel HEX)
- 也是文本格式,每行以':'开头
- 支持扩展线性地址(0x04记录类型)
- 很多国产MCU喜欢用这个格式
BIN(Binary)
- 纯二进制,没有地址信息
- 必须配合地址偏移使用
- 文件最小,传输最快
三种格式对比:
| 特性 | S19 | HEX | BIN |
|---|---|---|---|
| 可读性 | 中 | 中 | 差 |
| 地址信息 | 有 | 有 | 无 |
| 文件大小 | 大(约2倍) | 大(约2倍) | 小(原始大小) |
| 校验方式 | 行校验和 | 行校验和 | 无 |
| 典型应用 | NXP/Freescale | Infineon/ST | 通用 |
我的建议:在CANoe仿真中,我一般用S19或HEX格式做测试,因为可以直接看到地址信息,方便调试。但实际量产时,很多OEM要求用BIN格式,因为传输效率高。你可以在CANoe里写个CAPL函数,把S19/HEX转成BIN再发送。
4.7 实战中的小技巧
最后分享几个我在项目中积累的经验:
- 预编程阶段一定要加延时:ECU切换会话后,内部状态机需要时间稳定。我一般加100ms的等待。
- 主编程的块大小要匹配:有些ECU最大支持256字节,有些支持1KB。发大了ECU会拒绝,发小了效率低。
- 后编程阶段别急着切会话:ECU复位后,应用层启动需要时间。我习惯等3-5秒再发后编程指令。
- 日志记录要详细:每个诊断请求和响应都记下来。出问题时,日志就是你的救命稻草。
好了,刷写流程概览就讲到这里。下一章咱们会深入CANoe里怎么搭建刷写仿真环境,包括CAPL脚本怎么写、怎么模拟ECU响应。到时候我会拿一个实际项目案例来演示,保证干货满满。