☰
【AUTOSAR】 Classic Platform LdCom(LargeDataCOM)--从入门到放弃
2026/9/26 4:05:51 网站建设 项目流程

【AUTOSAR】 Classic Platform LdCom(LargeDataCOM)–从入门到放弃

这份材料以AUTOSAR_CP_SWS_LargeDataCOM.pdf为核心,另外参考了 System Template(AUTOSAR_CP_TPS_SystemTemplate.pdf)、RTE(AUTOSAR_CP_SWS_RTE.pdf)、PduR 以及 TP 相关规范。适合刚接触 AUTOSAR 通信栈、需要配置或测试大数据传输的人。


目录

  1. LdCom 是干什么的
  2. 在通信栈里的位置
  3. 两种 API 形态:IF-API 与 TP-API
  4. 配置上的硬性约束
  5. 和 RTE 与 Transformer 的配合
  6. 配置容器与关键参数
  7. 排障:三个常见问题
  8. 小结

1. LdCom 是干什么的

Standard COM 擅长的是小信号:1 bit 的开关、16 位的车速、几十字节的信号组。它的那套机制——信号打包解包、字节序转换、信号过滤、影子缓冲区、Update Bit——都是为这类数据设计的。

问题出在数据变大之后。雷达点云、相机图像块、刷写数据块、SOME/IP 或 ComXf 序列化之后的字节流,动辄几百字节到几 KB。这些数据如果还走 Standard COM,每帧都要按信号逐个提取、拷贝、再做一遍转换和过滤,CPU 和 RAM 的消耗都不划算——而且对一个"连续字节块"来说,这些处理本身就没有意义。

LdCom(Large Data COM)就是为这种场景准备的。它的思路很直接:把 Standard COM 里那些昂贵的处理全砍掉,只留下 ID 映射和透传。

它的主要特点:

  • 不申请本地缓冲区。数据在上层和底层之间靠指针和回调直接传递,LdCom 自己不占 RAM。
  • 不做任何数据处理。没有过滤、没有字节序转换,也没有超时监控,数据原样透传。
  • 1 个 PDU 只放 1 个信号,不做多信号打包。
  • 只支持事件触发发送,没有周期性发送。

两者的分工看图更清楚:

小信号走 Standard COM,大块字节数组和 Transformer 的输出走 LdCom,最后都汇到 PduR。


2. 在通信栈里的位置

LdCom 和 Standard COM 处于同一层(服务层),都夹在 RTE 和 PduR 之间。

往上看,LdCom 的用户有三类:

  • RTE:应用 SWC 的数据经 RTE 交给 LdCom。
  • Transformer 链:启用了 SOME/IP Serializer 之类的转换器时,序列化后的字节数组由 RTE 直接交给 LdCom。
  • SwCluC_LdComProxy:多核、多软件集群架构下,跨集群的代理。

往下看,只有 PduR。LdCom 把上层的 SignalId 换算成 PduId,调 PduR 的接口把数据送出去;反过来 PduR 收到数据后回调 LdCom。

这个换算本身很简单,但它是理解 LdCom 全部接口的钥匙:

上层调用时传的是 SignalId(也就是配置里的LdComHandleId),PduR 收到的却是 PduId。中间的查表由 LdCom 在内部完成,上下两层都看不到对方的编号体系。

2.1 多核与 ECUC 分区

多核 ECU 上,LdCom 需要按 ECUC 分区的规范来配,AUTOSAR 提供了两种模式:

  • 分区特定(Partition Specific):LdCom 为每个分区提供独立的回调实例,上层模块(比如 RTE)在各自分区的上下文里响应回调,不涉及跨核同步。
  • 分区无关(Partition Agnostic):所有分区共用一套回调函数。这就要求回调必须是可重入的,能被不同核同时安全调用。

选哪种,取决于上层模块都跑在哪些分区,以及回调里有没有共享状态。共用一套回调看着省事,但只要回调里存了一点静态数据,就会变成跨核竞争。


3. 两种 API 形态:IF-API 与 TP-API

LdCom 有两种工作模式,由配置项LdComApiType决定,生成出来的接口完全不同。

对比项IF-API(LDCOM_IF)TP-API(LDCOM_TP)
适用场景数据能装进一帧,不需要分片数据超过一帧,需要 CAN-TP、SOME/IP-TP 之类分片
数据传递方式一次调用带指针拷完(PduInfoType*)流式回调,TP 层分段来取 / 送数据
缓冲区要不要锁调用返回就结束,不用锁整个传输期间必须锁住,直到TpTxConfirmation/TpRxIndication
涉及的下层接口PduR_LdComTransmit、LdCom_RxIndicationPduR_LdComTransmit、LdCom_CopyTxData、LdCom_CopyRxData等

