CanTrcv_30_Sbc收发器模式与总线唤醒机制

2026-09-211

CanTrcv_30_Sbc 是面向 SBC 集成式 CAN 收发器的 AUTOSAR CAN Transceiver Driver 实现。它把上层模块看到的接口稳定在 CanTrcv 语义上,而把实际硬件访问交给 SBC Driver 完成。这样一来,CanIf、CanSM、EcuM 不需要关心收发器位于独立芯片、SBC 外设还是某个受 SBC 同步保护的内部组件,只需要按 CanTrcv API 管理工作模式、唤醒检测和局部网络能力。

本文围绕三个集成主线展开:NORMALSTANDBY 的模式控制,总线唤醒的上报路径,以及 SBC 访问、ICU 唤醒和跨分区调用带来的约束。

模块定位

CanTrcv_30_Sbc 位于 CAN Interface 与 SBC Driver 之间。它不是直接通过 SPI 或 DIO 操作收发器,而是调用 SBC Driver 提供的收发器访问服务,由 SBC Driver 负责底层硬件访问与同步。

原文图示 1

项目
AUTOSAR release Release 4
配置变体 Pre-compile、Post-build selectable
Vendor ID CANTRCV_30_SBC_VENDOR_ID = 30
Module ID CANTRCV_30_SBC_MODULE_ID = 70
Instance ID CANTRCV_30_SBC_INSTANCE_ID
支持能力 说明
收发器初始化 对已配置通道执行初始化,并把通道置为初始工作模式
SBC 控制 通过 SBC Driver API 控制收发器硬件
总线唤醒检测 可检测并上报 CAN 总线唤醒事件
模式读写 支持读取与设置收发器工作模式
不支持能力 集成含义
通过 SPI 直接控制 CAN 收发器 SPI 访问由 SBC Driver 或其硬件抽象侧承担
通过 DIO 直接控制 CAN 收发器 CanTrcv 不直接驱动收发器控制引脚
Self diagnostics 诊断语义需要结合 SBC 能力与系统诊断设计

这个定位决定了模块的关键边界:CanTrcv 负责 AUTOSAR CanTrcv 行为,SBC Driver 负责硬件访问,ICU 在特定唤醒方案中负责输入捕获,EcuM 负责系统唤醒事件的生命周期。

初始化与模式控制

上电或复位后,先调用 CanTrcv_30_Sbc_InitMemory() 初始化模块内部变量,再调用 CanTrcv_30_Sbc_Init() 初始化配置的收发器通道。Init() 完成后,每个已配置通道被切到 NORMAL。如果初始化前已经存在未上报的唤醒事件,模块会保存该事件,并在初始化路径中通过 EcuM_SetWakeupEvent() 通知 EcuM。

阶段 调用 结果
RAM 初始化 CanTrcv_30_Sbc_InitMemory() 初始化内部状态,必须早于其他功能
配置初始化 CanTrcv_30_Sbc_Init(ConfigPtr) 初始化所有配置通道
初始模式 Init() 内部动作 通道进入 CANTRCV_TRCVMODE_NORMAL
初始化前唤醒 内部保存后上报 通过 EcuM_SetWakeupEvent() 通知系统

原文图示 2

CanTrcv_30_Sbc_SetOpMode() 只支持 NORMALSTANDBY,不支持 SLEEP。如果请求的模式与当前模式一致,函数返回 E_OK,但不会触发实际硬件切换。模式切换完成且函数返回 E_OK 时,模块在 SetOpMode() 的调用上下文中调用 CanIf_30_Sbc_TrcvModeIndication()

模式相关服务 关键行为
CanTrcv_30_Sbc_SetOpMode(CanTrcvIndex, OpMode) 请求通道进入 NORMALSTANDBY
CanTrcv_30_Sbc_GetOpMode(CanTrcvIndex, OpMode) 返回当前检测到的工作模式
CanIf_30_Sbc_TrcvModeIndication() 模式变化完成后通知 CanIf
CANTRCV_TRCVMODE_NORMAL 正常通信模式
CANTRCV_TRCVMODE_STANDBY 待机并保留唤醒能力的模式

