文章包含了AUTOSAR基础软件(BSW)中CanSM模块相关的内容详解。本文从AUTOSAR规范解析,ISOLAR-AB配置以及模块相关代码分析三个维度来帮读者清晰的认识和了解CanSM这一基础软件模块。文中涉及的ISOLAR-AB配置以及模块相关代码都是依托于ETAS提供的工具链来配置与生成的,与AUTOSAR规范之间可能会有些许的出入,但总体的功能要点与处理流程都应该是一致的。
CanSM模块作为CAN栈中的模式管理模块,主要实现了对CAN控制器以及收发器的状态管理,它向上主要对ComM负责,提供CAN网络状态的控制,向下则主要使用CanIf模块提供的统一接口来完成对CAN控制器以及收发器的配置。CanSM模块在项目中常常需要关注的是它对CAN控制器BusOff的恢复机制,所以我在文章的最后专门针对CanSM的BusOff恢复机制进行了详尽的介绍,帮助读者更好的根据自己的项目需要完成对应的配置。
目录
Diagnostic Event Manager (DEM)
Basic Software Mode Manager (BswM)
CAN Network Management (CanNm)
AUTOSAR规范解析
AUTOSAR基础软件为每个通信总线指定一个特定的总线状态管理器。该模块应实现相应总线的控制流。如下图所示,CAN状态管理器(CanSM)是通信服务层的成员,它与通信硬件抽象层和系统服务层交互。
CanSM(Controller Area Network State Manager)是AUTOSAR基础软件中的一个模块,用于管理车辆控制系统中的CAN总线通信。它提供了一种统一的方式来操作和管理CAN控制器与收发器状态,向ComM模块提供了包括:COMM_NO_COMMUNICATION、COMM_SILENT_COMMUNICATION以及COMM_FULL_COMMUNICATION三种不同Can通信网络模式的实现。与此同时,CanSM还提供CAN BusOff故障的快/慢恢复机制,以确保CAN总线通信的可靠性和稳定性。 CanSM模块只能用于管理Can网络,就比如针对Lin总线有独立的LinSM。
CanSM的静态代码主要实现了一个名为CanSM_BSM的状态机来管理CAN网络,它会根据不同的前置条件以及触发来转换到不同的子状态机中,实现不同的控制效果。
下图展示了CAN网络通信中各个模块的主要作用,可以看到CanSM主要处理来自ComM的通信模式请求管理。
最后,我们总结一下CanSm主要涉及的功能包括:
- CAN控制器状态管理:当CanSM接收到ComM的Can状态切换请求或者检测到总线BusOff后,需要切换CAN控制器的状态,调用CanIf的CanIf_SetControllerMode()请求CAN控制器在CANIF_CS_STOPPED,CANIF_CS_STARTED,CANIF_CS_SLEEP之间切换,CanIf模块再调用Can驱动接口Can_SetControllerMode()执行具体CAN控制器的状态切换(CAN_T_START, CAN_T_STOP, CAN_T_SLEEP, CAN_T_WAKEUP)。由于CAN控制器操作延时等原因,网络的通信模式可能会和ComM请求的不一致,这就需要CanSM通过以下方式来提供接口向ComM等模块反馈当前的通信模式:
- CanSM提供CanSM_GetCurrentComMode()。ComM等模块可以通过这个API,主动得到CAN网络当前的通信模式。
- CanSM使用ComM提供的回调函数ComM_BusSM_ModeIndication(),来通知通信模式的改变。
- CAN收发器状态管理:当CanSM接收到ComM的CAN状态切换请求,如果对应的CAN通道包含收发器,CanSM需要切换对应CAN收发器的状态,调用CanIf的CanIf_SetTrcvMode()请求CAN收发器在CANTRCV_TRCVMODE_NORMAL、CANTRCV_TRCVMODE_SLEEP、 CANTRCV_TRCVMODE_STANDBY之间切换,CanIf模块再调用Can收发器驱动接口CanTrcv_SetOpMode()执行具体CAN收发器的状态切换。
- CAN总线BusOff故障处理:当CAN控制器检测到BusOff(通过Busoff中断或者周期调用Can_MainFunction_BusOff()进行Polling获取到总线进入BusOff),CAN驱动将调用CanIf_ControllerBusOff()通知BusOff事件到CanIf,CanIf再调用CanSM_ControllerBusOff()通知busoff事件到CanSM。CanSM在检测到对应Can通道BusOff事件发生后,将尝试进行BusOff恢复。
缩略语
- API:Application Program Interface,函数。
- BSW:Basic Software,基础软件。
- CAN:Controller Area Network。
- CanIf:CAN Interface,Can接口模块。
- CanSM:CAN State Manager,Can状态管理模块。
- ComM:Communication Manager,通信管理模块。
- DEM:Diagnostic Event Manager,诊断事件管理模块。
- DET:Default Error Tracer,错误跟踪记录模块。
- EcuM:ECU状态管理。
- PDU:Protocol Data Unit,协议数据单元。
- RX:Receive,接收。
- TX:Transmit,发送。
- SchM:BSW Scheduler,基础软件调度。
- SWC:Software Component,软件组件。
- BswM:Basic Software Mode Manager,基础软件模式管理。
- Indication:底层向上层的通知。
- WUVALIDATION:唤醒验证。
- BOR:BusOff Recovery,BusOff恢复。
- CC:CAN Controller。
模块依赖
接下来的部分简要说明CanSM模块需要从其他模块获得的配置信息和服务。下图展示了CanSM依赖其他模块必须/可选的实现,以及其他模块对CanSM的依赖。
ECU State Manager (EcuM)
EcuM模块初始化CanSM模块,并与CanSM模块交互进行CAN唤醒验证。
BSW Scheduler (SchM)
BSW调度器模块调用CanSM模块的循环MainFunction,这对于CanSM模块的状态机运转是必要的。
Communication Manager (ComM)
ComM模块使用CanSM模块的API来请求CAN网络的通信模式,这些通信模式具有唯一的网络手柄标识,CanSM模块还会将其CAN网络的当前通信模式通知给ComM模块。下图包含了CanSM提供给ComM的控制API。
一个ECU可以有不同的通信网络。每个网络都必须用唯一的网络句柄来标识。当ComM模块需要向网络请求通信模式,通过相关配置,ComM知道哪个句柄被分配给什么样的网络。对于CAN,ComM使用CanSM模块完成请求通信模式。
CAN Interface (CanIf)
CanSM模块使用Canlf模块的API来控制分配给CAN网络的CAN控制器和CAN收发器的操作模式,Canlf模块会向CanSM模块通知控制器事件。下图是CanIf动态配置代码中包含的CanSM相关事件发生时的回调函数。
Diagnostic Event Manager (DEM)
CanSM模块向DEM模块报告总线特定的生产错误,例如BusOff故障。
Basic Software Mode Manager (BswM)
CanSM需要向BswM模块通知总线特定模式的更改。CanSM通过BswM_CanSM_CurrentState()上报模式改变,状态包括:
CAN Network Management (CanNm)
CanSM模块需要向CanNm模块通知部分网络可用性,并在部分联网的情况下处理已通知的CanNm超时异常。
Default Error Tracer (DET)
CanSM模块向DET模块报告开发和运行时错误。
CanSM模块顶层状态机
下图为CanSM模块最顶层的状态机CANSM_BSM,它包含了各个子状态机的转换触发(Trigger)以及检测条件(Guarding condition)与状态转换效果(Effect)。
状态转化说明
下面介绍一下CANSM_BSM涉及的转化触发条件。
- Trigger-PowerOn:刚上电的时候,状态机处于CANSM_BSM_NOT_INITIALIZED。
- Trigger -CanSM_Init:通过CanSM_Init()函数调用,,将触发所有配置的CanSM状态机进入CANSM_BSM_S_PRE_NOCOM。
- Trigger-CanSM_DeInit:如果请求使用CanSM模块的CanSM_Delnit()函数,这将触发所有CAN网络的CanSM状态机进入CANSM_BSM_NOT_INITIALIZED。
- Trigger-T_START_WAKEUP_SOURCE:假设存在唤醒事件,CanSM_StartWakeUpSource()应该被EcuM调用,返回E_OK之后,CanSM的状态机应该进入CANSM_BSM_WUVALIDATION。
- Trigger-T_STOP_WAKEUP_SOURCE:如果请求CanSM_StopWakeUpSource()返回E_OK,CanSM的状态机应该回到CANSM_BSM_S_PRE_NOCOM。
- Trigger-T_FULL_COM_MODE_REQUEST:ComM调用接口CanSM_RequestComMode(),假当ComM_Mode等于COMM_FULL_COMMUNICATION,引起T_FULL_COM_MODE_REQUEST触发,如果当前状态为CANSM_BSM_WUVALIDATION,状态机进入CANSM_BSM_S_PRE_FULLCOM状态,如果当前状态为CANSM_BSM_S_SILENTCOM,则状态机直接进入CANSM_BSM_S_FULLCOM。
- Trigger-T_SILENT_COM_MODE_REQUEST:API请求CanSM_RequestComMode(),参数ComM_Mode等于COMM_SILENT_COMMUNICATION应触发转换到CANSM_BSM_S_SILENTCOM。
- Trigger-T_NO_COM_MODE_REQUEST:通过ComM调用接CanSM_RequestComMode(),假设ComM_Mode等于COMM_NO_COMMUNICATION,应该触发状态机到CANSM_BSM_S_PRE_NOCOM子状态机。
- Trigger-T_BUS_OFF:回调函数CanSM_ControllerBusOff()供CanIf当发生BusOff时使用,如果当前状态为CANSM_BSM_S_SILENTCOM,则会进入CANSM_BSM_S_SILENTCOM_BOR状态,若当前状态为CANSM_BSM_S_FULLCOM,则会再子状态机中尝试恢复。
- Trigger-T_REPEAT_MAX:如果状态机CANSM_BSM在它的一个子状态机中重复了调用CanIf模块提供的API,但没有得到返回值E_OK,则触发T_REPEAT_MAX这个事件,如果当前的状态为CANSM_BSM_S_FULLCOM,则会进入CANSM_BSM_S_PRE_NOCOM状态。
下面介绍一下CANSM_BSM涉及的转化前置条件。
- Guarding condition-G_FULL_COM_MODE_REQUESTED:判断最新接受的通信模式请求是CanSM_RequestComMode()是否为COMM_FULL_COMMUNICATION。
- Guarding condition-G_SILENT_COM_MODE_REQUESTED:判断最新接受的通信模式请求是CanSM_RequestComMode()是否为COMM_SILENT_COMMUNICATION。
下面介绍一下CANSM_BSM涉及的转化效果。
- Effect-E_PRE_NOCOM:CanSM_BSM状态机的E_PRE_NOCOM效果通过调用相应的CAN网络API实现。调用BswM_CanSM_CurrentState(),Network参数为对应网络的引用句柄,CurrentState为CANSM_BSWM_NO_COMMUNICATION。
- Effect-E_NOCOM:CanSM_BSM状态机的效果E_NOCOM应改变内部存储的网络模式,当前CAN网络是COMM_NO_COMMUNICATION。
- Effect-E_FULL_COM:这个转化效果取决于EcuPassive配置,当EcuPassive为假时,CanSM调用CanIf_SetPduMode(),PduModeRequest参数为CANIF_ONLINE。当EcuPassive为真时,CanSM调用CanIf_SetPduMode(),PduModeRequest参数为CANIF_TX_OFFLINE_ACTIVE。同时,CanSM需要调用ComM_BusSM_ModeIndication()将COMM_FULL_COMMUNICATION汇报给ComM,并使用BswM_CanSM_CurrentState()将COMM_FULL_COMMUNICATION汇报给BswM。
- Effect-E_FULL_TO_SILENT_COM:这个转换效果首先需要调用BswM_CanSM_CurrentState()与ComM_BusSM_ModeIndication()将状态COMM_SILENT_COMMUNICATION汇报给BswM与ComM模块,并使用CanIf_SetPduMode将ControllerId对应的CAN网络配置为CANIF_TX_OFFLIN。
- Effect-E_BR_END_FULL_COM:它与E_FULL_COM一致。
- Effect-E_BR_END_SILENT_COM:它与E_FULL_TO_SILENT_COM一致。
- Effect-E_SILENT_TO_FULL_COM:它与E_FULL_COM一致。
CanSM子状态机说明
CANSM_BSM_WUVALIDATION
子状态中,WU代表Wake-Up,VALIDATION代表验证,子状态机负责验证CAN总线是否处于活动状态,与EcuM配合完成唤醒源的验证,并根据需要完成对CANSM_BSM_S_PRE_FULLCOM状态的转换,主要是针对有Can收发器携带休眠唤醒功能的时候,此时此时需要借助外设CAN收发器驱动。此时调用的接口均为CDD内部接口,例如CanIf_SetTrcvMode接口到CANTRCV_TRCVMODE_NORMAL切换,需要调用CDD提供的接口。
CANSM_BSM_S_PRE_NOCOM
这个子状态机是在进入“无通信”状态之前的预备状态。在该状态下,CanSM会等待一段时间来确认是否存在通信问题,如果问题得不到解决,CanSM将转移到“无通信”状态。下图为子状态机的内部状态转换。
CANSM_BSM_S_SILENTCOM_BOR
子状态表示CAN总线网络在当前处于SILENT时,发生了BusOff错误,从而进入到这个子状态,这个子状态会尝试恢复BusOff错误,并重新回到CANSM_BSM_S_SILENTCOM子状态。
CANSM_BSM_S_PRE_FULLCOM
这个子状态是在进入FULLCOM之前的准备子状态,CanSM会执行必要的检查和准备工作,主要是将控制器状态成功设置为START状态。
CANSM_BSM_S_FULLCOM
该子状态尝试维持通信FULLCOM状态,完成控制器BusOff或者Reset的处理。
CANSM_BSM_S_CHANGE_BAUDRATE
该子状态机如名称所示,主要负责实现在运行过程中实现更改波特率的功能。
时序图
CanSm_StartCanController
下图展示了同步和异步两种启动Can控制器的时序图,同步会等待CanIf接口返回E_OK,表示已经启动完成,而异步则会直接返回E_OK,CanSM通过CanSM_ControllerModeIndication()回调函数来确认启动完成。
CanSm_StopCanController
该时序图与启动时序类似,只是将设置模式变为了CAN_CS_STOPPED。
ISOLAR-AB配置
CanSM
CanSMGeneral
下图CanSM模块通用配置截图。
下面我们介绍一些配置项:
- CanSMDevErrorDetect:切换错误跟踪器(Det)检测和通知的开启或关闭。
- CanSMMainFunctionTimePeriod:此参数定义函数CanSM_MainFunction的周期时间(秒)。
- CanSMchangeBaudrateApi:CANSM_ChangeBaudrate()函数是否支持。
- CanSMVersionlnfoApi:激活/停用版本信息API(CanSM_GetVersionlnfo)。
CanSMConfiguration
这个容器包含CanSM的配置信息。
我们介绍其中的一些参数:
- CanSMManagerNetwork:针对每个网络的配置子容器。
- CanSMModeRequestRepetitionMax:这个参数很重要,它指定CanSM模块发出的模式请求失败重复的最大数量,超过之后CanSM模块向Det报告默认错误并尝试返回无通信状态。
- CanSMModeRequestRepetitionTime:指定CanSM模块应在多长时间内使用Canlf模块的API重复模式更改请求。
CanSMManagerNetwork
具体CAN网络通道的设置,我们的工程只包含一路CAN通道,起名为了ECAN。
下面是一些它的参数:
- CanSMcontrollerld:它引用了在CanIf模块定义的CanlfCtrlcfg。
- CanSMDemEventParameterRefs:它包含CanSM模块使用的Dem事件,CanSMRbDynCreate_CANSM_E_BUS_OFF这个一般选用Disabled,并将CANSM_E_BUS_OFF引用到在Dem模块创建的DemEventParameter,用于上报BusOff故障。
- CanSMBorCounterL1ToL2:这个阈值定义了BusOff故障快恢复的次数,假设此处配置为5,那么就对应5次快恢复进入慢恢复。
- CanSMBorTimeL1:快恢复时间,以秒为单位。
- CanSMBorTimeL2:慢恢复时间,以秒为单位。
- CanSMBorTimeTxEnsured:此参数以秒为单位定义BusOff事件检查的持续时间。在该段事件检查评估在恢复重新启用传输路径后,恢复是否已经成功。如果在此期间发生了新的BusOff,则CanSM将再次进行BusOff恢复过程,判决此次没有成功恢复。
- CanSMBorTxConfirmationPolling:若设置为真,则使用CanSMBorTxConfirmationPolling来判决是否恢复已经成功,而不使用CanSMBorTimeTxEnsured。
- CanSMComMNetworkHandleRef:ComM中网络对应ComMchannel的引用。
代码解析
动态配置代码
下图为CanSM模块配置生成的动态代码。
我们针对一些常用的文件内容说明:
- CanSM_Cfg.h:包含了CanSM的一些通用配置生成的宏定义。
/* *********************************************************************************************************************** * * Product Info * Isolar version: ISOLAR-AB 4.0.2 * Product release version: RTA-BSW 3.1.0 * *********************************************************************************************************************** */ /*<VersionHead> * This Configuration File is generated using versions (automatically filled in) as listed below. * * $Generator__: CanSM / AR42.4.0.1 Module Package Version * $Editor_____: 9.0 Tool Version * $Model______: 2.3.0.4 ECU Parameter Definition Version * </VersionHead>*/ #ifndef CANSM_CFG_H #define CANSM_CFG_H /* *************************************************************************************************** * Version Information Defines *************************************************************************************************** */ /* * Vendor Id refers to a unique ID assigned by Autosar to every Member of Autosar Consortium, used during the call of CanSM_GetVersionInfo() \n */ #define CANSM_VENDOR_ID 6u /* * Module Id refers to a unique ID assigned by Autosar to every Module/Component within the Autosar, used during the call of CanSM_GetVersionInfo() BSW\n */ #define CANSM_MODULE_ID 140u /* AUTOSAR specification version */ /* * Used to declare the Major Release Number of Autosar Main Baseline under which this Component CanSM is delivered */ #define CANSM_AR_RELEASE_MAJOR_VERSION 4u /* * Used to declare the Minor Release Number of Autosar Main Baseline under which this Component CanSM is delivered */ #define CANSM_AR_RELEASE_MINOR_VERSION 2u /* * Used to declare the Revision Release Number of Autosar Main Baseline under which this Component CanSM is delivered */ #define CANSM_AR_RELEASE_REVISION_VERSION 2u /* Software version information */ /* * Used to declare Software Major Version number of Component CanSM, used during the call of CanSM_GetVersionInfo() */ #define CANSM_SW_MAJOR_VERSION 4u /* * Used to declare Software Minor Version number of Component CanSM, used during the call of CanSM_GetVersionInfo() */ #define CANSM_SW_MINOR_VERSION 0u /* * Used to declare Software Patch Version number of Component CanSM, used during the call of CanSM_GetVersionInfo() */ #define CANSM_SW_PATCH_VERSION 1u /* *************************************************************************************************** * Protected Includes *************************************************************************************************** */ /** *************************************************************************************************** * \moduledescription * CanSM Dem Auto generated configuration header file Generated only when CanSMDemBusOffReport is True and Dem module is present * * \scope CONF *************************************************************************************************** */ /* Import all the ErrorIds from dem_interrid.h and Production errors will be reported to Diagnostic Event manager */ #include "Dem.h" #if (!defined(DEM_AR_RELEASE_MAJOR_VERSION) || (DEM_AR_RELEASE_MAJOR_VERSION != CANSM_AR_RELEASE_MAJOR_VERSION)) #error "AUTOSAR major version undefined or mismatched" #endif #if (!defined(DEM_AR_RELEASE_MINOR_VERSION) || (DEM_AR_RELEASE_MINOR_VERSION != CANSM_AR_RELEASE_MINOR_VERSION)) #error "AUTOSAR minor version undefined or mismatched" #endif #include "SchM_CanSM.h" /* *************************************************************************************************** * Defines *************************************************************************************************** */ /* Start :All the Defines extracted from the Configuration Files comes here */ /************* START : GLOBAL CANSM CONFIGURATION ********************/ /*Development Error ON or OFF*/ #define CANSM_DEV_ERROR_DETECT (STD_OFF) /*Version Info API enabled or not*/ #define CANSM_VERSION_INFO_API (STD_OFF) /* Main Function Cycle time in seconds */ #define CANSM_MAINFUNCTION_CYCLE_TIME 0.01 /*Enable/Disable CanSM_ChangeBaudrate API*/ #define CANSM_CHANGE_BAUDRATE_API STD_OFF /*Enable/Disable CanSM_SetBaudrate API*/ #define CANSM_SET_BAUDRATE_API STD_OFF /*CanSMBorTxConfirmation enabled or not */ #define CANSM_BOR_TX_CONFIRMATION_POLLING STD_OFF #define CANSM_VARIANT_PRE_COMPILE 1 #define CANSM_VARIANT_POSTBUILD_SELECTABLE 2 /*CanSM variant info*/ #define CANSM_VARIANT_INFO CANSM_VARIANT_PRE_COMPILE /*Enable/Disable CanSM Calibration*/ #define CANSM_CALIBRATION STD_OFF /*RTE Enabled or Disabled*/ #define CANSM_ECUC_RB_RTE_IN_USE STD_ON /*Enable/Disable ECU passive feature*/ #define CANSM_TX_OFFLINE_ACTIVE_SUPPORT STD_OFF /************* END : GLOBAL CANSM CONFIGURATION ************************/ /* FC_VariationPoint_START */ /* Switch to enable/Disable Dem reporting to DSM after Re-Initialization. */ #define CANSM_DSM_REINIT_ENABLED STD_OFF /* FC_VariationPoint_END */ /************* START : CanSM CLUSTER CONFIGURATION **********************/ /*Number of CANSM Networks configured*/ #define CANSM_NUM_CAN_NETWORKS 1u /*Number of CAN Controllers configured*/ #define CANSM_NUM_CAN_CONTROLLERS 1u /* PN support */ #define CANSM_PN_SUPPORT_CONFIGD STD_OFF #define CANSM_START_SEC_CONST_8 #include "CanSM_MemMap.h" /*LUT for network index*/ extern CONST(uint8, CANSM_CONST) CanSM_NetworkId_LUT[1][CANSM_NUM_CAN_NETWORKS]; #define CANSM_STOP_SEC_CONST_8 #include "CanSM_MemMap.h" /************* END: CanSM CLUSTER CONFIGURATION ***********************/ #define CanSM_Config CanSM_ConfigSet[0] /* End : All the Defines extracted from the Configuration Files comes here */ /* CANSM_CFG_H*/ #endif
- CanSM_PBcfg.c:CanSM网络节点配置生成的结构体常量。
/* *********************************************************************************************************************** * * Product Info * Isolar version: ISOLAR-AB 4.0.2 * Product release version: RTA-BSW 3.1.0 * *********************************************************************************************************************** */ /*<VersionHead> * This Configuration File is generated using versions (automatically filled in) as listed below. * * $Generator__: CanSM / AR42.4.0.1 Module Package Version * $Editor_____: 9.0 Tool Version * $Model______: 2.3.0.4 ECU Parameter Definition Version * </VersionHead>*/ /********************************************************************************************************************* * Includes ********************************************************************************************************************** */ #include "CanSM_PBcfg.h" #define CANSM_START_SEC_CONST_8 #include "CanSM_MemMap.h" /*LUT for network index*/ CONST(uint8, CANSM_CONST) CanSM_NetworkId_LUT[1][CANSM_NUM_CAN_NETWORKS]= { {0} }; #define CANSM_STOP_SEC_CONST_8 #include "CanSM_MemMap.h" /* PRECOMPILE defines for placing the PB variables to the default data section*/ #define CANSM_START_SEC_CONST_8 #include "CanSM_MemMap.h" /* CanSM Network Index for corresponding CAN Controller ID */ CONST(uint8, CANSM_CONST) CanSM_NetworktoCtrl_Config_acu8[] = { 0 }; /* PRECOMPILE defines for placing the PB variables to the default data section*/ #define CANSM_STOP_SEC_CONST_8 #include "CanSM_MemMap.h" /* PRECOMPILE defines for placing the PB variables to the default data section*/ #define CANSM_START_SEC_CONST_8 #include "CanSM_MemMap.h" /* CAN Contollerid for each network */ static CONST(uint8, CANSM_VAR) CanSM_Ctrl_CanSMManagerNetwork_Can_Network_ECAN_Config_au8[] = { 0 }; /* PRECOMPILE defines for placing the PB variables to the default data section*/ #define CANSM_STOP_SEC_CONST_8 #include "CanSM_MemMap.h" /* PRECOMPILE defines for placing the PB variables to the default data section*/ #define CANSM_START_SEC_CONST_UNSPECIFIED #include "CanSM_MemMap.h" CONST(CanSM_NetworkConf_tst, CANSM_CONST) CanSM_Network_Config_acst[] = { /* ControllerStartIndx BusOffErrID BorTimeL1 BorTimeL2 BorTimeTxEnsured Trcv_Handle SizeOfController BorCounter_L1_L2 ComMChannelId canSMEnableBusOffDelay PN enabled/disabled for Transceiver*/ { CanSM_Ctrl_CanSMManagerNetwork_Can_Network_ECAN_Config_au8, DemConf_DemEventParameter_DemEventParameter_P12D2,4u, 10u, 2u,255, 1, 0, 0, FALSE, FALSE } }; /* CanSM Configuration */ CONST(CanSM_ConfigType, CANSM_CONST) CanSM_ConfigSet[] = { { CanSM_Network_Config_acst, CanSM_NetworktoCtrl_Config_acu8, 5, /*CanSMModeRequestRepetitionMax*/ 7, /*CanSMModeRequestRepetitionTime*/ CANSM_NUM_CAN_NETWORKS, /*Number of CANSM Networks configured*/ 0 /*Active configSet index*/ } }; /* PRECOMPILE defines for placing the PB variables to the default data section*/ #define CANSM_STOP_SEC_CONST_UNSPECIFIED #include "CanSM_MemMap.h"
集成代码
下图为CanSM模块包含的集成代码,其中SchM、MemMap文件这里就不赘述了。
api文件夹下有几个文件,我们介绍一下。
- CanSM.h:它包含了ComM.h头文件,并在文件中定义了其他模块可能用到得宏定义,结构体以及函数声明。
#ifndef CANSM_H #define CANSM_H /* *************************************************************************************************** * Includes *************************************************************************************************** */ #include "CanSM_Cfg.h" #include "ComM.h" /* *************************************************************************************************** * Defines *************************************************************************************************** */ /*********************************** DET Related error code *****************************************/ /* DET error definition for CanSM uninitialised */ #define CANSM_E_UNINIT 0x01u /* DET error definition for NULL POINTER is passed */ #define CANSM_E_PARAM_POINTER 0x02u /* DET error definition for invalid network handle */ #define CANSM_E_INVALID_NETWORK_HANDLE 0x03u /* DET error definition for invalid Controller ID */ #define CANSM_E_PARAM_CONTROLLER 0x04u /* DET error definition for invalid tranceiver ID */ #define CANSM_E_PARAM_TRANSCEIVER 0x05u /* DET error definition for error due to network request during pending indication */ #define CANSM_E_WAIT_MODE_INDICATION 0x07u /* FC_VariationPoint_START */ /* DET error definition for invalid Baudrate Configuration */ #define CANSM_E_PARAM_INVALID_BAUDRATE 0x09u /* FC_VariationPoint_END */ /* DET error definition for invalid Mode request for a network failed */ #define CANSM_E_MODE_REQUEST_TIMEOUT 0x0Au /* DET error definition for Null pointer in case of PBS */ #define CANSM_E_INIT_FAILED 0x0Cu /*As per 4.0.2*/ /* DET error definition for error due to network mode request during bus off recovery */ #define CANSM_E_BUSOFF_RECOVERY_ACTIVE 0x06u /* DET error definition for communication mode request */ #define CANSM_E_INVALID_COMM_REQUEST 0x08u /*************************************Service Id's for the Api's***************************/ /* Service Id for CanSM_Init API */ #define CANSM_INIT_SID 0x00u /*Service Id for CanSM_GetVersionInfo API */ #define CANSM_GETVERSIONINFO_SID 0x01u /* Service Id for CanSM_RequestComMode API */ #define CANSM_REQUESTCOMMODE_SID 0x02u /* Service Id for CanSM_GetCurrentComMode API */ #define CANSM_GETCURRENTCOMMODE_SID 0x03u /* Service Id for CanSM_ControllerBusOff API */ #define CANSM_CONTROLLERBUSOFF_SID 0x04u /*Service Id for CanSM_MainFunction API */ #define CANSM_MAINFUNCTION_SID 0x05u /* Service Id for CanSM_ConfirmPnAvailability API */ #define CANSM_CONFIRMPNAVAILABILITY_SID 0x06 /* Service Id for CanSM_ControllerModeIndication API */ #define CANSM_CTRLMODEINDICATION_SID 0x07u /* Service Id for CanSM_CheckTransceiverWakeFlagIndication API */ #define CANSM_CLEARTRCVWUFFLAGIND_SID 0x08u /* Service Id for CanSM_TransceiverModeIndication API */ #define CANSM_TRCVMODEINDICATION_SID 0x09u /* Service Id for CanSM_CheckTransceiverWakeFlagIndication */ #define CANSM_CHECKTRCVWAKEFLAGIND_SID 0x0au /* Service Id for CanSM_TxTimeoutException API */ #define CANSM_TXTIMEOUTEXCEPTION_SID 0x0bu #if (CANSM_CHANGE_BAUDRATE_API == STD_ON) /* Service Id for CanSM_CheckBaudrate API */ #define CANSM_CHECKBAUDRATE_SID 0x0cu /* Service Id for CanSM_ChangeBaudrate API */ #define CANSM_CHANGEBAUDRATE_SID 0x0eu #endif /*Service Id for CanSM_StartWakeupSource API */ #define CANSM_STARTWAKEUPVALIDATION_SID 0x11u /*Service Id for CanSM_StoptWakeupSource API */ #define CANSM_STOPWAKEUPVALIDATION_SID 0x12u /*Service Id for CanSM_SetEcuPassive API */ #define CANSM_ECUPASSIVE_SID 0x13u #if (CANSM_SET_BAUDRATE_API == STD_ON) /*Service Id for CanSM_SetBaudrate API */ #define CANSM_SETBAUDRATE_SID 0x0du #endif #define CANSM_GETBUSOFFDELAY_SID 0x0fu /* Service Id for CanSM_GetBusoff_Substate API */ #define CANSM_GETBUSOFFSUBSTATE_SID 0x0Fu /*Service Id for CanSM_GetNetworkMode_Substate API */ #define CANSM_GETNETWORKMODESUBSTATE_SID 0x11u /* *************************************************************************************************** * Type definitions *************************************************************************************************** */ /* FC_VariationPoint_START */ #if (CANSM_DSM_REINIT_ENABLED != STD_OFF) typedef struct { VAR(uint8, TYPEDEF) DEMReinitFlag_u8; Dem_EventStatusType CanSM_DEM_Eventstatus_u8; } CanSM_NetworkConf_DEM_tst; #endif /* FC_VariationPoint_END */ /*Network Configuration*/ typedef struct { P2CONST(uint8, TYPEDEF, CANSM_APPL_DATA)Cntrl_startidx_pu8; VAR(Dem_EventIdType, TYPEDEF)BusOffEventId_uo; /* Dem EventID for a bus-off for a CanSM Network handle */ #if (CANSM_CALIBRATION == STD_ON) P2FUNC(uint16, TYPEDEF,pBorTimeL1_pfct)(void); /* address of Count Value for Bus-Off Recovery time in Level 1 */ P2FUNC(uint16, TYPEDEF,pBorTimeL2_pfct)(void); /* address of Count Value for Bus-Off Recovery time in Level 2 */ #else VAR(uint16, TYPEDEF) BorTimeL1_u16; /* Count Value for Bus-Off Recovery time in Level 1 */ VAR(uint16, TYPEDEF) BorTimeL2_u16; /* Count Value for Bus-Off Recovery time in Level 2 */ #endif VAR(uint16, TYPEDEF) BorTimeTxEnsured_u16; /* Value in Counts for No Bus Off Event Check */ VAR(uint8, TYPEDEF) Trcv_hndle_u8; /* CAN Tranceiver Handle index */ /* Start Index of the Controllers */ VAR(uint8, TYPEDEF) SizeofController_u8; /* The number of Controllers present in the CanSM Network*/ VAR(uint8, TYPEDEF) BorCntL1L2_u8; /* Count Value at which bus-off recovery state machine switches from level 1 to level 2 */ VAR(NetworkHandleType, TYPEDEF) ComM_channelId_uo; /* ComM channel Id */ #if (CANSM_BOR_TX_CONFIRMATION_POLLING != STD_OFF) VAR(boolean, TYPEDEF) BorTxConfPolling_b; /* Bus Off recovery based on Tx confirmation with polling*/ #endif VAR(boolean, TYPEDEF) BusOffDelayConfig_b; /*Boolean value to enable/disable bus off delay */ VAR(boolean, TYPEDEF) TrcvPnConfig_b; /*partial Network enabled/disabled for Transceiver configured to CanSM Network*/ } CanSM_NetworkConf_tst; /* Values of CANSM states for a Network */ typedef enum { CANSM_BSM_S_NOCOM = (ComM_ModeType)COMM_NO_COMMUNICATION, CANSM_BSM_S_SILENTCOM = (ComM_ModeType)COMM_SILENT_COMMUNICATION, CANSM_BSM_S_FULLCOM = (ComM_ModeType)COMM_FULL_COMMUNICATION, CANSM_BSM_S_NOT_INITIALIZED, CANSM_BSM_S_PRE_NOCOM, CANSM_BSM_WUVALIDATION, CANSM_BSM_S_PRE_FULLCOM, CANSM_BSM_S_CHANGE_BAUDRATE, CANSM_BSM_S_SILENTCOM_BOR, CANSM_BSM_S_TX_TIMEOUT_EXCEPTION }CanSM_NetworkModeStateType_ten; /*This enum is used for Bus off substates*/ typedef enum { CANSM_BOR_IDLE = 1, CANSM_S_BUS_OFF_CHECK = 2, CANSM_S_NO_BUS_OFF = 3, CANSM_S_BUS_OFF_RECOVERY_L1 = 4, CANSM_S_RESTART_CC = 5, CANSM_S_RESTART_CC_WAIT = 6, CANSM_S_BUS_OFF_RECOVERY_L2 = 7 }CanSM_BusOffRecoveryStateType_ten; /* CanSMConfiguration Structure */ typedef struct { P2CONST(CanSM_NetworkConf_tst, AUTOMATIC,CANSM_CONST) CanSM_NetworkConf_pcst; /* Pointer to Network Configuration structure */ /* FC_VariationPoint_START */ #if(CANSM_DSM_REINIT_ENABLED != STD_OFF) P2VAR (CanSM_NetworkConf_DEM_tst, AUTOMATIC, CANSM_CONST ) CanSMNetworkConfDEM_pst; /* Pointer to DEM configuration structure based on CANSM_DSM_REINIT_ENABLED macro */ #endif /* FC_VariationPoint_END */ P2CONST (uint8, AUTOMATIC, CANSM_CONST ) CanSM_NetworktoCtrlConf_pcu8; /* CanSm Network Index mapped to corresponding CAN controller */ CONST(uint8, CANSM_CONST) CanSMModeRequestRepetitionMax_u8; /* Holds Maximal amount of mode request repetitions without a respective mode indication */ CONST(uint16, CANSM_CONST) CanSMModeRequestRepetitionTime_u16; /* Specifies in which time duration the CanSM module shall repeat mode change requests by using the API of the CanIf module*/ VAR(uint8, CANSM_VAR) CanSM_SizeOfCanSMNetworks_u8; /* Holds the number of Networks */ VAR(uint8, CANSM_VAR) CanSM_ActiveConfigset_u8; /* Active configset index */ }CanSM_ConfigType; #define CANSM_START_SEC_CONST_UNSPECIFIED #include "CanSM_MemMap.h" extern const CanSM_ConfigType CanSM_ConfigSet[]; #define CANSM_STOP_SEC_CONST_UNSPECIFIED #include "CanSM_MemMap.h" /* *************************************************************************************************** * Extern declarations *************************************************************************************************** */ #define CANSM_START_SEC_VAR_CLEARED_8 #include "CanSM_MemMap.h" extern VAR(uint8, CANSM_VAR) CanSM_GetBusOffDelay_Value_u8[CANSM_NUM_CAN_NETWORKS]; #define CANSM_STOP_SEC_VAR_CLEARED_8 #include "CanSM_MemMap.h" /* *************************************************************************************************** * Extern declarations *************************************************************************************************** */ #define CANSM_START_SEC_CODE #include "CanSM_MemMap.h" #if (CANSM_ECUC_RB_RTE_IN_USE == STD_OFF) extern FUNC(void, CANSM_CODE) CanSM_MainFunction(void); #endif extern FUNC(void, CANSM_CODE) CanSM_Init( const CanSM_ConfigType* ConfigPtr ); extern FUNC(void, CANSM_CODE) CanSM_GetVersionInfo( P2VAR(Std_VersionInfoType, AUTOMATIC, CANSM_APPL_CODE) VersionInfo ); #if (CANSM_SET_BAUDRATE_API == STD_ON) extern FUNC(Std_ReturnType, CANSM_CODE) CanSM_SetBaudrate(VAR(NetworkHandleType, AUTOMATIC) Network,CONST(uint16,AUTOMATIC) BaudRateConfigID); #endif /* FC_VariationPoint_START */ #if (CANSM_CHANGE_BAUDRATE_API == STD_ON) extern FUNC(Std_ReturnType, CANSM_CODE) CanSM_ChangeBaudrate(VAR(NetworkHandleType, AUTOMATIC) network,CONST(uint32,AUTOMATIC) Baudrate); extern FUNC(Std_ReturnType, CANSM_CODE) CanSM_CheckBaudrate(VAR(NetworkHandleType, AUTOMATIC) network, CONST(uint32,AUTOMATIC) Baudrate); #endif /* FC_VariationPoint_END */ extern FUNC(Std_ReturnType, CANSM_CODE) CanSM_StartWakeupSource(VAR(NetworkHandleType, AUTOMATIC) network); extern FUNC(Std_ReturnType, CANSM_CODE) CanSM_StopWakeupSource(VAR(NetworkHandleType, AUTOMATIC) network); extern FUNC(void, CANSM_CODE) CanSM_Rb_DisableBusOffRecovery(VAR(NetworkHandleType, AUTOMATIC) network); extern FUNC(Std_ReturnType, CANSM_CODE) CanSM_GetNetworkMode_Substate(VAR(NetworkHandleType, AUTOMATIC) network, P2VAR(CanSM_NetworkModeStateType_ten, AUTOMATIC, CANSM_APPL_DATA) NetworkMode_SubstatePtr ); extern FUNC(Std_ReturnType, CANSM_CODE) CanSM_GetBusoff_Substate(uint8 ControllerId, CanSM_BusOffRecoveryStateType_ten* BORStatePtr); #if(CANSM_TX_OFFLINE_ACTIVE_SUPPORT != STD_OFF) #define CANSM_START_SEC_CODE #include "CanSM_MemMap.h" extern FUNC(Std_ReturnType, CANSM_CODE) CanSM_SetEcuPassive( boolean CanSM_Passive ); #define CANSM_STOP_SEC_CODE #include "CanSM_MemMap.h" #endif #define CANSM_STOP_SEC_CODE #include "CanSM_MemMap.h" #endif /*CANSM_H*/
- CanSM_ComM.h:它包含了提供给ComM的API声明。
#ifndef CANSM_COMM_H #define CANSM_COMM_H /* *************************************************************************************************** * Includes *************************************************************************************************** */ #include "CanSM_Cfg.h" #include "ComM.h" /******************************************************************************* ** Function Prototypes ** *******************************************************************************/ #define CANSM_START_SEC_CODE #include "CanSM_MemMap.h" extern FUNC(Std_ReturnType, CANSM_CODE) CanSM_RequestComMode(VAR(NetworkHandleType, AUTOMATIC) network, VAR(ComM_ModeType, AUTOMATIC) ComM_Mode); extern FUNC(Std_ReturnType, CANSM_CODE) CanSM_GetCurrentComMode(VAR(NetworkHandleType, AUTOMATIC) network, P2VAR(ComM_ModeType, AUTOMATIC, CANSM_APPL_DATA) ComM_ModePtr); #define CANSM_STOP_SEC_CODE #include "CanSM_MemMap.h" #endif /* CANSM_COMM_H*/
- CanSM_BswM.h:它包含了枚举CanSM_BswMCurrentStateType的声明。
#ifndef CANSM_BSWM_H #define CANSM_BSWM_H /*************************************************************************************************** * Includes *************************************************************************************************** */ #include "CanSM_Cfg.h" /* ******************************************************************************** ** Enumeration ******************************************************************************* */ /*CAN specific communication modes / states notified to the BswM module*/ typedef enum { CANSM_BSWM_NO_COMMUNICATION = 0, CANSM_BSWM_SILENT_COMMUNICATION, CANSM_BSWM_FULL_COMMUNICATION, CANSM_BSWM_BUS_OFF, CANSM_BSWM_CHANGE_BAUDRATE }CanSM_BswMCurrentStateType; #endif /*CANSM_BSWM_H*/
- CanSM_Cbk.h:它包含了提供给其他模块的回调函数声明。
#ifndef CANSM_CBK_H #define CANSM_CBK_H /* *************************************************************************************************** * Includes *************************************************************************************************** */ #include "CanSM_Cfg.h" #include "CanIf.h" /******************************************************************************* ** Function Prototypes ** *******************************************************************************/ #define CANSM_START_SEC_CODE #include "CanSM_MemMap.h" extern FUNC(void, CANSM_CODE) CanSM_ControllerBusOff(VAR(uint8, AUTOMATIC) ControllerId ); extern FUNC(void, CANSM_CODE) CanSM_ControllerModeIndication(VAR(uint8, AUTOMATIC) ControllerId,VAR(CanIf_ControllerModeType,AUTOMATIC) ControllerMode); extern FUNC(void, CANSM_CODE) CanSM_TransceiverModeIndication(VAR(uint8, AUTOMATIC) TransceiverId,VAR(CanTrcv_TrcvModeType,AUTOMATIC) TransceiverMode); #if(CANSM_PN_SUPPORT_CONFIGD == STD_ON) extern FUNC(void, CANSM_CODE) CanSM_ClearTrcvWufFlagIndication(VAR(uint8, AUTOMATIC) Transceiver); extern FUNC(void, CANSM_CODE) CanSM_CheckTransceiverWakeFlagIndication(VAR(uint8, AUTOMATIC) Transceiver); extern FUNC(void, CANSM_CODE) CanSM_ConfirmPnAvailability(VAR(uint8, AUTOMATIC) TransceiverId); #endif #define CANSM_STOP_SEC_CODE #include "CanSM_MemMap.h" #endif /*CANSM_CBK_H*/
- CanSM_Priv.h:它包含了CanSM模块私有的结构体与函数声明。
- CanSM_TxTimeoutException.h:它包含了CanSM_TxTimeoutException()函数声明。
静态代码
主要介绍常见的静态代码涉及API说明,具体详细完整的介绍读者可以参考《AUTOSAR_SWS_CANStateManager.pdf》以及《RTA-BSWReferenceGuide.pdf》。
- CanSM_Init/CanSM_DeInit:CanSM模块初始化与去初始化。
- CanSM_RequestComMode:此API将CAN网络的通信模式更改为所请求的通信模式。
- CanSM_GetCurrentComMode:此API获取当前CAN网络的通信模式。
- CanSM_MainFunction:此API为CanSM的主功能函数,需要周期调用。
- CanSM_ControllerBusOff:此回调函数向CanSM通知某个CAN控制器上的BusOff事件。
- CanSM_ControllerModeIndication:此回调应将CAN控制器模式变化通知CanSM模块。
BusOff恢复专题
CAN总线的BusOff状态是指当CAN节点发送/接收错误次数超过规定的限制时,该节点将被自己禁用,不在发送/接收CAN帧,直到节点被重新启动或者重置。这是一种保护机制,以避免因晶振不准等物理原因导致节点往总线发送错误的波特率帧,最终影响其余正常节点通信。
为了避免某个设备因为自身原因(例如硬件损坏)导致无法正确收发报文而不断的破坏总线的数据帧,从而影响其它正常节点通信,CAN网络具有严格的错误诊断功能,CAN通用规范中规定每个CAN控制器中有一个发送错误计数器和一个接收错误计数器。根据计数值不同,节点会处于不同的错误状态,并根据计数值的变化进行状态转换,状态转换如下图所示。
当节点发送失败时,发送错误计数TEC加8,节点发送成功减去1。进入BusOff需要的是TEC>255,也就是说32次发送错误(位错误、形式错误、NACK等)即会BusOff。在总线关闭状态下,节点不能发送报文或应答总线上的报文,也就意味着不能再对总线有任何影响。
状态跳转和错误计数的规则使得节点在发生通信故障时有了较好的自我错误处理和恢复机制,从一种较严重的错误状态跳转到另一种严重性相对较低的状态,本质上就是一种恢复过程。在通信过程中,错误主动和错误被动两种状态下节点的恢复过程一般不需要MCU进行额外的编程处理,当节点进入总线关闭状态后,如果Can控制器开启了自动恢复功能,CAN控制器在检测到128次11个连续的隐性位后即可恢复通信,以500K的波特率为例,总线上只要有128*11*(1/500000)= 2.816ms的空闲,便可以轻易的恢复通信。
我们已经知道,当进入总线关闭状态时,节点已经发生了严重的错误,处于不可信状态,如果迅速恢复参与总线通信,具有较高的风险,但是如果不开启自动恢复功能,节点只能通过断电重新上电才能从BusOff中恢复。因此,在实际的应用中,往往会通过MCU对CAN控制器总线关闭状态的恢复过程进行编程处理,以控制节点从总线关闭状态恢复的时间,达到既提高灵活性又保证节点能够快速响应BusOff错误。具体包括“快恢复”和“慢恢复”策略,两种策略一般同时应用。
AUTOSAR快/慢恢复流程
CanSM需要在状态CANSM_BSM_S_FULLCOM与CANSM_BSM_S_SILENTCOM处理BusOff事件,处理的过程会首先选择快恢复参数,重复CanSMBorCounterL1ToL2次数后会进行慢恢复。恢复的流程如下:
- CAN控制器产生BusOff中断通知CanSM模块BusOff事件(或者轮询得到BusOff事件)。
- CANSM将ComM置为COMM_SILENT_COMMUNICATION、BswM置为CANSM_BSWM_BUS_OFF,关闭Tx PDU,并尝试重新启动Can控制器。重启CAN控制器首先采用快恢复参数,重启最大CanSMBorCounterL1ToL2次,时间间隔为CanSMBorTimeL1。
- 在进行CanSMBorCounterL1ToL2次尝试恢复后,如果仍然发生BusOff,转为慢恢复,时间间隔为CanSMBorTimeL2(例如2000ms)。进入慢恢复后一直执行慢恢复。
- 如果恢复次数超过CanSMModeRequestRepetitionMax,控制器仍然无法成功转换为START,则此路CAN从此下线。
- 如果在恢复次数限制内成功配置控制器进入START状态,则会打开Tx PDU,并将ComM置为COMM_FULL_COMMUNICATION、BswM置为CANSM_BSWM_FULL_COMMUNICATION,同时启动TxEnsureTimer确定在这个Timer超时期间是否会重新BusOff。
- 若TxEnsureTimer耗尽之前再一次出现BusOff,则开始下一次的BusOff恢复机制。
下面是一个简易的流程图,帮助您更好的理解整个BusOff的恢复过程。
十六宿舍 原创作品,转载必须标注原文链接。
©2023 Yang Li. All rights reserved.
欢迎关注 『十六宿舍』,大家喜欢的话,给个👍,更多关于嵌入式相关技术的内容持续更新中。