文章目录
- Com模块功能
- 通信传输控制
- [整体 communication 结构](#整体 communication 结构)
- [Signal 发送流程](#Signal 发送流程)
- [Signal 发送时序图](#Signal 发送时序图)
- [Signal 接收流程](#Signal 接收流程)
-
- [接收信号的 UpdateBit](#接收信号的 UpdateBit)
- [Signal 接收时序图](#Signal 接收时序图)
- [Com_TxPduInfo / Com_RxPduInfo、Com_PduGrpVector 数据来源](#Com_TxPduInfo / Com_RxPduInfo、Com_PduGrpVector 数据来源)
- [Com_TxSigGrpInfo / Com_RxSigGrpInfo](#Com_TxSigGrpInfo / Com_RxSigGrpInfo)
-
- [1. Signal Group 概念](#1. Signal Group 概念)
- [2. Com_TxSigGrpInfo / Com_RxSigGrpInfo](#2. Com_TxSigGrpInfo / Com_RxSigGrpInfo)
- I-PDU、N-PDU、L-PDU关系
Com模块功能
Com 模块为汽车控制单元中的应用软件提供了一个统一的通信环境, 为内部和外部通信定义了公共的软件通信接口, 增强了汽车控制单元中应用软件模块的可移植性。
通信传输控制
Com 模块控制 I-Pdu 数据的接收和发送, 在系统网络状态激活以后可由 BswM 或 CDD 模块调用 Com 提供的 Com_IpduGroupControl 服务函数控制 I-PduGroup 是否需要激活, 只有在 I-PduGroup 的状态为激活 状态时, 对应的 I-Pdu 才能进行数据的接收和发送。
通信传输控制主要实现以下功能点:
- 可将
I-Pdu按照不同的功能或者不同的通道划分到不同的I-PduGroup中, 在启动I-PduGroup时对应该组内的所有I-Pdu才能进行数据的接收和发送。 - 可通过调用
Com_IpduGroupControl服务函数将信号缓存数据设置为初始值。 - 可通过调用
Com_SetIpduGroup服务函数控制单个I-PduGroup的激活状态。 - 可通过调用
Com_ClearIpduGroupVector服务函数将所有的I-PduGroup状态设置为未激活状态, 停止报文的接收和发送处理。
整体 communication 结构
communication 自上到下,数据的传递过程是:
ASW-->RTE-->COM-->PDUR-->CANTP-->CAN Interface-->CAN Driver-->CAN controller-->CAN transceiver-->CAN BUS Line
-
Com模块获取应用层的信号(Signal),经一定处理封装为IPDU(Interaction Layer Protocol Data Unit)发送到PduR模块; -
PduR根据路由协议中所指定的I-PDU目标接收模块,将接收到的I-PDU经一定处理后发送给CanIf;PduR也可以将部分I-PDU发送给CAN TP模块,处理之后再发送给CANIf; -
CanIf将信号以L-PDU(Data Link Layer Protocol Data Unit)的形式发送给CAN驱动模块; -
CAN驱动模块将Message报文发送给CAN controller; -
CAN controller与外部硬件的CAN transceiver(CAN收发器) 进行CAN报文的收发; -
外部硬件
CAN收发器--CAN Transceiver Hardware主要工作内容为,接收CAN bus上的网络信息(通常叫做CAN Frame)相关的信号电平并将其转化为逻辑信息电平转发给CAN Controller, 接收从CAN Controller传输过来的逻辑电平信息并将其转化为信号电平传从到CAN bus上。CAN Transceiver有两条线,一条连CAN总线的高电平,一条低电平;

Signal 发送流程
以 NeuSar 为例,梳理 signal 更新发送流程:
- 在
NeuSar中,每一个signal都有一个buffer用来存储数据 - 调用
Rte_Write_XXX_XXX更新RTESignal的全局变量,并调用Com层接口 - 调用
Com_SendSignal(SignalId, SignalDataPtr)->Com_SendSignal_Process(SignalId, SignalDataPtr); 将需要发送的信号值,保存到相应signal的buffer中 task中周期调用Com_MainFunctionTx(void)->Com_PduTxProcess(com_astPdu),在Com_PduTxProcess中根据PDU的发送触发方式,进行相应处理- 以 周期 触发为例,调用
Com_PduPeriodicTxProcess(PduInfo, PduCycle)->Com_PduCycleSend(PduInfo, PduCycle)->Com_OnePduSend(PduInfo)->Com_PduTxSetVal(PduInfo),调用Com_PduTxSetVal ( PduInfo )把信号值放入PDU中(Com_TxPduInfo[txSigInfoPtr->acPduId].dataraw这个指针指向存储PDU数据的地址) - 调用
PduR_ComTransmit(PduId, PduInfo)->PduR_UpTransmit(PduId, PduInfo)->PduR_Route_LoTransmit(dstPduPtr, pduInfoPtr),在调用PduR_Route_LoTransmit中,根据路由通道不同,可以选择CanIf或者CanTp两种方式。 - 以
CanTp为例:CanTp_Transmit(CanTpTxSduId, CanTpTxInfoPtr)->CanTp_Transmit_WithData(CanTpTxSduId, CanTpTxInfoPtr, ErrorId), 在CanTp_Transmit_WithData函数中,将I-PDU数据封装成N-PDU数据(增加 帧类型、长度、目的地址等信息) CanTp_TxStateTask(CanTpTxSduId, TRUE:代表使用数据), 调用CanTp_TxStateTask发送数据,根据CAN类型不同,选择Can 2.0或者CanFd,继续封装N-PDU信息CanIf_Transmit(CanIfTxSduId, CanIfTxInfoPtr)->CanIf_Transmit_Process(txPduPtr, pduInfoPtr)->CanIf_TxQueueFilling(txPduPtr, pduInfoPtr, sduLen, canId),在CanIf_TxQueueFilling中将待发送的数据写入Can Driver的数据缓冲区内Can Driver成功发送报文,通过CanIf_TxConfirmation函数回调通知CanIfCanIf通过调用PduR_CanIfTxConfirmation -> PduR_LoTxConfirmation回调通知PduR发送成功PduR调用PduR_Route_UpTxConfirmation -> Com_TxConfirmation通知Com层发送成功Com通过发送消息确认来调用Com_TxPduClearUb_Process清除更新位。如果该signal绑定了回调函数,则执行回调函数,执行相关操作
设置信号的 UpdateBit
Update Bit 为 Com 信号或信号组数据更新位, 在通信矩阵中以一个信号形式存在, 占用 1 个 bit, 当信号数据发送时将 Update Bit 值设置为 1, 发送完成后将 Update Bit 设置为 0。
UpdateBit 作为判断信号或信号组数据是否被更新的标志,可通过配置项 ComUpdateBitPosition 进行配置 UpdateBit 在该 I-Pdu 所在的位置,用户在调用 Com 提供的发送服务接口函数时将信号对应的 Update Bit 设置为更新状态。
信号对应 UpdateBit 的清除, 根据该信号所在的 I-Pdu 配置项 ComTxIPduClearUpdateBit 配置的清除方式进行清除。
UpdateBit 的清除方式如下:
Confirmation: 在Com模块调用PduR提供的I-Pdu发送服务接口函数PduR_ComTransmit时, 且收到发送完成确认(Com_TxConfirmation) 后进行清除。Transmit: 在Com模块调用PduR提供的I-Pdu发送服务接口函数 PduR_ComTransmit 时, 且发送成功后进行清除。TriggerTransmit:PduR模块调用Com提供的回调函数 Com_TriggerTransmit, 在调用成功后进行清除。
信号的超时处理
Com 发送信号的超时监控, 用于监控信号是否在配置的超时时间内发送完成。 在一个 I-Pdu 内的所有信号如果配置不同的超时监控时间, 则根据该 I-Pdu 内信号配置的最小超时时间进行计算。
I-Pdu 的超时监控在调用 PduR 发送数据服务接口函数时启动, 在接收到发送完成确认后该周期的 I-Pdu 发送超时监控结束, 如果 Com 监控到 I-Pdu 发送超时, 可根据信号配置的 ComTimeoutNotification 回调函数将超时状态通知给 Rte 层。
信号的传输方式
Com 模块可通过 ComTransferProperty 配置项配置发送模式, 详细模式配置如下:
| 发送模块 | PERIODIC(周期) | DIRECT(触发) | MIXED |
|---|---|---|---|
| PENDING | 当用户请求信号的发送时, 不会立即触发对应的 I-Pdu 发送, 只能根据 I-Pdu 配置的发送周期进行周期性发送。 | ||
| TRIGGERED | I-Pdu 进 行 周 期发送 | 在信号有发送请求时, I-Pdu 会触发发送一次。 如果ComTxModeNumberOfRepetitions配置了重复发送次数, 且配置ComTxModeRepetitionPerio 重复发送周期, 则进行周期触发发送 | I-Pdu 进行周期和触发发送 |
| TRIGGERED_WITHOUT_REPETITION | I-Pdu 进 行 周 期发送 | I-Pdu 只会触发发送一次 | I-Pdu 触发发送一次,然后继续按照周期进行发送 |
| TRIGGERED_ON_CHANGE | I-Pdu 进 行 周 期发送 | 当信号数据与上次发送的信号数据的值或长度不同时, 触发发送一次。 如果 ComTxModeNumberOfRepetitions 配置了重复发送次数, 且配置ComTxModeRepetitionPerio 重复发送周期, 则进行周期触发发送 | I-Pdu 进行周期和触发发送 |
| TRIGGERED_ON_CHANGE_WITHOUT_REPETITION | I-Pdu 进 行 周 期发送 | 当信号数据与上次发送的信号值或长度不同时, 触发发送一次 | I-Pdu 进行周期和触发发送 |
Signal 发送时序图
时序图较大,查看时可以在图片上右键选择 "在新标签页中打开图片"

Signal 接收流程
以 NeuSar 为例,梳理 signal 接收流程:
Can驱动模块接收到报文会调用接口CanIf_RxIndication通知CanIf模块- 在通过所有过滤器和验证检查后,成功接收到发送给
CanIf的CAN Rx LPDU,调用CanIf_RxIndication_Process对PDU进行解析 CanIf调用PduR_CanIfRxIndication->PduR_LoRxIndication回调函数,将数据上传到PduR- 调用
PduR_Route_UpRxIndication,表示收到下层通信接口模块的I-PDU。即,当PduR_<Lo>RxIndication被调用时,PDU Router模块将为每个目的上层模块调用<Up>_RxIndication - 调用
Com_RxIndication,通知Com,表示收到下层通信接口模块的I-PDU。 - 调用
Com_RxIndicationProcess处理I-PDU数据 - 调用
Com_RxSignalAnalysis_Process解析信号,调用Com_RxSigRead_Normal获取解析出来的Signal值,再根据数据类型调用Com_RxSigUbInvFilterProcessI8或其他对应函数将接收到的数据存储在Com_RxSignalInfo[sigIdx].sigRTEValue中 - 调用
Com_RxSigNotification_Handle回调函数,通知RTE接收完成,更新 RTE 层的 全局变量 - 通过
RTE接口调用Rte_Read_XXX_XXX函数,内部再调用Com_ReceiveSignal->Com_ReceiveSignal_Process,将存储在RX Buff中Signal值赋给RTE中的全局变量
接收信号的 UpdateBit
如果接收的信号或者信号组配置有对应的 UpdateBit 数据更新位, Com 先解析对应 UpdedateBit 对应的信号数据, 如果 UpdedateBit 为 1, 代表对应的信号数据有更新并进行解析。
Signal 接收时序图

Com_TxPduInfo / Com_RxPduInfo、Com_PduGrpVector 数据来源
配置 COM 模块,需要导入 DBC 文件
一般来说,一个 DBC 文件中含有多个 Node;一个 PDU 相当于一个 message,而 COM 模块由多少个 PDU ,与导入 DBC 时选择的 Main Node 有关。

以 BMS 节点为例:

该 Node Tx Messages 有10个,Rx Messages 有2个,所以
c
extern CONST(COM_TxPduInfo_st, COM_CONFIG_DATA) Com_TxPduInfo[COM_TXPDU_NUM]; // COM_TXPDU_NUM = 10
extern CONST(COM_RxPduInfo_st, COM_CONFIG_DATA) Com_RxPduInfo[COM_RXPDU_NUM]; // COM_RXPDU_NUM = 10
在 Node 下,Tx Messages 共有 29 个 signal,Rx Messages 共有 4 个 signal,所以
c
extern CONST(COM_TxSignalInfo_st, COM_CONFIG_DATA) Com_TxSignalInfo[COM_TXSIG_NUM]; // COM_TXSIG_NUM = 29
extern CONST(COM_RxSignalInfo_st, COM_CONFIG_DATA) Com_RxSignalInfo[COM_RXSIG_NUM]; // COM_RXSIG_NUM = 4
Com_TxSigGrpInfo / Com_RxSigGrpInfo

1. Signal Group 概念
Com 模块控制 I-Pdu 数据的接收和发送, 在系统网络状态激活以后可由 BswM 或 CDD 模块调用 Com 提供的 Com_IpduGroupControl 服务函数控制 I-PduGroup 是否需要激活, 只有在 I-PduGroup 的状态为激活状态时, 对应的 I-Pdu 才能进行数据的接收和发送。
多个 Signal 可以组成一个 Signal Group。一个 Signal Group 中只能包含同一消息中的 Signal 。
从下面可以看出,信号组和普通信号的图标不同

下面问答参考:https://www.elecfans.com/d/1936426.html
- 问题1:什么是Signal Group,为什么要用Signal Group?
- 答:为了支持复杂数据类型的
AUTOSAR概念,AUTOSAR COM提供了信号组的解决方案。AUTOSAR COM模块一致地发送和接收信号组,为复杂数据类型提供必要的一致性。通俗的来讲,Signal Group就是一个IPDU里面的几个Signal的集合,这几个Signal的操作需要保持一致性(也就是如果外部发送方有对这几个数据中一个或多个数据有改动,那么接收方也需要同时更新,比如车道线的一阶参数、二阶参数、三阶参数、常数项是4个不同的Signal,这4个Signal就需要保持一致性,不然到最后仪表上画出来的车道线就会偶发的和实际不一样)。
- 问题2:什么是Shadow buffer,Shadow buffer机制为什么能保证数据的一致性?
- 答:本来
COM模块为每个Rx Signal和Rx Signal都设有一个Signal Buffer的,Signal数据的收发都通过这个Signal来实现。如果Signal Group,COM模块为每个Signal Group又额外设置了一片Signal Group Buffer,这片Buffer就是所谓的Shadow buffer。在发送Signal Group的时候,将Signal Group拷贝到IPDU Buffer的时候是原子操作(也就是拷贝前关闭全局中断,拷贝后打开全局中断,保证拷贝过程不被中断干扰)保证了Signal Group数据的一致性。
- 问题5:RTE在获取一个Signal时,如果这个Signal属于一个Signal Group,那么Signal的值从Signal的buffer获取还是Shadow buffer获取?
- 答:从
Shadow buffer中获取。
2. Com_TxSigGrpInfo / Com_RxSigGrpInfo
COM_TXGRP_NUM、COM_RXGRP_NUM 分别表示发送和接收信号组的个数
c
extern CONST(COM_TxSigGrpInfo_st, COM_CONFIG_DATA) Com_TxSigGrpInfo[COM_TXGRP_NUM + 1U];
extern CONST(COM_RxSigGrpInfo_st, COM_CONFIG_DATA) Com_RxSigGrpInfo[COM_RXGRP_NUM + 1U];
I-PDU、N-PDU、L-PDU关系
更多参考:https://blog.csdn.net/initiallizer/article/details/130040286
-
L-PDU:对应链路层的PDU,一般来说,我们称接口层(Interface,XX_If)为链路层,比如:CanIf、FlexrayIf等。更确切地说是Driver和Interface构成链路层。 -
N-PDU:网络层对应的PDU,一般来说,我们称传输层(Transport,XX_Tp)为网络层,比如:CanTp、FlexrayTp等。 -
I-PDU:交互层(表示层)对应的PDU。
XX_If以上模块的信息交互依赖 I-PDU,XX_If 与 XX_Tp模块的交互依赖 N-PDU。
一般来说,小数据传输时,用XX_If;大数据传输时,用XX_Tp。所以,在诊断的多帧传输时,XX_Tp层会将多个N-PDU缓存,直到一个完整的I-PDU接收完,之后通过 PduR送给DCM ,即:I-PDU = n * N-PDU(n是大于1的正整数)。