GetOpMode() 有一个容易被忽略的边界:如果上层刚发起模式切换,而模式变化还没有完成,在模式指示回调发生前读取到的模式可能仍不是最终模式。上层状态机应以模式指示和后续读取共同确认状态,而不是把一次立即读取当成唯一依据。

总线唤醒路径

总线唤醒围绕 CheckWakeup()GetBusWuReason()SetWakeupMode()CheckWakeFlag()MainFunction() 组织。典型路径是:硬件检测到总线活动,CanTrcv 检查收发器状态与唤醒标志,随后通过 EcuM 上报唤醒源。

原文图示 3

唤醒服务 用法 主要边界
CanTrcv_30_Sbc_CheckWakeup() 检查指定通道是否存在总线唤醒 检测到后调用 EcuM_SetWakeupEvent()
CanTrcv_30_Sbc_GetBusWuReason() 读取最近一次唤醒原因 多个原因同时存在时只返回最后检测到的原因
CanTrcv_30_Sbc_SetWakeupMode() 开启、关闭或清除唤醒上报 唤醒功能未启用时返回 E_NOT_OK
CanTrcv_30_Sbc_CheckWakeFlag() 请求检查 wake flag 状态 完成后调用 CanIf_30_Sbc_CheckTrcvWakeFlagIndication()
CanTrcv_30_Sbc_MainFunction() 周期轮询硬件唤醒状态 仅在 Wakeup support 设为 polling 时有效

CheckWakeup() 的返回值不能单独作为系统唤醒成立的判据。对于 ECU 唤醒状态机而言,有效动作是对应唤醒源被 EcuM_SetWakeupEvent() 上报。返回 E_OK 表示检测请求在当前条件下识别到总线唤醒,但系统层仍应以 EcuM 唤醒事件为准。

唤醒原因 含义 返回特性
CANTRCV_WU_INTERNALLY 内部原因唤醒 可作为最近唤醒原因返回
CANTRCV_WU_BY_BUS CAN 总线活动触发唤醒 典型总线唤醒原因
CANTRCV_WU_RESET 复位相关唤醒 可作为最近唤醒原因返回
CANTRCV_WU_ERROR 未检测到有效原因 函数返回 E_NOT_OK
CANTRCV_WU_NOT_SUPPORTED 当前通道不支持该唤醒原因 函数返回 E_NOT_OK
唤醒模式 行为
CANTRCV_WUMODE_ENABLE 开启唤醒事件上报
CANTRCV_WUMODE_DISABLE 关闭唤醒事件上报
CANTRCV_WUMODE_CLEAR 清除已有唤醒状态

如果在 DISABLEENABLE 的间隙发生唤醒,SetWakeupMode(ENABLE) 不会主动补发该事件。集成时需要在重新开启后调用 GetBusWuReason(),确认关闭上报期间是否已经发生过唤醒。

ICU 唤醒配置

当 CAN Controller 本身不支持 “wakeup by CAN bus”,但 ECU 又需要因为 CAN 总线活动醒来或开始通信时,可以使用 MCU 额外 I/O 输入配合 ICU。该输入通常并联到 CAN Rx,或者连接到收发器的 ERR 引脚,具体取决于收发器硬件。

ICU 配置项 建议值或行为
ICU channel 每个需要通过收发器唤醒的 CAN 通道配置一个输入通道
输入连接 CAN Rx 并联输入,或连接收发器 ERR 引脚
Measurement Mode SignalEdgeDetection
Signal Notification 调用系统唤醒验证入口的通知函数
Channel Wakeup Info 对应的 ECUM_WKSOURCE_CANx
IcuDefaultStartEdge 若存在该参数,配置为 ICU_FALLING_EDGE
Wakeup Capability 需要唤醒 ECU 时启用

通知函数通常只做一件事:把硬件输入边沿转给 EcuM。

void Icu_TrcvWakeUpNotification_0(void)
{
  EcuM_CheckWakeup(ECUM_WKSOURCE_CAN0);
}

