Can driver是最低层的一部分,执行硬件访问,并向上层提供一个硬件独立的API。唯一可以访问Can模块的上层是Can If模块。Can模块提供启动传输的服务,并调用CanIf模块的回调函数,以独立于硬件通知事件。此外,它还提供服务来控制属于同一CAN硬件单元的CAN控制器的行为和状态。几个CAN控制器可以由一个CAN模块来控制,只要它们属于同一CAN硬件单元。
如果只使用一个传输缓冲区,可能会发生内部优先级反转。由于优先级较低,存储在缓冲区中的消息会等待到总线上的传输数据稳定下来。在等待时间内,该消息可以防止由同一微控制器产生的更高优先级的消息来通过总线传输。
在一些CAN总线的调用中,可能会出现外部优先级反转的问题。让我们假设一个CAN节点希望传输一个具有高优先级的连续消息包,这些消息存储在不同的消息缓冲区中。如果CAN网络上这些消息之间帧的空间大于CAN标准定义的最小空间,则第二个节点能够开始对较低优先级消息的传输。最小帧空间由3个隐性位组成的间隔字段所决定的。
介绍和功能
CAN driver一共包含着5个功能,由底向上分别为: CAN L-PDU; HTH/HRH; Hardware Object; CAN Controller A,B,C...和CAN Hardware Unit。
CAN Hardware Unit:CAN Hardware可以由一个或多个相同类型的CAN Controller和一个或多个CAN RAM区域组成。
CAN Controller:一个CAN Controller只能去服务于一个物理通道。
Hardware Object:可以想成CAN Hardware Unit 在 CAN RAM区域内的一个PDU缓冲区。
HTH/HRH:全部由CAN driver提供;HRH,通常只表示一个硬件对象(用于软件过滤);HTH,通常表示一个或多个硬件对象。
CAN L-PDU:CAN协议数据单元。 由ID、DLC、Data(SDU)组成。 CAN driver可见。
结合上面的理解,可以看一下下面这幅图,会更直观一些。
我们再谈一下CAN Driver对其它模块的依赖关系。
CAN IF:首先说一下CAN IF,CanIf模块是Can驱动程序的上层。 只有上层能访问Can模块的为CanIf模块。
DET:如果“Default error Tracer”开关打开,Can Module应该能够检测到一些开发错误并报告给DET Module。
DEM:使用服务Dem_ReportErrorStatus()将生产代码相关错误报告给DEM。
ECUM:与Wakeup相关,当CAN总线发生唤醒时调用EcuMCheckWakeUp()。
CAN Dirver的功能
Driver State Machine:里面只包含两种状态,一种是CAN_UNINIT,另一种是CAN_READY,可以理解为假如一个初始化信号传入CAN_UNINIT,因为它自身是不可以将信号初始化的,所以会把信号传给CAN_READY,然后CAN_READY将非初始化的信号再传给CAN_UNINIT。
Can Controller State Machine:有四种状态(UNINIT;STOPPED;SLEEP;STARTED)。
UNINIT :CAN控制器未初始化。 所有属于CAN Module的寄存器处于Reset状态。 禁用Can Interrupt。 不加入Can总线。
STOPPED:CAN控制器被初始化但没有加入总线。
SLEEP:CAN BUS直接支持CAN Hardware,而SLEEP不同于STOPPED。
STARTED:也就是说它加入网络时,控制器处于正常模式,功能完整。
Initialization:EcuM模块在启动阶段初始化Can模块,在使用Can模块的任何其他函数之前,需要调用CanInit()函数。在Task或Interrupt上下段正常调用CAN驱动模块API 。
L-PDU Transmisson:在L-PDU传输过程中,Can模块根据需要将L-PDU的内容ID和数据长度转换为与硬件相关的格式,并触发传输。Can模块需要调用CanIf_TxConfirmation()来表示传输完成。 它应该被相应硬件资源的Tx-Interrupt服务程序调用,或者在polling mode下在Can_MainFunction_Write()中调用。一定要进行多路传输,以防止优先级的反转。
L-PDU Reception:可以理解成信号接收,具体的可以看我之前的文章。
WAKE UP:Can_CheckWakeup()将检查Can Controller是否检测到一个唤醒,并返回结果。CAN驱动程序将通过EcuM_SetWakeUpEvent()通知ECU状态管理器唤醒事件。
NOTIFICATION:模块能否只提供一个事件触发通知接口给CanIf模块,每个通知都由一个回调函数表示。