TJA1145 CAN收发器驱动深度解析:SPI访问与唤醒机制

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

CAN 收发器驱动经常被误认为只是CanSM下发NORMAL、STANDBY、SLEEP的薄封装。对 TJA1145 这类带 SPI 寄存器访问、局部网络(Partial Networking)和唤醒标志的器件来说,真正容易出问题的地方不在 API 名称,而在模式切换是否异步完成、唤醒事件由谁确认、SPI 请求是否还在 pending、以及 PN 配置什么时候才真正写入硬件。CanTrcv_30_Tja1145位于 AUTOSAR Classic 平台的基础软件(BSW)中,对上提供 CAN Transceiver Driver 接口,对下通过 SPI 访问收发器寄存器,并可借助 ICU 将 Rx/ERR 引脚上的电平变化转换为 ECU 唤醒路径。它支持 AUTOSAR 4.0.3,配置变体包括 Pre-compile、Post- build selectable 和 Post-build loadable。模块标识使用CANTRCV_30_TJA1145_VENDOR_ID、CANTRCV_30_TJA1145_MODULE_ID和CANTRCV_30_TJA1145_INSTANCE_ID,其中 instance ID 由配置工具中的 pre-compile 参数指定。这篇文章按工程集成路径拆解这个驱动:先说明硬件和功能边界,再看初始化、模式切换、唤醒检测、SPI/ICU 依赖,最后收束到 API、配置、DET 错误、限制和 AUTOSAR 偏差。

模块边界和硬件前提

虽然模块名带有Tja1145,这个驱动覆盖的硬件不只 NXP TJA1145,还包括 NXP UJA1168 和 Atmel ATA6570。硬件前提不能忽略,因为驱动只负责 CAN transceiver 功能,不会替应用处理 SBC 或 watchdog 的预置状态。

项目约束
支持硬件NXP TJA1145、NXP UJA1168、Atmel ATA6570
控制路径通过 SPI 控制 CAN 收发器
不支持路径不支持通过 DIO 控制 CAN 收发器
支持功能初始化、SPI 控制、唤醒检测、局部网络唤醒、模式获取和设置、自诊断
MICROSAR 扩展Identity Manager with Post-build selectable、Post-build loadable

UJA1168 出厂时FNMCbit 可能为 1,此时不能使用该驱动,使用前应确保该 bit 为 0。UJA1168 的 SPI 通信只在 SBC 处于NORMAL或STANDBY模式时可用,应用必须保证只在这两个模式下调用驱动 API。RESET 到 STANDBY 的转换还存在访问 SPI 前必须满足的时间约束,这个约束也由应用侧保证。ATA6570 的WDC符号控制 Window Watchdog,位于WDCR1寄存器 bit 7:5。驱动假定 watchdog 处于 disabled 状态,不会配置 watchdog;使用前需要确认WDC为001,对应默认的 Off mode。从相邻模块看,CanTrcv_30_Tja1145不是独立运行的 底层驱动 。它至少和CanSM、CanIf、EcuM、SPI、ICU、DET以及可选的 Time Service 发生关系。

初始化和模式状态

上电或复位后,初始化顺序分成两步。CanTrcv_30_Tja1145_InitMemory()先初始化驱动内存和必要值,必须在其他收发器驱动功能之前调用。随后CanTrcv_30_Tja1145_Init(ConfigPtr)初始化配置工具选中的所有 active channel,并把每个 CAN 收发器通道切到CANTRCV_TRCVMODE_NORMAL。如果初始化前已经有 wakeup event pending,驱动会保存该事件,并通过EcuM_SetWakeupEvent()通知 EcuM。局部网络相关数据也有一个容易踩到的边界:PN 的ID、MASK、DLC、DATA只有在初始化期间检测到 POR(Power-on-reset)或SYSERRflag 时才写入底层收发器硬件。也就是说,修改过的 PN 配置并不一定在普通重初始化后立即进入硬件,通常要等 CAN 收发器发生 power-on-cycle,或者初始化时进入相应错误恢复路径。收发器模式由CanTrcv_30_Tja1145_SetOpMode()切换,支持的主路径如下。

