4. 升级协议设计
好,咱们进入第四章。这一章要啃的是UDS诊断协议,也就是ISO 14229-1。说实话,搞Bootloader升级,UDS就是你的“通用语言”。没有它,ECU和诊断仪之间就是鸡同鸭讲。
我最早接触UDS是在一个商用车项目上。那时候刚入行,看着一堆0x10、0x27、0x31的十六进制数,头都大了。后来摸透了才发现,UDS的套路其实很固定。说白了,它就是一套“请求-响应”的对话规则。
4.1 UDS协议栈与OSI模型
先看一张图,把UDS在CAN总线里的位置搞清楚。
从图里能看出来,UDS在第七层,也就是应用层。它不关心底层是CAN 2.0还是CAN FD,也不管数据怎么分包。这些脏活累活,都交给下面的传输层和网络层去干。
我个人习惯把UDS理解成“ECU的API”。你调用不同的服务ID(SID),ECU就执行对应的操作。比如0x10是切换会话,0x27是解锁安全等级,0x31是运行一段程序。
4.2 诊断会话控制 (0x10)
ECU上电后,默认处于一个“默认会话”。在这个会话里,很多诊断服务是被禁止的。你想刷写程序?不行。你想读内存?也不行。必须先切换到正确的会话模式。
会话控制服务0x10,就是用来干这个的。它的请求格式很简单:
请求: 0x10 + 子功能
响应: 0x50 + 子功能 + 附加参数
常见的子功能有这些:
| 子功能 | 会话名称 | 典型用途 | 我见过的坑 |
|---|---|---|---|
| 0x01 | 默认会话 | 上电后的初始状态 | 很多服务在这里不可用 |
| 0x02 | 编程会话 | Bootloader升级专用 | 必须切到这个会话才能刷写 |
| 0x03 | 扩展诊断会话 | 读故障码、标定等 | 有些ECU不支持这个会话 |
| 0x04 | 安全系统诊断会话 | 安全相关功能 | 很少用,但遇到就头疼 |
4.3 安全访问 (0x27)
你想想看,如果谁都能随便刷写ECU,那车还不得乱套?所以UDS设计了安全访问机制。说白了,就是一把锁。你得先证明你有钥匙,ECU才让你碰它的内存。
安全访问的流程是一个“挑战-应答”模式:
- 请求种子: 诊断仪发0x27 + 01(请求种子),ECU返回一个随机数(种子)。
- 计算密钥: 诊断仪用种子和算法算出密钥。
- 发送密钥: 诊断仪发0x27 + 02 + 密钥,ECU验证。
- 验证结果: 密钥正确,ECU返回0x67 + 02;错误,返回0x7F。
这里有个关键点:种子和密钥的算法,是OEM自己定义的。ISO 14229只规定了流程,没规定算法。所以不同车企的算法千奇百怪。
// 伪代码示例:安全访问流程
// 步骤1: 请求种子
Tx: 0x27 0x01
Rx: 0x67 0x01 [Seed_Byte0] [Seed_Byte1] ... [Seed_Byte3]
// 步骤2: 计算密钥 (算法由OEM定义)
Key = CalculateKey(Seed);
// 步骤3: 发送密钥
Tx: 0x27 0x02 [Key_Byte0] [Key_Byte1] ... [Key_Byte3]
Rx: 0x67 0x02 // 成功
// 或
Rx: 0x7F 0x27 0x35 // 失败,NRC=0x35 (无效密钥)
4.4 例程控制 (0x31)
例程控制,说白了就是让ECU执行一段预置好的程序。在Bootloader升级里,这个服务特别有用。比如擦除Flash、检查CRC、复位ECU,都可以通过例程控制来实现。
例程控制有三个子功能:
| 子功能 | 含义 | 典型例程ID | 说明 |
|---|---|---|---|
| 0x01 | 启动例程 | 0xFF00 | 擦除Flash扇区 |
| 0x02 | 停止例程 | 0xFF01 | 停止正在运行的例程 |
| 0x03 | 请求例程结果 | 0xFF02 | 检查例程执行状态 |
举个例子,擦除Flash的流程:
// 启动擦除例程
Tx: 0x31 0x01 0xFF 0x00 [StartAddress_H] [StartAddress_L] [Length_H] [Length_L]
Rx: 0x71 0x01 0xFF 0x00 // 例程已启动
// 等待一段时间后,请求结果
Tx: 0x31 0x03 0xFF 0x00
Rx: 0x71 0x03 0xFF 0x00 [Status] // Status=0x00 表示成功
4.5 负响应码 (NRC)
UDS里,不是所有请求都能成功。当ECU无法执行某个服务时,它会返回一个负响应。格式是0x7F + 请求SID + NRC。
常见的NRC码:
| NRC | 含义 | 常见原因 |
|---|---|---|
| 0x10 | 一般拒绝 | 请求格式错误 |
| 0x11 | 不支持 | ECU不支持这个服务 |
| 0x12 | 子功能不支持 | 会话不对,或子功能无效 |
| 0x22 | 条件不满足 | 比如没切到编程会话 |
| 0x31 | 请求超出范围 | 地址或长度参数错误 |
| 0x35 | 无效密钥 | 安全访问密钥错误 |
| 0x36 | 尝试次数超限 | 安全访问失败次数太多 |
| 0x37 | 超时 | 操作时间窗口已过 |
| 0x78 | 请求正确-响应待定 | ECU正在处理,稍后重试 |
4.6 本章小结
UDS诊断协议是Bootloader升级的“骨架”。0x10控制会话状态,0x27保障安全访问,0x31执行具体操作。这三板斧用好了,升级流程就顺了。
嗯,这里要注意:不同OEM对UDS的实现有差异。比如有些ECU要求先切到扩展会话,再切到编程会话;有些则可以直接切。所以拿到一个项目,第一件事就是看诊断规范文档,别想当然。