AUTOSAR CAN Dirver模块说明及ETAS ISOLAR A/B配置
CAN Driver概述提供向下的硬件访问接口和向上的(CanIf)与硬件解耦的接口。
can模块为启动发送提供服务,并为通知事件调用CanIf的回调函数。
它还为控制CAN controller的状态和行为提供服务。
多个CAN controller可以被单独的CAN模块进行控制,只要他们属于同一个CAN Hardware Uint。
CAN Hardware Uint:由多个同类型的CAN controller以及一个或多个CAN RAM组成。
概念: 优先级倒置 内部优先级倒置
如果仅使用单个传输buffer,则可能会发生内部优先级倒置。由于优先级较低,存储在发送buffer中的报文会等到“总线上的流量平静下来”。在等待期间,这条报文会阻止同一个控制器的更高优先级的报文在该网段上的发送。这样就形成了优先级倒置的现象。如上图所示,这种现象应该发生在控制器内部,发送buffer中存在待发送的低优先级报文,但是protocol controller在处理其他高优先级的收发(并没有空闲下来),恰在此时,控制器内部要准备发送高优先级报文,但是却被占用buffer的低优先级报文阻止了。
————————————————
版权声明:本文为CSDN博主「大表哥汽车人」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_46481662/article/details/129325708
外部优先级倒置
假设CAN节点希望传输一个具有高优先级的连续消息包,这些消息存储在不同的消息缓冲区中。如果CAN网络上这些消息之间的帧间隙长于CAN标准定义的最小空间,则第二个节点能够开始传输较低优先级的消息。最小帧间隙由间歇场决定,即 3 个隐性位组成。在传输另一条报文期间挂起的报文在总线空闲期间被启动,最早在“间歇场”之后的位中启动。例外情况是,具有等待传输报文的节点会将“间歇场”的第三个位的显性位解释为SOF,并从第一个标识符位开始传输,而不使用第一个标识符位传输 SOF 位。CAN模块的内部处理时间必须足够短,可以以最小的帧间空间发送连续报文,以避免在上述所有情况下的外部优先级倒置。
CAN硬件单元(CAN Hardware Unit)
下图展示了一个由两个CAN controller所组成的CAN硬件单元。其中每个CAN controller连接一条物理总线。而且每个CAN controller都有对应的报文邮箱(Message Object Mailbox)
对其他模块的依赖
CAN 模块应该使用OsCounter来用于“超时检测”。是为了防止在硬件失效造成超时硬件无法做相应的响应,从而进入死循环。
等待硬件反应的CAN模块功能的阻塞时间应短于CAN Mainfunction(即Can_MainFunction_Read)触发周期,因为CAN Mainfunction不能用于该目的(不能响应计时溢出)。
CAN模块通过CanIf模块去和DEM, DET, ECUM模块进行交互。
功能描述
CAN硬件单元存在不同的类型,那么需要添加不同的CAN模块。
Driver状态机
当上电或复位,CAN模块应处于CAN_UNINIT状态
Can_Init()应改变模块状态到CAN_READY
通过调用Can_SetControllerMode(CAN_CS_STARTED)CAN 控制器会被启动。
那些对can controller有影响的寄存器设置只可以在Can_Init()中被设置。
调用Can_DeInit()函数可将模块状态改变为CAN_UNINIT.
CAN Controller状态机
四个状态:UNINIT, STOPPED, STARTED and SLEEP
can模块提供Can_Init, Can_SetBaudrate and Can_SetControllerMode这三个服务来执行必要的寄存器设置,从而使得CAN controller状态做相应的改变。
外部引起CAN Controller状态改变的事件包括:Bus-off , HW 唤醒
这些事件的识别要么是通过中断,要么通过对一个状态位的轮询来实现(在函数Can_MainFunction_BusOff or Can_MainFunction_Wakeup中)
CAN Controller会通过相应的回调函数去通知CanIf模块。状态会在这个回调函数中进行改变。
如果启用了“默认错误”检查,并且上层请求了不允许的转换,则 Can 模块应提出CAN_E_TRANSITION默认错误。当can模块执行Can_Write或调用回调函数时,是不会检查当时的实际状态的。
UNINT状态
STOPPED状态
STARTED状态
SLEEP状态
当CAN硬件支持睡眠模式,并且被触发转移到SLEEP状态,那么CAN模块可以将CAN Controller设置为SLEEP状态,且通过CAN总线是可以唤醒硬件的。
当CAN硬件不支持睡眠模式,且触发了转移到SLEEP状态,CAN模块应模拟逻辑 SLEEP 状态,仅当软件触发它转换到 STOPPED 状态时,它才会返回该状态。当逻辑SLEEP状态被激活过程中,CAN模块应保持在STOPPED状态。 CAN Controller状态的迁移
通过函数Can_SetControllerMode,可以实现状态迁移。
如果状态迁移成功,则会通过CanIf_ControllerModeIndication函数去通知上层。
一些转移是由外部事件引起的,那么则会通过CanIf_ControllerBusOff, EcuM_CheckWakeup这两个回调去通知上层。
执行Can_Init后,CAN Controller的状态会被置为STOPPED. 通过Can_SetBaudrate进行的状态迁移
如果通过调用Can_SetBaudrate函数,会引起CAN Controller的重新初始化,并且如果CAN Controller不在STOPPED状态,它会返回E_NOT_OK
如果必须进行重新初始化,那么函数Can_SetBaudrate需要保持CAN Controller在STOPPED状态。
如果必须进行重新初始话,那么函数Can_SetBaudrate确保所有引起CAN Controller入网的设置都被清掉。
通过Can_SetControllerMode进行的状态迁移
CAN模块通过CanIf_ControllerModeIndication函数通知上层状态迁移是否成功。监视状态迁移是上层模块的一个功能,但是不是CAN模块的功能。
Can_Mainfunction_Mode函数会去轮询一个CAN状态寄存器的标志位,直到状态发生变化并通过CanIf_ControllerModeIndication函数向上层进行通知。
函数Can_SetControllerMode通过系统服务GetCounterValue来进行超时检测,以防止发生阻塞。
如果标志位没有发生变化,并且CanTimeoutDuration溢出,那么函数Can_SetControllerMode会推出,并且Can_Mainfunction_Mode函数会继续对标志位的轮询。
Can_Mainfunction_Mode函数应该调用CanIf_ControllerModeIndication去通知上层状态转移成功。
通过调用函数Can_SetControllerMode(CAN_CS_STARTED),,可以让相应的CAN Controller入网。
函数Can_SetControllerMode(CAN_CS_STARTED)将等待一段时间以便使得CAN Controller完全正常工作状态,
在CAN控制器运行之前启动的传输请求会丢失。操作的唯一指标是接收 TX 确认或 RX指示。发送实体可能会收到确认超时,并且需要能够处理这种情况。 如果进入函数Can_SetControllerMode(CAN_CS_STARTED),我们发现CAN Controller没有处于STOPPED状态,那么它将检测到一个无效的状态转移。
Can_SetControllerMode(CAN_CS_STOPPED)会等待一段时间,直到CAN Controller真的关闭了。
如果CAN HW不支持休眠,那么从SLEEP到STOPPED的状态转移会从逻辑的睡眠模式返回。
Can_SetControllerMode(CAN_CS_STOPPED)会等待一段时间,直到CAN Controller处于STOPPED状态。
Can_SetControllerMode(CAN_CS_STOPPED)应取消挂起的报文。
Can driver是最低层的一部分,执行硬件访问,并向上层提供一个硬件独立的API 几个CAN控制器可以由一个CAN模块来控制,只要它们属于同一CAN硬件单元 CAN driver一共包含着5个功能,由底向上分别为: CAN L-PDU; HTH/HRH; Hardware Object; CAN Controller A,B,C...和CAN Hardware Unit。 Driver State Machine:里面只包含两种状态,一种是CAN_UNINIT,另一种是CAN_READY,可以理解为假如一个初始化信号传入CAN_UNINIT,因为它自身是不可以将信号初始化的,所以会把信号传给CAN_READY,然后CAN_READY将非初始化的信号再传给CAN_UNINIT。
EcuM模块在启动阶段初始化Can模块,在使用Can模块的任何其他函数之前,需要调用CanInit()函数。在Task或Interrupt上下段正常调用CAN驱动模块API 在L-PDU传输过程中,Can模块根据需要将L-PDU的内容ID和数据长度转换为与硬件相关的格式,并触发传输
页:
[1]