UDS服务
问题1:S3超时会话计时是怎么生效的?
答:实际上每次收到一个诊断服务,DCM的会话解析函数就会将S3重置为最大值,不局限于具体的某个服务,比如(2E,22,19,14服务),那为什么还需要有3E服务呢,是因为其他的服务都需要做一些回调函数操作,比如2E服务需要写入数据,19服务需要读取DTC故障码,都有具体的ECU操作,而单独加个3E服务,实际上3E服务内部的回调函数只需要回应正响应,没有具体的内部实现,这个S3超时起作用的位置在DCM的解析函数内部,而不是在3E服务的回调函数中,当DCM检测到S3超时后,就会初始化诊断相关状态,然后请求软复位,重启。
问题2:S3超时后是执行会话切换还是请求复位?
答:
标准行为:S3 超时 → 切回默认会话。
当前代码行为:S3 超时 → 软复位。
原因:设计者为了彻底清理状态、简化 Bootloader 逻辑、或满足特定安全需求,选择了复位而非仅切换会话。
问题3:3E服务是谁发送的?
答:3E服务是由诊断仪在刷写过程中循环发送的,是ECU响应的,确保ECU内部维持会话状态,一般ECU只是被动响应。
ECU 通常不会主动发送 3E 服务,因为 3E(TesterPresent)在 UDS 协议中的定义是诊断仪(Tester)发送给 ECU(Server),用于向 ECU 表明诊断仪仍然在线。ECU 的角色是被动响应,而不是主动发起。
为什么不建议 ECU 发送 3E?
协议角色颠倒:UDS 是基于客户端-服务器模型的,诊断仪是客户端,ECU 是服务器。如果 ECU 发送 3E,那就相当于服务器主动告诉客户端“我在线”,这不符合规范,也可能导致通信混乱。
无实际意义:ECU 无法通过发送 3E 来保持自己的会话,因为 S3 定时器是由 ECU 自己管理的,只要 ECU 收到任何请求(包括 3E)就会刷新定时器。ECU 不需要给自己发送请求。
可能引起冲突:如果两个节点都发送 3E,会导致总线上出现意外的帧,干扰正常的诊断通信。
问题4:诊断服务来了之后,DCM如何处理?
答:将 UDS 请求的“解析”与“执行”分离,这是 AUTOSAR 和很多诊断协议栈的典型做法。
1.UdsFunc_A_PDU_Analysis—— 初步解析与路由
作用:在收到一帧完整的诊断请求(通过 CAN-TP 重组后)时立即调用。
做的事情:
刷新 S3 定时器(任何有效请求都重置超时)。
提取 SID,查找服务配置表,检查当前会话是否支持该 SID、数据长度是否合法。
如果检查通过,调用该服务对应的
Analysis函数(如UdsFunc_SID_DSC_Analysis、UdsFunc_SID_TP_Analysis等)。这些
Analysis函数会进一步解析子功能、检查寻址类型和安全访问等,并设置st_Uds_Dcm_Info.ui8_Cur_Task为对应的任务(如UDS_TASK_SID_DSC)。如果任何检查失败,直接设置
st_Uds_Response.ui8_ResCode(负响应码),不设置任何任务。
特点:快速、轻量,不执行具体业务逻辑,只做合法性判断和任务分发。
2.UdsFunc_Receiver_Appl_Deal—— 应用层执行
作用:在主循环(
Dcm_MainFunction)中被周期性调用,根据当前ui8_Cur_Task执行对应的Appl_Deal函数。做的事情:
通过
switch判断当前任务,调用相应服务的Appl_Deal函数(如UdsFunc_SID_DSC_Appl_Deal、UdsFunc_SID_TP_Appl_Deal)。这些
Appl_Deal函数会真正执行服务:切换会话、计算密钥、读/写数据、控制例程等,并构造正响应数据。执行完成后将
ui8_Cur_Task重置为UDS_TASK_IDLE。
特点:可能耗时较长(如 Flash 擦写),与解析分离可以避免阻塞后续请求的接收(因为
UdsFunc_A_PDU_Analysis只在收到新请求时运行,而Appl_Deal可以在后台逐步完成)。
为什么需要两个?
解耦:解析(检查合法性)和执行(实际操作)分开,便于维护和测试。
非阻塞:如果某个服务执行时间较长(如擦除 1MB Flash),解析函数可以快速返回,不影响接收新的诊断请求(尽管当前设计是单任务顺序执行,但分离后可以很容易改为多任务或状态机)。
符合 AUTOSAR 规范:AUTOSAR DCM 模块中通常有
Dcm_StartOfReception/Dcm_EndOfReception(解析)和Dcm_MainFunction(执行)的划分。
总结
不是两个解析函数,而是一个解析/路由函数+ 一个执行调度函数。
解析函数负责“能不能做”,执行函数负责“怎么做”。
问题:会话切换的规则是什么样的呢?
答:支持的会话与切换条件
| 目标会话 | 允许的当前会话 | 切换时执行的动作 |
|---|---|---|
| 默认会话 (0x01) | 默认、编程、扩展 | 1. 清除所有诊断状态(安全锁、下载/传输标志等) 2. 若当前是编程会话,则触发硬复位 3. 切换为默认会话 |
| 编程会话 (0x02) | 编程、扩展(不允许从默认直接进入) | 1. 清除所有诊断状态 2. 切换为编程会话(无复位) |
| 扩展会话 (0x03) | 默认、扩展(不允许从编程直接进入) | 1. 关闭 5 秒紧急定时器(StayInBootTimeCntEn = FALSE)2. 清除所有诊断状态 3. 切换为扩展会话 |
设计原因
禁止默认→编程:强制要求先进入扩展会话并完成安全访问,防止未授权刷写。
禁止编程→扩展:编程会话是终点,只能退出到默认会话(并复位)或超时复位,避免状态混乱。
编程→默认时硬复位:确保刷写后系统彻底重启,新程序生效。
扩展会话关闭 5 秒定时器:因为扩展会话通常有持续通信,改由 S3 超时管理,避免正常操作被误复位。
问题:软硬复位的差别?
答:软复位时一般MCU内部的RAM不会清除数据,掉电时部分信息不会丢失;而硬复位相当于掉电重启,RAM内部所有的信息都不会保存;
问题:UDS诊断服务的31例程控制的时序是什么样的?
答:UDS 请求/响应是顺序的,诊断仪发送一条请求后,必须等待 ECU 的响应(或超时)才能发送下一条请求。如果连续发送,ECU 可能无法正确处理(例如缓冲区覆盖、状态混乱)。
正确的时序如下:
1. 诊断仪发送 31 01 FF 01
2. 诊断仪等待ECU响应(使用 P2 超时,如 50ms)
- 诊断仪若收到 71 01 [数据] → 完成
- 诊断仪若收到 7F 31 78 → 进入轮询模式,执行步骤3
- 诊断仪若收到其他负响应 → 报错结束
3. 进入轮询模式(仅当收到 78):
- 等待一段时间(例如 200ms,小于 S3 超时)
- 诊断仪发送 31 03 FF 01
- 诊断仪等待ECU响应(P2 或 P2*)
- 诊断仪若收到 71 03 [结果] → 完成
- 诊断仪若收到 7F 31 78 → 继续等待并重试
- 诊断仪若超过总超时(如 30s)→ 报错
