【正点原子Linux连载】第六十六章 Linux CAN驱动实验 -摘自【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.0

1)实验平台:正点原子阿尔法Linux开发板
2)平台购买地址:https://item.taobao.com/item.htm?id=603672744434
2)全套实验源码+手册+视频下载地址:http://www.openedv.com/thread-300792-1-1.html
3)对正点原子Linux感兴趣的同学可以加群讨论:935446741
4)关注正点原子公众号,获取最新资料更新
在这里插入图片描述
第六十六章 Linux CAN驱动实验

CAN是目前应用非常广泛的现场总线之一,主要应用于汽车电子和工业领域,尤其是汽车领域,汽车上大量的传感器与模块都是通过CAN总线连接起来的。CAN总线目前是自动化领域发展的热点技术之一,由于其高可靠性,CAN总线目前广泛的应用于工业自动化、船舶、汽车、医疗和工业设备等方面。I.MX6ULL自带了CAN外设,因此可以开发CAN相关的设备,本章我们就来学习一下如何驱动I.MX6U-ALPHA开发板上的CAN接口。

66.1 CAN协议简析
有关CAN协议详细内容请参考开发板资料里面由瑞萨电子编写的《CAN入门教程》,路径为:4、参考资料->CAN入门教程.pdf,本小节参考自此教程。
66.1.1 何为CAN?
CAN的全称为Controller Area Network,也就是控制局域网络,简称为CAN。CAN最早是由德国BOSCH(博世)开发的,目前已经是国际标准(ISO 11898),是当前应用最广泛的现场总线之一。BOSCH主要是做汽车电子的,因此CAN一开始主要是为汽车电子准备的,事实也是如此,CAN协议目前已经是汽车网络的标准协议。当然了,CAN不仅仅应用于汽车电子,经过几十年的发展,CAN协议的高性能和高可靠性已经得到了业界的认可,目前除了汽车电子以外也广泛应用于工业自动化、医疗、工业和船舶等领域。
以汽车电子为例,汽车上有空调、车门、发动机、大量传感器等,这些部件都是通过CAN总线连在一起形成一个网络,车载网络结构如图66.1.1.1所示:
在这里插入图片描述

图66.1.1.1 车载网络示意图
图66.1.1.1中各个单元通过CAN总线连接在一起,每个单元都是独立的CAN节点。同一个CAN网络中所有单元的通信速度必须一致,不同的网络之间通信速度可以不同。比如图66.1.1.1中125Kbps的CAN网络下所有的节点速度都是125Kbps的,整个网络由一个网关与其他的网络连接。
CAN的特点主要有一下几点:
①、多主控制
在总线空闲时,所有单元都可以发送消息(多主控制),而两个以上的单元同时开始发送消息时,根据标识符(Identifier 以下称为 ID)决定优先级。ID 并不是表示发送的目的地址,而是表示访问总线的消息的优先级。两个以上的单元同时开始发送消息时,对各消息ID 的每个位进行逐个仲裁比较。仲裁获胜(被判定为优先级最高)的单元可继续发送消息,仲裁失利的单元则立刻停止发送而进行接收工作。
②、系统的柔软性
与总线相连的单元没有类似于“地址”的信息。因此在总线上增加单元时,连接在总线上的其它单元的软硬件及应用层都不需要改变。
③、通信速度快,距离远
最高1Mbps(距离小于40M),最远可达10KM(速率低于5Kbps)。
④、具有错误检测、错误通知和错误恢复功能
所有单元都可以检测错误(错误检测功能),检测出错误的单元会立即同时通知其他所有单元(错误通知功能),正在发送消息的单元一旦检测出错误,会强制结束当前的发送。强制结束发送的单元会不断反复地重新发送此消息直到成功发送为止(错误恢复功能)。
⑤、故障封闭功能
CAN 可以判断出错误的类型是总线上暂时的数据错误(如外部噪声等)还是持续的数据错误(如单元内部故障、驱动器故障、断线等)。由此功能,当总线上发生持续数据错误时,可将引起此故障的单元从总线上隔离出去。
⑥、连接节点多
CAN 总线是可同时连接多个单元的总线。可连接的单元总数理论上是没有限制的。但实际上可连接的单元数受总线上的时间延迟及电气负载的限制。降低通信速度,可连接的单元数增加;提高通信速度,则可连接的单元数减少。
66.1.2 CAN电气属性
CAN总线使用两根线来连接各个单元:CAN_H和CAN_L,CAN控制器通过判断这两根线上的电位差来得到总线电平,CAN总线电平分为显性电平和隐性电平两种。显性电平表示逻辑“0”,此时CAN_H电平比CAN_L高,分别为3.5V和1.5V,电位差为2V。隐形电平表示逻辑“1”,此时CAN_H和CAN_L电压都为2.5V左右,电位差为0V。CAN总线就通过显性和隐形电平的变化来将具体的数据发送出去,如图66.1.2.1所示:
在这里插入图片描述

