OEM UDS诊断规范工程落地指南:从会话时序到DTC状态字节与闪存刷写的ECU实现要点

基于OEM《基于CAN的UDS服务》诊断工具要求规范,详解服务/会话矩阵、时序参数、DTC状态字节管理与刷写流程的ECU落地要点

2026-08-11
UDSISO 14229ISO 15765CAN诊断DTC状态字节ECU刷写否定响应码车规嵌入式

UDS(统一诊断服务)车规诊断的工程落地,成败取决于四个容易被忽视的硬性细节:会话支持矩阵、时序参数、DTC 状态字节管理与刷写(重编程)流程。本文基于一份 OEM《OEM诊断工具要求:基于CAN的UDS服务》规范译文(引用 ISO 14229-1 / ISO 15765-2/3/4 标准族),将规范中 ECU 供应商必须满足的字节级、时序级要求整理为可直接执行的实现清单:诊断帧 DLC 必须恒为 8 且填充 0x00、OBD ECU 应用层响应 P2 上限 50ms、会话保活 S3 超时 5000ms、19 服务 DTC 状态字节 8 个 bit 的精确管理语义,以及 34→36→37 刷写流程中对闪存格式(Intel .hex / Motorola .s19)、波特率、电源锁定、烧录日志与重编程计数器的明确要求。对正在为商用车、工程机械、特种车辆开发 ECU 诊断固件的嵌入式团队,这份指南可直接对照自查。

一、背景:OEM 诊断规范是 ECU 供应商的"硬门槛"

整车厂(OEM)在项目定点后,会向 ECU 供应商签发一份《OEM诊断工具要求:基于CAN的UDS服务》规范文档,其目的明确:"为 OEM 车辆开发基于 CAN 协议上使用 UDS 的各类 ECU 的诊断测试软件所需的固件支持和文档要求"。这份规范基于 ISO 14229-1(UDS 应用层)、ISO 15765-2(CAN 网络层)、ISO 15765-3(基于 CAN 的 UDS)、ISO 15765-4(排放相关系统)标准族,并对标准中由 OEM 自行裁量的部分做了强制规定。关键点在于:规范第五条明确提出"ECU供应商应与 OEM 诊断团队确认本文件的最新版本""任何偏差都需诊断团队批准"——这意味着规范中的每一条(哪怕看似啰嗦的填充字节规则)都是审核项,未满足即无法通过 EOL(生产线末端)测试与售后诊断验收。

规范的约束范围覆盖五个层级:物理层与数据链路层(DLC、填充字节)、网络层(11 位/29 位 CAN ID、SF/FF/CF/FC 帧与时序)、会话层(S3 保活)、应用层(P2 响应时序、服务字节结构)以及工程交付物(附录 A 的 EOL 工具开发文档要求)。对于长期做工业物联网、以 MCU 为中心的嵌入式开发团队而言,这套体系既是车规项目的门槛,也是把工业设备诊断能力提升到车规水准的参照系。

二、冲突:四类高频审核不通过项

对照规范逐条梳理,ECU 供应商在首轮交付中最常被 OEM 打回的四类问题分别是:

第一,帧级硬性规则执行不严。规范第 6 章与第 10 章明确规定:每个诊断 CAN 帧的 DLC 必须恒为 8,消息未填满时剩余字节填充 00h;同时"ECU 不得拒绝接收带有非零填充字节的诊断请求"。部分实现用 DLC 可变或截断帧传输,直接违反规范且无法通过网络层一致性测试。

第二,时序参数不达标或未按会话区分。规范第 7 章网络层规定:法定 OBD ECU 的接收侧响应时间 N_Ar 为 1ms、发送侧 N_As 为 21ms,接收连续帧 N_Cr 为 75/150ms;第 8 章会话层规定:测试仪在无其他请求时发送"测试仪存在"(0x3E)的周期建议 2000ms、超时 <5000ms,ECU 维持会话活跃的超时 S3 为 5000ms;第 9 章应用层规定:ECU 对请求的响应延迟 P2_CAN_ECU 为 0~50ms,收到 $78(请求已正确接收,等待响应)后最长 5s 内必须给出最终响应。时序不达标是 EOL 自动化测试失败的头号原因。

