国家兴亡匹夫有责,从神九用到CAN总线讲起(11) 细节决定成败
CAN总线的另一个重要隐患是由于协议的缺陷而不必要的停止服务。通信要保证随时提供服务,用可信赖性的属性来说,这是属于可用性(availability)的指标。CAN在什么时候不能提供服务呢?从宽一点的角度来讲,不能及时提供服务也属于此类问题。例如低优先级的消息长时间被高优先级消息所阻断,不能发送。这就引起人们在调度策略上的研究,提出各种解决方案。另一类原因是物理上有损伤,硬件已无法工作,此类问题往往用物理拓扑来解决。第三类原因是受到电磁干扰,频繁出错,通信没有了质量,所以不能服务。这往往用提高防干扰措施解决。第四类原因是协议有缺陷,在特定情况下偶尔的电磁干扰也会停止服务,扩大了电磁干扰影响的后果,我要说的问题就属于第四类。
CAN是远比RS485等先进的总线,它不仅有物理层、数据链路层,还有建筑在它上面的容错管理机制,它把节点的健康状态分为三种,第一种是正常工作的状态,在CAN规范中称为主动报错的状态(error active),节点在这种状态时发现收发有错,就会发主动报错帧(active error frame),通知别的节点,以便保证所有节点的一致性(要么大家都收下“正确“的帧,要么大家都不收这个帧,这里“正确”打引号就是因为前面所讨论的有错帧漏检)。第二种是带病工作的状态,在CAN规范中称为消极报错的状态(error passive),节点在这种状态时发现收发有错,就会发报错帧(passive error frame),只有消极报错的状态的发送节点才能通知别的节点,保证所有节点的一致性。第三种状态称为离线(bus off),离线时节点还在听总线上的通信,但是没有一般意义上的收发过程。报错是纠错的前提,有些协议需要更高层次的报错纠错机制,他们会大大增加实现的难度,大大延迟了实现所需的时间,所以无法与CAN相比。
这三种状态可以根据通信中出错的次数而转换,每个节点有二个出错计数器,用于保存通信收发过程中出错/成功的情况,当计数值小于128时为主动报错状态,任一计数器等于或超过128时变为消极报错状态,接收错计数器超128后被限值,不再增加上去,而发送错计数器超255后节点进入离线状态。离线后,节点听到总线上有128次连续的11个1,就可恢复到主动报错状态。是不是自动恢复由芯片设计者决定,一种是自动恢复,一种是必须有host的干预。出错计数器增减详细数值与规则在讨论用到时候再提及。
以前我对此进行过讨论,中文见:杨福宇,“CAN总线中的一种安全隐患“,《单片机与嵌入式系统应用》,2009, No.1,p.20-22 , 杨福宇,“CAN消极报错发送节点变为离线状态的故障“,《单片机与嵌入式系统应用》,2009, No.5,p18-20。
在这里我把要重点再提一下:
1。处于消极报错状态的节点发送的消极报错帧不能保证与其它节点的收发同步结束,由于新帧出现在消极报错帧分界符内,SOF破坏了分界符的格式,引起新的错;
2。只要不断有挂起待发的新帧存在,这个节点就在不断地出错,当然无法收发,这是一种表面上在工作而实际上不工作的等效离线状态。
3。等效离线的时间长度取决于挂起待发消息的多少,而挂起待发消息取决于总线的调度算法,在普通事件触发方式时由于没有时间同步,而且节点间时钟的制造误差,会周期性地出现挂起队列的高峰,即周期性地形成长的挂起队列,使等效离线的时间很长。
4。更有甚者,发送节点在这种连续的出错情况下会进入真离线状态,它的恢复期也是真离线时间。二者相加使节点停止服务的时间可达到数十毫秒。
因为一般介绍CAN的书籍是为设计服务的,没有提到标准中有消极报错帧分界符内的格式检查;因为这是多种规定冲突的结果;因为它是调度有关的结果,所以为了让大家了解来龙去脉,我将详细列举各证据。
图1是消极报错帧的格式,它的消极报错标志(passive error flag)由6个连续的1开始,在CAN总线上1总可以被0改写,所以它读回时并不一定是1,要等到读回6个连续的相同位才算报错标志发送结束。这是它在等有没有别的节点发报错帧,如果别的节点也发,那么或者是主动报错帧(报错标志为6个0),或者也是消极报错帧,如果这样,它们的报错帧分界符(error delimiter)是一样长的,它们在帧开始时间上是同步的。如果是局部错,那么它会等到正常帧的Ack分界符和EOF部分,它的消极报错帧分界符就会超出帧间间隔(inter frame space)中的服务间隔部分(inter mission,I.M,3位),正是这里,埋下了不断错的可能性。
图1 消极报错帧
图2是消极报错发送节点在ACK 位有局部错而发消极报错帧,它被其他接收节点理解为EOF和I.M。其它节点在I.M后开始的新帧开始符SOF=0将落在该消极报错帧的分界符内。图3是消极报错发送节点在EOF内有局部错而发消极报错帧,它的报错标志无法在这里被确认,要等到新帧的Ack分界符后才能被确认,如图2那样,它的分界符内会有更新的帧的SOF,从而不断错下去。图2. 消极报错发送节点在ACK 位有局部错而发消极报错帧
消极报错帧分界符内的错是一种格式错,国际标准 ISO 16845:2004(E) 第 8.5.13项有规定(这是对发送节点的规定,也有对接收节点的规定见7.5.6项):“(本试验)的目的是验证作为发送节点的消极报错状态的被测试单元在分界符内观察到损坏而检测出格式错。“
国际标准 ISO 11898:2003(E) 第 10.8.3规定了总线空闲的定义,即3位I.M没发现显位。10.8.4项规定了只要总线一空,主动报错节点有发送就可发送,所以不会等待任何发消极报错帧的节点结束其发送,因为它们根本不知道有发消极报错帧的节点存在。
国际标准ISO 11898-1:2003(E) 第 4.18项对发送节点有定义,这个定义很重要,它决定了连续错时它就见不到总线空闲,就一直归类于发送节点,它每次错都要增加发送错计数器,而把这个节点一直推到离线状态。
根据 ISO 16845:2004(E) 第 8.6.9项,发送节点不断错时就一直加8,所以从128到255只要有连续16个待发的帧就会使发送节点进入真正离线。
:
ISO 11898-1:2003(E) 第 13.1.4.4项规定了由离线恢复的时间,在此规定下,如果128次的发送平均每帧为100位,帧间的空闲为10位,那么恢复的时间约128*(100+3+10)=14464位。
而16次等效离线占用的时间是16*(100+3)=1648位。这样,处于消极报错状态的发送节点由于一次本地的局部错,可能产生16112位的不能服务的时间(即失效时间)。对500kbps的CAN系统,每位2us,所以有32.2ms的失效时间。如果采用29位的标识符,例如常见的用J1939协议时,同样的数据域,由于id增加18位,填充位增加4位,每帧增加22位,总的失效时间将是16112+(128+16)*22=19280位=38.4ms。像PSA厂的车用250kbps的CAN,这个失效时间将达到76.8ms。
你能容许这样长的失效时间吗?特别是在发生错帧漏检之后还不能及时用正确帧去纠正吗?…
用户1406868 2016-2-1 12:01
自做自受 2016-1-29 21:11
自做自受 2016-1-29 01:10
用户1855290 2016-1-28 18:35
自做自受 2016-1-28 12:11
自做自受 2016-1-28 11:55
yanzyzlh_937739565 2016-1-28 11:25
用户1111435 2016-1-28 11:17
用户1678053 2016-1-28 08:53
用户1454308 2016-1-28 08:22