【小猫爪】AUTOSAR学习笔记06-Communication Stack之ComM模块
前言
前面分别介绍了ComNm和ComSM两兄弟,这一章则来看看两兄弟的老板,那就是Communication Stack中管理层中最核心的一个模块,那就是ComM模块。
前面已经分别介绍了干活两兄弟NM模块和SM模块,NM模块主要负责的是基于总线报文管理ECU休眠,SM模块则是控制总线通信状态,这两兄弟其实都是实际执行者,ComM模块则是真正的总线管理者,用户只要对ComM模块告知自己想要的通信模式,ComM模块则会直接协调NM和SM两兄弟直接干活以达到用户想要的通信模式。
1 ComM简介
ComM 模块位于 AUTOSAR 的系统服务层,透过 RTE 与用户(这里的用户指的是可以对ComM模块下达请求的模块,可以是BswM,SWC, Runables等)直接交互。向下控制各总线状态管理器和网络管理器(SM 和 Nm),为用户提供统一的通信管理功能,同时协调SM 和 Nm 之间的状态关系。
2 ComM功能介绍
ComM 模块主要功能如下:
1. 初始化
2. 用户或 DCM 请求通信模式
3. 通知应用通信模式切换
4. 限制通道或 ECU 的通信功能
5. 与 EcuM 的唤醒功能协同、与 BswM 控制通信协同
6. 控制各通道的总线状态
7. 请求或释放网络管理服务
2.1 PNC 状态管理
ComM进行通信模式管理提供有两大状态机,其中一个就是PNC 状态管理,在介绍之前,得搞清楚PNC到底是个啥?PNC是Partial Network Cluster的缩写,一般将这些在某种条件下需要保持同样工作状态,且连接在同一总线(或由网关连接)的ECU称之为一组PNC,对这些ECU统一进行网络管理。在一些特殊应用中,如果网关也使能了PNC,那么则可以通过网关进行网络协调,让不同总线上的ECU组成一个大型PNC组。
ComM 模块对每组 PN 定义了一组状态机,用于描述各 PN 组的状态、状态转移关系和状态转移动作。该状态机共包含 4 种状态,分别为:
- PNC_NO_COMMUNICATION
- PNC_PREPARE_SLEEP
- PNC_READY_SLEEP
- PNC_REQUESTED
状态切换如下图所示:
观察状态切换图,可以看到上面出现了ERA, EIRA的字眼,无论是开启还是关闭ECU的通信功能,都是需要进行请求的,而这个请求则分为内部请求与外部请求,我们称之为External Internal Request Array,也即EIRA。每一个ECU都需要有EIRA,来根据部分网络活动进而切换IPdu Group的状态。至于ERA,External Requested Array,它主要用于网关,仅收集外部PN请求的场景。网关会将外部PN请求镜像回请求总线,同时将这个请求发送到其他的总线上。IRA,Internal Requested Array,代表ECU内部对于PNC状态的请求,既可以是SWC通过RTE直接请求ComM接口,或者在某种条件满足时,由BswM请求ComM接口。
系统上电后整个PNC的状态在COMM_PNC_NO_COMMUNICATION。
在PNC状态切换过程中如果是主动唤醒节点直接请求FULL通信,或者是网关节点控制的节点在收到网关下的ERA数组的相关状态位,直接从COMM_PNC_NO_COMMUNICATION进入到COMM_PNC_REQUESTED阶段。如果是被动唤醒的节点,则根据接收到唤醒报文中的PNC位状态切换到COMM_PNC_READY_SLEEP或者COMM_PNC_PREPARE_SLEEP。
而COMM_PNC_FULL_COMMUNICATION内部的三个子状态的切换也是根据该节电的是否能被动唤醒功能进行内部的状态切换,主要体现是主动唤醒下需要Request Full相关的操作以及NM报文中对应的UserData中相关的PNC位进行转换的。
总结一下可以让ComM的PNC状态机切换的事件可以来自于:
1. 来自用户的请求 ComM_RequestComMode()函数调用
2. 来自 EcuM 模块的唤醒通知 ComM_EcuM_WakeUpIndication()
3. 来自 Com 模块的 PNC 值变化通知
4. ComM 模块内部定时器超时事件
2.2 Channel状态管理
上面提到ComM进行通信模式管理提供有两大状态机,另外一个就是Channel状态管理。这里的Channel指的是一个通信总线,比方说,一路ECU有两路CAN,一路FlexRay,那么就可以说对于ComM模块就有3个Channel。ComM 模块对每一个Channel都定义了一个状态机,用于描述通道的各种状态、状态转移关系和状态转移动作。该状态机共包含 3 个主状态,分别为:
- COMM_NO_COMMUNICATION
- COMM_FULL_COMMUNICATION
- COMM_SILENT_COMMUNICATION
其中除 COMM_SILENT_COMMUNICATION 外,其余状态还包含有子状态。其状态转移图如下:
1. COMM_NO_COMMUNICATION:系统上电后进入到COMM_NO_COMMUNICATION,在该状态下具有下面两个子状态:COMM_NO_COM_NO_PENDING_REQUEST和COMM_NO_COM_REQUEST_PENDING。
2. COMM_NO_COM_NO_PENDING_REQUEST:在初始化完成ComM后进入该状态,该状态下总线不能进行任何的通信活动,需要等待FULL_COM请求切换状态,请求可来源于:① 用户请求User Request;② DCM Notification需要激活对应的通道;③ 来自于EcuM或者NM的Passive WakeUp通知。
3. COMM_NO_COM_REQUEST_PENDING:收到FULL_COM请求后,会切换至COMM_NO_COM_REQUEST_PENDING状态,然后等待Communication Allowed的触发信号,只有 “CommunicationAllowed=TRUE时” 才能将通信模式转换为FULL_COM模式下进行数据通信,如果没有Allowed的使能,则对FULL_COM请求将不会被执行。
4. COMM_FULL_COMMUNICATION:离开NO_COM状态后,则进入COMM_FULL_COMMUNICATION状态,在该状态下总线可以进行正常的数据通信,其也有两个子状态:COMM_FULL_COM_NETWORK_REQUESTED和COMM_FULL_COM_READY_SLEEP。而这两个模式的切换则是会根据NmVariant的变化来变化,后面会对NmVariant进行介绍。
5. COMM_SILENT_COMMUNICATION:该状态主要用于支持NM的Sleep流程处理,是NM状态机的Prepare Sleep阶段,只有在NM进入到prepare Sleep模式下该状态才进入。
总结一下可以让ComM的Channel状态机切换的事件可以来自于:
1. 来自 User 的请求 ComM_RequestComMode()函数调用
2. 来 自 Dcm 模 块 的 ComM_DCM_ActiveDiagnostic() 和ComM_DCM_InactiveDiagnostic()函数调用
当诊断仪与 Dcm 模块通信时,需要保证通道的正常可用状态,不能进入休眠。这时Dcm 模块通过在适当的时机调用 ComM 模块的 ComM_DCM_ActiveDiagnostic()来请求通道保持在FULL_COM状态 。 完成诊断通信后 , Dcm模块再调用ComM_DCM_InactiveDiagnostic()接口释放对通道的使用。这时如果没有其他用户再使用该通道,则通道最终将进入 NOCOM 模式,通道关闭,所以在前面介绍Channel状态管理状态切换的时候就提到了Dcm模块是让ComM Channel状态切换的一个重要来源。
3. 来 自 Nm 模 块 的 网 络 状 态 通 知 ComM_Nm_NetworkMode() 与ComM_Nm_PrepareBusSleepMode()和 ComM_Nm_BusSleepMode()函数调用
4. 来自 Nm 的 ComM_Nm_RestartIndication()和 ComM_Nm_NetworkStartIndication()
5. 来自 EcuM 模块的唤醒通知 ComM_EcuM_WakeUpIndication()
当某个通信通道发生唤醒事件后,EcuM 会调用 ComM_WakeupIndication()函数通知ComM 模块。该通知会作为通道正常工作的一个触发源,将该通道状态切换到 FULLCOM模式。这时 ComM 会调用网络管理模块的 Nm_PassiveStartup()唤醒网络管理模块。
6. ComM 模块内部定时器等
2.3 通信禁止功能
通信禁止包含两种情况:一是禁止唤醒总线,二是限制通信。
在某些唤醒线路故障情况下,某些应用会错误地请求总线,从而错误地唤醒总线上其他 ECU。这时可以通过调用 ComM_PreventWakeUp()接口,忽略用户请求,从而避免系统错误。该功能称为禁止唤醒总线。该功能只在对应通道进入 NO_COM 或 SILENT_COM时有效。
当通道处于 FULL_COM 模式时,应用可以调用 ComM_LimitChannelToNoComMode()或 ComM_LimitECUToNoComMode()来强制某个通道或整个 ECU 所有通道进入 NO_COM模式。这时 ComM 将忽略 User 对通道的占用,调用 Nm_NetworkRelease()释放网络管理。当远程休眠条件满足时,通道将最终进入 NO_COM 模式。该功能称为限制通信。该功能只在对应通道处于 FULL_COM 时有效。
2.4 不同类型的NM
NM模块有一个参数叫做NmVariant,可以指定每一个通道所对应的NM模块的网络管理能力,分为四种类型:
- FULL:该通道具备网络管理模块的所有功能,因此本 ECU 具备保持总线唤醒的能力,同时可以由 NM 向 ComM 模块指示何时进入网络同步休眠状态。
- PASSIVE:该通道的网络管理模块处于 PASSIVE 模式,即本身只接收网络管理报文,但不向外发送网络管理报文。本 ECU 不具备保持总线唤醒的能力,但可以根据其他 ECU的网络管理报文,向 ComM 模块指示进入网络同步休眠状态。
- LIGHT:该通道不具有网络管理模块,因此不会接收或发送网络管理报文。但可以通过配置定时器,在没有通信需求的一段时间以后自动进入休眠状态。该配置项一般用于需要延迟休眠的场景。
- NONE:该通道不具有网络管理模块,因此不会接收或发送网络管理报文。一旦进入FULL_COM模式就不会退出,也不会自动进入休眠状态,只有通过 ECU 电源才能控制网络关闭。
在同一个 ECU 上,FULL 和 PASSIVE 不能同时存在,即当某个通道配置了 PASSIVE类型时,本 ECU 上所有通道都只能为 PASSIVE、LIGHT 或 NONE 之一,不能为 FULL。当某个通道配置了 FULL 时,本 ECU 上所有通道都只能为 FULL、LIGHT 或 NONE 之一,不能为 PASSIVE。
FULL 是最常见的网络类型,在大部分应用场景中推荐使用该配置,这时需要将 NM的 PASSIVE 模式禁用。在 FULL 类型网络通道上,状态转移图与标准图一致。PASSIVE 节点对网络的休眠唤醒没有决定权,完全听从其他节点的仲裁。例如本节点在仍有发送应用报文的需求时,网络上其他节点决定休眠,则本节点会无条件同步休眠,关闭总线接口的发送功能。
LIGHT 节点和 NONE 节点不具备网络管理功能,若接入一个具备网络管理功能的网络中,会影响网络正常休眠唤醒功能。一般应当独立使用或同样类型的节点组网。这两种类型的通道没有 SILENT 状态。NONE 节点一旦进入 FULL_COM 状态就无法切回NO_COM,除非系统复位。LIGHT 节点从 FULL_COM 到 NO_COM 是通过内部的一个定时器实现的,该定时器参数值由配置参数 ComMNmLightTimeout 决定。
2.5 User、PNC 与 Channel 的映射
上面提到了ComM模块的两种状态机,那么怎么样正确使用这两种状态机呢?用户,PNC,Channel三者的映射关系如下图所示:
每个 User 向下可以关联多个 PNC,每个 PNC 向上也可以关联多个 User,User 既可以关联 PNC 也可以直接关联 Channel,每个 PNC 向下可以关联多个 Channel,每个 Channel向上也可以关联多个 PNC 或 User。但是同一 Channel 不能既关联 User,又关联该 User下的 PNC。说得简单点就是自上而下,是交叉树状自上而下,用户想要控制一个一个总线接口,可以是User->PNC->Channel, 也可以是User->Channel。
User 可以通过接口请求 FULLCOM 和 NOCOM 模式,此时所有该 User 映射的通道或 PNC 都会收到请求。由于一个通道或 PNC 可以映射多个 User,因此只有当映射的所有 User 都请求了 NOCOM 时,ComM 才会在该通道或 PNC 上释放通信能力,否则只要有一个 User 请求 FULLCOM,ComM 都会为该通道或 PNC 保持通信能力。
在某些特殊情况下,用户可以通过 API 限制某个通道或整个 ECU 的通信能力,这时即使有用户请求FULLCOM,该请求也会被暂时抑制。限制通信的优先级高于 User 对通道的请求。
DCM 模块会使用某些通道作为诊断通道。它通过 API 激活该通道的通信能力。此时不论该通道映射的 User 请求何种模式,也不论该通道是否被限制通信,ComM 都会为该通道保持通信能力,也就是说 DCM 激活通道的优先级最高。
2.6 状态保存
ComM 的一些配置状态和计数值可以保存到非易失存储器中,在下次上电后恢复。可以保存的内容包含:
1. ECU 所有通道的禁止唤醒总线状态(NoWakeup)
2. ECU 组分类(EcuGroupClassification)
3. 禁止计数器
当使能此功能时,需要在 NvM 模块配置这几个 Block,且需要将其在 NvM 模块中将这几个模块配置在 ReadAll 和 WriteAll 列表中,以便在上电时自动恢复数据,以及下电前自动保存数据。