第三,DTC 状态字节管理语义混乱。规范第 11.5 章(19 服务)对 DTC 状态字节的 8 个 bit 给出了精确定义(测试失败/本循环失败/老化/已确认/自清除后未测试/自清除后失败/本循环未完成/警告指示灯),并要求 ECU 供应商正确定义 DTC 及其状态字节结构、响应最大数据长度需 OEM 批准。多数实现只维护 bit0 与 bit3,导致 14 服务清除后状态恢复、永久 DTC(子功能 15)等场景处理错误。

第四,刷写流程工程化不足。规范附录 A 对固件刷写提出了具体到"闪存文件格式、波特率、电源锁定时间、烧录日志、重编程计数器、失败后无限重试恢复"的交付要求,而不少 ECU 供应商只在开发环境里演示过刷写,从未按 OEM 规范组织过完整的 34→36→37 刷写时序与断电恢复设计。

三、问题:如何把这些 OEM 要求落地为 ECU 固件设计?

问题的本质是:OEM 规范描述的是"必须满足什么",而 ECU 固件需要回答"如何用代码与状态机实现"。以下从四个维度给出可执行的落地设计,并以 C 语言给出关键实现片段。

四、方案:四大落地点与实现要点

4.1 服务与会话支持矩阵:先定"能力边界"

规范第 11.1 章给出了 OEM 支持的 22 项诊断服务清单,第 11.3 章(表15)规定了每项服务在四种会话(默认 0x01 / 编程 0x02 / 扩展 0x03 / 固件无线升级 0x55)下的可用性。落地时第一件事就是按矩阵裁剪实现,避免"实现了多余服务反而暴露漏洞":

服务(SID) 默认会话 0x01 编程会话 0x02 扩展会话 0x03 无线升级 0x55 寻址方式
10 启动诊断会话物理
11 ECU复位物理
27 安全访问物理
28 通信控制功能
3E 测试仪存在物理
85 控制DTC设置功能
22 按标识符读数据物理
2E 按标识符写数据物理
14 清除诊断信息物理
19 读取DTC信息物理
2F 输入输出控制物理
31 常规控制物理
34/35/36/37 上传下载物理

实现要点:用一张"会话 × 服务"静态查表(而非散落的 if 判断)做会话准入控制,任何服务进入时先查表,不支持的组合直接回 NRC 0x7E(当前活动会话中不支持子功能)或 0x7F(活动会话中不支持该服务);同时在 0x10 切换会话时记录会话进入时间戳,供 S3 计时使用。

4.2 时序参数:把 OEM 数字变成定时器配置

时序要求必须落地为三组定时器:会话保活定时器(S3=5000ms,超时自动回默认会话并复位安全访问状态)、应用层响应定时器(P2_CAN_ECU=50ms,超时前未处理完则回 $78 并启动 P2*_CAN_ECU=5000ms 定时器)、网络层发送/接收定时器(N_As/N_Ar/N_Bs/N_Cr 按 OBD ECU 的 21ms/1ms/75ms/75ms 配置)。规范强调"BS 强烈建议设为 0",即分段消息传输过程中不应再发流控帧,连续帧间隔 STmin 在正常诊断模式 <=5ms、引导加载模式 =0。

时序参数 符号 OEM 要求 落地说明
ECU 响应延迟P2_CAN_ECU0 ~ 50ms超时先回 $78,再启 P2*(最长 5s)
$78 后最终响应P2*_CAN_ECU0 ~ 5s用于例程执行/闪存擦写等耗时操作
会话保活超时S3_ECU5000ms超时回默认会话并注销安全访问
测试仪保活周期S3_DT建议 2000ms,<5000ms无请求时周期发 0x3E
发送端传输时间N_AsOBD ECU 21ms普通 ECU 1000ms
接收端传输时间N_ArOBD ECU 1ms普通 ECU 1000ms
等待流控/连续帧N_Bs / N_CrOBD ECU 75/150ms普通 ECU 1000ms
块大小 / 间隔时间BS / STminBS 建议 0;STmin 正常 ≤5ms,刷写 =0分段传输期间不插流控帧

