1、概述
根据AUTOSAR BSW架构,接收到的数据将在上层通信模块,即AUTOSAR COM、CanNm、CanTp和DCM中进行评估和处理。这意味着,上层模块既不能使用CanDrv的缓冲区,也不能访问CanIf的缓冲区。只有当CanIfPublicReadRxPduDataApi设置为TRUE时,CanIf才会在接收路径中提供内部缓冲。解决了发送缓冲问题,并考虑动态I-PDU。
如果接收到CanDrv L-PDU,则调用CanIf的CanIf_RxIndication ()。对L-PDU特定数据的访问由以下参数组织。
- 硬件接收句柄(HRH)
- 接收CAN标识符(CanId)
- 接收数据长度
- 参考已收到的L-PDU
函数原型图1:注意可以对此函数进行更改。
2、具体描述接收
接收到的L-PDU依赖于硬件,并分配给通信系统的最低层CanDrv。HRH是CanDrv和使用L-PDU的上层模块之间的链接。HRH标识CAN硬件接收句柄,接收新的CAN L-PDU。
在CanDrv调用CanIf_RxIndication(),指示接收到的L-PDU后,CanIf将按照接收指示进行处理。CanIf无法识别CanDrv是使用临时缓冲还是直接访问硬件。它期望在调用CanIf_RxIndication()时得到标准化的L-PDU数据。
CAN硬件接收句柄被锁定,直到复制到临时或上层模块缓冲区的过程结束。硬件对象将在CanIf的CanIf_RxIndication()返回后立即释放,以避免数据丢失。
CanDrv、CanIf和属于接收到L-PDU的上层模块访问相同的临时缓冲区,该临时缓冲区可以位于CAN控制器的硬件接收对象中,也可以位于CanDrv中的临时缓冲区中。
接收的信号流图2:
调用CanIf_RxIndication()引用新接收到的L-PDU的参数,如果调用了函数CanIf_RxIndication(),CanIf将对CAN L-PDU进行评估接收,并准备L-SDU供上层通信层访问。CanIf使用()通知上层模块这个异步事件,如果配置成功,并且检测到L-PDU进行处理。
如果总线镜像是全局启用的,并且通过调用CAN控制器的CanIf_EnableBusMirroring()激活,那么CanIf应该为该控制器上用CanIf_RxIndication()来表示的每一帧接收调用Mirror_ReportCanFrame()。
如果调用函数CanIf_RxIndication(),CanIf会按照指定的方式处理接收到的L-PDU。如果软件过滤拒绝接收到的L-PDU,CanIf会结束对canif_rxindicator()调用的接收指示。
如果CanIf在软件过滤过程中接受通过CanIf_RxIndication()接收到的L-PDU, CanIf随后会处理数据长度检查。如果CanIf在数据长度检查期间使用CanIf_RxIndication()接收L-PDU, CanIf将根据配置的数据长度的字节数复制到静态接收缓冲区。
如果为接收的L-SDU配置了元数据,CanIf将PDU有效负载复制到静态接收缓冲区,并将CANID复制到类型为CAN_ID_32的MetaDataItem。
在数据长度检查期间,如果CanIf接受通过CanIf_RxIndication()接收到的L-PDU,CanIf会识别是否配置了目标上层模块(CanIfRxPduUserRxIndicationUL,CanIfRxPduUserRxIndicationName),并为接收到的L-SDU提供接收指示服务。
如果目标上层模块被配置为提供接收指示服务,CanIf称之为配置接收指示回调服务CanIfRxPduUserRxIndicationName,提供所需的参数上层通知回调函数的参数CanIf_RxIndication ()。
CanIf在调用CanIf_RxIndication()时执行以下步骤:
- 软件过滤(只有BasicCAN)
- 数据长度检查
- 缓冲接收L-SDU
- 调用上层接收指示回调服务
读取接收到的数据APICanIf_ReadRxPduData()是上层模块读取CANL-SDU最近从CAN网络接收到的公共接口。上层模块只通过CanIf服务发起接收请求,而不直接访问CanDrv。发起的接收请求成功完成,CanIf将接收到的L-SDU写入上层模块I-PDU缓冲区。
函数CanIf_ReadRxPduData()使得在不依赖接收事件的情况下读取数据成为可能。在配置时启用它,不一定为相同L-SDU配置接收指示服务。如果需要,可以启用接收指示服务。
通过这种方式的类型机制获得L-SDU,可以选择由参数CanIfRxPduUserRxIndicationUL和CanIfRxPduReadData,在配置时根据上层模块的需求,相应的接收L-SDU。
如果配置参数CanIfPublicReadRxPduDataApi设置为TRUE,则CanIf将接收到的L-SDU(在此情况下CanIfRxPduReadData是启用的)存储到接收到的L-SDU缓冲区。这意味着,如果配置参数CanIfRxPduReadData设置为TRUE,CanIf必须为这个接收L-SDU分配接收L-SDU缓冲区。
在调用CanIf_RxIndication()并通过软件过滤和数据长度检查后,CanIf将接收到的L-SDU存储在这个接收到的L-SDU缓冲区中。在调用CanIf_ReadRxPduData()指定的接收L-SDU缓冲区时,CanIf应避免抢占接收L-SDU缓冲区的访问事件
3、控制器模式服务
CanIf提供用于控制由CanDrv支持的CAN控制器通信模式的服务。这意味着所有CAN控制器都由相应的API服务来控制,以请求和读取当前控制器模式。
可以通过调用CanIf_SetControllerMode()服务,来根据上层的请求更改CAN控制器状态。请求通过CanIf经过CanDrv API传递到指定的CAN控制器。在CAN网络上对所有CAN控制器的一致性管理是CanSm的任务。通过这种方式,CanSm负责将CAN网络的所有CAN控制器按顺序设置为睡眠模式或唤醒。
CanIf通过调用函数CanIf_SetControllerMode()或CanIf_ControllerBusOff()接受每个状态转换请求。CanIf不决定CAN控制器请求的模式转换是否有效。CanIf仅通过获取当前模式和执行请求的模式转换来与CanDrv交互。
该网络相关状态机在CanSm中实现。CanIf只存储请求的模式并执行请求的转换。
为了避免频繁请求CanDrv,可以对每个控制器存储CanIf_ControllerModeIndication()和Can_GetControllerMode()所指示的最后状态。需要注意的是,不仅CanSm能够请求CAN控制器模式的改变。根据CanSm请求的操作模式,CanIf转发请求CanDrvs。
如果ControllerId引用的控制器模式处于CAN_CS_STOPPED状态,并且如果CanIf_Transmit()调用中的PduIdType参数被分配给该CAN控制器,那么CanIf_Transmit()调用不会导致Can_Write()调用,而是返回E_NOT_OK。如果ControllerId引用的控制器模式进入CAN_CS_STOPPED状态,CanIf会清除分配给CAN控制器相应的CanIf传输缓冲区。
如果ControllerId引用的控制器模式进入CAN_CS_STOPPED状态,那么CanIf通过调用(id, E_NOT_OK)为分配给CAN控制器的每个未完成的TxConfirmation,通知相应的上层模块传输失败。如果启用了CanIfPublicTxConfirmPollingSupport,那么CanIf还会清除关于TxConfirmation的信息。
这确保了对于每个PDU,都会调用一个正的或负的。当调用回调CanIf_ControllerBusOff(ControllerId)时,CanIf调用CanSm或CDD的CanSM_ControllerBusOff(ControllerId)。