图66.1.2.1 CAN电平
CAN总线上没有节点传输数据的时候一直处于隐性状态,也就是说总线空闲状态的时候一直处于隐性。CAN网络中的所有单元都通过CAN_H和CAN_L这两根线连接在一起,如图66.1.2.2所示:
在这里插入图片描述

图66.1.2.2 CAN网络示意图
途中所有的CAN节点单元都采用CAN_H和CAN_L这两根线连接在一起,CAN_H接CAN_H、CAN_L接CAN_L,CAN总线两端要各接一个120Ω的端接电阻,用于匹配总线阻抗,吸收信号反射及回拨,提高数据通信的抗干扰能力以及可靠性。
CAN总线传输速度可达1Mbps/S,最新的CAN-FD最高速度可达5Mbps/S,甚至更高,CAN-FD不在本章讨论范围,感兴趣的可以自行查阅相关资料。CAN传输速度和总线距离有关,总线距离越短,传输速度越快。
66.1.3 CAN协议
通过CAN总线传输数据是需要按照一定协议进行的,CAN协议提供了5种帧格式来传输数据:数据帧、遥控帧、错误帧、过载帧和帧间隔。其中数据帧和遥控帧有标准格式和扩展格式两种,标准格式有11位标识符(ID),扩展格式有29个标识符(ID)。这5中帧的用途见表66.1.3.1:
帧类型 帧用途
数据帧 用于CAN节点单元之间进行数据传输的帧
遥控帧 用于接收单元向具有相同 ID 的发送单元请求数据的帧
错误帧 用于当检测出错误时向其它单元通知错误的帧
过载帧 用于接收单元通知其尚未做好接收准备的帧
间隔帧 用于将数据帧及遥控帧与前面的帧分离开来的帧
在这里插入图片描述

表66.1.3.1 帧用途
1、数据帧
数据帧由7段组成:
①、帧起始,表示数据帧开始的段。
②、仲裁段,表示该帧优先级的段。
③、控制段,表示数据的字节数及保留位的段。
④、数据段,数据的内容,一帧可发送0~8个字节的数据。
⑤、CRC段,检查帧的传输错误的段。
⑥、ACK段,表示确认正常接收的段。
⑦、帧结束,表示数据帧结束的段。
数据帧结构如图66.1.3.1所示:
在这里插入图片描述

图66.1.3.1 数据帧结构
图66.1.3.1给出了数据帧标准格式和扩展格式两种帧结构,图中D表示显性电平0、R表示隐性电平1,D/R表示显性或隐性,也就是0或1,我们来简单分析一下数据帧的这7个段。
①、帧起始
帧起始很简单,标准格式和扩展格式都是由一个位的显性电平0来表示帧起始。
②、仲裁段
仲裁段表示帧优先级,仲裁段结构如图66.1.3.2所示:
在这里插入图片描述

图66.1.3.2 仲裁段结构
标准格式和扩展格式的仲裁段不同,从图66.1.3.2可以看出,标准格式的ID为11位,发送顺序是从ID10到ID0,最高7位ID10~ID4不能全为隐性(1),也就是禁止0X1111111XXXXX这样的ID。扩展格式的ID为29位,基本ID从ID28到ID18,扩展ID由ID17到ID0,基本ID与标准格式一样,禁止最高7位都为隐性。
③、控制段
控制段由6个位构成,表示数据段的字节数,标准格式和扩展格式的控制段略有不同,如图66.1.3.3所示:
在这里插入图片描述

图66.1.3.3 控制段结构
图66.1.3.3中r1和r0为保留位,保留位必须以显性电平发送。DLC为数据长度,高位在前,DLC段有效值范围为0~8。
④、数据段
数据段也就是帧的有效数据,标准格式和扩展格式相同,可以包含0~8个字节的数据,从最高位(MSB)开始发送,结构如图66.1.3.4所示:
在这里插入图片描述