当前模式目标模式支持情况说明
NORMALSTANDBY支持常规降级到待机
STANDBYSLEEP支持进入低功耗路径
STANDBYNORMAL支持回到 active/NORMAL
SLEEPNORMAL支持唤醒后回到 active/NORMAL
NORMALSLEEP不支持需要先进入STANDBY
SLEEPSTANDBY不支持不由该服务直接完成

当某个通道的所有唤醒源都被禁用时,硬件不会真正进入 sleep。此时如果请求STANDBY -> SLEEP,驱动只把软件模式改为 sleep,底层收发器硬件仍停留在 standby。这种 sleep emulation 对上层状态机是可见的:上层看到的是软件 sleep,但硬件功耗和唤醒源语义不能按真实 sleep 推断。CanTrcv_30_Tja1145_GetOpMode()用来读取指定收发器当前模式。若此前已经请求过模式切换,直到模式切换完成并触发CanIf_30_Tja1145_TrcvModeIndication()之前,读取到的模式可能还不是稳定结果。SetOpMode()返回E_OK时,表示收发器状态接受了切换请求;通知函数可能在中断上下文、任务上下文,或者SetOpMode()调用上下文中发生,而且通知给CanIf的模式不保证一定等于请求模式。

active mode 启动时间

TJA1145 切到 active mode,也就是软件侧NORMAL,最大需要 220 us。默认情况下,驱动在设置并验证 Mode control 和 CAN control 寄存器后,就立即向CanSM报告 active mode 转换成功。随后CanSM启动 CAN controller,而 CAN controller 在检测到 11 个连续 recessive bit 后开始参与总线通信。这个时间关系在高速 CAN 网络上尤其明显:

波特率11 个 recessive bit 对应时间
1000 kbit/s11 us
500 kbit/s22 us
250 kbit/s44 us

如果 TJA1145 的 Rx pin 在 active mode 完成前保持 recessive,CAN controller 可能把这段电平误认为总线上的 11 个 recessive bit。等收发器真正反映 CAN bus 电平后,controller 可能把任意 dominant level 当作帧起始,从而在帧中间参与接收并产生 error frame。CAN 网络本身应能容忍 error frame,但如果项目要规避这种行为,需要使用 AUTOSAR Time Service,并把CanTrcvTimerType配成Timer_1us16bit。如果没有现成 Time Service,需要提供Tm.h、Tm.c并实现Tm_BusyWait1us16bit()。

唤醒检测和局部网络

如果配置工具中启用了 bus wakeup detection ,上层在唤醒场景下调用CanTrcv_30_Tja1145_CheckWakeup(CanTrcvIndex)。当收发器处于 sleep 或 standby,且检测到 bus wakeup 事件时,同步 SPI 模式下该函数可以返回E_OK;否则返回E_NOT_OK。在异步 SPI 模式下,E_OK只表示“检查唤醒的请求已被接受”,真正的唤醒有效性不能从返回值判断。局部网络选择性唤醒还有一个配置组合条件:同一 channel 上必须同时启用CanTrcvChannel\CanTrcvWakeupByBusUsed和CanTrcvChannel\CanTrcvPartialNetwork\CanTrcvPnEnabled。只开其中一个,不能得到选择性唤醒的完整语义。CanTrcv_30_Tja1145_GetBusWuReason()返回最近一次检测到的唤醒原因。如果期间发生多次唤醒,只报告最后一次。可返回的 wakeup reason 包括:

唤醒原因含义
CANTRCV_WU_INTERNALLY通过CanTrcv_30_Tja1145_SetOpMode()设置 NORMAL 导致内部唤醒
CANTRCV_WU_ERROR未检测到唤醒,或未保存原因;函数返回E_NOT_OK
CANTRCV_WU_NOT_SUPPORTED收发器不支持唤醒检测;函数返回E_NOT_OK
CANTRCV_WU_BY_BUS外部 bus wakeup
CANTRCV_WU_RESETreset 后检测到唤醒
CANTRCV_WU_POWER_ONpower-on wakeup
CANTRCV_WU_BY_SYSERR内部硬件错误导致收发器唤醒
CANTRCV_WU_BY_PINWAKE pin 边沿导致唤醒

