CanDriver详解
短短几天发生了好些事情,关于人员调整,关于项目安排。唯技术不可辜负,但是也得知道,再牛的技术也就是管理层的一份数据。
分享一下对CanDriver的Autosar 规范解读,我大致看完个人感觉Can Driver中包含对象与控制器等状态机的关系主要是包含与不包含的关系,举例子来讲就是Can Driver中硬件单元与Can 控制器的关系,Can控制器与物理通道的关系;Can Driver的两种状态下,Can 控制器可以处于什么状态,不能处于什么状态,大致了解就行。我还是想说任何人的理解都比不上自己直接去阅读规范。(我选择的AutoSar CanDriver 规范是R23-11)
概念介绍
规范原话: Can driver是最低层的一部分,执行硬件访问,并向上层提供一个硬件独立的API。唯一可以访问Can模块的上层是Can If模块。Can模块 (这边Can模块就是Can Driver的意思)提供启动传输的服务,并调用CanIf模块的回调函数,以独立于硬件通知事件。此外,它还提供服务来控制属于同一CAN硬件单元的CAN控制器的行为和状态。几个CAN控制器可以由一个CAN模块来控制,只要它们属于同一CAN硬件单元。
Can Driver 对象
- Can Controller:一个CAN Controller只能去服务于一个物理通道
- Can Hardware Unit:CAN硬件单元可能由一个或多个CAN控制器组成相同类型和一个或多个CAN RAM区域。CAN硬件单元为芯片上或外部设备。表示CAN硬件单元由一个CAN驱动器驱动。
- Hardware Object: 硬件对象是在CAN控制器或CAN硬件单元的内存中定义的PDU缓冲区,用于临时存放发送或接收的CAN帧。
Can Controller
一个Can控制器正常对应一个物理通道。
Can Hardware Unit
CAN硬件单元结合了一个或多个CAN控制器,这些控制器可能是位于芯片上或作为相同类型的外部独立设备,具有通用或单独的硬件对象。
(通过共享CAN RAM,多个CAN控制器可以被组合在一起,由一个硬件单元控制)
Driver 状态机
Can驱动模块有个非常简单的状态机,只有两种状态CAN_UNINIT和CAN_READY。
在上电或者重置的时候,状态为CAN_UNINIT,初始化硬件单元内的所有控制器后,通过Can_Init函数应将模块状态更改为CAN_READY。Can_DeInit函数在取消初始化硬件单元内的所有控制器之前将模块状态更改为CAN_UNINIT。
Can Controller 状态机
就像我上一篇提到,Can Controller不同的物理硬件是有不同的设计和状态机,以下是规范里的原话翻译:每个CAN控制器都有在硬件中实现的复杂状态机。
为了简化,在本文中,状态的数量减少到以下四个基本状态描述:UNINIT,停止,启动和睡眠。
- CAN控制器状态 UNINIT(未初始化)
描述:在此状态下,CAN控制器未被初始化。所有属于CAN模块的寄存器都处于复位状态,CAN中断被禁用。此时,CAN控制器没有参与CAN总线上的通信。
行为:所有的寄存器和功能处于默认的复位状态,不处理任何CAN消息或事件。通常,系统在启动时的初始状态是UNINIT。
- CAN控制器状态 STOPPED(停止)
描述:在此状态下,CAN控制器已经初始化,但不参与CAN总线的通信。控制器不会发送错误帧或确认帧。
行为:虽然控制器已经被初始化,但它处于停止状态,因此不处理任何CAN消息,也不会向网络发送错误或确认信号。许多CAN控制器在进入“初始化”模式时会进入此状态,直到系统准备好进行正常操作。
- CAN控制器状态 STARTED(启动)
描述:控制器处于正常的操作模式,具有完整的功能,能够参与CAN网络的通信。
行为:在此状态下,CAN控制器可以发送和接收CAN消息,参与网络通信。许多CAN控制器在离开“初始化”模式时会进入此状态,表示它们准备好进行正常的操作和通信。
- CAN控制器状态 SLEEP(休眠)
描述:此状态下的硬件设置与STOPPED状态只有在支持睡眠模式的CAN硬件上有所不同。支持睡眠模式的CAN硬件可以通过CAN总线直接唤醒。
行为:在SLEEP状态下,CAN控制器处于低功耗模式,但仍可以通过CAN总线接收唤醒信号,以便从低功耗模式恢复。此模式通常用于节能操作,当系统进入低功耗状态时,控制器会进入SLEEP状态,等待唤醒信号。
1. CAN模块(driver)提供的服务:
Can_Init: 初始化CAN模块,配置与CAN控制器相关的寄存器,以确保CAN控制器处于初始状态并准备好进行通信。
状态转换:UNINIT -> STOPPED
描述:当调用 Can_Init 函数时,所有属于同一硬件单元的 CAN 控制器的状态会从 UNINIT(未初始化)转换为 STOPPED(停止)。这一过程由 Can_Init 函数触发。
操作:Can_Init 函数负责对所有 CAN 控制器进行配置,确保它们处于 STOPPED 状态。
函数调用:Can_Init
触发条件:Can_Init 函数被调用时,所有的控制寄存器会根据静态配置进行设置。
配置:Can_Init 函数会对所有 CAN 控制器进行必要的配置,确保它们能够进入 STOPPED 状态。这包括设置所有的控制寄存器。
错误处理:CAN_E_TRANSITION
条件:如果 Can_Init 函数被调用时,CAN 模块不处于 CAN_UNINIT 状态,或任何一个 CAN 控制器不处于 UNINIT 状态,Can_Init 函数应该引发错误CAN_E_TRANSITION。
解释:这意味着 Can_Init 函数只能在系统初始状态下(所有模块和控制器均未初始化)调用,否则会导致状态转换错误。错误 CAN_E_TRANSITION 表示尝试进行不允许的状态转换。
Can_SetBaudrate: 设置CAN控制器的波特率(通信速率),调整CAN总线上的数据传输速度。
Can_SetControllerMode: 改变CAN控制器的工作模式,例如从正常模式切换到休眠模式或从休眠模式切换到正常模式。通过这个服务,可以控制CAN控制器的运行状态。
Can_DeInit:
-
从 STOPPED 到 UNINIT:
这个状态转换由 Can_DeInit 函数触发。当调用 Can_DeInit 时,所有处于 STOPPED 状态的CAN控制器将被转换到 UNINIT 状态。 -
从 SLEEP 到 UNINIT:
当CAN控制器处于 SLEEP 状态时,调用 Can_DeInit 函数也会使CAN控制器转换到 UNINIT 状态。
这种转换适用于所有CAN硬件单元中的CAN控制器。
功能和行为 -
Can_DeInit 函数的作用:
Can_DeInit 函数会将所有CAN控制器的状态设置为 UNINIT。
这意味着所有CAN控制器将被准备好重新配置。在 UNINIT 状态下,CAN控制器的所有配置将被清除,并且所有的硬件寄存器将恢复到初始状态。 -
错误处理:
如果在调用 Can_DeInit 函数时,CAN模块不在 CAN_READY 状态,或者任何CAN控制器的状态是 STARTED,则应触发错误 CAN_E_TRANSITION。
这表示不能在控制器处于 STARTED 状态或模块未准备好时执行去初始化操作。
2. 状态变化的触发方式:
CAN控制器的状态变化可以由外部事件触发,主要有以下两种:
Bus-off事件: 当CAN网络检测到严重错误(如大量错误帧)导致控制器进入Bus-off状态。
硬件唤醒事件(HW wakeup event): 当CAN控制器从低功耗模式被唤醒以恢复正常通信。
这些事件(Bus-off或硬件唤醒)可以通过中断或状态位的方式指示。状态位可以在Can_MainFunction_BusOff或Can_MainFunction_Wakeup函数中通过轮询的方式检测。
寄存器设置: 在检测到这些事件后,CAN模块会进行必要的寄存器设置,以确保CAN控制器的行为符合预期(例如,在Bus-off情况下可能不进行硬件恢复)。
通知上层模块: 处理完事件后,CAN模块会通过回调函数通知CanIf模块。随后,软件状态会在这个回调函数中进行更新。
3. 错误处理机制:
开发错误检测: 如果启用了开发错误检测,并且上层软件请求了不允许的状态转换(例如试图从Bus-off状态直接转换到正常模式),CAN模块会报告开发错误CAN_E_TRANSITION。
4. 写操作与回调函数的执行:
CAN模块在执行Can_Write或调用回调函数时,不会检查CAN控制器的实际状态。这意味着即使CAN控制器处于Bus-off状态,Can_Write操作仍然会被执行。(这种设计可能是为了简化模块设计,但也要求上层模块在调用这些函数时确保控制器处于适当的状态,我不太确定是不是这样,规范里没有写) 。
L-PDU
(待定,这边规范写的我看的云里雾里的,等回头理解更深刻再来写。)
API接口
结构体
- Can_ConfigType
在 AUTOSAR 中,CAN 驱动程序的初始化数据结构是用于配置整个 CAN 模块和所有控制器的设置。这种数据结构通常包含以下内容:
总体初始化数据:
包括对整个 CAN 硬件模块的初始化配置,例如时钟设置、总线速率等。
SFR 设置(Special Function Registers):
涉及所有控制器的特殊功能寄存器设置,这些寄存器控制 CAN 硬件的特性和操作。
控制器配置结构的指针:
指向每个 CAN 控制器特定配置的指针,这些配置结构包含了对每个控制器的具体设置,如波特率、过滤器设置等。 - Can_PduType
- Can_IdType
00:CAN 消息,使用标准 CAN ID。
01:CAN FD 帧,使用标准 CAN ID。
10:CAN 消息,使用扩展 CAN ID。
11:CAN FD 帧,使用扩展 CAN ID。 - Can_HwHandleType
对于使用标准范围的CAN硬件单元:句柄通常是一个8位的整数,因此最大值为255。这意味着该硬件单元最多可以有256个不同的硬件对象(句柄范围是0到255)。
对于使用扩展范围的CAN硬件单元:如果一个CAN硬件单元的硬件对象数量超过255个,可能会使用一个扩展范围的句柄。这通常意味着句柄的范围被扩展到16位或更大,以支持更多的硬件对象。 - Can_HwType
这个类型定义了一个数据结构,用于明确提供一个硬件对象句柄(Hardware Object Handle),包括与之对应的CAN控制器、CanDrv(CAN驱动)以及具体的CAN ID。这样的数据结构通常包含以下几个部分:
硬件对象句柄(Hardware Object Handle):唯一标识一个硬件对象的句柄,用于访问或操作特定的CAN硬件对象。
CAN控制器(CAN Controller):指定哪个CAN控制器负责这个硬件对象。CAN控制器是处理CAN消息的硬件模块,可能会有多个控制器在一个系统中。
CanDrv:代表CAN驱动程序,负责硬件和应用程序之间的接口。CanDrv通常提供对CAN控制器的访问和管理功能。
CAN ID:特定的CAN标识符,用于标识CAN消息的目标或来源。CAN ID用于区分不同的CAN消息。 - Can_ErrorStateType
常见的CAN控制器错误状态包括:
错误警告(Error Warning):
状态:CAN控制器检测到错误,处于警告状态。
描述:此状态表示错误的数量已经接近CAN控制器的错误限制。通常会有一个警告标志(如LED灯)或错误计数器来指示。
错误被动(Error Passive):
状态:CAN控制器的错误计数器达到了一个较高的值,但没有达到总线关闭的阈值。
描述:在此状态下,CAN控制器仍能参与总线通信,但不会主动发起总线错误。它会尽量减少对总线的干扰。
总线关闭(Bus Off):
状态:CAN控制器检测到错误次数已经超过了最大允许值。
描述:在此状态下,CAN控制器停止参与CAN总线通信,直到被重置或重新初始化。通常需要软件干预来恢复正常操作。
总线错误(Bus Error):
状态:CAN总线检测到错误,例如数据位错误或位错误。
描述:这表示在CAN总线上发生了错误,可能需要进行错误处理和恢复操作。
硬件错误(Hardware Error):
状态:CAN控制器自身出现硬件故障。
描述:可能导致CAN控制器无法正常工作。需要检查硬件和连接情况。
接收缓冲区溢出(Receive Buffer Overflow):
状态:接收缓冲区中数据溢出。
描述:接收的数据超过了缓冲区的容量,可能导致数据丢失或错误。
发送缓冲区溢出(Transmit Buffer Overflow):
状态:发送缓冲区中数据溢出。
描述:发送缓冲区已满,新的数据不能被写入,可能导致数据发送失败。 - Can_ControllerStateType
- Can_ErrorType
- Can_TimeStampType
API函数
影响整个硬件单元的服务
- Can_Init
- Can_GetVersionInfo
- Can_DeInit
影响单个CAN控制器的服务
- Can_SetBaudrate
- Can_SetControllerMode
- Can_DisableControllerInterrupts
- Can_EnableControllerInterrupts
- Can_CheckWakeup
- Can_GetControllerErrorState
- Can_GetControllerMode
- Can_GetControllerRxErrorCounter
- Can_GetControllerTxErrorCounter
- Can_GetCurrentTime (draft)
- Can_EnableEgressTimeStamp (draft)
- Can_GetEgressTimeStamp (draft)
- Can_GetIngressTimeStamp (draft)
影响硬件句柄的服务
- Can_Write
调度函数
- Can_MainFunction_Write
- Can_MainFunction_Read
- Can_MainFunction_BusOff
- Can_MainFunction_Wakeup
- Can_MainFunction_Mode
强制接口(回调函数)
- CanIf_ControllerBusOff
文件:CanIf_Can.h
功能:通知 CanIf 模块关于 CAN 控制器进入 Bus-Off 状态的事件。
参数:与具体的 CAN 控制器相关联的 CanIf ControllerId(抽象的 CAN 控制器标识符)。
用途:用于上层模块得知 CAN 控制器由于总线错误而进入 Bus-Off 状态,并采取适当措施(如重新初始化控制器)。 - CanIf_ControllerModeIndication
文件:CanIf_Can.h
功能:通知 CanIf 模块关于 CAN 控制器状态转移的事件。
参数:与具体的 CAN 控制器相关联的 CanIf ControllerId(抽象的 CAN 控制器标识符)。
用途:用于上层模块得知 CAN 控制器的状态变更(如从 STOPPED 到 STARTED),确保正确的操作和状态管理。 - CanIf_RxIndication
文件:CanIf_Can.h
功能:指示成功接收到一个 CAN Rx L-PDU 的事件,该 L-PDU 在经过所有过滤和验证检查后。
用途:用于将接收到的 CAN 数据传递给上层模块,以便进行进一步处理或应用。 - CanIf_TxConfirmation
文件:CanIf_Can.h
功能:确认一个先前成功处理的 CAN TxPDU 的传输。
用途:用于通知上层模块一个数据包已成功传输,确保发送操作的确认和完整性。 - Det_ReportRuntimeError
文件:Det.h
功能:报告运行时错误的服务。如果配置了错误回调,该回调将被调用。
用途:用于诊断和错误处理,当系统检测到运行时错误时,触发相关的错误报告机制。 - GetCounterValue
文件:Os.h
功能:读取计数器的当前计数值(返回硬件定时器的滴答数,如果计数器由硬件驱动;如果由软件驱动,则返回软件滴答数)。
用途:用于获取计数器的当前值,以便进行时间测量或延迟处理。
可选接口
- CanIf_ConfirmCtrlPnAvailability (draft)
Header File: CanIf_CanDrv.h
Description: 该服务用于指示控制器运行在 PN (Plug-and-Play) 通信模式,参考对应的 CAN 控制器及抽象的 CanIf ControllerId。
Tags: atp.Status=draft(表示接口还在草案阶段) - CanIf_ControllerErrorStatePassive
Header File: CanIf_Can.h
Description: 从接收错误计数器 (RxErrorCounter) 和发送错误计数器 (TxErrorCounter) 值中推导错误计数阈值,并将其报告给 IdsM 作为安全事件 SEV_CAN_ERRORSTATE_PASSIVE。还准备相关的上下文数据以供安全事件使用。 - CanIf_ErrorNotification
Header File: CanIf_Can.h
Description: 从 CanError 参数推导总线错误来源(接收或发送),并报告总线错误为安全事件 SEV_CAN_TX_ERROR_DETECTED 或 SEV_CAN_RX_ERROR_DETECTED。还准备相关的上下文数据以供安全事件使用。 - CanIf_TriggerTransmit
Header File: CanIf.h
Description: 在这个 API 中,调用者模块需要检查可用数据是否适合 PduInfoPtr->SduLength 报告的缓冲区大小。如果适合,则将数据复制到 PduInfoPtr->SduDataPtr 提供的缓冲区,并更新 PduInfoPtr->SduLength 中实际复制的数据长度。如果不适合,则返回 E_NOT_OK 而不改变 PduInfoPtr。 - Det_ReportError
Header File: Det.h
Description: 报告开发错误。调用此服务以通知开发错误处理机制。 - EcuM_CheckWakeup
Header File: EcuM.h
Description: 检查给定的唤醒源。将参数传递给集成函数 EcuM_CheckWakeupHook。还可以在唤醒源的 ISR 中调用此函数,以设置 PLL 和检查可能连接到同一中断的其他唤醒源。 - EcuM_SetWakeupEvent
Header File: EcuM.h
Description: 设置唤醒事件。 - Icu_DisableNotification
Header File: Icu.h
Description: 禁用给定通道的通知。 - Icu_EnableNotification
Header File: Icu.h
Description: 启用给定通道的通知。