如果系统不需要对该唤醒源进行验证,也可以在通知函数中调用 EcuM_SetWakeupEvent()。两种写法的差别在于:前者触发 EcuM 的唤醒验证路径,后者直接声明唤醒事件成立。

SBC 依赖与跨分区调用

CanTrcv_30_Sbc 的硬件访问依赖 SBC Driver。SBC Driver 暴露的服务名和 CanTrcv 可使用的回调名之间存在固定映射;当 CANTRCV_30_SBC_CALLBACK_FUNCTIONS == STD_ON 时,应用侧需要实现这些回调,以便跨 OS Application 或安全分区时通过受控入口访问 SBC 功能。

SBC Driver 服务 CanTrcv 回调入口
Sbc_CanTrcv_SetMode(params) CanTrcv_30_Sbc_Hw_SetMode(params)
Sbc_CanTrcv_ReadStatus(params) CanTrcv_30_Sbc_Hw_ReadStatus(params)
Sbc_CanTrcv_ClearEvents(params) CanTrcv_30_Sbc_Hw_ClearEvents(params)
Sbc_CanTrcv_WritePnConfig(params) CanTrcv_30_Sbc_Hw_WritePnConfig(params)
CanTrcv 与 SBC 所在分区 SBC 分类 调用方式
同一分区 trusted 直接调用 SBC 服务
不同分区 trusted CallTrustedFunction(IDX_SBC_CANTRCV_..., ...)
同一分区 non-trusted 直接调用 SBC 服务
不同分区 non-trusted osCallNonTrustedFunction(IDX_SBC_CANTRCV_..., ...)

跨分区设计的核心问题不是函数名,而是执行上下文:CanTrcv API 可能由任务或
中断
触发,SBC Driver 又可能要求特定 OS Application 或安全上下文。把访问汇聚到 CanTrcv_30_Sbc_Hw_* 回调后,可以在应用层统一放置 trusted function、non-trusted function 或直接调用策略。

数据一致性与 Exclusive Area

模式切换、唤醒检查和硬件状态读取都会访问同一组 SBC 收发器服务。模块使用 CANTRCV_EXCLUSIVE_AREA_0 保护这些调用,避免上层服务在关键硬件访问期间相互打断。

Exclusive Area 用途
CANTRCV_EXCLUSIVE_AREA_0 保护经由 SBC Driver 的收发器硬件访问
保护对象 模式、状态、事件和 PN 配置相关访问
持续时间 覆盖一次 SBC 模块调用,持续时间较长
实现来源 VStdLib、Schedule Manager 或 OSEK OS,取决于中断锁配置
受保护 API 原因
CanTrcv_30_Sbc_Init() 初始化期间访问所有配置通道
CanTrcv_30_Sbc_SetOpMode() 切换硬件模式并触发模式指示
CanTrcv_30_Sbc_GetOpMode() 读取硬件当前模式
CanTrcv_30_Sbc_CheckWakeup() 读取并上报硬件唤醒状态
CanTrcv_30_Sbc_MainFunction() 周期轮询硬件唤醒状态

集成时应避免这些 API 相互抢占。尤其是 SetOpMode()CheckWakeup()MainFunction(),它们都可能触发 SBC 访问和上层回调;如果系统中断锁粒度不清晰,容易造成上层状态机读到短暂不一致的收发器状态。

API 矩阵

下面按用途归

CanTrcv 提供的服务。所有服务都要求模块已初始化,除非服务本身就是 InitMemory()Init()

