您的位置首页>企业动态>

Linux环境下实现基于ARM9的CAN总线通信

导读大家好,我是极客范的本期栏目编辑小友,现在为大家讲解Linux环境下实现基于ARM9的CAN总线通信问题。基于ARM9的CAN总线通信在Linux环境下的

大家好,我是极客范的本期栏目编辑小友,现在为大家讲解Linux环境下实现基于ARM9的CAN总线通信问题。

基于ARM9的CAN总线通信在Linux环境下的实现。

1.引言CAN(Controller Area Network,控制器局域网)总线最早是由德国BOSCH公司提出的,它实现了汽车环境中微控制器之间的通信,并在车辆上的ECU(电子控制装置)之间交换信息,从而形成汽车电子控制网络。由于其成本低、实时性好、容错性高、设计灵活等特点,被广泛应用于各个工业领域,被公认为最有前途的现成总线之一。同时,随着ARM(Advanced RISC Machines)芯片和嵌入式Linux操作系统的成熟和完善,CAN通信的发展更加便捷,应用也更加广泛。本文将从硬件和软件两个方面介绍一种基于EP9315的Linux环境下的CAN总线通信方式。2.硬件介绍和接口实现。本次设计选用了Cirrus Logic公司推出的EP9315处理器和飞利浦公司推出的SJA1000独立CAN控制器。简要介绍了以下两种芯片,然后详细描述了CAN接口的硬件电路设计。2.1 EP9315和SJA1000芯片简介EP9315是EP93XX系列微处理器的旗舰产品。先进的ARM920T微处理器内核运行在200MHz(工业条件下推荐184MHz),支持Linux、Windows CE等操作系统的内存管理单元MMU,16KB指令缓存和16KB数据缓存,可以为现有程序和数据提供零等待时间,或者通过锁存器的方式保证关键指令和数据的访问无延迟。EP9315集成了MaverickKey数学协处理器和MaverickKey硬件可编程ID。前者显著提高了ARM920T的浮点、整形运算和信号处理能力。同时,它还拥有丰富的集成外设接口,包括1/10/100Mbps以太网MAC和3通道USB2.0全速主端口。SPI、I S、AC'97的串行接口、PCMCIA接口、光栅/液晶接口、图像加速器、带12位A/D转换器的触摸屏接口、键盘接口、UART接口、丰富的GPIO、4组32位SDRAM无缝连接等。SJA1000是一款高性能CAN控制器,支持BasicCAN和PeliCANl模式,并提供英特尔和摩托罗拉寻址模式。地址线和数据线分时复用。SJA1000基于寄存器寻址,可以通过读写寄存器进行操作。2.2硬件接口电路设计EP9315拥有16个增强型GPIO。通过配置PADR和PADDR寄存器,EGPIO2可以控制SJ1000的ALE地址锁存信号,EGPIO3可以接收SJA1000的中断信号,并且可以配置中断类型。由于SJA1000的数据线和地址线是时分复用的,因此RD、WR和CS信号在发送地址时必须无效,但仅在发送或读取数据时有效。因此,逻辑是通过组合CPLD(EPM7032芯片)或部分逻辑门实现的,地址运算(nCS5_PHYBASE0x50000000)和数据运算分别选择两个BANK。在读取SJA1000时,EP9315首先通过CS选通SJA1000,通过EGPIO2使ALE有效,锁存地址,CS5通过CPLD选通FLASH的BANK5,将地址存储在映射的BANK5区域,然后使ALE 0取消数据锁存,最后将EP9315的RD信号置低,通过74LV32后使SJA1000的读取信号有效,从而完成读取操作。在写操作中,SJA1000同样被选通,ALE被使能,地址被发送并锁定在BANK5,然后ALE被取消,EP9315的WR信号被置低,SJA1000的WR信号通过74LV32被使能,然后数据被发送到映射的BANK3,数据被写入SJA1000完成写操作。3.软件分析与实现本文采用内核版本为2.4.21-rmk1的Linux系统,搭建ARM-LINUX交叉编译环境,采用动态模块加载的方法开发驱动程序。模块化的优点是可以将内核镜像大小保持在最小,并且具有最大的灵活性,便于在不重新编译和引导内核的情况下检查新的内核代码。Shell用户应用的开发主要采用GDB远程调试技术。调试环境由主机GDB和目标调试存根组成,它们通过串口或TCP连接。驱动程序和应用程序的总体流程图如图2所示。

