UDS会话切换0x10服务详解:从报文格式到刷写链路实战
做ECU测试这几年我遇到过太多因为会话切换没搞明白导致的刷写失败、服务被拒。UDS诊断里会话Session是比任何功能服务都靠前的一道门门没开对后面所有动作都白搭。这篇文章就用实际报文来拆解UDS诊断中最常被问到的会话切换也就是0x10服务DiagnosticSessionControl从报文格式、状态机规则一直讲到刷写中的完整切换链路适合刚接触诊断协议的同学也适合已经在做台架测试但总被NRC卡住的朋友。1. 先理解UDS会话ECU并不会时刻开放全部权限1.1 会话机制到底解决什么问题UDSUnified Diagnostic Services是ISO 14229定义的一套汽车诊断协议跑在CAN、CAN FD、DoIP或者LIN上应用层通过SIDService ID区分功能。0x10这个SID负责的就是会话控制。会话机制的本质是给ECU内部划分了几个不同权限的运行模式。ECU在出厂、售后、产线、刷写、标定、防盗匹配这些不同场景下开放给诊断仪的功能范围完全不同。如果一上电就把编程、安全访问、DTC写入这些高权限能力全部开放那整车的网络安全风险会非常大。会话切换就是一把钥匙把ECU从低权限模式切换到高权限模式。常见的会话定义四个0x01 默认会话上电后通常停在这里只有基础读操作比如读版本、读DTC状态0x02 编程会话允许使用0x34请求下载、0x36数据转移这类刷写服务0x03 扩展会话允许标定、复杂例程控制、写入请求也是进入编程会话前必经的中间态0x04 安全系统诊断会话部分平台用于安全气囊、主动安全这类系统的特殊诊断一个粗暴但好用的类比是门禁默认会话就像大厅扩展会话是办公区编程会话是机房。没有刷卡切会话就硬闯机房轻则被保安拦下NRC否定响应重则触发整车安全保护。1.2 别被Web开发里的Session带跑偏搜索UDS会话相关问题时很容易看到一些Web领域的词条比如“there is no session with id”“cookie和session的区别”。这里需要明确一点UDS里的Session是ECU内部诊断状态机和浏览器会话没有一点关系。UDS上下文里出现“session”字样指的就是0x10服务控制的诊断会话状态。容易混淆的还有0x29服务。0x29在ISO 14229里是Authentication安全认证服务负责基于证书、挑战码的认证流程。0x29和会话切换相关但执行时不能把它当成切会话的入口。切会话永远是0x100x29只是帮你在高权限会话里做身份确认。不少人以为“29服务”能切会话实际是乌龙。2. 会话切换的入口0x10服务与应答逻辑2.1 请求报文怎么组0x10服务请求格式非常固定0x10 Sub-functionSub-function就是目标会话ID常见值如下表格所示。Sub-function会话名称典型用途0x01defaultSession默认会话上电初始态0x02programmingSession编程会话刷写固件0x03extendedDiagnosticSession扩展诊断会话标定/高级读写0x04safetySystemDiagnosticSession安全系统诊断会话0x40-0x7FOEM自定义厂家扩展会话比如bootloader特殊态这里有一个细节Sub-function的bit7是suppressPosRspMsgIndicationBit也就是抑制肯定响应位。比如你要切到扩展会话但不想让ECU回肯定响应可以发0x10 0x83而不是0x10 0x03。请求110 03 // 切扩展会话正常回正响应 请求210 83 // 切扩展会话抑制正响应抑制位生效后ECU不会回50 03但如果切换失败否定响应7F 10 xx还是会回的。这个行为需要特别注意很多上位机脚本只看有没有响应帧判断成功结果把否定响应也当成成功看着像是切过去了实际状态没变。2.2 肯定响应与两个关键定时器0x10服务成功后肯定响应格式是50 Sub-function P2_Server_max(2字节) S3_Server_max(2字节)举个例子实际抓包经常看到TX: 10 03 RX: 50 03 00 32 13 88展开解读50是肯定响应SID等于请求SID0x4003表示当前已进入扩展会话00 32表示P2_Server_max单位ms换算后是50ms13 88表示S3_Server_max单位ms换算后是5000msP2_Server_max的含义是非默认会话下ECU处理新请求后需要在50ms内给出首次响应如果处理时间超过50ms必须先回一帧7F xx 78ResponsePending让诊断仪知道请求还在处理防止诊断仪超时误判。S3_Server_max的含义是在这个会话下如果超过5000ms没有收到任何新的诊断请求ECU会自动跳回默认会话。这就是诊断协议里保活的根源切到扩展会话后工具必须周期性发送诊断请求来维持会话状态否则ECU就悄悄退出了。P2和S3的具体值在不同ECU上不一样但通常符合ISO 14229的默认推荐非默认会话P250msS35000ms。有些OEM自定义值可能不同要以车型规范为准。2.3 否定响应被拒了要知道为什么切换失败时ECU回的是7F 10 NRC常用NRC整理如下NRC名称含义与常见场景0x12subFunctionNotSupported子功能不支持比如直接发10 02但ECU不支持0x13incorrectMessageLengthOrInvalidFormat报文长度或格式错误比如发了10 03 01多一个字节0x22conditionsNotCorrect条件不满足比如整车状态不允许编程0x33securityAccessDenied安全访问被拒通常对应编程会话要求先解锁0x34authenticationRequired要求先走0x29认证新一代安全架构常见0x78requestCorrectlyReceivedResponsePending不是错误是ECU还在处理稍后会再补响应0x7EsubFunctionNotSupportedInActiveSession当前会话不支持该子功能切换常见于部分特殊会话遇到7F 10 33基本说明你试图切入的会话需要更高安全等级遇到7F 10 22则说明ECU认为当前整车条件不满足比如车速不为零、挡位不在P挡、点火开关不在ON挡都会导致条件不满足。3. 会话状态机谁可以切到谁是有规矩的3.1 标准切换规则与工程实践ISO 14229里会话切换不是一个任意矩阵标准Annex A定义了会话状态图工程实现上一般遵循这么几条不成文但很常见的规则。当前会话目标会话普遍行为默认会话0x01扩展会话0x03允许不需要解锁默认会话0x01编程会话0x02多数ECU拒绝NRC 0x22或0x33默认会话0x01安全系统诊断0x04需要特定条件通常拒绝扩展会话0x03默认会话0x01允许扩展会话0x03编程会话0x02允许但通常需要先通过0x27安全访问或0x29认证扩展会话0x03扩展会话0x03多数ECU直接成功相当于重置S3定时器编程会话0x02默认会话0x01允许编程会话0x02扩展会话0x03允许部分ECU需要先回默认再切编程会话0x02编程会话0x02多数成功相当于重置定时器关键点在于默认会话直接切编程会话在国产车和合资车的实际标定中大多走不通。如果你在工程规范里看到“programming session shall only be entered from extended session”意思是编程会话只能从扩展会话进入那就必须先10 03再10 02。顺带一提很多ECU进入编程会话后会短暂屏蔽部分常规诊断服务甚至有些ECU在编程会话下会自动让出总线调度避免刷写过程被干扰。测试时如果发现进入编程会话后之前能用的服务突然回NRC 0x11serviceNotSupported不要惊讶这是正常的权限收窄。3.2 S3超时回退ECU的“自动锁门”S3定时器的存在让很多新手栽跟头。CANoe或PCAN里做了很久的标定中间停下来喝口水回来继续发请求发现响应全部变成NRC 0x11。原因很简单扩展会话5秒超时已经回默认会话了默认会话根本不支持标定服务。这个“自动锁门”是ISO强制的安全设计防止诊断仪异常掉线后ECU一直暴露在高权限状态。刷写过程中一段数据转移完成后如果上位机处理文件需要几秒钟而ECU已经回默认后续下载流程立刻断链整个刷写包都要从头来过。维护会话的办法有两种周期性发送任意受支持的服务比如10 03重发切扩展会话或者22 F1 90读软件版本号之类的无副作用请求上位机内置S3心跳线程保证请求间隔小于S3值通常保守做法是间隔1000ms到2000ms发一次心跳实测经验不要卡着4500ms去发心跳网络抖动、CAN总线繁忙都可能让你错过窗口。宁可每1000ms发一个轻量读服务。3.3 条件不满足与会话切换的关联前面提到的NRC 0x22往往不是单纯“你权限不够”而是外部条件没达标。比如整车电源模式不在KL15 ON车速不满足安全条件挡位不在允许范围发动机转速不为零刷写时不允许发动机运行安全访问未完成部分ECU把未解锁也归到0x22而不是0x33所以排查0x22时不能只盯诊断层还要看ECU输入状态。用CANoe里增加环境变量或者读取ECU的电源模式、挡位信号能快速定位。此外部分ECU有“引脚拉低进入特殊模式”的机制。例如某些MCU的Bootloader里编程会话可能还要求物理引脚状态配合。这时候单纯发0x10 02进不去是正常的需要硬件搭接。这是厂家特定的行为操作前一定先看Bootloader规范。4. 完整实例从默认会话一路切到编程会话4.1 场景设定假设我现在要给一块VCU刷写Bootloader工具用的是CANoe CANcaseXLECU地址按标准设置。刷写前置流程是默认会话 - 扩展会话 - 安全访问解锁 - 编程会话 - 传输数据这个过程里每一步的报文我都从日志里截出来带着解释过一遍。4.2 从默认会话切到扩展会话第一步发送TX: 10 03ECU响应RX: 50 03 00 32 13 88说明50 03表示进入扩展会话成功。00 32是P2_Server_max50ms13 88是S3_Server_max5000ms。响应回来后ECU已经把S3定时器启动接下来5秒内必须维持请求。这里我习惯在做完切换后立刻用一个22服务读版本号一方面是确认会话确实生效另一方面也能顺带保活。比如TX: 22 F1 90 RX: 62 F1 90 01 02 03能正常读到版本号说明当前确实在扩展会话下22服务是被允许的。如果还在默认会话22服务很多ECU是不可用的会回7F 22 11。4.3 安全访问进编程会话前的必经之路扩展会话不代表你能刷写。0x10 03只打开了扩展诊断的门编程会话还需要安全访问解锁。标准流程是seed-key机制用0x27服务。日志如下TX: 27 01 // 请求seedlevel 01 RX: 67 01 11 22 33 44 // 返回seed 0x11223344 TX: 27 02 55 66 77 88 // 发送通过算法计算出的key RX: 67 02 // 解锁成功如果key算错了ECU会回RX: 7F 27 35NRC 0x35表示invalidKey。连续多次错误key还会触发延时锁定机制锁定时长从几十毫秒到几秒不等这是防止暴力破解seed-key的既定设计。安全访问解锁和会话切换是两件事但要注意顺序。多数ECU要求先在扩展会话下做安全访问解锁成功后才允许切编程会话。如果你在默认会话直接发27服务大概率被拒因为默认会话根本不开放安全访问服务。还有一点安全访问解锁状态不跟随会话切换而永久保留。部分ECU设计成一旦退出到默认会话安全解锁状态也随之清除重新进入扩展后需要再次解锁。我测试中遇到不少这样的实现所以刷写脚本里“10 03 - 27 - 10 02”的顺序必须严格串行不能提前切默认会话。4.4 从扩展会话切编程会话安全访问解锁成功后发送TX: 10 02正常响应RX: 50 02 00 32 13 88这说明已经进入编程会话P2_Server_max50msS3_Server_max5000ms。此时0x34、0x36、0x37这类传输服务才被允许执行。如果在未解锁时强行发送10 02会遇到两种典型回报TX: 10 02 RX: 7F 10 33 // securityAccessDenied或者某些ECU统一归为条件不满足RX: 7F 10 22 // conditionsNotCorrect这两种都是“没有资格进入编程会话”的信号区别只是NRC分类策略不同。遇到0x22时尤其先确认自己的安全访问状态。进入编程会话后刷写基础链路一般是这样10 02 - 34 00 44 ... - 36 01 data - 36 02 data - 37 - 31 01 FF 0034请求下载、36数据传输、37请求退出传输、31例程控制做刷写完成校验。整套动作里所有请求都必须卡在编程会话有效期内一旦S3超时回到默认后面所有SID都会被打回。4.5 会话切换时序上的一个坑有些ECU对于“扩展会话-安全访问-编程会话”这一串动作有时间限制。比如规范里会写安全访问解锁成功后必须在例如200ms内发起编程会话切换否则解锁状态自动失效。这个限制在一些老式Bootloader里非常常见因为Bootloader本身不跑完整操作系统内存里的解锁状态是靠RAM保持的掉电或者看门狗复位都会清掉。如果是这种ECU你的上位机在解锁后不能有任何多余的延时代码必须在最短时间内把10 02发出去。实测中我还遇到过一个ECU编程会话切换成功后会自动执行一个内部复位复位期间总线上会有几百ms的静默。上位机如果没有处理好这个静默窗口会误以为ECU掉线了然后主动断开连接。正确的做法是在切编程会话成功后等待一段明确的静默时间再发送第一个刷写请求。5. 会话切换常见问题与排查经验5.1 NRC速查与排查优先级会话切换失败先看NRC再结合整车条件查效率最高。我整理了一张实际排查顺序表现象优先排查方向7F 10 12目标子功能根本不存在查规范中的会话定义7F 10 13请求长度或者格式错了比如多发了字节7F 10 22整车条件不满足查电源模式、车速、挡位、安全状态7F 10 33安全访问未解锁先做27服务再切会话7F 10 34需要0x29认证流程查证书和挑战码流程7F 10 11目标服务在当前会话下不支持注意是否已回默认实际排查时我经常先怀疑是不是S3超时偷偷退了会话再怀疑条件不满足。因为日志里可能几十秒前还是扩展会话但是中间没有任何请求等再次发请求时ECU已经回默认。这种问题不是诊断逻辑错了是保活没做。5.2 案例刷写流程中段突然NRC 0x11一次项目里刷写脚本每次跑到第4包数据就失败日志如下TX: 10 02 RX: 50 02 00 32 13 88 TX: 27 01 ... TX: 34 ... RX: 74 ... TX: 36 01 ... RX: 76 ... TX: 36 02 ... RX: 7F 36 11跑到36第二包就回NRC 0x11。最初怀疑是36报文格式问题但检查发现36请求格式完全正确。后来把每条请求的时间戳拉出来看才发现34和36之间隔了整整6.2秒。问题在于上位机在34请求后花了几秒钟计算内存分配然后跳过35直接发36中间没有保活请求S3超时导致ECU退回了默认会话36自然不被支持。解决方式就是在传输过程中也要周期保活或者在34请求之前临时把S3心跳间隔调小。这类“莫名其妙NRC 0x11”的问题八成都是会话超时导致。5.3 案例编程会话每次进不了复位一下就好另一个客户报障说ECU每次切编程会话都失败NRC不是0x22就是0x33但复位后第一次能成功再次失败。查下来是两个原因叠加上一次刷写异常退出ECU还停留在编程会话部分服务被锁存再次切编程会话时安全访问解锁状态混乱ECU判定为非法重复切换解决办法是先发10 01回默认等待一段明确时间再重新执行“扩展-解锁-编程”的完整链路。有些ECU需要掉电重启才能彻底恢复正常这时按规范流程走一遍电源循环即可。这个案例给了一个通用经验切会话失败时先不要猜把“当前会话确认”作为第一步。用10 01切回默认是成本最低的自愈手段。5.4 0x29认证服务与0x10会话的关系新一代安全架构下0x29服务越来越常见。很多人在刷写或者在线配置时看到0x29以为能替代0x10切会话这是理解偏差。0x29是Authentication服务做的是身份认证基于公钥基础设施和挑战码认证成功后可以获取某种角色权限比如“刷写允许”的权限。0x10是DiagnosticSessionControl做的是会话状态切换。两者协同的典型流程是10 03 - 29 02 ... - 29 04 ... - 10 02也就是说先切到扩展会话然后走0x29认证流程拿到“allowed to program”的授权再去切编程会话。如果ECU要求0x34而你没走0x29切换会话时可能被回0x34。要特别记住0x29认证结果有时和会话的S3超时绑定。认证成功后如果迟迟没切编程会话超时后认证授权也会一并失效。5.5 工具与链路层面的会话状态干扰最后说一个工具层面的问题。CANoe、PCAN、智己诊断仪这类工具有的会内置自动保活机制有的不会。如果你在CANoe里开了“TP层自动心跳”功能它可能在会话状态里自动来回发送请求掩盖了协议栈真实状态导致问题只在实车上出现。另一个常见干扰是ECU的看门狗复位。刷写过程中ECU如果因为地址校验失败等原因复位会话状态会重置到默认。此时从工具侧看总线连接还在但会话已经变了。遇到刷写中途“掉线”又“自动恢复”一定要检查ECU有没有复位过最简单的方法就是读ECU启动时间或者上电计数器。收个尾会话切换看起来就是几条报文的组合但真正考验人的是对ECU状态机的理解。我自己做测试的体会是凡是刷写、标定、配置类问题先花一分钟确认当前会话状态和S3超时再谈后续。把0x10的报文格式、NRC含义、切换规则、保活策略这几件事刻在脑子里能少踩很多坑。最后分享一个小技巧在写测试脚本时把会话切换封装成一个原子函数内部自动完成“读当前状态-切目标会话-确认响应-记录时间戳”任何一次切换都会留下日志。这样不仅方便排查也方便在回归测试里快速定位到底是ECU问题还是脚本问题。千万别图省事直接在测试用例里裸发10 03、10 02脚本越随意问题越难查。
上一篇/下一篇内容由系统自动关联
返回资讯列表 →