3、诊断会话控制(0x10):默认会话、扩展会话、编程会话、会话切换流程与状态机
各位同学,咱们今天聊聊诊断会话控制。这个服务,SID是0x10,说白了就是ECU的“工作模式切换器”。你想想看,ECU平时在车上跑着,你不能随便动它的内存吧?那太危险了。所以UDS协议定义了三种基本会话:默认、扩展、编程。每种会话下,能用的诊断服务是不一样的。
我个人习惯把会话理解成“权限等级”。默认会话就是普通用户,只能看看故障码、读读数据。扩展会话像工程师模式,能写参数、做例程。编程会话嘛,那就是超级管理员权限,可以直接刷写固件。嗯,这里要注意,权限越高,风险越大。
3.1 三种会话的定义与特点
先看默认会话(Default Session)。ECU上电后,自动进入的就是这个状态。说白了,这是最安全的模式。在这个会话下,你只能执行一些非破坏性的服务,比如0x22读取数据、0x19读取故障码。我刚开始做项目时,有次忘了切会话就直接发0x2E写数据请求,结果ECU直接回复NRC 0x7F——服务不支持。当时还以为是ECU坏了,查了半天才发现是会话不对。
扩展会话(Extended Session)就灵活多了。它允许你执行0x2E写入数据、0x31例程控制等服务。我在项目中遇到过,做产线终检时,需要把校准参数写进ECU,这时候就必须先切到扩展会话。注意,扩展会话是有超时机制的,一般默认5秒没有诊断请求,ECU就会自动跳回默认会话。这个设计是为了防止诊断仪拔掉后,ECU一直留在高权限状态。
编程会话(Programming Session)是最高权限。它主要用于Bootloader刷写。在这个会话下,你可以执行0x34请求下载、0x36数据传输、0x37请求退出传输。我曾经见过一个案例,某供应商的ECU在编程会话下没有禁用CAN通信,结果刷写过程中被其他节点的报文干扰,导致刷写失败。所以,编程会话通常会禁用所有非诊断通信。
| 会话类型 | SID | 子功能 | 典型用途 | 超时时间 |
|---|---|---|---|---|
| 默认会话 | 0x10 | 0x01 | 上电后默认状态,安全只读 | 无(一直保持) |
| 扩展会话 | 0x10 | 0x02 | 参数标定、例程控制 | 通常5秒 |
| 编程会话 | 0x10 | 0x03 | Bootloader刷写 | 通常10秒 |
核心要点:会话切换不是随便切的。从默认切到扩展,ECU会检查当前是否允许切换。如果ECU正在执行某个关键任务(比如正在写EEPROM),它会回复NRC 0x22(条件不满足)。
3.2 会话切换流程与状态机
会话切换的流程其实很简单。你发一条0x10请求,带上目标会话的子功能ID。ECU收到后,先检查当前状态是否允许切换。如果允许,就回复肯定响应,然后ECU内部的状态机就跳转到新会话。如果不允许,就回复否定响应。
举个例子,你想从默认会话切到扩展会话:
请求:02 10 02
响应:06 50 02 00 32 01 F4
这个响应里,50是肯定响应(0x10+0x40),02表示切到了扩展会话,后面跟着三个字节的P2和P2*定时参数。00 32表示P2时间为50ms,01 F4表示P2*时间为500ms。这些定时参数很重要,决定了你发下一条诊断请求前需要等多久。
状态机这块,我建议你画个图来理解。ECU内部维护一个会话状态变量,初始值是默认会话。收到0x10请求后,状态机做三件事:
- 检查当前会话是否允许切换到目标会话
- 如果允许,保存新会话ID,启动会话超时定时器
- 返回肯定响应,附带新的定时参数
我的小技巧:在实际开发中,我习惯在状态机里加一个“切换中”的中间态。这样如果切换过程中出现异常(比如EEPROM写入失败),ECU可以优雅地回退到原会话,而不是卡死。
3.3 会话超时与自动回退
这个机制很重要。ECU在非默认会话下,会启动一个定时器。每次收到有效的诊断请求,定时器就重置。如果定时器超时了,ECU就自动跳回默认会话。为什么要这样设计?你想想看,如果诊断仪突然断开了,ECU还留在扩展会话里,那多危险。
我曾经在项目里踩过一个坑。当时测试刷写流程,发现刷到一半总是失败。查了很久才发现,是因为编程会话的超时时间设得太短了,只有5秒。而刷写一个大文件需要传输好几秒,中间稍微一卡顿,超时了,ECU就跳回默认会话,刷写自然就中断了。后来我把超时时间改成了30秒,问题就解决了。
避坑指南:我曾经见过一个ECU,在编程会话下没有正确处理超时。刷写过程中,如果某包数据延迟了,ECU直接跳回默认会话,但此时Flash还在写入状态,导致整个ECU变砖。所以,超时处理一定要和当前任务联动,不能简单粗暴地直接跳转。
3.4 实际开发中的注意事项
做会话控制开发,有几个点你得特别注意:
- 会话切换的原子性:切换过程中,如果ECU正在处理其他任务(比如CAN报文接收),要确保切换操作是原子的,不能出现半切换状态。
- 定时参数的协商:ECU返回的P2和P2*时间,诊断仪应该尊重。我见过有些诊断仪不管ECU返回的参数,硬用自己的定时,结果导致通信超时。
- 会话与安全访问的关联:有些ECU设计成,切到扩展会话后,还需要做安全解锁才能执行写操作。这个顺序不能乱,先切会话,再解锁,最后操作。
嗯,说到安全解锁,那是下一个章节的内容了。咱们先把会话控制吃透。你想想看,会话控制是整个UDS诊断的基础,如果这个搞不清楚,后面的刷写、标定都没法做。所以,我建议你动手写个简单的状态机模拟器,用串口调试助手发0x10请求,观察ECU的响应和状态变化。实践出真知嘛。
最后,留个思考题:如果ECU当前在编程会话,你发0x10 0x01想切回默认会话,ECU应该怎么处理?是直接切,还是先检查有没有正在进行的刷写任务?这个问题,我在下一章会详细讲。