图2驱动程序和应用程序的整体流程。

Linux下CAN驱动的实现CAN设备是一个字符设备,以字节为单位逐个执行I/O操作。当请求读写时,实际的硬件输入/输出立即发生。字符设备的缓存是可选的,不支持随机访问。应用程序可以通过标准系统调用打开、读取、写入和关闭字符设备,如访问字节流(如文件)。驱动程序主要由以下四个关键环节组成:(1)模块初始化module_init(Mysja1000_init)模块的初始化功能负责注册模块提供的任何设施。module_init的使用是强制的,这个宏将在模块的目标代码中添加一个特殊的段来解释内核初始化函数的位置。没有这个定义,初始化函数将永远不会被调用。模块正常初始化时,CAN设备和设备中断的注册,SJA1000芯片中相关寄存器的配置,以及EP9315 EGPIO端口的初始化设置都在初始化函数中完成,利用函数Void * _ _ Ioremap(无符号长Phys _ Addr,无符号长Size,无符号长Flags)将IO地址空间映射到内核的虚拟地址空间。

去,这样就可以像读写RAM那样读写IO内存资源了。

⑵服务于I/O请求的子程序这部分程序又被称为是驱动程序的上半部分。调用这部分程序是由于系统调用的结果。当该部分程序执行时,系统仍认为是与进行调用的进程属于同一个进程,只是由用户态变成了核心态。由于此部分程序是驱动程序与应用程序的接口,所以必须通过Linux下的一个关键的数据结构file_operaTIons来实现该文件操作接口。file_operaTIons结构中的成员几乎全是函数指针,实质上是一个函数跳转表。例如can_open入口点用来打开CAN设备准备进行I/O操作;can_read入口点用来实现接收CAN数据帧;can_write入口点用来实现发送CAN数据帧;can_ioctl入口点提供了一种执行CAN设备特定操作的方法,通过ioctl来实现对SJA1000寄存器的读写操作,使用户根据需要方便的配置SJA1000状态等等。⑶中断服务子程序这部分程序又被称为是驱动程序的下半部分。Linux系统负责接收硬件中断,再由系统调用中断服务子程序,而不是直接从ARM的中断向量表中调用这部分程序。在模块初始化时已经利用request_irq( )函数注册了设备中断,所以当IRQ(中断请求)产生时,ISR(中断服务例程)运行。在中断服务程序中,首先要读取SJA1000的中断寄存器IR的值,识别中断源,比如当接收中断位RI为1则说明是接收中断,进而调用接收函数来接收数据。当CPU读取这个只读存储器时,除了RI位外的所有位都被复位。⑷缓冲区操作SJA1000内部设有发送缓冲器TXB(13个字节),接收缓冲器RXB(13个字节)和RXFIFO(64个字节)。其中TXB是CPU和BSP(位流处理器)之间的接口,存储发送到CAN网络上的完整报文。接收缓冲器是接收过滤器和CPU之间的接口,用来接收和存储CAN总线上的报文,RXB是RXFIFO的一个窗口,可被CPU访问。为了提高收发效率,在驱动中开辟软件缓冲区,大小可以根据需要设置,将大量数据经过软件缓冲区后再进行处理。在操作软件缓冲区时,采用生产者/消费者模型,分别设定数据存入与读出的指针,并且利用memcopy函数完成对帧数据的操作。比如读取数据时,首先在操作模式下将SJA1000中起始地址为16的RXB数据读入一个数组,经过一些必要判断,再将此数组中的数据由memcopy函数传入指定的软件缓冲区。硬件缓冲与软件缓冲间一次传递一帧数据,帧有标准帧与扩展帧之分。3.2 Shell应用程序的实现 Shell应用程序主要是为用户提供一系列方便直观的接口,使得用户不必了解硬件工作的细节,不必研究驱动的具体实现,而仅仅根据自身的需要,通过一些简单明了的命令来完成所要求的任务。本文就将在Shell应用程序中实现以下命令功能:init初始化寄存器,rsja读取寄存器值,wsja写寄存器,gfrm收数据帧,sfrm发数据帧,conf配置滤波器,help帮助,exit退出。在主函数main中,通过int open(const char * filename, int mode)函数打开CAN设备,得到一个文件句柄fd,将此句柄传递给shell函数,这样就可以在各个命令函数中对CAN设备进行操作,比如可以在函数int write_sja1000(int fd,unsigned char addr, unsigned char value)中使用ioctl(fd,SJA_WRITE,&reg_data)来实现对SJA1000寄存器的写操作。在shell应用程序中,可以设定一个字符数组char cmd[5],通过fgets(cmd,5,stdin)来接收用户键入的命令,再经过strcmp函数辨认出用户的命令类型,执行相关操作。为避免输入缓冲区出现垃圾导致命令识别出现错误,需要及时清空输入缓冲,而当gcc中fflush函数无效的情况下,则可以通过while((c=getchar())!='n'&&c!=EOF){ }来清空输入缓冲。完成了所有驱动以及应用程序的编写后,用Makfile文件制定编译规则,然后根据规则进行编译,调试成功后可将二进制代码通过超级终端下载到板子运行,至此结束所有工作。4.结语本文提供了一种EP9315与CAN控制器SJA1000的接口方案,详细分析了Linux操作系统下驱动与应用程序的原理及开发流程,实现了CAN设备通信,并在实际应用和测试中证明了该设计的正确性和可靠性。由于嵌入式Linux的众多优势以及CAN的实时性,易用性,可靠性等优点,它们将在工业控制及生活的各个领域具有更广泛的应用前景。本文作者创新点:利用EP9315与SJA1000实现CAN总线通信,完成了由硬件连接,底层驱动以致上层应用软件的所有工作,利用软件方便稳定的控制CAN通信。

