CanTrcv_30_Sbc收发器驱动详解:SBC模式控制与总线唤醒机制

2026-10-18 10:09:15 30阅读

CanTrcv_30_Sbc是面向 SBC 集成式 CAN 收发器的 AUTOSAR CAN Transceiver Driver 实现。它把上层模块看到的接口稳定在 CanTrcv 语义上,而把实际硬件访问交给 SBC Driver 完成。这样一来,CanIf、CanSM、EcuM 不需要关心收发器位于独立芯片、SBC 外设还是某个受 SBC 同步保护的内部组件,只需要按 CanTrcv API 管理工作模式、唤醒检测和局部网络能力。本文围绕三个集成主线展开:NORMAL与STANDBY的模式控制,总线唤醒的上报路径,以及 SBC 访问、ICU 唤醒和跨分区调用带来的约束。

模块定位

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

项目值
AUTOSAR releaseRelease 4
配置变体Pre-compile、Post-build selectable
Vendor IDCANTRCV_30_SBC_VENDOR_ID = 30
Module IDCANTRCV_30_SBC_MODULE_ID = 70
Instance IDCANTRCV_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()通知系统

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

模式相关服务关键行为
CanTrcv_30_Sbc_SetOpMode(CanTrcvIndex, OpMode)请求通道进入NORMAL或STANDBY
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 上报唤醒源。

唤醒服务用法主要边界
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_BUSCAN 总线活动触发唤醒典型总线唤醒原因
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清除已有唤醒状态

如果在DISABLE到ENABLE的间隙发生唤醒,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 ModeSignalEdgeDetection
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 服务
不同分区trustedCallTrustedFunction(IDX_SBC_CANTRCV_..., ...)
同一分区non-trusted直接调用 SBC 服务
不同分区non-trustedosCallNonTrustedFunction(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()taskvoid;非重入;早于所有功能
CanTrcv_30_Sbc_Init(ConfigPtr)taskvoid;初始化所有配置通道
CanTrcv_30_Sbc_SetOpMode(CanTrcvIndex, OpMode)task / interruptE_OK或E_NOT_OK;成功完成模式变化后调用CanIf_30_Sbc_TrcvModeIndication()
CanTrcv_30_Sbc_GetOpMode(CanTrcvIndex, OpMode)task / interruptE_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设置ENABLE、DISABLE或CLEAR
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 / interruptTrcvSysData[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()taskWakeup 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服务
0x00CanTrcv_30_Sbc_Init()
0x01CanTrcv_30_Sbc_SetOpMode()
0x02CanTrcv_30_Sbc_GetOpMode()
0x03CanTrcv_30_Sbc_GetBusWuReason()
0x04CanTrcv_30_Sbc_GetVersionInfo()
0x05CanTrcv_30_Sbc_SetWakeupMode()
0x06CanTrcv_30_Sbc_MainFunction()
0x07CanTrcv_30_Sbc_CheckWakeup()
0x09CanTrcv_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_CODECanTrcv 代码
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_VERSIONAUTOSAR release major
CANTRCV_30_SBC_AR_RELEASE_MINOR_VERSIONAUTOSAR release minor
CANTRCV_30_SBC_AR_RELEASE_PATCH_VERSIONAUTOSAR 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
DeviationCanIf 通知函数带_30_Sbc前缀用于区分局部索引与全局索引换算
DeviationCanIf_CheckTrcvWakeFlagIndication()总会被调用避免 CanSM 等待通知时卡住
DeviationGetTrcvSystemData()参数去掉const驱动需要写入诊断数据
DeviationCanTrcvInitState不决定初始化模式初始化后通道固定进入NORMAL
标准回调语义实现中的回调名
CanIf_TrcvModeIndicationCanIf_30_Sbc_TrcvModeIndication
CanIf_ConfirmPnAvailabilityCanIf_30_Sbc_ConfirmPnAvailability
CanIf_ClearTrcvWufFlagIndicationCanIf_30_Sbc_ClearTrcvWufFlagIndication
CanIf_CheckTrcvWakeFlagIndicationCanIf_30_Sbc_CheckTrcvWakeFlagIndication

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

集成关注点

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

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


作者:不脱发的程序猿
链接:https://www.aiddithome.com/p/12f4ce26425236.html
本作遵循 [CC BY 4.0 署名] 许可,版权归作者所有。若存在违规行为,您可以点击 “举报”。


登录 后发表评论
3条评论
天快亮了
1楼 · 2026-10-18 10:11:44

模式切换做不好容易误唤醒,这篇把底层逻辑理清了,收藏。

第三次终于亮了
2楼 · 2026-10-18 10:11:43

SBC的收发器驱动里模式切换和唤醒时序最烦人,写得很细,感谢。

探头看一眼
3楼 · 2026-10-18 10:11:43

CanTrcv这一层平时很少有人展开讲,能沉下来说机制的不多。