3.1 IF-API 的发送流程

四步就完事,而且都在同一次调用里跑完:

  1. RTE 调LdCom_Transmit(SignalId, PduInfoPtr)。
  2. LdCom 把 SignalId 换成 PduId,调PduR_LdComTransmit。
  3. 驱动把帧发出去,E_OK逐层返回。
  4. 硬件发完之后,PduR 回调LdCom_TxConfirmation,LdCom 再触发<LdComUser_LdComCbkTxConfirmation>通知 RTE。

第 3 步和第 4 步是分开的,这点容易混淆:E_OK只代表"已受理",不代表"已经发到总线上"。真正发完要等TxConfirmation。

3.2 TP-API 的发送流程

  1. RTE 调LdCom_Transmit,随后锁定发送缓冲区。锁住的原因很直接:后面 TP 层是异步来取数据的,中间应用要是把数据改了,发出去的包就前后不一致。
  2. LdCom 把请求转给 PduR,TP 层开始分片。
  3. 每要一段数据,TP 层调LdCom_CopyTxData,LdCom 转成<LdComUser_LdComCbkCopyTxData>找 RTE 要。RTE 把指定长度的片段写进 TP 给的缓冲区。
  4. 第 3 步反复执行,直到所有分片发完。
  5. TP 层回调LdCom_TpTxConfirmation,LdCom 通知 RTE,解锁发送缓冲区。

第 3 步的写法是关键:是"TP 层来拉",不是"LdCom 主动推"。正因为如此,LdCom 不需要任何中间缓冲区,数据直接从 RTE 的内存流到 TP 的帧里。

3.3 TP-API 的接收流程

  1. TP 层收到首帧(First Frame),调LdCom_StartOfReception,把总长度TpSduLength和一个bufferSizePtr传进来。
  2. LdCom 转给 RTE 的<LdComUser_LdComCbkStartOfReception>。RTE 在这里锁定接收缓冲区,并把缓冲区能装多少通过bufferSizePtr写回去。
  3. 每个分片到达,TP 层调LdCom_CopyRxData;LdCom 转成<LdComUser_LdComCbkCopyRxData>,分片数据直接写进 RTE 的接收缓冲区。
  4. 所有分片到齐,TP 层回调LdCom_TpRxIndication。LdCom 通知 RTE,解锁缓冲区,并按配置触发DataReceivedEvent。

如果第 2 步里 RTE 发现缓冲区装不下TpSduLength,应该直接返回BUFREQ_E_OVFL拒收,而不是硬写。这是防内存越界最关键的一步。

3.4 TriggerTransmit:让底层决定何时取数据

FlexRay、LIN 这类轮询式总线上,什么时候发不由上层决定,而是控制器来问。这时走的是另一条路:

  1. 下层调LdCom_TriggerTransmit(TxPduId, PduInfoPtr)。
  2. LdCom 转给<LdComUser_LdComCbkTriggerTransmit>。
  3. RTE 把准备好的数据写进PduInfoPtr->SduDataPtr,并把实际长度回填。

4. 配置上的硬性约束

不是随便一个信号都能配成 LdCom,System Template 对此有硬性规定(规则 ID 见TPS_SYST_02016等)。

数据类型:处理的ISignal必须满足下面三条之一。

  • 类型是UINT8_N(定长字节数组)
  • 类型是UINT8_DYN(变长字节数组)
  • 关联了 DataTransformation,也就是 Transformer 链的输出

打包与位置:

  • packingByteOrder必须是Opaque。LdCom 不做字节序转换,数据只能当不透明字节流处理。
  • startPosition必须是 0,不支持在 PDU 里偏移插入信号。
  • 一个ISignalIPdu里有且仅有 1 个ISignal。1:1,不允许把多个小信号打包进同一个 LdCom PDU。

传输属性与定时:

  • transferProperty只能是triggered或triggeredWithoutRepetition。不支持pending,也不支持自动重复发送。
  • 不允许定义更新位(updateIndicationBitPosition)。
  • 定时只能用事件控制(EventControlledTiming),且numberOfRepetitions必须为 0。
  • 不允许配置minimumDelay(最小间隔定时器)。

这些约束背后的逻辑是一致的:LdCom 不维护本地缓冲区,也不做状态管理。所以配置里任何"需要记住上一次状态"的能力,它都用不了。


5. 和 RTE 与 Transformer 的配合

5.1 缓冲区锁与 RTE_E_COM_BUSY

