AUTOSAR 实战|CANIf 模块深度详解(R23-11 & RTA-CAR)


一、导读 & 文档范围说明

本文围绕 AUTOSAR 23-11 中的 CAN 接口模块(CanIf) 展开,从架构定位、关键概念、数据流到 API 设计进行系统梳理。

整体思路是:

  • 把 CanIf 当成 Com 服务层 ↔ 底层 Can 驱动(CanDrv) 之间的一层“总调度”;
  • 说明它如何承担所有与硬件无关的通信逻辑,让底层 CanDrv 尽可能“只管寄存器”;
  • 梳理 L-PDU/L-SDU、HOH/HRH/HTH、CAN Hardware Unit、Hardware Object 等核心概念;
  • 发送/接收数据流、缓冲策略、软件过滤、控制器模式、PDU 通道模式、BusOff / 唤醒 / 部分网络 等关键行为讲清楚;
  • 最后结合 RTA-CAR 实现给出一套完整的 API & 回调索引清单,方便工程查表。

你可以把这篇文章理解为:
🔧 “看得懂 AUTOSAR 标准 + 能落地到 RTA-CAR 项目配置”的 CanIf 实战笔记。

文档目的 & 参考标准

  • 本文档用于描述 CanIf BSW 模块在 RTA-CAR 下的功能与行为
  • 适用版本:AUTOSAR CP R23-11
  • 标准参考文件:
    《Specification of CAN Interface》AUTOSAR_CP_SWS_CANInterface.pdf

本文在阐述过程中会引用和解释 AUTOSAR 标准中的内容,
但并不替代该标准,建议你在阅读本文时,同时打开标准 PDF 对照细节。


二、CanIf 模块在架构中的位置

架构示意

CAN 接口模块(CAN Interface, CanIf) 的核心职责是:

  • 集中实现与 CAN 硬件无关的任务;
  • 屏蔽硬件细节,对上提供统一的 L-PDU 接口;
  • 让底层驱动 CanDrv 专注访问和控制具体硬件(寄存器、邮箱、RAM 等)。