图66.1.3.4 数据段
注意,图66.1.3.4中数据段的064为bit,对应到字节就是08字节。
⑤、CRC段
CRC段保存CRC校准值,用于检查帧传输错误,标准格式和扩展格式相同,CRC段结构如图66.1.3.5所示:
在这里插入图片描述

图66.1.3.5 CRC段结构
从图66.1.3.5可以看出,CRC段由15位的CRC值与1位的CRC界定符组成。CRC值的计算范围包括:帧起始、仲裁段、控制段、数据段,接收方以同样的算法进行计算,然后用计算得到的CRC值与此CRC段进行比较,如果不一致的话就会报错。
⑥、ACK段
ACK段用来确认接收是否正常,标准格式和扩展格式相同,ACK段结构如图66.1.3.6所示:
在这里插入图片描述

图66.1.3.6 ACK段结构
从图66.1.3.7可以看出,ACK段由ACK槽(ACK Slot)和ACK界定符两部分组成。发送单元的ACK,发送2个隐性位,而接收到正确消息的单元在ACK槽(ACK Slot)发送显性位,通知发送单元正常接收结束,这个过程叫发送ACK/返回ACK。发送 ACK 的是所有接收单元中接收到正常消息的单元,所谓正常消息是指不含填充错误、格式错误、CRC 错误的消息,这些接收单元既不处于总线关闭态也不处于休眠态的所有接收单元中。
⑦、帧结束
最后就是帧结束段,标准格式和扩展格式相同,帧结束段结构如图66.1.3.7所示:
在这里插入图片描述

图66.1.3.7 帧结束段结构
从图66.1.3.7可以看出,帧结束段很简单,由7位隐性位构成。
2、遥控帧
接收单元向发送单元请求数据的时候就用遥控帧,遥控帧由6个段组成:
①、帧起始,表示数据帧开始的段。
②、仲裁段,表示该帧优先级的段。
③、控制段,表示数据的字节数及保留位的段。
④、CRC段,检查帧的传输错误的段。
⑤、ACK段,表示确认正常接收的段。
⑥、帧结束,表示数据帧结束的段。
遥控帧结构如图66.1.3.8所示:
在这里插入图片描述

图66.1.3.8 遥控帧结构
从图66.1.3.8可以看出,遥控帧结构基本和数据帧一样,最主要的区别就是遥控帧没有数据段。遥控帧的RTR位为隐性的,数据帧的RTR位为显性,因此可以通过RTR位来区分遥控帧和没有数据的数据帧。遥控帧没有数据,因此DLC表示的是所请求的数据帧数据长度,遥控帧的其他段参考数据帧的描述即可。
3、错误帧
当接收或发送消息出错的时候使用错误帧来通知,错误帧由错误标志和错误界定符两部分组成,错误帧结构如图66.1.3.9所示:
在这里插入图片描述

图66.1.3.9 错误帧结构
错误标志有主动错误标志和被动错误标志两种,主动错误标志是6个显性位,被动错误标志是6个隐性位,错误界定符由8个隐性位组成。
4、过载帧
接收单元尚未完成接收准备的话就会发送过载帧,过载帧由过载标志和过载界定符构成,过载帧结构如图66.1.3.10所示:
在这里插入图片描述

图66.1.3.10 过载帧结构
过载标志由6个显性位组成,与主动错误标志相同,过载界定符由8个隐性位组成,与错误帧中的错误界定符构成相同。
5、帧间隔
帧间隔用于分隔数据帧和遥控帧,数据帧和遥控帧可以通过插入帧间隔来将本帧与前面的任何帧隔开,过载帧和错误帧前不能插入帧间隔,帧间隔结构如图66.1.3.11所示:
在这里插入图片描述

图66.1.3.11 帧间隔结构
图66.1.3.11中间隔由3个隐性位构成,总线空闲为隐性电平,长度没有限制,本状态下表示总线空闲,发送单元可以访问总线。延迟发送由8个隐性位构成,处于被动错误状态的单元发送一个消息后的帧间隔中才会有延迟发送。
66.1.4 CAN速率
CAN总线以帧的形式发送数据,但是最终到总线上的就是“0”和“1”这样的二进制数据,这里就涉及到了通信速率,也就是每秒钟发送多少位数据,前面说了CAN2.0最高速度为1Mbps/S。对于CAN总线,一个位分为4段:
①、同步段(SS)
②、传播时间段(PTS)
③、相位缓冲段1(PBS1)
④、相位缓冲段2(PBS2)
这些段由Tq(Time Quantum)组成,Tq是CAN总线的最小时间单位。帧由位构成,一个位由4个段构成,每个段又由若干个Tq组成,这个就是位时序。1 位由多少个Tq 构成、每个段又由多少个Tq 构成等,可以任意设定位时序。通过设定位时序,多个单元可同时采样,也可任意设定采样点。各段的作用和 Tq 数如图66.1.4.1所示:
在这里插入图片描述