CanTrcv_30_Tja1145_SetWakeupMode()控制 wakeup event 是否向上层报告:

模式行为
CANTRCV_WUMODE_ENABLE向上层报告 wakeup event
CANTRCV_WUMODE_DISABLE不向上层报告 wakeup event
CANTRCV_WUMODE_CLEAR清除 pending wakeup event

如果配置中没有启用 wakeup handling,该函数始终返回E_NOT_OK。如果 wakeup reporting 处于DISABLE到ENABLE之间时检测到了唤醒,重新 enable 并不会主动上报这次事件;应在重新 enable 后调用CanTrcv_30_Tja1145_GetBusWuReason()检查是否已有唤醒原因。唤醒检查路径可以按下面理解。

CanTrcv_30_Tja1145_CheckWakeFlag()用于请求驱动检查底层收发器 wake flag。检测到的唤醒通过EcuM_SetWakeupEvent()报告,具体原因再通过GetBusWuReason()查询。请求完成后,驱动调用CanIf_30_Tja1145_CheckTrcvWakeFlagIndication();这个通知可能发生在中断上下文、任务上下文或CheckWakeFlag()调用上下文中。CanTrcv_30_Tja1145_ClearTrcvWufFlag()用来清除 wakeup flag,但受硬件架构影响,它会清除所有 wakeup flags,而不是只清除某一个来源。清除请求完成后,驱动调用CanIf_30_Tja1145_ClearTrcvWufFlagIndication()。PN activation 通过CanTrcv_30_Tja1145_SetPNActivationState()动态切换:

参数硬件唤醒行为
PN_ENABLED配置为只对匹配帧唤醒,即 WUF(Wakeup Frame)
PN_DISABLED配置为对任意 bus activity 唤醒,即 WUP(Wakeup Pattern)

该 API 的前提是生成配置中已经为相关 channel 启用了 selective wakeup。PN_DISABLED的状态变化要到下一次 mode change 后才生效。对于 TJA1145,PN_ENABLE对硬件没有立即效果;重新启用 selective wakeup 需要重新初始化。驱动也明确建议该 API 只在CanTrcv_30_Tja1145_Init()之后直接使用,并且该 API 不能被其他 CanTrcv API 打断。

ICU 唤醒脚集成

当 CAN controller 不支持“wakeup by CAN bus”,但 ECU 又需要因为 CAN bus 通信被唤醒并启动自身通信时,可以借助 MCU 的 I/O port 和 ICU。该 I/O port 可以并联到 CAN Rx port,也可以直接接到收发器 ERR port,取决于具体收发器。驱动使用 ICU 的两个服务:

ICU 服务使用时机
Icu_EnableNotification()切换到STANDBY期间使能 ICU notification
Icu_DisableNotification()上报 wakeup event 后关闭 ICU notification

每个需要通过 CAN bus 唤醒的 CAN channel 都要配置对应 ICU channel,并绑定 signal notification function 和 transceiver wakeup source。ICU channel 的测量模式应配置为边沿检测。由于 wakeup event 由 Rx pin 或 ERR pin 从 recessive 到 dominant 的电平变化提供,IcuDefaultStartEdge建议配置为ICU_FALLING_EDGE。如果 transceiver 不只是唤醒 CAN channel,还要唤醒整个 ECU,则该 ICU channel 需要开启Wakeup Capability。signal notification function 由用户实现。使用 wakeup validation 时,典型实现是通知 EcuM 检查对应唤醒源:

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

如果对应 wakeup source 不使用 wakeup validation,可以直接调用EcuM_SetWakeupEvent()。

SPI 访问、排他区和周期任务

底层硬件访问通过 SPI 完成。驱动使用Spi_SetupEB()准备外部 buffer,再通过Spi_SyncTransmit()或Spi_AsyncTransmit()发送 sequence,读取或写入 CAN transceiver 寄存器。每个收发器硬件都需要配置 device、channel、job 和 sequence。