因此:

  • 上层模块(COM / PduR / CanNm / CanTp / DCM / Xcp …
    👉 只通过 CanIf 与 CAN 网络交互;
  • CanIf 在架构中位于:
    Com 服务层Com 驱动层(CanDrv/CanTrcv) 之间。

三、术语与缩略语(Acronyms & Abbreviations)

为了后面阅读顺畅,这里先把核心术语过一遍:

  • CAN L-Pdu(CAN Protocol Data Unit)
    • 由标识符(CanId)、数据长度、数据(SDU)组成;
    • CAN 驱动可见
  • CAN L-SDU(CAN Service Data Unit)
    • 在 CAN L-PDU 内部承载的“业务数据”;
    • CanIf 上层模块可见(例如 PduR、COM)。
  • SDU / SDT
    • SDU:Service Data Unit(服务数据单元);
    • SDT:SDU Type。
  • HOH(Hardware Object Handle)
    • CAN 硬件对象句柄;
    • 抽象表示一个 CAN 邮箱 / 硬件消息对象。
  • HRH(Hardware Receive Handle)
    • 硬件接收句柄。
  • HTH(Hardware Transmit Handle)
    • 硬件发送句柄。
  • CAN Hardware Unit
    • CAN 硬件单元,可包含:
      • 一个或多个 同类型 CAN 控制器
      • 一个或多个 CAN RAM 区域
    • 可以是片上模块,也可以是外部器件;
    • 对上由一个 CanDrv 驱动实例表示。
  • Hardware Object(HW Object)
    • 位于 CAN RAM 内的一个 PDU 缓冲区
    • 一般对应一个 CAN 邮箱(Message Object/Mailbox)

四、硬件对象句柄 HOH(HRH / HTH)

4.1 概念:HOH = “对 CAN 邮箱的抽象引用”

用于发送(HTH)和接收(HRH)的 HOH,抽象地引用了一个 CAN 邮箱,这个邮箱中包含:

  • CAN ID (CanId)
  • DLC(数据长度)
  • Data(数据本体)

相关特性:

  • HOH 由 CanDrv 配置并提供
  • HOH 作为参数用于调用 CanDrv 的服务(如 Can_Write 等);
  • CanIf 只是 “使用者”
    • 不根据硬件细节去解释 HOH;
    • 不直接访问硬件特定的缓冲区,只通过 CanDrv 提供的 API 访问。

这样,CanIf 对硬件保持完全“脱敏”,实现真正的硬件无关性

一个 CAN 控制器可以在一个邮箱中提供多个发送硬件对象,并逻辑组成一个 Hw Object 池(Multiplexed Hw Objects),然后通过一个 HTH 来寻址。

CanIf 通过两种 HOH 访问 CanDrv:HTH(Tx) 和 HRH(Rx)


4.2 HRH(Hardware Receive Handle)

  • HRH 是用来引用 CAN 控制器邮箱中一个 逻辑接收对象
  • HRH 可以在该接收对象上支持 BasicCAN 或 FullCAN 接收
  • HRH 与一组 Rx L-SDU(CanRxPduId 列表) 静态关联。

配置能力:

  • HRH 可以配置为接收:
    • 单个 CanId(FullCAN);
    • 一组离散 CanId(BasicCAN);
    • 一段 CanId 范围(BasicCAN);
    • 所有 CanId。

当 HRH 采用 BasicCAN 接收方式时:

  • 硬件过滤只是把“某个范围内的 CanId”放入此 HRH;
  • 真实业务上并非这个范围内所有 ID 都属于当前 ECU;
  • 因此 必须在 CanIf 中启用软件过滤,只将配置的 Rx L-PDU 转发给上层。

实战建议:
HRH 设计时尽量让一个 HRH 覆盖 同一上层模块 的一组 PDU,
方便在软件过滤和上层分发时逻辑更加清晰。


4.3 HTH(Hardware Transmit Handle)

  • HTH 是一个句柄,用于引用 CAN 控制器邮箱中一个 逻辑发送对象
  • 可在此对象上使用 BasicCAN 或 FullCAN 方式发送 L-PDU;
  • HTH 与一组 Tx L-PDU(CanTxPduIds) 绑定。

约束与关系:

  • 每个 CanIf Tx L-PDU 在配置时需要静态分配到一个 CanIfBufferCfg
  • 一个 HTH 对应一组 Tx L-PDU;
  • HRH/HTH 及其硬件对象的定义由 CanDrv 决定,CanIf 只通过配置引用。

五、静态 L-PDU(Static L-Pdus)

CanIf 支持对 属于某个 CAN 控制器的所有 L-PDU 的发送和接收进行统一启用 / 去启用。

特性:

  • 每个 L-PDU 都被绑定到一个具体的上层模块(如 COM、PduR、CanTp 等);
  • 这样在以下场景中,CanIf 能够准确找到对应上层模块
    • 接收指示(RxIndication);
    • 发送确认(TxConfirmation);
    • 数据读取(ReadRxPduData / 通知状态)。

六、CAN 硬件单元(CAN Hardware Unit)

CAN 硬件单元的目的,是把“同一种控制器硬件 + 其 RAM”抽象为一个逻辑单元,由一个 CanDrv 负责驱动。

特性与约束:

  • 若系统中存在不同类型的 CAN 控制器:
    • 必须采用不同的 CanDrv 类型;
    • 然后再通过统一的 CanIf API 暴露给上层。
  • CanIf 在 配置阶段 会收集:
    • CAN 控制器的数量;
    • 控制器类型;
    • 每个控制器上的 HOH / HW Object 信息。

这样,上层模块始终通过 HOH + CanIf 来访问 CAN 控制器,而无需理解任何硬件细节。


七、BasicCAN 与 FullCAN

说明:以下讨论适用于传统 CAN/CAN FD。CAN XL 使用描述符 + 队列方式,类似以太网,访问方式不同,不在此节讨论范围。

7.1 两种方式的区别

  • FullCAN
    • 一个硬件对象(邮箱)只支持一个 固定 CanId 的收发;
    • 对每个 ID 有独立的缓存,易管理,但资源占用大。
  • BasicCAN
    • 一个硬件对象可以发送或接收 某个范围内的 CanId
    • 利用硬件过滤器+软件过滤的组合,可在较少邮箱上覆盖更多 ID。

当 HRH 配置为 BasicCAN:

  1. 硬件接收过滤器决定是否把帧放入此 HRH;
  2. HRH 收到的帧可能超出预期业务所需的 L-PDU 列表;
  3. 因此必须 启用软件过滤,再从中筛出属于本 ECU 的 Rx L-PDU。

7.2 配置相关

  • 所有 HOH(HTH / HRH)通过配置容器 CanIfHthCfg / CanIfHrhCfg 进行配置和排序;
  • 每个 HOH 通过 CanIfHthIdSymRef / CanIfHrhIdSymRef 关联到底层硬件过滤器;
  • 对于 BasicCAN 类型的 HRH,可配置 CanIfHrhSoftwareFilter 作为软件 Rx 过滤器;
  • CanIf_RxIndication() 带着某个 HRH 进入 CanIf 时,CanIf 必须对该 HRH 的数据执行软件过滤流程。

八、模块初始化(Initialisation)

8.1 初始化流程

  • EcuM 调用 CanIf_Init 初始化 CanIf:
    • 初始化所有全局变量和数据结构(包括标志位、发送 / 接收缓冲区);
    • 仅初始化 CanIf 模块状态,并 不会把控制器拉起到“工作模式”。
  • CanDrv / CanTrcv 初始化:
    • 由 EcuM 分别调用它们自己的初始化函数完成。

8.2 运行时重新初始化

如果需要在运行中重新初始化整个 CAN 模块:

  1. EcuM 调用 CanSm;
  2. CanSm 调用 CanIf_SetControllerMode
  3. CanIf 将来自 CanSm 的模式切换请求映射到对应的 Can_SetControllerMode 等底层 API;
  4. 底层完成控制器状态转换后,再通过 CanIf_ControllerModeIndication 回调上报。

九、发送路径:Transmit 请求 & 缓冲 & 确认

Transmit 流程

9.1 发送请求:CanIf_Transmit

CanIf_Transmit 是上层模块在 CAN 网络上发送一个 L-PDU 的统一入口。

基本过程:

  1. 上层模块调用 CanIf_Transmit(TxPduId, PduInfoPtr)
  2. CanIf 做以下处理:
    • 检查 CanIf 是否已经初始化;
    • 根据 TxPduId 标识目标 CanDrv;
    • 找到对应的 HTH(发送硬件对象);
    • 调用 Can_WriteCanXL_Write
  3. CanDrv 成功把 L-PDU 写入发送硬件对象时:
    • CanIf_Transmit 返回 E_OK
    • 否则返回 E_NOT_OK(在未启用发送缓冲的情况下)。

规范要求:

  • 若 TxPduId 非法,CanIf 应向 DET 报告 CANIF_E_INVALID_TXPDUID 开发错误。

9.2 发送缓冲(Transmit Buffering)

9.2.1 一般行为

在 CanIf 视角下,“一次发送”的生命周期:

  • 开始:上层调用 CanIf_Transmit()
  • 结束:上层 _TxConfirmation 回调被调用。

在整个生命周期中,待发送的 L-PDU 只允许在 一个地方存储

  • 要么在 CAN 硬件发送对象中
  • 要么在启用发送缓冲时,存储在 CanIf 内部发送缓冲区

对于 Triggered Transmission 场景:

  • CanIf 只缓存“发送请求”,不缓存数据本身
  • 当 HTH 空闲时,通过 CanIf_TriggerTransmit 回调向上层“按需取数”;
  • 整个流程中,同一个 L-PDU 仍然只被缓存一次(在上层或硬件中)。
9.2.2 启用发送缓冲时的行为
  • 如果 CAN 驱动中对应发送缓冲已被占用,Can_Write 返回 CAN_BUSY
    • CanIf 将此 PDU 放入内部发送队列;
    • CanIf_Transmit 仍然返回 E_OK,代表“请求已受理,由 CanIf 后续排队发送”;
    • CanIf_TxConfirmation 通知先前缓冲区已清空时,CanIf 会从内部队列中继续发送排队的 PDU。

上层模块只需调用一次 CanIf_Transmit,无需在 CAN_BUSY 时重复调用。

9.2.3 未启用发送缓冲时
  • 当底层 Can_Write 无法把 PDU 写入缓冲(例如 CAN_BUSY):
    • CanIf_Transmit 直接返回 E_NOT_OK
    • 上层如果需要重发,需要自行控制重试策略。
9.2.4 缓冲区关联与大小
  • 每个 Tx L-PDU 静态关联到某个 CanIfBufferCfg
  • CanIfBufferCfg 与 HTH 一起配置,缓冲区大小通过参数 CanIfBufferSize 决定;
  • 若关闭发送缓冲,可以把 CanIfBufferSize 配为 0 或不配置该容器。

数据长度超限处理:

  • 若 PDU 长度 > 缓冲区大小:
    • CanIf 只缓冲 不超过配置长度的部分,多余部分直接丢弃;
    • 通过 Det_ReportRuntimeError 上报 CANIF_E_DATA_LENGTH_MISMATCH 运行时错误。
9.2.5 缓冲区特性
  • 若某个 PDU 再次进入 CanIf,而缓冲区中已经存在同一个 PDU:
    • 缓冲中的旧数据会被新数据覆盖,即保持“最新数据优先”的设计;
  • 若缓冲区中的 PDU 与当前 PDU 不同:
    • 不会覆盖,CanIf_Transmit 返回 E_NOT_OK
  • 发送缓冲仅在 HTH 配置为 BasicCAN 时可用,FullCAN 不支持发送缓冲。

所有发送缓冲会在 CanIf_Init 调用时完成初始化。


9.3 发送确认(Transmit Confirmation)

Tx 中断确认

Tx 轮询确认

流程摘要:

  1. 当某个 L-PDU 发送完成,CanDrv 调用 CanIf_TxConfirmation(TxPduId)
  2. 若启用 Bus Mirroring(总线镜像)
    • 针对该控制器上每一个被确认发送的帧,CanIf 调用 Mirror_ReportCanFrame
      并传递存储的内容和 CAN ID;
  3. CanIf 根据 TxPduId 找到对应上层模块,调用其 _TxConfirmation,通知发送成功;
  4. 若启用了 CanIfPublicTxConfirmPollingSupport
    • 当某 CAN 控制器处于 CAN_CS_STARTED 状态时,
      CanIf 会为该控制器缓存接收到的 TxConfirmation 信息,供轮询读取之用。

十、接收数据流(Receive Data Flow)

按 AUTOSAR BSW 架构,上层通信栈(COM / CanNm / CanTp / DCM / Xcp 等)负责解析数据内容
上层既不能直接操作 CanDrv 的 Rx 缓冲,也不能访问 CanIf 的 Tx 缓冲。

只有在 CanIfPublicReadRxPduDataApi = TRUE 时,CanIf 才会为 Rx 路径提供内部接收缓冲(Tx 缓冲已在前文介绍)。

10.1 接收指示入口:CanIf_RxIndication

RxIndication 时序 1

RxIndication 时序 2

接收流程:

  1. 新 PDU 到达硬件后,CanDrv 调用 CanIf_RxIndication(Mailbox, PduInfoPtr)
    • MailboxCan_HwType)包含 HRH、控制器信息;
    • PduInfoPtr 包含数据指针和长度。
  2. CanIf 对该 L-PDU 做“接收接受性”评估:
    • 若开启了软件过滤:执行 HRH + CanId 的软件过滤;
    • 若开启了数据长度检查:比较接收长度与配置长度;
    • 若通过检查,则为上层模块准备好 L-SDU 访问。
  3. 若配置了 <User_RxIndication> 回调且 PDU 被接受:
    • CanIf 调用 <User_RxIndication> 通知上层。
  4. 若启用 Bus Mirroring 且指定控制器激活了镜像:
    • 对该控制器上每个接收的帧调用 Mirror_ReportCanFrame

