4. Dcm模块配置实战

Dcm(Diagnostic Communication Manager)是AUTOSAR基础软件中诊断通信的核心模块,它位于PDU Router之上、应用层诊断服务处理之下,负责诊断请求的解析、会话与安全状态管理、服务分发以及响应组包。在MICROSAR中,Dcm的配置主要通过DaVinci Configurator完成,配置结果最终以Dcm_Cfg.c/h、Dcm_Lcfg.c等代码形式生成并参与编译。本节围绕诊断服务表、会话与安全等级、服务处理流程与代码生成四个关键环节展开,帮助读者建立从配置输入到可运行代码的完整认知。

一、诊断服务表:Dcm的核心数据结构

诊断服务表(Diagnostic Service Table)是Dcm配置的骨架,它决定了ECU能够响应哪些诊断服务、每个服务的子功能如何分发、以及请求与响应的数据长度约束。在MICROSAR中,服务表由若干层结构组成:最上层是服务表(DcmDslServiceTable),每个表项指向一个服务处理函数;服务内部再通过子功能表(Subfunction Table)区分同一服务的不同子功能,例如0x10服务的01/02/03子功能分别对应不同会话切换。

配置时需要为每个服务表项指定以下关键参数:服务ID(SID)、会话掩码(Session Mask)、安全等级掩码(Security Level Mask)、寻址类型(物理寻址/功能寻址)、请求最小/最大长度、响应最小/最大长度、以及是否支持抑制正响应(Suppress Positive Response)。这些参数共同构成Dcm在运行时判断“是否处理该请求”的依据。

以一个典型的0x22(ReadDataByIdentifier)服务为例,配置表项可抽象为:SID=0x22,支持物理寻址与功能寻址,请求长度3字节(SID+2字节DID),响应长度3+N字节,会话掩码允许默认会话与扩展会话,安全等级掩码要求Level 1。当诊断仪发送22 F1 90时,Dcm首先匹配服务表,再检查当前会话与安全状态是否满足掩码要求,最后调用配置的读取回调函数。

Dcm 诊断服务表结构与请求匹配路径 诊断请求 PDU 例:22 F1 90 DcmDslServiceTable SID=0x22 会话掩码=0x03 安全掩码=0x01 寻址=物理/功能 Subfunction Table 0x10 → 会话切换 0x22 → 数据读取 应用回调 ReadData 运行时状态检查(会话掩码 & 安全等级掩码) 当前会话 ∈ 服务允许会话集合? 当前安全等级 ≥ 服务要求等级? 不满足 → 返回 NRC 0x7E / 0x7F / 0x33 配置 → 代码生成映射 DaVinci 配置项 服务表 / 会话 / 安全 Dcm_Cfg.c / Dcm_Lcfg.c 服务表常量、回调指针 编译链接 Dcm.o + 应用回调 ECU 可执行 服务表决定“能响应什么”,会话与安全掩码决定“当前是否允许响应”,代码生成将配置固化为可编译常量

二、会话与安全等级管理

会话(Session)与安全等级(Security Level)是Dcm运行时状态机的两个核心维度。会话通常包括默认会话(Default Session,0x01)、编程会话(Programming Session,0x02)和扩展会话(Extended Session,0x03)。安全等级则通过0x27服务(Security Access)的种子-密钥机制解锁,常见Level 1用于一般诊断写操作,Level 2用于刷写或标定。

在MICROSAR配置中,会话与安全等级并非独立存在,而是通过“状态组合”参与服务表匹配。每个服务表项都带有会话掩码和安全等级掩码,Dcm在收到请求后,先根据当前会话状态和安全状态计算一个“当前状态掩码”,再与服务表项的掩码做按位与运算。若结果非零,说明当前状态允许该服务;若为零,则返回否定响应NRC 0x7F(服务在当前会话不支持)或NRC 0x33(安全访问被拒绝)。

配置时需要注意几个易错点。第一,会话切换服务0x10本身通常需要在默认会话和扩展会话中都可用,否则诊断仪无法从默认会话进入扩展会话。第二,0x27服务的种子请求和密钥发送必须成对配置,且密钥校验回调需要与应用层安全算法一致。第三,S3定时器(Session Timeout)超时后,Dcm会自动回落到默认会话并清除安全等级,这一行为由DcmDspSessionTimeout参数控制,典型值为5000ms。

