本帖最后由 JasonLee27 于 2020-6-18 15:32 编辑
硬件环境:AC7811通用开发板 周立功USBCAN软件环境:Keil 5.23
看到有坛友提到关于CAN协议方面的移植,想起来自己之前写过一些,不过还只是一个半成品,就算是抛砖引玉吧
附件包含了网络管理的例程以及UDS的例程
网络管理的例程是参照OSEK 2.5.2的文档实现的。
诊断TP层参照15765-2标准。应用层参照14229标准,大部分变量,函数名称,宏定义都直接取自标准。大家可以参照标准来对照理解。
这里主要讲下功能的验证:
网络管理:
单个节点的话,用CAN盒接收报文的顺序应该如下,9帧alive和ring报文后,单节点进入跛行。时间间隔分别是100ms,260ms,1000ms。
如果你手里有两块以上的板子,可以进行建环测试,改一下nodeID,范围0~1F。
这是我两个node测试的结果,在单节点跛行的情况下加入一个新的节点并建环,这里可以用两块板子测试,也可以用一块板子的两路CAN测试(我的代码应该可以支持多路网络管理,修改代码即可实现)
另外网络管理还实现了休眠和唤醒操作,通过按键KEY6,KEY7实现,大家可以自行测试一下(这里只让网络管理休眠了,没有让MCU整个休眠,有需要的可以自行添加)
诊断的话有三份代码,一份是bootloader,一份是app,还有一份client是测试升级用的客户端代码。
测试诊断必须要准备两个板子了,一个板子烧写bootloader和app,此时就已经可以用周立功的CAN工具里面自带的诊断功能进行测试了(应用层只实现了一些基本的会话切换以及34,36,37服务,大多数服务应该都会回消极响应了,响应的逻辑基本参照14229里面提供的负响应判断逻辑,有根据自己以往的经验稍作修改:
诊断的升级功能,我这里实现的非常简单,因为按照完整的FBL流程,我有太多东西需要做了。
升级我仅仅实现了10,11,34,36,37服务,用于复位,以及下载,至于其他的前期后期的工作就都省了。
升级的流程可以看下client里面的代码实现,先通过10服务切换至编程模式,按FBL定义,收到编程会话请求后会复位进入bootloader并保持。后面再通过34,36,37服务将代码传输到目标板。升级完成后复位,目标板就运行了新的app了。
const uint8_t step1[]={0x02, 0x10, 0x03};
const uint8_t step2[]={0x02, 0x10, 0x02};
uint8_t sendData[520];
#define StepToal 2
const uint8_t *step[2]=
{
step1,
step2,
};
int udsClientLoop(void)
{
uint16_t index=0;
uint8_t seq=0;
uint16_t i;
uint32_t totalCount=sizeof(data);
uint32_t transferCount;
for (index=0;index<StepToal;index++)
{
TpTransmit(0, &step[index][1], step[index][0]);
while (s_waitRes==0);
s_waitRes=0;
mdelay(100);
}
index = 0;
sendData[index++] = 0x34;
sendData[index++] = 0x00;
sendData[index++] = 0x44;
sendData[index++] = 0x08;
sendData[index++] = 0x00;
sendData[index++] = 0x80;
sendData[index++] = 0x00;
sendData[index++] = (totalCount>>24) & 0xff;
sendData[index++] = (totalCount>>16) & 0xff;
sendData[index++] = (totalCount>>8) & 0xff;
sendData[index++] = totalCount & 0xff;
TpTransmit(0, sendData, index);
while (s_waitRes==0);
s_waitRes=0;
mdelay(100);
transferCount=0;
while (transferCount < sizeof(data))
{
index = 0;
uint16_t count=0;
sendData[index++] = 0x36;
sendData[index++] = seq++;
if ((totalCount - transferCount) > 128)
{
count = 128;
}
else
{
count = totalCount - transferCount;
}
for (i=0;i<count;i++)
{
sendData[index++] = data[transferCount++];
}
TpTransmit(0, sendData, index);
while (s_waitRes==0);
s_waitRes=0;
mdelay(100);
}
index = 0;
sendData[index++] = 0x37;
TpTransmit(0, sendData, index);
while (s_waitRes==0);
s_waitRes=0;
mdelay(10);
index = 0;
sendData[index++] = 0x11;
sendData[index++] = 0x01;
TpTransmit(0, sendData, index);
while (1)
{
}
return 0;
}
升级文件的制作通过编译app,会在project下生成一个uds_demo.h,这个是将app生成的bin文件转为数组,然后把这个文件替换到client的代码中即可。
这是测试过程中目标板的打印,升级后打印从update变成了old(事先烧的打印是update的)。说明app已经被替换。
this is boot
this is a update App
this is boot
this is boot
this is a old App
诊断的ID定义如下
#define NPDUidPhys (0x702)
#define NPDUidFunc (0x700)
#define NPDUidDiag (0x701)
诊断的应用层感觉写的不是很好,但CANTP写的还算凑合。
总结来说,网络管理要实现起来还是比较简单的,代码量也不大,但诊断的代码量确实有点大了,应用层的逻辑也多,自己完全实现起来还是比较费脑子的,但如果框架搭好了,那代码量也就是时间的问题了。
另外,我手里没有CANoe也没有测试用例,网络管理和诊断都没有做完整的测试,只能简单的验证一下功能。实际使用还是要慎重的
文档都是标准的,就不贴了,大家网上搜一搜就有。
OSEKNM_sample.rar
(941.37 KB)
CANUDS.rar
(3.85 MB)
|
牛X啊,小伙考虑来我司上班吧,哈哈