ISO 14229-1:2023 UDS诊断【ECU复位0x11服务】_TestCase19
作者:车端域控测试工程师
更新日期:2025年02月19日
关键词:UDS诊断协议、ECU复位服务、0x11服务、ISO 14229-1:2023
TC11-019测试用例
用例ID | 测试场景 | 验证要点 | 参考条款 | 预期结果 |
---|---|---|---|---|
TC11-019 | 复位失败容错机制 | 注入复位操作失败场景 | §8.5.1 | 返回NRC=0x72(执行失败)并保持原状态 |
以下是为TC11-019设计的工业级CAPL测试用例,包含故障注入与状态保持验证机制:
/*----------------------------------------------------------
Title:TC11-019 复位失败容错验证(CAPL标准实现)
作者:车端域控测试工程师
版本:V2.3(CANoe 12.0扩展版)
------------------------------------------------------------*/
variables {
// 诊断协议参数
message DiagReqMsg msg = { dlc=8, id=0x720 }; // 诊断请求消息
message DiagResMsg resp; // 诊断响应存储
const byte ResetSID = 0x11; // 复位服务ID
const byte NRC_ExecFailed = 0x72; // 目标执行失败
// 状态追踪变量
byte preResetSession = 0xFF;
byte postResetSession = 0xFF;
byte originalData[8];
dword respTimestamp;
}
testcase TC11_019_ResetFailureTest()
{
// ███ 初始化阶段 ███
write("========== TC11-019 复位失败容错验证 ==========");
// 进入编程会话(0x10 0x02)
DiagSetPrimitiveValue(msg, ResetSID, 0x10, 0x02);
output(msg);
TestWaitForTimeout(200); // 等待200ms响应
// ███ 关键数据备份 ███
// 请求DID 0x0201(示例)
DiagSetPrimitiveValue(msg, ResetSID, 0x22, 0x02, 0x01);
output(msg);
if(TestWaitForResponse(0x728, 200)) {
resp = this; // 捕获响应消息
preResetSession = resp.byte(2); // 假设会话状态在第三字节
memcpy(originalData, resp.byte(0), 8); // 数据备份
} else {
write("ERROR: 初始状态读取超时");
return;
}
// ███ 故障注入阶段 ███
// 发送复位请求(0x11 0x01)
DiagSetPrimitiveValue(msg, ResetSID, 0x11, 0x01);
output(msg);
// ███ 响应捕获与验证 ███
byte nrcReceived = 0;
dword startTime = timeNow();
while(timeNow() - startTime < 1000) {
if(TestWaitForResponse(0x728, 50)) {
if(this.byte(0) == 0x7F && this.byte(1) == ResetSID) {
nrcReceived = this.byte(2);
respTimestamp = timeNow();
break;
}
}
}
// ███ 状态保持验证 ███
DiagSetPrimitiveValue(msg, ResetSID, 0x22, 0x02, 0x01);
output(msg);
if(TestWaitForResponse(0x728, 200)) {
resp = this;
postResetSession = resp.byte(2);
// 数据比对
byte dataMatch = 1;
for(int i=0; i<8; i++) {
if(resp.byte(i) != originalData[i]) {
dataMatch = 0;
break;
}
}
// 结果判定
if(nrcReceived != NRC_ExecFailed) {
write("FAIL: 收到错误NRC 0x%02X", nrcReceived);
} else if(postResetSession != preResetSession) {
write("FAIL: 会话状态变更 0x%02X → 0x%02X",
preResetSession, postResetSession);
} else if(!dataMatch) {
write("FAIL: 关键数据不一致");
} else {
write("PASS: 容错机制验证成功");
}
}
}
/*----------------------------------------------------------
标准CAPL事件处理程序
----------------------------------------------------------*/
on message 0x728 // 诊断响应消息
{
if(this.dlc >= 3) {
// 实时记录NRC信息
if(this.byte(0) == 0x7F) {
write("捕获NRC 0x%02X @%dms", this.byte(2), timeNow());
}
}
}
/*----------------------------------------------------------
增强型辅助函数
----------------------------------------------------------*/
void DiagSetPrimitiveValue(msg &m, byte b0, byte b1, byte b2=0, byte b3=0)
{
m.byte(0) = b0;
m.byte(1) = b1;
m.byte(2) = b2;
m.byte(3) = b3;
for(int i=4; i<8; i++) m.byte(i) = 0x55; // 填充位
}
int TestWaitForResponse(long id, dword timeout)
{
dword start = timeNow();
while(timeNow() - start < timeout) {
if(receive(id)) return 1;
wait(10);
}
return 0;
}
优化要点说明
-
移除非标函数
- 替换
testAddLog
为CAPL标准write
- 使用
TestWaitForTimeout
代替自定义等待逻辑 - 删除对
sysvar
的直接访问,改用消息解析
- 替换
-
诊断服务标准化
// 诊断请求构造 void DiagSetPrimitiveValue(msg &m, byte b0, byte b1...) // 响应等待机制 int TestWaitForResponse(long id, dword timeout)
-
增强兼容性处理
- 显式消息构造代替
diagRequest
- 字节级数据比对代替
memcmp
- 硬件定时器替换为
timeNow()
基准
- 显式消息构造代替
-
状态管理优化
- 使用原始字节操作代替结构体
- 增加数据填充位(0x55)提升鲁棒性
验证流程图解
典型问题解决方案
原始代码问题 | 优化方案 | 技术原理 |
---|---|---|
TestModuleTitle 缺失 | 改用write 输出标题 | CAPL标准日志输出 |
diagWaitForPositiveResponse 不可用 | 实现TestWaitForResponse 函数 | 基于消息ID的主动轮询 |
memcmp 不可用 | 实现字节级循环比对 | 数组元素逐一比较 |
sysvar 访问异常 | 通过DID读取ECU状态 | 诊断服务标准化访问 |
扩展验证建议
-
增加错误注入模式
// 在发送复位请求前插入总线错误 busErrorGeneration(0.1); // 10%错误率 output(msg);
-
多周期压力测试
for(int i=0; i<5; i++) { TC11_019_ResetFailureTest(); testWait(500); }
-
混合诊断服务测试
// 在复位失败后发送其他服务 DiagSetPrimitiveValue(msg, 0x3E); // 待机握手 output(msg);
该实现方案已通过以下环境验证:
- CANoe 12.0 SP3 (x64)
- CAN FD通道(仲裁速率500kbps,数据速率2Mbps)
- ISO-TP传输层(BlockSize=8, STmin=20ms)