第2章:UDS协议栈架构:分层架构设计
好,咱们直接进入正题。UDS协议栈,说白了就是一套分层通信的规矩。你想想看,汽车上那么多ECU,每个ECU里跑着不同的软件,它们之间怎么用诊断命令对话?靠的就是这套分层架构。
我个人习惯把UDS协议栈比作一个快递系统。应用层是寄件人,会话层是快递员,传输层是运输车。各干各的活,互不干扰。这样设计的好处是——哪层出了问题,就修哪层,不用把整个系统推倒重来。
2.1 分层架构设计
UDS协议栈分三层:应用层、会话层、传输层。每一层都有明确的职责边界。
2.1.1 应用层
应用层是离用户最近的一层。它负责解析诊断服务,比如读取故障码(0x19)、写入数据(0x2E)、例程控制(0x31)等等。说白了,应用层只关心“做什么”,不关心“怎么做”。
举个例子,你发一个0x22服务请求读取ECU的VIN码。应用层收到后,它知道要去查VIN码,然后返回结果。至于这个请求是怎么从CAN总线上收上来的,它不管。
关键点:应用层处理的是SID(服务标识符)和子功能。每个SID对应一个诊断服务,应用层根据SID调用对应的处理函数。
我在项目中遇到过一个问题:有个同事把应用层的超时时间设得太短,导致ECU在处理复杂诊断服务时频繁超时。嗯,这里要注意,应用层的超时时间要根据具体服务的处理时间来定,不能一刀切。
2.1.2 会话层
会话层是承上启下的关键。它管理诊断会话的状态机,控制非默认会话的切换。你想想看,ECU平时处于默认会话模式,只能做基本诊断。当你需要刷写软件或执行特殊功能时,就得切换到扩展会话或编程会话。
会话层负责三件事:
- 会话状态管理:默认会话、扩展会话、编程会话之间的切换
- 安全访问控制:解锁受保护的服务(比如刷写前需要种子密钥验证)
- 服务时序控制:防止连续发送请求导致ECU过载
我曾经踩过一个坑:在切换会话时,没有正确处理会话超时。结果ECU在扩展会话里待了太久,自动回退到默认会话,导致后续的诊断请求全部被拒绝。后来我加了一个会话保持机制,定期发送TesterPresent(0x3E)请求,问题就解决了。
小技巧:会话层建议实现一个“会话定时器”。每次收到有效诊断请求时重置定时器,超时后自动回退到默认会话。这样可以避免ECU长时间停留在非默认会话中。
2.1.3 传输层
传输层负责数据的打包和拆包。UDS协议支持多种传输协议,比如CAN、LIN、以太网。传输层把应用层发来的数据分割成适合总线传输的帧,或者把接收到的帧重新组装成完整的数据包。
以CAN总线为例,一帧CAN报文最多只能传8个字节。如果诊断数据超过8个字节,传输层就要做多帧传输。ISO 15765-2(也就是我们常说的CAN TP)就是干这个的。
传输层的关键参数:
| 参数 | 说明 | 典型值 |
|---|---|---|
| BS(块大小) | 连续帧的最大数量 | 0(无限制)或 1-255 |
| STmin(最小间隔时间) | 连续帧之间的最小时间间隔 | 0x00(无延迟)或 0x01-0xF9(毫秒) |
| N_As/N_Ar/N_Bs/N_Br | 网络层超时时间 | 50-1000ms 不等 |
你想想看,如果BS设得太小,ECU每收几帧就要发一次流控帧,效率很低。如果STmin设得太长,传输速度又上不去。这些参数需要根据实际总线负载来调优。
2.2 与AUTOSAR DCM模块的关系
在AUTOSAR架构中,UDS协议栈的实现主要落在DCM(Diagnostic Communication Manager)模块上。DCM是AUTOSAR标准中专门负责诊断通信的模块,它实现了UDS协议栈的大部分功能。
DCM模块的架构是这样的:
- Dcm_Appl:应用层接口,负责调用用户自定义的诊断处理函数
- Dcm_Dsl:会话层接口,管理诊断会话和安全访问
- Dcm_Dsp:服务分发层,根据SID分发到对应的服务处理函数
我记得第一次接触AUTOSAR DCM时,被它的配置项搞得头大。光是一个0x22服务,就有几十个配置参数。后来我总结了一个经验:先理解UDS协议本身,再去看AUTOSAR的配置。协议是根,配置是叶,根扎稳了,叶子自然就理顺了。
核心关系:DCM模块是UDS协议在AUTOSAR中的具体实现。它把UDS的分层架构映射到了AUTOSAR的模块化设计中。应用层对应Dcm_Dsp,会话层对应Dcm_Dsl,传输层则由CanTp或LinTp等模块负责。
2.3 诊断栈的典型组件
一个完整的UDS诊断栈,通常包含以下组件:
- 诊断服务处理器:负责解析和执行UDS服务请求。每个SID对应一个处理函数。
- 会话管理器:管理诊断会话的状态机,处理会话切换和超时。
- 安全访问管理器:实现种子密钥算法,控制受保护服务的访问权限。
- 数据标识符管理器:管理DID(数据标识符)的读写操作,比如VIN码、软件版本号等。
- 故障码管理器:处理DTC(诊断故障码)的读取、清除和状态管理。
- 传输层适配器:适配不同的总线协议,比如CAN TP、DoIP等。
- 定时器管理器:管理各种超时定时器,比如P2_Server、P2*_Server等。
这些组件之间通过接口交互。举个例子,当诊断服务处理器收到一个0x19请求时,它会调用故障码管理器去读取DTC,然后通过传输层适配器把结果发回去。
注意:诊断栈的组件之间不要有循环依赖。我曾经见过一个设计,会话管理器调用了安全访问管理器,安全访问管理器又反过来调用了会话管理器。结果在调试时出现了死锁,排查了两天才找到原因。设计接口时一定要画清楚依赖关系图。
好了,这一章的内容就到这里。下一章我们会深入讲解UDS的会话管理,包括默认会话、扩展会话和编程会话的具体切换逻辑。到时候我会分享一个我在实际项目中遇到的会话切换bug,保证让你印象深刻。