第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里写数据,那车还不得乱套?
流程是这样的:
- 诊断仪发0x27 01(请求种子)
- ECU返回种子(比如4字节随机数)
- 诊断仪用算法算出密钥,发0x27 02(发送密钥)
- 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这三个服务的细节,以及怎么处理大数据块传输。到时候我会分享一些实际项目中的优化技巧。