【CAN通信】Can Driver模块详细介绍

目录

前言

1.CAN Driver模块详细设计

1.1关键概念理解

1.2 Drive状态机

1.3 CAN Controller状态机

1.3.1 UNINIT状态

1.3.2 STOPPED状态

1.3.3 STARTED状态

1.3.4 SLEEP状态

1.2 CAN Controller状态切换

1.2.1 CAN_Init切换状态

1.2.2 CAN_SetBaudrate切换状态

1.2.3 Can_SetControllerMode切换状态

1.2.3 硬件事件切换状态

1.3 Can Controller初始化

1.4 L-PDU发送

1.5 发送数据的一致性

1.6 L-PDU接收

1.7 Wakeup Concept

1.8 关键API解析

1.8.1 Can_Init

1.8.2 Can_SetControllerMode

1.8.3 Can_DisableControllerInterrupts

1.8.4 Can_EnableControllerInterrupts

1.8.5 Can_CheckWakeup

1.8.6 Can_Write

2. RH850-U2A16 RS-CANFD模块简介

2.1 CAN通道数

2.2 时钟选择

2.3中断通知

2.4 MB邮箱配置

3. 总结


前言

纵向来看,CAN Driver属于CAN通信协议栈的底层驱动模块,横向来看CAN Driver属于MCAL层(microcontroller abstraction layer)。CAN Driver驱动模块执行硬件访问操作,给上层模块提供独立于硬件的API访问接口。CAN Interface模块是唯一能够直接访问CAN Driver模块的上层模块。 此外,它还提供服务来控制属于同一CAN硬件单元的CAN控制器的行为和状态。一个CAN模块可以控制多个CAN控制器,只要它们属于同一个CAN硬件单元。

为了较详细的接收CAN Driver,本文将从以下四个大的方面展开叙述:CAN Driver AUTOSAR详细设计文档详解、RH850芯片CAN模块简介、MCAL配置工具CAN Driver配置、CAN Driver模块代码分析。

完成以上分析后,能回答以下问题:

--数据怎么完成收发功能?

--怎么保证数据传输的一致性?

--CANDriver怎么实现CAN Controller状态机?

CAN总线协议推荐参考这篇博文:

CAN总线协议详解

1.CAN Driver模块详细设计

1.1关键概念理解

CAN controller: 一个CAN controller对应一路物理通道,也就是说一个ECU接了几路CAN就有几个CAN controller

CAN Hardware Unit: 一个CAN硬件单元可以由一个或多个相同类型的CAN控制器和一个或多个CAN RAM区域组成。CAN硬件单元可以是芯片上的,也可以是外部设备。CAN硬件单元由一个CAN驱动程序表示。

CAN L-PDU: Data Link Layer Protocol Data Unit数据链路层协议数据单元。也就是包含帧头的在CAN报文数据,包括报文ID,数据长度DLC,及报文数据SDU。

CAN L-SDU: Data Link Layer Service Data Unit: 数据链路层服务数据单元。也就是CAN报文的数据部分。

Hardware Object: CAN硬件对象定义为CAN硬件单元/ CAN控制器的CAN RAM内部的PDU缓冲区。一个硬件对象被定义为在CAN硬件单元的CAN RAM内的L-PDU缓冲区。理解上,一个Hardware Object对应一个邮箱Maiboxes,可以设置为发送或者接收邮箱,而Maiboxes其实就是一段硬件RAM缓存。

Harware Receive Handle(HRH): 硬件接收句柄(HRH)由CAN驱动程序定义和提供。每个HRH通常只代表一个硬件对象。HRH可用于优化软件滤波。

Hardware Transmit Handle(HTH): 硬件传输句柄(HTH)是由CAN驱动程序定义和提供的。每个HTH通常只代表一个或多个被配置为硬件传输缓冲池的硬件对象。

1.2 Drive状态机

