RTLinux下CAN接口卡驱动程序开发

2009-07-02 08:36
新媒体研究 2009年10期

张 鹏 郭 芹

[摘要]介绍RTLinux下的设备驱动模型,以PCI接口的CAN卡为例详细描述了RTLinux下开发设备驱动程序的一般方法。并通过RTLinux与Linux下设备驱动程序开发过程的对比,描述两者的异同,给出将Linux下设备驱动源码更改为RTLinux设备驱动的方法。

[关键词]RTLinux 设备驱动 CAN

中图分类号:TP3文献标识码:A文章编号:1671-7597(2009)0520006-02

一、引言

在飞行器控制、机器人控制、数控加工等应用场合,传统的Windows、

Linux等桌面操作系统已不能满足这种高实时性的应用需求,越来越多的控制器开始采用实时操作系统。RTLinux是一个源码开放的实时操作系统,得到了广泛的应用。对于采用RTLinux作为控制系统软件开发平台的设计者来说,所面临的一大问题是设备厂商一般不会提供设备在RTLinux下的驱动程序,需要用户自行开发。如何开发RTLinux下的设备驱动程序,为RTLinux下的实时应用程序提供操作接口,成为我们利用RTLinux开发控制系统首先要解决的问题。有些情况下设备厂商会提供Linux下驱动源码,我们又该如何将其修改后应用到RTLinux平台上。CAN总线是工业控制中应用十分广泛一种现场总线,CAN接口卡也是在实时控制经常用到的典型设备。本文结合PCI接口CAN控制器的驱动设计实例,详细介绍RTLinux下设备驱动程序的开发步骤,并与Linux下设备驱动程序的开发做出对比。

二、RTLinux设备驱动程序结构

RTLinux是在Linux的基础上对进程调度、中断处理等方面进行了改进,保证了系统的实时性,使实时任务能在限定的时间内得到响应。在RTLinux中,设备驱动程序是以模块的形式存在于内核中的,用户通过insmod命令将驱动模块载入内核。RTLinux提供了符合POSIX标准的设备驱动设计方式,其设计方法与Linux下设备驱动程序的开发类似。所有的设备在RTLinux中都被当作一个文件来看待,所有对设备的操作都可以通过对设备文件进行操作来完成。Linux中的I/O子系统向内核中的其他部分提供了统一标准的设备接口file_operations,在RTLinux中,系统提供了类似的接口rtl_file_operations。在驱动程序初始化时通过rtl_register_chrde

v()对设备进行注册,这样当用户在实时线程中通过open,release,ioctl等标准POSIX I/O接口函数对设备进行操作时,RTLinux内核将会通过rtl_file_operations结构访问驱动程序提供的函数。同样在RTLinux的rtl_posixio.h中提供了rtl_unregister_chrdev(),rtl_request_irq(),

rtl_free_irq()等与Linux驱动程序设计相关操作对应的函数。但RTLinux设备驱动程序在开发时与Linux下的驱动程序开发也有很多不同之处,主要包括以下几点:

1.在RTLinux下用rtl_regiser_chrdev()注册设备驱动程序时,是为运行在RTLinux内核空间的实时线程提供接口,而不是对用户空间的程序提供文件系统接口,用户也不需要根据注册的设备号用mknod创建设备节点。

2.在Linux中,用户程序与设备驱动程序分别运行于用户空间和内核空间,驱动程序在与用户程序交换数据时需要用到copy_from_user(),copy_to_user()等函数。而在RTLinux中,实时线程与设备驱动共同运行在内核空间,共享同一内存空间,他们之间的数据交换可以直接使用memcpy之类的函数来实现。

3.在RTLinux中,有软中断和硬中断之分。所谓软中断就是指一般的Linux内核中断,它的优点在于可以无限制的使用Linux的内核调用。而硬中断是直接来自硬件的中断,有非常短的中断延迟。对于实时驱动程序而言,我们为了保证实时性必须及时响应硬中断,可以通过rtl_request_irq

()安装中断处理程序,并通过rtl_hard_enable_irq()使能中断。

在下面的CAN接口卡驱动程序的设计实例中,我们会对这几个方面做详细的说明。

三、CAN接口卡的设备驱动程序设计

(一)CAN卡的硬件结构

CAN总线是一种在汽车电子和工业控制中得到广泛应用的现场总线。CAN接口卡扩展了PC设备的CAN接口,实现了PC与其他设备通过CAN总线进行通信。本文中使用的CAN卡为PCI接口的CAN控制器,用来扩展PC机上的CAN接口,实现PC机端CAN数据的收发,其硬件结构框图如下图1所示。

PCI9052是PLX公司的PCI总线从模式接口芯片,用来把对PCI总线上的操作转换为对局部总线的操作,93LC46是一串行EEPROM,用来存储初始化信息。SJA1000是PHILIPS公司的CAN总线控制器,它封装了CAN2.0通讯协议,功能强大,方便易用。82C250为CAN总线收发器件,提供对总线的差动发送能力和对CAN控制器的差动接收能力。

(二)驱动程序的开发步骤

