第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诊断栈,通常包含以下组件:

  1. 诊断服务处理器:负责解析和执行UDS服务请求。每个SID对应一个处理函数。
  2. 会话管理器:管理诊断会话的状态机,处理会话切换和超时。
  3. 安全访问管理器:实现种子密钥算法,控制受保护服务的访问权限。
  4. 数据标识符管理器:管理DID(数据标识符)的读写操作,比如VIN码、软件版本号等。
  5. 故障码管理器:处理DTC(诊断故障码)的读取、清除和状态管理。
  6. 传输层适配器:适配不同的总线协议,比如CAN TP、DoIP等。
  7. 定时器管理器:管理各种超时定时器,比如P2_Server、P2*_Server等。

这些组件之间通过接口交互。举个例子,当诊断服务处理器收到一个0x19请求时,它会调用故障码管理器去读取DTC,然后通过传输层适配器把结果发回去。

注意:诊断栈的组件之间不要有循环依赖。我曾经见过一个设计,会话管理器调用了安全访问管理器,安全访问管理器又反过来调用了会话管理器。结果在调试时出现了死锁,排查了两天才找到原因。设计接口时一定要画清楚依赖关系图。

好了,这一章的内容就到这里。下一章我们会深入讲解UDS的会话管理,包括默认会话、扩展会话和编程会话的具体切换逻辑。到时候我会分享一个我在实际项目中遇到的会话切换bug,保证让你印象深刻。