错误报告约束(规范要求):

  • Mailbox->Hoh 非法:报告 CANIF_E_PARAM_HOH
  • Mailbox->CanId 非法:报告 CANIF_E_PARAM_CANID
  • PduInfoPtr->SduLength 非法:报告 CANIF_E_INVALID_DATA_LENGTH
  • PduInfoPtrMailbox 为 NULL:报告 CANIF_E_PARAM_POINTER

注意:CanIf 不知道 CanDrv 是使用临时缓冲还是直接读硬件寄存器,只假设在调用 CanIf_RxIndication 时,接收到的 L-PDU 已经是“标准化格式”。


10.2 读取最近接收数据:CanIf_ReadRxPduData

ReadRxPduData 时序

  • CanIf_ReadRxPduData 是上层模块读取 最近一次接收的某 Rx L-PDU 的通用接口;
  • 上层只能通过此 API 请求数据,不能直接访问 CanDrv
  • 当 CanIf 把 L-PDU 数据写入上层 I-PDU 缓冲区后,此次读取请求即完成。

配置与行为:

  • CanIfPublicReadRxPduDataApi = TRUE 时:
    • 对所有 CanIfRxPduReadData = TRUE 的 Rx L-PDU,CanIf 会为其分配一个接收缓冲;
    • CanIf_RxIndication 接收成功后,数据会被写入该缓冲;
  • 上层可以选择:
    • 只靠 RxIndication 回调;
    • 只用 ReadRxPduData 轮询;
    • 或两种方式并存。

错误报告:

  • CanIfRxSduId 非法(例如未配置为存储在 CanIf 内部):
    • 报告 CANIF_E_INVALID_RXPDUID
  • CanIfRxInfoPtr 为 NULL:
    • 报告 CANIF_E_PARAM_POINTER

10.3 读取 Tx/Rx 通知状态

CanIf 提供两个轮询接口:

  • CanIf_ReadTxNotifStatus(CanIfTxSduId)
    • 返回静态 / 动态 CAN Tx L-PDU 的发送确认状态;
    • CanIfPublicReadTxPduNotifyStatusApi = TRUECanIfTxPduReadNotifyStatus = TRUE
      • 每次调用后,该 L-SDU 的通知状态会被重置。
  • CanIf_ReadRxNotifStatus(CanIfRxSduId)
    • 返回 CAN Rx L-PDU 的接收指示状态;
    • 对于定义为接收“多个 CAN ID(范围接收)”的 RxSduId,不允许使用此 API
    • API 是否可用由 CanIfPublicReadRxPduNotifyStatusApi 决定。

这两个接口都适用于“上层采用轮询方式判断某个 PDU 是否最近有收发事件”的场景。


十一、CAN 控制器模式(Controller Mode)

11.1 一般功能

CanIf 提供一组服务来控制所有由 CanDrv 表示的 CAN 控制器的通信模式:

  • 上层调用 CanIf_SetControllerMode(ControllerId, ControllerMode)
  • CanIf 不判断“模式切换请求是否合理”,只负责将请求转发到 CanDrv
  • 为减少对 CanDrv 的频繁查询调用,可以使用:
    • CanIf_ControllerModeIndication:由驱动在模式变化时回调;
    • CanIf_GetControllerMode:上层从 CanIf 缓存中直接读当前模式。

通常由 CanSm 发起这些模式切换,但并不限制其他模块使用这些 API。

11.2 控制器运行模式行为

  • 若控制器处于 CAN_CS_STOPPED
    • 对该控制器上的任何 PDU 调用 CanIf_Transmit 时,
      CanIf 不会调用 Can_Write/CanXL_Write,直接返回 E_NOT_OK
  • 当控制器进入 CAN_CS_STOPPED
    • 清空所有指向该控制器的发送缓冲区;
    • 调用上层 _TxConfirmation 并传入 E_NOT_OK,通知所有未完成的发送失败;
    • CanIfPublicTxConfirmPollingSupport = TRUE,还会清空 TxConfirmation 缓冲。

BusOff 处理:

  • CanDrv 调用 CanIf_ControllerBusOff(ControllerId)
    • CanIf 调用 CanSm_ControllerBusOff(ControllerId)
      由 CanSm 根据 BusOff 策略对受影响的 CAN 网络进行恢复。

模式变化通知:

  • CanDrv 调用 CanIf_ControllerModeIndication(ControllerId, ControllerMode)
    • CanIf 转调 CanSm_ControllerModeIndication 通知上层。

