> 文章列表 > 读懂AUTOSAR:CanIf模块“发送缓冲”详解

读懂AUTOSAR:CanIf模块“发送缓冲”详解

读懂AUTOSAR:CanIf模块“发送缓冲”详解

目录

发送缓冲的一般行为

在发送LPDU缓冲中报错LPDU

L-PDU缓冲的清除

发送 L-PDU 缓冲区的数据完整性


发送缓冲的一般行为

在CanIf范围内,发送过程始于调用CanIf_Transmit()函数,结束于调用上层模块的回调服务函数<User_TxConfirmation>()。在发送过程中,CanIf、CanDrv和CAN邮箱共同将要发送的L-PDU仅存储一次在一个单一位置。根据发送方法,这些位置可以是:

• CAN硬件发送对象或

• 如果启用发送缓冲,则为CanIf内的发送L-PDU缓冲区。

对于触发式传输,CanIf只需要存储给定L-PDU的传输请求,而不是其数据。当HTH(硬件发送缓冲区)再次空闲时,数据将通过触发传输函数及时获取。请求传输的单个Tx L-PDU永远不应被重复存储。这种行为对应于CAN网络上定期通信的通常方式。

如果启用传输缓冲(Tx Bufferring),当CanDrv在传输请求时拒绝一个Tx L-PDU时,CanIf将把它存储在CanIf Transmit L-PDU Buffer(CanIfBufferCfg)中。基本上,用于缓冲Tx L-PDU的CanIf的整个缓冲区由一个或多个CanIfBufferCfg(请参见CanIfBufferCfg)组成。每个CanIfBufferCfg分配给一个或多个专用的CanIfBufferHthRef(请参见CanIfBufferHthRef),并且可以配置为缓冲一个或多个Tx L-PDU。但是,如上所述,在CanIfBufferCfg的总数中只能缓冲Tx L-PDU的一个实例。

CanIf在L-PDU传输期间的行为取决于是否在相应的Tx L-PDU的配置设置中启用了传输缓冲。如果禁用传输缓冲,并且传输请求到CanDrv失败(CAN控制器邮箱正在使用,BasicCAN),则L-PDU不会被复制到CAN控制器的邮箱中,CanIf_Transmit()将返回值E_NOT_OK。如果启用了传输缓冲,并且传输请求到CanDrv失败,根据CanIfTxBuffer配置,L-PDU可以存储在CanIfTxBuffer中。在这种情况下,API CanIf_Transmit()将返回值E_OK,即使无法执行传输。在这种情况下,CanIf通过CanIf_TxConfirmation()回调处理L-PDU的未完成传输,上层不必重试传输请求。

可用的传输CanIf Tx L-PDU缓冲区的数量可以完全独立于在CAN网络描述文件中为此ECU定义的已用Transmit L-PDU的数量进行配置。

根据[SWS_CANIF_00835],Tx L-PDU通过CanIfBufferCfg配置容器(请参见CanIfBufferCfg)引用HTH。如果不需要传输缓冲,这也是有效的。在这种情况下,必须将CanIfBufferCfg的缓冲区大小(请参见CanIfBufferSize)设置为0。然后,CanIfBufferCfg配置容器仅用于引用HTH。

在发送LPDU缓冲中报错LPDU

CanIf是一种软件模块,用于在Controller Area Network(CAN)通信系统中传输CAN L-PDU(Protocol Data Unit)。当CanDrv在调用Can_Write()函数时返回CAN_BUSY时,CanIf会尝试将新的Transmit L-PDU或其Transmit请求仅存储在Transmit L-PDU缓冲区中(参见[SWS_CANIF_00381])。如果启用了参数CanIfPublicTxBuffering(参见CanIfPublicTxBuffering),则CanIf应支持对基本CAN传输的CAN L-PDU进行缓冲,该功能在[SWS_CANIF_00063]中定义。对于动态Transmit L-PDU,CanId也必须存储在CanIfTxBuffer中,详见[SWS_CANIF_00849]。

当Can_Write()函数调用返回CAN_BUSY时,CanDrv拒绝了所请求的L-PDU传输,因为在传输请求(Tx request)时没有可用的硬件对象。如果被拒绝的数据长度超过了配置的大小,则CanIf应将已配置的数据量缓冲起来,丢弃其余部分,并向DET的Det_ReportError服务报告开发错误代码CANIF_E_DATA_LENGTH_MISMATCH,详见[SWS_CANIF_00895]。

