罗东华,李海岗,王忠民
(1.山东传媒职业学院信息工程系,山东济南250200;2.72946部队,山东淄博255000;3.山东省科学院自动化研究所,山东济南250014)
随着计算机控制技术的不断发展,嵌入式系统已经广泛渗透到仪器仪表、工业控制等各个领域,成为备受关注的热点[1].而Linux作为一个源码公开、结构清晰、功能强大,且稳定可靠的操作系统,在嵌入式系统中占据主流位置[2].在工业控制与监测领域,温度监控是一项必不可少的功能模块.文中介绍了基于模拟量传输的温度传感器在Linux系统下驱动程序的开发方法,阐述了可动态加载的设备驱动程序的配置、设计和调试步骤.
驱动程序的目的是驱动硬件正常工作,所以编写驱动程序要针对特定的硬件来进行.Linux设备驱动程序是为特定的硬件提供给应用程序的一组标准化接口,它隐藏了设备工作的细节.设备驱动程序从总体上看分为两部分:驱动程序与Linux内核的接口、驱动程序与设备的接口[3].其代码结构大致可以分为如下几个部分:驱动程序的注册与注销、设备的打开与释放、设备的读写操作、设备的控制操作、设备的中断和轮询处理[4].
Liunx系统的设备分为三种类型:字符设备、块设备和网络设备.基于模数转换模块(ADC)的温度传感器属于字符设备,其实现流程包括设备的注册,文件操作结构体(file_operations)赋值,以及编写文件操作结构体中用到的函数.模数转换模块功能非常简单,所以在文件操作结构体中只需要设置打开函数(open)、释放函数(release)以及读取函数(read)的指针,相应的仅需要实现open函数、release函数和read函数.
open函数提供给驱动程序以初始化的能力,主要工作内容如下:
1)检查设备特定的错误(诸如设备未就绪或类似的硬件问题).
2)如果设备是首次打开,则对其进行初始化.
3)如果有必要,更新file_operations指针[5].在Linux系统用户空间的应用程序中,如果要打开温度传感器设备,需要调用此内核函数(device_open).另外,还可以在此函数中使用一个全局变量,记录设备打开次数,以标识设备是否为第一次打开.
release函数作用与open正好相反,它释放由open分配的所有资源,并关闭设备.同样的,记录设备打开次数的全局变量需要在此函数中进行减操作.
read函数的作用是拷贝数据到应用程序空间,其表达式为:
static ssize_t device_read(struct file*file,char*buffer,size_t length,loff_t*offset)
参数file是文件指针,参数buffer是指向用户空间的缓冲区,参数length是数据长度,参数loff_t是指向长偏移量类型(long offset type)对象的指针.该函数内部的程序流程图如图1所示.
图1 read函数程序流程图
read函数还检查用户空间的指针是否有效,如果指针无效,就不会进行拷贝;如果在拷贝过程中遇到无效地址,则仅仅会复制部分数据.
驱动程序编写完成后,还需要建立该程序的makefile文件,代码如下:
其中,obj-m是生成目标文件的名称,KERNELDIR是内核路径.
有了adcdriver.c和makefile文件,使用make命令即可得到驱动文件adcdriver.ko.然后使用insmod命令动态加载驱动程序,基于模数转换模块的温度传感器驱动就加载进了Linux内核中.
为了测试该驱动程序,需要编写Linux系统用户空间下的应用程序adc.c,程序流程图如图2所示.
图2 应用程序adc.c的流程图
在Linux的用户空间运行此应用程序,能够得到嵌入式处理器S3C2440模数转换模块的有效数据,根据温度传感器模拟量数值与温度的对应关系,即可获取外部环境温度.
文中介绍了Linux操作系统下驱动程序的基本原理和框架,编写了基于模数转换模块(ADC)的温度传感器的驱动程序和应用程序,并给出实际项目中的操作步骤,对实现同类芯片的其他硬件驱动有很好的参考价值.
[1] 张威,黄冲.嵌入式Linux设备驱动的设计方法研究[J] .江西师范大学学报:自然科学版,2007,31(4):391-393.
[2] 巍鹜,张焕强,方贵明.基于Linux的USB驱动程序实现[J] .计算机应用,2002,22(8):17-19.
[3] 李亚峰,欧文盛.ARM嵌入式Linux系统开发从入门到精通[M] .北京:清华大学出版社,2007.
[4] 陈涛,余学才,朱良销.信号发生模块的Linux驱动程序设计[J] .化工自动化及仪表,2010,37(11):88-91.
[5] Corbet J,Rubini A,Hartman G K.Linux设备驱动程序[M] .北京:中国电力出版社,2006.