11.3 模式切换为异步过程

  • CanIf_SetControllerMode 的行为是“发起模式切换请求”;
  • 真正的模式切换完成时间不确定,完成时由 CanIf_ControllerModeIndication 回调通知;
  • 上层也可以通过 CanIf_GetControllerMode 轮询当前模式。

十二、唤醒(WakeUp)

只有当 CAN 控制器和收发器处于通信禁用的休眠模式时,ECU 才支持通过 CAN 总线唤醒。

12.1 唤醒检测(Wakeup Detection)

  • 若启用唤醒支持,上层或集成代码可调用 CanIf_CheckWakeup(WakeupSource)
  • CanIf_CheckWakeup 内部会调用:
    • Can_CheckWakeup(底层 CAN 驱动);
    • CanTrcv_CheckWakeup(收发器驱动);
  • 只要其中任一返回 E_OKCanIf_CheckWakeup 将返回 E_OK
  • 在实际系统中,该函数经常由 EcuM_CheckWakeup 调用,以响应 CAN 唤醒事件。

错误情况:

  • WakeupSource 非法,报 CANIF_E_PARAM_WAKEUPSOURCE

12.2 唤醒验证(Wakeup Validation)

  • 在检测到总线唤醒事件后,如果系统配置了唤醒验证
    • EcuM 会在 WAKEUP VALIDATION 状态中等待验证结果;
    • 此时会调用 CanIf_SetControllerMode / CanIf_SetTrcvMode 来重新打开控制器和收发器;
    • 若启用了 CanIf_CheckValidation API:
      • 上层通过 CanIf_CheckValidation(WakeupSource) 完成对唤醒事件的确认;
      • 需要时通过 EcuM_ValidateWakeupEvent 告知 EcuM 验证通过。

十三、PDU 通道模式控制(Pdu Channel Mode Control)

13.1 PDU 通道组(Pdu Channel Groups)

  • 每个 L-PDU 都被分配给一个物理 CAN 通道(某控制器上的某个网络);
  • 所有连接到同一物理通道的 L-PDU 会被放入一个 PDU 通道组 中统一管理;
  • 一个 L-PDU 只能属于一个通道组。

13.2 PDU 通道模式(Pdu Channel Modes)

通过 CanIf_SetPduMode(ControllerId, PduModeRequest) / CanIf_GetPduMode 控制 PDU 通道模式(前提:控制器模式为 CAN_CS_STARTED)。

可配置模式:

  • CANIF_OFFLINE (0x00)
    • 该通道 Tx / Rx 均禁用 → 无通信模式。
  • CANIF_TX_OFFLINE (0x01)
    • 仅 Tx 禁用,Rx 仍启用。
  • CANIF_TX_OFFLINE_ACTIVE (0x02)(需 CanIfTxOfflineActiveSupport = TRUE
    • 发送路径处于“离线主动”模式:
      • 不实际发帧,但立刻调用上层 TxConfirmation,模拟发送成功;
    • Rx 正常启用。
  • CANIF_ONLINE (0x03)
    • Tx / Rx 均启用 → 正常通信。

与控制器状态联动规则:

  • 若通过 CanIf_SetControllerMode 将控制器设为 CAN_CS_SLEEP
    • 对应 PDU 通道模式会切到 CANIF_OFFLINE
  • CanIf_SetControllerMode 设为 CAN_CS_STOPPED,或通过 CanIf_ControllerBusOff 通知 BusOff:
    • 对应通道会被设置为 CANIF_OFFLINECANIF_TX_OFFLINE(具体组合按配置而定)。
13.2.1 CANIF_OFFLINE 模式
  • 初始化时,所有通道默认处于 CANIF_OFFLINE
  • 在该模式下:
    • 阻止所有 L-PDU 的 CanIf_Transmit 进入 CanDrv(返回 E_NOT_OK);
    • 清空对应通道的发送缓冲;
    • 不调用上层的 RxIndication / TxConfirmation 回调。
13.2.2 CANIF_TX_OFFLINE 模式
  • 当物理通道切换到 CANIF_TX_OFFLINE 时:
    • 阻止所有 Tx 请求(CanIf_Transmit 返回 E_NOT_OK);
    • 清空发送缓冲;
    • 仍然允许调用上层的 RxIndication 回调;
    • 不调用 TxConfirmation。

CANIF_OFFLINECANIF_TX_OFFLINE 模式下,
由于不接受新的 Tx 请求,控制器不会因为新发送请求导致 BusOff,
BusOff 通知在此意义上被“隐式抑制”。

但注意:在切换到离线模式之前,已经在硬件发送队列中的帧仍会被发送,
若这些帧导致 BusOff,CanIf 不会阻止 BusOff 通知。

13.2.3 CANIF_ONLINE 模式
  • 当通道模式切到 CANIF_ONLINE
    • 允许 CanIf_Transmit 把所有关联 PDU 的 Tx 请求向下转发;
    • 允许调用上层的 RxIndication / TxConfirmation。
13.2.4 CANIF_TX_OFFLINE_ACTIVE 模式
  • 当前模式下:
    • 所有 Tx 请求不会真正发帧;
    • 但会立即调用对应上层模块的 TxConfirmation 回调,模拟发送成功;
    • Rx 完全正常。

实战用途:

  • 产线测试 / HIL 仿真场景下,经常需要上层“以为”已经发送,
    但实际上不希望总线上有任何真实报文。

十四、软件接收过滤(Software Receive Filter)

并非所有通过硬件接收过滤进入 BasicCAN HRH 的 L-PDU 都是当前 ECU 关心的。

CanIf 的软件过滤任务,就是把这些“不属于我的帧”过滤掉。

14.1 软件过滤设计思路

  • 配置工具负责管理硬件接收过滤相关信息,核心包括:
    • 各个 L-PDU 关联的硬件对象;
    • 各硬件对象“不被硬件过滤掉”的 CAN ID 范围或列表。

可配置情况:

  • FullCAN 接收
    • 每个 HRH 接收一个固定的 CanId;
  • BasicCAN 接收列表
    • HRH 对应一组可被接受的分散 ID;
  • BasicCAN 接收范围
    • HRH 对应一个或多个 ID 范围:
      • 通过上限/下限:
        • CanIfHrhRangeRxPduUpperCanId
        • CanIfHrhRangeRxPduLowerCanId
      • 或通过基准 ID + 掩码:
        • CanIfHrhRangeBaseID
        • CanIfHrhRangeMask
      • 掩码指示哪些比特需要匹配。

每种范围配置都可以接受 标准 ID 和扩展 ID
软件过滤本身是可选的,可以为某些 HRH 启用,为另一些关闭。

优先级规则:

  • 若某个单独 CanId 与某个范围都匹配:
    • 单独 CanId 优先;
  • 若多个范围都匹配:
    • 范围更小(更精细)的优先。

实战建议:

  • 尽量避免范围互相嵌套,否则容易产生配置错乱;
  • 对于关键诊断 / 安全相关 PDU,优先采用 FullCAN,方便快速定位与调试。

十五、数据长度检查(Data Length Check)

  • 在接收路径中,实际数据长度会与 CanIfRxPduDataLength 对比;
  • 只要 接收的长度 ≥ 配置的长度,且其他过滤条件通过,CanIf 就会接受该 PDU。

配置方式:

  • 全局开关:CanIfPrivateDataLengthCheck
  • 单 PDU 开关:CanIfRxPduDataLengthCheck
    • 若全局关闭,则不能在单 PDU 上强行开启。

若数据长度检查失败:

  • CanIf 拒绝该 PDU;
  • 调用 DET 报告 CANIF_E_INVALID_DATA_LENGTH

若检查通过:

  • 接收的实际长度会传递给上层模块,供其做进一步检查(例如协议级长度校验)。

十六、轮询模式(Polling Mode)

在某些硬件或系统配置中,不使用中断,而采用轮询方式处理 CAN 事件:

  • CanIf / CanDrv 提供 定期调用的通知服务,用于检测:
    • 发送完成事件;
    • 接收事件;
    • 错误状态变化。

特点:

  • 上层只依赖这些通知服务,不关心底层是用中断还是轮询;
  • 若系统中存在多个 CanDrv,需要在集成阶段统一规划各驱动的轮询周期;
  • CanIf 必须支持:
    • 中断触发的通知服务;
    • 任务级轮询调用的通知服务。

当访问某个 CAN 控制器邮箱被阻塞时,后续的发送缓冲策略会被触发,以避免阻塞扩散。


十七、多 CAN 驱动支持(Multiple Can Driver Support)

为同时支持多个 CanDrv,并对上层提供统一的 CanIf 接口,需要:

  • 在下行方向:
    • CanIf 将所有请求(Tx、模式切换、查询等)映射到正确的 CanDrv 实例;
  • 在上行方向:
    • CanIf 根据来源控制器 / HRH / HTH 提供正确的回调给上层,区分不同驱动实例的事件。

是否支持多驱动由参数 CanIfPublicMultipleDrvSupport 控制。


十八、部分网络(Partial Networking, PN)

当配置了 部分网络(PN) 支持:

  • 全局开关:CanIfPublicPnSupport = TRUE
  • 每个 CAN 控制器支持一个 PnTxFilter,覆盖 PDU 通道模式。

PnTxFilter 生效条件:

  • 某个控制器上至少有一个 Tx L-PDU 被配置为 CanIfTxPduPnFilterPdu

行为:

  • 若某控制器的 PnTxFilter 启用
    • 对该控制器的所有 Tx 请求,若对应 Tx L-PDU 不是 CanIfTxPduPnFilterPdu
      • CanIf_Transmit 返回 E_NOT_OK
    • 只有被标记为 CanIfTxPduPnFilterPdu 的 L-PDU 才会继续发送。
  • 在 PnTxFilter 开启时,如果某控制器产生 CanIf_RxIndication
    • 对应控制器的 PnTxFilter 将被 禁用,恢复为 CanIf_SetPduMode 所设定的模式。
  • 若通过 CanIf_SetPduMode 将某控制器设置为 CANIF_TX_OFFLINE,且启用了 PN:
    • 对应控制器的 PnTxFilter 将被 启用

部分网络常用于:

  • 节能唤醒策略;
  • 只允许“唤醒报文”在网络尚未 fully online 时转发等场景。

十九、CanIf API 详解(按功能分组整理)

下面对原始规范中列出的 CanIf API 进行分组化整理
内容尽量保持完整,同时对 WeChat 阅读做一些排版优化。
(参数名、返回值、Service ID、定义头文件等信息均保留,方便查表粘贴。)


19.1 模块初始化与去初始化

1)CanIf_Init
  • 说明:
    • 仅应由 EcuM 调用;
    • 初始化 CanIf 模块自己的状态(变量、缓冲区等);
    • 不会将 CAN 控制器初始化到可工作状态。
  • 原型:
    • void CanIf_Init(const CanIf_ConfigType* ConfigPtr);
  • 参数:
    • ConfigPtr:指向选定配置结构体的指针。
  • 返回值: void
  • 可重入性: No
  • 同步/异步: Synchronous
  • Service ID: 0x01
  • Defined in: CanIf.h
