2、烧录协议基础:UDS协议简介、基于CAN的刷写流程、基于以太网的刷写流程
各位同学,咱们今天聊聊烧录协议的基础。说实话,很多刚入行的工程师觉得协议就是一堆报文,背下来就行了。但我不这么看。协议背后是通信的逻辑,是ECU和工具之间的“对话规则”。你搞懂了规则,遇到任何奇葩问题都能找到根因。
2.1 UDS协议简介:诊断与刷写的通用语言
UDS,全称是Unified Diagnostic Services,统一诊断服务。它定义在ISO 14229标准里。说白了,就是汽车电子设备之间怎么“说话”的一套规矩。
我个人习惯把UDS理解成“汽车界的HTTP协议”。HTTP有GET、POST这些方法,UDS也有自己的“服务ID”(SID)。比如0x10是诊断会话控制,0x22是读取数据,0x2E是写入数据。刷写固件时,我们最常用的是0x34(请求下载)、0x36(传输数据)、0x37(请求退出传输)。
核心要点:UDS是面向连接的、请求-响应的协议。工具发请求,ECU给响应。响应里有个“否定响应码”(NRC),告诉你为什么不行。比如0x31表示请求超出范围,0x78表示正在处理,请稍等。
我在项目中遇到过一件事。有个同事刷写时总失败,日志里全是0x31。他查了半天没头绪。我过去一看,发现他发送的“请求下载”报文里,内存地址写错了。ECU说“你让我写的地址我不认识”,所以一直拒绝。嗯,这就是典型的“请求超出范围”。
2.2 基于CAN的刷写流程:经典但依然主流
CAN总线在汽车里用了三十多年了。虽然现在以太网越来越火,但CAN刷写依然是量产线上的主力。为什么?成本低、稳定、成熟。
基于CAN的刷写流程,大致分这么几步:
- 建立诊断会话:发送0x10 03,让ECU进入扩展诊断会话。这是刷写的前提。
- 安全访问:发送0x27,通过种子-密钥验证。这是防盗机制,防止随便谁都能刷写。
- 请求下载:发送0x34,告诉ECU我要写数据了,写到哪里,写多大。
- 传输数据:发送0x36,把固件数据分包发送。CAN一帧最多8字节,所以需要拆包。
- 请求退出传输:发送0x37,告诉ECU数据发完了。
- 检查完整性:发送0x31 01 FF 00,请求ECU执行完整性检查(比如CRC校验)。
- 复位ECU:发送0x11 01,让ECU软复位,加载新固件。
避坑指南:我曾经在量产线上遇到过一个坑。CAN刷写时,工具发送0x36的速度太快,ECU来不及处理,直接丢包了。后来我加了一个“流控机制”——每发完一包,等ECU回复0x78(正忙),再发下一包。问题就解决了。记住,ECU不是PC,它的处理能力有限。
这里给个简单的CAN刷写报文示例:
// 请求下载(0x34)
发送: 02 34 00 44 00 00 10 00 // 数据长度=0x1000字节
接收: 03 74 20 00 AA // 响应:成功,块大小=0x20字节
// 传输数据(0x36)
发送: 10 0C 36 01 00 00 00 00 // 第一帧,数据长度=12字节
发送: 21 01 02 03 04 05 06 07 // 后续帧
接收: 03 76 20 00 AA // 响应:成功
// 请求退出传输(0x37)
发送: 01 37
接收: 03 77 20 00 AA // 响应:成功
你想想看,CAN刷写最麻烦的就是分包。固件动辄几兆字节,每包最多7字节有效数据(CAN标准帧数据域8字节,但UDS协议头占1字节)。所以刷写一个2MB的固件,需要发送约30万帧。这还不算等待响应的时间。所以量产时,CAN刷写速度通常只有几十KB/s。
2.3 基于以太网的刷写流程:高速时代的必然选择
随着ADAS系统越来越复杂,固件体积也越来越大。一个完整的ADAS固件,动辄几百兆甚至上GB。用CAN刷写?那得等到天荒地老。所以以太网刷写应运而生。
基于以太网的刷写,核心协议是DoIP(Diagnostic over Internet Protocol),定义在ISO 13400标准里。说白了,就是把UDS报文封装在TCP/IP包里传输。
DoIP刷写的流程和CAN刷写类似,但有几个关键区别:
| 对比项 | CAN刷写 | DoIP刷写 |
|---|---|---|
| 传输层 | CAN总线 | TCP/IP |
| 单帧数据量 | 最多8字节 | 最多64KB(TCP分段) |
| 典型速度 | 50-100 KB/s | 1-10 MB/s |
| 连接方式 | 广播/点对点 | 点对点(TCP连接) |
| 地址分配 | CAN ID | IP地址+端口 |
DoIP刷写的流程大致如下:
- 车辆发现:工具发送广播报文,ECU回复自己的IP地址和逻辑地址。
- 建立TCP连接:工具连接ECU的DoIP端口(默认13400)。
- 路由激活:发送路由激活请求,告诉ECU我要开始诊断了。
- 建立诊断会话:和CAN一样,发送0x10 03。
- 安全访问:和CAN一样,发送0x27。
- 请求下载:发送0x34,但数据长度可以很大。
- 传输数据:发送0x36,但每包可以发4096字节甚至更多。
- 请求退出传输:发送0x37。
- 检查完整性:发送0x31。
- 复位ECU:发送0x11 01。
注意:DoIP刷写虽然快,但有个坑——TCP的粘包问题。工具发送数据时,如果连续发送多个0x36报文,TCP协议可能会把它们合并成一个包发送。ECU收到后,如果解析逻辑写得不好,就会把两个报文当成一个来处理,导致解析错误。我建议在应用层加一个简单的分隔符,或者严格控制发送间隔。
我记得有一次,客户反馈说以太网刷写偶尔会失败。我抓包一看,发现工具发送的0x36报文被TCP合并了。ECU那边解析时,把两个报文的数据域拼在一起了,结果校验失败。后来我在工具端加了一个“发送后等待100ms”的逻辑,问题就解决了。虽然牺牲了一点速度,但稳定性上去了。
2.4 总结:选CAN还是选以太网?
这个问题没有标准答案。我个人建议:
- 固件小于10MB:用CAN刷写就够了。成本低,工具链成熟。
- 固件大于100MB:必须用DoIP。否则量产线会卡死。
- 介于两者之间:看你的量产节拍。如果每辆车刷写时间超过5分钟,建议上DoIP。
好了,这一章就到这里。下一章我们会深入UDS的细节,包括每个服务的报文格式和状态机。到时候我会分享一些我在量产线上踩过的坑,保证让你少走弯路。