SPI 对象关键配置
Devicechip select idle high,data edge 为 falling edge 有效,clock idle low
Channel每个硬件创建 4 个,external buffer,maximum length 4,单字节宽度 8 bit,默认发送数据0xFF,MSB first
Job每个硬件创建 4 个,priority 为最高0,job end call 为NULL_PTR,绑定对应 channel 和 device
Sequence N包含JOB_RW_REG_0;同步 SPI 时 end call 为NULL_PTR,异步 SPI 时使用CanTrcv_30_Tja1145_SpiIndicationN_
Sequence M包含JOB_RW_REG_0..2;异步 SPI 时使用CanTrcv_30_Tja1145_SpiIndicationM_
Sequence L包含JOB_RW_REG_0..3;异步 SPI 时使用CanTrcv_30_Tja1145_SpiIndicationL_

如果使用异步 SPI,SPI driver 必须在 interrupts locked 时也提供轮询事件的方法,例如Spi_MainFunction_Driving()。否则CanTrcv_Init或同步访问模拟路径可能无法推进 SPI sequence 状态。驱动使用CANTRCV_EXCLUSIVE_AREA_0保护通过 SPI interface 对收发器硬件的原子访问和内部状态更新。该排他区持续时间被定义为 LONG,因为它覆盖 SPI 调用和状态更新。涉及的服务包括Init()、SetOpMode()、GetOpMode()、CheckWakeup()、MainFunction()、诊断数据读取、WUF flag 清除、timeout/silence flag 读写、wake flag 检查以及 SPI indication 等。API 说明中反复出现的“not reentrant”不是形式要求,而是和这个共享 SPI 访问模型直接相关。异步 mode change 使用时,CanTrcv_30_Tja1145_MainFunction()必须尽可能快地周期调用。一次 mode change 可能需要多个周期才能完成。如果驱动以同步方式使用,则通常不需要调用MainFunction(),除非生成配置中把 Wakeup Support 配成 Polling。

API 矩阵

这些 API 大多可在 task 或 interrupt level 调用,但都不是 reentrant。初始化类和 PN activation 类 API 更严格,必须在 task level 调用。

CanTrcv_30_Tja1145_InitMemory(void)

主要参数:无返回值:无调用上下文和关键限制:task level,not reentrant;必须先于其他驱动功能调用

CanTrcv_30_Tja1145_Init(ConfigPtr)

主要参数:ConfigPtr指向配置结构;多配置时可选择对应CanTrcv_30_Tja1145_Config__Ptr返回值:无调用上下文和关键限制:task level,not reentrant;调用前必须完成InitMemory(),且 SPI driver 已初始化

CanTrcv_30_Tja1145_SetOpMode(CanTrcvIndex, OpMode)

主要参数:通道索引和目标CanTrcv_TrcvModeType返回值:E_OK表示切换请求被接受;E_NOT_OK表示状态不接受或参数越界,前一状态不变调用上下文和关键限制:task 或 interrupt level,not reentrant;并非所有模式转换都允许;进入 NORMAL 且 selective wakeup enabled 时会读取错误标志并可能调用CanIf_30_Tja1145_ConfirmPnAvailability()

CanTrcv_30_Tja1145_GetOpMode(CanTrcvIndex, OpMode*)

主要参数:通道索引和保存当前模式的指针返回值:E_OK表示模式已检测;E_NOT_OK表示未检测到模式调用上下文和关键限制:task 或 interrupt level,not reentrant;模式切换完成前读取值可能无效

CanTrcv_30_Tja1145_GetBusWuReason(CanTrcvIndex, Reason*)

主要参数:通道索引和保存唤醒原因的指针返回值:E_OK表示检测到 wakeup reason;E_NOT_OK表示未检测到或不支持调用上下文和关键限制:task 或 interrupt level,not reentrant;只报告最后一次唤醒原因

CanTrcv_30_Tja1145_SetWakeupMode(CanTrcvIndex, TrcvWakeupMode)

主要参数:通道索引和ENABLE、DISABLE、CLEAR返回值:E_OK表示 wakeup state 已切换;E_NOT_OK表示失败或参数越界调用上下文和关键限制:task 或 interrupt level,not reentrant;未启用 wakeup handling 时总是E_NOT_OK