2)CanIf_Deinit
  • 说明:
    • 去初始化 CanIf 模块;
    • 调用者必须保证当前没有正在收发的操作,也没有未完成的发送确认。
  • 原型:
    • void CanIf_Deinit(void);
  • 参数: None
  • 返回值: void
  • 可重入性: No
  • 同步/异步: Synchronous
  • Service ID: 0x02
  • Defined in: CanIf.h

19.2 控制器模式管理 & 错误状态查询

3)CanIf_SetControllerMode
  • 说明:
    • 调用对应 CAN 驱动的 Can_SetControllerMode 服务以改变 CAN 控制器模式;
    • 调用者负责确保没有正在进行的收发操作且没有未完成的 TxConfirmation。
    • ControllerId 非法:
      • 报告 CANIF_E_PARAM_CONTROLLERID
    • ControllerMode 非法(不是 CAN_CS_STARTED / CAN_CS_SLEEP / CAN_CS_STOPPED):
      • 报告 CANIF_E_PARAM_CTRLMODE
  • 原型:
    • Std_ReturnType CanIf_SetControllerMode(uint8 ControllerId, Can_ControllerStateType ControllerMode);
  • 参数:
    • ControllerId:逻辑 ControllerId;
    • ControllerMode:请求的目标模式。
  • 返回值: Std_ReturnType
    • E_OK:请求被接受;
    • E_NOT_OK:请求未被接受。
  • 可重入性: 可重入(同一控制器上不可重入)
  • 同步/异步: Asynchronous
  • Service ID: 0x03
  • Defined in: CanIf.h
4)CanIf_GetControllerMode
  • 说明:
    • 获取当前 CAN 控制器模式;
    • ControllerId 非法:
      • CANIF_E_PARAM_CONTROLLERID
    • ControllerModePtr 为 NULL:
      • CANIF_E_PARAM_POINTER
  • 原型:
    • Std_ReturnType CanIf_GetControllerMode(uint8 ControllerId, Can_ControllerStateType* ControllerModePtr);
  • 参数:
    • In:ControllerId
    • Out:ControllerModePtr
  • 返回值: Std_ReturnType(同上)
  • 可重入性: No
  • 同步/异步: Synchronous
  • Service ID: 0x04
  • Defined in: CanIf.h