TP-API 模式下传输跨越多个通信周期,必须防止中途被改。

  • 发送方向:RTE 调完LdCom_Transmit就锁住发送缓冲区。如果TpTxConfirmation还没回来,SWC 又去Rte_Write同一个信号,RTE 会返回RTE_E_COM_BUSY,拒绝覆盖。
  • 接收方向:RTE 在StartOfReception环节锁住接收缓冲区。TpRxIndication结束之前,SWC 去Rte_Read同样会拿到RTE_E_COM_BUSY。

这个返回值不是故障,而是正常的状态反馈。应用层该做的是先判断再决定,而不是当成错误来处理。

5.2 复杂结构体怎么走 Transformer

SWC 之间要传结构体时,通常配一条 Transformer 链:

  1. SWC 调Rte_Write_<p>_<a>(&structData)。
  2. RTE 调 Transformer(比如SomeIpXf_Serialize)把结构体序列化成字节数组,存进 RTE 申请的临时缓冲区。
  3. RTE 把这个字节数组当成UINT8_N/UINT8_DYN信号,调LdCom_Transmit交给 LdCom。
  4. 接收端反过来:LdCom 收到字节数组,RTE 调SomeIpXf_Deserialize还原成结构体,交给接收方 SWC。

Transformer 是 RTE 层的事情,LdCom 只看到一坨字节。这也解释了为什么它的配置约束里要求Opaque——它确实不关心里面装的是什么。


6. 配置容器与关键参数

LdCom 的行为完全由 ECUC 配置决定,容器层次如下:

容器 / 参数类型与取值说明
LdCom模块根容器
└LdComGeneral全局设置
└LdComDevErrorDetectBoolean开发错误检测开关
└LdComVersionInfoApiBoolean是否生成版本查询接口
└LdComConfig配置主体
└LdComIPdu0…*每个 PDU 一项
├LdComHandleIdInteger 0…65535RTE / PduR 调用时用的句柄 ID,ECU 范围内唯一
├LdComApiTypeLDCOM_IF/LDCOM_TP决定生成 IF 接口还是 TP 接口
├LdComIPduDirectionLDCOM_SEND/LDCOM_RECEIVE收发方向
└LdComPduRefReference指向 PduR 里的 IPdu
└LdComUserModule0…*上层用户模块,一般是 RTE
└LdComUserModuleCnf用户模块配置
├LdComUserIPdu→LdComUserCbkHandleIdInteger用户侧回调句柄
└LdComUserCallback回调定义
├LdComUserCallbackNameString回调函数名
└LdComUserCallbackType枚举回调类型,见下

LdComUserCallbackType的常见取值有LDCOM_RX_INDICATION、LDCOM_TP_COPY_RX_DATA、LDCOM_TP_COPY_TX_DATA、LDCOM_TP_RX_INDICATION等,和前面讲过的各个回调一一对应。

这里最关键的一项是LdComApiType:配成LDCOM_TP才会生成LdCom_CopyTxData/LdCom_CopyRxData这些接口,配成LDCOM_IF就只生成LdCom_Transmit/LdCom_RxIndication。


7. 排障:三个常见问题

7.1 调用发送返回RTE_E_COM_BUSY

原因:这个信号配的是 TP-API。上一次发送还没结束(TP 层还在分片,RTE 发送缓冲区处于锁定状态),应用又调了一次发送。

怎么查:

  1. 看底层 TP 的传输速率和总线负载,确认有没有发生卡包或超时。
  2. 检查LdCom_TpTxConfirmation是否正常触发、是否完成了解锁。
  3. 应用侧加一层发送状态判断,别在 BUSY 期间硬写。

7.2 配置工具报 “Invalid Signal Mapping”

原因:把一个普通标量信号(比如uint16)映射给了 LdCom,或者往同一个 LdCom IPdu 里塞了多个信号。

怎么查:

  1. 信号类型是不是UINT8_N或UINT8_DYN。
  2. startPosition是不是 0,packingByteOrder是不是Opaque。
  3. 这个 IPdu 里是不是只有 1 个信号。

7.3 大数据传输时数据错乱或内存越界

原因:没按流式拷贝的规矩来,或者 RTE 给的接收缓冲区比发送方的总长度小。

怎么查:

  1. 在LdCom_StartOfReception里核对TpSduLength和bufferSizePtr的大小关系。
  2. 装不下就返回BUFREQ_E_OVFL,别硬写。

8. 小结

LdCom 做的事情其实很少:不缓冲、不转换、不过滤,只把上层的 SignalId 换成 PduId,然后把数据透传下去。省下来的这些开销,换来的正是大数据传输需要的效率。

判断一个信号该用哪个模块,看数据形态就够了:

  • 要按位打包、要做字节序转换、要周期性发送、要监控超时 → Standard COM。
  • 是一整块连续字节、要分片、由事件触发 → LdCom。

两者不是替代关系。同一个 ECU 上经常同时存在,各管一摊。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询