qq:731905316
前言:UDS...Unified diagnostic service(统一的诊断服务),可以参考14229可以获得相关服务,其中有一部分服务是用来做ECU更新的(也常被叫做FBL),笔者将谈谈这部分,大神们就见笑了。更新可分为:下位机(Bootloader),上位机(更新工具)及其之间的通信协议。
1.下位机:
通常来说下位机就是:MCU(单独就说它了)。那么MCU需要关注的几个地方无非就是:跳转和向量表重映射。之前有用过 Cortex-M0 M3 M4做过更新,M0相比 M3 M4是有区别的,因为它没有中断偏移寄存器,即:VTOR (Vector Table Offset Register)。那么针对这种情况,相关手册也给出方案,大致意思是将 RAM起始地址映射为0x0000_0000,并将App中断向量表拷贝到RAM起始地址。所以对于像M0这种情况,我们需要在App中加如下代码:
memcpy((void*)RAM_STAT_ADDRESS, (void*)APP_START_ADDRESS, vctor_size); //vctor_size 向量表大小
那么对于有中断偏移寄存器的,操作起来就更方便了,如下:
void xBSP_VectorInit(void)
{
//设置向量表基地址
#ifdef VECT_TAB_SRAM
SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */
#else
SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */
#endif
}
2.上位机:
上位机就是用来跟ECU或某种硬件设备通信的工具,像PC端软件(windows Linux IOS)或者手持机等。使用上位机的话,一般还会根据我们使用的CAN卡决定,价格从几百到十几万不等。但是对于我们而言,需要的是这个CAN卡的库,这里就拿windows开发上位机来说,需要官方的动态链接库做二次开发。通常拿到库的时候,我们需要测试设备打开,复位,发送,接收这几个比较重要的API(二次开发中用的比较频繁)。然后根据UDS协议和厂商要求开发。
3.通信协议:
基于UDS更新,不得不说 ISO 15765-2 和 ISO 14229-1.
ISO 15765-2 网络层:描述了CAN ,SF(单帧),FF(首帧),FC(流控帧)和 CF(续帧) 的传输要求。根据要求我们可以用代码实现网络层的解析。
根据 ISO 14229-1 和 厂商的要求我们可以将这一层进行更深入的解析,根据项目而言比较常用的服务有:
0x10 0x11 0x14 0x27 0x28 0x31 0x34 0x36 0x85 等。具体内容大家可以查查手册就会找到(笔者也发布了一个UDS代码生成的工具,里面也有描述 https://download.csdn.net/download/weixin_38426553/10825699)。
总体来说,协议根据标准分层解包,是比较可靠有效的方法。
4.部分代码展示 windows:
unsigned int WINAPI xCAN_TxThread(PVOID lpParameter)
{
CCAN_UDS_Win32Dlg* dlg = (CCAN_UDS_Win32Dlg*)lpParameter;
UINT8 frameReqStatus = REQ_FALSE;
UINT8 reqStatus = xCAN_FAILURE;
while(1)
{
//等待事件触发,事件由上层API产生
WaitForSingleObject(hCAN_TxEvent, INFINITE);
if (xCAN_SUCCESS == dlg->my_UDSCAN.xCAN_FrameReq(&frameReqStatus))
{
/*获取帧请求后的状态:1.准备继续发送,*/
switch (frameReqStatus)
{
case REQ_SFSUCCESS:
case REQ_FFSUCCESS:
case REQ_CFSUCCESS:
ResetEvent(hCAN_TxEvent);
break;
case REQ_CFWAITE:
break;
default:
break;
}
}
/*控制线程定时*/
Sleep(dlg->cycleTimer); //发送数据不能过快
}
return 0;
}
unsigned int WINAPI xCAN_RxThread(PVOID lpParameter)
{
CCAN_UDS_Win32Dlg* dlg = (CCAN_UDS_Win32Dlg*)lpParameter;
while(1)
{
//等待事件触发,由一个定时器提供,保证接收跟解包同步
WaitForSingleObject(hCAN_RxEvent, INFINITE);
xCAN_ReceiveFrameData(dlg);
ResetEvent(hCAN_RxEvent);
}
}
/*****************************************************/
uint8_t xSYS_CANUnpackFrame(uint8_t* indata,uint8_t* unpackOver)
{
static uint32_t frameTick = 0; //用于多帧计数
uint32_t i;
uint8_t FrmType = indata[0]&0xf0;
switch(FrmType)
{
case 0x00: //sf
{
memset(ServiceUnpackData.validData,0xff,512);
ServiceUnpackData.frameType = 0;
ServiceUnpackData.serviceType = indata[1];
ServiceUnpackData.validSize = indata[0];
ServiceUnpackData.frameNum = 1;
memcpy(ServiceUnpackData.validData,(uint8_t*)&indata[1],ServiceUnpackData.validSize);
ServiceUnpackData.isResp = 1;
*unpackOver = TRUE;
}
break;
case 0x10: //ff
。。。。。。内容太多,就不展示了。。。。。。。
6.上位机界面展示:
7.打印的相关报文:
1) 2085.814 1 Rx 07DF - 8 02 10 03 FF FF FF FF FF
2) 2094.165 1 Rx 07EB - 8 06 50 03 00 32 00 C8 00
3) 2200.169 1 Rx 07DF - 8 02 85 02 FF FF FF FF FF
4) 2204.183 1 Rx 07EB - 8 02 C5 02 00 00 00 00 00
5) 2207.624 1 Rx 07DF - 8 03 28 00 03 FF FF FF FF
6) 2214.187 1 Rx 07EB - 8 02 68 00 00 00 00 00 00
7) 2218.514 1 Rx 07E3 - 8 02 10 02 FF FF FF FF FF
8) 2224.179 1 Rx 07EB - 8 06 50 02 00 32 00 C8 00
9) 2328.289 1 Rx 07E3 - 8 02 27 03 FF FF FF FF FF
10) 2334.183 1 Rx 07EB - 8 06 67 03 C6 7E 81 6B 00
11) 2338.712 1 Rx 07E3 - 8 06 27 04 C6 7E 81 6B FF
12) 2344.193 1 Rx 07EB - 8 02 67 04 00 00 00 00 00
13) 2349.942 1 Rx 07E3 - 8 10 0C 31 01 FF 00 00 C1
14) 2354.195 1 Rx 07EB - 8 30 00 00 00 00 00 00 00
15) 2356.805 1 Rx 07E3 - 8 21 00 00 00 01 00 00 FF