文章目录
在AUTOSAR Classic Platform (CP) 中, Com模块 (Communication模块)是负责实现 应用层与通信栈之间的接口 。它主要管理与通信相关的数据传输,并确保应用层数据通过CAN、LIN、FlexRay、以太网等通信总线正确传输。
Com模块的主要功能
-
信号的处理和映射:
- Com模块负责将应用层的信号映射到PDU(Protocol Data Unit,协议数据单元),并将接收到的PDU解析回应用层的信号。
- 信号可以是标量、数组,甚至是复合数据类型,Com模块对这些不同类型的数据提供相应的打包和解包功能。
-
信号组:
- Com模块还支持信号组的概念,可以将多个信号组合在一起作为一个单元来进行处理,以提高效率。
-
数据的传输和接收:
- Com模块通过调用底层的PDU Router(PduR模块),将打包好的PDU发送给下层的通信接口模块(如CAN、LIN、FlexRay等)。
- 接收到的PDU也通过PDU Router传递给Com模块进行解包。
-
定期传输:
- Com模块能够为周期性数据传输提供支持,确保在预定义的时间间隔内发送和接收消息。
-
事件驱动传输:
- 支持基于事件触发的数据传输,当某个信号的值发生变化时,会触发数据传输。
-
数据更新通知:
- 当通信总线接收到新的数据时,Com模块会通知应用层数据已更新。
-
缓冲管理:
- 对于需要发送和接收的数据,Com模块提供缓冲区以便进行数据存储和管理。
-
信号网关
也就是针对单个信号进行处理和转发。通过信号网关,系统可以实现信号从一个网络到另一个网络的透明转发,而不必对整个PDU(Protocol Data Unit)进行处理。信号网关可以将不同总线之间的信号转发。例如,将来自CAN总线的信号转发到LIN总线或Ethernet网络。
Com模块的配置
AUTOSAR CP中的Com模块通常通过AUTOSAR工具链进行配置。典型的配置包括:
- 定义应用层信号及其属性(如数据类型、大小、发送周期等)。
- 映射应用层信号到PDU。
- 定义通信接口和相关参数,如信号的刷新率、延迟时间等。
与其他模块的交互
- PduR模块:Com模块通过PduR模块与具体的总线通信模块(如CanIf、LinIf)交互,完成PDU的发送与接收。
- 应用层模块:Com模块直接与RTE (Run-Time Environment)进行交互,应用层通过RTE调用Com模块的API来发送和接收信号。
应用举例
应用层通过Com模块接收CAN报文
在AUTOSAR CP中,Com模块接收CAN信号的过程大致可以分为以下几个步骤:CAN Driver接收CAN报文,通过CAN Interface(CanIf)、PDU Router(PduR)模块传递给Com模块,最终由Com模块解包,将信号传递给应用层。
注意:报文与信号的不同,一条CAN报文可能包含很多个信号,当Com模块接收到CAN报文,会将报文解析出对应的信号传递给应用层。比如ID为123的CAN报文组成 报文(Message) 与 不同颜色的Signals
假设:
- 我们要接收一个CAN报文,其中包含三个信号:
Signal_A
(1字节)Signal_B
(2字节)Signal_C
(4字节)
- 报文通过CAN总线接收后,Com模块需要从PDU中提取出这三个信号并传递给应用层。
- CAN Driver接收CAN报文
CAN控制器接收到CAN总线上的报文,并通过CAN Driver 模块处理。CAN Driver会将收到的CAN报文放入缓冲区,并通知上层CAN Interface(CanIf)。
void CanIf_RxIndication(Can_HwType* Mailbox, PduInfoType* PduInfoPtr)
在此函数中,PduInfoPtr
包含了接收到的CAN报文数据。CanIf_RxIndication
负责将收到的CAN报文传递给PDU Router(PduR)。
- CanIf模块传递PDU
CanIf模块会根据接收的CAN报文的ID,查找与其对应的PDU ID,并将数据传递给**PDU Router(PduR)**模块。
PduR_CanIfRxIndication(PduId, &PduInfo);
PduId
:与接收到的CAN报文相关联的PDU ID。PduInfo
:包含接收到的CAN报文数据(即PDU)。
- PDU Router传递给Com模块
PduR模块 根据PDU ID,找到相应的接收路径,将PDU传递给Com模块进行解包处理。
Com_RxIndication(PduId, &PduInfo);
PduId
:对应于此报文的PDU ID。PduInfo
:包含接收到的PDU数据。
- Com模块解包PDU并更新信号
Com模块在接收到PDU后,按照预先配置好的信号映射,将PDU中的数据解包为各个信号。
-
Signal_A
从PDU的第0字节解包。 -
Signal_B
从PDU的第1和第2字节解包。 -
Signal_C
从PDU的第3到第6字节解包。void Com_RxIndication(PduIdType PduId, const PduInfoType* PduInfoPtr) {
// 从PDU中提取信号值
uint8_t Signal_A = PduInfoPtr->SduDataPtr[0]; // 提取第0字节
uint16_t Signal_B = (PduInfoPtr->SduDataPtr[1] << 8) | PduInfoPtr->SduDataPtr[2]; // 提取第1、2字节
uint32_t Signal_C = (PduInfoPtr->SduDataPtr[3] << 24) |
(PduInfoPtr->SduDataPtr[4] << 16) |
(PduInfoPtr->SduDataPtr[5] << 8) |
PduInfoPtr->SduDataPtr[6]; // 提取第3-6字节// 更新信号值到信号缓存 Com_UpdateSignal(Signal_A_ID, Signal_A); Com_UpdateSignal(Signal_B_ID, Signal_B); Com_UpdateSignal(Signal_C_ID, Signal_C);
}
在这个过程中,Com模块会将解包后的信号值存入内部缓存,并根据配置,可能会向应用层触发数据更新通知。
- Com模块通知应用层
如果信号配置了通知回调函数,当信号值更新时,Com模块会调用该回调函数通知应用层数据已更新,应用层可以随时获取最新的信号值。
void Com_UpdateSignal(SignalIdType SignalId, SignalType SignalValue) {
// 更新信号值
Com_SignalBuffer[SignalId] = SignalValue;
// 如果信号配置了更新通知回调,则调用回调函数通知应用层
if (Com_SignalCallback[SignalId] != NULL) {
Com_SignalCallback[SignalId](SignalValue);
}
}
应用层通过Com模块的API可以随时获取最新的信号值,例如:
Com_ReceiveSignal(Signal_A_ID, &value_A);
Com_ReceiveSignal(Signal_B_ID, &value_B);
Com_ReceiveSignal(Signal_C_ID, &value_C);
应用层通过Com模块发送CAN报文
在AUTOSAR CP中,Com模块负责将应用层的信号打包成CAN报文,并通过底层的通信模块(如CAN Interface,CAN Driver)将报文发送到CAN总线。整个过程涉及信号处理、PDU打包、路由传输等步骤。
假设:
- CAN报文包含三个信号:
Signal_A
(1个字节)Signal_B
(2个字节)Signal_C
(4个字节)
- 这些信号映射到一个PDU,最终封装成CAN报文,并通过CAN总线发送出去。
- 信号定义与配置
在AUTOSAR的配置工具中,工程师需要预先定义好CAN报文和其包含的信号:
Signal_A
:1 byteSignal_B
:2 bytesSignal_C
:4 bytes 这些信号将映射到一个CAN PDU中。
信号映射到PDU的配置:
Signal_A
从第0字节开始,占用第0字节。Signal_B
从第1字节开始,占用第1和第2字节。Signal_C
从第3字节开始,占用第3到第6字节。
- 应用层更新信号
在应用层,RTE(Run-Time Environment)调用Com模块的API来更新信号值。假设应用层代码更新了三个信号的值:
Com_SendSignal(Signal_A_ID, &value_A);
Com_SendSignal(Signal_B_ID, &value_B);
Com_SendSignal(Signal_C_ID, &value_C);
在调用这些API时,Com模块将会缓存这些信号的值,等待触发条件(如周期性或事件驱动)发送报文。
- 信号打包成PDU
当满足发送条件时(例如:周期性发送,或某个信号更新导致触发发送),Com模块会将这些信号按照配置打包成一个PDU。
打包过程:
Signal_A
的值被放置在PDU的第0字节。Signal_B
的值被放置在PDU的第1、2字节。Signal_C
的值被放置在PDU的第3-6字节。
PDU最终被组装成如下形式:
PDU = [Signal_A | Signal_B | Signal_C]
PDU = [0xAA | 0xBBBB | 0xCCCCCCCC] // 假设Signal_A=0xAA, Signal_B=0xBBBB, Signal_C=0xCCCCCCCC
- PDU发送到PDU Router(PduR)
Com模块完成PDU的打包后,通过PduR模块 进行路由,将打包好的PDU传递给下层的CAN Interface模块(CanIf)。
PduR_ComTransmit(PduId, &PduInfo);
PduInfo
包含了PDU的数据和长度。
- PDU传递给CAN Interface模块(CanIf)
PduR模块将PDU传递给CanIf模块,CanIf模块根据PDU ID将PDU映射到具体的CAN报文(CAN Message)。
CanIf_Transmit(CanTxPduId, &CanPduInfo);
在这一步,CanIf模块会根据配置的CAN ID和PDU内容构建CAN报文,将数据放入CAN控制器的发送缓冲区。
CAN Driver发送CAN报文
CanIf模块调用底层CAN Driver模块,CAN Driver模块负责通过CAN控制器将报文发送到CAN总线。
Can_Write(CanTxPduId, &CanPduInfo);
最终,CAN报文如下:
CAN Message = [CAN ID | Data]
Data = [0xAA | 0xBBBB | 0xCCCCCCCC] // 打包好的信号数据
该报文通过CAN总线发送给其他节点。
通过这种模块化的方式,AUTOSAR CP的Com模块确保了应用层数据可以按照预定义的方式正确发送到CAN总线,并解耦了应用层和底层通信协议的复杂性。
对于应用层来讲,无需关注底层如何实现,只需要将对应的信号传递给Com,对于底层来讲,无需关注应用层如何解析,只需要提供原始的CAN报文(Message),极大提高了开发效率!