2年之前因为在调试AUTOSAR存储协议栈的时候使用DET并没发现有用的信息,所以就武断下结论--这玩意没有用。活到老学到老吧,bug经历的多了,发现这玩意还挺有用的。说一下这个bug的背景。
在将时间同步报文改道CanTsync之后,由于这个AUTOSAR工具本身的问题以及配置工程师本身的操作手法问题,PduR中的pdu个数虽然更新,但是Pdu的Id并没更新,只是简单的删除了之前Pdu的Id,其余Pdu的ID并没改变,也就是最大的PduId号仍为85。而恰恰被改道CanTsyn的Pdu在81之前,也就是剩下的pdu有5个是在81之后的81,82,83,84,85。而代码中这个ID的总个数却变为了81,也即它只能识别0-80之间的Pdu,80以后的pdu就被当作无效pdu丢掉了。所以导致丢帧。
接下来说一下怎么用DET来排查这个问题:
第一步-打开DET
打开COM协议栈各个模块的DET和DET模块本身。
使能DET模块
不使用DLT,直接通过串口打印错误信息。
第二步-打桩
在det.c中找到Det_ReportError()这个函数,该函数的4个参数ModuleId, InstanceId, ApiId, ErrorId是DET最重要的信息。在该函数中打桩,将错误信息通过串口传出去:
void Det_ReportError(uint16 ModuleId, uint8 InstanceId, uint8 ApiId, uint8 ErrorId)
{
PrintStr("===ModuleId:%d InstanceId:%d ApiId:%d ErrorId:%d====\r\n",ModuleId, InstanceId, ApiId, ErrorId);
}
第三步-复现故障
第四步-破译错误信息
首先说ModuleId
可以参考《AUTOSAR_TR_BSWModuleList.pdf》这个文件,因为在AUTOSAR架构里面,每个模块的ID都是标准。那么ModuleId=51对应的模块就是PDUR
其实ErrorId也是标准,也可以在各个模块的模块标准内找到定义,但我们可以用更便捷的方法:
再次查ErrorId
打开PDUR模块的全部源码,找到Det_ReportError这个函数的所有调用,随便找到一个即可:
然后顺藤摸瓜,找到定义PDUR_E_INVALID_REQUEST的.h文件:
我们是顺着PDUR_E_INVALID_REQUEST这个值点进来的,但是我们本例中的ErrorId是2,是下面的PDUR_E_PDU_ID_INVALID,这个宏定义和注释已经足够明确了,如果还不满足的话就在pdur模块下搜索所有PDUR_E_PDU_ID_INVALID.
搜索到31个结果,这样显然是大海捞针,所以继续使用其他参数来进一步筛选。
再搜索InstanceId
用上面同杨的方法,找到InstanceId = 50.
找到InstanceId = 50且ErrorId是2的出处:
那很明显就是这句话了,也就是我们DET里面的信息是这句代码产生的,结合函数上下文就能对故障分析个7788,如果还不够,就借助劳特巴赫等调试工具来定位问题:
总结-DET的局限性
DET在我们调试协议栈的时候,能够帮助我们发现配置、开发中的错误,但对于程序跑飞这样的底层代码问题DET并不那么好用。这种情况下就需要借助我在《AUTOSAR实战教程 - 软件集成调试_程序跑飞一招解决》这篇文章里面介绍的方法来定位错误了。