4.3 DTC 状态字节管理:8 个 bit 的完整语义

19 服务(0x19)子功能 02"按状态掩码报告 DTC"是售后诊断使用频率最高的功能,其核心是 DTC 状态字节。规范给出 8 个 bit 的精确定义,ECU 固件必须为每个 DTC 维护完整的 8 位状态机,而非只维护"有/无故障":

Bit 名称 OEM 规范语义 置位条件
0testFailedDTC 测试未完成,且在测试仪发出请求时失败当前有故障且测试失败
1testFailedThisOperationCycle本操作循环内测试失败(循环结束清除)本次点火循环失败过
2pendingDTC挂起 DTC:循环内测试至少通过一次且从未失败才会被清除一次及以上失败、未确认
3confirmedDTC已确认 DTC:检测次数足够,需存入长期存储器(如待处理 DTC 已设置一次或多次)按确认标准累计
4testNotCompletedSinceLastClear自上次清除后测试未完成清除后未跑完监控
5testFailedSinceLastClear自上次清除后至少失败过一次清除后失败过
6testNotCompletedThisOperationCycle本操作循环内测试未完成本循环未跑完监控
7warningIndicatorRequested警告指示灯点亮条件由 OEM 定义;若灯亮,已确认 DTC 必须置 1灯亮 → bit3 同步置 1

实现要点:为每个 DTC 维护 uint8_t status,监控函数每循环按上述条件更新;14 服务清除诊断信息时,仅清非永久 DTC,永久 DTC(子功能 15 可读)在对应监控成功通过前保留于非易失存储;19 服务子功能 02 请求中的状态掩码仅适用于 02/13 子功能,其余子功能(03 快照/04 扩展数据/14 检测计数/15 永久)无掩码字节,响应结构须按 OEM 批准的最大长度截断。状态字节更新代码如下:

/* DTC 状态字节更新(每监控循环调用,示意) */
#define DTC_TEST_FAILED        0x01u
#define DTC_FAIL_THIS_CYCLE    0x02u
#define DTC_PENDING            0x04u
#define DTC_CONFIRMED          0x08u
#define DTC_NOT_CLEARED        0x10u
#define DTC_FAIL_SINCE_CLEAR   0x20u
#define DTC_NOT_DONE_CYCLE     0x40u
#define DTC_WARN_LAMP          0x80u

void dtc_update_status(dtc_t *d, uint8_t test_failed, uint8_t cycle_end) {
    if (test_failed) {
        d->status |= DTC_TEST_FAILED | DTC_FAIL_THIS_CYCLE
                   | DTC_PENDING | DTC_FAIL_SINCE_CLEAR;
    } else {
        d->status &= ~(DTC_TEST_FAILED);
        if (cycle_end) d->status |= DTC_NOT_DONE_CYCLE;   /* 循环结束未跑完 */
    }
    /* 确认逻辑:挂起次数累计达到 OEM 确认标准 */
    if ((d->status & DTC_PENDING) && (++d->pending_cnt >= CONFIRM_CNT)) {
        d->status |= DTC_CONFIRMED;
        dtc_store_nvm(d);            /* 写入非易失存储 */
    }
    /* 永久 DTC:清除后监控未通过前不得清状态 */
    if (d->permanent && !(d->status & DTC_CONFIRMED) && !test_failed)
        d->status |= DTC_CONFIRMED;
}

4.4 否定响应码(NRC):建全表,按服务裁剪

规范第 11.8 章给出了覆盖全部诊断服务的通用否定响应码表(表2),从 0x10 普遍拒绝到 0x93 电压过低共 40+ 项,其中发动机工况类(0x81~0x93:转速过高/低、温度过高/低、车速、档位、刹车开关、电压等)是动力域 ECU 特有的条件类 NRC。落地时建议将 NRC 全表固化进固件枚举,并按 4.1 节矩阵为每个服务裁剪"支持的 NRC 列表",防止出现"规范要求支持 0x24 却返回 0x13"的审核问题。

