4. UDS诊断服务在AURIX上的实现

在AURIX TC3xx上实现UDS诊断,核心不是把ISO 14229的服务表照抄一遍,而是把每个服务的请求解析、会话与安全前置条件、内部动作、响应组装和副作用管理,落到一个可维护的状态机上。AURIX通常作为诊断目标ECU,通过CAN或CAN FD接收请求,由诊断栈完成传输层组包,再交给UDS服务分发层。本节围绕常用服务在AURIX端的实现方式,说明它们如何共享会话、安全等级和DTC状态,并给出一个可落地的状态机设计。

服务分类与共享状态

这些服务可以按“是否改变ECU状态”分为三类。第一类是会话与通信控制类:0x10(DiagnosticSessionControl)、0x28(CommunicationControl)、0x3E(TesterPresent)、0x85(ControlDTCSetting)。它们改变诊断会话、通信使能或DTC记录开关,是其他服务的前置条件。第二类是数据与例程类:0x22(ReadDataByIdentifier)、0x2E(WriteDataByIdentifier)、0x31(RoutineControl)、0x19(ReadDTCInformation)。它们读写数据、执行例程或读取故障信息,多数要求默认会话以上,部分写操作还要求安全解锁。第三类是安全与复位类:0x27(SecurityAccess)、0x11(ECUReset)、0x14(ClearDiagnosticInformation)。0x27是进入受保护操作的门禁,0x11和0x14会改变ECU运行或故障存储状态。

在AURIX端,这些服务不应各自维护私有标志,而应共享一组诊断状态变量:当前会话(default、programming、extended)、安全等级(locked、level1、level2)、通信控制状态(normal、noRxAndTx)、DTC设置使能(enabled、disabled)、以及待执行的复位类型。共享状态的好处是前置条件判断集中,响应码一致,避免某个服务绕过安全校验。

AURIX UDS服务分发与共享状态机 CAN/CAN FD 诊断请求帧 传输层 ISO-TP 组包/拆包 UDS服务分发 SID解析 + 前置条件 会话/安全/通信检查 服务处理函数 0x10 0x11 0x14 0x19 0x22 0x27 0x28 0x2E 0x31 0x3E 0x85 读写NVM / 执行例程 / 组装响应 共享诊断状态(全局) 会话状态 default/ext/prog 安全等级 locked/L1/L2 通信控制 normal/noRxTx DTC使能 on/off S3定时器(5s) · P2/P2*定时器 · 待执行复位类型 · 安全种子/密钥状态 前置条件读取 响应组装 正响应 SID+0x40 / 负响应 0x7F+NRC 经传输层回传 处理结果 副作用 复位 / 清DTC / 写NVM 会话切换 / 安全锁定 触发 定时器管理 S3: 5s 无请求 → 回默认会话 P2: 50ms 响应超时 超时

会话与安全状态机

0x10服务是状态机的驱动源。AURIX端收到0x10 01(默认会话)、0x10 02(编程会话)、0x10 03(扩展会话)时,先检查请求的会话是否允许从当前会话跳转。例如从默认会话可以直接进入扩展会话,但进入编程会话通常要求先处于扩展会话并已通过安全访问。跳转成功后,必须重置S3定时器(通常5秒),并在响应中返回P2和P2*参数,例如P2=50ms、P2*=5000ms,告诉测试仪响应超时和增强超时。若请求会话不支持,返回NRC 0x12(subFunctionNotSupported)或0x7E(subFunctionNotSupportedInActiveSession)。

0x27安全访问是两阶段握手:先请求种子(0x27 01或0x27 03),ECU生成随机种子并记录;再发送密钥(0x27 02或0x27 04),ECU用相同算法校验。AURIX端通常用HSM或软件算法生成种子和校验密钥。若密钥错误,返回NRC 0x35(invalidKey),并递增失败计数;连续失败达到阈值(例如3次)后启动延迟锁定,期间返回NRC 0x37(requiredTimeDelayNotExpired)。安全等级解锁后,0x2E、0x31等受保护服务才允许执行。安全状态在会话切换或ECU复位后应回到locked。

