本帖最后由 yfy812 于 2020-6-10 09:51 编辑
can的等效离线故障v2
Fault-degradation 表示系统出错时性能降级运行,尽量保存可用的功能,维持功能安全。这一概念在CAN开发时就有了,只是后来被更为重视。CAN为了满足性能下降时不是突然的,所以设计了运行的3种状态:主动报错(Erroractive);消极报错(Error passive)和离线(Busoff)。主动报错状态时,主动报错标志(active error flag)是6个D(显位),通过破坏填充位规则,使全体节点都知道,大家同时丢弃这个帧,保证了系统内数据的一致性。消极报错状态时,节点发现的错所发的消极报错标志(passive error flag)是6个R(隐位),报错帧不能通知到其他节点,也就不影响其他节点的正常收发。在离线状态时,节点停止了收发,代表出错太多的节点不会再干扰系统。这3种状态是根据出错计数器的值判断的,节点发现错时根据一定的规则确定出错计数器的增量,正常接收时每次将出错计数器减1,此外还有值的上下限。
但是由于设计上的缺陷,产生了第4种状态,即本文所述的等效离线状态:在一定条件下,节点会处于连续的出错状态,既不能发送,也不能接收其它节点所发的数据帧。而这一切并非真正发生了连续的电磁干扰类的出错。而且,越是没干扰,其他节点的传送越正常,等效离线的时间可能就越长:一直等到没有新的待发送的帧为止。
等效离线的发生有三个条件:节点已经在消极报错状态(error passive status);该节点又发生了一次局部错;其它节点有挂起待发帧在总线上等待发送。
ISO16845-2004中有关(发送节点)报错帧分界符内需要查格式错的条款截图如下: 这条规定是产生连续出错的条件:因为新发帧的SOF落在发送节点消极报错帧分界符内。
In ISO 11898-1:2003(E)[7] item 4.18:
对于发送节点,因为CAN标准这条规定,要等到见到总线空闲时它的发送状态才结束,如果因连续出错,他就一直处于发送,出错计数器就一直加上去,直至达到真正的离线状态。
CAN标准规定的消极报错帧:在发送连续R时如果没有见到6个连续的相同位则重新开始试探,读回6个连续的相同位时视为报错标志发完,然后开始发R,读回R时作为消极报错帧分界符开始,开始后必须继续有连续7个R,才算消极报错帧分界符结束。CAN标准又规定如分界符内又有D,就作为新错,节点要重发消极报错帧。
对于消极报错发送节点,发生局部错的位置可分为二类。 第1类:在ACK分界符前有回读的bit错或stuff错时,消极报错标志的连续6个R会被接收节点以填充规则检验、CRC检验发现有错,引起接收节点报错。接收节点的主动报错帧的连续6个D决定了发送节点消极报错帧报错标志结束时间的同步,就不会发生分界符内出错的情况。也就不会发生等效离线。 第2类:在ACK及分界符后到EOF第3位间有局部错时,例如CRC受干扰回读错、CRCDel回读错、EOF1\2\3回读错时,该节点所发(P.E.Flag)的6个R会被接收节点认为是正常的发送帧结尾EOF部分和2位服务间隔(I.M.)。别的节点所发新帧开始位(SOF),将落入发送节点消极报错帧分界符(P.E.Del)内,形成新错(图1)。如果别的节点所发新帧传送中未发生新错,该消极报错发送节点就见不到6个连续的相同位,它等待的6个连续的相同位将在别的节点所发新帧的ACK位后开始,它期待的(P.E.Del)将延续到别的节点所发新帧结束之后,所以只要有挂起待发帧,这种出错状态就重复下去。 由此可知,产生等效离线错误的位置数为ACK Delimiter 及EOF1~8共9位,其概率为9*BER。 图1 消极报错发送节点在ACK及其后有本地错时,对数据流的不同解释。
下面讨论待发帧堆积起来形成队列的原因。
由于CAN的事件触发调度性质,节点之间是没有时间同步机制的,即使节点的就绪时间有初始相位差,可以不发生竞争,但由于晶振频率差异,它们的就绪时间相位差也在变化,周期性地变小-过0-变大-变小。当相位差为0时就会产生竞争,竞争失败者会退出,分散在各节点的竞争失败者在总线上形成待发送的队列。例如,当节点a、b间存在晶振频率差异df=10-4时(a慢),节点间存在发送帧(假设周期相同)就绪时刻的初始相位差dt=3ms(a早3ms),那么过一段时间t=dt/df=30s之后,这个相位差就会变为0。对不同节点的不同帧,存在一个t的最小公倍数,此时堆起来的队列长度会达到最大。
这个待发队列的长度决定了等效离线的时间长度,以及出错计数器累加的次数。为此,编写了程序来求取典型应用情况下队列长度的分布及其出现比率。当知道出现比率之后便可以求得等效离线+真正离线故障的概率了。
图2仿真得到的挂起队长度与出现概率关系
在消极报错状态的发送节点遇到16次重复错后,会进入真正离线状态,所以要求取有16帧挂起待发的概率。这与ECU的设计有关,较难分析。我们以仿真来求取(程序见附录),底盘CAN总线系统内一般有6个节点,约有60个左右的消息要传送,则每个节点平均有10条消息,假定周期为10、20、50、100、1000ms等各有2条,每条帧长为97bit,加上填充位,大约100bit,在500kbps时传送1帧大约0.2ms。6个节点的总线负载率总计43.4%。当一个节点等效离线后,还有5个节点约50条消息要发,总线负载率总计36.2%。在时钟差的影响下,可以构成一个峰值,节点在相对频差-0.2、0.4、0.6、0.8*100ppm下的仿真结果见图3。其中队列长度每0.2ms统计一次(送完1帧),累计出该队列长在整个仿真时间内的出现次数。为了便于ECU编程,采样与写CAN控制器在一个任务中完成,所以假定10条消息在4ms内就绪。仿真开始时是最坏情况:所有节点同时开始写CAN控制器任务。有初始相位差时,可能会经过较长时间(最小公倍数)达到消除初始相位差影响,但总是存在这样一个所有节点同时要求发送的最坏情况。在上述频差下,节点1、2经500s差10ms,也就是说二个节点的10ms周期的消息就绪时间又重合了,其它节点与节点1的组合各为250s、166s、125s又重合了。由于较长周期消息对挂起队长的影响较小,所以仿真的时段取得较短。以600s的结果计算,挂起长度为16以上的情况有3590次,占600秒内传送的总次数的比率为1.2*10-3。需要特别注意的是,挂起队长的分布不是均匀的,因此处于等效离线而转为真正离线的机会也不是均匀分布的。由上述仿真60s、600s的结果看,挂起长度为16以上的情况都是3590次,如果在最坏情况60s内遇上了的机会便是1.2*10-2。如果在最坏情况6s内遇上挂起长度为16以上的情况有1005次,机会便是3.3*10-2。 图中队列长度18的出现数比队列长度17次的多,可以由下解释:虽然每个18队都要经过17队而下降,但是处于18队时仍可能增长到19队或更长,它们退下时又要经过18队状态。而在某时,由于同时就绪的消息多于2个,所以使队长度直接由小于17而跳到18,从而使18队的出现次数多于17队。 于是,消极报错发送节点发生等效离线而进入真正离线的概率是P=BER*9* 1.2*10-3,其中BER为误码率。这是一个乐观的估计,实际情况可能更大。 当在坏状态时,BER=0.01,便有P=1.08*10-5。
对消极报错接收节点,ISO16845也有检查(P.E.Del)的类似规定。发生在帧内任一位的局部错均可能产生类似的情形,即(P.E.Del)内遇到其它节点挂起待发帧的发送,造成再出错的情形。假定帧长为135位,那么其等效离线的概率是P=BER*135*1.2*10-3。消极报错接收节点在等效离线时是不能收发的,会引起收发的丢帧,由于不能发,会加长后面时段待发的队列。但是消极报错接收节点不会进入真正离线的状态。等这个节点处于可发送状态时它仍然是消极报错状态,就有上述真正离线的状态的风险了。
离线的时间
发生等效离线的节点不再能发送,所以应扣除消息源是该节点的那些帧。此时的分析方法可以参考CAN的传统调度分析方法,最坏的情况是最低优先级消息的送达时间。这样分析的结果与应用的具体配置有关,对每一个节点是不同的。 假定挂起待发的消息平均有4字节数据,采用11位ID,平均填充位取8位,再加3位服务间隔,那么16帧导致的等效离线为16*(84+3)=1392bit,真正离线的时间为128个帧,最坏情况为帧间有10 bit的空闲。所以真正离线将有128*(84+3+10)=12416 bit。二者相加,消极报错发送节点出错后会有的总计13808bit的不能服务的时间,在500kbps速率下,这相当于27.6ms。如果采用29位ID,填充位也增加,帧长变为105bit,此时消极报错发送节点出错后不能服务的离线时间将达34.5ms。有的车采用250kbps速率,那将有69ms不能服务的离线时间。
34.5ms对应用有什么意义?假定车以120km/h运动时要紧急刹车,那么刹车延迟34.5ms相当于多移动了34.5*10-3*120*103/3600m=1.1m,增加了追尾可能。1.1m是很严重的,2010丰田prius召回就是因为ABS延迟60ms动作造成刹车距离有0.7m的增加。 图3 2010 prius 召回的考虑是增加了0.7米的刹车距离
假定刹车信号为每20ms一次,对4轮驱动有4个ECU时,如果某个ECU a**速a信号时出错,ECUa进入等效离线和真正离线。这意味着连续有另1次收不到轮速a信号,它们会以某种估值替代,不会准确。ECUa等效离线,也收不到其他ECU来的所有信号,估值替代更不准,无法正常工作。此时车会有点转向,在弯道上便有转出路肩的可能。 文献[F.Cornoet al.”A MULTI-LEVEL APPROACH TO THE EPENDABILITYANALYSIS OF CAN NETWORKS FOR AUTOMOTIVE APPLICATIONS” 17th Symposium on Integrated Circuits andSystems Design, 2004. SBCCI 2004. Volume, Issue, 7-11 Sept. 2004 Page(s): 71 –75]描述了阶跃转向的仿真,the step steermaneuver (ISO 7401:2003) 。该系统有6个节点,16个信号与转向有关,在10秒内交换了9000个帧。注入10000个错误到CAN寄存器,统计出其中38.3%与丢包有关。仿真中使刹车节点的CAN有限自动机造成丢包断网(The faulty trajectoryis the result of a soft error in the state register of the FSM implementing theCAN protocol controller that equips the Brake node.),其他都正常。该文称:“丢包更为风险大,在转向开始后的1-1.25秒内发生的故障严重影响后面的操控,无法更新车轮的信息使车动态控制器采用了最临界的决策,显著地影响后面的行为”(“Faults classified asPacket or Burst loss are conversely more critical. Our analysis showed that iforiginated in a time ranging from 1.00 second to 1.25 second from maneuver’sstart, the faults could dramatically alter the maneuver. In this time lapse,the VDC takes the most critical decisions, and thus the lack of updatedinformation about the wheels’ status affects dramatically the behavior of thecar.”。本文的等效离线后果与他是相同的,因此可以引用来参考。由于该文的刹车节点的CAN有限自动机注入错误的描述不够详细,很可能在1次注入错造成在Bus off 之后,也自动回到error active 状态,如是这样,等同于真正离线时间的影响。那么本文分析的(发送节点由等效离线再到真正离线的)后果,就因为有外加的等效离线时间,可能比该文的仿真结果还要坏。
图4表示为该文的丢包引起弯道外冲的仿真结果,图中的单位为m (the axis reports the car’s position expressed in meters).
用等效离线时的丢包数也可以表示系统的服务品质,例如本文仿真中队列的长度就可以表示丢包的数目,6s内遇上挂起长度为16以上的情况有1005次,机会便是3.3*10-2。对等效离线的接收节点,假定帧长为135位,那么其等效离线的概率是P=BER*135*3.3*10-2。则6秒内出现连续丢16个以上包的概率为Plost>16=0.01*135*3.3*10-2=4.4*10-2。这也是非常大的。所以改进等效离线故障是十分必要的。
附录. 计算挂起待发队列长度出现概率的程序
% busy.m %此程序用于计算CAN总线上挂起待发的帧有多少 % 总线上有5 个节点,每个节点的本地晶振是有频差的 % 每个节点有要发送的帧10条,周期为5种: 10ms(m1,m2), 20ms(m3,m4), 50ms(m5.m6),100ms(m7,m8) 和1000ms(m9,m10),其中mi的i已经代表了帧的优先级 % 这些帧的就绪时间相互之间有相位为0ms(m1), 5ms(m2)(即10ms周期的一半), 1ms(m3),11ms(m4) (即20ms周期的一半); 2ms(m5), 27ms(m6) (即50ms周期的一半), 3ms(m7), 53ms(m8) (即100ms周期的一半), 4ms(m9),504ms(m10) (即1000ms周期的一半) % 晶振频差的变化为 (-0.8,-0.6,-0.4,-0.2,0,0.2,0.4,0.6 and0.8)*100ppm %假定节点1 为准确的,即频差为 0 ;其它节点可在上述范围内选,但没有相同的 % 帧长相同,为0.2ms % 仿真时长为10000s, 362 frames/second/node. 即3.62*10^6 帧/节点/一次仿真. % %当计时单位为0.2ms时,节点内各帧的初始相移bias和周期period 可写为: bia(1)=0;bia(2)=2;bia(3)=4;bia(4)=6;bia(5)=8;bia(6)=10;bia(7)=12;bia(8)=14;bia(9)=16;bia(10)=18; ped(1)=50;ped(2)=50;ped(3)=100;ped(4)=100;ped(5)=250;ped(6)=250;ped(7)=500;ped(8)=500;ped(9)=5000;ped(10)=5000;
% 节点频差设为,这部分本来考虑循环测试每一种频差的组合,最后只使用了一种组合,即:fset=0,-0.2,0.4,0.6,0.8 %para(1)=-0.8;para(2)=-0.6;para(3)=-0.4;para(4)=-0.2;para(5)=0.2;para(6)=0.4;para(7)=0.6;para(8)=0.8; %fset(1)=0; %节点1为准确的 %for i1=1:1:4 % for i2=i1+1:1:6 % for i3=i2+1:1:7 % for i4=i3+1:1:8 % fset(2)=para(i1);fset(3)=para(i2);fset(4)=para(i3);fset(5)=para(i4); % end % end % end %end
%时间单位为0.2ms, 仿真步长0.2ms, 整个仿真 5*10^6 步 % 初始化 %所有节点的所有帧发送请求job未就绪 job=zeros(5,10); %row=5=节点, column=10=帧 lastcyc=job; %定义lastcyc维度,lastcyc代表已经经过的周期数 lastcyc(1:5,1:10)=-1; % 节点i帧j的周期数lastcyc, 第1个周期为lastcyc= 0 %susnum的column代表待发队长度,取初值全0 susnum=zeros(1,50); % susnum的值代表该长度在仿真中出现的次数 %susnum(1) 代表无挂起帧,这是matlab数组由1开始决定的, %susnum(2) 有1个挂起帧
% 主程序 for runstep=1:1:3000000 %决定就绪的job 数 localstep(1)=runstep; for j=2:1:5 %节点 2 到5 localstep(j)=runstep*(1+fset(j)*10^-4); %本地时间,单位0.2ms end for j=1:1:5 %检查节点j内帧k是否应该就绪 for k=1:1:10 %检查节点j内的每个帧k temp=floor((localstep(j)-bia(k))/ped(k)); %找帧k经过了几个周期ped(k) if temp>=0 %temp代表了周期数,已取整,第1个周期= 0 if lastcyc(j,k)~=temp %上一仿真步周期数比本次小才开始新的寻求发送的job,这里是不等于判断 lastcyc(j,k)=temp; %更新帧k上一周期的**值 job(j,k)=1; %节点j的帧k在本次仿真步时就绪请求发送 %条件不满足时lastcyc的状态不变 end end end end %计算总线上待发帧的数目 temp=0; %代表待发数初值,复用此变量 for i=1:1:5 %节点i的循环 for j=1:1:10 %节点i中帧j的循环 if job(i,j)==1 %帧j是否就绪 temp=temp+1; %帧j就绪就入待发排队,等待竞争发送,此时temp代表了队长度 end end end susnum(temp+1)=susnum(temp+1)+1; %susnum中保存整个仿真中队长为temp+1的个数,由matlab数组定义由1开始,故+1 %susnum(1) 代表无帧待发 %当前的发送过程 jobt=0; %发送job尚未寻到,初值 for k=1:1:10 %帧的优先级循环,k=1是最高优先级帧 for i=1:1:5 %在节点i内寻找 if jobt==0 %已定发送了就跳出 if job(i,k)==1 %节点i的帧k就绪时 job(i,k)=0; %将此发送job消除 jobt=1; %发送job已寻到 end end end end ifrunstep==30000 %绘图 i=12:1:50; %从队长度=12开始绘图 plot(i,susnum(i-1),'ro--'); % grid on a=susnum %在matlab工作窗口内显示当时的队长分布 end %以下为不同仿真长度时用的 ifrunstep==300000 i=12:1:50; hold on; plot(i,susnum(i-1),'go--'); grid on a=susnum end ifrunstep==3000000 i=12:1:50; hold on; plot(i,susnum(i-1),'bo--'); grid on a=susnum end end a=1
|