生命周期与模式 API 上下文 返回与回调
CanTrcv_30_Sbc_InitMemory() task void;非重入;早于所有功能
CanTrcv_30_Sbc_Init(ConfigPtr) task void;初始化所有配置通道
CanTrcv_30_Sbc_SetOpMode(CanTrcvIndex, OpMode) task / interrupt E_OKE_NOT_OK;成功完成模式变化后调用 CanIf_30_Sbc_TrcvModeIndication()
CanTrcv_30_Sbc_GetOpMode(CanTrcvIndex, OpMode) task / interrupt E_OK 表示检测到当前模式
CanTrcv_30_Sbc_GetVersionInfo(VersionInfo) task / interrupt 将版本信息写入调用方提供的结构
唤醒与标志 API 上下文 返回与回调
CanTrcv_30_Sbc_GetBusWuReason(CanTrcvIndex, Reason) task / interrupt 读取最近一次唤醒原因
CanTrcv_30_Sbc_SetWakeupMode(CanTrcvIndex, TrcvWakeupMode) task / interrupt 设置 ENABLEDISABLECLEAR
CanTrcv_30_Sbc_CheckWakeup(CanTrcvIndex) task / interrupt 检测到总线唤醒时调用 EcuM_SetWakeupEvent()
CanTrcv_30_Sbc_ClearTrcvWufFlag(CanTrcvIndex) task / interrupt 清除硬件所有 wakeup flag,完成后调用 CanIf_30_Sbc_ClearTrcvWufFlagIndication()
CanTrcv_30_Sbc_CheckWakeFlag(CanTrcvIndex) task / interrupt 完成后调用 CanIf_30_Sbc_CheckTrcvWakeFlagIndication()
诊断、周期与 PN API 上下文 要点
CanTrcv_30_Sbc_GetTrcvSystemData(CanTrcvIndex, TrcvSysData) task / interrupt TrcvSysData[7:0] 为模式,[15:8] 为状态,[31:16] 为事件
CanTrcv_30_Sbc_ReadTrcvTimeoutFlag(CanTrcvIndex, FlagState) task / interrupt 读取 timeout flag
CanTrcv_30_Sbc_ClearTrcvTimeoutFlag(CanTrcvIndex) task / interrupt 清除 timeout flag
CanTrcv_30_Sbc_ReadTrcvSilenceFlag(CanTrcvIndex, FlagState) task / interrupt 读取 silence flag
CanTrcv_30_Sbc_MainFunction() task Wakeup support 为 polling 时周期执行
CanTrcv_30_Sbc_SetPNActivationState(ActivationState) task 切换 selective wakeup 行为

SetPNActivationState() 的约束比普通模式 API 更强。PN_ENABLED 表示硬件配置为只被配置帧唤醒,也就是 WUF;PN_DISABLED 表示硬件配置为任何总线活动都能唤醒,也就是 WUP。要让 selective wakeup 生效,生成配置中也必须启用对应能力。

PN 操作 生效规则
PN_ENABLED 仅对已在生成配置中启用 PN 的通道有意义
PN_DISABLED 在下一次模式变化后生效
从 disabled 回到 enabled 仅改变软件状态,硬件不会立即恢复 selective wakeup
推荐调用时机 紧跟 CanTrcv_30_Sbc_Init() 后使用
并发约束 不应被任何其他 CanTrcv API 打断

服务 ID 与错误码

CANTRCV_30_SBC_DEV_ERROR_DETECT == STD_ON 时,模块通过 DET 报告开发错误。错误报告使用模块 ID、实例 ID、服务 ID 和错误码定位调用问题。

