历史上的今天
返回首页

历史上的今天

今天是:2025年02月07日(星期五)

正在发生

2018年02月07日 | Android系统下CAN总线的驱动程序开发实现

2018-02-07 来源:eefocus

    嵌入式操作系统Android下CAN驱动程序的实现,不但需要在Linux内核中添加CAN驱动设备,还要实现Android HAL层的调用。以S5PV 210微处理器与CAN总线控制器MCP2515为例,分析了Android设备驱动原理,以及Android下CAN设备驱动程序的开发流程和方法,设计了相关的重要数据结构和代码,实现了CAN总线的驱动程序开发。

    Android是指“机器人”,由Google公司于2007年11月5日发布的基于Linux平台的开源手机操作系统,是首个为移动终端打造的真正开放和完整的移动软件。Android是一个开放平台,在嵌入式移动设备领域里具有良好的应用前景,但在不同的设备上往往有不同的硬件支持,要在Android中添加这些硬件应用,不是单纯地在Linux内核中添加驱动模块,还必须在用户空间和应用框架中添加对应的支持。
    控制器局域网络(Control Area Network,CAN),属于现场总线的范畴,是德国Bosch公司在20世纪80年代初,为解决现代汽车中众多的控制与测试仪器之间的数据交换而开发的一种串行数据通信总线。由于CAN总线的数据通信具有良好的可靠性、实时性和灵活性,CAN已经在汽车工业、航空工业、工业控制等领域中得到了广泛应用。文中以S5PV210微处理器为硬件平台,通过扩展其SPI接口,实现了CAN控制器MCP 2515在Android操作系统下的驱动程序开发。

1 系统硬件结构
    系统数据的收发都要通过CAN总线模块,CAN总线模块设计框图如图1所示,S5PV210通过SPI接口实现与MCP2515的连接,MCP2515的CAN输入输出引脚和CAN总线收发器MCP2551接在一起,构成一个完整的CAN总线收发模块。

a.JPG

    
1.1 S5PV210的SPI接口
    接口协议(Setial Peripheral Interface,SPI)是Motorola公司推出的一种使用时钟线和2根数据线传输数据的同步串行协议,即串行外设接口。S5PV210提供的SPI接口主要用于S5PV210与外围低速器件之间进行同步串行数据传输,可以实现全双工通信,传输速度最高可达5 Mbit·s-1。SPI总线接口主要用于主从分布式的通信网络,由4根线即可完成主从之间的数据通信,这4根线分别为:时钟线(SCLK)、数据输入线(SI)、数据输出线(SO)和片选线(CS),其中CS的有效与否完全由主控制器决定,时钟信号也由主控制器发出。
1.2 CAN控制器MCP2515
    MCP2515是MICroChip生产的一款独立CAN协议控制器。MCP2515支持CAN1.2、CAN2.0A、主动和被动CAN2.0B等版本的协议,能够发送和接收标准和扩展报文,它还同时具备验收过滤以及报文管理功能。图2为MCP2515的结构框图。该器件主要由3个部分组成:(1)CAN协议引擎。(2)为器件及其运行进行配置的控制逻辑和SRAM寄存器。(3)SPI协议模块。

b.JPG

    
1.3 CAN收发器MCP2551
    MCP2551是一个可容错的高速CAN器件,可作为CAN协议控制器和物理总线接口。MCP2551可为CAN协议控制器提供差分收发能力,它完全符合ISO—11898标准,且满足24 V电压要求。它的工作速率达1 Mbit·s-1。

2 CAN总线驱动程序的设计
2.1 Android操作系统驱动原理
    Android虽然使用了Linux内核,但应用程序是用Java语言开发的,所以应用程序在调用设备驱动不能像Linux应用程序那样使用系统调用,必须用Java虚拟机的JNI的本地(Native)方法。另一方面,Android要成为一个通用性强的平台,必须加强它的可移植性,这也是在Andr oid架构添加一个(HAL)硬件抽象层的原因,目的是为设备的调用提供一个更高级的封装。图3所示为Android驱动程序的技术结构。


c.JPG

    
    HAL Stub以*.so库的形式存在,在整个驱动架构中,它是驱动运行在用户空间的一部分,它往上为Dalvik虚拟机提供硬件设备的抽象接口,往下通过系统调用与Linux内核中的驱动程序交互数据,在这个过程中HAL可以对驱动程序的数据进行处理,即在Linux内核中的驱动程序只需提供一个与硬件设备传输数据的功能,而具体的操作可以由HAL完成。Android下CAN总线驱动程序的实现,不但要在Linux内核中添加CAN驱动模块,还必须在用户空间和应用框架中添加对应的支持。