图66.1.4.1 一个位各段及其作用
1个位的构成如图66.1.4.2所示:
在这里插入图片描述

图66.1.4.2 一个位的构成
图66.1.4.2中的采样点是指读取总线电平,并将读到的电平作为位值的点。位置在 PBS1 结束处。根据这个位时序,我们就可以计算CAN通信的波特率了。具体计算方法,我们等下再介绍,前面提到的CAN协议具有仲裁功能,下面我们来看看是如何实现的。
在总线空闲态,最先开始发送消息的单元获得发送权。
当多个单元同时开始发送时,各发送单元从仲裁段的第一位开始进行仲裁。连续输出显性电平最多的单元可继续发送。实现过程,如图66.1.4.3所示:
在这里插入图片描述

图66.1.4.3 CAN总线仲裁过程
图66.1.4.3中,单元1和单元2同时开始向总线发送数据,开始部分他们的数据格式是一样的,故无法区分优先级,直到T时刻,单元1输出隐性电平,而单元2输出显性电平,此时单元1仲裁失利,立刻转入接收状态工作,不再与单元2竞争,而单元2则顺利获得总线使用权,继续发送自己的数据。这就实现了仲裁,让连续发送显性电平多的单元获得总线使用权。
关于CAN协议就讲到这里,关于CAN协议更详细的内容请参考《CAN入门教程》。
66.1.5 I.MX6ULL FlexCAN简介
I.MX6ULL带有CAN控制器外设,叫做FlexCAN,FlexCAN符合CAN2.0B协议。FlexCAN完全符合CAN协议,支持标准格式和扩展格式,支持64个消息缓冲。I.MX6ULL自带的FlexCAN模块特性如下:
①、支持CAN2.0B协议,数据帧和遥控帧支持标准和扩展两种格式,数据长度支持0~8字节,可编程速度,最高1Mbit/S。
②、灵活的消息邮箱,最高支持8个字节。
③、每个消息邮箱可以配置为接收或发送,都支持标准和扩展这两种格式的消息。
④、每个消息邮箱都有独立的接收掩码寄存器。
⑤、强大的接收FIFO ID过滤。
⑥、未使用的空间可以用作通用RAM。
⑦、可编程的回测模式,用于进行自测。
⑧、可编程的优先级组合。
……
FlexCAN支持四种模式:正常模式(Normal)、冻结模式(Freeze)、仅监听模式(Listen-Only)和回环模式(Loop-Back),另外还有两种低功耗模式:禁止模式(Disable)和停止模式(Stop)。
①、正常模式(Normal)
在正常模式下,FlexCAN正常接收或发送消息帧,所有的CAN协议功能都使能。
②、冻结模式(Freeze)
当MCR寄存器的FRZ位置1的时候使能此模式,在此模式下无法进行帧的发送或接收,CAN总线同步丢失。
③、仅监听模式(Listen-Onley)
当CTRL寄存器的LOM位置1的时候使能此模式,在此模式下帧发送被禁止,所有错误计数器被冻结,CAN控制器工作在被动错误模式,此时只会接收其他CAN单元发出的ACK消息。
④、回环模式(Loop-Back)
当CTRL寄存器的LPB位置1的时候进入此模式,此模式下FlexCAN工作在内部回环模式,一般用来进行自测。从模式下发送出来的数据流直接反馈给内部接收单元。
前面在讲解CAN协议的时候说过CAN位时序,FlexCAN支持CAN协议的这些位时序,控制寄存器CTRL用于设置这些位时序,CTRL寄存器中的PRESDIV、PROPSEG、PSEG1、PSEG2和RJW这5个位域用于设置CAN位时序。
PRESDIV为CAN分频值,也即是设置CAN协议中的Tq值,公式如下:

fCANCLK为FlexCAN模块时钟,这个根据时钟章节设置即可,设置好以后就是一个定值,因此只需要修改PRESDIV即可修改FlexCAN的Tq频率值。
Tq定了以后我们结合图66.1.4.1中的各个段来看一下如何设置FlexCAN的速率:
SS:同步段(Synchronization Segment),在I.MX6ULL参考手册中叫做SYNC_SEG,此段固定为1个Tq长度,因此不需要我们去设置。
PTS:传播时间段(Propagatin Segment),FlexCAN的CTRL寄存器中的PROPSEG位域设置此段,可以设置为0~7,对应1~8个Tq。
PBS1:相位缓冲段1(Phase Buffer Segment 1),FlexCAN的CRTL寄存器中的PSEG1位域设置此段,可以设置为0~7,对应1~8个Tq。
PBS2:相位缓冲段2(Phase Buffer Segment 2),FlexCAN的CRTL寄存器中的PSEG2位域设置此段,可以设置为1~7,对应2~8个Tq。
SJW:再同步补偿宽度(reSynchronization Jump Width),FlexCAN的CRTL寄存器中的RJW位域设置此段,可以设置0~3,对应1~4个Tq。
FlexCAN的CAN位时序如图66.1.5.1所示:![在这里插入图片描述](https://img-blog.csdnimg.cn/1f787187245a4b5fab1ff44c8fc14757.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5q2j54K55Y6f5a2Q,size_20,color_FFFFFF,t_70,g_se,x_16)

在这里插入图片描述

图66.1.5.1 FlexCAN位时序
根据图66.1.5.1所示,SYNC+SEG+(PROP_SEG+PSEG1+2)+(PSEG2+1)就是总的Tq,因此FlexCAN的波特率就是:

关于I.MX6ULL的FlexCAN控制器就讲解到这里,如果想更加详细的了解FlexCAN,请参考《I.MX6ULL参考手册》的“Chapter 26 Flexible Controller Area Network(FLEXCAN)”章节。

66.2 硬件原理图分析
正点原子I.MX6U-ALPHA开发板CAN接口原理图如图66.2.1所示:
在这里插入图片描述

图66.2.1 CAN原理图
图66.2.1中CAN1_TX和CAN1_RX是I.MX6ULL FlexCAN1的发送和接收引脚,对应I.MX6ULL的UART3_CTS和UART3_RTS这两个引脚。TJA1050是CAN收发器,通过TJA1050向外界提供CAN_H和CAN_L总线,R10是一个120欧的端接匹配电阻。
66.3 实验程序编写
66.3.1 修改设备树
NXP原厂提供的设备树已经配置好了FlexCAN的节点信息(FlexCAN1和FlexCAN2),但是我们还是要来看一下如何配置I.MX6ULL的CAN1节点。首先看一下I.MX6ULL的FlexCAN设备树绑定文档,打开Documentation/devicetree/bindings/net/can/ fsl-flexcan.txt,此文档描述了FlexCAN节点下的相关属性信息,这里就不做介绍了,大家自行查阅。
1、FlexCAN1引脚节点信息
首先肯定是CAN1引脚配置信息,打开imx6ull-alientek-emmc.dts,找到如下所示内容:

示例代码66.3.1.1 CAN1引脚信息
1 pinctrl_flexcan1: flexcan1grp{
2 	fsl,pins = <
3       MX6UL_PAD_UART3_RTS_B__FLEXCAN1_RX  0x1b020
4       MX6UL_PAD_UART3_CTS_B__FLEXCAN1_TX  0x1b020
5   >;
6 };
第3和第4行将UART3_RTS和UART3_CTS这两个引脚分别复用为FlexCAN1的RX和TX,电气属性都设置为0x1b020。
2、FlexCAN1控制器节点信息
打开imx6ull.dtsi文件,找到名为“flexcan1”的节点,内容如下:
示例代码66.3.1.2 imx6ull.dtsi文件flexcan1节点信息
1  flexcan1: can@02090000 {
2   	compatible = "fsl,imx6ul-flexcan", "fsl,imx6q-flexcan";
3   	reg = <0x02090000 0x4000>;
4   	interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
5   	clocks = <&clks IMX6UL_CLK_CAN1_IPG>,
6        	<&clks IMX6UL_CLK_CAN1_SERIAL>;
7   	clock-names = "ipg", "per";
8   	stop-mode = <&gpr 0x10 1 0x10 17>;
9   	status = "disabled";
10 };
注意示例代码66.3.1.2中的flexcan1节点不需要我们修改,这里只是告诉大家FlexCAN1完整节点信息。根据第2行的compatible属性就可以找到I.MX6ULL的FlexCAN驱动源文件,驱动文名为drivers/net/can/flexcan.c。第9行的status属性为disabled,所以FlexCAN1默认关闭的。在imx6ull-alientek-emmc.dts中添加使能FlexCAN1的相关操作,找到如下所示代码:
示例代码66.3.1.3 imx6ull-alientek-emmc.dtsi文件flexcan1节点信息
1 &flexcan1 {
2   	pinctrl-names = "default";
3   	pinctrl-0 = <&pinctrl_flexcan1>;
4   	xceiver-supply = <&reg_can_3v3>;
5   	status = "okay";
6 };
第3行指定FlexCAN1所使用的pinctrl节点为pinctrl_flecan1,也就是示例代码66.3.1.1中的pinctrl节点。
第4行xceiver-supply属性指定CAN收发器的电压为3.3V。
第5行将flexcan1节点的status属性改为“okay”,也就是使能FlexCAN1。
3、关闭FlexCAN2相关节点
I.MX6ULL带有两个CAN控制器:FlexCAN1和FlexCAN2,NXP官方的EVK开发板这两个CAN接口都用到了,因此NXP官方的设备树将这两个CAN接口都使能了。但是,正点原子的I.MX6U-ALPHA开发板将FlexCAN2的IO分配给了ECSPI3,所以正点原子的I.MX6U-ALPHA开发板就不能使用CAN2,否则的话ECSPI3外设就无法使用。关闭FlexCAN2节点很简单,在imx6ull-alientek-emmc.dts文件中找到名为“flexcan2”的节点,然后将其屏蔽掉即可。
重新编译设备树,我们还需要配置Linux内核,使能内核里面的FlexCAN驱动。

66.3.2 使能Linux内核自带的FlexCAN驱动
NXP官方提供的linux内核默认已经集成了I.MX6ULL的FlexCAN驱动,但是没有使能,因此我们需要配置Linux内核,打开FlexCAN驱动,步骤如下:
1、使能CAN总线
首先打开CAN总线子系统,在Linux下CAN总线是作为网络子系统的,配置路径如下:
-> Networking support
-> <*> CAN bus subsystem support //打开CAN总线子系统
如图66.3.2.1所示:
在这里插入图片描述

图66.3.2.1 使能Linux内核CAN总线子系统
2、使能Freescale系CPU的FlexCAN外设驱动
接着使能Freescale系CPU的FlexCAN外设驱动,配置路径如下:
-> Networking support
-> CAN bus subsystem support
-> CAN Device Drivers
-> Platform CAN drivers with Netlink support
-> <*> Support for Freescale FLEXCAN based chips //选中
配置如图66.3.2.2所示:
在这里插入图片描述

图66.3.2.2 使能Freescale的FlexCAN驱动
配置好以后重新编译内核,然后使用新的内核和设备树启动开发板。
66.4 FlexCAN测试
66.4.1 检查CAN网卡设备是否存在
使用新编译的内核和设备树启动开发板,然后输入如下命令:
ifconfig -a //查看所有网卡
前面我们说了,Linux系统中把CAN总线接口设备作为网络设备进行统一管理,因此如果FlexCAN驱动工作正常的话就会看到CAN对应的网卡接口,如图66.4.1.1所示:
在这里插入图片描述

图66.4.1.1 当前系统网卡信息
从图66.4.1.1可以看出,有一个名为“can0”的网卡,这个就是I.MX6U-ALPHA开发板上的CAN1接口对应的can网卡设备。如果使能了I.MX6ULL上的FlexCAN2的话也会出现一个名为“can1”的can网卡设备。
66.4.2 移植iproute2
在移植ip命令的时候必须先对根文件系统做个备份!防止操作失误导致系统启动失败!切记!笔者的血泪经验教训!
busybox自带的ip命令并不支持对can的操作,因此我们需要重新移植ip命令,也就是iproute2,iproute2源码下载地址为:https://mirrors.edge.kernel.org/pub/linux/utils/net/iproute2/。这里我们下载4.4.0版本的,笔者试过最新的版本,但是编译一直有问题。4.4.0版本的iproute2已经下载好放到了开发板光盘中,路径为:1、例程源码->7、第三方库源码-> iproute2-4.4.0.tar.gz。将iproute2-4.4.0.tar.gz发送到ubuntu中并解压,命令如下:
tar -vxzf iproute2-4.4.0.tar.gz
解压完成以后会得到一个名为“iproute2-4.4.0”的目录,进入此目录中,打开Makefile并修改。在Makefile中找到下面这行:
CC := gcc
改为
CC:=arm-linux-gnueabihf-gcc
修改完成以后如图66.4.2.1所示:
在这里插入图片描述

图66.4.2.1 Makefile修改后的CC
Makefile修改完成以后直接使用“make”命令编译,编译成功以后就会在iproute2源码的ip目录下得到一个名为“ip”的命令,如图66.4.2.2所示:
在这里插入图片描述

图66.4.2.2 编译得到的ip命令
以下操作请严格按照教程步骤来!否则可能会导致系统无法启动!
1、将交叉编译得到的ip拷贝到开发板中
首先将交叉编译到的ip命令拷贝到开发板中,先不要替换开发板根文件系统中原有的ip命令!切记!切记!先拷贝到开发板根文件系统的其他目录里面,比如我这里就拷贝到/lib/modules/4.1.15这个目录里面,命令如下:
sudo cp ip /home/zuozhongkai/linux/nfs/test_rootfs/lib/modules/4.1.15/ -f
拷贝完成以后在开发板上先执行一下新的ip命令,查看一下版本号,命令如下:
cd lib/modules/4.1.15/
./ip -V //执行新的ip命令,查看版本号
如果新编译的ip命令运行正确的话就会打印出其版本号,如图66.4.2.3所示:
在这里插入图片描述

图66.4.2.3 ip命令版本号
2、在开发板根文件系统中用新的ip命令替换原来的
注意,此步骤在开发板中执行!开发板根文件系统中原来的ip命令是busybox自带的,存放在/sbin目录下。接下来,我们使用新的ip命令替换原来的,在开发板中执行如下命令:
cd lib/modules/4.1.15/
cp ip /sbin/ip -f
拷贝完成以后将/lib/modules/4.1.15/目录下的ip命令删除掉,重启开发板,查看根文件系统是否可以正常启动!如果正常启动的话输入如下命令查看ip命令版本号:
ip -V //查看ip命令版本号
结果如图66.4.2.4所示:
在这里插入图片描述

图66.4.2.4 ip命令版本号
至此,iproute2中的ip命令就已经移植好了,稍后的can测试中我们会使用ip命令来设置can0网卡的相关信息。
3、替换ip命令以后系统启动失败怎么办?
如果在替换ip命令的时候操作失误可能会导致开发板系统启动失败,如图66.4.2.5所示:
在这里插入图片描述

图66.4.2.5 替换ip命令以后系统启动失败
从图66.4.2.5可以看出,系统启动失败,提示“Object “it” is unknown, try “ip help”.”,这是因为ip命令替换错误导致的!所以说一定要严格按照本节教程讲解的步骤替换ip命令。遇到图66.4.2.5中的错误以后解决方法很简单,把以前的ip命令替换回来就行了,这就是前面强烈建议大家对根文件系统做个备份的原因!!!最简单的方法就是用备份的根文件系统重新做一遍!
66.4.3 移植can-utils工具
can0网卡已经出现了,但是工作正不正常还不知道,必须要进行数据收发测试。这里我们使用can-utils这个工具来对can0网卡进行测试,因此要先移植can-utils到我们的开发板根文件系统中。can-utils源码我们已经下载下来放到了开发板光盘中,路径为:1、例程源码->7、第三方库源码-> can-utils-2020.02.04.tar.gz。
在ubuntu中新建一个名为“can-utils”的目录来存放can-utils的编译结果。然后将can-utils源码拷贝到ubuntu中并解压,命令如下:
tar -vxzf can-utils-2020.02.04.tar.gz //解压
解压完成以后得到一个名为“can-utils-2020.02.04”的目录,这个即使can-utils源码,进入到此目录中,然后配置并编译,命令如下:
cd can-utils-2020.02.04 //进入can-utils源码目录
./autogen.sh //先执行autogen.sh,生成配置文件configure
./configure --target=arm-linux-gnueabihf --host=arm-linux-gnueabihf --prefix=/home/zuozhongkai/linux/IMX6ULL/tool/can-utils --disable-static --enable-shared //配置
make //编译
make install
编译完成以后就会前面创建的“can-utils”目录下就会多出一个“bin”目录,此目录下保存着can-utils的各种小工具,如图66.4.3.1所示:
在这里插入图片描述

图66.4.3.1 can-utils小工具集
将图66.4.3.1中的所有can-utils小工具全部拷贝到开发板根文件系统下的/usr/bin目录下,命令如下:
sudo cp bin/* /home/zuozhongkai/linux/nfs/rootfs/usr/bin/ -f
拷贝完成以后我们就可以使用这些小工具来测试CAN了。
66.4.4 CAN通信测试
正点原子的I.MX6U-ALPHA开发板上只有一个CAN接口,因此我们还需要另外一个CAN设备,可以使用另一块I.MX6U-ALPHA开发板,或者USB转CAN设备,这里我两个都测试一下。
1、两块ALPHA开发板连接测试
准备两块ALPHA开发板,然后将CAN接口连接起来,ALPHA开发板上CAN接线端子如图66.4.4.1所示:
在这里插入图片描述

图66.4.4.1 ALPHA开发板FlexCAN1接口
将两个开发板的CAN接口连接起来,注意,CAN_H接CAN_H,CAN_L接CAN_L!
①、收发测试
首先使用ip命令设置两个开发板的CAN接口,首先设置CAN接口的速度,输入如下所示命令:
ip link set can0 type can bitrate 500000
上述命令设置can0速度为500Kbit/S,两个CAN设备的速度要设置为一样的!速度设置好以后打开can0网卡,命令如下:
ifconfig can0 up //打开can0
can0打开以后就可以使用can-utils里面的小工具进行数据收发测试了。一个开发板用来接收数据,一个用来发送数据,接收数据的开发板使用candump命令,输入如下命令:
candump can0 //接收数据
发送数据的开发板使用cansend命令向接收单元发送8个字节的数据:0X11、0X22、0X33、0X44、0X55、0X66、0X77、0X88。输入如下命令:
cansend can0 5A1#11.22.33.44.55.66.77.88
cansend命令用于发送can数据,“5A1”是帧ID,“#”号后面的“11.22.33.44.55.66.77.88”就是要发送的数据,十六进制。CAN2.0一次最多发送8个字节的数据,8个字节的数据之间用“.”隔开。
如果CAN工作正常的话接收端就会接收到上面发送过来的这8个字节的数据,如图66.4.4.2所示:
在这里插入图片描述

图66.4.4.2 接收到的数据
从图66.4.4.2可以看出,接收端的can0接口接收到了8个字节的数据,帧ID为5A1,说明CAN驱动工作正常。
如果要关闭can0的话输入如下命令:
ifconfig can0 down
②、回环测试
如果要在一个板子上进行CAN回环测试,按照如下命令设置CAN:
ifconfig can0 down //如果can0已经打开了,先关闭
ip link set can0 type can bitrate 500000 loopback on //开启回环测试
ifconfig can0 up //重新打开can0
candump can0 & //candump后台接收数据
cansend can0 5A1#11.22.33.44.55.66.77.88 //cansend发送数据
如果回环测试成功的话那么开发板就会收到发送给自己的数据,如图66.4.4.3所示:
在这里插入图片描述

图66.4.4.3 CAN回环测试结果
2、USB转CAN卡测试
接下来我们使用一个USB转CAN卡与正点原子的I.MX6U-ALPHA开发板进行数据收发测试,这里我使用的是周立功出品的USBCAN设备,型号为“USBCAN-I+”,如图66.4.4.4所示:
在这里插入图片描述

图66.4.4.4 USBCAN设备
首先设置开发板的can0接口,速度为500Kbit/S,命令如下:
ip link set can0 type can bitrate 500000 //设置can0,速率500Kbit
ifconfig can0 up //打开can0
candump can0 & //candump后台接收数据
按照USBCAN说明手册设置好USB CAN卡,速度设置为500Kbit,首先通过USBCAN向ALPHA发送数据,发送的数据如图66.4.4.5所示:
在这里插入图片描述

图66.4.4.5 USBCAN发送的数据
从图66.4.4.5可以看出,USBCAN发送了5帧数据帧,帧类型为标准帧,这5帧数据都是一样的,帧ID分别为0~4。开发板CAN接口工作正常的话就会接收到这5帧数据,接收到的数据如图66.4.4.6所示:
在这里插入图片描述

图66.4.4.6 开发板CAN接口接收到的数据
从图66.4.4.6可以看出,开发板can0接口接收到了5帧数据,和USBCAN发送的一致。也可以通过开发板向USBCAN发送数据,输入如下命令发送数据:
cansend can0 5A1#11.22.33.44.55.66.77.88
USBCAN接收到数据,如图66.4.4.7所示:
在这里插入图片描述

图66.4.4.7 USBCAN接收到的数据
关于CAN驱动就讲解到这里,如果要编写CAN总线应用的话就直接使用Linux提供的SocketCAN接口,使用方法类似网络通信,本教程不讲解应用编程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值