CAN模块只有两个非常简单的状态机,CAN_UNINIT和CAN_READY状态。ECU上电或者重启后,CAN模块进入CAN_UNINIT状态,ECM调用Can_Init函数后进入CAN_READY状态。

1.3 CAN Controller状态机

CAN Driver模块为每一个CAN Controller(每一路CAN)维持一个硬件状态机,状态机有UNINIT,STOPPED,STARTED,SLEEP四种状态。对应在CanIf模块也维持一个CANIF_CS_UNINIT, CANIF_CS_STOPPED, CANIF_CS_STARTED, CANIF_CS_SLEEP四个状态的软件状态机。在状态切换期间,CAN Driver模块的状态和CanIf模块的状态可能是不一样的(传输可能失败或被延迟,因为硬件CAN控制器还没有参与总线,Can模块没有为这种情况提供通知到CanIf模块)。

  CAN Driver模块提供的Can_Init,Can_SetBaudrate,Can_SetControllerMode服务可以切换CAN Controller的状态。外部的Bus-Off事件和HW wakeup事件也本可以切换状态机。

  外部事件可以通过中断或者MainFunction轮询的方式被监控到,事件切换状态机发生在事件发生后调用的callbakc回调函数当中。

1.3.1 UNINIT状态

CAN Controller没有被初始化,CAN模块的所有的寄存器都是reset状态,CAN相关中断都被disable的。CAN Controller没有参与CAN到CAN-Bus总线活动中。

1.3.2 STOPPED状态

在这种状态下,CAN控制器被初始化,但不参与总线。此外,错误帧和ACK不能发送。

1.3.3 STARTED状态

控制器处于正常运行模式,功能完整,参与CAN总线网络。

1.3.4 SLEEP状态

  CAN硬件(收发器)区分支持休眠和不支持休眠的硬件,不同的CAN硬件的SLEEP状态不一样。

  支持休眠的CAN硬件,如果切换到SLEEP状态,CAN模块就会设置CAN Controller进入SLEEP状态,这SLEEP状态下CAN新建能够被CAN总线唤醒。

 不支持休眠的CAN硬件,如果切换到SLEEP状态,CAN模块设置一个逻辑SLEEP状态,只能通过软件切换到STOPPED状态。

CAN硬件应保持在STOPPED状态,当逻辑SLEEP状态被触发后。

1.2 CAN Controller状态切换

上层模块调用Can_SetControllerMode函数切换CAN Controller状态。CAN Driver模块成功完成状态切换后调用CanIf_ControllerModeIndication回调函数通知到上层CanIf模块。

事件触发的状态切换回调用事件触发后的回调函数通知到上层模块,例如Bus-Off后底层调用CanIf_ControllerBusOff,EcuM_CheckWakeup函数通知到CanIf和EcuM模块。

1.2.1 CAN_Init切换状态

  EcuM模块在初始化阶段调用CAN_Init函数完成CAN模块的初始化(所有硬件配置相关的寄存器的设置),CAN Controller状态从UNINIT状态切换到STOPPED状态。

1.2.2 CAN_SetBaudrate切换状态

  CAN_SetBaudrate函数的调用不会切换当前状态到另一个状态,只会当前状态完成硬件寄存器配置后又回到当前状态。如果设置波特率必须重新初始化CAN Driver模块,则切换波特率的时候CAN Controller必须在STOPPED的状态,否则返回E_NOT_OK。

 CAN_SetBaudrate函数在实际项目中基本不用。

1.2.3 Can_SetControllerMode切换状态

  上层模块调用Can_SetControllerMode函数后,Can_MainFunction_Mode周期函数回轮询CAN状态寄存器的模式标志,如果CAN Controller的模块切换成功了,Can_MainFunction_Mode函数调用CanIf_ControllerModeIndication通知到CanIf层。

Can_SetControllerMode(CAN_T_START) --> STOPPED-->STARTED:

在STOPPED状态下调用Can_SetControllerMode(CAN_T_START)函数后,设置硬件相关的寄存器,等待有限的一段时间,使的CAN Controller能够参与到CAN网络总线活动中。

