4. UDS诊断会话控制(0x10):默认会话、编程会话、扩展会话、会话切换流程与安全策略
诊断会话控制,服务ID是0x10。说白了,它就是ECU的“工作模式切换器”。
ECU不能一直用同一种姿态响应诊断请求。有些操作太危险,比如刷写Flash、标定参数,必须进入特定模式才能干。我刚开始做UDS开发时,就吃过这个亏——在默认会话下发了一个写ECU复位类型的请求,结果ECU直接不理我,返回了否定响应。后来才明白,权限不够。
4.1 三种会话:默认、编程、扩展
UDS定义了三种标准会话状态。每个ECU上电后,默认进入默认会话。你可以通过0x10服务主动切换。
| 会话类型 | 子功能ID | 典型用途 | 我见过的坑 |
|---|---|---|---|
| 默认会话 (Default Session) | 0x01 | 读取故障码、读取数据、基本通信 | 很多ECU在默认会话下禁止写操作 |
| 编程会话 (Programming Session) | 0x02 | 刷写Bootloader、应用程序、标定数据 | 刷写时不能断电,否则ECU变砖 |
| 扩展会话 (Extended Session) | 0x03 | 写入参数、执行例程、标定、特殊功能 | 扩展会话通常需要先解锁安全访问 |
核心原则:会话等级越高,能执行的诊断服务越多。但高等级会话通常有超时机制,超时后自动退回默认会话。
4.2 会话切换流程:请求与响应
切换会话的流程很简单。Tester发一条0x10服务请求,ECU回复肯定或否定响应。
请求报文格式:
| 字节0 | 字节1 |
| 0x10 | sub-function |
肯定响应格式:
| 字节0 | 字节1 | 字节2-3 |
| 0x50 | sub-function | P2_Server_max (可选) |
注意那个P2_Server_max。它告诉Tester:当前会话下,ECU处理请求的最大时间。我遇到过一些ECU,在编程会话里把P2时间设得很长,因为刷写Flash确实慢。Tester如果按默认会话的超时去等,就会误判超时。
我的习惯:收到肯定响应后,先解析P2_Server_max,动态调整Tester的超时定时器。别写死。
4.3 会话切换流程:状态机与超时
ECU内部维护一个会话状态机。切换不是瞬时的,有严格的时序要求。
每个会话都有一个S3 Server超时定时器。如果在这个时间内没有收到任何诊断请求,ECU自动退回默认会话。这个时间通常由OEM定义,常见值是5秒。
我曾经踩过的坑:在编程会话里刷写Bootloader,刷写过程本身需要十几秒。但ECU的S3定时器只有5秒。刷到一半,ECU超时退回默认会话,刷写中断,ECU变砖。后来我学乖了:在刷写大块数据前,先发一条0x3E(Tester Present)服务,保持会话活跃。
4.4 安全策略:会话与安全访问的联动
会话切换本身不需要安全解锁。但进入高等级会话后,很多敏感服务(比如写入数据、执行例程)需要先通过0x27服务(安全访问)解锁。
举个例子:
- Tester发送0x10 03,进入扩展会话。ECU响应肯定。
- Tester发送0x2E(写入数据),请求写入标定参数。ECU返回否定响应:0x7F 0x2E 0x33(securityAccessDenied)。
- Tester发送0x27,完成安全解锁。
- Tester再次发送0x2E,ECU接受请求。
你想想看,为什么要有这个设计?
会话控制只是“模式选择”,安全访问才是“权限验证”。两者缺一不可。我见过一些ECU设计,把安全解锁和会话绑定在一起——进入编程会话时自动解锁。这种做法风险很高,万一Tester异常断开,ECU就处于“解锁+编程会话”状态,容易被恶意攻击。
推荐做法:会话切换只负责模式切换,不负责权限验证。安全解锁必须独立完成,并且每次解锁都有时效性(通常解锁后一段时间内有效,超时自动锁定)。
4.5 实际开发中的避坑指南
- 会话切换失败处理:ECU收到0x10请求后,如果当前正在执行某个例程(比如正在擦除Flash),应该返回否定响应0x7F 0x10 0x22(conditionsNotCorrect)。我遇到过ECU直接忽略请求,导致Tester超时。
- 会话嵌套:有些ECU支持“会话嵌套”,比如在扩展会话里再进入编程会话。但大部分ECU不支持,切换前必须先退回默认会话。建议查OEM规范。
- P2_Server_max的解析:肯定响应里的P2_Server_max是2字节,单位是毫秒。有些ECU返回0x0000,表示使用默认值(比如50ms)。别把0x0000当成0ms处理。
- 多ECU场景:在CAN总线上,多个ECU同时响应0x10请求?不可能。每个ECU有独立的诊断地址,Tester通过CAN ID区分。但要注意,如果两个ECU的地址冲突,总线会乱。
我的测试习惯:写一个自动化脚本,遍历所有会话切换组合(默认->扩展、默认->编程、扩展->编程、编程->扩展、扩展->默认、编程->默认),检查每次切换的响应时间、P2_Server_max值、以及切换后能执行的服务列表。这个脚本能发现很多ECU实现的bug。
4.6 总结
0x10服务是UDS诊断的“门禁系统”。它不负责开门后的权限验证,但决定了你能进哪扇门。默认会话是安全区,编程会话是手术室,扩展会话是调试间。记住:会话有超时,超时自动回退;会话切换不自动解锁,安全访问要单独做。
嗯,这一章就到这里。代码实现和测试用例,我们后面章节再细聊。