从1980年代,Kvaser就开始CAN产品的研发,在相关产品开发领域有近40多年的经验,对CAN和相关总线技术有着非常深入的研究。广州智维电子科技是KVASER的中国引进者,我们会不定期分享一些有趣的发现和特定情况的技术处理。
在开发严重依赖通信协议的软件应用程序时,关键问题之一是:应用程序快速地处理传入的报文,而不会丢弃报文。本文就将分享如何使用CANlib检测CAN帧溢出情况。
在将CAN数据导入应用程序时发生丢失CAN帧的情况,通常是由于应用程序花费太多时间处理某一报文,应用程序暂停等待用户交互,或者应用程序正在等待共享系统资源,如数据文件等等。不管什么原因,应用程序开发人员应该计划检测这些丢弃的报文,以防止在由应用程序行为导致错误时搜索系统问题。
为了检测这个问题,CANlib提供了三种方法来检查接收缓冲区状态和确定CAN帧是否已经丢弃:
1.canRead标志参数
用于确定CAN帧是否已被丢弃的第一种方法是监视由canRead函数返回的标志参数。标志参数包含两个位,它们表示在此函数调用和和当前调用返回的最后一个报文之间是否发生软件或硬件溢出。这些位被定义为用于硬件溢出的canMSGERR_HW_OVERRUN和用于软件溢出的canMSGERR_SW_OVERRUN。你也可以使用canMSGERR_OVERRUN掩码同时检查这两种情况。因此,当应用程序检查到这些位集中的一个时,应用程序就会获知在当前CAN帧和接收的前一个CAN帧之间丢弃了报文。
要了解在使用软件的情况下如何显示,可以假设一个接收缓冲区,它可容纳10帧(当然,CANlib中的实际默认接收缓冲区大小远大于10)。硬件已接收到10个CAN帧并将其放入可填入的缓冲区。
硬件接收到另一个CAN帧,但接收缓冲区已满,因此该帧未添加到缓冲区。
硬件接收到第12个CAN帧,覆盖未添加到缓冲区的帧。
应用程序调用canRead删除第一个接收的CAN帧,并为要添加到接收缓冲区的第12帧留下点。
第1到10的CAN帧在由canRead检索时不会指示溢出。当第11帧丢弃,通过canRead从缓冲区检索时,第12个CAN帧将指示溢出。
canReadStatus
用于确定CAN帧是否已被丢弃的第二种方法是调用canReadStatus。如果设置了canSTAT_HW_OVERRUN或canSTAT_SW_OVERRUN位,该函数返回的标志参数将指示溢出。你可以使用canSTAT_OVERRUN掩码检查这些溢出位是否已设置。
此状态信息是异步更新的,意味着canReadStatus返回的值是最后一次报告的值,但不一定是当前状态。要确保报告的数据是最新的,你可以以周期性速率调用canRequestChipStatus。canRequestChipStatus要求更新状态信息,但是函数退出时信息不是最新的。调用完成后将保持当前的状态一段时间。
所以让我们拿前面的我们的完整的缓冲区以及硬件接收到第11个报文为例来说明。我们每秒调用canRequestChipStatus两次,每秒调用一次canReadStatus。
此时canReadStatus不会指示溢出。当硬件接收到第12个CAN帧覆盖未添加到缓冲区的帧时,芯片状态改变以指示溢出。
在下一个周期性canRequestChipStatus调用过程中报告该状态开始。当进程完成时,下一次调用canReadStatus将指示溢出。这意味着根据第12个CAN帧在canRequestChipStatus和canReadStatus调用的周期中到达的时间,canReadStatus调用将不会在事件(在本例中)后最多一秒钟指示状态。
一旦在canReadStatus调用的标志参数中指示溢出,状态将保持锁定状态,直到你使用canIOCtl例程与canIOCTL_CLEAR_ERROR_COUNTERS函数清除状态。这是为了防止应用程序由于检查到溢出和使用canReadStatus例程轮询状态之间的竞争情况而丢弃检测到的溢出。
请求接收缓冲区级别
第三种方法是通过使用函数参数设置为canIOCTL_GET_RX_BUFFER_LEVEL的canIoCtl例程来监视接收缓冲区的当前深度。返回的缓冲区将是当前存储在接收缓冲区中的CAN帧的计数。
请记住,有时候与其把时间花费在检查缓冲区级别,不如花点时间清空接收缓冲区。在执行预定义块传输时,检查接收缓冲区级别可能更有用,其中应用程序可以等待直到在处理帧之前接收到整个块。
注意事项
你可能会注意到,当使用第二、三个方法(canReadStatus或canIOCTL_GET_RX_BUFFER_LEVEL)时,如果缓冲区已满并处于溢出状态,那么在接下来的canRead调用中指示溢出状态。要在这些方法中检索数据,接收队列必须置于稳定状态,以便检查整个队列。在此过程中,由于空间不足,报文可能在驱动程序和应用程序缓冲区之间被丢弃。这种丢弃由使用canRead检索的下一个CAN帧的溢出状态表示。
要点总结
应用程序开发人员应该在canRead()处理期间始终检测丢弃的报文,以防止在由应用程序行为导致错误时搜索系统问题。你的应用程序设计可能会对CAN总线上的流量造成问题,这是你的第一条指示。使用此方法进行监视将有助于在握手报文丢弃或预期的周期性报文超时时,确定故障发生在何处。虽然你可以使用单独的工具来监视总线上所需的报文,但监视溢出标志将指示你的应用程序节点是最终原因或至少有风险。
你可以使用canRead溢出信息来跟踪溢出的频率。当流量带宽由于报文突发而增加时,这可以识别应用的可能问题。
当在GUI上指示当前溢出状态或向用户发出重要报文可能已被丢弃的警告时,使用canReadStatus方法。
当你愿意停止GUI或其他进程时,将使用检查接收缓冲区级别,以便在达到特定大小后专门计算资源立即清空缓冲区——防止发生溢出。一个这样的情况是闪烁节点。