热度 28
2013-5-20 09:53
1951 次阅读|
11 个评论
国家兴亡匹夫有责,从神九用到 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 位有局部错而发消极报错帧 图 3 消极报错发送节点在 EOF 内有局部错而发消极报错帧 消极报错帧分界符内的错是一种格式错,国际标准 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 。 你能容许这样长的 失效时间 吗?特别是在发生错帧漏检之后还不能及时用正确帧去纠正吗? …