3、刷写核心服务:34H服务(请求下载)、36H服务(传输数据)、37H服务(请求退出传输)

好,咱们今天聊点硬核的。OTA刷写,说白了就是给车机“换脑子”。而34H、36H、37H这三个服务,就是换脑子过程中最核心的三板斧。我个人习惯把这仨服务称为“刷写三兄弟”——大哥开门、二哥搬砖、三弟收尾。

你想想看,ECU里存着旧程序,你要把新程序写进去。总得先告诉ECU:“嘿,我要开始写了,你准备好没?”这就是34H服务。然后你得把数据一块一块传过去,这就是36H服务。最后传完了,你得说一声:“好了,没了,你收工吧。”这就是37H服务。

嗯,逻辑上很简单。但实际项目中,坑可不少。我一个个说。

3.1 34H服务——请求下载

34H服务,全称是“Request Download”。它的作用,就是客户端(比如你的刷写工具)告诉服务器(ECU):“我要下载数据了,你准备一下接收缓冲区。”

这个服务的请求报文格式是这样的:

请求:34H + 数据格式标识符 + 地址和长度格式标识符 + 内存地址 + 内存大小

其中:

  • 数据格式标识符(1字节):高4位表示压缩方法,低4位表示加密方法。0x00就是不压缩不加密。我在项目中遇到过,有些ECU只支持0x00,你传别的值它直接给你NRC 0x13(不支持的参数)。
  • 地址和长度格式标识符(1字节):高4位表示地址字节数,低4位表示长度字节数。比如0x44,就是地址占4字节,长度占4字节。
  • 内存地址:你要写入的起始地址。这个地址是ECU内部的逻辑地址,不是物理地址。我曾经踩过坑,把Flash物理地址直接传过去了,结果ECU死活不认。
  • 内存大小:你要下载的数据总长度。

服务器收到34H请求后,如果一切正常,会回复一个肯定响应:

响应:74H + 最大数据块长度

这个“最大数据块长度”很关键。它告诉客户端:“你每次最多能传多少字节给我。”不同ECU的这个值不一样,有的支持4096字节,有的只支持256字节。我建议你在设计刷写工具时,先发一个34H探探路,看看ECU能接受多大的块,别一上来就传大包。

核心要点:34H服务是刷写的“握手”阶段。它决定了后续36H传输的块大小和地址范围。如果34H失败了,后面的36H和37H根本不用发。

注意:34H服务执行后,ECU会进入一个“下载模式”。在这个模式下,ECU可能不会响应其他非刷写相关的服务。所以,刷写过程中不要乱发其他诊断请求,否则ECU可能会给你NRC 0x21(忙)或者直接不理你。

3.2 36H服务——传输数据

36H服务,全称是“Transfer Data”。这是刷写过程中最累的活——搬砖。客户端把数据一块一块地传给ECU。

请求报文格式:

请求:36H + 块序列号 + 数据块

其中:

  • 块序列号(1字节):从0x01开始递增。注意,不是从0x00开始。我刚开始做的时候就从0x00开始传,结果ECU回复NRC 0x13。查了半天文档才发现,规范里明确写了序列号从1开始。
  • 数据块:实际要写入的数据。长度不能超过34H响应中给出的“最大数据块长度”。

服务器收到36H请求后,会回复:

响应:76H + 块序列号

这个响应里的块序列号,是ECU期望你下一次发送的序列号。也就是说,ECU会告诉你:“我收到了第1块,你下次发第2块。”

这里有个细节:ECU在回复76H时,可能已经将数据写入了Flash,也可能只是暂存在RAM缓冲区里。具体行为取决于ECU的实现。我个人习惯的做法是,每发完一块数据,都检查一下ECU的响应时间。如果响应时间突然变长,说明ECU可能在擦除Flash或者写Flash,这时候不要急着发下一块,等ECU响应完再说。

避坑指南:我曾经遇到过一个问题——ECU的“最大数据块长度”是4096字节,但我每次发4096字节时,ECU偶尔会回复NRC 0x21(忙)。后来发现,ECU的接收缓冲区虽然能装4096字节,但它的处理速度跟不上。解决方案是:把块大小降到2048字节,问题就解决了。所以,不要迷信理论最大值,实际项目中要适当降低块大小,保证传输稳定性。

36H服务还有一个变种——你可以用36H来请求ECU上传数据。但咱们讲的是刷写,所以只讨论下载方向。

3.3 37H服务——请求退出传输

37H服务,全称是“Request Transfer Exit”。它的作用很简单:告诉ECU,数据传完了,你可以收工了。

请求报文格式:

请求:37H

没错,就一个字节。没有额外的参数。

服务器收到37H后,会回复:

响应:77H

但注意,ECU在回复77H之前,可能会做一些收尾工作,比如:

  • 检查数据的完整性(CRC校验)
  • 把RAM缓冲区里的数据刷入Flash
  • 更新程序的有效性标志

这些操作可能需要一些时间。我见过有些ECU,37H的响应时间长达5秒。如果你的刷写工具设置了超时时间,记得把这个时间设长一点,别因为超时而误判为失败。

重要提醒:37H服务执行成功后,ECU会退出“下载模式”。但此时程序还没有真正运行。通常还需要一个“复位”操作(11H服务)来让ECU启动新程序。所以,37H只是刷写流程的结束,不是整个OTA流程的结束。

3.4 三个服务的协作流程

咱们把这三个服务串起来,看看完整的刷写流程:

  1. 第一步:34H请求下载
    • 客户端发34H,告诉ECU要写数据了
    • ECU回复74H,告诉客户端最大块大小
  2. 第二步:循环36H传输数据
    • 客户端发36H,带块序列号和数据
    • ECU回复76H,确认收到并告知下一个序列号
    • 重复直到所有数据传完
  3. 第三步:37H请求退出传输
    • 客户端发37H,告诉ECU数据传完了
    • ECU回复77H,确认退出

这个流程看起来简单,但实际项目中,每一步都可能出问题。我列几个常见的坑:

问题 可能原因 解决方案
34H被拒(NRC 0x13) 数据格式标识符不支持 检查ECU支持的压缩/加密方式
36H响应超时 ECU正在写Flash,处理不过来 增大超时时间,或降低块大小
37H失败(NRC 0x22) 数据完整性校验失败 检查传输过程中是否有丢包或数据错误
刷写后程序跑不起来 地址或长度参数错误 仔细核对34H中的内存地址和大小

总结一下:34H、36H、37H这三个服务,是UDS刷写的基石。34H定规矩,36H搬数据,37H收尾。每一个服务都有它的细节和坑。我个人建议,在开发刷写工具时,先把这三个服务的交互逻辑调通,再考虑加密、压缩、安全访问等高级功能。基础不牢,地动山摇。

嗯,今天就聊到这儿。下一章咱们会讲安全访问服务(27H),这可是刷写流程中的“看门狗”,不搞定它,你连34H都发不出去。到时候见。