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服务)。

这里有个关键点:安全访问的解锁状态是绑定在会话上的。什么意思呢?

  • 你在编程会话里解锁了,切到扩展会话,解锁状态还在。
  • 但你切回默认会话,解锁状态就丢了。
  • 再切回编程会话,需要重新解锁。

我记得有一次,测试同事问我:“为什么我切回编程会话后,刷写请求被拒绝了?”我一看日志,原来他切回编程会话后,没有重新做安全访问。这就是典型的“会话切换导致权限丢失”问题。

个人经验: 我习惯在OTA升级流程中,先切到编程会话,然后立即做安全访问解锁。解锁成功后,再开始传输数据。这样能避免中间切换会话导致的权限丢失。

4.5 超时机制与S3Server定时器

每个会话都有一个超时定时器,叫S3Server。这个定时器的作用是:如果客户端长时间不发请求,ECU就自动切回默认会话。

为什么要这样设计?说白了,是为了安全。万一诊断仪掉线了,或者通信中断了,ECU不能一直停留在高权限的会话里。否则,别人随便接个诊断仪就能搞破坏。

S3Server的典型值:

会话模式 典型超时时间 说明
默认会话 5秒 超时后仍留在默认会话
编程会话 300秒 超时后切回默认会话
扩展会话 120秒 超时后切回默认会话

你想想看,如果编程会话的超时时间只有5秒,那刷写固件时,你每发一帧数据都要在5秒内完成。这显然不现实。所以编程会话的超时时间通常设得很长。

我建议你在实现时,把S3Server做成可配置的。这样不同项目可以根据需求调整。但要注意,超时时间不能设得太短,否则频繁超时会影响用户体验。

4.6 实际项目中的切换策略

在OTA项目中,我一般这样设计会话切换流程:

  1. ECU上电后,自动进入默认会话。
  2. 客户端发送0x10 02,请求切换到编程会话。
  3. ECU响应成功,进入编程会话。
  4. 客户端发送0x27服务,进行安全访问解锁。
  5. 解锁成功后,开始传输固件数据。
  6. 传输完成后,客户端发送0x10 01,切回默认会话。
  7. ECU执行复位操作,完成升级。

这个流程看起来简单,但实际项目中会有很多细节。比如,如果传输过程中超时了怎么办?我一般会在客户端实现一个心跳机制,定期发送诊断请求,保持会话不超时。

核心要点: 会话切换是OTA升级的“入场券”。你只有正确切换会话,才能进行后续的刷写操作。记住:编程会话 + 安全访问解锁 = 刷写权限。

好了,关于诊断会话控制,今天就讲到这里。下一节,我们会聊聊安全访问服务(0x27),看看怎么解锁ECU的高权限操作。到时候我会分享一些我在项目中遇到的“奇葩”解锁算法,保证让你大开眼界。