在CAN Controller完全运行起来前的发送请求会丢失,在发送回调中通知到上层。上层会判断发送超时后做相应处理。

Can_SetControllerMode(CAN_T_STOP) --> STARTED-->STOPPED:

STARTED状态下调用Can_SetControllerMode(CAN_T_STOP)函数,CAN硬件会设计相关寄存器的bits,之后CAN Controller停止参与总线通信。同时未发送出去被挂起的消息会被删除。

Can_SetControllerMode(CAN_T_SLEEP) --> STOPPED-->SLEEP:

STOPPED状态下调用Can_SetControllerMode(CAN_T_SLEEP) 函数,CAN Controller进入到sleep模式。

如果CAN硬件(收发器)支持睡眠模式,Can_SetControllerMode(CAN_T_SLEEP) 函数会等待一段函数直到CAN Controller进入到SLEEP状态,同时保证CAN硬件能够被唤醒。

如果CAN硬件(收发器)不支持睡眠模式,Can_SetControllerMode(CAN_T_SLEEP) 函数会设置CAN Controller进入到逻辑sleep模式。逻辑睡眠模式将会保持直到Can_SetControllerMode(CAN_T_WAKEUP)被调用。

Can_SetControllerMode(CAN_T_WAKEUP) --> SLEEP-->STOPPD:

  如果CAN硬件不支持睡眠模式,Can_SetControllerMode(CAN_T_WAKEUP) 将从逻辑sleep模式中退出,但是不会影响到CAN Controller的硬件状态(因为硬件已经在STOPPED状态了)。

  如果CAN硬件支持睡眠模式,Can_SetControllerMode(CAN_T_WAKEUP)将会等待一段时间,直到CAN Controller进入到STOPPED状态。

1.2.3 硬件事件切换状态

CAN-Bus报文唤醒

  CAN-Bus事件发生后CAN Controller从SLEEP状态切换到STOPPED状态,并且调用EcuM_CheckWakeup回调函数通知到EcuM模块。在CAN-Bus总线接收报文唤醒状态切换过程中调用Can_SetControllerMode(CAN_T_WAKEUP)函数将返回CAN_NOT_OK。仅支持硬件睡眠唤醒的ECU有这个特性。

Bus-Off事件

  Bus-Off事件发生后CAN Controller从STARTED状态切换到STOPPED状态,Bus-Off中断或者MainFucntion中调用CanIf_ControllerBusOff回调函数通知到CanIf层za

1.3 Can Controller初始化

  EcuM模块调用Can_Init函数完成CAN硬件的初始化。

1.4 L-PDU发送

Can模块将L-PDU中的ID,DLC,和Data设置到硬件的MessageBox当中,然后触发报文发送。

Can_Write函数将会存储PduInfo参数中swPduHandle子参数直到Can模块调用CanIf_TxConfirmation(swPduHandle是CanIf_TxConfirmation的一个参数)。

L-PDU发送成功后,CAN模块调用调用CanIf_TxConfirmation通知到CanIf层。

1.5 发送数据的一致性

  CAN模块直接从上层模块拷贝数据,数据一致性由上层模块保证。

1.6 L-PDU接收

  为了防止接收到的消息丢失,一些控制器支持从一组硬件对象构建的FIFO。还有一些控制器,可以配置具有相同属性的另一个硬件对象,该硬件对象作为影子缓冲区,并在主对象繁忙时介入。

  在RX接收中断或者Can_MainFunction_Read中将接收到数据拷贝到上一层。Can模块需要保证ISR或者Can_MainFunction不被自己中断,这样在拷贝数据到上一层的时候就不会发生数据不一致的问题了。

1.7 Wakeup Concept

CAN模块处理的唤醒事件是能够被CAN controller检测到的,而不是Can Transceiver。两种可能的唤醒场景:中断唤醒和轮询唤醒事件唤醒。

