文章目录
- 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
更新RTE
Signal
的全局变量,并调用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
函数回调通知CanIf
CanIf
通过调用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的正整数)。