2.2 CAN驱动程序实现流程
    主控制器S5PV210通过其自身的SPI接口实现与MCP2515的连接,若要使平台正常工作,软件的实现是必需的。首先要确保S5PV210的SPI口可以正常收发数据,然后利用SPI口对MCP2515的寄存器进行设置。CAN驱动程序流程图如图4所示,第一步是实现S5PV210的SPI总线的加载和声明;第二步是Linuxkernel中CAN驱动的实现,包括MCP2515的初始化、MCP2515的读写、CAN驱动的加载。第三步是Android HAL层的调用。

d.JPG

    

3 CAN总线驱动程序的实现
3.1 SPI总线加载和声明
    系统的CAN总线设备通过S5PV210的SPI总线连接,因此,需要设计SPI线驱动完成数据接收与发送。关于SPI总线驱动在Linux内核中已有良好的支持,加载并声明SPI总线就可以直接使用。Linux内核使用包装后的抽象设备驱动spi_driver,间接与原始设备驱动建立联系,并最终通过调用driver_register来注册原始设备驱动,即只需要在内核提供的spi_driver上修改调试,大幅提高了程序效率和可移植性。
    这样在结构体mop2515_driver里完成了对MCP2515驱动函数probe,remove的赋值。然后就可以通过SPI对MCP2515的寄存器进行设置来实现CAN总线驱动程序。

3.2 Linux中CAN驱动程序实现
    针对MCP2515控制器,在Linux kernel设计中采用字符设备驱动开发的形式。驱动初始化函数statICint_init MCP2515_init(),首先通过ioremap()函数将S5PV210的SPI寄存器的物理地址映射到内核空间,这样才可以在驱动程序中访问和配置S5PV210的SPI寄存器。在正确配置S5PV210的SPI寄存器后,通过register_chrdev()函数为MCP2515注册设备驱动,分配主设备号,这样在设备文件目录中创建对应的设备文件后,就可以用Linux的系统函数操作MCP2515了。而分配内存部分放在probe()函数中完成,分配空间包括为设备数据结构以及其内部的接收发送缓冲区动态分配空间。同时在probe()还需要完成申请中断工作,并初始化中断处理队列,在中断处理队列中读取CANINTF寄存器,判断是接收/发送中断的哪一个缓冲器,或者说是错误中断最后通过enable_IRQ()函数使能S5PV210相应的中断引脚。
    (1)MCP2515初始化。在实现了SPI的加载和声明后,就可以利用SPI写命令对MCP2515进行初始化。MCP2515的初始化过程为:首先将CAN控制寄存器CANCTRL的REQOP<2:0>位设置为‘100’进入配置模式,所有错误计数器被清零,进入配置模式后设置波特率,禁止所有中断,设置滤波器,清除发送接收缓存,打开中断,完成MCP2515的初始化。MCP2515初始化过程如图5所示。

e.JPG

    
    (2)MCP2515中断方式。由于CAN总线接收数据时必须与系统以中断方式交换数据,所以必须注册中断。使用的中断函数有request_irq(),free_irq(),enable_irq()和dISAble_irq(),其中函数request_irq()是给定的中断源装载中断处理程序;enable_irq()调用中断控制函数使给定的中断链有效;free_irq()释放分配给已定中断的内存;disable_irq()使定义中断链失效。具体代码为request_irq(irq_EINTO mcp2515_int,IRQF_DISABLED,device_name,NULL);其中函数request_irq()的第1个参数是设备申请的中断号;第2个参数是向系统注册的中断处理函数;第3个参数是中断处理的属性,IRQF_DISABLED表示中断处理程序是一个快速中断处理程序,被调用时屏蔽所有中断;第4个参数是中断的设备名称;第5个参数是申请时通知系统的设备标志,该函数返回值为0表示申请成功,返回负数表示失败,这样当中断发生时,在中断处理函数mcp2515_int()中读取CAN状态寄存器CANSTAT,判断RXB0是否装入报文,如果是则把报文通过SPI接收数据寄存器读取到buff er中,等待系统函数CAN_Read()读取。
    (3)MCP2515驱动程序的核心文件结构file_operations。CAN总线应用程序通过file_operations数据结构访问CAN设备驱动函数,</kem el/linux/fs.h>对file_operations数据结构中的各个变量做了详解。内核可以通过文件结构来访问驱动程序的函数,实现系统调用。
    CAN应用程序可以通过系统函数read()和write()实现读取和写入相应的数据,open()函数中完成设备的打开,close()函数中完成注销设备的工作,ioctl()函数中需要完成MCP2515控制器的初始化工作:设置控制器的工作模式、设置控制总线的波特率、清空发送缓冲区和接收缓冲区等。