如果Can_Write()函数用于触发传输的PDU配置返回CAN_BUSY,并且启用了传输缓冲(参见[SWS_CANIF_00063]),则CanIf应检查是否可以在CanIfTxBuffer中缓冲所请求通过Can_Write()函数传输的Transmit请求,详见[SWS_CANIF_00881]。当CanIf检查是否可以缓冲CanIf Tx L-PDU或Transmit请求时(参见[SWS_CANIF_00381]、[SWS_CANIF_00881]),只有当CanIf Tx L-PDU被分配到配置了大于零的缓冲区大小的CanIfBufferCfg(参见CanIfBufferCfg)时,这才是可能的,详见[SWS_CANIF_00835]。

任何CanIfTxBuffer的缓冲区大小只有在启用传输缓冲时才可配置大于零。此外,如果CanIfTxBuffer未分配到FullCAN HTH(参见CanIfBufferSize),则单个CanIfTxBuffer的缓冲区大小只能配置为大于零。

[SWS_CANIF_00836] 当已分配的CanIfTxBuffer的缓冲区大小大于零(参见[SWS_CANIF_00835]),如果CanIfTxL-PDU或传输请求尚未在CanIfTxBuffer中缓冲,则CanIf应将CanIf Tx L-PDU或传输请求缓冲在分配的CanIfTxBuffer的空闲缓冲区元素中。

[SWS_CANIF_00068] 当已分配的CanIfTxBuffer的缓冲区大小大于零(参见[SWS_CANIF_00835])且Can_Write()返回CAN_BUSY时,如果CanIfTxL-PDU已经在CanIfTxBuffer中缓冲,则CanIf应在分配的CanIfTxBuffer中直接覆盖已经发送的CanIfTxL-PDU。

注意:对于已存储的传输请求[参见[SWS_CANIF_00068]],由于数据将直接被CanDrv捕获(使用CanIf_TriggerTransmit()),因此无需进行任何操作。因此,最新的数据将自动发送。

如果要保持不同L-PDU的各种传输请求的顺序,则上层模块的传输请求必须与先前的传输确认通知连接。这意味着仅当CanIf通知了前一个L-PDU的传输确认时,上层模块才会请求传输后续L-PDU。

注意:传输请求的顺序还可以根据配置的硬件传输对象的数量而有所不同。

[SWS_CANIF_00837] 如果缓冲区大小大于零,并且所有缓冲区元素都已被占用,并且使用新的L-PDU调用CanIf_Transmit()(没有相同L-PDU的其他实例已存储在缓冲区中),则不应存储新的L-PDU或其传输请求,并且CanIf_Transmit()应返回E_NOT_OK。

L-PDU缓冲的清除

“Transmit L-PDU缓冲区的清除”是指CAN总线接口模块(CanIf)在传输确认期间(参见[SWS_CANIF_00007]),应评估是否存在存储在CanIfTxBuffers中的未决CanIf Tx L-PDUs或传输请求,这些缓冲区被分配给新的空闲硬件发送对象(参见[SWS_CANIF_00466])。

如果按照[SWS_CANIF_00386],CanIfTxBuffers中存在未决的CanIf Tx L-PDUs或传输请求,则CanIf应按照最高优先级(参见[SWS_CANIF_00070])为该未决的CanIf Tx L-PDU或传输请求(分配给新的硬件发送对象)调用Can_Write()。

[SWS_CANIF_00070]规定CanIf应按照优先级顺序(参见[12])传输存储在发送L-PDU缓冲区中的L-PDUs或传输请求,且CanIf不应区分L-PDUs和传输请求。当CanIf针对存储在CanIfTxBuffer中的按优先级排序的L-PDUs和传输请求调用函数Can_Write(),并且Can_Write()的返回值是E_OK时,CanIf应立即将该L-PDU或传输请求从发送L-PDU缓冲区中删除,直到传输确认返回。

[SWS_CANIF_00183]规定的行为简化了存储在发送L-PDU缓冲区中的新传输L-PDU的选择。

发送 L-PDU 缓冲区的数据完整性

[SWS_CANIF_00033]规定CanIf应保护传输L-PDU缓冲区免受并发访问,以用于准备发送的L-PDU和请求。这可以通过在BSW调度器中定义的独占区域来实现。可以配置这些独占区域,使其在进入时禁用所有中断。BSW调度器模块的相应服务是SchM_Enter_CanIf()和SchM_Exit_CanIf()。

该规范旨在防止对传输L-PDU缓冲区的并发访问,特别是在存储新的L-PDU或删除已传输的L-PDU时。由于无法避免这种抢占式的访问,因此需要使用独占区域和调度器服务来确保数据完整性。