您的当前位置:首页正文

嵌入式Linux的PC104数据采集卡的驱动设计

2024-01-27 来源:汇意旅游网
第34卷 第2l期 Vo1.34 ・计算机工程 2008年11月 November 2008 N0.21 Computer Engineeri ̄ng 开发研究与设计技术・ 文章编号:100 428(20o8)21— 23岳--03 文献标识码:A 中圈分类号:TP31L.52 嵌入式Linux的PC104 数据采集卡的驱动设计 朱斌,程明臂 (南京工业大学自动化学院,南京21 0009) 摘要:在PC104模块硬件平台和嵌入式Linux系统下,设计并实现PC104总线结构数据采集卡DMM一16一AT的设备驱动程序。利用嵌入 式Linux平台,设计设备驱动程序与系统引导、操作系统内核以及外部设备三者间的接口,屏蔽DMM一16一AT的硬件特性,通过文件系统 实现对DMM一16.T的访问操作。该方法解决了工业色谱仪在嵌入式LiAnux下通过DMM一16-T进行采样的问题。A 关健诃:嵌入式Linux;PC104规范;驱动设计;数据采集与处理 Driver Design of PC 104 Data Acquisition Card in Embedded Linux ZHU Bin,CHENG Ming-xiao (College ofAmomation,Nanjing University ofTechnology,Nanjing 210009) [Abstract]The device driver of PC104 data acquisition card is designed and implemented in the embedded Linux environment based on he tPCIIM platform.The interfaces between the device driver and system boot.system kernel,peJ  ̄heral devices separately are also designed.By using this driver,,characterisicst of all hardware are masked and DMM一16- AT can be accessed easily through ilfe system.It is proved that this driver can solve he samplting problems on industrial chromatograph by DMM 16-AT in embedded Linux environment. [Key wordsl embedded Linux;PC104;driver design;data acquisition and processing 1概述 嵌入式Linux系统是一个分布式、多用户、多任务的操 作系统,被广泛应用于通信系统、航空航天仪器、工业控制 等方面。但在很多总线的外围设备都不具备嵌入式Linux下 的驱动程序。若要使用,就需自行开发驱动程序。在嵌入式 Linux系统下,通过文件系统来屏蔽硬件设备特性,把具体 设备抽象成设备文件,用户程序就可以通过标准的文件操作 实现对设备的访问…。 本文以Diamond Systems公司开发的PC104总线结构的 数据采集卡DMM一16一AT为硬件外设,在自行裁减和移植的 嵌入式Linux平台支持下,阐述驱动程序的结构设计和开发 流程。 2 PC104总线和DMM-16一AT数据采集卡 PC104是一种专门为嵌入式控制而定义的工业控制总 线,被IEEE协会定义为IEEE.P996.1。它是ISA(IEEE.996") 标准的延伸,是一种优化的、小型堆栈式结构的嵌入式控制 系统。小型化的尺寸、极低的功耗和堆栈的总线形式,受到 众多从事嵌入式产品生产厂商的欢迎。截止目前,全球已有 200多家厂商在生产和销售符合PC104规范的嵌入式板卡。 DMM一16一AT数据采集卡是遵循PC104总线结构而设计 图1 DMM-16.・AT结构 3驱动程序开发 设备驱动程序从本质上讲,是常驻内存的低级硬件处理 程序的共享库,对设备进行抽象处理。它封装了如何控制设 的一个扩展模块。在任何PC兼容的嵌入式计算机上,只需 有PC104扩展连接器,就能实现强大的数据采集功能。图1 就是DMM-16一AT的主板结构简图。其中,J1为PC104的8 bil 总线连接口;J2为PC104的16 bit总线连接口;J3是用户I/O 日;J4是A/D单端,差分输入配置;J5是D/A范围/极性配置; J6是DMA/INTERRUPT/ADDRESS(直接内存传输/中断/地址) 配置;J7为厂家保留使用 J。 备的技术细节,并通过特定的接口,导出一个规范的操作集 合。内核使用规范的设备接口,通过文件系统接口把设备操 作导出到用户空问程序中I 。 作者倚介:朱斌(1984--),男,硕士研究生,主研方向:嵌入式 Linux系统;程明霄,教授 收稿日期:2007--12—25 E-marl:lyglary@126 corn 3.1驱动程序与外界的接口 嵌入式Linux设备驱动程序与外界的接IZl可以分为3个 部分: 通过上述函数,设备驱动程序完成了系统资源的申请, 包括内存、中断、时钟等。 3.2.2服务于I/O请求的子程序 这部分可以称为驱动程序的上半部分。主要通过file结 构来识别驱动程序,而且内核使用file—operation结构来访问 驱动程序中的函数。 (1)与系统引导的接13。利用驱动程序对设备初始化。 (2)与操作系统内核的接口。通过数据结构file一_operations 实现。 (3)与外部设备的接1:1。规定驱动程序如何与外设进行交 互访问。 完整的驱动代码通常包括:设备的打开与释放,设备的 读写操作,设备的控制操作,设备的中断和轮询处理。它们 图2为驱动程序与外界接口的示意图。 都可以是file_operation结构的组成部分。 Fileoperation结构定义如下: struct fileoperations f struct module owner;//module的拥有者 1ofLt( llseek)(struct ifel , ̄off_t,int); //移动文件指针的位置,只能用于可以随机存取的设备 ssize-t( read)(struct ifel ,char ,size—t,loff_t ); //从设备中读取数据,与write类似 ssize_t( write)(struct file ,const char ,size—t,1off_t ); 圈2驱动程序与外界的接口 //向字符设备中写入数据 3.2驱动程序的组织结构 int( ioct1)(struct inode ,struct ifel ,unsigned int,unsignedlong); 驱动程序具有一个较为标准的组织结构,它有3个组成 //控:制设备,除读写操作外的其它控制命令 部分: int( mmap)(struct ifle ,struct vm area—struct ); //用于把设备的内容映射到地址空间 (1)自动配置和初始化子程序; unsigned int( pol1)(struct file ,struct poll—table—struct ); (2)服务于I/O请求的子程序; //用于查询设备是否可读写或处于某种状态 (3)中断服务子程序。 int( lock)(struct file ,int,struct file—lock ); 3.2.1 自动配置和初始化子程序 //-文件锁定,用于文件共享时的互斥访问 这部分子程序负责检测目标驱动硬件设备是否存在,以 int( open)(stmct inode ,struct ifel ); 及能否正常工作。如果设备正常,则进行相关的资源配置。 //;打开设备进行I/O操作 对于DMM16,编写初始化函数init一.moduleO对其进行初 int( =release)(struct inode ,struct file ); 始化,程序片断分以下几段: //关闭设备并释放资源 ); ’ #define DEVICENAME‘'dmml6'’ static int dram 1 6可以看出,file_operations结构中的成员全部是函数指 major=252; int rc=0; 针,所以,实质上就是函数跳转表。 rc=register在file—operations结构中,每个字段都必须指向驱动程序 chrdev(dmm16 major,"dmml6”,&dmml6一fops); 其中,major是为设备驱动程序向系统申请的主设备号,如 中,实现特定操作的函数,即要求把驱动中用到的函数记录 果为0,则系统为该驱动程序动态地分配一个主设备号,返 到相应字段中,没用到的就不管,那么,就可以使得驱动程 回值赋给re。此处已定义主设备号为252,则返回的re值为 序既精简又实用 下面是DMM16的fiel—operations结构: 0,表示注册成功,返回.EINVAL表示申请的主设备号非法, static struct file—.operations dscud...fops-- 返回一BUSY表示所申请的主设备号正在被使用。name是设 { 备名,此处定义为“dmml6”'。dmml6一.fops是file—operation open:dmml6一.open, re lease:dmml6release, 类型的结构指针。如果登记成功,设备名会出现在/proc/ 、一iocfl:dmml6ioctl, devices的文件里,登记失败则会返回负值。 read:dram 1 6read, memset(pci.一boards,0,sizeof(PCI一.INFO); J; 其中,memset()函数用来清空相应的内存空间,以用于 其中,dmml6一_open负责打开DMM16总线控制器,动态申 DMM16和操作系统内核的数据交换;pci.一boards是一数组指 请并且清空缓冲区;dmm16一release负责关闭总线控制器,释 针;PCI—INFO是关于DMMI6配置信息的结构体,它定义了 放所申请的全部系统资源;dmml6一read完成对缓冲区数据的 中断号、设备号等一系列参数。 读取;dmml6一ioctl用于向总线控制器发送各种命令,如配 struct pci—dev dev=NULL; 置中断请求、查询设备状态、获得设备的版本号等,其部分 dev=pci_finddevice(PCI_VENDOR_ID,device id,deV); 代码如下: 其中,pci—find一.device()用于操作系统自动搜索PCI设备,而 static int dmml6一DMM16为ISA设备,需要利用跳线进行手动设置,然后配 ioctl(struct inode node。struct file fielp, unsigned int cmd,unsigned long arg) 合此函数,才能实现硬件的自动搜寻。此函数有3个参数: fint rc: (1)供应商ID; if(cmd==IOCTL. DMM16—._CONF) (2)设备ID; {.一 (3)函数的返回值,NULL表示从头开始查找。 rc=copy—fron—user((void' )&conf,(void )arg, 一237— sizeof(DMM16—.CONF));... return initadint(kpdata,&conf); 下,同时把驱动源文件dmml6.C添加到/usr/src/linux/drivers/ char/目录下。 ),,配置采样板,进行中断申请 else if(cmd==IOCTL——DMM16——STATE) (2)修改/usr/src/linux/arch/i386目录下的config.in脚本文 件,在最后一行加入代码: comment‘dmm16’ (…)//查询采样板状态 else bool‘dmml6 card support’CONFIGd【mml6 {printk(“dmml6一ioctl got unknown ioctl code%d\n”,cmd); return—ENOTTY; (3)修改/usr/src/linux/drivers/char目录下的Makefile文 件,添加如下代码: ’ ifdef CONFIGdmml6 ~)//其他未知命令 return O;1 LOBJS+=dmml6.O 3.2-3 中断服务子程序 endif (4)修改/usr/src/linux/kernel下的mem.c文件,在int chr— 这部分可称为驱动程序的下半部分。设备在I/O请求结 束时或其他状态发生改变时产生中断。此时,系统自动调用 devinit0函数中增加如下2行代码: 中断服务例程。对于DMMI6,设置其中断类型为FIFO中断。 /dev/dmml6 252 #define DMM 1 6MAJOR 252 因为DMM16具有先进先出的FIFO存储栈结构,AID转换后 的数据自动存储在FIFO中,当FIFO达到预置深度时,向系 (5)利用如下命令编译内核: cd/usr/src/linux/drivers/cbar 统内核申请中断。 gcc—c dmml6.C-Wall—D~一KERNEL 首先需要向系统注册设备使用的中断,通过request—irq() rm f dmm16.O 接13函数来实现,具体操作如下: cd/usr/src/linux request—irq(IRQ—DMM16,dmml6一adint,SA—IN—TERRUPT, make config DEVICENAME,isrdmml6); 编译成功后,就可以像使用普通文件一样,对设备进行 其中,IRQ—DMM16是申请的中断号;dmml6一adint是中断 操作。用户可以使用系统提供的接口函数来开发自己的应用 处理函数的指针;SA_INTERRUPT是一个与中断管理有关的 程序。 位掩码选项;DEVICE_NAME是设备名,它被用来在 4.2驱动程序的测试 /proc/interrupts中显示中断拥有者;isr—dmml6是一个唯一的 驱动加载后,对DMM16采样所得的数据进行滤波、量 标志符,通过该指针,多个设备可共享信号线,驱动程序也 程转换等处理,结合嵌入式Linux上流行的GUI软件 可用它指向自己的私有数据区,用来识别哪个设备产生了中 MiniGUI,可以把采样所得数据实时地显示出来 J。图3是实 断。这个函数已经被封装在上面提及的init—adint0函数中。 时采样曲线。 然后是中断处理子程序实现用户所要实现的功能。对于 DMM16,主要完成将所采集的数据送入系统所设置的大容量 缓冲区,作为原始数据,实现硬件寄存器、操作系统内核, 以及用户之间数据的传送。相关代码如下: 宙0.25 脚 insw(dmmdata一>base—address,dmmdata->pCurPos,dmmdata一> 0.1O samples—.per——int); 用于从dmmdata一>base—address指定的地址连续读入 0.oo dmmdata一>samplesper_int数量个采样值,保存在dmmdata一时I司 —> pCurPos所指向的地址空间中,实现硬件寄存器和操作系统 图3实时采样曲线 内核之间的数据传送。 copy—to—user(buff,dmmdata一>pReadPos,count); 5结束语 本文阐述了在嵌入式Linux平台下,PC104总线结构的 用于从指向核心内存中的指针dmmdata一>pReadPos拷贝 Byte到指向用户内存的指针buff中去,实现核心态和用户 DMM一16一AT采样卡驱动的开发过程。根据PC104总线特点, 遵循Linux驱动开发的通用流程,设计出一套实际可行的硬 态之间的数据传送。 件操作接口,满足工业色谱仪数据采集的实时需求。目前, 4驱动程序实现 该驱动已成功运用于国产工业色谱仪上,并且收到了良好效 4.1驱动程序的编译和添加 果,创造出较好的经济效益。 在嵌入式Linux下,驱动程序的编译添加,一般有2种 方式:(1)静态编译进内核,再运行新的内核来测试;(2)编译 参考文献 成模块在运行时加载。 [1】邹思轶.嵌入式Linux设计与应用[M】.北京:清华大学出版社, 方式(1)效率较低,但是,在某些场合是唯一的方法。方 2002. 式(2)调试效率很高,它使用insmod工具,将编译的模块直 [2】SBS Science&Technology Co.Ltd..Diamond—MM一16一AT Auto— 接插入内核,如果出现故障,可以使rmmod从内核中卸载模 calibiafing 16一bit Analog I/O PC/104 Module User Manual[Z]. 块。不需要重新启动内核,这使驱动调试效率大大提高,但 2002. 嵌入式系统是针对具体应用的,所以,一般采用将设备驱动 【3]Rubini A.Linux设备驱动程序【M].北京:中国电力出版社,2000. 程序以静态的方法编译进内核。具体操作步骤如下: [4]魏永明.基于Linux和MiniGUI的嵌入式系统软件开发指南[z]. (1)将驱动头文件dmm16.h添加到,usr/include/linux/目录 f2005—04—03).http://www.minigui.com. 一238一 

因篇幅问题不能全部显示,请点此查看更多更全内容