服务 ID 服务
0x00 CanTrcv_30_Sbc_Init()
0x01 CanTrcv_30_Sbc_SetOpMode()
0x02 CanTrcv_30_Sbc_GetOpMode()
0x03 CanTrcv_30_Sbc_GetBusWuReason()
0x04 CanTrcv_30_Sbc_GetVersionInfo()
0x05 CanTrcv_30_Sbc_SetWakeupMode()
0x06 CanTrcv_30_Sbc_MainFunction()
0x07 CanTrcv_30_Sbc_CheckWakeup()
0x09 CanTrcv_30_Sbc_GetTrcvSystemData()
错误码 含义 典型触发点
0x01 CANTRCV_30_SBC_E_INVALID_TRANSCEIVER 通道索引无效 CanTrcvIndex 超出配置范围
0x02 CANTRCV_30_SBC_E_PARAM_POINTER 空指针 输出参数为 NULL_PTR
0x11 CANTRCV_30_SBC_E_UNINIT 模块未初始化 初始化前调用业务 API
0x21 CANTRCV_30_SBC_E_TRCV_NOT_STANDBY 硬件不在 standby 需要 standby 前置条件的唤醒操作
0x22 CANTRCV_30_SBC_E_TRCV_NOT_NORMAL 硬件不在 normal 需要 normal 前置条件的操作
0x23 CANTRCV_30_SBC_E_PARAM_TRCV_WAKEUP_MODE 唤醒模式参数无效 SetWakeupMode() 参数非法
0x24 CANTRCV_30_SBC_E_PARAM_TRCV_OPMODE 目标模式不受支持 请求 SLEEP 或硬件不支持的模式
0x40 CANTRCV_30_SBC_E_NO_TRCV_CONTROL 收发器不受控制或硬件状态无效 生产错误场景
返回值 模块语义
E_OK 请求被接受,或检测到了有效状态
E_NOT_OK 参数非法、状态不满足、底层访问失败或当前能力未启用
模式 API 返回 E_NOT_OK 前一个模式保持不变
唤醒 API 返回 E_NOT_OK 可能表示未检测到唤醒,也可能表示当前通道不支持该能力

返回值的含义要结合 API 使用。例如 GetBusWuReason() 返回 E_NOT_OK 可能只是没有有效唤醒原因,而 SetOpMode() 返回 E_NOT_OK 则意味着请求的状态变化没有被接受。

配置、文件与内存映射

模块交付文件分为静态文件和生成文件。静态文件提供 API 与实现,生成文件携带配置、类型和外部数据声明。

文件 类型 用途
CanTrcv_30_Sbc.h 静态头文件 上层模块包含的 CanTrcv API 声明
CanTrcv_30_Sbc.c 静态源文件 模块实现
CanTrcv_30_Sbc_Cfg.h 生成头文件 类型定义、外部数据声明,供头文件包含
CanTrcv_30_Sbc_Cfg.c 生成源文件 配置数据
CanTrcv_GeneralTypes.h 通用类型头文件 定义 SWS 指定的 CanTrcv 类型,可被 Can_GeneralTypes.h 包含
编译抽象宏 用途
CANTRCV_30_SBC_VAR 模块变量
CANTRCV_30_SBC_APPL_VAR 应用侧变量指针
CANTRCV_30_SBC_CONST 模块常量
CANTRCV_30_SBC_CODE 模块代码
CANTRCV_30_SBC_APPL_CODE 应用侧回调代码
内存段 典型内容
CANTRCV_30_SBC_START_SEC_CODE / STOP_SEC_CODE CanTrcv 代码
CANTRCV_30_SBC_START_SEC_CONST_UNSPECIFIED / STOP_SEC_CONST_UNSPECIFIED 未指定宽度常量
CANTRCV_30_SBC_START_SEC_VAR_NOINIT_UNSPECIFIED / STOP_SEC_VAR_NOINIT_UNSPECIFIED 未初始化变量
配置项 集成影响
CANTRCV_30_SBC_DEV_ERROR_DETECT 开启后通过 DET 报告开发错误
CANTRCV_30_SBC_CALLBACK_FUNCTIONS 开启后需要应用提供 CanTrcv_30_Sbc_Hw_* 回调
Wakeup support 选择 polling 时需要周期调用 MainFunction()
Version Info API 开启后可通过 API 读取版本信息
CanTrcvInitState 该配置不改变初始化行为,通道仍初始化为 NORMAL
CanTrcvSPICommRetries / CanTrcvSPICommTimeout 在该实现中为可选配置,因为收发器访问经由 SBC Driver

版本也可以通过头文件中的宏读取:

版本宏 含义
CANTRCV_30_SBC_AR_RELEASE_MAJOR_VERSION AUTOSAR release major
CANTRCV_30_SBC_AR_RELEASE_MINOR_VERSION AUTOSAR release minor
CANTRCV_30_SBC_AR_RELEASE_PATCH_VERSION AUTOSAR release patch
CANTRCV_30_SBC_SW_MAJOR_VERSION 软件 major
CANTRCV_30_SBC_SW_MINOR_VERSION 软件 minor
CANTRCV_30_SBC_SW_PATCH_VERSION 软件 patch