CanTrcv_30_Tja1145_GetVersionInfo(VersionInfo)

主要参数:Std_VersionInfoType指针返回值:无调用上下文和关键限制:task 或 interrupt level,not reentrant;需要配置 Version Info Api

CanTrcv_30_Tja1145_CheckWakeup(CanTrcvIndex)

主要参数:通道索引返回值:同步模式下E_OK可表示检测到 bus wakeup;异步模式下E_OK表示请求被接受调用上下文和关键限制:task 或 interrupt level,not reentrant;有效唤醒应以EcuM_SetWakeupEvent()为准

CanTrcv_30_Tja1145_GetTrcvSystemData(CanTrcvIndex, TrcvSysData*)

主要参数:通道索引和uint32*诊断数据 buffer返回值:E_OK表示诊断寄存器读取成功调用上下文和关键限制:task 或 interrupt level,not reentrant;要求硬件支持 Selective Wakeup/PN;仍有 SPI 请求 pending 时返回E_NOT_OK

CanTrcv_30_Tja1145_ClearTrcvWufFlag(CanTrcvIndex)

主要参数:通道索引返回值:E_OK表示 WUF flag 清除请求成功调用上下文和关键限制:task 或 interrupt level,not reentrant;硬件支持 Selective Wakeup/PN;会清除所有 wakeup flags

CanTrcv_30_Tja1145_ReadTrcvTimeoutFlag(CanTrcvIndex, FlagState*)

主要参数:通道索引和 flag state 指针返回值:E_OK表示 timeout flag 状态读取成功调用上下文和关键限制:task 或 interrupt level,not reentrant;底层硬件不支持读取 timeout flag,因此FlagState不会被设置

CanTrcv_30_Tja1145_ClearTrcvTimeoutFlag(CanTrcvIndex)

主要参数:通道索引返回值:E_OK表示 timeout flag 清除请求成功调用上下文和关键限制:task 或 interrupt level,not reentrant;该驱动不支持 timeout flag,此 API 无实际效果

CanTrcv_30_Tja1145_ReadTrcvSilenceFlag(CanTrcvIndex, FlagState*)

主要参数:通道索引和 flag state 指针返回值:E_OK表示 silence flag 状态读取成功调用上下文和关键限制:task 或 interrupt level,not reentrant;该函数无实际效果

CanTrcv_30_Tja1145_CheckWakeFlag(CanTrcvIndex)

主要参数:通道索引返回值:E_OK表示 wake flag 检查请求被接受调用上下文和关键限制:task 或 interrupt level,not reentrant;检测到唤醒后通过EcuM_SetWakeupEvent()上报

CanTrcv_30_Tja1145_MainFunction(void)

主要参数:无返回值:无调用上下文和关键限制:task context,not reentrant;周期检查 wakeup,并在异步 SPI 时处理 pending requests

CanTrcv_30_Tja1145_SetPNActivationState(ActivationState)

主要参数:PN_ENABLED或PN_DISABLED返回值:E_OK表示 PN activation state 成功切换调用上下文和关键限制:task level,not reentrant;调用期间不得被其他 CanTrcv API 打断;建议只在Init()后直接调用CanTrcv_30_Tja1145_GetTrcvSystemData()返回的TrcvSysData是 32 bit 诊断数据,字段含义如下:

位范围内容
bit 07-00Main status register
bit 15-08Transceiver status register
bit 23-16Wake pin status register
bit 31-24reserved,读出值未定义

配置项和生成文件

交付文件分成静态文件和动态文件。静态文件包括CanTrcv_30_Tja1145.h和CanTrcv_30_Tja1145.c,前者供上层 include,后者为实现文件。动态文件包括CanTrcv_30_Tja1145_Cfg.h、CanTrcv_30_Tja1145_Cfg.c、CanTrcv_30_Tja1145_PBcfg.c和CanTrcv_GeneralTypes.h。其中PBcfg.c承载 Post-build loadable 配置数据,CanTrcv_GeneralTypes.h放置 SWS 定义的 CanTrcv 类型,也可被Can_GeneralTypes.hinclude。内存映射使用CANTRCV_30_TJA1145_START_SEC_*和CANTRCV_30_TJA1145_STOP_SEC_*成对宏,覆盖 code、const、noinit var、 init var 和 post-build configuration 等 section,例如:

