3、诊断会话控制(0x10):默认会话、编程会话、扩展会话的切换逻辑、会话状态机、实际项目中的会话管理策略

3.1 会话控制到底在解决什么问题?

各位工程师朋友,咱们直接切入正题。

诊断会话控制,服务ID是0x10。说白了,它就是ECU的“工作模式切换器”。

你想想看,一辆车上几十个ECU,每个ECU都有不同的功能。有些功能是日常用的,比如读取车速、发动机转速。有些功能是维修时才用的,比如写入配置、刷写固件。还有些功能是出厂前才用的,比如标定参数。

如果所有功能都开放,那安全性怎么保证?

所以,UDS协议定义了三种会话:默认会话编程会话扩展会话。ECU根据当前会话,决定允许哪些诊断服务。

我在项目中遇到过,有同事把扩展会话和编程会话搞混了,结果刷写时一直报错。嗯,这里面的门道,咱们慢慢聊。

3.2 三种会话的“人设”

3.2.1 默认会话(Default Session)

这是ECU上电后的默认状态。说白了,就是“日常模式”。

在这个模式下,ECU只开放最基础的服务。比如:

  • 0x22(读取数据)—— 读个故障码、读个版本号
  • 0x14(清除故障码)—— 清一下历史故障
  • 0x19(读取故障码信息)—— 查查当前有啥问题

但像0x2E(写入数据)、0x31(例程控制)、0x34(请求下载)这些“危险操作”,默认会话是不允许的。

我的习惯: 项目初期,我会先确认ECU在默认会话下到底开放了哪些服务。有些OEM会偷偷多开几个,这会影响安全策略。

3.2.2 扩展会话(Extended Session)

扩展会话,你可以理解为“维修模式”。

当车辆进4S店维修时,诊断仪会发送0x10 03,让ECU进入扩展会话。这时候,ECU会开放更多服务:

  • 0x2E(写入数据)—— 比如修改VIN码、配置参数
  • 0x31(例程控制)—— 比如执行某个自检程序、复位某个模块
  • 0x2F(输入输出控制)—— 比如强制某个执行器动作

注意,扩展会话不能进行刷写。刷写需要更高级的权限。

我记得有一次,客户反馈说ECU无法写入配置。我一看日志,发现诊断仪发送的是0x10 01(默认会话),然后直接发0x2E。这当然不行。先切到扩展会话,再写数据,问题就解决了。

3.2.3 编程会话(Programming Session)

编程会话,就是“刷写模式”。

这是权限最高的会话。只有在这个会话下,才能执行:

  • 0x34(请求下载)
  • 0x36(数据传输)
  • 0x37(请求退出传输)
  • 0x31(刷写相关的例程,比如擦除、校验)

进入编程会话后,ECU通常会关闭一些非必要的通信,比如CAN报文、网络管理。这是为了保证刷写过程的稳定性和安全性。

避坑指南: 我曾经遇到过,某ECU在编程会话下,居然还继续发送网络管理报文。结果刷写到一半,总线负载过高,导致超时失败。后来我们强制在编程会话下关闭所有非诊断报文,才解决问题。

3.3 会话状态机:切换逻辑与规则

会话切换不是随意的,它有一套严格的状态机。我画个简化的图给你看:

+----------------+      0x10 02      +------------------+
|  默认会话      | ----------------> |  编程会话        |
| (Default)      |                   | (Programming)    |
+----------------+                   +------------------+
       |                                    |
       | 0x10 03                            | 0x10 01 或 0x10 03
       v                                    v
+----------------+                   +------------------+
|  扩展会话      |                   |  默认会话        |
| (Extended)     | <---------------- | (Default)        |
+----------------+      0x10 01      +------------------+

核心规则就三条:

  1. 从默认会话可以切换到任何会话。 这是最灵活的起点。
  2. 从扩展会话只能切换到默认会话。 不能直接跳到编程会话。必须先回默认,再进编程。
  3. 从编程会话可以切换到默认会话或扩展会话。 刷写完成后,通常切回默认会话。

为什么这样设计?

你想想看,如果扩展会话能直接切到编程会话,那万一诊断仪在维修时误操作,直接发起刷写,后果很严重。所以UDS协议强制要求:编程会话必须从默认会话进入。这算是一道安全屏障。

我个人的经验是,在开发诊断栈时,一定要把状态机实现得滴水不漏。有些ECU的协议栈实现有bug,允许从扩展会话直接切到编程会话。这在OEM的测试中,是会被一票否决的。

3.4 实际项目中的会话管理策略

理论说完了,咱们聊聊实战。

3.4.1 会话超时与保持

ECU不会永远待在扩展会话或编程会话里。它有一个会话超时定时器(S3定时器)。

通常,OEM会规定:

  • 扩展会话超时:5秒(如果5秒内没有诊断请求,自动切回默认会话)
  • 编程会话超时:10秒(刷写过程中,通常由Tester持续发送请求来保持会话)

我在项目中遇到过,某诊断仪在刷写时,每发送一个数据块后,等待ECU的响应,然后再发下一个。但中间间隔超过了10秒,结果ECU自动切回了默认会话。刷写当然失败了。

解决方案?诊断仪需要定期发送0x3E(Tester Present)服务,告诉ECU:“我还活着,别切回去。”

我的建议: 在开发诊断仪时,把0x3E的发送间隔设为2秒。这样即使某个请求处理时间较长,也不会超时。但注意,0x3E本身也会被ECU响应,别把总线搞爆了。

3.4.2 安全访问与会话的关系

很多工程师会问:会话和安全访问(0x27)是什么关系?

简单说:会话决定“能不能做”,安全访问决定“谁来做”

举个例子:

  • 你想写入VIN码。首先,ECU必须在扩展会话下(会话权限)。
  • 然后,诊断仪必须通过安全访问的种子-密钥验证(安全权限)。
  • 两者都满足,才能执行0x2E写入。

我见过一个项目,OEM要求:在扩展会话下,如果安全访问失败,ECU必须立即切回默认会话。这是一种安全策略,防止暴力破解。

3.4.3 多ECU场景下的会话协调

现在的车,网关、域控制器、多个ECU协同工作。诊断时,会话管理就更复杂了。

比如,你想刷写网关。但网关同时负责路由诊断报文到其他ECU。如果你把网关切到编程会话,它可能无法正常路由了。

怎么办?

有些OEM的做法是:网关在编程会话下,仍然保留路由功能。但会降低优先级,或者只路由特定的报文。

我个人习惯是,在项目早期就和OEM确认好:编程会话下,ECU的哪些功能要保留,哪些要关闭。这个决策会影响整个诊断架构的设计。

3.5 总结与避坑清单

好了,会话控制的内容就讲到这里。我帮你整理一个避坑清单:

常见问题 原因 解决方案
刷写时ECU无响应 会话超时,自动切回默认会话 定期发送0x3E保持会话
写入配置失败 未切换到扩展会话 先发0x10 03,再发0x2E
从扩展会话直接切编程会话失败 UDS协议不允许 先切回默认,再切编程
编程会话下总线冲突 ECU未关闭非诊断报文 编程会话中禁用网络管理报文

最后说一句:会话控制是诊断的基础。基础不牢,地动山摇。希望今天的分享,能帮你少踩几个坑。