4、诊断会话控制(0x10):默认会话、编程会话、扩展会话的切换逻辑与安全机制
各位同学,咱们今天聊聊诊断会话控制。这个服务,UDS协议里编号是0x10。说实话,它是整个诊断通信的“大门”。你连门都进不去,后面的读写数据、刷写程序,想都别想。
我个人习惯把会话切换理解成“权限等级”。你想想看,车上的ECU不可能让谁都能随便改数据。所以它设计了几个不同的会话模式,每种模式开放不同的服务权限。
4.1 三种核心会话模式
UDS标准里定义了三种最常用的会话。我直接给你列出来:
| 会话模式 | SID(子功能) | 主要用途 | 典型权限 |
|---|---|---|---|
| 默认会话 | 0x01 | 上电后的初始状态 | 只读基本数据(如VIN码) |
| 编程会话 | 0x02 | 刷写固件、升级软件 | 允许内存写入、安全访问 |
| 扩展会话 | 0x03 | 高级诊断、标定、配置 | 允许读写复杂参数、执行例程 |
嗯,这里要注意。默认会话是ECU上电后自动进入的。说白了,它就是个“待客室”。你只能看看基本信息,想干点别的?不行。
编程会话,这个在OTA升级里最常用。我记得有一次做项目,客户要求刷写时不能有任何中断。我就在编程会话里把通信超时时间设得很长,防止刷到一半掉线。这个后面会细讲。
扩展会话,我习惯叫它“工程师模式”。你想想看,标定工程师要调参数,测试工程师要跑例程,这些操作都需要扩展会话的支持。
4.2 会话切换逻辑
切换会话,客户端发一条0x10服务请求就行了。格式很简单:
请求:02 10 02
响应:06 50 02 00 32 01 F4
这个请求的意思是:我要切换到编程会话(0x02)。响应里的0x50是肯定响应,后面跟着会话参数。00 32表示默认会话的超时时间是50秒,01 F4表示编程会话的超时时间是500秒。
为什么会这样?因为刷写固件是个耗时操作。你想想看,一个几百KB的固件,用CAN总线传,怎么也得几分钟。如果超时时间设得太短,刷到一半就超时退出了,那可就麻烦了。
我建议你在设计时,把编程会话的超时时间设得足够长。我个人习惯设成300秒到600秒。当然,也要看你的刷写策略。如果是压缩包分段传输,时间可以短一点。
4.3 切换规则与限制
会话切换不是你想切就能切的。有几个硬性规则:
- 默认会话可以随时切到其他会话。这是最自由的。
- 非默认会话之间可以互相切换。比如从编程切到扩展,或者反过来。
- 任何会话都可以切回默认会话。但要注意,切回默认会话时,之前申请的权限(比如安全解锁状态)会被清空。
我曾经踩过一个坑。有一次做OTA测试,刷写完成后,我直接切回了默认会话。结果发现ECU不响应后续的诊断请求了。查了半天,原来是切回默认会话时,安全访问的解锁状态被清掉了。后续的请求因为没有解锁,被ECU拒绝了。
4.4 安全机制:会话与安全访问的联动
会话切换本身不涉及安全验证。但你要执行敏感操作(比如写内存、刷固件),就必须先通过安全访问(0x27服务)。
这里有个关键点:安全访问的解锁状态是绑定在会话上的。什么意思呢?
- 你在编程会话里解锁了,切到扩展会话,解锁状态还在。
- 但你切回默认会话,解锁状态就丢了。
- 再切回编程会话,需要重新解锁。
我记得有一次,测试同事问我:“为什么我切回编程会话后,刷写请求被拒绝了?”我一看日志,原来他切回编程会话后,没有重新做安全访问。这就是典型的“会话切换导致权限丢失”问题。
4.5 超时机制与S3Server定时器
每个会话都有一个超时定时器,叫S3Server。这个定时器的作用是:如果客户端长时间不发请求,ECU就自动切回默认会话。
为什么要这样设计?说白了,是为了安全。万一诊断仪掉线了,或者通信中断了,ECU不能一直停留在高权限的会话里。否则,别人随便接个诊断仪就能搞破坏。
S3Server的典型值:
| 会话模式 | 典型超时时间 | 说明 |
|---|---|---|
| 默认会话 | 5秒 | 超时后仍留在默认会话 |
| 编程会话 | 300秒 | 超时后切回默认会话 |
| 扩展会话 | 120秒 | 超时后切回默认会话 |
你想想看,如果编程会话的超时时间只有5秒,那刷写固件时,你每发一帧数据都要在5秒内完成。这显然不现实。所以编程会话的超时时间通常设得很长。
我建议你在实现时,把S3Server做成可配置的。这样不同项目可以根据需求调整。但要注意,超时时间不能设得太短,否则频繁超时会影响用户体验。
4.6 实际项目中的切换策略
在OTA项目中,我一般这样设计会话切换流程:
- ECU上电后,自动进入默认会话。
- 客户端发送0x10 02,请求切换到编程会话。
- ECU响应成功,进入编程会话。
- 客户端发送0x27服务,进行安全访问解锁。
- 解锁成功后,开始传输固件数据。
- 传输完成后,客户端发送0x10 01,切回默认会话。
- ECU执行复位操作,完成升级。
这个流程看起来简单,但实际项目中会有很多细节。比如,如果传输过程中超时了怎么办?我一般会在客户端实现一个心跳机制,定期发送诊断请求,保持会话不超时。
好了,关于诊断会话控制,今天就讲到这里。下一节,我们会聊聊安全访问服务(0x27),看看怎么解锁ECU的高权限操作。到时候我会分享一些我在项目中遇到的“奇葩”解锁算法,保证让你大开眼界。