目录
1、引言
在汽车电子领域,ECU升级通常采用UDS(Unified Diagnostic Services)协议实现。常见的实现方式包括UDS on CAN和UDS on IP,本文将重点介绍基于CAN总线的UDS协议进行ECU刷写升级的方法。
2、刷写流程
下面介绍下刷写的一般流程
编程前(PreProgramming)
- 进入拓展会话(10 83)
- 会话保持(3E 80)
- 编程前条件预检查(31 01 02 03)
- 禁用 DTC功能(85 82 FF FF FF)
- 停止通讯报文(28 81 03)
编程过程(MainProgramming)
- 进入Boot(10 02)
- Boot下的安全解锁(27 xx)
- 写入指纹信息(2E F1 5A 01 01 01 01 02 03 04 05 06 07 08 09)
- 刷写Driver文件
- 完整性检查(31 01 02 02)
- 擦除APP文件的内存(31 01 FF 00 44 01 00 00 00 00 3C 00 00 )
- 刷写APP文件
- APP文件完整性检查(31 01 02 02)
- 全部文件下载完毕后,进行编程依赖性检查(31 01 FF 01)
- 硬件重启(11 01)
编程后(PostProgramming)
- 进入拓展会话(10 03)
- 使能通讯(28 80 03)
- 解除DTC控制(85 81 FF FF FF)
3、脚本环境配置
本文介绍的刷写,UDSonCAN部分基于osek_tp.dll实现,需要在节点加载dll文件。
新建TestModule,又击打开配置页面,在Components下点击Add按钮添加osek_tp.dll,dll位置在CANoe安装目录下Exec32里。
4、编写脚本
4.1 创建can tp连接
通过调用osek_tp.dll的API接口,可以快速实现UDS协议栈功能,包括:单帧诊断请求处理、多帧诊断请求解析以及UDS参数配置等操作。
void flash_ZCUL_osektp_init(long &handle)
{
handle = CanTpCreateConnection( 0); // Normal mode
CanTpSetTxIdentifier(handle, ZCUL_Req_ID);
CanTpSetRxIdentifier(handle, ZCUL_Resp_ID);
CanTpSetAcceptOtherMode(handle, 2);
}
这段代码创建CanTP连接,设置发送和接收ID以及接收模式
4.2 发送并接收诊断消息
发送诊断请求可以使用CanTpSendData函数完成,接收诊断数据使用回调函数CanTp_ReceptionInd(long connHandle, byte data[])实现,为了使刷写脚本跟容易编写,更易读,将接收消息部分做一下处理。
variables
{
byte gOSEK_Response_Buffer[128];
dword gOSEK_Response_Length;
}
long WaitForOSEKTPResponse(byte data[],long &length,dword timeout)
{
// const dword waitDuration = 1000; // [ms]
long eventHandle1, eventHandle2, eventHandle3;
long res;
dword i,j;
eventHandle1 = TestJoinTextEvent(osektp_positiveText);
eventHandle2 = TestJoinTextEvent(osektp_negativeText);
eventHandle3 = TestJoinTextEvent(osektp_pendingText);
res = TestWaitForAnyJoinedEvent (timeout);
if (res > 0)
{
length=gOSEK_Response_Length;
for(i=0;i<length;i++)
{
data[i]=gOSEK_Response_Buffer[i];
}
if (res == eventHandle1)
{
//positive
return 1;
}
if (res == eventHandle2)
{
//negative
return 2;
}
}
else
{
return -1;
}
if(res == eventHandle3)
{
for(j=0;j<3;j++)
{
eventHandle1 = TestJoinTextEvent(osektp_positiveText);
eventHandle2 = TestJoinTextEvent(osektp_negativeText);
eventHandle3 = TestJoinTextEvent(osektp_pendingText);
res = TestWaitForAnyJoinedEvent (osektp_pendingTimeout);
if (res > 0)
{
length=gOSEK_Response_Length;
for(i=0;i<length;i++)
{
data[i]=gOSEK_Response_Buffer[i];
}
if (res == eventHandle1)
{
//positive
return 1;
}