一、BusOff 的产生
BusOff,即总线掉线;
当前节点Can线短路(物理短接)或发向总线的报文被干扰出错(NO ACK错误也会导致TEC++),总的来说就是当前节点向总线发送错误帧,发送错误计数器(TEC)开始计数(发一帧错误帧TEC+8,成功发送一帧正常帧TEC - 1),当TEC > 255,当前节点进入BusOff,关闭Controller,期间不再接收/发送报文。
TEC(发送错误计数器)/REC(接收错误计数器) 是硬件计数器
当TEC > 255,Protocol Status Register BO会置1,代表此节点状态已进BusOff状态
二、BusOff 的恢复
1、上报流程
前面可知,传输错误计数器是由硬件寄存器TEC完成的,在autosar分层架构中,需要层层上报,不可逾越;
step1. 由Can底层驱动up CanIf(BusOff处理模式配置为中断处理)
在CanDriver中,产生中断,调用BusOff中断处理函数(Can_17_McmCan_IsrBusOffHandler),
判断BO是否置1;
若为1,继续调用Can_17_McmCan_lBusOffHandler,判断进行busoff处理的前提条件:
(1)BO位 == 1
(2)INIT位 == 1
(3)本路CAN Controller运行在CANIF_CS_STARTED状态
If 条件满足,则:
(1)调用函数取消所有pending Tx请求
(2)将本路CAN Controller工作模式设置为CAN_17_MCMCAN_STOPPED(CANIF_CS_STOPPED)(此时本节点不可收发报文)
(3)调用CanIf_ControllerBusOff向上通知CanIf
step 2. 由CanIf处理后up CanSM
在CanIf中的处理主要是在CanIf_ControllerBusOff,操作如下:
(1)设置发送通知状态为 CANIF_NO_NOTIFICATION
(2)将CAN Controller状态设置为 CANIF_CS_STOPPED
(3)设置对应通道的PDU通道模式为CANIF_TX_OFFLINE
(4)IF 配置的busoff事件通知的上层模块为CanSM(配置工程里提供了CanSM和CDD,配置容器在CanIf的CanIfDispatchCfg中),则调用CanSM_ControllerBusOff,通知给CanSM
2、CanSM对BusOff的恢复处理
step 3. 由CanSM处理(BusOff的恢复处理是CanSM的主要功能之一)
(1)CanSM_ControllerBusOff中判断条件
if ((CANSM_BSM_S_FULLCOM == networkPtr->curBsmState)
&& ((FULLCOM_S_BUS_OFF_CHECK == networkPtr->fullComState)
|| (FULLCOM_S_NO_BUS_OFF == networkPtr->fullComState)))
条件满足则:
(2)(void)BswM_CanSM_CurrentState(netID, CANSM_BSWM_BUS_OFF)设置BswM状态BusOff
ComM_BusSM_ModeIndication(netID, ComMode);设置ComM模式COMM_SILENT_COMMUNICATION
(3)如果设置了BusOff故障,则在此调用Dem_ReportErrorStatus报告BusOff故障事件(PREFAILED,要过滤波)
(4)networkPtr->fullComState = FULLCOM_S_RESTART_CC; sub bsm state (通过设置此状态供CanSM_BsmSFullCom函数使用;)此时BSM状态为CANSM_BSM_S_FULLCOM,子状态为FULLCOM_S_RESTART_CC,进入case:调用CanSM_FullCom_S_Restart_CC,在此函数中调用CanSM_SetControllerModeRepeat将所有cancontroller模式设置为CANIF_CS_STARTED,以便于后续尝试恢复通信,同时关闭TX(设置网络子状态为FULLCOM_S_TX_OFF),
(5)networkPtr->repeatCounter = 0u;
(6)CanSM_ControllerMode[ControllerId] = CANIF_CS_STOPPED;
(7)networkPtr->busOffEventStartTime = 0u; (BusOff事件发生时间计时,由busoff发生后从0开始,在1ms函数CanSM_FullCom_S_Tx_Off中周期++,只有在BusOff事件刚发生或者cansm初始化时清0)
在(4)中 “同时关闭TX(设置网络子状态为FULLCOM_S_TX_OFF)”,之后由1ms周期的cansm_mainfunction调用的CanSM_BsmSFullCom中进入case FULLCOM_S_TX_OFF :CanSM_FullCom_S_Tx_Off进行第(7)的快慢恢复计时操作;
CanSMBorTimeL1或者CanSMBorTimeL2耗尽,重新发送Tx PDU,让故障节点再次尝试向Can总线发送报文,既然要向总线上发报文了,就要置一些通信相关模块的工作模式,
- CanIf:CANIF_ONLINE 、
- BswM:CANSM_BSWM_FULL_COMMUNICATION 、
- ComM:COMM_FULL_COMMUNICATION 、
- networkPtr->fullComState = FULLCOM_S_BUS_OFF_CHECK; (bsm的子状态),(busoff check状态,在此状态中检查borTimeTxEnsuredTime是否耗尽,若耗尽,则gBusOffPassive = TRUE;证明busoff已恢复,然后子状态为FULLCOM_S_NO_BUS_OFF,busOffCounter清0);
(可以)启动CanSMBorTimeTxEnsured,确认Busoff是否恢复。(也可以使用Confirm方式确认Busoff恢复)
3、CanSMBorTimeTxEnsured和CanSMBorTxConfirmationPolling启用策略
在CanSMBorTimeTxEnsured时间内,Busoff再次发生,则进行下一次的Busoff恢复机制,如果CanSMBorTimeTxEnsured耗尽,则说明成功从Busoff状态恢复。如果在CanSMBorTimeTxEnsured时间内,再次发生Busoff,则Busoff次数累加。
若 CanSMBorTxConfirmationPolling 为 false,停留在BUS_OFF_CHECK状态没有超过时间参数CanSMBorTimeTxEnsured,在此时间段内,没有新的 Busoff 事件产生,则认为 Busoff恢复成功。
若 CanSMBorTxConfirmationPolling 为 true,停留在 BUS_OFF_CHECK状态,直到检测到确实有一帧 Can 报文发送成功并给出了发送确认则认为 Busoff 恢复成功。这种情况下,需要调用 CanIf 的CanIf_GetTxConfirmationState 接口。
如果Busoff 恢复不成功,节点一直在慢恢复期,意味着该节点不会外报文(应用报文和网络管理报文均不会外发),其他节点会上报对应的节点丢失故障。