唤醒事件的ISR中会调用EcuM_CheckWakeup,传递唤醒源参数通知到EcuM模块。然后ECU状态管理器将设置MCU,并通过Can接口调用Can模块,从而调用Can_CheckWakeup。

当通过轮询检测到唤醒事件时,EcuM将像之前一样通过Can接口周期性地调用Can_CheckWakeup。在这两种情况下,Can_CheckWakeup将检查是否有Can控制器检测到的唤醒,并返回结果。CAN驱动程序将通过EcuM_SetWakeupEvent通知EcuM唤醒事件。

防止错误唤醒事件的唤醒验证将由EcuM和CanIf模块在事后完成,而不需要Can模块的参与。

1.8 关键API解析

1.8.1 Can_Init

初始化CAN模块,完成CAN模块寄存器的静态配置。

1.8.2 Can_SetControllerMode

软件触发CAN Controller的状态切换。Can_SetControllerMode函数将关闭唤醒up中断,同时检查唤醒状态。Can_SetControllerMode函数将启用新状态下需要的中断。当CAN中断已经被Can_DisableControllerInterrupts功能禁用时,禁止CAN中断将不被执行。

1.8.3 Can_DisableControllerInterrupts

Can_DisableControllerInterrupts函数Disable所有的CAN Controller相关的中断。

1.8.4 Can_EnableControllerInterrupts

Can_EnableControllerInterrupts函数Enable所有的CAN Controller相关中断。

1.8.5 Can_CheckWakeup

Check当前控制器有没有唤醒发生,如果唤醒发生后调用EcuM_SetWakeupEvent通知到EcuM模块。

1.8.6 Can_Write

参数:Can_HwHandleType Hth 用于发送消息的HRH标识

Const Can_PduType * PduInfo 指向被发送的消息结构体

CanIf模块调用Can_Write函数发送报文

Can_Write函数首先Check用于发送报文的Hardware Obejcet(在Hth中被定义,可以理解未发送邮箱)是否是空闲的。如果空闲将执行以下操作,否则返回CAN_BUSY

  1. 获取互斥锁mutex
  2. 将PduInfo中的信息填充到硬件响应的寄存器当中
  3. 所有开始发送报文的操作做完
  4. 是否互斥锁mutex
  5. 返回CAN_OK

2. RH850-U2A16 RS-CANFD模块简介

2.1 CAN通道数

RH850-U2A16共有RS-CANFD单元,每个unit有8路CAN通道,总共16路CAN通道。

2.2 时钟选择

RH850-U2A16可选的时钟源有四个,可以根据实际使用的CAN通道数和波特率选择时钟源。

2.3中断通知

RH850-U2A16每一路CAN有错误中断,发送中断,发送/接收 FIFO完成中断。每个units有全局的错误中断和接收FIFO中断。

2.4 MB邮箱配置

RH850-U2A16发送邮箱配置(Payload为64字节):

--Normal模式:每个CAN通道最多可以配置64个发送邮箱MB

--TX Queue模式:4个TX Queue,每个Queue最大64个Buffers

--RX/Tx FIFO模式:最多3个FIFO,每个FIFO深度最大为128个Buffers

RH850-U2A16接收邮箱配置(Payload为64字节):

--Normal模式:每个CAN通道最多可以配置16个接收邮箱MB

--FIFO模式:8个Receive FIFO,每个FIFO最大深度128个Buffers,接收数据如果容易丢失的话就使用FIFO模式

--RX/Tx FIFO模式:最多3个FIFO,每个FIFO深度最大为128个Buffers

3. 总结

 本文详细介绍了AUTOSAR架构下CAN Driver的基本概念,并介绍了RH850-U2A芯片的CAN硬件资源。基于RH850-U2A芯片的MCAL配置,请关注博主的后续文章。

参考文档:

1.Specification of Communication Manager 4.3.1

2. RH850/U2A-EVA GroupUser’s Manual: Hardware

瑞萨官网

  • 10
    点赞
  • 52
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

汽车电子嵌入式

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值