1. UDS诊断协议概述:OSI模型与汽车诊断、UDS协议标准ISO 14229、诊断会话模式与安全访问机制

大家好,我是老张。做汽车电子Bootloader开发十几年了,今天咱们来聊聊UDS诊断协议的基础。说实话,很多刚入行的朋友一上来就啃ISO 14229标准文档,几百页看下来头都大了。我个人的习惯是,先搞懂它为什么存在,再去看它怎么用。

1.1 OSI模型与汽车诊断

先问大家一个问题:为什么汽车诊断要扯上OSI七层模型?

你想想看,一辆车上有几十个ECU,它们通过CAN总线连在一起。诊断仪要跟某个ECU通信,中间得经过物理层、数据链路层、网络层……这不就是OSI模型干的事吗?

ISO 14229-1里明确说了,UDS协议主要工作在OSI模型的第5层(会话层)和第7层(应用层)。但实际开发中,我们更关心的是下面几层怎么配合。

OSI层 汽车诊断中的实现 我的经验
第7层 应用层 UDS服务(如0x22读数据、0x2E写数据) 这部分是咱们写代码最常打交道的
第6层 表示层 数据编码格式(Intel/Motorola) 踩过坑,字节序搞反了ECU直接不响应
第5层 会话层 诊断会话管理(默认/扩展/编程会话) 后面会详细讲,这里先记住
第4层 传输层 ISO 15765-2(CAN的传输层) 多帧传输的拆包组包就在这里
第3层 网络层 CAN ID过滤、路由 Bootloader里经常要处理物理寻址和功能寻址
第2层 数据链路层 CAN控制器(如M_CAN、SJA1000) 驱动层,我一般直接调芯片厂商的库
第1层 物理层 CAN收发器(如TJA1040) 硬件工程师的事,但出了问题也得一起查

核心要点:UDS协议不关心底层是CAN还是LIN还是以太网。它只定义「诊断仪和ECU之间怎么对话」。底层传输的事,交给ISO 15765、ISO 13400这些标准去管。

1.2 UDS协议标准ISO 14229

ISO 14229这个标准,全称是「道路车辆—统一诊断服务」。说白了,它就是一本汽车诊断的「对话手册」。

手册里规定了:

  • 诊断仪可以发哪些请求(比如读故障码、写数据、执行例程)
  • ECU应该怎么响应(肯定响应、否定响应)
  • 会话怎么建立、怎么切换
  • 安全怎么保障(安全访问)

我记得刚入行那会儿,师傅扔给我一本ISO 14229-1的PDF,说「看完这个就能写Bootloader了」。结果我啃了三天,连诊断会话模式都没搞明白。后来才发现,实际项目中常用的服务就那么十几个,没必要全背下来。

常用的UDS服务(刷写Bootloader必备):

  1. 0x10 - 诊断会话控制(切换会话模式)
  2. 0x27 - 安全访问(解锁ECU)
  3. 0x22 - 读取数据标识符(读版本号、序列号)
  4. 0x2E - 写入数据标识符(写配置参数)
  5. 0x31 - 例程控制(擦除Flash、检查编程条件)
  6. 0x34 - 请求下载(告诉ECU我要刷数据了)
  7. 0x36 - 传输数据(把数据一块一块发过去)
  8. 0x37 - 请求传输退出(结束数据传输)
  9. 0x3E - 测试仪在线(防止ECU超时退出会话)

我的小技巧:刚开始写Bootloader时,先把0x10、0x27、0x34、0x36、0x37这五个服务调通。其他的可以后面再加。我曾经在一个项目里只用了这五个服务就完成了刷写功能,客户验收也没问题。

1.3 诊断会话模式

ECU不可能一直处于「随便让人刷写」的状态。万一有人误操作把程序刷坏了怎么办?所以UDS定义了三种会话模式:

会话模式 SID (0x10的子功能) 用途 我的备注
默认会话 0x01 上电后的初始状态,只允许读操作 安全,但啥也干不了
扩展会话 0x03 允许读写操作,但禁止刷写 常用于标定、配置参数
编程会话 0x02 允许刷写Flash,Bootloader的核心模式 进入后要小心,别断电

这里有个关键点:会话模式是有超时机制的。ECU如果在S3Server时间内(通常是5秒)没收到任何诊断请求,会自动跳回默认会话。这就是为什么刷写过程中要定时发0x3E服务。

避坑指南:我曾经在一个项目里,刷写到一半网络突然卡了,0x3E没发出去。ECU自动退出编程会话,Flash写入到一半的数据全废了。从那以后,我都在刷写循环里加了个定时器,每2秒强制发一次0x3E,宁可多发也不能漏发。

1.4 安全访问机制

光有会话模式还不够。万一有人进入了编程会话,但他是恶意攻击者呢?所以UDS又加了一层安全访问机制(0x27服务)。

安全访问的流程是这样的:

  1. 诊断仪发0x27 0x01(请求种子)
  2. ECU返回一个随机种子(比如4字节的随机数)
  3. 诊断仪用约定的算法计算密钥
  4. 诊断仪发0x27 0x02(发送密钥)
  5. ECU验证密钥,正确则解锁,错误则锁定一段时间

这个算法可以是任何东西:简单的异或、AES加密、自定义的查表法。我见过最奇葩的是一个项目里用MD5取前4字节当密钥,虽然不安全但够用了。

重要提醒:安全访问的种子和密钥算法,在量产车上是保密的。但在Bootloader开发阶段,我建议先用一个简单的算法(比如种子+固定值),等调试通过后再换成正式算法。不然算法写错了,连自己都解锁不了ECU,那就尴尬了。

嗯,这里还要注意一点:安全访问是有次数限制的。ISO 14229规定,如果连续输错密钥,ECU应该增加延迟时间。比如第一次输错等1秒,第二次等2秒,第三次等4秒……我见过有些ECU直接锁死,必须重新上电才能解锁。

好了,这一章的内容就这些。总结一下:

  • OSI模型帮我们理解UDS在汽车网络中的位置
  • ISO 14229定义了诊断服务的「语法」和「语义」
  • 会话模式控制ECU的「权限等级」
  • 安全访问机制防止「非法操作」

下一章,咱们会深入Bootloader的架构设计,讲讲怎么在Flash里安排程序空间、怎么处理跳转。到时候我会分享一个我踩过的坑——跳转时忘了关中断,结果程序跑飞了。敬请期待。