郑雯玉,陈军桦,吴志勇,赵 磊,于 潇
(山东理工大学计算机科学与技术学院,山东 淄博 255049)
嵌入式系统强调软件和硬件的协同性、整合性和可裁剪性,以满足系统对功能、成本、体积及功耗等方面的要求[1].通常,嵌入式系统要求嵌入式操作系统具有更高的可靠性和实时性.PC/104是与PC/AT兼容的专门为嵌入式系统定义的一种总线标准,它具有结构紧凑、自堆栈、功耗低等优点,在工业控制领域得到了广泛的应用.本文研究嵌入式Linux操作系统在PC/104环境下的应用技术,结合数据采集卡驱动程序的设计过程,讨论了硬件设备驱动程序的设计方法及编程技术,并给出实验结果.
___实验系统地硬件结构分为上位机和下位机两部分.上位机是标准的个人计算机,下位机是PC/104标准的嵌入式计算机系统,该嵌入式系统由嵌入式系统主板和数据采集模块(Diamond-MM-32-AT)构成.嵌入式系统的外部存储器是一张CF卡(Compact Flash),主板上配备了CF卡的卡座.上位机和下位机通过网线相互连接.系统框架如图1所示.
图1 系统框架图
嵌入式系统主板采用盛博协同嵌入式计算机公司生产的SCM/LX-3160,它是一款高性能的“ALL IN ONE”PC/104 CPU模块.该模块采用AMD Geode LX 800 CPU,工作频率500M Hz;具有128KB一级高速缓存和128KB二级高速缓存;在板表贴256M RAM;VGA控制器支持CRT输出;两个以太网接口;一个CF卡接口;具有一个与8259A等同的中断控制器.
数据采集模块采用美国钻石公司生产的Diamond-MM-32-AT,带有16位精度的32路模拟输入通道,输入信号幅值范围可调,最高采样频率为200kHz,板载FIFO缓冲区1024字节,具有自动校准功能.
嵌入式系统软件开发环境包括上位机软件开发环境和下位机软件开发环境.上位机的操作系统是Ubuntu 9.03,程序编辑器使用Geany,程序编译器使用gcc 4.3.3.Linux操作系统内核的定制裁剪、Diamond-MM-32-AT在Linux内核之上的驱动程序的编写和编译在上位机进行.上位机编译好的驱动程序通过NFS(Network File System,网络文件系统)传输给下位机的CF卡.下位机软件系统环境的构建,包括Linux内核的裁剪与移植、根文件系统的搭建和启动引导程序的安装[2].简要构建过程如下:
(1)将CF卡分区并格式化为ext3文件系统,然后安装引导加载器grub V0.97.
(2)编译linux内核.所用内核版本为2.6.31.配置过程中先禁用模块支持,尽可能根据硬件最小化配置,配置为可抢占式内核以提高实时性,最后启用模块支持并保存配置.执行make bzImage命令,编译生成内核镜像文件bzImage.拷贝bzImage文件到CF卡上/boot目录下.编译后的内核源码树原样保留,将用于驱动编译.在后面的驱动程序的makefile中,内核源码树路径应该为编译内核时的源码树路径.[3]
(3)根文件系统采用busybox 1.15.1.为提高运行速度和避免手动添加动态库的麻烦,将busybox编译成一个静态文件,而不使用共享库.
(4)建立基本设备文件/dev/null、/dev/zero、/dev/console,并编写启动配置文件.必需的三个配置文 件 是/etc/inittab、/etc/init.d/rcS和/boot/grub/menu.lst.其中grub配置文件menu.lst中,使用“root=/dev/hda1”方式直接引导CF卡上的根文件系统.
至此,下位机的软件环境构建过程完毕.将CF卡插入嵌入式主板SCM/LX-3160的CF卡座.开启下位机电源,下位机系统开始运行.本系统各组成部分所占用空间见表1.
表1 系统各部分体积
硬件设备驱动程序的核心功能有两点:一是对硬件设备端口的操作;二是对硬件设备中断的控制和响应.设备驱动程序是Linux内核与硬件之间的接口,并对内核屏蔽了硬件设备的细节.Linux把所有的设备当作一种特殊的文件(设备文件)来处理,所以应用程序可以像操作普通文件一样操作硬件设备.作为内核模块的一部分,驱动程序主要完成以下功能:
(1)硬件设备的初始化和关闭.
(2)从硬件设备端口读取数据,以及将内核数据传送到硬件设备端口.
(3)把来自用户程序的设置和数据传送给设备文件,以及将数据从设备文件读出.
(4)控制和响应外部中断.
(5)检测并处理设备运行时出现的错误[4].
Diamond-MM-32-AT工作模式定义在头文件dmm32.h中,该头文件同时也定义了用于在用户空间和内核空间传递参数的结构体.因此,用户应用程序必须包含该头文件.该模块模拟量采集的三种工作模式定义如下:
DMM32_IOC_AD_SINGLE 是最简单的A/D采样模式,以软触发方式启动A/D转换,读取数据并保存到用户空间后,紧接着启动下一次A/D转换,直到读取到用户程序所要求的数据量后退出.无法以精确的频率采样.
DMM32_IOC_AD_CLKINT 用板载计数器82c54的输出脉冲触发中断,中断处理例程软触发启动A/D转换并将数据保存到一个全局数组buffer中,待所需数据全部采集完毕后禁用中断并唤醒已经休眠的读进程read(),read()将内核空间buffer里的数据读入用户空间后退出.
DMM32_IOC_AD_FIFOINT 用板载计数器82c54的输出作为A/D转换的启动信号,转换所得数据由硬件自行写入板载FIFO,待FIFO中的数据量到达设定阈值时触发硬件中断.中断处理例程将从FIFO中读取设定数量的数据,并送入一个循环缓冲区内,同时唤醒已经休眠的读进程read();read()从循环缓冲区中读取用户指定的数据量,并写入用户空间.在用户应用程序中不停地调用read()即可以得到连续的数据流.
3.3.1 添加头文件以及系统宏
#include"dmm32.h"//用户编写的头文件,包括模式(即ioctl命令字)定义和用户所需参数结构体定义
#include"dmm32_buffer.h"//用户自定义缓冲区,在DMM32_IOC_AD_FIFOINT模式时,将FIFO中的数据读入用户空间,使用该缓冲区以防止数据丢失
MODULE_LICENSE("Dual BSD/GPL");//告诉内核该模块使用自由许可证,如果没有这个声明,系统在加载该模块时会警告
驱动程序还需要操作方式的控制参数,这些参数可在insmod命令装载模块时赋值.参数必须使用module_param宏来声明,使其对insmod命令可见.
module_param(dmm32_irq_id,int,S_IRUGO);//设备中断号
module_param(dmm32_major,int,S_IRUGO);//主设备号
module_param(dmm32_minor,int,S_IRUGO);//次设备号
module_param(dmm32_nr_devs,int,S_IRUGO;//设备数量
module_param(dmm32_fifo_depth,int,S_IRUGO);//FIFO深度
3.3.2 全局变量
dmm32.c中的全局变量保存主设备号、次设备号、设备中断号以及FIFO深度等信息.
3.3.3 设备的初始化及释放
module_init(dmm32_init);//宏,指定dmm32_init为用户加载模块时调用的初始化函数
module_exit(dmm32_exit);//宏,指定dmm32_exit为用户卸载模块时调用的清理函数
以上两个宏都定义在<linux/module.h>中.
3.3.4 对设备文件的主要操作
对设备文件的打开、关闭、读、写以及控制等的操作通过file_operations结构体向系统说明,该结构体定义如下.
图2 应用程序流程图
以下是几个设备文件的重要操作:
用户应用程序采用DMM32_IOC_AD_FIFOINT工作模式,此模式下FIFO深度达到512字节时触发硬件中断.使用一个循环队列作为缓存,并将该缓存的定义和有关操作放在头文件buffer.h中.模拟信号输入通道0外接1kHz的正弦波信号,电压范围为-5V~+5V,采样频率为200kHz.程序流程如图2所示.
应用程序将数据保存到一个外部文件,文件数据达到4MB时程序停止,程序运行历时约10s.程序停止后,打开保存数据的外部文件,每个采样点数据占用2字节,每个正弦周期200个采样点的电压值同被测信号的幅值完全吻合,整个外部文件共计104个周期的2M个采样数据.此应用程序成功调用Diamond-MM-32-AT设备驱动程序模块,程序运行过程中无内核异常或警告,多次连续运行亦稳定.表明在PC/104环境下,所开发基于Linux操作系统的硬件设备驱动程序运行可靠.
在PC/104规范的硬件环境下构建嵌入式Linux操作系统的方法,研究了基于嵌入式Linux操作系统的硬件设备驱动程序基本结构及设计方法,并给出了一款高性能数据采集卡的驱动程序实例.通过用户应用程序对驱动程序的实际调用实验,验证了驱动程序的可行性和稳定性,为进一步研究嵌入式Linux环境下更复杂的硬件设备操作奠定了坚实的基础.
[1]李善平,刘丈峰,王焕龙,等.Linux与嵌入式系统[M].北京:清华大学出版社,2003.
[2]许德新,谈振藩,胡文彬,等.嵌入式Linux在PC104平台上的构建与实现[J].应用科技,2006,33(10):35-37.
[3]王忠凯,赵磊,郭浩,等.FAT文件系统在UC/OS-Ⅱ内核上的应用[J].山东理工大学学报(自然科学版).2009.23(5):60-65.
[4]何世烈,陈健.基于嵌入式Linux的设备驱动程序设计[J].单片机与嵌入式系统应用.2007,1(7):65-67.
[5]JONA THANCORBET,ALESSANDRORUBINI,G REG KROAH-HARTMAN.Linux设备驱动程序[M].魏永明,耿岳,钟书毅,译.3版.北京:中国电力出版社,2005.