第3章:UDS协议基础:ISO 14229标准、诊断会话控制、安全访问、服务标识符(SID)概览

好,咱们进入UDS协议。说实话,这是整个Bootloader开发里最绕不开的一块。你想想看,ECU刷写、诊断、标定,底层通信全靠它。ISO 14229这个标准,我最早接触是在2015年做的一个国六项目,当时被各种Session和Security Access搞得头大。后来摸透了,发现其实核心就那么几个点。

3.1 ISO 14229标准概览

UDS,全称是Unified Diagnostic Services。它定义了一套统一的诊断服务规则。说白了,就是告诉ECU和诊断仪之间怎么说话、说什么话。

这个标准覆盖了从物理层到应用层的规范。但咱们做Bootloader开发,最关心的是应用层。也就是服务ID(SID)、子功能、数据参数这些。

我个人习惯把UDS服务分成三类:

  • 诊断管理类:会话控制、安全访问、复位、读取DTC等
  • 数据传输类:读取数据、写入数据、例程控制等
  • 存储类:写入内存、擦除内存、检查编程完整性等

嗯,这里要注意,刷写流程主要用的是存储类和诊断管理类。数据传输类偶尔也会用到,比如读取刷写进度。

3.2 诊断会话控制(0x10服务)

这个服务,SID是0x10。它的作用就是切换ECU的工作模式。ECU平时跑应用软件,你发个0x10 02,它就进入编程会话,准备接收刷写数据。

我记得第一次做刷写测试时,忘了发会话切换指令,直接发刷写请求,ECU直接NRC拒绝。后来养成习惯,刷写前必发0x10 02。

常见的子功能有:

子功能 含义 典型用途
0x01 默认会话 上电后的默认模式
0x02 编程会话 刷写Bootloader或应用
0x03 扩展诊断会话 标定、读取特定数据

重要提醒:编程会话下,ECU会关闭一些非必要的通信和功能,比如CAN报文发送频率降低。这是为了确保刷写过程稳定。

3.3 安全访问(0x27服务)

安全访问,SID是0x27。它的目的是防止非法刷写。你想想看,如果谁都能往ECU里写数据,那车还不得乱套?

流程是这样的:

  1. 诊断仪发0x27 01(请求种子)
  2. ECU返回种子(比如4字节随机数)
  3. 诊断仪用算法算出密钥,发0x27 02(发送密钥)
  4. ECU验证密钥,通过则解锁

我曾经在一个项目里遇到过坑:种子和密钥的算法是客户提供的,但文档里写的是大端模式,实际ECU用的是小端。结果密钥死活对不上。后来抓CAN报文才发现问题。所以,做安全访问时,一定要确认字节序。

我的建议:开发阶段可以先把安全访问关掉,或者用固定种子。等刷写流程调通了,再开启安全校验。这样能省不少调试时间。

3.4 服务标识符(SID)概览

SID就是每个服务的身份证。UDS标准里定义了很多SID,但Bootloader刷写常用的就那么几个。我列个表,你记一下:

SID 服务名称 刷写中的用途
0x10 诊断会话控制 进入编程会话
0x27 安全访问 解锁刷写权限
0x28 通信控制 关闭非刷写相关通信
0x31 例程控制 执行擦除、检查等操作
0x34 请求下载 开始数据传输
0x36 传输数据 发送刷写数据块
0x37 请求传输退出 结束数据传输
0x11 ECU复位 刷写完成后复位ECU

你看,刷写流程其实就是这几个SID的组合拳。先0x10进会话,再0x27解锁,然后0x34请求下载,0x36传数据,0x37结束,最后0x11复位。是不是很清晰?

3.5 负响应码(NRC)

有请求就有响应。如果ECU不支持某个服务,或者条件不满足,它会回一个负响应。NRC的格式是0x7F + SID + NRC码。

常见的NRC码:

  • 0x12:子功能不支持。比如你发0x10 05,ECU没有这个会话。
  • 0x22:条件不满足。比如没进编程会话就发刷写请求。
  • 0x31:请求超出范围。比如数据长度不对。
  • 0x35:安全访问被拒绝。密钥错误。
  • 0x78:请求正确,但正在处理。ECU需要更多时间。

避坑指南:我曾经遇到一个ECU,刷写时偶尔回0x78。一开始以为是bug,后来发现是ECU在擦Flash时耗时较长,需要多发几个请求。解决方案是增加超时重试机制,并处理0x78响应。

3.6 实际刷写中的UDS交互示例

咱们看一个简化的刷写交互流程。假设你要刷写一个应用软件:

诊断仪 -> ECU: 0x10 02 (请求编程会话)
ECU -> 诊断仪: 0x50 02 (肯定响应)

诊断仪 -> ECU: 0x27 01 (请求种子)
ECU -> 诊断仪: 0x67 01 AA BB CC DD (返回种子)

诊断仪 -> ECU: 0x27 02 11 22 33 44 (发送密钥)
ECU -> 诊断仪: 0x67 02 (解锁成功)

诊断仪 -> ECU: 0x34 00 44 00 00 10 00 (请求下载,地址0x1000,长度0x1000)
ECU -> 诊断仪: 0x74 20 00 (同意下载,块大小0x200)

诊断仪 -> ECU: 0x36 01 [数据块1] (传输数据)
ECU -> 诊断仪: 0x76 01 (肯定响应)

... (重复传输直到数据发完)

诊断仪 -> ECU: 0x37 (请求退出传输)
ECU -> 诊断仪: 0x77 (肯定响应)

诊断仪 -> ECU: 0x11 01 (请求硬复位)
ECU -> 诊断仪: 0x51 01 (肯定响应,然后复位)

你看,整个过程就是一问一答。每个步骤都有明确的SID和响应。只要按照这个流程走,刷写基本不会出问题。

好了,UDS协议基础就讲到这里。下一章咱们会深入讲0x34、0x36、0x37这三个服务的细节,以及怎么处理大数据块传输。到时候我会分享一些实际项目中的优化技巧。