写在前面:
入行一段时间了,基于个人理解整理一些东西,如有错误,欢迎各位大佬评论区指正!!!
经常开公司的朋友都知道,如果作为老板,如果你有十多个项目,近百个开发工程师。你想了解每个项目进展,不可能One By One去和工程师沟通。那么项目经理就很重要了。
我理解的CANSM模块就是做项目经理的工作,向上汇报状态,向下发布工作,当项目出现风险时快速处理。
0.CANSM主要功能
0.1CAN控制器状态管理
当CanSM接收到ComM的Can状态切换请求或者检测到总线BusOff后,需要切换CAN控制器的状态。
调用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(),来通知通信模式的改变。
0.2CAN收发器状态管理
当CanSM接收到ComM的CAN状态切换请求,如果对应的CAN通道包含收发器,CanSM需要切换对应CAN收发器的状态,调用CanIf的CanIf_SetTrcvMode()请求CAN收发器在CANTRCV_TRCVMODE_NORMAL、CANTRCV_TRCVMODE_SLEEP、 CANTRCV_TRCVMODE_STANDBY之间切换,CanIf模块再调用Can收发器驱动接口CanTrcv_SetOpMode()执行具体CAN收发器的状态切换。
0.3CAN总线BusOff故障处理
当CAN控制器检测到BusOff(通过Busoff中断或者周期调用Can_MainFunction_BusOff()进行Polling获取到总线进入BusOff),CAN驱动将调用CanIf_ControllerBusOff()通知BusOff事件到CanIf,CanIf再调用CanSM_ControllerBusOff()通知busoff事件到CanSM。CanSM在检测到对应Can通道BusOff事件发生后,将尝试进行BusOff恢复。
1.依赖模块
作为一名项目经理,要知道自己向谁汇报,工作都指派给谁。
那CANSM都依赖那些模块?
1.1ECUM
EcuM模块初始化CanSM模块,并与CanSM模块交互进行CAN唤醒验证。
进行CAN唤醒验证这部分涉及EcuM_StartWakeupSources等函数,当出现唤醒源后,调用CanSM_StartWakeupSources唤醒对应CAN通道。
1.2BSWM
BSW调度器模块调用CanSM模块的循环MainFunction,这对于CanSM模块的状态机运转是必要的。
CanSM需要向BswM模块通知总线特定模式的更改。CanSM通过BswM_CanSM_CurrentState()上报模式改变,状态包括:
1.3ComM
ComM模块使用CanSM模块的API来请求CAN网络的通信模式,这些通信模式具有唯一的网络手柄标识,CanSM模块还会将其CAN网络的当前通信模式通知给ComM模块。下图包含了CanSM提供给ComM的控制API。可见不光CanSM,FrSM和EthSM同样有类似函数。
1.4CANIf
CanSM模块使用Canlf模块的API来控制分配给CAN网络的CAN控制器和CAN收发器的操作模式,Canlf模块会向CanSM模块通知控制器事件。下图是CanIf动态配置代码中包含的CanSM相关事件发生时的回调函数。
1.5CANNM
CanSM模块需要向CanNm模块通知部分网络可用性,并在部分联网的情况下处理已通知的CanNm超时异常。
2.状态机
下图为CanSM模块最顶层的状态机CANSM_BSM,它包含了各个子状态机的转换触发(Trigger)以及检测条件(Guarding condition)与状态转换效果(Effect)。
2.1转换触发条件
下文水平线用以分类
- 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。对应上文中ECUM模块中处理
- Trigger-T_STOP_WAKEUP_SOURCE:如果请求CanSM_StopWakeUpSource()返回E_OK,CanSM的状态机应该回到CANSM_BSM_S_PRE_NOCOM。对应上文中ECUM模块中处理
- 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。(Silent模式下停发APP报文)
- 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状态。
2.2转换前置条件
- Guarding condition-G_FULL_COM_MODE_REQUESTED:判断最新接受的通信模式请求是CanSM_RequestComMode()是否为COMM_FULL_COMMUNICATION。
- Guarding condition-G_SILENT_COM_MODE_REQUESTED:判断最新接受的通信模式请求是CanSM_RequestComMode()是否为COMM_SILENT_COMMUNICATION。
2.3CANSM_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一致。
2.4子状态机
上图中包含9种不同的子状态,部分子状态内部包含子状态机。
2.4.1CANSM_BSM_WUVALIDATION
子状态中,WU代表Wake-Up,VALIDATION代表验证,子状态机负责验证CAN总线是否处于活动状态,与EcuM配合完成唤醒源的验证,并根据需要完成对CANSM_BSM_S_PRE_FULLCOM状态的转换,主要是针对有Can收发器携带休眠唤醒功能的时候,此时此时需要借助外设CAN收发器驱动。此时调用的接口均为CDD内部接口,例如CanIf_SetTrcvMode接口到CANTRCV_TRCVMODE_NORMAL切换,需要调用CDD提供的接口。
2.4.2CANSM_BSM_S_PRE_NOCOM
这个子状态机是在进入“无通信”状态之前的预备状态。在该状态下,CanSM会等待一段时间来确认是否存在通信问题,如果问题得不到解决,CanSM将转移到“无通信”状态。下图为子状态机的内部状态转换。
2.4.3CANSM_BSM_DeInitPnSupported
了解不多
2.4.4CANSM_BSM_S_SILENTCOM_BOR
子状态表示CAN总线网络在当前处于SILENT时,发生了BusOff错误,从而进入到这个子状态,这个子状态会尝试恢复BusOff错误,并重新回到CANSM_BSM_S_SILENTCOM子状态。
2.4.5CANSM_BSM_S_PRE_FULLCOM
这个子状态是在进入FULLCOM之前的准备子状态,CanSM会执行必要的检查和准备工作,主要是将控制器状态成功设置为START状态。
2.4.6CANSM_BSM_S_FULLCOM
该子状态尝试维持通信FULLCOM状态,完成控制器BusOff或者Reset的处理。
2.4.7CANSM_BSM_S_CHANGE_BAUDRATE
该子状态机如名称所示,主要负责实现在运行过程中实现更改波特率的功能。
3.函数调用
3.1CANSM_StartCanController
3.CANSM_StopCanController
4.配置参数
CANSM模块中需要配置项除了Mainfunction周期,CanController引用。还有两个参数:
CanSMBorTimeL1、CanSMBorTimeL2.
分别配置快恢复时间,慢回复时间。
想了解它俩如何配置,需要先了解CAN BusOff恢复机制,基于需要配置。
4.1BusOff恢复机制
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错误。具体包括“快恢复”和“慢恢复”策略,两种策略一般同时应用。
4.2快/慢恢复机制
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恢复机制。