基于嵌入式LINUX驱动程序开发的研究_第1页
基于嵌入式LINUX驱动程序开发的研究_第2页
基于嵌入式LINUX驱动程序开发的研究_第3页
基于嵌入式LINUX驱动程序开发的研究_第4页
基于嵌入式LINUX驱动程序开发的研究_第5页
已阅读5页,还剩5页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、基于嵌入式LINUX 驱动程序开发的研究黄志武潘俊杉(孝感学院计算机科学系,湖北孝感432000摘要本文阐述了嵌入式设备驱动程序的功能与结构,并结合实例说明了嵌入式Linux 下设备驱动程序开发的过程。关键词嵌入式系统;设备驱动程序;嵌入式linux 作者简介:黄志武,男,湖北武汉人,硕士研究生,教师,研究方向:嵌入式系统与应用。1.引言嵌入式Linux 由于其可应用于多种硬件平台、内核高效稳定、源码开放、软件丰富、网络通信和文件管理机制完善等优良特性,已经成为嵌入式操作系统的主力军,是整个嵌入式系统的重要组成部分。在嵌入式Linux 系统中,由于内核的保护机制,用户一般不能直接访问硬件,而是

2、要通过调用驱动程序来实现对硬件的控制1。进行嵌入式系统的开发,很大的工作量是为各种设备编写驱动程序。设备驱动程序是Linux 内核的重要组成部分,不同版本的内核,其主要区别也是体现在设备驱动程序的不同。2.设备驱动程序及其功能在嵌入式系统中对硬件的控制涉及寄存器中各位的操作,通常这些操作与设备直接相关并且对时序的要求非常严格,如果这些工作都交给应用程序来负责,那么对硬件设备的编程将变得异常复杂而困难。操作系统一般是通过提供设备驱动程序来完成对特定硬件的控制,以建立应用程序和设备之间的抽象接口,而不是应用程序直接操作硬件。设备驱动程序实际是处理和操作硬件控制器的软件,从本质上讲,是内核中具有最高

3、特权级的、驻留内存的可共享的底层硬件处理例程。驱动程序的作用也就是屏蔽硬件的底层细节,从而简化应用程序的编写。Linux 操作系统将设备分成三大类。一类是像磁盘那样以记录块或“扇区”为单位,成块进行输入/输出设备,称为“块设备”,文件系统通常都建立在块设备上;另一类是像键盘那样以字符(字节为单位,逐个进行输入/输出的设备,称为“字符设备”。第三类是网络设备,是介于块设备和字符设备之间的一种特殊设备2。Linux 操作系统将所有的设备全部都看成文件,都纳入文件系统的范畴,都通过文件的操作界面进行操作。因此,每一个设备都至少由文件系统的一个文件代表,因而都有一个“文件名”。而且应用程序通常可以通过

4、系统调用open(“打开”这个设备文件,建立起与目标设备的连接。对于执行该应用程序的进程而言,建立起的连接就表现为一个已经打开的文件,随后就可以通过read(、write (、ioctl(等常规的文件操作对目标设备进行操作。3.设备驱动程序的结构一般Linux 设备驱动程序可以分为3个主要组成部分:(1自动配置和初始化子程序,负责检测所要驱动的硬件设备是否存在和能否正常工作。如果设备正常则对这个设备及其相关的设备驱动程序需要的软件状态进行初始化。这部分驱动程序仅在初始化时被调用一次。(2服务于I/O 请求的子程序,又称为驱动程序的上半部。调用这部分程序是由于系统调用的结果。这部分程序在执行时,

5、系统仍认为是与进行调用的进程属于同一个进程,只是由用户态变成了核心态,具有进行此系统调用的用户程序的运行环境,因而可以在其中调用sleep(等与进程运行环境有关的函数。(3中断服务程序,又称为驱动程序的下半部。在Linux 系统中并不是直接从中断向量表调用设备驱动程序的中断服务子程序,而是由Linux 系统来接收硬件中断,再由系统调用中断服务子程序。中断可以在任何一个进程运行时产生,因而在中断服务程序被调用时,不能依赖于任何进程的状态,也就不能调用任何与进程运行环境有关的函数。因为设备驱动程序一般支持同一类型的若干设备,所以一般在系统调用中断服务子程序时,都带有一个或多个参数,以唯一标志请求服

6、务的设备。在系统内部,I/O 设备的存/取通过一组固定的入口点来进行,这组入口点是由每个设备的设备驱动程序提供的3。Linux 系统中,设备驱动程序所提供的这组入口点由一个文件操作结构来向系统进行说明。file_operations 结构定义于linux/fs.h 文件中,不同的内核版本,file_opera-tions 结构也会有所差异。下面的结构体就是一个典型的file_operations 结构:struct file_operations struct module *owner;loff_t (*llseek(struct file *,loff_t,int;ssize_t (*re

7、ad(struct file *,char *,size_t,loff_t *;ssize_t (*write(struct file *,const char *,size_t,loff_t *;int (*readdir(struct file *,void *,filldir_t;unsignedint(*poll(structfile*,structpoll_table_struct *;66系统开发int(*ioctl(struct inode*,struct file*,unsigned int,unsigned long;int(*mmap(struct file*,struct

8、 vm_area_struct*; int(*open(struct inode*,struct file*;int(*flush(struct file*;int(*release(struct inode*,struct file*;int(*fsync(struct file*,struct dentry*,int datasync;int(*fasync(int,struct file*,int;int(*lock(struct file*,int,struct file_lock*; ssize_t(*readv(struct file*,const struct iovec *,u

9、nsigned long,loff_t*;ssize_t(*writev(struct file*,const struct iovec *,unsigned long,loff_t*;ssize_t(*sendpage(struct file*,struct page*, int,size_t,loff_t*,int;unsigned long(*get_unmapped_area(struct file*,un-signed long,unsigned long,unsignedlong,unsigned long;file_operations结构中的成员全部是函数指针,所以实质上就是函

10、数跳转表。每个进程对设备的操作,都会根据major、minor设备号,转换成对file_operations结构的访问。在用户自己的驱动程序中,首先要根据驱动程序的功能,完成file_operations结构中函数实现。不需要的函数接口可以直接在file_operations结构中初始化为NULL。file_operations变量会在驱动程序初始化时,注册到系统内部。当操作系统对设备进行操作时,会调用驱动程序注册的file_operations结构中的函数指针。除了file_operations结构中的函数外,设备驱动程序开发还需要编写对内存、I/O端口和时钟等资源操作的函数。实际上,驱动程

11、序主要就是由这些函数组成的,操作系统正是通过调用这些函数来实现对硬件的操纵。4.设备驱动程序开发过程嵌入式设备的硬件种类是非常丰富的,在默认的内核发布版中不可能包括所有驱动程序,所以进行嵌入式Linux系统的开发,很大的工作量是为各种设备编写驱动程序。在ARM平台上开发嵌入式Linux的设备驱动程序与在其他平台上开发并没有本质的区别。下文就以一个完整的字符设备LED驱动程序为实例,简要说明嵌入式LINUX驱动程序的开发过程:(1系统资源和设备号定义#define DEVICE_NAME"leds"/*定义led设备的名字*/#define LED_MAJOR231/*定义l

12、ed设备的主设备号*/ static unsigned long led_table=/*I/O方式led 设备对应的硬件资源*/GPIO_B7,GPIO_B8,GPIO_B9,GPIO_B10,;(2定义初始化和入口、出口函数模块的入口函数leds_init(,所做的工作是点亮I/O端口对应的LED,这些二极管可以作状态指示之用。regis-ter_chrdev(完成字符设备在系统中的注册,并建立与文件系统的关联。static devfs_handle_t devfs_handle;static int_init leds_init(voidint ret;int i;/*在内核中注册设备*

13、/ret=register_chrdev(LED_MAJOR,DEVICE_NAME,&leds_fops;if(ret<0printk(DEVICE_NAME"can't register major num-bern"return ret;devfs_handle=devfs_register(NULL,DEVICE_NAME,DE-VFS_FL_DEFAULT,LED_MAJOR,0,S_IFCHR|S_IRUSR|S_IWUSR,&leds_fops,NULL;/*使用宏进行端口初始化,set_gpio_ctrl和write_gpi-o

14、_bit均为宏定义*/for(i=0;i<8;i+set_gpio_ctrl(led_tablei|GPIO_PULLUP_EN|GPI-O_MODE_OUT;write_gpio_bit(led_tablei,1;printk(DEVICE_NAME"initializedn"return0;卸载模块时调用leds_exit(函数,执行后设备处于空闲状态。static void_exit leds_exit(voiddevfs_unregister(devfs_handle;unregister_chrdev(LED_MAJOR,DEVICE_NAME;(3定义主要

15、操作函数leds_ioctl(ioctl入口,执行读、写之外的操作,通过参数cmd设定命令参数/*使用ioctl控制led*/static int leds_ioctl(struct inode*inode,struct67系统开发Research of Developing Device Driver Based on Embedded Linux SystemHuang ZhiwuPan Junshan(Department of Computer Science,Xiaogan University ,Xiaogan 432000,Hubei 【Abstract 】Expatiates

16、the function and structure of embedded device driver and with an example ,the process of developing device driver based on embedded Linux system is introduced.【Keywords 】embedded system ;device driver ;embedded Linuxfile *file,unsigned int cmd,unsigned longargswitch(cmdcase 0:case 1:if (arg >4ret

17、urn -EINVAL;write_gpio_bit(led_tablearg,!cmd;default:return -EINVAL;(4文件系统接口定义static struct file_operations leds_fops =owner:THIS_MODULE,ioctl:leds_ioctl,;(5模块化module_init(leds_init;module_exit(leds_exit;用insmod 命令加载模块时,调用module_init(;用rmmod 命令来卸载模块时,调用module_exit(6编译并安装驱动程序驱动程序编写完成后,就要对源程序进行编译并安装。编译的过程可以通过修改makefile 文件并执行make 命令完成,也可以通过手工输入命令的方式编译驱动模块:¥arm-linux-gcc -D_KERNEL_-DMODULE I ¥(INCLUDE02Wall -o -c leds.c -o leds.o以上命令将生成leds.o 文件,把该文件复制到板子的/lib 目录下,使用以下命令安装leds 模块:¥insmod /lib/leds.o LED 驱动程序就加载到LINUX 内核中了。5.小结驱动程序就是一个函数和数据结构的集合,它的目的是实现一个简单的管理设备的接口,内核利用这个接口请求驱动程序控制设

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论