NRC 名称 典型触发场景 常见实现错误
0x12子功能不受支持19 服务收到未实现子功能误回 0x31
0x13消息长度错误或格式无效0x34 地址/长度格式标识符非法长度校验缺失直接处理
0x22条件不正确刷写期间收到 0x22 读数据未做会话/状态门禁
0x24请求序列错误未请求下载就发 0x36 传输数据刷写状态机缺序列校验
0x31请求超出范围0x2F 控制不存在的 DIDDID 表越界访问
0x33安全访问被拒绝未解锁即发 0x2E 写数据跳过 0x27 直接放行
0x7E/0x7F会话/服务不受支持当前会话不允许该服务未查会话矩阵
0x72/0x73编程失败/块序列计数错误0x36 块序号不连续、擦写失败刷写容错与续传缺失
0x92/0x93电压过高/过低刷写时电源电压越界未做刷写电压门限保护

4.5 刷写(重编程)流程:34→36→37 的 OEM 细节

刷写是规范附录 A 着墨最多的部分,直接决定 EOL 刷写与售后 OTA 的成败。完整流程为:0x10 03 进入编程会话 → 0x85 01 关闭 DTC 记录 → 0x27 安全访问解锁 → 0x28 通信控制静默 → 0x34 请求下载(携带数据格式标识符、地址和长度格式标识符、内存地址与大小)→ 0x36 传输数据(块序列计数器从 1 递增,每块最大长度由 0x34 响应的"块长度最大值"决定)→ 0x37 请求传输退出 → 0x11 01 硬复位。OEM 对 ECU 供应商的交付要求包括:

刷写状态机核心是序列校验与断点续传,伪代码示例如下:

/* 刷写状态机(简化) */
typedef enum { FLASH_IDLE, FLASH_AUTHED, FLASH_REQ_DL, FLASH_XFER, FLASH_EXIT } flash_state_t;

int uds_36_transfer(uint8_t seq, const uint8_t *data, uint16_t len) {
    if (g_fs != FLASH_XFER)  return NRC_SEQUENCE_ERROR;   /* 0x24 */
    if (seq != (g_block_seq + 1) % 256) {
        return NRC_BLOCK_SEQ_ERROR;                        /* 0x73 */
    }
    g_block_seq = seq;
    if (flash_write_block(g_addr, data, len) != OK) {
        return NRC_GENERAL_PROG_FAIL;                      /* 0x72 */
    }
    g_addr += len;   /* 按 0x34 响应块长度自动换页,支持续传 */
    return NRC_NONE;
}

断电续刷的实现要点:每次成功写入一个块后,在非易失区记录"当前块序号 + 校验和",上电时若检测到刷写未完成且收到新的 0x34 请求,从记录块续传;同时依据规范"未使用的内存和可写位置应包含默认值 $FF",擦除后空区域必须以 0xFF 填充,避免残留数据被误判为有效固件。

五、总结

OEM UDS 诊断规范的核心不是协议本身,而是对时序、状态与交付物的一整套强制要求:DLC 恒为 8、S3=5000ms、P2=50ms、DTC 状态字节 8 位完整语义、NRC 全表裁剪,以及 34→36→37 刷写流程中闪存格式、波特率、电源锁定、烧录日志与无限重试恢复等工程细节。建议 ECU 开发团队以"会话×服务矩阵 + 时序参数表 + DTC 状态机 + 刷写状态机"四张清单组织固件设计,并按附录 A 提前准备 EOL 工具开发文档,即可显著降低 OEM 审核驳回率与 EOL 测试返工成本。

本文基于 译文_OEM UDS Service required.pdf 技术资料整理优化。规范引用标准:ISO 14229-1(UDS)、ISO 15765-2/3/4(CAN 网络层与会话/应用层、OBD 排放相关要求)、SAE J1962/ISO 15031-3(OBD 连接器)、SAE J2012/ISO 15031-6(三字节 DTC 编码)。

需要定制开发?

沧州艾诺威电子 — 国家高新技术企业,20+项国家专利
嵌入式系统开发 · 物联网方案 · AI智能硬件 · 一站式交付

立即微信咨询

电话:13930711029 | 邮箱:tech@czinv.com | 24小时内响应