3.3 CAN驱动编译
    (1)将写好的驱动源文件拷贝到/kernel/drivers/char/下,并打开Kconfig添加如下代码:
    config S5pv210_CAN
    tristate“S5pv210 can controller driver”
    depends on ARCH_S5pv210
    help
    This option enable support for CAN
    (2)在/kernel/drivers/char/Makefile文件的适当位置添加如下代码:
    obj-$(CONFIG_S5pv210_CAN)+=S5pv210-can.o
    (3)添加can功能。在/kernel/下make menuconfig DeviceDrivers→Characterdevices→S5pv210 cancontroller driver动态加载CAN驱动并保存退出。
    (4)重新编译内核。在终端进入/kernel/目录,执行make命令后在/kernel/drivers/char/下找到S5pv210_can.o,此为Linux kernel层生成的CAN设备驱动文件,kernel层驱动向下直接操作硬件,向上层也就是HAL层,提供/dev/can设备节点文件,提供驱动接口uncLOCked_ioctl()函数。

4 Android HAL层的调用
    CAN驱动程序在Android系统下的实现,硬件抽象层(HAL)的调用是关键。将Android系统移植到其他硬件平台或在Android系统中添加新硬件支持时,都需要对Android HAL层进行移植或实现在libhardware接口的头文件hardware.h中,定义了HAL实现过程中的3个通用结构体struct hw_module_t、struct hw_module_methods_t和struct hw_device_tostruct hw modules_methods_t用来表示一个模块表示方法,结构体中只包含了打开模块的函数指针。struethw_module_t用来定义一个硬件模块的信息,具体的硬件模块中,需要“继承”这个结构体。st ruct hw_device_t用来表示一个硬件设备,在一个硬件模块中可以同时包含多个硬件设备。在一个模块的HAL层开发中,具体的硬件调用流程为:(1)通过ID得到硬件模块。(2)从硬件模块得到hw_modules_t,打开得到硬件设备hw_device_t。(3)调用hw_device_t中的各个方法。(4)通过hw_device_t的close关闭设备。
    Android系统下CAN模块的实现在完成SPI总线和:MCP2515控制器的驱动后必须实现Android HAL层的调用。CAN总线的HAL层调用流程如图6所示。

f.JPG

    
    编写HAL层使用struet hw_module_t、struct hw_module_methods_t和struct hw_device_t 3个结构体来设置对CAN模块的操作方法;JNI层主要完成对HAL层提供的硬件操作方法的注册,JNI通过CAN_HARDWARE_MODULE_ID找到对应的stub,使Framework层可以使用这些方法;Setv ice层主要声明了JNI可以提供的方法,加载libcan_runtime.so,加载时会调用JNI层的JNI_OnLoad,这样JNI中的方法可以被 Service调用;编写App应用程序,使App直接调用service,完成Android HAL层的调用。之后将can文件夹放到系统development目录下。
    配置环境变量执行../build/envsetup.sh。然后执行mmm development/can编译文件。最后,重新编译内核,生成镜像文件,下载并运行操作系统。此时,CAN总线驱动程序将会加载,这样就实现了Android系统下CAN控制器MCP2515驱动程序的开发。

    5 结束语
    在分析Android驱动原理的基础上,介绍了CAN总线在Android下的实现流程,并添加了CAN驱动程序在嵌入式操作系统Android中,对其他Android平台非标准设备驱动程序的开发有一定的借鉴作用。


推荐阅读

史海拾趣

AMERICASEMI [America Semiconductor, LLC]公司的发展小趣事

AMERICASEMI公司成立于XXXX年,起初是一家专注于半导体技术研发的小型创业公司。在创立初期,公司面临着资金短缺、市场竞争激烈等诸多挑战。然而,凭借创始团队对半导体技术的深刻理解和市场需求的敏锐洞察,AMERICASEMI成功开发出一系列具有竞争力的半导体产品,并逐渐在市场中占据了一席之地。

Analog Microelectronics GmbH公司的发展小趣事

随着电子行业的快速发展,AMERICASEMI意识到只有不断创新才能在市场中立于不败之地。因此,公司加大了对研发的投入,积极引进先进的技术和设备,不断提升自身的研发能力。经过多年的努力,AMERICASEMI成功研发出多款具有创新性的半导体产品,如高性能的功率管理芯片和低功耗的传感器等,这些产品在市场上获得了广泛的认可。

