2、刷写协议基础:UDS协议简介、诊断会话控制、安全访问、刷写相关的服务(如34/36/37服务)

各位好,欢迎来到刷写协议基础这一章。

做ECU刷写,说白了就是和ECU“对话”,让它把旧程序忘掉,装上新程序。那用什么语言对话?就是UDS——统一诊断服务。我最早接触UDS是在一个OBD项目里,当时觉得它就是读读故障码,后来才发现,刷写才是UDS最硬核的应用场景之一。

2.1 UDS协议简介

UDS(ISO 14229)是汽车电子行业的通用诊断协议。它定义了一套标准化的服务,覆盖了从读取故障码到在线编程的全流程。

为什么刷写要用UDS?原因很简单:

  • 标准化:无论哪家Tier1,基本都支持UDS,不用为每个ECU学一套新协议。
  • 安全性:UDS内置了安全访问、身份验证机制,防止非法刷写。
  • 可靠性:有流控制、超时重传机制,保证大数据传输不丢包。

UDS的通信模型是“请求-响应”式。Tester(刷写工具)发请求,ECU回响应。每个服务都有一个唯一的SID(服务标识符)。

核心概念:UDS刷写主要依赖三个服务——34(请求下载)、36(传输数据)、37(请求退出传输)。这三个服务配合起来,就能把二进制文件完整地写入ECU的Flash中。

2.2 诊断会话控制(10服务)

ECU平时可能处于低功耗模式,不会响应刷写请求。你需要先通过10服务(DiagnosticSessionControl)把它切换到正确的会话模式。

常见的会话模式有三种:

会话模式 SID+SubFunction 用途
默认会话 10 01 上电后的初始状态,只响应基本诊断服务
编程会话 10 02 刷写专用模式,开启34/36/37等刷写服务
扩展诊断会话 10 03 允许读写数据、执行例程,常用于标定

我个人习惯,在刷写开始前,先发一条10 02,然后检查ECU回的是50 02。如果没收到正确响应,后面的刷写流程根本走不通。

小技巧:有些ECU在切换会话后,会重置某些状态(比如安全访问状态)。所以我的建议是:切换会话后,重新走一遍安全访问流程,不要偷懒。

2.3 安全访问(27服务)

ECU不会让随便一个设备就刷写程序。它需要验证你的身份——这就是27服务(SecurityAccess)。

流程大概是这样的:

  1. 请求种子:Tester发27 01,ECU返回一个随机种子(比如4字节数据)。
  2. 计算密钥:Tester用种子和约定的算法算出密钥。
  3. 发送密钥:Tester发27 02 + 密钥,ECU验证。
  4. 解锁成功:ECU回67 02,表示安全访问通过。

嗯,这里要注意:不同ECU的密钥算法可能完全不同。有的用AES,有的用自定义异或。我曾经在一个项目里,因为算法文档写错了一个字节,折腾了两天才找到问题。

避坑指南:我曾经遇到过,连续输错密钥3次,ECU直接锁死,必须断电重启才能恢复。所以刷写工具里一定要加失败重试次数限制,并且处理好ECU的“延时惩罚”机制。

2.4 刷写核心三件套:34/36/37服务

这三个服务是刷写的主力。我习惯把它们叫做“下载三部曲”。

2.4.1 34服务:请求下载(RequestDownload)

告诉ECU:“我要开始传数据了,你准备好接收。” 请求里要带上数据长度和内存地址信息。

报文格式示例:

请求:34 00 44 00 08 00 00 10 00
  - 34:SID
  - 00:压缩方法(无压缩)
  - 44:加密方法(无加密)
  - 00 08:要写入的字节数(8字节)
  - 00 00 10 00:起始内存地址(0x1000)

ECU收到后,会返回一个74响应,里面包含它允许的最大数据块长度(比如74 20表示每次最多传32字节)。

关键点:34服务返回的“最大数据块长度”决定了后面36服务每次能发多少数据。如果ECU说一次只能传32字节,你硬传64字节,ECU会直接拒掉。

2.4.2 36服务:传输数据(TransferData)

这是真正传数据的服务。Tester把二进制文件切成小块,一块一块地发。

报文格式示例:

请求:36 01 [32字节数据]
  - 36:SID
  - 01:块序号(从1开始递增)
  - [32字节数据]:实际要写入的固件数据

ECU每收到一块,会回76响应。如果ECU回的是NRC(否定响应码),比如7F 36 31(请求超出范围),那就要检查数据块序号或数据内容了。

我记得有一次,刷写过程中总是卡在某个数据块上。排查了半天,发现是ECU的Flash驱动有个Bug——当写入地址跨页时,会触发异常。后来我调整了数据块大小,保证每次写入不跨页,问题就解决了。

2.4.3 37服务:请求退出传输(RequestTransferExit)

数据传完了,告诉ECU:“结束传输,你可以处理了。” ECU收到后,会做校验、擦除临时缓冲区等收尾工作。

报文格式:

请求:37
响应:77

有些ECU在收到37服务后,还会自动触发完整性校验。如果校验失败,ECU会回NRC,并且可能拒绝启动新程序。

2.5 刷写流程全景图

下面这张图,把整个刷写流程串起来了。你可以把它当作刷写程序的“路线图”。

UDS刷写流程全景图 UDS刷写流程全景图 10 02 编程会话 27 01/02 安全访问 34 请求下载 36 传输数据(循环直到数据发完) 循环 37 请求退出传输 刷写完成 说明: 每个步骤都必须收到 ECU的正确响应(如50、 67、74、76、77)才能继续。

2.6 刷写中的常见NRC及处理

刷写过程中,ECU可能返回各种否定响应码。我整理了一份常见清单:

NRC 含义 常见原因
0x22 条件不正确 没切换到编程会话就发34服务
0x24 请求序列错误 没做安全访问就发36服务
0x31 请求超出范围 内存地址或数据长度不合法
0x33 安全访问被拒绝 密钥错误或已锁定
0x36 超过最大数据块长度 36服务发的数据超过了34服务允许的长度
0x37 响应待定 ECU正在忙,需要Tester等待

实战建议:我一般在刷写工具里加一个“NRC自动重试”逻辑。遇到0x37(响应待定),就等100ms再重试;遇到0x31或0x33,直接停止刷写并报错,避免反复尝试浪费时间。

2.7 小结

这一章我们聊了UDS刷写的核心基础。从10服务切换会话,到27服务安全访问,再到34/36/37下载三部曲,每一步都有它的意义和坑点。

你想想看,刷写本质上就是一次“受控的、安全的、可靠的数据搬运”。理解了这个本质,后面再学更复杂的刷写策略(比如压缩刷写、差分刷写)时,就会轻松很多。