这次我们来看车载诊断里的 0x11 服务(ECUReset,ECU 复位)。在 UDS(ISO 14229)体系里,0x11 几乎是每个 ECU 必做的服务,可真正把它测透的项目组并不多。原因很简单:请求帧只有“SID + 子功能”两个字节,但子功能权限、会话限制、安全等级、复位类型差异、下电时序、复位后的网络管理和 DTC 状态,每一项都是独立的测试维度,设计用例时稍不注意就会漏。
先说核心特点:0x11 服务既要验证正响应链路(0x51),也要验证多条负响应路径(0x12、0x13、0x22、0x31、0x33、0x72);子功能覆盖硬复位、软复位、钥匙 OFF/ON 复位、快速下电使能/禁能;测试时还要结合诊断会话切换和安全访问解锁,并且要关注复位后的 ECU 行为。对测试工程师来说,这意味着用例不能只写“发 0x11,看有没有响应”,而要从需求文档出发逐条拆约束、按最坏情况设计前置条件和预期结果。
本文会按“根据需求设计用例”的完整流程展开:先给 0x11 服务的核心能力速览,再讲协议格式与测试边界,然后是环境准备、测试点拆解、具体用例设计、CANoe CAPL 与 udsoncan 自动化执行示例,以及常见问题和排查思路。适合刚接触 UDS 诊断测试的工程师,也适合正在写 0x11 服务测试用例、被评审打回“覆盖不全”的同行。这里说的“网络诊断”是车载总线诊断,和日常运维里常见的 DNS/网络连通性诊断是两回事,本文不涉及 DNS 排障。
1. 0x11 服务核心能力速览
设计用例前,先建立一张规格速览表。这张表直接决定测试范围,也是后续用例评审时最容易对标的一张表。
| 测试维度 | 说明 |
|---|---|
| 服务名称 | ECUReset(ECU 复位) |
| 协议标准 | ISO 14229-1(UDS) |
| 请求 SID | 0x11 |
| 正响应 SID | 0x51 |
| 负响应 SID | 0x7F(NRC 字节指示拒绝原因) |
| 主要子功能 | 0x01 hardReset、0x02 keyOffOnReset、0x03 softReset、0x04 enableRapidPowerShutDown、0x05 disableRapidPowerShutDown |
| 常见 NRC | 0x12、0x13、0x22、0x31、0x33、0x72 |
| 会话约束 | 各子功能在默认/编程/扩展会话下的支持情况,以需求文档为准 |
| 安全约束 | 部分子功能需要先执行 0x27 安全访问解锁,等级以需求文档为准 |
| 功能寻址 | 0x11 是否禁止功能寻址,以 OEM 需求为准,一般建议物理寻址测试 |
| 测试目标 | 子功能支持性、正响应内容、NRC 路径、时序、复位后行为 |
| 适合场景 | 研发验证、产线下线检测、售后诊断、自动化回归测试 |
这张表的每一条都要能对应到需求文档的具体条款。如果需求文档写明了“0x01 仅扩展会话支持且需要安全等级 0x03 解锁”,那这条就直接变成用例的前置条件和预期结果。需求里没写清楚的地方,一定要在用例评审时找 ECU 开发确认,不能在测试执行阶段再猜。
2. 0x11 服务协议行为与测试边界
0x11 服务请求格式很简单:
Byte 0:0x11(SID) Byte 1:子功能(复位类型)正响应格式:
Byte 0:0x51(SID + 0x40) Byte 1:子功能回显 Byte 2-3:powerDownTime(仅 0x04/0x05 需要,单位 ms,大端)负响应格式:
Byte 0:0x7F Byte 1:0x11 Byte 2:NRC2.1 子功能定义
ISO 14229-1 中定义的子功能类型如下,实际支持哪些、各子功能在什么会话下可用、是否需要解锁,全部以项目需求文档为准。
| 子功能 | 名称 | 行为说明 |
|---|---|---|
| 0x01 | hardReset | 模拟 ECU 电源断开再上电,硬件电路执行复位,外部电源电压不一定真正掉电 |
| 0x02 | keyOffOnReset | 模拟钥匙 OFF 再 ON,需要处理网络管理状态和外部的 KL15 状态变化 |
| 0x03 | softReset | 软件复位,不重置硬件电源,常用于应用层参数重新加载 |
| 0x04 | enableRapidPowerShutDown | 启用快速下电,正响应携带 powerDownTime,通知客户端 ECU 将在多长时间后下电 |
| 0x05 | disableRapidPowerShutDown | 禁用快速下电,取消之前使能的快速下电请求 |
测试时最容易忽略的是 0x04/0x05 子功能的 powerDownTime 字段。它不是一个可选项,而是需求中可能明确要求校验的响应数据。如果你的需求写了“0x04 正响应必须返回 0x51 0x04 + 两字节 powerDownTime,且数值范围在 xxx ms”,那用例里就必须逐个边界值去卡。
2.2 测试边界
0x11 服务有几条边界必须明确:
第一,物理寻址与功能寻址的差异。0x11 在整车网络里通常只建议物理寻址,因为功能寻址会对总线上多个 ECU 同时触发复位,容易造成整车级异常。需求如果写明“0x11 不支持功能寻址”,那测试就要覆盖功能寻址请求下 ECU 不应答或返回 0x7F 0x11 0x12 的场景。
第二,诊断会话切换代价。很多复位子功能只允许在扩展会话或编程会话下执行。如果用例里需要先切换到扩展会话,切换动作本身也可能触发安全访问等级重置,这时前置条件要写清楚。
第三,安全访问解锁状态。0x11 服务常常和 0x27 安全访问联动。用例设计时要把“未解锁请求”和“已解锁请求”都列出来,未解锁大概率返回 0x33,已解锁才期望正响应。
第四,复位后行为。复位不是“响应完就结束”。ECU 复位后大概率会回到默认会话、清掉一部分 volatile DTC、重新发起网络管理报文、总线通信需要一段时间恢复。这些行为是否在需求文档范围内,直接影响用例断言怎么写。
3. 测试环境与工具准备
在开始设计用例之前,先把测试环境固定下来。0x11 服务测试对总线工具的要求不高,但对电源控制和时序采集有要求。
硬件部分需要:
- DUT(被测 ECU)或 HIL/台架系统,能够提供 KL30、KL15 等电源控制。
- 诊断总线接口,常见的是 CAN、CAN FD、以太网 DoIP,或者带 FlexRay 的总线接口卡。
- 总线工具:Vector CANoe/CANalyzer + VN 系列接口卡,或者 PCAN、同星、周立功等支持 UDS 的接口设备。
- 可编程电源:用于模拟上下电和快速下电时序,至少能手动或脚本控制电压输出。
- 宿主机:Windows 为主,CANoe 在 Windows 下运行;如果用 python 脚本,跨平台相对灵活。
软件部分需要:
- CANoe 12 或更高版本,配置诊断通道和诊断描述文件(CDD/ODX)。
- 文本工具或 Excel 管理用例,最终用例要能导出成可评审的表格。
- python 环境,安装 python-can、udsoncan、isotp 等库,用于轻量自动化执行。
还有一个容易被忽略的点:诊断通道配置。如果用 CANoe,需要把诊断协议配置为 ISO 14229,确认寻址方式是物理寻址还是功能寻址,确认诊断报文的 CAN ID(物理请求/响应 ID),以及是否启用了 ISO-TP 分段传输。通道配置错了,后面所有用例都会得到“ECU 无响应”的假失败。
4. 从需求文档拆解 0x11 测试点
写用例最忌讳“拿到服务就抄标准”。标准只定义协议框架,需求文档才定义 ECU 的具体实现。所以第一步是把需求文档里的相关条款逐条摘出来,变成可验证的测试点。
以一份典型的 0x11 需求为例,通常会出现这些条目:
- 服务支持的子功能列表。
- 每个子功能允许的诊断会话:默认会话 0x01、编程会话 0x02、扩展会话 0x03。
- 每个子功能是否需要安全访问,以及需要的安全等级。
- 正响应格式要求,特别是 0x04/0x05 的 powerDownTime 取值范围。
- 负响应 NRC 的触发条件,例如“非扩展会话下执行 0x02 返回 0x22”。
- 复位类型的行为定义,例如“0x03 softReset 不能清除 DTC,0x01 hardReset 必须清除 volatile DTC”。
- 复位后的通信恢复时间要求,例如“复位后 200ms 内必须重新发送网络管理报文”。
- 功能寻址下的行为约束。
拆解测试点的方法很简单:每条需求条目至少映射到两个用例,一个正向用例验证正常路径,一个反向用例验证异常路径。子功能有 5 个,那至少就有 5 组正向用例;每个子功能叠加会话、安全等级、NRC 路径,就能扩展出 20 到 30 条用例。如果需求文档里写了“0x11 服务不支持功能寻址”,还要再加一条功能寻址请求的异常用例。
拆完后形成一张测试点追踪矩阵:
| 需求条款 | 测试点描述 | 对应用例 ID |
|---|---|---|
| 4.1.1 | 支持 0x01 hardReset | TC_ECUReset_001 |
| 4.1.2 | 0x02 仅扩展会话支持 | TC_ECUReset_014 |
| 4.1.3 | 0x01 需要安全等级 3 解锁 | TC_ECUReset_020 |
| 4.1.4 | 0x04 正响应包含 powerDownTime | TC_ECUReset_026 |
这个矩阵既是需求追溯的证据,也是后面用例评审时最有效的沟通工具。
5. 0x11 服务用例设计实践
这一节是文章主体。用例设计按“子功能、会话与安全、NRC 路径、响应时序、复位后行为”五个维度展开。
5.1 子功能支持性用例
子功能支持性测试的目标是确认 ECU 对 0x01、0x02、0x03、0x04、0x05 的实际支持情况,并与需求文档比对。
以 0x01 hardReset 为例:
- 测试目的:验证 ECU 在指定会话、已解锁条件下执行硬复位并返回正确正响应。
- 前置条件:ECU 上电,处于扩展会话,已完成安全访问解锁。
- 输入:0x11 0x01。
- 操作步骤:
- 发送 0x10 0x03 切换到扩展会话。
- 执行 0x27 安全访问解锁(按需求等级)。
- 发送 0x11 0x01。
- 等待正响应,记录响应时间。
- 复位后等待 ECU 重新上线,检查网络管理报文和 DTC 状态。
- 预期结果:响应帧为 0x51 0x01;ECU 执行硬复位,复位后回到默认会话,volatile DTC 被清除。
- 失败分析:若返回 0x7F 0x11 0x33,先查安全解锁是否成功;若返回 0x7F 0x11 0x22,查当前会话是否满足需求。
0x02 keyOffOnReset 的测试略有不同。它模拟钥匙 OFF/ON,通常会触发 ECU 外部唤醒和网络管理状态迁移。测试时除了检查 0x51 0x02 响应,还要关注 KL15 信号的变化和 ECU 是否在预期时间内恢复通信。如果台架支持模拟 KL15,建议把“KL15 OFF 后延迟 xx ms 再 ON”的时序做成可配置参数。
0x03 softReset 是最常用于软件刷写后的复位。测试重点是验证复位后 RAM 数据重新初始化,但非易失性存储中的数据不被破坏。可以在复位前写入一组标定数据,复位后读取比对。
0x04/0x05 快速下电相关子功能,除正响应外,必须校验 powerDownTime 字段。若需求规定“0x04 正响应 powerDownTime 应在 1000-3000ms”,则用边界值 1000、1500、3000 分别验证,记录 ECU 实际下电时间是否与返回值一致。
5.2 会话与安全访问限制用例
这一组用例的目的是验证需求中“哪个子功能在哪个会话下可用、是否需要解锁”的限制条件。
典型的会话切换用例:
| 用例 ID | 子功能 | 会话 | 安全解锁 | 预期结果 |
|---|---|---|---|---|
| TC_ECUReset_010 | 0x01 | 默认会话 | 不要求 | 正响应 0x51 0x01 或 0x22,以需求为准 |
| TC_ECUReset_011 | 0x01 | 扩展会话 | 要求 | 解锁后正响应 |
| TC_ECUReset_012 | 0x02 | 默认会话 | 不要求 | 预期 0x7F 0x22(若需求要求扩展会话) |
| TC_ECUReset_013 | 0x03 | 编程会话 | 要求 | 解锁后正响应 |
| TC_ECUReset_014 | 0x04 | 默认会话 | 不要求 | 预期 0x7F 0x22 |
执行时,每条用例都要先检查“当前会话是否正确”,再检查“解锁状态”,否则无法准确判定 NRC 是由哪个条件触发的。
安全访问组合用例建议单独列出一组:
- 未解锁执行 0x01,预期 0x33。
- 解锁后执行 0x01,预期 0x51 0x01。
- 解锁后切换会话,再执行 0x01,观察安全状态是否被重置。很多 ECU 的安全状态在会话切换后会被清掉,这时如果直接发送 0x01,预期应从正响应变为 0x33。
5.3 NRC 路径用例
NRC 路径是 0x11 服务用例评审中最常被查的覆盖维度。设计时要覆盖每一种需求中定义的否定响应码。
0x12 subFunctionNotSupported:发送一个未定义的子功能,例如 0x10。如果 ECU 不支持,预期返回 0x7F 0x11 0x12。
0x13 incorrectMessageLengthOrInvalidFormat:构造长度错误的请求,例如只发送一个字节 0x11,或在 0x11 后跟两个字节的有效负载。请求长度不是 ISO-TP 规定的 2 字节时,预期返回 0x7F 0x11 0x13。发送长度异常请求时要注意 ISO-TP 层是否会把报文发出去,需要先确认发送端不报错。
0x22 conditionsNotCorrect:在需求规定“仅扩展会话支持”的情况下,于默认会话发送该子功能,预期返回 0x22。这是最常见的条件不满足场景。
0x31 requestOutOfRange:如果需求把某些子功能值显式声明为无效,例如“保留值 0x06-0xFF”,发送 0x06 时预期返回 0x31。这条要特别注意,不能和 0x12 混在一起测,因为 0x31 和 0x12 的判定依据取决于需求对“无效值”的定义。
0x33 securityAccessDenied:未解锁情况下发送需要解锁的子功能,预期返回 0x33。
0x72 generalProgrammingFailure:这个 NRC 通常和编程会话、刷写流程有关。0x11 服务里出现 0x72 的场景较少,一般在编程过程中复位失败时出现。若需求明确了 0x72 的触发条件,则按需求设计;需求没写,这组用例可以降级不测。
5.4 响应帧与时序用例
响应帧验证不是只验证“返回了 0x51”,而是逐字节断言:
- 正响应 SID 必须是 0x51。
- 子功能回显必须与请求一致。
- 0x04/0x05 的 powerDownTime 必须是两字节,字节顺序为大端,数值在需求范围内。
时序测试要重点关注两个参数:
- P2Server 和 P2*Server。通常 P2 默认 50ms,具体值以需求为准。测试方法是在发请求时刻打时间戳,收到正响应或负响应时再打时间戳,统计响应时间是否在允许范围内。
- 复位后的通信恢复时间。很多 ECU 复位后不会立刻响应新的诊断请求,测试需要等待 ECU 重新上线。需求如果写明“复位后 200ms 内发送第一条网络管理报文”,测试就要在总线上抓帧,确认第一条 NM 报文的时间戳。
时序用例可以做成一条独立用例:发送 0x11 0x01,抓取响应帧和后续总线报文,把所有时间戳记录到测试报告里。这组用例不一定每个项目都做,但涉及快速下电和整车休眠唤醒的项目几乎必做。
5.5 复位后行为用例
复位后行为容易被测试遗漏。0x11 服务不是“响应发完就结束”,ECU 复位后会发生一系列状态变化:
- 诊断会话回到默认会话。如果测试前 ECU 在扩展会话,复位后应切回默认会话。
- volatile DTC 被清除,但 permanent DTC 可能保留。具体以需求为准。
- 网络管理报文重新开始发送。
- 应用层重新初始化,标定参数从非易失性存储加载。
设计复位后行为用例时,建议把验证动作拆成两段:第一段是复位前的状态准备,例如写入测试 DTC、读取当前会话;第二段是复位后的状态断言,例如读取会话状态、读取 DTC 状态、抓取网络管理报文。
一条完整的复位后行为用例:
- 前置条件:ECU 处于扩展会话,制造一个 volatile DTC,记录当前 NM 状态。
- 操作步骤:
- 发送 0x11 0x01。
- 等待正响应。
- 等待 ECU 重新上线。
- 发送 0x10 0x01 或直接读取当前会话。
- 读取 DTC 状态。
- 预期结果:正响应为 0x51 0x01;复位后会话为默认会话;volatile DTC 被清除;NM 报文重新发送。
- 失败分析:若 DTC 未被清除,确认写入的是 volatile 还是 permanent DTC;若会话仍为扩展会话,确认 ECU 是否真正执行了复位。
6. 用测试工具执行 0x11 服务用例
6.1 CANoe CAPL 发送与响应处理
在 CANoe 中用 CAPL 发送 0x11 请求可以用诊断发送函数,也可以直接用 CAN 报文发送函数。这里给一个基于诊断函数的示例,实际项目需要按自己的诊断通道和 CDD 文件调整。
/* 发送 0x11 ECUReset 请求 */ void SendECUReset(byte subFunction) { byte request[2]; request[0] = 0x11; request[1] = subFunction; /* 物理寻址发送,诊断通道名和请求 ID 按实际工程配置 */ DiagSendRequest(request, elcount(request)); }响应处理可以挂在诊断事件回调里:
/* 响应接收回调 */ on DiagResponse { byte respSid; byte subFunc; if (this.service == 0x11) { respSid = this.GetRespSID(); subFunc = this.GetRespData(1); if (respSid == 0x51) { write("ECUReset 正响应, subFunc=0x%02x", subFunc); /* 继续解析 powerDownTime */ } else if (respSid == 0x7F) { write("ECUReset 负响应, NRC=0x%02x", this.GetRespData(2)); } } }如果是用 CAN 报文函数直接发送,要注意自己拼装 ISO-TP 单帧或多帧。0x11 请求只有两个字节,CAN 单帧即可容纳:
/* 直接通过 CAN 报文发送 0x11 请求 */ on key 'r' { message 0x7E0 msg; msg.byte(0) = 0x02; /* 单帧,数据长度 2 */ msg.byte(1) = 0x11; /* SID */ msg.byte(2) = 0x01; /* sub-function: hardReset */ output(msg); }这里 0x7E0 是常见的物理请求 ID,实际项目的 CAN ID 要以诊断规范为准。
6.2 udsoncan 自动化脚本示例
如果项目允许使用 Python 做轻量自动化,udsoncan 是一个常见的 UDS 客户端库。它依赖 ISO-TP 传输层,实际使用时需要根据总线和接口卡选择连接方式。
from udsoncan.client import Client from udsoncan.services import ECUReset from udsoncan.connections import PythonIsoTpConnection # 连接参数需要按实际接口卡、CAN ID、波特率调整 conn = PythonIsoTpConnection() with Client(conn, request_timeout=2) as client: # 先切换扩展会话 client.change_session(0x03) # 按需求执行安全访问解锁,这里假设需要 # client.request_security_access(0x03, key) # 发送 0x11 软复位 response = client.ecu_reset(ECUReset.ResetType.softReset) if response.positive: print("正响应, subFunction =", response.service_data) else: print("负响应, NRC =", response.code)udsoncan 官方对 ECUReset 服务有封装,ResetType 的值对应标准子功能。脚本化的优势是方便回归:用例清单直接写成一个列表,逐条跑,日志统一输出。
7. 批量执行与测试数据管理
0x11 服务用例通常不是单条手动执行,而是整组批量跑。批量执行时要注意几个工程化问题。
7.1 用例清单与断言字典
在自动化脚本里,把用例定义成结构化数据,而不是写死在一个函数里:
test_cases = [ { "case_id": "TC_ECUReset_001", "session": 0x03, "unlock": True, "subfunc": 0x01, "expect_sid": 0x51, "expect_subfunc": 0x01, "priority": "P0", }, { "case_id": "TC_ECUReset_101", "session": 0x01, "unlock": False, "subfunc": 0x10, "expect_nrc": 0x12, "priority": "P1", }, ]执行循环里对每一条用例做“前置条件准备 -> 发送请求 -> 断言响应 -> 输出日志”的统一处理。任何一个用例失败时,记录完整的请求帧、响应帧、时间戳和当前会话状态,方便事后定位。
7.2 测试数据管理
建议按以下目录结构组织 0x11 服务测试数据:
tests/ cases/ ecu_reset_cases.json logs/ TC_ECUReset_001.log TC_ECUReset_002.log report/ ecu_reset_report.csv每条用例执行后把结果追加到 CSV 或 Excel 报告,至少包含:
- 用例 ID。
- 前置会话。
- 是否解锁。
- 子功能。
- 请求帧。
- 实际响应。
- 是否通过。
- 失败原因。
批量失败时不要急着改代码。优先看前三行,如果第一批全部失败,大概率是连接配置或会话切换逻辑问题,而不是子功能实现问题。
8. 资源占用与时序性能观察
0x11 服务测试里,资源占用通常不是指显存,而是总线资源、测试工具负载和 ECU 复位后的总线恢复情况。这几个点直接决定测试结果是否可信。
8.1 总线负载与报文捕获
执行复位测试时,建议同时开启总线报文记录。复位的瞬间可能会触发总线上的其他 ECU 发出大量报文,如果总线负载过高,诊断响应可能会被延迟。观察指标有两个:
- 总线负载率:CAN 总线建议不要超过 80%,超过时优先关闭不相关的周期报文,避免影响时序结论。
- 诊断响应时间:从请求帧发送到响应帧到达之间的时间差,P2 与 P2* 都要记录。
8.2 复位后上线时间
硬复位和软复位对 ECU 的启动时间影响不同。测试时在脚本里记三个时间点:
- T0:发送 0x11 请求。
- T1:收到正响应 0x51。
- T2:ECU 重新上线后发出第一条网络管理报文或应用报文。
需求如果定义了 T2 - T1 的上限,脚本里直接断言。如果需求没写,至少把这个时间记录到测试报告,作为后续评估“复位后通信恢复是否正常”的参考数据。
8.3 日志与进程清理
用 CANoe 做长时间循环测试时,注意检查日志文件大小和诊断通道状态。批量跑完 100 条用例后,如果出现“后续用例全部超时”,优先检查测试工具是否产生了残留进程或诊断连接是否断开。常见的做法是每 50 条用例强制重启一次诊断连接,并在日志里打印一条分隔标记。
9. 0x11 服务测试常见问题与排查
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
| 发送 0x11 后完全无响应 | 物理请求 ID 错误、ISO-TP 通道未配置、总线连接断开 | 检查诊断通道配置和 CAN 报文抓包 | 核对请求 ID,重新配置诊断通道 |
| 返回 0x7F 0x11 0x33 | 安全访问未解锁或解锁状态已失效 | 确认当前安全等级,检查会话切换后是否清了解锁状态 | 重新执行 0x27 解锁,再发 0x11 |
| 返回 0x7F 0x11 0x22 | 当前会话不满足子功能条件 | 读取当前会话,对比需求文档 | 切换到需求指定会话后重测 |
| 返回 0x7F 0x11 0x12 | 请求了 ECU 不支持的子功能 | 检查子功能值是否在需求支持列表内 | 改用需求支持的子功能 |
| 返回 0x7F 0x11 0x13 | 请求长度错误 | 检查发送帧的长度是否不是 2 字节 | 修正长度为 SID + 子功能 |
| 复位后 ECU 不重新上线 | 电源时序问题、ECU 启动异常、复位类型不匹配 | 抓取电源电压和总线报文,查看启动日志 | 检查 KL15/KL30 时序,按需求调整 |
| 批量测试后几十条用例全部超时 | 诊断连接卡死、工具进程残留、总线报文干扰 | 查看日志尾部,确认最后一条成功用例 | 重启诊断连接,清理进程,分批执行 |
| 0x04 正响应没有 powerDownTime | 需求可能不要求,或 ECU 实现有差异 | 对照需求文档确认正响应格式 | 以需求文档为准,必要时找开发确认 |
如果测试中出现“同一子功能第一次执行成功、第二次失败”的情况,优先怀疑安全访问状态被会话切换或外部事件重置。复测前必须把前置条件恢复到一致状态。
10. 0x11 服务用例设计最佳实践
把这部分放在最后,是希望你在真正动手之前先建立一套约束自己的规则。0x11 服务本身不大,但用例设计得是否严谨,直接体现测试团队对诊断规范的理解深度。
第一,用例必须能从需求追溯到实现。每一条用例都能对应到需求文档的某个条款或协议标准的某个行为,不被“标准如此”糊弄过去。需求里没写、协议标准里又模糊的地方,要明确标注为待澄清项,并在评审时处理。
第二,优先覆盖异常路径。正向路径只有“发请求、收正响应”,异常路径却包含子功能非法、会话不对、长度错误、未解锁、功能寻址禁发、复位失败等多条分支。评审时重点看 NRC 路径是否覆盖全。0x11 的 NRC 路径覆盖通常比正响应验证更能发现问题。
第三,复位后行为必须纳入断言。不要在收到 0x51 后直接判定用例通过。复位后的会话状态、DTC 状态、网络管理报文、通信恢复时间才是真正影响整车功能的点。建议在用例模板里单独设置“复位后验证”一栏,明确填写断言项。
第四,执行环境要可控。电源电压、KL15 状态、总线通道、诊断连接都需要在用例开始前固定下来。测试 HIL 或台架的信号差异会造成结果不稳定,因此用例前置条件必须写“ECU 已上电,KL15 = ON,扩展会话,安全访问已解锁”这类可复核的状态。
第五,合规与安全边界。0x11 是复位类服务,误操作会导致 ECU 重启、刷写中断、整车通信瞬断。在产线或实车上执行前,必须确认环境安全,并取得相关授权;不要对运行中的整车安全相关系统随意执行硬复位。涉及诊断刷写流程时,要遵循 OEM 的刷写规范和版本管理流程。
11. 总结与下一步
0x11 服务的用例设计,本质就是围绕“子功能、会话、安全、NRC、时序、复位后行为”六个维度做覆盖。请求帧虽然只有两个字节,但每条需求约束都可能展开成一组正向和反向用例,最终形成 20 到 40 条可执行的测试用例。这篇文章里给出的用例模板、CAPL 示例和 udsoncan 脚本可以直接参考调整,但一定要以实际需求文档为准,不要照搬标准里的每个 NRC 和子功能。
回到最前面的判断:0x11 服务“看起来简单、测起来麻烦”。建议你拿到需求后,先不要把时间花在写完整用例上,而是先做一轮需求澄清,把所有“支持/不支持、需要/不需要、默认/扩展/编程会话”的关键词标出来,形成测试点矩阵。再用本文第 5 节的框架把矩阵转成用例,最后用脚本批量执行并输出报告。整个过程跑通一轮之后,你会明显感觉到 0x11 服务的测试覆盖度和评审通过率都有改善。
下一步可以围绕 0x11 服务扩展三个方向:一是把它和其他诊断服务组合起来做“服务交互测试”,例如 0x11 与 0x27 安全访问、0x10 会话控制的联动;二是把用例接入持续集成,每次软件版本更新后自动回归;三是补充 DoIP 和 CAN FD 下的传输层兼容性测试,尤其是长响应的 ISO-TP 分段处理和超时重传逻辑。