旌芯半导体(GN)公司的发展小趣事

AMERICASEMI公司成立于XXXX年,起初是一家专注于半导体技术研发的小型创业公司。在创立初期,公司面临着资金短缺、市场竞争激烈等诸多挑战。然而,凭借创始团队对半导体技术的深刻理解和市场需求的敏锐洞察,AMERICASEMI成功开发出一系列具有竞争力的半导体产品,并逐渐在市场中占据了一席之地。

DURATOOL公司的发展小趣事

在电子行业,产品质量是企业生存和发展的基石。DURATOOL公司深知这一点,因此一直将品质管理作为企业发展的核心。公司建立了严格的质量管理体系,从原材料采购到产品生产、检验、包装等各个环节都进行严格把关。此外,DURATOOL公司还积极引入国际先进的质量管理理念和方法,不断提升产品质量水平。这些努力使得DURATOOL公司的产品在市场上享有良好的口碑和信誉,赢得了广大用户的信任和支持。

Elytone Electronics Co Ltd公司的发展小趣事

近年来,Elytone公司积极响应国家环保政策,致力于推动绿色发展。他们采用环保材料和清洁能源进行生产,减少了对环境的污染。同时,公司还加强了对废弃物的回收和处理工作,实现了资源的循环利用。这些举措不仅提升了公司的社会形象,也为行业的可持续发展做出了积极贡献。

创基(CBI)公司的发展小趣事

创基公司(CBI)自创立之初,便以技术创新为核心竞争力。在电子行业早期,该公司率先研发出了一种高效能、低功耗的芯片,这一技术革新极大地满足了市场对于高性能电子产品的需求。随着技术的不断完善和市场的逐步认可,CBI的芯片产品迅速占领了市场,成为行业内的佼佼者。

问答坊 | AI 解惑

C51步步学笔记

Neoic论坛的一篇很不错的帖子,详细讲述了如何使用C语言开发51系列单片机。具体内容见如下链接: C51步步学笔记…

查看全部问答>

FPGA设计时序收敛

FPGA设计时序收敛1、2…

查看全部问答>

众多NEC电子的中文资料

本帖最后由 paulhyde 于 2014-9-15 09:29 编辑 众多NEC电子的中文资料,大家快来发掘~~NEC电子提供了众多NEC电子的中文资料,大家快来发掘~~NEC电子提供了很多单片机的中文资料,大家可以自己去发掘适合自己的学习内容^______^ 主页:http://www. ...…

查看全部问答>

wince跟windows mobile有啥关系?

wince跟windows mobile有啥关系?…

查看全部问答>

熟悉TCPMP 播发器开放式软件的朋友看过来!

本人想简单修改一下TCPMP播发软件的UI界面,用EVC4.0编译时出现一堆.h找不到,上百个错误.有经验的朋友是否可以指点迷路?说个1,2,3,4.多谢!…

查看全部问答>

vc2005开发智能设备程序,如何拷贝一个ocx到模拟器,并且在模拟器注册该ocx?

vc2005开发智能设备程序,如何拷贝一个ocx到模拟器,并且在模拟器注册该ocx?…

查看全部问答>

我的目标机刷屏很慢,不知道是怎么回事?

我的目标机刷屏很慢,不知道是怎么回事? 基本上是一行一行的刷,等的人心都碎了!请大侠们帮忙! 我用的是VxWorks5.5,Tornado2.2的版本!…

查看全部问答>

C2664错误(EVC环境下)

wsprintf(sTmp,\"%d.%d.%d.%d\",(IP&0xFF),((IP>>8 ) & 0xFF),((IP>>16) & 0xFF),((IP>>24) & 0xFF)); m_ip_combo_ctrl.AddString(sTmp); 这里出现了两个错误: error C2664: \'wsprintfW\' : cannot convert parameter 1 from \'char [32]\' to ...…

查看全部问答>

【求助】索爱GPRS47求助 Xiaoliang

我用GPRS47用GPRS方式发送数据,调试中发现: AT*E2IPO=1,"220.181.28.42",80 CONNECT 到此说明已经连接到网络上了,可以进行数据发送,可是在这个数据状态下,如何回到命令状态却是实现不了 资料上的两个状态切换命令:ATO<CR>和+++AT ...…

查看全部问答>

一个关于flash的问题

mx29lv128的16M的flash,板子上电可以从flash引导系统,但是在系统中用reset指令之后系统就没反应了,系统起来之后flash起始部分内容为FF,但是奇怪的是断电重启,系统依然能够从flash启动,有人知道这是为什么吗?…

查看全部问答>