Linux环境下实现基于ARM9的CAN总线通信

1. 引言CAN(Controller Area Network)总线最早是由德国BOSCH公司提出,实现汽车环境中的微控制器通讯,在车载各电子控制装置ECU之间交换信息,形成汽车电子控制网络。由于其具有成本低,实时性好,容错性高,设计灵活等特点,目前已被广泛的应用于各种工业领域,被公认为是最有前途的现成总线之一。与此同时,随着ARM(Advanced RISC Machines)芯片及嵌入式Linux操作系统的成熟与完善,使得CAN通信的开发更为便利,应用更为广泛。本文就将从硬件,软件两方面介绍一种在Linux环境下实现基于EP9315的CAN总线通信方式。2. 硬件介绍及其接口实现 本设计选用的是Cirrus Logic公司推出的EP9315处理器及PHILIPS公司推出的SJA1000独立CAN控制器。下面先对两款芯片作简要介绍,再对CAN接口硬件电路设计作详细说明。2.1 EP9315及SJA1000芯片简介EP9315是EP93XX系列微处理器的旗舰产品。内嵌先进的运行于200MHz(工业条件下推荐运行184MHz)的ARM920T微处理器核,以及支持Linux,Windows CE等操作系统的存储器管理单元MMU,16KB指令高速缓存和16KB数据高速缓存可为现有的程序和数据提供零等待时间,或者以锁存的方式确保对关键指令和数据的无延迟存取。EP9315内部集成了MaverickCrunch 数学协处理器和MaverickKey 硬件可编程ID,前者显著提高了ARM920T的浮点,整形运算与信号处理能力,同时它还具有丰富的集成外设接口,包括1/10/100Mbps以太网MAC,3通道USB2.0全速主口,SPI、I S和AC’97串行接口,PCMCIA接口,Raster/LCD接口,图像加速器,带12位A/D转换器的触摸屏接口,键盘接口,UART接口,丰富的GPIO,支持4组32位SDRAM的无缝连接等。SJA1000是一款高性能的CAN控制器,支持BasicCAN和PeliCANl两种工作模式,提供INTEL和Motorola两种寻址方式,地址线和数据线分时复用,SJA1000基于寄存器编址,可以通过读写寄存器来操作它。2.2 硬件接口电路设计EP9315带有16个增强型GPIO,可以通过配置PADR、PADDR寄存器使得EGPIO2控制SJ1000的ALE址锁存信号,EGPIO3接收SJA1000的中断信号,并且可以配置中断类型。由于SJA1000的数据线与地址线分时复用, 当在送地址时,RD、WR、CS信号必须无效,送数据或读数据时,RD、WR、CS信号才有效,因此结合CPLD(EPM7032芯片)或是一些逻辑门来实现该逻辑,并片选两个BANK来分别用于地址操作(nCS5_PHYBASE 0x50000000)和数据操作(nCS3_PHYBASE 0x30000000)。当读SJA1000时,首先由EP9315通过CS选通SJA1000,通过EGPIO2使得ALE有效,锁存地址,并由CS5经CPLD选通FLASH的BANK5,将地址存入映射后的BANK5区域,然后使得ALE为0取消地址锁存,最后置低EP9315的RD信号,经74LV32后使得SJA1000的读信号有效,完成读操作;写操作时,同理选通SJA1000,使能ALE,发送地址并将其锁存在BANK5,然后取消ALE,置低EP9315的WR信号,通过74LV32使能SJA1000的WR信号,接着发送数据置映射后的BANK3,将数据写入SJA1000,完成写操作。3. 软件分析及实现本文采用Linux系统,内核版本为2.4.21-rmk1,搭建ARM-LINUX交叉编译环境同时利用动态模块加载法来进行驱动开发。模块化的优点在于能将内核映像尺寸保持在最小,并且具有最大的灵活性,便于检验新的内核代码而不需重新编译,引导内核。Shell用户应用程序的开发主要采用了GDB远程调试技术,该调试环境由宿主机GDB和目标机调试stub共同构成,两者通过串口或TCP连接。驱动程序与应用程序的整体流程图如图2所示。