5)CanIf_GetControllerErrorState
  • 说明:
    • 调用相应 CAN 驱动服务,获取 CAN 控制器错误状态;
    • ControllerId 非法:CANIF_E_PARAM_CONTROLLERID
    • ErrorStatePtr 为 NULL:CANIF_E_PARAM_POINTER
  • 原型:
    • Std_ReturnType CanIf_GetControllerErrorState(uint8 ControllerId, Can_ErrorStateType* ErrorStatePtr);
  • 参数:
    • In:ControllerId
    • Out:ErrorStatePtr
  • 返回值: Std_ReturnType
  • 可重入性: 对同一 ControllerId 非可重入
  • 同步/异步: Synchronous
  • Service ID: 0x4b
  • Defined in: CanIf.h

19.3 PDU 发送/接收相关 API

6)CanIf_Transmit
  • 说明:
    • 请求发送一个 PDU;
    • CanIf 将调用 Can_Write,使用:
      • swPduHandle = 对应的 CanTxPduId(用于后续 CanIf_TxConfirmation);
      • length = PduInfoPtr->SduLength
      • Id = 该 TxPduId 关联的 CAN ID;
      • Sdu = PduInfoPtr->SduDataPtr
    • TxPduId 非法:报 CANIF_E_INVALID_TXPDUID
  • 原型:
    • Std_ReturnType CanIf_Transmit(PduIdType TxPduId, const PduInfoType* PduInfoPtr);
  • 返回值:
    • E_OK:请求被接受(可能进入底层或排队);
    • E_NOT_OK:请求未被接受。
  • 可重入性:
    • 对不同 PduId 可重入;
    • 对同一 PduId 不可重入。
  • 同步/异步: Synchronous
  • Service ID: 0x49
  • Defined in: CanIf.h
7)CanIf_ReadRxPduData
  • 说明:
    • 提供某个 CanIfRxSduId 最近接收的数据长度和内容;
    • CanIfRxSduId 非法(比如没配置 CanIfRxPduReadData):
      • CANIF_E_INVALID_RXPDUID
    • CanIfRxInfoPtr 为 NULL:
      • CANIF_E_PARAM_POINTER
  • 原型:
    • Std_ReturnType CanIf_ReadRxPduData(PduIdType CanIfRxSduId, PduInfoType* CanIfRxInfoPtr);
  • 返回值:
    • E_OK:有可用数据;
    • E_NOT_OK:无有效数据。
  • 可重入性: Non Reentrant
  • 同步/异步: Synchronous
  • Service ID: 0x06
  • Defined in: CanIf.h
8)CanIf_ReadTxNotifStatus
  • 说明:
    • 返回某个静态 / 动态 Tx L-PDU 的当前发送确认状态;
    • 若启用 CanIfPublicReadTxPduNotifyStatusApi 且该 L-PDU 的 CanIfTxPduReadNotifyStatus = TRUE
      • 调用后会重置通知状态。
  • 原型:
    • CanIf_NotifStatusType CanIf_ReadTxNotifStatus(PduIdType CanIfTxSduId);
  • 可重入性: Non Reentrant
  • 同步/异步: Synchronous
  • Service ID: 0x07
  • Defined in: CanIf.h
9)CanIf_ReadRxNotifStatus
  • 说明:
    • 返回某个 Rx L-PDU 的接收指示状态;
    • 对于“接收多个 CAN ID(范围接收)”的 RxSduId,不允许调用此 API;
    • CanIfPublicReadRxPduNotifyStatusApi 全局控制是否可用。
  • 原型:
    • CanIf_NotifStatusType CanIf_ReadRxNotifStatus(PduIdType CanIfRxSduId);
  • 可重入性: Non Reentrant
  • 同步/异步: Synchronous
  • Service ID: 0x08
  • Defined in: CanIf.h

19.4 PDU 模式管理 API

10)CanIf_SetPduMode
  • 说明:
    • 设置某 ControllerId 关联 PDU 通道的模式;
    • ControllerId 非法:CANIF_E_PARAM_CONTROLLERID
    • PduModeRequest 非法:CANIF_E_PARAM_PDU_MODE
  • 原型:
    • Std_ReturnType CanIf_SetPduMode(uint8 ControllerId, CanIf_PduModeType PduModeRequest);
  • 返回值:
    • E_OK / E_NOT_OK
  • 可重入性: Non Reentrant
  • 同步/异步: Synchronous
  • Service ID: 0x09
  • Defined in: CanIf.h
11)CanIf_GetPduMode
  • 说明:
    • 获取某 ControllerId 对应 PDU 通道的当前模式;
    • ControllerId 非法:CANIF_E_PARAM_CONTROLLERID
    • PduModePtr 为 NULL:CANIF_E_PARAM_POINTER
  • 原型:
    • Std_ReturnType CanIf_GetPduMode(uint8 ControllerId, CanIf_PduModeType* PduModePtr);
  • 返回值: E_OK / E_NOT_OK
  • 可重入性: 可重入(同一通道不可重入)
  • 同步/异步: Synchronous
  • Service ID: 0x0A
  • Defined in: CanIf.h

19.5 动态 Tx ID & 收发器模式相关

12)CanIf_SetDynamicTxId
  • 说明:
    • 重新配置某 CAN L-PDU 的 CAN ID;
    • CanIfTxSduId 非法:CANIF_E_INVALID_TXPDUID
    • CanId 非法:CANIF_E_PARAM_CANID
    • CanIfPublicSetDynamicTxIdApi 配置是否可用。
  • 原型:
    • void CanIf_SetDynamicTxId(PduIdType CanIfTxSduId, Can_IdType CanId);
  • 返回值: void
  • 可重入性: Non Reentrant
  • 同步/异步: Synchronous
  • Service ID: 0x0C
  • Defined in: CanIf.h
13)CanIf_SetTrcvMode
  • 说明:
    • 调用收发器驱动,对 TransceiverId 修改模式;
    • TransceiverId 非法:CANIF_E_PARAM_TRCV
    • TransceiverMode 非法(不是 CANTRCV_TRCVMODE_STANDBY / CANTRCV_TRCVMODE_SLEEP / CANTRCV_TRCVMODE_NORMAL):
      • CANIF_E_PARAM_TRCVMODE
    • 模式切换顺序由规范限制:
      • NORMAL → STANDBY → SLEEP;
      • 但 CanIf 不做顺序检查。
    • 是否可用由预编译参数控制。
  • 原型:
    • Std_ReturnType CanIf_SetTrcvMode(uint8 TransceiverId, CanTrcv_TrcvModeType TransceiverMode);
  • 返回值: E_OK / E_NOT_OK
  • 可重入性: Non Reentrant
  • 同步/异步: Asynchronous
  • Service ID: 0x0D
  • Defined in: CanIf.h
14)CanIf_GetTrcvMode
  • 说明:
    • 调用 CanTrcv_GetOpMode 获取当前收发器模式;
    • TransceiverId 非法:CANIF_E_PARAM_TRCV
    • TransceiverModePtr 为 NULL:CANIF_E_PARAM_POINTER
  • 原型:
    • Std_ReturnType CanIf_GetTrcvMode(uint8 TransceiverId, CanTrcv_TrcvModeType* TransceiverModePtr);
  • 返回值: E_OK / E_NOT_OK
  • 可重入性: Non Reentrant
  • 同步/异步: Synchronous
  • Service ID: 0x0E
  • Defined in: CanIf.h