AUTOSAR 符合性与偏差

CanTrcv_30_Sbc 保留 AUTOSAR CanTrcv 的主要接口语义,但由于收发器硬件挂在 SBC 上,部分能力和回调命名存在实现差异。

类型 内容 集成影响
Addition 增加 CanTrcv_30_Sbc_InitMemory() 上电后必须先初始化内部状态
Limitation 不支持 SPI 直接连接 SPI 访问由 SBC Driver 所在层负责
Limitation 不支持 DIO 直接连接 不通过 DIO 操作收发器控制引脚
Limitation 收发器访问经由 SBC Driver 硬件同步责任落在 SBC Driver
Deviation CanIf 通知函数带 _30_Sbc 前缀 用于区分局部索引与全局索引换算
Deviation CanIf_CheckTrcvWakeFlagIndication() 总会被调用 避免 CanSM 等待通知时卡住
Deviation GetTrcvSystemData() 参数去掉 const 驱动需要写入诊断数据
Deviation CanTrcvInitState 不决定初始化模式 初始化后通道固定进入 NORMAL
标准回调语义 实现中的回调名
CanIf_TrcvModeIndication CanIf_30_Sbc_TrcvModeIndication
CanIf_ConfirmPnAvailability CanIf_30_Sbc_ConfirmPnAvailability
CanIf_ClearTrcvWufFlagIndication CanIf_30_Sbc_ClearTrcvWufFlagIndication
CanIf_CheckTrcvWakeFlagIndication CanIf_30_Sbc_CheckTrcvWakeFlagIndication

CanIf_CheckTrcvWakeFlagIndication() 的行为尤其重要:即使没有检测到唤醒,驱动也会调用该通知。否则 CanSM 在发起 wake flag 检查后可能一直等待完成通知。如果确实检测到唤醒,则另行通过 EcuM_SetWakeupEvent() 上报唤醒源。

集成关注点

场景 关注点 建议动作
上电初始化 InitMemory() 必须最早执行 把它放入 EcuM 或启动代码的早期初始化段
模式切换 只支持 NORMALSTANDBY 上层不要请求 SLEEP
同模式请求 返回 E_OK 但不发生硬件切换 状态机不要把它当作一次真实迁移
模式读取 切换完成前可能读到旧状态 结合 CanIf_30_Sbc_TrcvModeIndication() 使用
唤醒判断 E_OK 不是系统唤醒的唯一依据 EcuM_SetWakeupEvent() 对应唤醒源为准
唤醒关闭窗口 DISABLEENABLE 间可能有事件 重新开启后调用 GetBusWuReason()
ICU 唤醒 需要正确连接 CAN Rx 或 ERR 输入 ICU 配成 falling edge 并绑定 EcuM wakeup source
跨分区访问 SBC 服务可能在不同 OS Application 使用 CanTrcv_30_Sbc_Hw_* 回调统一入口
PN 切换 PN_DISABLED 下一次模式变化后生效 PN 状态切换后安排一次明确的模式迁移
Exclusive Area SBC 调用持续时间较长 避免受保护 API 在任务和中断间互相打断

对这个模块而言,最容易出问题的不是 API 名称,而是上下文关系:初始化先后顺序、CanTrcv 与 SBC 的分区边界、ICU 唤醒输入的电气连接、以及 EcuM 唤醒源是否与通道配置一致。只要这几处边界明确,CanTrcv_30_Sbc 可以把 SBC 内部收发器稳定地接入 AUTOSAR CAN 通信栈。


作者:不脱发的程序猿。本文同步自作者 CSDN 博客。

原文:https://handsome-man.blog.csdn.net/article/details/162843140

创作许可协议

本项目采用 CC BY(署名) 进行许可。

评论(0)
- 没有更多了 -