Section用途
CANTRCV_30_TJA1145_START_SEC_CODE/STOP_SEC_CODE代码段
CANTRCV_30_TJA1145_START_SEC_CONST_UNSPECIFIED/STOP_SEC_CONST_UNSPECIFIED常量段
CANTRCV_30_TJA1145_START_SEC_VAR_NOINIT_UNSPECIFIED/STOP_SEC_VAR_NOINIT_UNSPECIFIEDnoinit 变量段
CANTRCV_30_TJA1145_START_SEC_VAR_INIT_UNSPECIFIED/STOP_SEC_VAR_INIT_UNSPECIFIEDinit 变量段
CANTRCV_30_TJA1145_START_SEC_PBCFG/STOP_SEC_PBCFGpost-build 配置段

部分配置只能通过 user configuration file 完成。

用户配置宏默认行为何时改写
CANTRCV_30_TJA1145_SPI_MAINFUNCTION()默认映射到Spi_MainFunction_Driving()异步 SPI 下CanTrcv_Init期间需要轮询 SPI event;若 SPI driver 不支持也不需要轮询,可定义为空
CANTRCV_30_TJA1145_SPI_SYNC_TRANSMIT(Ret, Seq)同步 SPI 时默认映射到Spi_SyncTransmit需要用自定义逻辑模拟同步发送,或在异步 SPI 上封装等待 sequence 完成
CANTRCV_30_TJA1145_WAKE_PIN_EVENT_RISING默认STD_ON不希望 WAKE pin 上升沿触发唤醒时设为STD_OFF
CANTRCV_30_TJA1145_WAKE_PIN_EVENT_FALLING默认STD_ON不希望 WAKE pin 下降沿触发唤醒时设为STD_OFF
CANTRCV_30_TJA1145_AUTO_REINIT默认关闭需要启用SYSERR自动恢复时定义为STD_ON

同步发送宏的自定义形式类似下面这样:

#define CANTRCV_30_TJA1145_SPI_SYNC_TRANSMIT(Ret, Seq) \
  (Ret) = Appl_DoSyncTransmit(Seq);

如果项目使用 ASR 4.1.1 或更高版本 SPI driver,而 SPI 类型已经从Spi_DataType迁移到Spi_DataBufferType,需要在用户配置文件中加入:

#define CanTrcv_SpiDataType Spi_DataBufferType

Post-build loadable 可重新配置的 CanTrcv 参数集中在CanTrcvPartialNetwork和CanTrcvPnFrameDataMaskSpec相关内容:

容器可在 Post-build 调整的参数
CanTrcvPartialNetworkCanTrcvBaudRate、CanTrcvPnCanIdIsExtended、CanTrcvPnEnabled、CanTrcvPnFrameCanId、CanTrcvPnFrameCanIdMask、CanTrcvPnFrameDlc、CanTrcvPowerOnFlag
CanTrcvPnFrameDataMaskSpecCanTrcvPnFrameDataMask、CanTrcvPnFrameDataMaskIndex

Wakeup source identifier 也可以在 Post-build 调整,但位置不在 CanTrcv 配置中,而在 EcuM 配置中。需要解除 CanTrcv 到 wakeup source 的引用,例如CanTrcvWakeupSourceRef、CanTrcvPorWakeupSourceRef、CanTrcvSyserrWakeupSourceRef,再调整 EcuM 的EcuMWakeupSourceId。

SYSERR 自动恢复

收发器支持从SYSERR状态自动恢复。若在STANDBY或SLEEP切到NORMAL期间检测到SYSERR,驱动会通过重写并校验 PN 配置来重新初始化底层硬件。同步 SPI 和异步 SPI 下恢复上下文不同:

SPI 模式自动恢复执行位置
同步 SPI在CanTrcv_30_Tja1145_SetOpMode()调用上下文中完成
异步 SPI在 task level 异步完成,依赖周期调度推进

重新初始化可能耗时。期间所有请求,包括新的模式切换请求,都会保持 pending。恢复完成后,驱动继续执行 pending requests。该功能默认关闭,需要在用户配置文件中加入:

