3. UDS协议核心
刷写流程,说白了就是ECU固件升级的完整操作规范。很多工程师刚接触UDS刷写时,总觉得不就是发几个34 36 37服务嘛,结果一上实车就出问题。我见过太多因为跳过预编程步骤,导致刷写后ECU锁死的案例。
UDS标准把刷写流程拆成三个阶段:预编程、主编程、后编程。每个阶段又包含若干步骤,加起来一共10个核心步骤。嗯,咱们一个一个来看。
核心要点:三个阶段缺一不可。预编程是准备工作,主编程是数据传输,后编程是收尾验证。跳过任何一步,都可能让ECU变砖。
3.1 预编程阶段(步骤1-4)
预编程阶段,说白了就是让ECU进入可刷写的状态。ECU在正常运行时,有很多保护机制——比如禁止写入Flash、网络通信繁忙、DTC记录中。你得先把这些障碍清掉。
步骤1:诊断会话控制 (10 02)
发送 10 02 切换到编程会话。ECU收到后,会关闭一些非关键通信,释放资源。我遇到过一个问题:有些ECU从默认会话切到编程会话时,响应时间特别慢,超过500ms。后来发现是ECU内部在保存当前运行参数。嗯,这里建议超时设到1秒以上。
步骤2:安全访问解锁 (27 03/04)
刷写是高风险操作,ECU不会让随便谁都能写Flash。你得通过种子-密钥验证。发送 27 03 请求种子,ECU返回一串随机数;你用算法算出密钥,发 27 04 带密钥过去。
实战技巧:我个人习惯在安全访问失败后,等待至少100ms再重试。有些ECU有防暴力破解机制,连续失败3次会锁死30分钟。我曾经在测试时连续发请求,结果ECU直接罢工了半小时。
步骤3:通信控制 (28 03)
发送 28 03 关闭应用报文和网络管理报文。为什么?刷写时总线上一堆报文干扰,万一刷到一半网络管理报文要求休眠,那就麻烦了。关闭非诊断通信,让总线安静下来。
步骤4:DTC控制 (85 02)
发送 85 02 设置DTC存储为关闭状态。刷写过程中ECU会经历各种异常状态——电压波动、通信中断、内存操作繁忙。如果不关DTC记录,ECU会记一堆故障码,刷完还得清,麻烦。
警告:步骤3和步骤4的顺序不要搞反。先关通信,再关DTC。如果先关DTC再关通信,ECU在关闭通信的过程中可能产生新的DTC,而此时DTC记录还没关掉,就会把异常状态记下来。
3.2 主编程阶段(步骤5-8)
主编程阶段是真正的数据传输环节。这里有个关键概念:数据块。固件文件通常很大,几百KB甚至几MB,不能一次性发完。你得把固件切成小块,一块一块传。
步骤5:请求下载 (34 00 44)
发送 34 00 44 + 内存地址 + 数据长度。告诉ECU:我要往哪个地址写数据,写多少字节。ECU会返回一个最大数据块长度(MaxNumberOfBlockLength),告诉你每个数据块最多能传多少字节。
举个例子:
请求:34 00 44 00 10 00 00 00 10 00
↑ ↑ ↑ ↑ ↑ ↑
34 00 44 地址高字节 数据长度
响应:74 00 44 00 10
↑ ↑ ↑ ↑
74 00 44 最大块长度=16字节
步骤6:数据传输 (36)
发送 36 + 块序列号 + 数据。把固件数据按步骤5得到的最大块长度切分,一帧一帧发。注意:块序列号从01开始,每发一块加1。
关键点:步骤5和步骤6是循环执行的。每传完一个数据块,都要重新发一次34请求下载,再发36传数据。直到整个固件传完。
步骤7:请求退出传输 (37)
发送 37 结束当前数据块的传输。ECU收到后,会把刚才收到的数据写入Flash。注意:37服务只是结束当前块,不是结束整个刷写流程。下一个块还得从34开始。
步骤8:检查编程依赖 (31 01 FF 00)
这一步很多人会忽略。发送 31 01 FF 00 执行编程依赖检查。ECU会校验刚写入的固件完整性、版本兼容性、签名有效性。如果校验失败,ECU会返回NRC,告诉你刷写有问题。
我遇到过最坑的情况:固件刷完了,ECU也复位了,结果起不来。后来发现是刷写顺序错了——先刷了应用层,后刷了Bootloader,导致Bootloader覆盖了应用层的启动向量。嗯,从那以后我每次都在主编程最后加一步依赖检查。
3.3 后编程阶段(步骤9-10)
后编程阶段是收尾工作。固件写进去了,但ECU还在编程会话里,网络通信还关着,DTC记录也关着。你得让ECU恢复正常运行状态。
步骤9:ECU复位 (11 01)
发送 11 01 让ECU硬件复位。ECU重启后,会从新的固件启动。注意:复位后ECU会回到默认会话,之前设置的通信控制和DTC控制都会自动恢复。
经验之谈:复位后不要立即发诊断请求。ECU启动需要时间,Bootloader要初始化硬件、校验固件、跳转到应用。我一般等2-3秒再发连接请求。有些ECU启动慢,等5秒都正常。
步骤10:重新连接验证
ECU复位后,你需要重新建立诊断连接:
- 发送
10 01进入默认会话 - 发送
22 F1 00读取ECU的软件版本号,确认固件已更新 - 发送
19 02 0F读取DTC,确认没有刷写相关的故障码
如果版本号正确,DTC为空,恭喜你,刷写成功。
3.4 10个步骤速查表
| 步骤 | 服务 | 请求示例 | 说明 |
|---|---|---|---|
| 1 | 诊断会话控制 | 10 02 | 切换到编程会话 |
| 2 | 安全访问 | 27 03/04 | 种子-密钥验证解锁 |
| 3 | 通信控制 | 28 03 | 关闭非诊断通信 |
| 4 | DTC控制 | 85 02 | 关闭DTC存储 |
| 5 | 请求下载 | 34 00 44 | 声明写入地址和长度 |
| 6 | 数据传输 | 36 | 发送固件数据块 |
| 7 | 请求退出传输 | 37 | 结束当前数据块 |
| 8 | 检查编程依赖 | 31 01 FF 00 | 校验固件完整性 |
| 9 | ECU复位 | 11 01 | 硬件复位启动新固件 |
| 10 | 重新连接验证 | 10 01 + 22 F1 00 | 确认版本号、检查DTC |
常见坑点:
- 步骤5-7循环时,块序列号不要重复,否则ECU会认为数据重复而拒绝写入
- 步骤8的依赖检查必须在所有数据块传完之后执行,不能提前
- 步骤9复位后,ECU可能进入Bootloader模式,需要重新走安全访问才能继续诊断
好了,三阶段十步骤就讲完了。你想想看,其实刷写流程并不复杂,关键是把每一步的时序和依赖关系搞清楚。我在实际项目中,经常看到工程师把步骤3和步骤4搞反,或者漏掉步骤8。嗯,这些细节决定了刷写是成功还是变砖。