搞了两年的Autosar,用到的网络管理都是Autosar网络管理,虽然偶尔有听到或看到Osek网络管理,但是一直没机会具体进行开发和测试。最近有机会具体接触和开发到,弄完之后感受就是:还是Autosar的网络管理好用,Osek Nm状态比Autosar Nm复杂一点,而且Osek Nm不好测试。
目录
前言
以逻辑环为理解OSEK网管的切入点:
Osek网管报文的字节数据定义
1、(开始)逻辑环是怎么建立的?
步骤1:主动唤醒的节点发出Alive报文
步骤2:被动唤醒的节点发出Alive报文
步骤3:接收到Alive报文,ECU更新逻辑环中自己的后继节点
步骤4:ECU发处Alive报文前后的OSEK NM状态跳变情况
步骤5:CAN总线上发出第一帧Alive报文的ECU节点等待“TTyp”时间后,发出第一帧Ring报文,其它节点按照逻辑顺序发出Ring报文
步骤6:逻辑环建立完成
2、(结束)如果所有ECU都不需要工作了,如何结束逻辑环进入休眠?
中间小结:
3、(运行过程)逻辑环运行过程中,有一个新的ECU节点加入怎么处理?
4、(运行过程)逻辑环运行过程中,有一个ECU节点异常退出怎么处理?
某个ECU异常退出对于其它节点网管状态的影响:
某个ECU异常退出对自己内部网管状态的影响:
1、具体如何进入LimpHome状态:
2、进入LimpHome状态后的动作:
3、如何从LimpHome状态恢复
OsekNm与Autosar网管的区别:
网络休眠->网络唤醒:
网管唤醒后正常工作:
网络唤醒->网络休眠:
异常情况:
前言
据我目前所知,网络管理有Osek网络管理和Autosar网络管理。Osek网络管理具体又分为Osek直接网络管理和Osek间接网络管理。Autosar网络管理只有Autosar直接网络管理。
直接网络管理:简单来说就是通过网管报文实现网络管理
间接网络管理:简单来说就是通过应用报文实现网络管理(间接网络管理没有网管报文)
而在汽车电子领域,网络管理的目的就是为了汽车上各个ECU节点能够同起同睡(关于同起同睡,可以点这里详细理解)。
本篇文章讲的是Osek直接网络,同时对比Autosar网络管理。
另外,再科普文中需要提前理解的概念:网管报文、ECU地址
网管报文:所谓网管报文,就是一段范围ID的报文,Osek网络管理定义0x400-0x4FF的报文为网管报文。
ECU地址:若网管报文ID范围为0x400-0x4FF,则基地址为0x400,ECU地址为0x00-0xFF,如BMS节点的ECU地址为0x08。
刚开始接触OSEK网管的时候,各种网上学习,然后看到好多文章在讲什么令牌啊、逻辑环啊什么的,而状态机图还是不常见的那些状态机图,对于我这个小白来说实在是太难受了,这么抽象理解半天没搞懂。
以逻辑环为理解OSEK网管的切入点:
我们先来看一下各个ECU节点都处于唤醒状态并且处于稳定正常工作的情况:
所谓的OSEK NM的逻辑环,其实就是上面图中那个东西:每个ECU按照逻辑顺序依次发出网管报文,并且报文的Byte0的数据指向下个节点地址。
从上面的报文可以看到,当前网络上有6个ECU节点,节点地址分别是:0x01,0x02,0x04,0x06,0x08,0x10。并且已经建立了逻辑环,另外我们称这些报文为Ring报文。
接下来,我们从上面所示的逻辑环为学习OSEK NM的突破口,引出一系列问题,然后逐一解答,就很容易理解OSEK网管了。
1、(开始)这个逻辑环是怎么建立的?
2、(运行过程)逻辑环运行过程中,有一个新的ECU节点加入怎么处理?
3、(运行过程)逻辑环运行过程中,有一个ECU节点异常退出怎么处理?
4、(结束)如果所有ECU都不需要工作了,如何结束逻辑环进入休眠?
在我看来,OSEK网管机制无非就这4种情况,我觉得把这4个问题解答完,整个Osek直接网管就清晰明了了。
在此之前,我们先看下Osek网管报文的字节数据定义:
Osek网管报文的字节数据定义
Source ID:该报文的报文ID
Dest.ID(Byte0):目的地址,即指向的下一个ECU地址
OpCode(Byte1):
Bit0 为 Alive 报文标志位;
Bit1 为 Ring 报文标志位;
Bit2 为 LimpHome 报文标志位;
Bit3、Bit6、Bit7 预留,设置为“0”;
Bit4 代表 Sleep.Ind 即节点的睡眠指示位;
Bit5 代表 Sleep.Ack 即节点 Ring 报文的睡眠确认位;
其实这个也很好记,8个Bit,从低到高是按报文发出的时间顺序的:
列出表格如下:
DataFiled(Byte2-7):数据内容与网络管理无关,数据内容由用户定义(比如可以填唤醒原因,用于问题分析等)
另外,OSEK 网管机制中需要用到下面的时间参数需要先贴出来。大家有个印象即可,暂时不需要理解。下面讲解时用到的时候就明白了。
1、(开始)逻辑环是怎么建立的?
建立逻辑环,又涉及到整个ECU网络的同起同睡、主动唤醒和被动唤醒了,如果对这些概念不理解的朋友可以点击这里看一下(同起同睡、主动唤醒和被动唤醒)。
步骤1:主动唤醒的节点发出Alive报文
好了,现在整个CAN网络的所有ECU都处于休眠状态。假设ECU_A(节点地址为0x408)有主动工作请求并且主动唤醒了,然后ECU_A会向CAN总线发出一帧网管报文,由于此时逻辑环还未建立,因此发出的这帧网管报文我们称之为Alive报文。
如下面这张图所示
Byte1:0x01。指示该报文为Alive报文。
Byte0:0x08。由于该报文为Alive报文,因此该报文是指向自己的(0x408)。
步骤2:被动唤醒的节点发出Alive报文
当主动唤醒的ECU节点发出首帧CAN总线上的Alive网管报文后,CAN总线上其它ECU节点收到网管报文后被动唤醒,并且也发出一帧Alive报文,如下图所示
步骤3:接收到Alive报文,ECU更新逻辑环中自己的后继节点
CAN总线上的节点在发出一帧Alive报文的同时还会接收来自总线其它节点的Alive报文。并且根据接收到的网管报文的报文ID,更新自己的后继节点。具体逻辑如下图所示:
其中:
R:Receiver为接收到网管报文的ECU(可以理解为自己)
S:Source为发送网管报文的ECU(可以理解为发网管报文过来的ECU)
L:Log.successor为接收到网管报文的ECU的当前后继ECU(可以理解为当前自己的后继ECU)
更新自己后继节点的算法流程图如下:
当L = S的时候,就说明自己的后继节点(即L)需要更新为发送该网管报文的ECU节点(即S)。
用第一行举个例子:
假设,Source-ECU发出的报文ID为0x400,Log.successor-ECU地址为0x01,Receiver-ECU的地址为0x0F。
当Source-ECU没有发出网管报文的时候,Receiver-ECU为逻辑环中地址最大的ECU节点,因此它的后继节点为地址最低的节点:0x01。现在Source-ECU发出了网管报文0x400,因此Receiver-ECU的后继节点就不是0x01,而是0x00了。如下图所示:
图中其它行也是一样的理解。
好了。每个ECU节点按照这种后继节点的更新机制,当CAN总线上所有的ECU都发出一帧Alive报文后,同时每个ECU也都找到了自己的后继节点。
步骤4:ECU发处Alive报文前后的OSEK NM状态跳变情况
步骤5:CAN总线上发出第一帧Alive报文的ECU节点等待“TTyp”时间后,发出第一帧Ring报文,其它节点按照逻辑顺序发出Ring报文
我们先来看一下"TTyp"定时器。
定义:
即:两帧Ring报文的时间间隔。
再看看“Ttyp”定时器何时开启何时关闭及定时器到时动作,如下图所示:
从这个表格可以看出,TTyp定时器的使用,其实就是实现了使得各个节点按照逻辑顺序依次发出Ring报文的功能,如一开始的那张图,可以知道TTyp定时器就是100ms。
而CAN总线发出的第一帧Ring报文从何而来?
其实这就跟上述 “TTyp”定时器开启的情况①有关:每个ECU发出Alive报文后都会开启自己的TTyp定时器。
由于大家的TTyp定时器的时间都是一样的,因此当然是发出首帧Alive报文的ECU的Ttyp定时器先计时完,然后发出第一帧Ring报文。如下图所示:
Byte1:0x02,指示该报文为Ring报文。
Byte0:0x10,指示该报文指向的下个地址为0x10的ECU,如下图所示。
步骤6:逻辑环建立完成
各个ECU按照 “TTyp”定时器开启条件和关闭条件,当计时完成就发出自己的Ring报文。
至此!整个逻辑环就建完了。各个ECU按部就班发出Ring报文就好了,正如本篇文章开头的图片所示:
到这为止,大家应该对开头的这张图就有了更深的理解。
在建立逻辑环的过程中,涉及到两个重要的网管状态:NMRESET、NMNORMAL。
这两个状态实际上做了许多事情,如下图所示,大家可以仔细看看。
2、(结束)如果所有ECU都不需要工作了,如何结束逻辑环进入休眠?
再看回Osek网管报文的帧结构:
其中
Bit4,SleepInd位:即睡眠指示位,这个位的置位与其它ECU无关。当ECU自己没有主动工作请求后,在发出的网管报文中就把SleepInd置位。当ECU有主动工作请求时,在发出的网管报文中就把SleepInd置位。(睡眠指示位无论是在Alive、Ring、LimpHome报文都能置位)
Bit5,SleepAck位:即睡眠应答位,这个位的置位与其它ECU有关。逻辑环中每个ECU在发出Ring报文前,都会首先检查一遍逻辑环中其它ECU的SleepInd位是否都已置位,并且自己无主动请求,则将发出的Ring报文的SleepAck位置位,其它ECU检测到网管报文的SleepAck位置位后,则进入NMWaitBusSleep状态。(睡眠应答位只在Ring置位)
因此,当逻辑环中ECU都不需要工作后,会发出SleepInd位置位的报文,当最后一个不需要工作的ECU将SleepAck位置位后发出Ring报文,然后大家就都停放网管报文和应用报文,大家都进入NMTwbsNormal状态了。并等待TWaitBusSleep后进入NMBusSleep状态,大家都休眠了。
流程如下图所示:
另外,当处于NMTwbsNormal状态若检测到唤醒源主动唤醒或被动唤醒(被动唤醒即SleepInd不置位的网管报文),则重新进入NMReset状态,重新开始建环流程。
中间小结:
到这里为止,就是处于正常情况下(所有ECU的Rx和Tx都正常)的OSEK网管从唤醒,到建环,再到完成建环,到最后整个网络休眠的整个流程。
但是由于OSEK网管的逻辑环机制,导致当某些ECU出现异常情况的时候,出现异常的ECU和其它ECU必须有相对应的措施。
而Autosar网管则远远没这么复杂,它只需要检测总线是否有网管报文,有网管报文就保持唤醒,没网管报文则进入休眠,不需要检测网管报文的数据内容,当某个ECU出现异常的时候,其它ECU是不需要对应做任何操作的。
好了,讲完OSEK网管正常工况,下面开始讲OSEK网管异常工况。
3、(运行过程)逻辑环运行过程中,有一个新的ECU节点加入怎么处理?
当CAN总线上各个节点唤醒并且处于逻辑环正常工作的时候,在一遍逻辑环的循环中的每个ECU肯定能被指向一次。
如果这时候有个ECU打开自己的CAN通道接入CAN总线中,CAN总线肯定没有一个ECU发的网管报文是指向它的。这怎么办呢?
因此,这新加入的ECU需要具备检测自己是否被逻辑环跳过的机制,当发现自己被跳过后,需要立即发送Alive报文,以加入逻辑环中。
官方解释及检测是否被跳过的算法流程图如下图所示:
其中:
R:Receiver为接收到网管报文的ECU(可以理解为自己)
S:Source为发送网管报文的ECU(可以理解为发网管报文过来的ECU)
D:Destination为所发送的网管报文的指向地址(可以理解为发网管报文过来的ECU的网管报文的指向地址)
以第3行举例如下:
假设:Source为0x08,Destination为0x00, Receiver为0x0F。
即,Source节点发送的网管报文的指向地址为0x00,但是由于,Receiver节点的地址是0x0F,因此,Source节点应该发送网管报文的指向地址为0x0F。
可以发现,Receive节点被跳过了。
其它情况也是同样的分析方式。
4、(运行过程)逻辑环运行过程中,有一个ECU节点异常退出怎么处理?
某个ECU异常退出对于其它节点网管状态的影响:
逻辑环正常工作的时候,某个节点异常退出,对其它节点而言的现象,就是突然少了这个节点的Ring报文。
因此,我们先看下逻辑环正常工作的时候,一帧Ring报文对其它节点有什么作用。
影响①:对Ring报文指向的ECU节点的作用。
即,Ring报文指向的ECU需要开启TTyp计时器,等待计时器到时后就发出它的Ring报文。
影响②:对Ring报文不指向的ECU节点的作用。
即,当ECU接收到不指向自己的Ring报文的时候,会关闭TTyp定时器,因为Ring报文不指向它,所以下一个发Ring报文的ECU不是它,当然就不需要开启TTyp定时器了。
可见,当某个ECU突然退出逻辑环,当出现指向这个ECU的Ring报文时,其它所有ECU的TTyp定时器都会关闭,但由于最后一帧Ring报文指向的这个ECU退出了逻辑环,因此它不会再发出Ring报文了。逻辑环到它这就卡住了。
因此,若Ring报文只控制CAN总线网络上ECU节点的TTyp计时器,则还无法监测到某个ECU退出逻辑环的情况。
于是,另外一个叫做“TMax”计时器就排上用场了。
“TMax”定义如下:
即:两帧Ring报文之间最大的时间间隔。
我们再来看下“ TMax”定时器开启、关闭及计时器到时动作,如下图所示:
由上图可见,接收到不指向自己的Ring报文后会开启“TMax”定时器。并且当定时器到时后,NM状态会进入RESET状态。
因此,当某个ECU突然退出逻辑环后,其它所有ECU的TTyp定时器都会关闭,但同时会开启“TMax”定时器,当定时器时间一到,CAN总线网络上每个正常节点都进入RESET状态,重新发送Alive报文,然后重复开始建环的动作。
某个ECU异常退出对自己内部网管状态的影响:
首先要知道,正常情况下,参与CAN网络的节点是不可能无故退出网络的。某个ECU退出CAN网络只有两种情况:
①该ECU的接收出问题了,导致无法接收网管报文。
②该ECU的发送出问题了,导致无法发送网管报文。
那么,怎么样才算接收出问题,怎么样才算发送出问题呢?
于是官方定义两个参数:
这两个参数的值由车企定义。一般来说,rx_limit = 4。tx_limit = 8。
阈值rx_limit和tx_limit对应两个计数器:
当NMrxcount大于等于rx_limit或tx_limit大于等于NMtxcount,则认为ECU通信出现错误,NM状态进入NMLimpHome状态(即跛足状态)
如下图所示:
NMrxcount和NMtxcount计数器累加或清0的条件:
如下图所示:
即:
进入NMRest状态:
①NMrxcounter加1
②NMtxcounter加1
进入NMRest状态:
①成功接收网管报文时,清空NMrxcounter
②成功发送网管报文时,清空NMtxcounter
③有发送网管报文的请求时,NMtxcounter加1
好了,当有了一些LimpHome的基本概念后。我们看下当ECU的通信出错后,具体是如何进入LimpHome状态的:
1、具体如何进入LimpHome状态:
a、当有主动请求(Active)或CAN总线上存在节点SleepInd不为1时,TX失败:
情况A:当处于NMNORMAL状态出现TX失败
①当出现CAN总线上的Ring报文指向我们后,我们开启“TTyp”定时器,定时时间完成后,我们会请求发出网管报文但发送失败(NMtxcounter+1),并开启“TMax”定时器,由于我们没发出网管报文,导致其它ECU的“TMax”计时完成,我们的“TMax”计时也完成同时网管状态进入NMRESET状态。
②我们进入REST状态后请求发出Alive报文但发送不成功(NMtxcounter+1),并再次进入NMNORMAL状态。
③由于我们Alive报文发送不成功,CAN总线的逻辑环不会包含我们节点,因此,逻辑环会跳过我们,我们由于检测到被跳过,因此会请求发送Alive报文,但仍然发送失败(NMtxcounter+1)。
④不断循环步骤3,直到NMtxcounter等于txlimit。我们的NM状态进入LimpHome状态
情况B:当处于NMRESET状态出现TX失败
情况A中的除去①,剩下的②③④即是处于NMRESET状态出现TX失败的流程。
b、当有主动请求(Active)时,RX失败:
由于我们有主动请求,因此不会进入休眠。
又由于无法接收报文,我们无法收到指向我们的Ring报文,“TMax”计时完成后,我们会进入RESET状态(NMrxcount+1),并发送Alive报文,然后进入NMNORMAL。
不断循环上述情况,直到NMrxcount等于rxlimit。我们的NM状态进入LimpHome状态
c、当无主动请求(Passive)且CAN总线上所有节点SleepInd为1,TX失败:
当我们无主动请求,且所有节点SleepInd为1时,逻辑环一定会出现某个节点SleepAck为1。由于txlimit为8,理论上来说,当这个NMtxcounter计数器还没到txlimit,我们节点就能接收到SleepAck为1的报文,则直接进入WaitBusSleep模式了。
d、当无主动请求(Passive)时,RX失败:
①由于无法接收到Ring报文,“TMax”计时完成后,我们会进入RESET状态(NMrxcount+1)
②在RESET状态发送Alive报文后,开启“TTyp”定时器,并进入NMNORMAL状态,“TTyp”定时器完成后,由于未收到其它节点的报文,因此我们认为总线上所有节点的SleepInd已置位,然后我们发送SleepAck报文,并进入WaitBusSleep模式。
2、进入LimpHome状态后的动作:
当ECU处于LimpHome状态,ECU将不再申请加入逻辑环,即不再发送Alive报文和Ring报文。而是发送LimpHome报文。
LimpHome状态如下图:
LimpHome报文的发送情况:
情况1、当有主动请求(Active)或接收到CAN总线上存在节点SleepInd不为1时:
LimpHome状态处于“NMLimpHome Active”子状态,并按照TError周期发送LimpHome报文
情况2、当无主动请求且接收到CAN总线上所有节点SleepInd都为1时:
发送SleepInd置1的LimpHome报文,LimpHome状态从“NMLimpHomeActive”子状态跳至““NMLimpHomeActivePreSleep”子状态。发送完该报文同时开启“TMax”计时器,等待计时结束后网管状态进入NMTwbsLimpHome,等待TwaitBusSlee时间后进入BusSleep状态
情况3、当接收到SleepAck置1的网管报文
则直接进入NMTwbsLimpHome状态,等待TwaitBusSlee时间后进入BusSleep状态。
另外,当在NMTwbsLimpHome状态再次有主动请求或接收到CAN总线上存在节点SleepInd不为1时,则根据上述的情况1、2、3执行对应操作。
3、如何从LimpHome状态恢复
简单来说,就是在LimpHome状态时,如果成功发送LimpHome报文且成功接收到网管报文后,网管状态则跳转至Reset状态。
但是你看上面的LimpHome状态图,可以看到其实状态图里面描述的是很复杂的。但是它只不过是详细拆开了各种情况去讲解,大家结合上面的内容,理解一下就可以了。
另外,下面再贴上一些Osek网管的状态图:
①:Osek网管的完整简化状态图
② 从唤醒状态,到休眠状态,再到唤醒状态的过程状态图
OsekNm与Autosar网管的区别:
首先:Autosar网管不需要检测网管报文的数据内容。
网络休眠->网络唤醒:
Osek网管:主动唤醒的节点先发出一帧Alive报文,其它各个节点接收到网管报文后被动唤醒,发出一帧Alive网管报文
Autosar网管:主动唤醒的节点先发出网管报文(持续发出网管报文),其它节点接收到网管报文后被动唤醒,同时也发出网管报文(只发出几帧网管报文)。
网管唤醒后正常工作:
Osek网管:无论是主动唤醒节点还是被动唤醒节点,都要按照逻辑环机制发出Ring报文。
Autosar网管:主动唤醒的节点持续按照周期发送网管报文,被动唤醒的节点不发送网管报文。
网络唤醒->网络休眠:
Osek网管:接收到Ring报文的SleepAck后所有节点马上进入预休眠状态,等待TwaitBusSleep时间后进入BusSleep状态。
Autosar网管:总线不再出现网管报文后所有节点等待一段时间后进入预休眠状态,等待TwaitBusSleep时间后进入BusSleep状态。
异常情况:
Osek网管:ECU有对应的LimpHome状态,及该状态下对应的动作。
Autosar网管:由于ECU的休眠唤醒只于总线上是否有网管报文有关,因此某个ECU出现异常时,其它ECU不会有对应的处理机制,异常ECU本身也没有对应的网管机制
好了,Osek网管主要的内容大致就是这些了,这文章是我写的最久的一篇,但是质量可能不太好,后面我再学习过程中发现写的不好的地方会再回来改改的。主要先记录下来,不然久了就忘记了。
相对于Autosar网管,Osek网管真的复杂很多。
返回目录:
Autosar BSW 开发笔记(目录)-CSDN博客