4、通信协议基础(UDS on CAN):ISO 14229-1概述、诊断会话控制、安全访问机制

各位同学,今天我们聊点硬核的——UDS on CAN。说实话,很多工程师做了好几年Bootloader,对UDS的理解还停留在“发个报文、收个响应”的层面。但真正遇到问题的时候,比如会话切不过去、安全访问死活过不了,你就知道基础不牢有多痛苦了。

我个人习惯,讲协议一定要先讲“为什么”。UDS(统一诊断服务)说白了就是汽车电子设备的“通用语言”。不管你是ECU、TCU还是BCM,大家用同一套规则对话。ISO 14229-1就是这本“语法书”。

4.1 ISO 14229-1概述:UDS的骨架

ISO 14229-1定义了UDS的服务、子功能、格式和时序。它不关心底层是CAN、LIN还是以太网,只关心“应用层”怎么说话。

一个典型的UDS报文长这样:

| 字节0 | 字节1 | 字节2...N |
| 服务ID | 子功能 | 数据参数 |

举个例子,读取ECU的软件版本号:

请求:22 F1 90
响应:62 F1 90 01 02 03 04

这里0x22是“读取数据通过标识符”的服务ID,0xF190是数据标识符。响应里的0x62是肯定响应,后面跟着数据。

核心要点:UDS服务分为6大类,共26个服务。Bootloader开发中,你至少需要掌握:诊断会话控制(0x10)、安全访问(0x27)、写入数据(0x2E)、例程控制(0x31)、请求下载(0x34)、传输数据(0x36)、请求退出传输(0x37)。

我在项目中遇到过,有些工程师把服务ID和子功能搞混。比如0x10是服务ID,0x01/0x02/0x03才是子功能(对应不同会话)。千万别写反了,否则ECU直接给你回个否定响应。

4.2 诊断会话控制:ECU的“工作模式”

ECU不是一直都能刷写的。它有不同的“工作模式”,UDS里叫诊断会话。通过0x10服务来切换。

常见的会话模式:

子功能 会话名称 说明
0x01 默认会话 上电后的初始状态,功能受限
0x02 编程会话 允许刷写、解锁等操作
0x03 扩展诊断会话 允许更多诊断功能,但不允许刷写

切换会话的报文格式:

请求:10 02          // 切换到编程会话
响应:50 02 00 32 00 // 肯定响应,后面是P2和P2*定时参数

避坑指南:我曾经在项目里遇到一个问题——ECU在默认会话下发送了刷写请求,结果ECU直接不理我。后来才发现,刷写必须在编程会话下进行。而且,从默认会话切换到编程会话,有些ECU需要先进入扩展会话,再进编程会话。这个顺序,不同芯片厂商要求不一样,一定要看数据手册。

为什么要有会话机制?你想想看,如果随便一个诊断仪都能刷写ECU,那车在路上跑着突然被人远程刷了,多危险。会话控制就是第一道安全门。

4.3 安全访问机制:ECU的“门禁系统”

光有会话控制还不够。编程会话虽然开放了刷写权限,但谁都能进?不行。还得有“钥匙”——安全访问机制(0x27服务)。

安全访问的流程,说白了就是“挑战-应答”:

  1. 诊断仪发送“请求种子”报文
  2. ECU返回一个随机种子(通常是4字节)
  3. 诊断仪用特定算法计算密钥
  4. 诊断仪发送“发送密钥”报文
  5. ECU验证密钥,通过则解锁

报文示例:

// 第一步:请求种子(安全等级1)
请求:27 01
响应:67 01 12 34 56 78  // 种子是0x12345678

// 第二步:发送密钥
请求:27 02 9A BC DE F0  // 密钥是计算后的结果
响应:67 02              // 肯定响应,解锁成功

重要提醒:安全算法是OEM(整车厂)的核心机密。不同OEM的算法完全不同,有的用AES,有的用自定义的异或+查表。千万不要在公开代码里暴露算法细节。我曾经见过一个项目,因为算法泄露,导致某车型被第三方随意刷写,最后整车厂不得不召回所有ECU升级安全逻辑。

这里有个细节:安全等级。0x27服务支持多个安全等级(子功能0x01-0x05对应请求种子,0x02-0x06对应发送密钥)。等级1通常用于刷写,等级2用于更敏感的操作。我个人习惯,在Bootloader里至少实现两个等级,一个给产线用,一个给售后用。

还有一个容易踩的坑:种子有效时间。ECU生成种子后,通常有个超时计时器(比如5秒)。如果诊断仪5秒内没发回正确的密钥,种子就失效了,必须重新请求。我刚开始做的时候,调试工具发送太慢,老是超时,折腾了两天才发现是计时器的问题。

4.4 实际开发中的注意事项

讲到这里,我总结几个实战经验:

  • 会话保持:ECU在编程会话下,如果长时间没有诊断请求,会自动跳回默认会话。所以刷写过程中要定时发送“Tester Present”(0x3E服务)保持会话。
  • 安全访问失败处理:ECU通常有失败计数器。连续输错3次密钥,ECU会锁定一段时间(比如30秒)。这个机制是为了防止暴力破解。
  • 时序参数:P2和P2*定时参数在会话切换响应里返回。P2是ECU处理请求的最大时间,P2*是扩展时间。如果诊断仪在P2时间内没收到响应,可以重发请求。

一句话总结:UDS on CAN是Bootloader的“通信语言”。会话控制决定了ECU“能做什么”,安全访问决定了“谁来做”。这两个机制配合好了,刷写流程就成功了一半。

下一章,我们会深入讲解刷写流程的核心——0x34请求下载、0x36传输数据和0x37请求退出传输。到时候我会结合一个实际的刷写案例,带大家走一遍完整的流程。

嗯,今天就到这里。有问题随时问我。