15)CanIf_GetTrcvWakeupReason
  • 说明:
    • 调用收发器驱动获取唤醒原因;
    • TransceiverId 非法:CANIF_E_PARAM_TRCV
    • TrcvWuReasonPtr 为 NULL:CANIF_E_PARAM_POINTER
  • 原型:
    • Std_ReturnType CanIf_GetTrcvWakeupReason(uint8 TransceiverId, CanTrcv_TrcvWakeupReasonType* TrcvWuReasonPtr);
  • 返回值: E_OK / E_NOT_OK
  • 可重入性: Non Reentrant
  • 同步/异步: Synchronous
  • Service ID: 0x0F
  • Defined in: CanIf.h
16)CanIf_SetTrcvWakeupMode
  • 说明:
    • 调用 CanTrcv_SetTrcvWakeupMode 设置唤醒通知模式;
    • TransceiverId 非法:CANIF_E_PARAM_TRCV
    • TrcvWakeupMode 非法:CANIF_E_PARAM_TRCVWAKEUPMODE
  • 原型:
    • Std_ReturnType CanIf_SetTrcvWakeupMode(uint8 TransceiverId, CanTrcv_TrcvWakeupModeType TrcvWakeupMode);
  • 返回值: E_OK / E_NOT_OK
  • 可重入性: Non Reentrant
  • 同步/异步: Synchronous
  • Service ID: 0x10
  • Defined in: CanIf.h

19.6 唤醒检查 & 验证

17)CanIf_CheckWakeup
  • 说明:
    • 检查底层 CAN 驱动或收发器驱动是否报告唤醒事件;
    • 通常由集成代码调用(例如 EcuM);
    • WakeupSource 非法:CANIF_E_PARAM_WAKEUPSOURCE
  • 原型:
    • Std_ReturnType CanIf_CheckWakeup(EcuM_WakeupSourceType WakeupSource);
  • 返回值: E_OK / E_NOT_OK
  • 可重入性: Non Reentrant
  • 同步/异步: Asynchronous
  • Service ID: 0x11
  • Defined in: CanIf.h
18)CanIf_CheckValidation
  • 说明:
    • 用于验证先前的唤醒事件;
    • WakeupSource 非法:CANIF_E_PARAM_WAKEUPSOURCE
    • 若系统不需要 Wakeup 验证,可通过 CanIfPublicWakeupCheckValidSupport = FALSE 省略该 API。
  • 原型:
    • Std_ReturnType CanIf_CheckValidation(EcuM_WakeupSourceType WakeupSource);
  • 返回值: E_OK / E_NOT_OK
  • 可重入性: Reentrant
  • 同步/异步: Synchronous
  • Service ID: 0x12
  • Defined in: CanIf.h

19.7 Tx 确认状态轮询 & Bus Mirroring & 时间戳

19)CanIf_GetTxConfirmationState
  • 说明:
    • 报告自上次控制器启动以来,是否发生过任何 TxConfirmation;
    • ControllerId 非法:CANIF_E_PARAM_CONTROLLERID
    • 若 BusOff 恢复策略不需要 Tx 确认状态,可通过关闭 CanIfPublicTxConfirmPollingSupport 省略该 API。
  • 原型:
    • CanIf_NotifStatusType CanIf_GetTxConfirmationState(uint8 ControllerId);
  • 返回值: CanIf_NotifStatusType
  • 可重入性: 可重入(同一控制器不可重入)
  • 同步/异步: Synchronous
  • Service ID: 0x19
  • Defined in: CanIf.h
20)CanIf_ClearTrcvWufFlag
  • 说明:
    • 请求清除指定收发器的 WUF 标志;
    • TransceiverId 非法:CANIF_E_PARAM_TRCV
    • 是否支持由 CanIfPublicPnSupport + CanIfPublicTrcvPnEnable 控制。
  • 原型:
    • Std_ReturnType CanIf_ClearTrcvWufFlag(uint8 TransceiverId);
  • 返回值: E_OK / E_NOT_OK
  • 可重入性: 对不同收发器可重入
  • 同步/异步: Asynchronous
  • Service ID: 0x1e
  • Defined in: CanIf.h
21)CanIf_CheckTrcvWakeFlag
  • 说明:
    • 请求检查指定收发器的唤醒标志;
    • TransceiverId 非法:CANIF_E_PARAM_TRCV
    • 支持条件同上。
  • 原型:
    • Std_ReturnType CanIf_CheckTrcvWakeFlag(uint8 TransceiverId);
  • 返回值: E_OK / E_NOT_OK
  • 可重入性: 对不同收发器可重入
  • 同步/异步: Asynchronous
  • Service ID: 0x1f
  • Defined in: CanIf.h
22)CanIf_SetBaudrate
  • 说明:
    • 设置 CAN 控制器波特率配置;
    • 根据需求,控制器可能需要复位;
    • ControllerId 非法:CANIF_E_PARAM_CONTROLLERID
    • 是否支持由 CanIfSetBaudrateApi 决定。
  • 原型:
    • Std_ReturnType CanIf_SetBaudrate(uint8 ControllerId, uint16 BaudRateConfigID);
  • 返回值: E_OK / E_NOT_OK
  • 可重入性: 对不同 ControllerId 可重入,对同一 ControllerId 不可重入
  • 同步/异步: Synchronous
  • Service ID: 0x27
  • Defined in: CanIf.h
23)CanIf_GetControllerRxErrorCounter / CanIf_GetControllerTxErrorCounter
  • 说明:
    • 调用对应 CanDrv API 返回 Rx/Tx 错误计数器;
    • ControllerId 非法:CANIF_E_PARAM_CONTROLLERID
    • 若指针参数为 NULL:CANIF_E_PARAM_POINTER
    • 某些控制器不支持相应计数器时将返回 E_NOT_OK
  • 原型:
    • Std_ReturnType CanIf_GetControllerRxErrorCounter(uint8 ControllerId, uint8* RxErrorCounterPtr);
    • Std_ReturnType CanIf_GetControllerTxErrorCounter(uint8 ControllerId, uint8* RxErrorCounterPtr /* 实为 TxErrorCounterPtr */);
  • 返回值: E_OK / E_NOT_OK
  • 可重入性: 对同一 ControllerId 非可重入
  • 同步/异步: Synchronous
  • Service ID:
    • Rx:0x4d;Tx:0x4e
  • Defined in: CanIf.h