#define CANTRCV_30_TJA1145_AUTO_REINIT STD_ON

需要注意,AUTOSAR 偏差中还有一个与 POR 相关的边界:如果进入 NORMAL 时检测到 POR,CanTrcv_SetOpMode不执行重新初始化。因为这种情况通常意味着Vs和Vcc低于下限后又恢复,而 MCU 仍保持 active;此时正确功能无法保证,应执行整个 MCU 的完整重新初始化,并在过程中重新调用CanTrcv_Init()。

DET 错误和返回语义

当 pre-compile 参数CANTRCV_30_TJA1145_DEV_ERROR_DETECT == STD_ON时,开发错误通过Det_ReportError()上报。上报的 instance ID 由配置工具指定。

Service ID服务
0x00CanTrcv_30_Tja1145_Init
0x01CanTrcv_30_Tja1145_SetOpMode
0x02CanTrcv_30_Tja1145_GetOpMode
0x03CanTrcv_30_Tja1145_GetBusWuReason
0x04CanTrcv_30_Tja1145_GetVersionInfo
0x05CanTrcv_30_Tja1145_SetWakeupMode
0x06CanTrcv_30_Tja1145_MainFunction
0x07CanTrcv_30_Tja1145_CheckWakeup
0x08CanTrcv_30_Tja1145_MainFunctionDiagnostics
0x09CanTrcv_30_Tja1145_GetTrcvSystemData
0x0ACanTrcv_30_Tja1145_ClearTrcvWufFlag
0x0BCanTrcv_30_Tja1145_ReadTrcvTimeoutFlag
0x0CCanTrcv_30_Tja1145_ClearTrcvTimeoutFlag
0x0DCanTrcv_30_Tja1145_ReadTrcvSilenceFlag
0x0ECanTrcv_30_Tja1145_CheckWakeFlag
0x0FCanTrcv_30_Tja1145_SetPNActivationState
Error code错误宏触发条件
0x01CANTRCV_30_TJA1145_E_INVALID_TRANSCEIVER函数参数中使用了非法 channel index
0x02CANTRCV_30_TJA1145_E_PARAM_POINTER函数参数中使用了NULL_PTR
0x11CANTRCV_30_TJA1145_E_UNINITCAN transceiver hardware 尚未初始化
0x21CANTRCV_30_TJA1145_E_TRCV_NOT_STANDBYCAN transceiver hardware 不在 standby mode
0x22CANTRCV_30_TJA1145_E_TRCV_NOT_NORMALCAN transceiver hardware 不在 normal operation mode
0x23CANTRCV_30_TJA1145_E_PARAM_TRCV_WAKEUP_MODE请求的 wakeup mode 非法
0x24CANTRCV_30_TJA1145_E_PARAM_TRCV_OP_MODE请求的 operation mode 不被底层收发器硬件支持
0x25CANTRCV_30_TJA1145_E_BAUDRATE_NOT_SUPPORTED选择的 baudrate 不被底层收发器硬件支持
0x40CANTRCV_30_TJA1145_E_NO_TRCV_CONTROLCAN transceiver 不受控制,保持在非法状态;这是 production error

几个E_OK语义需要单独区分。SetOpMode()的E_OK是请求被接受,不代表通知的模式一定等于请求模式。异步 SPI 下CheckWakeup()的E_OK是检查请求被接受,不代表已检测到 wakeup。唤醒是否有效,应以EcuM_SetWakeupEvent()是否被调用为准。

标准符合性、限制和偏差

驱动增加了CanTrcv_30_Tja1145_InitMemory(),用于实现独立的 BSW module memory initialization。这是 AUTOSAR 标准 API 之外的扩展,但它也是该模块初始化顺序的一部分。明确限制如下:

限制工程影响
CanTrcv_ReadTrcvTimeoutFlag和CanTrcv_ClearTrcvTimeoutFlag无实际效果底层硬件限制导致 timeout flag 相关功能不可用
不支持CanTrcv_MainFunctionDiagnostics无法区分 local errors 和 bus errors,因此不做 bus error polling
旧 SPI 类型为Spi_DataType使用 ASR 4.1.1 或更高 SPI driver 时,需要把CanTrcv_SpiDataType映射到Spi_DataBufferType

