3. DoIP报文格式详解
好,咱们进入正题。DoIP的报文格式,说白了就是车上的ECU之间怎么「说话」的规矩。我当年刚接触这个协议时,看着那一串十六进制数也是头大。但摸清楚套路后,你会发现它其实挺有逻辑的。
3.1 通用报文头
每个DoIP报文,开头都带一个通用报文头。就像你寄快递,总得先写个快递单吧?这个头就是快递单。
| 字段 | 长度(字节) | 说明 |
|---|---|---|
| 协议版本 | 1 | 当前固定为0x02(ISO 13400-2) |
| 反向协议版本 | 1 | 取反,用于校验,0xFD |
| 负载类型 | 2 | 标识后面跟着的是什么报文 |
| 负载长度 | 4 | 后面数据的字节数 |
我个人习惯,拿到一个DoIP报文,先看前4个字节。协议版本不对?直接扔掉。负载类型不对?说明不是我要的消息。嗯,这里要注意,负载长度是4字节的大端序,别搞反了。
负载类型常见值:
- 0x0001:诊断报文(UDS over DoIP)
- 0x0002:诊断确认报文
- 0x0003:AliveCheck请求
- 0x0004:AliveCheck响应
- 0x0005:路由激活报文
3.2 诊断报文
诊断报文,这是咱们最常用的。说白了就是把UDS请求包在DoIP里发出去。格式如下:
| 通用报文头 (8字节) | 源地址 (2字节) | 目标地址 (2字节) | UDS数据 (N字节) |
源地址和目标地址,就是逻辑地址。比如诊断仪是0x0E80,某个域控制器是0x1001。我在项目中遇到过,有人把源和目标写反了,结果ECU死活没响应。你想想看,地址都错了,车能理你吗?
我的经验:UDS数据部分,就是标准的ISO 14229-1请求。比如0x10 03代表诊断会话控制,0x22 F1 90代表读取VIN码。DoIP只负责传输,不关心UDS内容。
3.3 诊断确认报文
这个报文,是接收方告诉你「我收到了你的诊断请求」。注意,它不是UDS响应,而是DoIP层的确认。
| 通用报文头 (8字节) | 源地址 (2字节) | 目标地址 (2字节) | 确认码 (1字节) | 预留 (3字节) |
确认码很关键:
- 0x00:成功,正常处理
- 0x01:目标地址不可达
- 0x02:源地址未知
- 0x03:消息太大,装不下
- 0x04:其他错误
我曾经调试一个域控制器,发现诊断仪发了请求,ECU也回了确认,但就是没有UDS响应。查了半天,原来是确认码是0x01,目标地址不可达。嗯,路由表没配好,白忙活一场。
3.4 AliveCheck请求/响应
AliveCheck,直译就是「活着吗?」。DoIP节点之间需要定期确认对方还在线。这个机制我特别喜欢,因为它简单粗暴有效。
AliveCheck请求:
| 通用报文头 (8字节) | 源地址 (2字节) |
负载类型是0x0003,源地址就是发送方的逻辑地址。
AliveCheck响应:
| 通用报文头 (8字节) | 源地址 (2字节) | 目标地址 (2字节) |
负载类型是0x0004,目标地址就是请求方的地址。
避坑指南:我曾经遇到过一个情况,域控制器在发送AliveCheck响应时,把目标地址填成了自己的地址。结果诊断仪一直收不到响应,以为节点挂了。后来发现是代码里地址赋值搞反了。所以,写代码时一定要仔细核对源和目标。
AliveCheck的发送间隔,一般是2-5秒。如果连续3次没收到响应,就认为对方离线了。这个超时时间,我建议根据实际网络负载调整。网络忙的时候,适当放宽一点。
3.5 路由激活报文
路由激活,是DoIP通信的第一步。诊断仪想跟某个ECU通信,必须先激活路由。就像你进小区,得先跟保安打个招呼吧?
| 通用报文头 (8字节) | 源地址 (2字节) | 目标地址 (2字节) | 激活类型 (1字节) | 预留 (5字节) | OEM特定数据 (可选) |
激活类型:
- 0x00:默认激活
- 0x01:带安全认证的激活
- 0x02-0xFF:OEM自定义
路由激活的响应报文,格式类似,但多了个响应码:
- 0x00:激活成功
- 0x01:目标地址不可达
- 0x02:源地址已被占用
- 0x03:认证失败
- 0x04:资源不足
我的建议:在智能驾驶域控制器中,路由激活一定要做安全认证。你想想看,如果随便一个设备都能激活路由,那车上的数据不就裸奔了吗?我参与的一个项目,就因为没有做认证,被测试团队发现了一个严重的安全漏洞。后来我们加上了基于证书的认证,才通过评审。
好了,DoIP的报文格式就这些。说白了就是:通用头打底,负载类型定方向,后面跟着具体数据。你只要记住这五个报文类型,DoIP通信的基本框架就掌握了。下一章,咱们聊聊这些报文在实际的智能驾驶域控制器中是怎么流转的。