我们开发CAN卡RTLinux下驱动程序的最终目的是提供能在实时线程调用的功能函数,如发送、接收CAN消息、配置CAN网络等,并提供统一、标准的操作接口。而这些功能的实现是通过对CAN控制芯片SJA1000内部寄存器的操作来完成的。这就需要我们首先得到这些寄存器的映射地址,然后对相应功能需要的读写操作进行封装。我们采用的是Linux 2.4.20内核,RTLinux的版本为rtlinux-3.2-rc1,驱动程序的开发主要有以下步骤:

1.获取PCI设备的资源配置信息。这一步的操作与Linux下PCI设备驱动程序的开发完全一致。当驱动程序访问PCI设备的时候,它的内存和I/O区域已经被映射到了处理器的地址空间。我们所要做的就是得到这个设备结构指针。Linux内核中提供了相应的结构和函数用来得到设备的资源配置信息。在驱动程序的初始化阶段,我们利用函数struct pci_dev * pci_

find_device(unsigned int vendor, unsigned int device, struct pci_dev *from)来寻找PCI设备。参数vendor和device是由设备厂商指定的,并存储在EEPROM中。当找到设备后,该函数会返回一个pci_dev结构类型的指针,根据该结构中resource有关的域我们就可以得到设备的基地址、中断号等信息。在接下来的设计中,我们就可以根据此基地址得到SJA1000内部各寄存器的地址,进行相应的I/O操作。

2.注册中断处理函数。由于CAN卡在接收数据时必须与系统以中断的方式交换数据,而且在发送数据时,当遇到发送缓冲器忙的时候也需要根据发送完成产生的中断来确定何时发送下一帧数据,所以在CAN卡的驱动程序中我们要注册中断处理函数。为了确保响应硬件中断的实时性,RTLinux内核对Linux的中断处理做了改进,在硬件中断控制器和Linux内核之间用一层软中断模拟器进行隔离,避免了由于Linux关中断造成的系统在一段时间内无法响应中断的情况。在RTLinux中我们通过函数int rtl_requ

est_irq(unsigned int irq, void(*handler)(void))来注册硬中断。第一个参数为设备的中断号,这个我们在第一步的操作中已经得到,第二个参数就是中断处理函数的指针。这里我们定义了函数CAN_ interrupt_handle

r()。在中断服务程序中,我们要对发送和接收中断分别做出处理,其程序流程如下图2所示。

3.定义并实现设备操作接口。为了实现在RTLinux的实时线程中通过标准POSIX I/O函数(如read、write等)对设备进行操作,我们在驱动程序中定义自己的rtl_file_operation结构:

struct rtl_file_operationsrtl_can_fops = {

read: CAN_read, //从CAN总线读取数据

write: CAN_write, //向CAN总线发送数据

ioctl: CAN_ioctl, //对指定寄存器进行操作,实现配置功能

open: CAN_open, //打开设备

close: CAN_close //释放设备

};

在驱动程序的入口函数init_module()中我们通过int rtl_register

_chrdev(unsigned int major, const char* name, struct rtl_file_operations *fops)来注册设备驱动程序,第一个参数为主设备号,第二个参数为设备名称,我们取“/dev/can”,第三个参数fops即为rtl_can_fops。这样当我们用open()等POSIX I/O函数对设备/dev/can进行操作时,rtl_file_operations中对应的CAN_open()等将会执行。我们分别定义了函数CAN_read(),CAN_write(),CAN_ioctl()来完成CAN卡的数据接收、发送和配置功能,函数的实现就是对相应寄存器进行操作,并与调用它的实时应用程序交换数据。限于篇幅,我们这里不对寄存器级的编程做详细的介绍。需要注意的是,调用驱动程序的实时应用程序和驱动程序运行于同一地址空间。以int CAN_write(struct rtl_file *filp, cons

t char *buf, size_t count, loff_t* ppos)为例,我们在程序中可以直接对用户程序传过来的指针buf指向的内存空间进行操作,而不必像在Linux驱动程序中一样,用copy_from_user()获取用户空间的数据。

四、结束语

RTLinux是性能优越的实时多任务操作系统,是构建实时控制系统的理想平台,而RTLinux设备驱动程序是连接实时应用程序与硬件设备的桥梁。本文详细介绍了在RTLinux下CAN接口卡驱动程序的开发过程,并将其应用于一机器人控制系统。实践证明,该驱动程序具有良好的实时性和稳定性,机器人达到了快速、平稳的控制效果。鉴于RTLinux高实时性及源码开放的特点,其会在工业控制及其它领域具有更广泛的应用前景。

参考文献:

[1]FSM Labs,Geting Started with RTLinux.http://www.fsmlabs.com,2

001.04.20.

[2]Corbet,J.等著,魏永明、耿岳、钟书毅译,Linux设备驱动程序[M].北京:中国电力出版社,2006.

作者简介:

张鹏(1977-),男,山东水利职业学院教师,硕士,主要研究方向软件工程;郭芹(1981-),女,山东水利职业学院教师,硕士,主要研究方向计算机图像处理。