3. 刷写流程核心服务:诊断会话控制(0x10)、安全访问(0x27)、诊断故障码读取(0x19)、写入数据(0x2E)、例程控制(0x31)

好,咱们直接进入正题。刷写流程里,有五个服务是绕不开的。我常说它们是Bootloader的“五虎上将”。少了哪一个,刷写流程都跑不起来。

这五个服务分别是:诊断会话控制(0x10)安全访问(0x27)诊断故障码读取(0x19)写入数据(0x2E)例程控制(0x31)

今天我就把这五个服务的核心要点、实现细节、还有我踩过的坑,一次性给你讲透。

3.1 诊断会话控制 (0x10) —— 刷写的“入场券”

说白了,0x10服务就是告诉ECU:“我要开始干活了,你准备好没?”

ECU平时可能跑在默认会话里,只响应一些基本诊断请求。但刷写需要更高级的权限,比如解锁内存、执行擦除操作。这时候,你就得通过0x10服务切换到编程会话

我个人习惯把会话切换分成三步:

  1. 请求切换:发送0x10 02,请求进入编程会话。
  2. ECU响应:ECU返回肯定响应或否定响应。
  3. 应用层准备:ECU内部会停止应用任务,初始化刷写环境。

核心要点:

  • 编程会话下,ECU会禁用一些非必要的通信,比如CAN报文。
  • 如果切换失败,ECU会返回NRC 0x12(子功能不支持)或0x22(条件不满足)。
  • 我建议你在切换前,先检查ECU当前会话状态,避免重复切换。

嗯,这里要注意。有些ECU在编程会话下会关闭DTC存储功能。你想想看,刷写过程中产生一堆故障码,那多麻烦。

3.2 安全访问 (0x27) —— 刷写的“钥匙”

0x27服务,说白了就是一把锁。ECU不想让随便什么人都能刷写,所以你得先证明你是“自己人”。

安全访问的流程,我记得在项目里调试过无数次:

  1. 请求种子:发送0x27 01,请求种子。
  2. ECU返回种子:ECU返回一串随机数(种子)。
  3. 计算密钥:Tester用种子和算法算出密钥。
  4. 发送密钥:发送0x27 02,带上密钥。
  5. ECU验证:ECU比对密钥,通过则解锁。

避坑指南:

我曾经遇到过一个问题:种子请求次数过多,ECU会进入“锁定状态”。这时候你必须等待一段时间,或者断电重启才能继续。所以,我建议你在Tester端做好重试机制,比如最多尝试3次,失败后等待30秒。

为什么要有安全访问?说白了,就是防止误刷写。你想想看,如果随便一个诊断仪都能刷写,那ECU岂不是乱套了?

3.3 诊断故障码读取 (0x19) —— 刷写的“体检报告”

0x19服务,用来读取ECU的故障码。刷写前读一下,刷写后再读一下,对比一下,就知道刷写过程有没有产生新问题。

我个人习惯在刷写流程里加入两次0x19请求:

  • 刷写前:读取当前故障码,记录状态。
  • 刷写后:再次读取,确认没有新增故障码。

这里有个细节:刷写过程中,ECU可能会因为断电、通信中断等原因产生临时故障码。这些故障码在刷写完成后,应该被清除。所以,0x19服务通常和0x14(清除诊断信息)配合使用。

注意:

不要以为0x19只是读故障码那么简单。有些ECU在编程会话下,会屏蔽故障码存储。这时候你读到的故障码,可能不是真实状态。我建议你在刷写完成后,先切换到默认会话,再读取故障码。

3.4 写入数据 (0x2E) —— 刷写的“笔”

0x2E服务,用来写入数据到ECU。刷写过程中,你写入的是固件数据、配置参数、或者密钥。

写入数据的流程,其实很简单:

  1. 请求写入:发送0x2E,带上DID(数据标识符)和数据。
  2. ECU响应:ECU返回肯定响应或否定响应。
  3. 数据存储:ECU将数据写入指定地址。

嗯,这里要注意。0x2E服务写入的数据,通常是非易失性存储器(比如Flash或EEPROM)。所以,写入操作一定要小心,写错了可能导致ECU变砖。

核心要点:

  • 写入数据前,最好先读取当前数据,确认状态。
  • 写入完成后,再读取一次,验证数据是否正确。
  • 我建议你在写入过程中,加入CRC校验,确保数据完整性。

我记得有一次,客户反馈刷写后ECU无法启动。排查了半天,发现是0x2E写入的配置参数错了。从那以后,我每次写入数据都会做两次校验:一次在写入前,一次在写入后。

3.5 例程控制 (0x31) —— 刷写的“执行器”

0x31服务,用来执行ECU内部的特定程序。刷写过程中,最常用的例程就是擦除Flash检查编程完整性

例程控制的流程:

  1. 请求启动例程:发送0x31 01,带上例程ID。
  2. ECU执行:ECU开始执行例程,比如擦除Flash。
  3. ECU返回结果:执行完成后,ECU返回肯定响应或否定响应。

我个人习惯把例程控制分成三类:

  • 启动例程:开始执行。
  • 停止例程:中断执行。
  • 请求结果:查询执行状态。

避坑指南:

我曾经遇到过一个问题:擦除Flash的例程执行时间很长,超过了Tester的超时时间。结果Tester以为例程失败了,又发了一次擦除请求。这下好了,ECU同时执行两个擦除操作,直接死机。

所以,我建议你在Tester端设置合理的超时时间,或者在例程执行期间,定期发送“请求结果”来查询状态。

为什么例程控制这么重要?你想想看,刷写过程中,擦除Flash、写入数据、校验完整性,这些操作都需要ECU内部程序来执行。0x31服务就是用来调用这些程序的。

3.6 五个服务的协同工作

这五个服务不是孤立的。它们需要按照一定的顺序协同工作,才能完成一次完整的刷写流程。

我总结了一个典型的刷写流程:

  1. 会话控制 (0x10):切换到编程会话。
  2. 安全访问 (0x27):解锁ECU。
  3. 故障码读取 (0x19):记录刷写前的故障码。
  4. 例程控制 (0x31):擦除Flash。
  5. 写入数据 (0x2E):写入固件数据。
  6. 例程控制 (0x31):检查编程完整性。
  7. 故障码读取 (0x19):确认刷写后没有新增故障码。

核心要点:

这个流程不是固定的。有些ECU可能需要在写入数据前,先执行一些初始化例程。有些ECU可能需要在刷写完成后,重新上电才能生效。所以,你一定要根据具体的ECU规范来调整流程。

好了,这五个服务就讲到这里。下一章,我会带你深入刷写流程的细节,看看数据是怎么从Tester传到ECU的。