3. AUTOSAR架构概览
各位好,欢迎来到第三章。前两章我们聊了DCM的整体架构和它跟DEM、PduR这些模块怎么配合。今天咱们要深入底层,看看DCM真正干活时依赖的那几个核心数据结构。
说白了,DCM就像个消息处理工厂。工厂要运转,得有流水线、有工位、有物料、有状态灯。那Dcm_DslProtocolType、Dcm_DslConnectionType、Dcm_DslMessageType、Dcm_DslStatusType这四个结构体,就分别扮演了这些角色。我个人习惯把这一章称为“诊断模块的骨架”——骨架搭不对,后面所有功能都容易出问题。
3.1 Dcm_DslProtocolType:定义“用什么方式聊”
先看第一个。Dcm_DslProtocolType,它描述的是诊断通信的“协议层属性”。你想想看,UDS over CAN 和 UDS over DoIP,虽然上层都是UDS,但底层行为完全不同。这个结构体就是用来区分这些差异的。
它的核心字段包括:
- ProtocolId:协议的唯一标识,比如0x01代表CAN,0x02代表DoIP。
- PduId:关联到PduR的PDU ID,用于收发报文。
- TimingParams:协议相关的定时参数,比如P2、P2*这些。
- ProtocolCapabilities:协议支持的能力位掩码,比如是否支持分段传输。
我记得在做一个DoIP项目时,遇到过一个问题:诊断仪发过来的请求总是超时。查了半天,发现是ProtocolType里的P2*定时配置错了。DoIP的P2*默认是5000ms,但配置里写成了500ms。嗯,这种低级错误,排查起来最费时间。
| 字段 | 类型 | 说明 |
|---|---|---|
| ProtocolId | uint8 | 协议标识,如CAN=0x01, DoIP=0x02 |
| PduId | PduIdType | 关联的PDU ID,用于收发 |
| TimingParams | struct | 包含P2、P2*、S3等定时参数 |
| ProtocolCapabilities | uint32 | 能力位掩码,如分段传输、安全访问等 |
3.2 Dcm_DslConnectionType:定义“谁在跟谁聊”
接下来是Dcm_DslConnectionType。这个结构体描述的是一个“诊断连接”。一个连接,就是ECU和一个诊断仪之间的通信通道。
为什么需要这个?因为一个ECU可能同时跟多个诊断仪通信(比如CAN和DoIP同时在线)。每个连接都需要独立维护状态。这个结构体就负责记录:
- ConnectionId:连接的唯一ID。
- ProtocolRef:指向所属的ProtocolType。
- SourceAddress:诊断仪的源地址。
- TargetAddress:ECU的目标地址。
- ConnectionStatus:当前连接状态,比如空闲、活跃、挂起。
我曾经在一个项目中,发现诊断会话总是莫名其妙被重置。排查到最后,发现是ConnectionType里的SourceAddress配置错了。两个诊断仪用了相同的源地址,导致DCM认为它们是同一个连接,状态互相覆盖。避坑指南:每个诊断仪必须分配唯一的源地址,这个在项目初期就要规划好。
3.3 Dcm_DslMessageType:定义“聊什么内容”
Dcm_DslMessageType,这是最核心的数据结构。它描述的是“一条诊断消息”。每次收到诊断请求,DCM都会把它解析成一个Dcm_DslMessageType实例,然后往下传。
它的字段非常多,我挑几个关键的说说:
- MessageId:消息的唯一ID,用于跟踪。
- RequestData:请求数据的指针和长度。
- ResponseData:响应数据的指针和长度。
- ServiceId:诊断服务ID,比如0x10(诊断会话控制)、0x22(读取数据)。
- SubFunction:子功能,比如0x01(默认会话)、0x02(编程会话)。
- MessageStatus:消息处理状态,比如待处理、处理中、已完成。
说白了,这个结构体就是诊断请求和响应的“容器”。DCM的所有处理逻辑,都是围绕这个结构体展开的。
/* Dcm_DslMessageType 简化定义示例 */
typedef struct {
uint16 MessageId;
uint8* RequestData;
uint16 RequestLength;
uint8* ResponseData;
uint16 ResponseLength;
uint8 ServiceId;
uint8 SubFunction;
Dcm_DslMessageStatusType MessageStatus;
/* 其他字段省略 */
} Dcm_DslMessageType;
3.4 Dcm_DslStatusType:定义“当前状态如何”
最后一个,Dcm_DslStatusType。它描述的是DCM模块的整体运行状态。这个结构体相对简单,但很重要。
它的主要字段:
- DcmStatus:DCM模块状态,比如初始化、运行、错误。
- ActiveProtocol:当前活跃的协议ID。
- ActiveConnection:当前活跃的连接ID。
- ErrorCode:最近一次错误的代码。
这个结构体通常用于监控和诊断。比如,当DCM进入错误状态时,可以通过读取Dcm_DslStatusType来获取错误原因。
我个人习惯在调试时,把这个结构体的内容定期打印出来。这样能快速定位问题出在哪个环节——是协议层、连接层,还是消息处理层。
3.5 四个结构体的关系:一张图说清楚
这四个结构体不是孤立的。它们之间的关系,我画了张图,你一看就明白。
从这张图可以清楚看到:
- ProtocolType 是基础配置,定义了通信协议的特性。
- ConnectionType 引用ProtocolType,并添加了连接特有的信息(源地址、目标地址)。
- MessageType 由ConnectionType创建,承载具体的诊断消息。
- StatusType 反映整个DCM模块的状态,由各个连接和消息处理过程更新。
3.6 配置时的注意事项
最后,结合我的经验,给你几个配置时的建议:
- ProtocolType 要提前规划好:项目初期就要确定支持哪些协议,每个协议的定时参数要跟客户确认清楚。我见过太多项目后期改定时参数,导致重新测试的案例。
- ConnectionType 的数量要合理:不是越多越好。每个连接都会占用内存。如果只需要一个诊断仪连接,就别配置多个。
- MessageType 的缓冲区大小要留够:特别是DoIP场景,消息可能很大。我曾经因为缓冲区配小了,导致分段传输失败,排查了好久。
- StatusType 要用于调试:在产品开发阶段,把StatusType的内容通过调试接口输出,能帮你快速定位问题。