与 AUTOSAR SWS 的主要偏差如下:

偏差驱动行为
CanIf notification function 使用模块专用名称使用CanIf_30_Tja1145_TrcvModeIndication、CanIf_30_Tja1145_ConfirmPnAvailability、CanIf_30_Tja1145_ClearTrcvWufFlagIndication、CanIf_30_Tja1145_CheckTrcvWakeFlagIndication;这些函数内需要把本地CanTrcvIndex换算为 CanIf 全局 index
CanIf_CheckTrcvWakeFlagIndication总是调用即使未检测到 wakeup 也调用,避免锁住CanSM;真正检测到 wakeup 时再调用EcuM_SetWakeupEvent()
CanTrcv_SetOpMode中 POR 不触发重新初始化POR 场景要求 MCU 完整重新初始化,并在过程中调用CanTrcv_Init()
CanTrcv_GetTrcvSystemData参数去掉constTrcvSysData需要由驱动写入,因此使用可写uint32*
CanTrcvSPICommRetries和CanTrcvSPICommTimeout不是强制使用因 SWS 未说明使用位置,BSWMD multiplicity 设为0..1
CanTrcv_CheckWakeup返回值语义调整异步 SPI 下E_OK表示请求被接受,完成动作可能在MainFunction中发生
初始化模式不使用CanTrcvInitState每个 CAN transceiver channel 均初始化到NORMAL

集成关注点

这类驱动集成时,首先要把启动顺序固定下来:CanTrcv_30_Tja1145_InitMemory()在所有 CanTrcv 功能之前,CanTrcv_30_Tja1145_Init()之前 SPI driver 已初始化。如果使用 UJA1168,还要保证 SBC 处于允许 SPI 通信的模式,并满足 RESET 到 STANDBY 后的访问等待时间。其次要把 SPI 同步/异步策略和 OS 调度策略一起确认。异步 SPI 下,CANTRCV_30_TJA1145_SPI_MAINFUNCTION()、SPI sequence indication、CanTrcv_30_Tja1145_MainFunction()的周期调用共同决定 mode change、wakeup check 和自动恢复能否推进。排他区持续时间为 LONG,调用方不应假定这些 API 是短临界区函数。PN 和唤醒配置要按硬件写入时机理解。修改 PN frame ID、mask、DLC、data mask 后,底层硬件并不一定立即获得新配置;只有 POR 或SYSERR相关初始化路径才会写入 PN 数据。对于 selective wakeup,同一 channel 上CanTrcvWakeupByBusUsed与CanTrcvPnEnabled必须同时成立。最后,唤醒有效性不要直接绑定 API 返回值。CheckWakeup()在异步路径中返回E_OK只是请求确认,CheckWakeFlag()的 indication 也可能在没有 wakeup 时被调用。真正的 wakeup 事件以EcuM_SetWakeupEvent()为准,最近一次唤醒原因再由GetBusWuReason()读取。

小结

CanTrcv_30_Tja1145的核心不是简单地“把收发器切到 NORMAL”,而是在 SPI 访问、模式异步完成、PN 配置写入、ICU 唤醒脚和 EcuM/CanIf 通知之间维持一致性。集成时最值得盯住的点是初始化顺序、异步 SPI 推进机制、sleep emulation、PN 配置生效条件、SYSERR自动恢复以及CheckWakeup()返回值语义。把这些边界处理清楚,CanSM、EcuM和收发器硬件之间的状态才不会在低功耗和唤醒路径上相互误判。


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


登录 后发表评论
3条评论
只看不说话
1楼 · 2026-10-18 10:11:44

TJA1145这两年用得挺多,SPI去配置寄存器的注意点讲得很清楚。

参数党小马
2楼 · 2026-10-18 10:11:44

唤醒机制这块,不同配置的理解容易混,文章写得明白。

调参到凌晨
3楼 · 2026-10-18 10:11:44

NXP这颗收发器细节多,能这样逐项解析的确实少,好评。