24)CanIf_EnableBusMirroring
  • 说明:
    • 为指定控制器启用 / 禁用总线镜像;
    • ControllerId 非法:CANIF_E_PARAM_CONTROLLERID
  • 原型:
    • Std_ReturnType CanIf_EnableBusMirroring(uint8 ControllerId, boolean MirroringActive);
  • 参数:
    • MirroringActive = TRUE:接收/发送的每一帧都调用 Mirror_ReportCanFrame
    • FALSE:不做镜像报告。
  • 返回值: E_OK / E_NOT_OK
  • 可重入性: Reentrant
  • 同步/异步: Synchronous
  • Service ID: 0x4c
  • Defined in: CanIf.h
25)时间戳相关:CanIf_GetCurrentTime / CanIf_EnableEgressTimeStamp / CanIf_GetEgressTimeStamp / CanIf_GetIngressTimeStamp
  • 说明(共性):
    • 都需要底层驱动支持时间戳;
    • 开关由 CanIfGlobalTimeSupport 控制;
    • 若 Controller/TxPduId 或指针参数非法,分别报告对应 DET 错误(CANIF_E_PARAM_CONTROLLERID / CANIF_E_PARAM_LPDU / CANIF_E_PARAM_POINTER)。
  • 原型:
    • Std_ReturnType CanIf_GetCurrentTime(uint8 Controller, Can_TimeStampType* timeStampPtr);
    • void CanIf_EnableEgressTimeStamp(PduIdType TxPduId);
    • Std_ReturnType CanIf_GetEgressTimeStamp(PduIdType TxPduId, Can_TimeStampType* timeStampPtr);
    • Std_ReturnType CanIf_GetIngressTimeStamp(PduIdType TxPduId, Can_TimeStampType* timeStampPtr);
  • 特性:
    • GetCurrentTime:读当前控制器硬件时间;
    • EnableEgressTimeStamp:在指定 L-PDU 上启用发送时间戳;
    • GetEgressTimeStamp:读发送时间戳;
    • GetIngressTimeStamp:在 RxIndication 上下文中读取接收时间戳。

19.8 回调(Callbacks)与错误上报

这里只列出关键回调及要点,保持与原文一致:

  • CanIf_TriggerTransmit
    • 上层检查可用数据是否适配缓冲区;
    • 若适配,将数据拷贝到 PduInfoPtr->SduDataPtr 并更新 SduLength
    • 不适配则返回 E_NOT_OK 且不修改 PduInfoPtr
    • 仅当 CanIfTriggerTransmitSupport = TRUE 时提供。
  • CanIf_TxConfirmation
    • 通知某 CAN Tx L-PDU 已成功发送;
    • TxPduId 非法:CANIF_E_PARAM_LPDU
  • CanIf_RxIndication / CanIf_XLRxIndication
    • 指示接收到 CAN / CAN XL Rx L-PDU;
    • 检查 Hoh、CanId、长度、指针合法性,并报告对应 DET 错误。
  • CanIf_ControllerBusOff
    • 通知某控制器 BusOff。
  • CanIf_ConfirmPnAvailability / CanIf_ConfirmCtrlPnAvailability
    • 通知某收发器 / 控制器正在运行于 PN 通信模式。
  • CanIf_ClearTrcvWufFlagIndication / CanIf_CheckTrcvWakeFlagIndication
    • 对应 CanIf_ClearTrcvWufFlag / CanIf_CheckTrcvWakeFlag API 的完成指示。
  • CanIf_ControllerModeIndication / CanIf_TrcvModeIndication
    • 通知控制器 / 收发器模式切换完成。
  • CanIf_ControllerErrorStatePassive / CanIf_ErrorNotification
    • 使用 Rx/Tx 错误计数器或 Can_ErrorType 推导总线错误源并上报安全事件(通过 IdsM_SetSecurityEventWithContextData)。

19.9 与其他模块接口(Interface)

按照原文给出的分类:

  • 必选接口 / API:
    • Can_GetControllerErrorState
    • Can_GetControllerRxErrorCounter
    • Can_GetControllerTxErrorCounter
    • Can_SetControllerMode
    • Can_Write
    • Det_ReportRuntimeError
  • 可选接口:
    • Can_CheckWakeup
    • Can_SetBaudrate
    • 各种 CanNm_* / CanTp_* / J1939Nm_* / J1939Tp_*
    • CanSM_*(BusOff、模式指示、PN 可用性等)
    • CanTrcv_*(唤醒标志、唤醒模式、OpMode 等)
    • CanTSyn_*
    • CanXL_Write
    • Det_ReportError
    • EcuM_ValidateWakeupEvent
    • IdsM_SetSecurityEventWithContextData
    • Mirror_ReportCanFrame
    • PduR_CanIfRxIndication / PduR_CanIfTxConfirmation
    • Xcp_CanIfRxIndication / Xcp_CanIfTxConfirmation

二十、总结回顾(与开头摘要呼应)

本文围绕 AUTOSAR 23-11CanIf 模块,从架构定位、关键概念、数据流到 API 设计进行了系统梳理:

  • 说明了 CanIf 作为 Com 服务层与底层 CanDrv 的抽象接口
    集中实现与硬件无关的通信逻辑,让 CanDrv 专注具体控制器操作;
  • 详细解释了 L-PDU/L-SDU、HOH/HRH/HTH、CAN Hardware Unit、Hardware Object 等术语,
    以及 HRH/HTH 如何作为对 CAN 邮箱的抽象引用,将上层 PDU 与底层硬件对象解耦;
  • 介绍了 CanIf 对 静态 L-PDU 的管理,BasicCAN 与 FullCAN 的区别,
    以及在硬件过滤与软件过滤中的协同作用,
    通过 CanIfHthCfg/CanIfHrhCfg、软件过滤器和 ID 范围 / 掩码机制,将接收的 CanId 映射到正确的 Rx L-PDU;
  • 从初始化流程入手,说明了 EcuM、CanSm、CanDrv、CanTrcv 与 CanIf 的协同关系,
    并重点讲解了 发送与接收数据流
    • CanIf_Transmit 的处理步骤与发送缓冲策略;
    • 触发发送(TriggerTransmit)机制;
    • TxConfirmation 的中断/轮询两种调用路径;
    • RxIndication 后的软件过滤、数据长度检查、接收缓存以及 CanIf_ReadRxPduData/ReadTx/RxNotifStatus 等读取接口;
  • 系统讲解了 控制器模式PDU 通道模式CANIF_OFFLINE/TX_OFFLINE/TX_OFFLINE_ACTIVE/ONLINE) 的联动机制,
    BusOff 处理、轮询模式、多 CanDrv 支持、部分网络(PN)下的 PnTxFilter 行为,以及唤醒检测与唤醒验证流程;
  • 最后,以 接口列表 的形式对 CanIf 提供的各类服务函数和回调
    (控制器/收发器模式控制、波特率切换、错误计数与错误上报、时间戳与总线镜像等)进行了归纳,
    为你理解 RTA-CAR 中 CanIf 的实现、配置要点和与上下游模块的交互关系提供了一份尽可能完整的参考文档。
Logo

免费领 150 小时云算力,进群参与显卡、AI PC 幸运抽奖

更多推荐