数据读写与例程控制

0x22 ReadDataByIdentifier按DID读取数据。AURIX端应维护一张DID表,每个DID对应数据长度、读取函数和所需安全等级。例如DID 0xF190为VIN,长度17字节,默认会话可读;DID 0xF18C为ECU序列号,扩展会话可读。收到请求后,先查表,若DID不存在返回NRC 0x31(requestOutOfRange),若安全等级不足返回NRC 0x33(securityAccessDenied)。读取函数从NVM或RAM中取值,组装成正响应。

0x2E WriteDataByIdentifier与0x22对称,但必须检查DID是否可写、长度是否匹配、安全等级是否满足。写入前建议先做范围校验,例如某标定DID只允许写入0x0000~0x0FFF,超出则返回NRC 0x31。写入成功后更新NVM,并返回正响应。0x31 RoutineControl用于启动、停止和查询例程,子功能为0x01 start、0x02 stop、0x03 requestResults。AURIX端为每个RID注册例程函数,例如RID 0x0203为“擦除应用区”,start时调用Flash擦除,requestResults返回擦除状态。例程执行可能跨多个诊断周期,因此状态机需要记录例程运行状态,避免重复启动。

故障信息与通信控制

0x19 ReadDTCInformation用于读取DTC。常用子功能包括0x02(reportDTCByStatusMask)、0x04(reportDTCSnapshotRecordByDTCNumber)、0x06(reportDTCExtDataRecordByDTCNumber)。AURIX端DTC存储通常由DEM模块管理,每个DTC有状态字节(testFailed、confirmedDTC、pendingDTC等)。0x19 02请求携带状态掩码,ECU返回所有状态字节与掩码按位与非零的DTC及其状态。0x14 ClearDiagnosticInformation按组清除DTC,收到后调用DEM清除接口,并返回正响应。注意0x14通常要求扩展会话,且清除后DTC状态应复位。

0x28 CommunicationControl控制通信。子功能0x00 enableRxAndTx、0x01 enableRxAndDisableTx、0x02 disableRxAndEnableTx、0x03 disableRxAndTx。AURIX端收到后设置通信控制状态,并影响应用报文的收发。0x85 ControlDTCSetting控制DTC记录,子功能0x01 on、0x02 off。关闭DTC设置后,新的故障不再写入DTC存储,但已有DTC保留。0x3E TesterPresent用于保持会话,收到后重置S3定时器并返回正响应;若子功能为0x80,则抑制正响应。0x11 ECUReset按子功能执行复位,例如0x01 hardReset、0x03 softReset。收到后先返回正响应,再触发看门狗或系统复位,确保响应已发出。

状态机实现要点

在AURIX端,建议用一个诊断主循环按固定周期调用UDS状态机。状态机至少包含IDLE、RECEIVING、PROCESSING、RESPONDING、PENDING五个状态。IDLE等待请求;RECEIVING由传输层组包;PROCESSING执行服务处理函数;RESPONDING发送响应;PENDING用于需要长时间执行的例程,此时返回NRC 0x78(requestCorrectlyReceived-ResponsePending),并在完成后发送最终响应。每个服务处理函数返回统一的结果结构:正响应数据、负响应NRC或pending标志。这样0x31长例程和0x11复位都能纳入同一状态机。

实现时把会话、安全、通信、DTC使能四个状态集中在一个结构体中,所有服务处理函数只读该结构体判断前置条件,只通过统一接口修改状态。这样能避免0x27解锁后0x2E仍被拒绝、0x85关闭DTC后0x19仍返回新故障等不一致问题。

最后,服务响应码要统一。常见NRC包括0x11服务不支持、0x12子功能不支持、0x13长度错误、0x22条件不满足、0x31请求超出范围、0x33安全拒绝、0x35密钥无效、0x37延迟未到、0x78响应挂起。AURIX端应在分发层统一做长度检查和会话检查,把服务特有的校验放在各自处理函数中,保证负响应行为可预测、可测试。