
EasyXMen诊断模块Dcm深度剖析UDS服务从报文接收到响应发送的全过程【免费下载链接】开源小满EasyXMen代码仓库持续18年精心打造的安全车控操作系统BSW代码。项目地址: https://gitcode.com/easyxmen/XMenEasyXMen开源小满是一个持续 18 年打磨的安全车控操作系统 BSW 代码仓库其中的DcmDiagnostic Communication Manager诊断通信管理模块完整实现了 AUTOSAR 标准的诊断通信。本文带你从一张诊断报文的出生讲起彻底看懂 UDS统一诊断服务请求从报文接收到响应发送的全过程帮助新手快速掌握车载诊断模块的内部机制。一、Dcm 模块架构UDS 诊断的三层设计Dcm 模块位于 BSWCode/Dcm/代码按 AUTOSAR 经典的分层思想组织可理解为三层流水线层级核心文件职责Dsl 层协议层Dcm_Dsl.c报文收发、协议行管理、P2/P2*/P4 定时器Dsd 层服务/会话层Dcm_Dsd.c会话控制、安全访问、SID 分发调度Dsp 层数据层Dcm_Dsp.cDID 数据读写连接应用层接口每个 UDS 服务都有独立实现文件如 Dcm_UDS0x10.c诊断会话控制、Dcm_UDS0x22.c按 DID 读数据、Dcm_UDS0x27.c安全访问、Dcm_UDS0x31.c例程控制等另配有 OBD 服务实现 Dcm_OBD.c。 分层的好处新增一个 UDS 服务只需增加一个Dcm_UDS0xXX.c文件并在 Dcm_UDS.c 中注册互不影响。二、报文接收阶段Dcm_StartOfReception 入口当诊断仪Tester通过 CAN/LIN/以太网发来一条 UDS 请求如10 03切换扩展会话底层传输协议栈会通过PduR调用 Dcm 的接收入口2.1 三个接收 APIDcm_StartOfReceptionDcm_Dsl.c单帧报文入口。它做四件事通过 RxPduId查找协议行Protocol Row确定连接 ID 与接收缓冲区大小校验缓冲区是否足够容纳整条请求否则返回BUFREQ_E_OVFL从报文首字节提取 SID服务 ID存入协议控制单元把剩余数据拷贝到接收缓冲区并记录元数据发送方地址等。Dcm_CopyRxData后续数据块拷贝多帧传输时逐块接收。Dcm_TpRxIndicationDcm_Dsl.c传输协议层告知整帧接收完成/失败。2.2 协议状态机每条协议行的生命线Dcm 为每条协议行维护一个状态机Dcm_Dsl.h状态流转如下IDLE → RECEIVING → RECEIVED → PROCESSING → SENT → IDLE 接收中 收完整帧 服务处理中响应已发这个状态机是理解 Dcm 的关键同一时间一条协议行只能处理一条请求新请求到来时若状态机不空闲会依据配置决定排队或拒绝。三、请求处理阶段SID 分发与服务执行3.1 主循环驱动异步处理Dcm 不是纯中断驱动而是由周期性调用的Dcm_MainFunctionDcm.c推进所有异步流程每个周期依次执行DcmInternal_CheckTimer—— 检查 P2/P2*/P4/S3 等诊断定时器是否超时DcmInternal_ProcessTxConfirmation—— 处理发送确认驱动状态机回到 IDLEDcmInternal_ProcessRxIndication—— 处理接收完成通知把 RECEIVED 状态推进为 PROCESSINGDcmInternal_ProcessRequest—— 执行实际的服务请求处理。3.2 UDS 服务分发请求进入 PROCESSING 后Dcm 依据协议行中的SID查表分发到对应服务实现Dcm_UDS.c。以最常见的几个服务为例服务功能实现文件0x10诊断会话控制切换默认/编程/扩展会话Dcm_UDS0x10.c0x22读 DID 数据读 ECU 标定/状态数据Dcm_UDS0x22.c0x2E写 DID 数据写 ECU 参数Dcm_UDS0x2E.c0x27安全访问Seed-Key 解锁Dcm_UDS0x27.c0x31例程控制执行/停止诊断例程Dcm_UDS0x31.c0x34/0x36/0x37数据传输刷写下载块Dcm_UDS0x36.c0x19读 DTC读故障码OBD 风格Dcm_UDS0x19.c0x3ETesterPresent保持诊断会话活跃Dcm_UDS0x3E.c每个服务函数返回三种结果成功构造正响应、失败返回 NRC 负响应码、PENDING耗时操作未完成先回7F XX 78响应挂起稍后由Dcm_MainFunction继续推进——这正是长时刷写操作不会卡死诊断总线的秘密。3.3 DID 数据如何被读到以0x22 F1 90为例Dsl 层定位 SID 后Dsd 层校验当前会话/安全等级是否允许该 DID然后 Dsp 层通过配置表中的读函数指针回调应用层取数Dcm.c 中Dcm_GetVin的实现就是典型例子遍历 DID 信号表逐个调用DspDataReadFnc填充数据。若 DID 不支持当前会话返回 NRC0x31requestOutOfRange会话不匹配则返回 NRC0x7F XX 10。四、响应发送阶段从 CopyTxData 到发送确认4.1 构造响应报文正响应首字节为SID 0x40后跟服务返回的数据如10 03→50 03负响应固定三字节7F SID NRC常见 NRC 如0x10拒绝请求、0x12服务不支持、0x13子功能不支持、0x31范围超限、0x33安全访问被拒绝。4.2 传输与确认响应通过DslInternal_ProcessTransmitDcm_Dsl.c交给 PduR 发送。发送完成后底层协议栈回调Dcm_TxConfirmation主循环将其状态标记为已确认协议行状态机回到IDLE等待下一条请求。五、定时器体系诊断总线的节拍器⏱️ UDS 协议的生命由四个定时器维系配置于协议行由DcmInternal_CheckTimer统一驱动P2ECU 收到完整请求后响应正/负响应的最长时间P2*响应挂起0x78之后下一次响应含新的 0x78 或最终响应的最长时间P4诊断仪发 TesterPresent0x3E后 ECU 响应的最长时间S3会话保持超时。超时后 ECU 自动回落默认会话/安全等级——这就是为什么诊断仪要周期发送 0x3E 维持会话。此外0x10服务还带S3server 会话定时器处理Dcm_UDS0x10.c0x29统一安全访问R23-11 新增则依赖Dcm_UDS0x29_MainFunction做异步认证超时检测。六、完整时序一条 0x22 请求的生命周期把上面所有环节串起来一条 UDS 请求在 Dcm 中的完整旅程如下诊断仪 ──10/50──→ CanTp ──→ PduR ──→ Dcm_StartOfReception 【状态: RECEIVING】 │ 提取SID拷贝数据 Dcm_TpRxIndication 【状态: RECEIVED】 │ Dcm_MainFunction → ProcessRequest │ Dcm_UDS0x22 → 校验会话/安全 → 调用应用层读DID │ ┌──────────────┴──────────────┐ 成功: 50 22 F1 90 xx... 失败: 7F 22 13 │ DslInternal_ProcessTransmit → PduR → CanTp │ Dcm_TxConfirmation 【状态: IDLE】整个过程体现了典型的请求-响应异步解耦设计接收、处理、发送三个环节通过状态机和主循环串联任何一步耗时等待 Flash 写入、等待安全模块签名都不会阻塞其他协议行。七、新手上手建议先读入口从 Dcm.h 的 API 注释开始理解Dcm_Init/Dcm_MainFunction/ 收发确认四个核心接口再读状态机精读 Dcm_Dsl.h 中的Dcm_StateType与Dcm_ProtocolCtrlType这是全局脉络的地图挑一个服务精读推荐从最简单的 Dcm_UDS0x10.c会话控制入手再看复杂的 Dcm_UDS0x29.c统一安全认证关注版本记录Dcm.h 头部的修订历史记录了近百条 NRC 处理、定时器、动态 DID 等 bug 修复是理解边界条件的好材料配合周边模块看Dcm 与 ComM通信模式、Dem故障管理0x14 清 DTC 时联动、PduR路由、CanTp多帧传输协同工作理解接口关系比抠单个函数更有收获。总结EasyXMen 的 Dcm 模块以三层 状态机 主循环为骨架把 UDS 诊断从报文接收到响应发送拆成了清晰可控的异步流水线。掌握StartOfReception → RxIndication → ProcessRequest → Transmit → TxConfirmation这条主线你就能读懂绝大多数车载诊断代码了。【免费下载链接】开源小满EasyXMen代码仓库持续18年精心打造的安全车控操作系统BSW代码。项目地址: https://gitcode.com/easyxmen/XMen创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考