图2 驱动程序与应用程序的整体流程

3.1 Linux下CAN驱动的实现CAN设备属于字符型设备,是以字节为单位逐个进行I/O操作的设备,在对它发出读写请求时,实际的硬件I/O紧接着就发生了。字符型设备的缓存是可有可无的,而且也不支持随机访问。应用程序可以通过标准系统调用像访问字节流(类似文件)一样来打开,读,写,关闭字符型设备。驱动程序主要由一下4个关键环节组成:⑴模块的初始化 module_init(Mysja1000_init)模块的初始化函数负责注册模块所提供的任何设施。module_init的使用是强制性的,这个宏会在模块的目标代码中增加一个特殊的段,用于说明内核初始化函数所在的位置。没有这个定义,初始化函数永远不会调用。当模块正常初始化时,在初始化函数中完成了对CAN设备以及设备中断的注册,对SJA1000芯片中相关寄存器的配置,对EP9315中的EGPIO口的初始化设置,并且利用函数void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags) 将IO地址空间映射到内核的虚拟地址空间上去,这样就可以像读写RAM那样读写IO内存资源了。

⑵服务于I/O请求的子程序这部分程序又被称为是驱动程序的上半部分。调用这部分程序是由于系统调用的结果。当该部分程序执行时,系统仍认为是与进行调用的进程属于同一个进程,只是由用户态变成了核心态。由于此部分程序是驱动程序与应用程序的接口,所以必须通过Linux下的一个关键的数据结构file_operaTIons来实现该文件操作接口。file_operaTIons结构中的成员几乎全是函数指针,实质上是一个函数跳转表。例如can_open入口点用来打开CAN设备准备进行I/O操作;can_read入口点用来实现接收CAN数据帧;can_write入口点用来实现发送CAN数据帧;can_ioctl入口点提供了一种执行CAN设备特定操作的方法,通过ioctl来实现对SJA1000寄存器的读写操作,使用户根据需要方便的配置SJA1000状态等等。⑶中断服务子程序这部分程序又被称为是驱动程序的下半部分。Linux系统负责接收硬件中断,再由系统调用中断服务子程序,而不是直接从ARM的中断向量表中调用这部分程序。在模块初始化时已经利用request_irq( )函数注册了设备中断,所以当IRQ(中断请求)产生时,ISR(中断服务例程)运行。在中断服务程序中,首先要读取SJA1000的中断寄存器IR的值,识别中断源,比如当接收中断位RI为1则说明是接收中断,进而调用接收函数来接收数据。当CPU读取这个只读存储器时,除了RI位外的所有位都被复位。⑷缓冲区操作SJA1000内部设有发送缓冲器TXB(13个字节),接收缓冲器RXB(13个字节)和RXFIFO(64个字节)。其中TXB是CPU和BSP(位流处理器)之间的接口,存储发送到CAN网络上的完整报文。接收缓冲器是接收过滤器和CPU之间的接口,用来接收和存储CAN总线上的报文,RXB是RXFIFO的一个窗口,可被CPU访问。为了提高收发效率,在驱动中开辟软件缓冲区,大小可以根据需要设置,将大量数据经过软件缓冲区后再进行处理。在操作软件缓冲区时,采用生产者/消费者模型,分别设定数据存入与读出的指针,并且利用memcopy函数完成对帧数据的操作。比如读取数据时,首先在操作模式下将SJA1000中起始地址为16的RXB数据读入一个数组,经过一些必要判断,再将此数组中的数据由memcopy函数传入指定的软件缓冲区。硬件缓冲与软件缓冲间一次传递一帧数据,帧有标准帧与扩展帧之分。3.2 Shell应用程序的实现 Shell应用程序主要是为用户提供一系列方便直观的接口,使得用户不必了解硬件工作的细节,不必研究驱动的具体实现,而仅仅根据自身的需要,通过一些简单明了的命令来完成所要求的任务。本文就将在Shell应用程序中实现以下命令功能:init初始化寄存器,rsja读取寄存器值,wsja写寄存器,gfrm收数据帧,sfrm发数据帧,conf配置滤波器,help帮助,exit退出。在主函数main中,通过int open(const char * filename, int mode)函数打开CAN设备,得到一个文件句柄fd,将此句柄传递给shell函数,这样就可以在各个命令函数中对CAN设备进行操作,比如可以在函数int write_sja1000(int fd,unsigned char addr, unsigned char value)中使用ioctl(fd,SJA_WRITE,&reg_data)来实现对SJA1000寄存器的写操作。在shell应用程序中,可以设定一个字符数组char cmd[5],通过fgets(cmd,5,stdin)来接收用户键入的命令,再经过strcmp函数辨认出用户的命令类型,执行相关操作。为避免输入缓冲区出现垃圾导致命令识别出现错误,需要及时清空输入缓冲,而当gcc中fflush函数无效的情况下,则可以通过while((c=getchar())!='n'&&c!=EOF){ }来清空输入缓冲。完成了所有驱动以及应用程序的编写后,用Makfile文件制定编译规则,然后根据规则进行编译,调试成功后可将二进制代码通过超级终端下载到板子运行,至此结束所有工作。4.结语本文提供了一种EP9315与CAN控制器SJA1000的接口方案,详细分析了Linux操作系统下驱动与应用程序的原理及开发流程,实现了CAN设备通信,并在实际应用和测试中证明了该设计的正确性和可靠性。由于嵌入式Linux的众多优势以及CAN的实时性,易用性,可靠性等优点,它们将在工业控制及生活的各个领域具有更广泛的应用前景。本文作者创新点:利用EP9315与SJA1000实现CAN总线通信,完成了由硬件连接,底层驱动以致上层应用软件的所有工作,利用软件方便稳定的控制CAN通信。

技术专区 IBM调研报告: 传统企业逆袭后,是否会打破原有平衡?天时地利人和,兆易创新深度布局存储芯片产业链EMC设计元器件选择及电路设计很关键“通用芯片”:解决“5G时代”的新问题中国半导体企业如何走出自己道路?且看排行榜TOP50
郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。