2、诊断会话控制:默认会话、扩展会话、编程会话的切换机制与状态机
好,咱们接着聊。上一章我们把UDS的整体框架搭起来了,这一章我打算深入一个非常核心的机制——诊断会话控制。
说白了,ECU不是什么时候都听你使唤的。它有自己的“工作状态”,也就是会话模式。你想想看,如果车辆在高速行驶时,你一个诊断指令过去让它刷写程序,那不出大事了?所以,UDS定义了三种基本会话:默认会话、扩展会话和编程会话。它们之间的切换,有一套严格的状态机逻辑。
2.1 三种会话模式,各司其职
我们先搞清楚这三种会话是干嘛的。
| 会话模式 | 会话ID (SID) | 主要用途 | 我个人的理解 |
|---|---|---|---|
| 默认会话 (Default Session) | 0x01 | 上电后的初始状态,只允许读取基本信息(如VIN码、故障码) | ECU的“待机模式”,安全第一 |
| 扩展会话 (Extended Session) | 0x03 | 允许执行一些非安全关键的功能,如读写数据、执行例程 | ECU的“调试模式”,可以动动手脚了 |
| 编程会话 (Programming Session) | 0x02 | 允许刷写程序、更新固件,这是最高权限模式 | ECU的“手术模式”,动刀子的时候 |
嗯,这里要注意。默认会话是ECU上电后自动进入的。你想想看,如果一上电就进入编程会话,那万一有恶意指令,ECU就裸奔了。所以,默认会话是最安全的,权限最低。
2.2 切换机制:一条指令搞定
切换会话,靠的是诊断会话控制 (Diagnostic Session Control, 0x10) 服务。它的请求格式很简单:
请求:0x10 + 目标会话ID
例如:切换到扩展会话 -> 发送 0x10 0x03
例如:切换到编程会话 -> 发送 0x10 0x02
ECU收到后,如果允许切换,就会回复一个肯定响应:
响应:0x50 + 目标会话ID
例如:成功切换到扩展会话 -> 回复 0x50 0x03
是不是很简单?但实际项目中,坑往往不在指令本身,而在切换的时机和条件。
核心要点: 切换会话不是无条件的。ECU内部有一个状态机,它会根据当前会话、安全状态、以及是否正在执行其他服务,来决定是否允许切换。
2.3 状态机:会话切换的“交通规则”
我画个简单的状态机图,你感受一下:
状态机示意:
[默认会话] --(0x10 0x03)--> [扩展会话]
[默认会话] --(0x10 0x02)--> [编程会话]
[扩展会话] --(0x10 0x01)--> [默认会话]
[扩展会话] --(0x10 0x02)--> [编程会话]
[编程会话] --(0x10 0x01)--> [默认会话]
[编程会话] --(0x10 0x03)--> [扩展会话] // 这个路径,有些ECU不支持
你看,从默认会话可以直接跳到编程会话,也可以跳到扩展会话。但从编程会话跳回默认会话,是允许的。不过,从编程会话直接跳到扩展会话,这个路径在有些ECU实现中是被禁止的。为什么?
我个人习惯是,在编程会话结束后,先切回默认会话,再根据需要切到扩展会话。这样最保险,不会触发ECU的“非法状态转换”错误。
2.4 避坑指南:我踩过的那些雷
我曾经在一个项目中,遇到一个很奇怪的问题。刷写程序时,明明发送了0x10 0x02,ECU也回复了0x50 0x02,但紧接着发送刷写指令,ECU就报错“服务不支持”。
排查了半天,发现是ECU内部有一个会话超时定时器。默认会话下,这个定时器是关闭的。但一旦切换到编程会话,定时器就开始计时。如果在一定时间内(比如5秒)没有收到任何有效的诊断请求,ECU会自动切回默认会话。
我当时就是发送完切换指令后,停顿了几秒才发刷写指令,结果定时器超时了,ECU已经悄悄回到了默认会话。嗯,从那以后,我写代码时都会在切换会话后,立即发送下一条指令,不给定时器超时的机会。
警告: 编程会话通常有严格的超时限制。如果超时,ECU会自动退出编程会话,回到默认会话。这会导致后续的刷写操作全部失败。所以,切换后要尽快执行操作。
2.5 实战中的小技巧
最后,分享几个我在项目中常用的技巧:
- 先切扩展,再切编程: 有些ECU要求必须先进入扩展会话,才能进入编程会话。虽然标准没这么规定,但很多厂商的私有协议会这么要求。我建议你养成这个习惯,兼容性更好。
- 检查响应中的子功能: 响应0x50后面跟着的会话ID,一定要和你请求的一致。如果不一致,说明ECU拒绝切换,或者切换到了其他会话。我曾经遇到过ECU返回0x50 0x01的情况,意思是“我拒绝你的请求,我留在默认会话”。
- 会话切换与安全访问的关系: 进入编程会话,通常需要先进行安全访问(解锁)。但进入扩展会话,不一定需要。这个顺序要搞清楚。我一般先切到扩展会话,然后解锁,再切到编程会话。
好了,这一章的内容就到这里。会话控制是UDS诊断的基石,搞懂了它,后面的刷写、例程执行才能顺利进行。下一章,我们聊聊安全访问,也就是怎么给ECU“上锁”和“解锁”。