建议在配置完成后,用CANoe或诊断仪依次执行“默认会话→扩展会话→安全解锁→读取DID→写DID→会话超时回落”的完整序列,观察每个阶段Dcm返回的响应码,以验证会话与安全掩码配置是否正确。

三、服务处理流程

Dcm的服务处理流程可以概括为“接收—解析—状态检查—分发—执行—组包—发送”七个阶段。当PDU Router将诊断请求PDU递交给Dcm后,Dcm首先进行长度校验和SID识别;若SID不在服务表中,直接返回NRC 0x11(服务不支持)。若SID存在,则进一步检查子功能、会话掩码和安全掩码。全部通过后,Dcm调用配置的应用回调函数,由应用层完成实际的数据读取或写入,并将结果写入响应缓冲区。最后Dcm根据响应长度和抑制正响应标志决定是否发送正响应。

对于需要多帧传输的长响应(如0x22读取长数据块),Dcm会与CanTp协同完成分段发送。配置时需要确保响应最大长度不超过CanTp的缓冲区能力,否则会在运行时出现缓冲区溢出或响应截断。MICROSAR中可通过DcmDspMaxResponseSize参数进行约束。

四、代码生成与集成验证

DaVinci Configurator在完成Dcm配置后,会生成Dcm_Cfg.c、Dcm_Cfg.h、Dcm_Lcfg.c等文件。其中Dcm_Cfg.c包含服务表常量数组、会话配置表、安全等级配置表以及回调函数指针表。这些文件与Dcm核心代码一起编译,最终形成可执行的诊断协议栈。

代码生成后,建议重点检查三类内容:一是服务表数组的条目数与配置是否一致;二是回调函数指针是否指向正确的应用函数;三是会话超时和安全等级回落参数是否与需求匹配。若使用MICROSAR的Dcm模块,还可以通过Dcm_GetSesCtrlType和Dcm_GetSecurityLevel等API在运行时读取当前状态,用于调试和验证。

/* Dcm_Cfg.c 中服务表片段示例(示意) */
static const Dcm_ServiceTableType Dcm_ServiceTable[] = {
  { 0x10u, Dcm_Conf_Service_10, 0x03u, 0x00u, DCM_PHYSICAL | DCM_FUNCTIONAL },
  { 0x22u, Dcm_Conf_Service_22, 0x03u, 0x01u, DCM_PHYSICAL | DCM_FUNCTIONAL },
  { 0x27u, Dcm_Conf_Service_27, 0x03u, 0x00u, DCM_PHYSICAL },
  { 0x2Eu, Dcm_Conf_Service_2E, 0x02u, 0x01u, DCM_PHYSICAL },
  { 0x3Eu, Dcm_Conf_Service_3E, 0x01u, 0x00u, DCM_PHYSICAL | DCM_FUNCTIONAL }
};

上表中,0x10服务在默认会话和扩展会话均可用(掩码0x03),安全等级要求为0;0x22服务要求扩展会话且安全等级1;0x2E写DID服务仅允许扩展会话且必须安全解锁。这些掩码值需要与诊断规范中的服务权限矩阵严格对应,任何一位配置错误都可能导致诊断仪在特定会话下无法执行预期服务。

代码生成后不要直接手工修改Dcm_Cfg.c,因为下次重新生成会覆盖修改。若需调整,应在DaVinci配置界面中修改参数并重新生成,确保配置与代码始终一致。

完成代码生成与编译后,建议在台架上执行一轮基础诊断测试:使用诊断仪依次发送0x10 03进入扩展会话、0x27 01请求种子、0x27 02发送密钥、0x22 F1 90读取DID、0x2E F1 90写入DID,并观察每一步的响应码。若某一步返回NRC 0x7F或0x33,应回到服务表掩码配置中检查对应服务的会话与安全等级设置。通过这种“配置—生成—测试—回查”的闭环,可以快速定位并修正Dcm配置中的典型问题。