你好,欢迎来到电脑编程技巧与维护杂志社! 杂志社简介广告服务读者反馈编程社区  
合订本订阅
 
 
您的位置:文章管理 / 本期精品文章
嵌入式Linux设备驱动的研究与开发
 

苟培培  郭麦成  孙静 王涛

摘要本文首先介绍了在嵌入式Linux环境下设备驱动程序的开发流程,详细描述了Linux设备驱动程序的体系结构和Linux设备文件的概念。然后通过一个例子描述了如何设计和编写Linux设备驱动程序,并解释了其中的核心代码。最后构建一个Glade工程调用这个设备驱动程序,完成测试工作。

关键词设备文件设备驱动 Glade

中图法分类:TP311.11

 

一、 引言

Linux是开放源代码的操作系统由于其具有高效稳定、执行速度快、实现了真正的多任务、多用户环境、强大的网络功能、较好的可裁减性与移植性等特点在嵌入式系统领域获得了飞速的发展。针对ARM体系结构CPU开发的具有MMU功能的嵌入式Linux操作系统无疑是ARM平台上操作系统的最佳选择。本文主要研究了Linux下进行开发驱动程序并构建一个GUI程序来使用这个驱动程序的一般流程。

 

二、 Linux设备驱动程序

Linux支持三类硬件设备:字符设备、块设备和网络设备。字符设备是指无须缓存直接按字节读写的设备。块设备是以块为单位进行读写,能够进行随机访问。网络设备在Linux里做专门的处理,它没有映射到文件系统的设备节点,对它的访问采用socket机制实现。字符设备与块设备的主要区别是:在对字符设备发出读/写请求时,实际的硬件I/O一般紧接着发生。块设备则不然,它利用一块系统内存作缓冲区来进行实际的I/O操作。

应用层

系统调用接口

虚拟文件系统(VFS)

网络子层

字符设备驱动

设备接口

硬件

块设备驱动

网络设备驱动

1  驱动程序结构

Linux中,几乎所有的内容都是文件,对设备驱动的访问也是以文件操作的方式实现。无论是字符设备还是块设备,用户对设备的操作都是通过虚拟文件系统(VFS)转化为设备驱


动与硬件操作例程的交互。即使是访问网络设备的socket接口,也是通过VFS实现的。Linux通过VFS为用户提供了一个统一的设备访问接口,使用户能够透明地访问设备驱动程序如图1所示。所有的硬件设备都可以使用和操作文件标准的系统调用接口来打开、关闭、读写和I/O控制操作,而驱动程序的主要任务就是实现这些系统函数的调用。Linux系统中的所有硬件设备都使用一种特殊的设备文件来表示。每个设备文件都有两个设备号:一个是主设备号,它用来标识该设备的种类,也标识该设备使用的驱动程序;另一个是次设备号,用来标识使用同一设备驱动程序的不同硬件设备。

 

实现一个嵌入式Linux设备驱动的大致流程如下:

定义主、次设备号,也可以动态获取;实现驱动初始化和清除函数,如果驱动程序采用模块方式,则要实现模块初始化和清除函数;设计所要实现的文件操作,定义file_operations 结构;实现所需的文件操作调用,如readwrite 等;实现中断服务函数,并用request_irq 向内核注册。中断并不是每个设备驱动都需要;将驱动编译到内核或编译成模块,用insmod 命令加载;生成设备节点文件。

下面以一个简单的例子来说明设备驱动程序的结构,这个驱动程序是用来控制目标板上的一组LEDled_fops结构体定义了该设备需要的操作接口。它的成员全部是函数指针,所以实质上就是函数跳转表。

struct file_operations led_fops = {

open: led_open,   /*打开设备操作 */

read: led_read,    /* 读设备操作  */

write: led_write,   /* 写设备操作   */

ioctl: led_ioctl,    /* 控制模块的设置 */

release: led_release, /*释放设备操作 */

};

ssize_t led_read(struct file *filp, char *Putbuf, size_t length, loff_t *f_pos)

{     unsigned short BottonStatus;

    unsigned char Bottontmp = 0;

       int i;

       BottonStatus = (KEY_CS & 0xff ); /*获取当前8个按键的状态*/

       for(i = 0 ; i < 8; ++i)

       {  if( ((BottonStatus >> i) & 1) == 0 )

                   Bottontmp = (i+1);

       }

       copy_to_user( Putbuf,&Bottontmp, length);

/*将内核空间的数据复制到用户空间*/

       return length;

}

ssize_t led_write(struct file *filp, const char *Getbuf, size_t length, loff_t *f_pos)

{     int num;

unsigned char UsrWantLed;

copy_from_user(&UsrWantLed, Getbuf, length);     

/*将用户空间的写入到设备文件的内容传送到内核空间 */

num = ( (UsrWantLed) & 0xff );

LED_CS=~(1 << (num-1));  /*通过对LED_CS地址赋值来控制LED的亮灭 */

return (0);     

}

  推荐精品文章

·2024年6月目录 
·2024年5月目录 
·2024年4月目录 
·2024年3月目录 
·2024年2月目录 
·2024年1月目录
·2023年12月目录
·2023年11月目录
·2023年10月目录
·2023年9月目录 
·2023年8月目录 
·2023年7月目录
·2023年6月目录 
·2023年5月目录

  联系方式
TEL:010-82561037
Fax: 010-82561614
QQ: 100164630
Mail:gaojian@comprg.com.cn

  友情链接
 
Copyright 2001-2010, www.comprg.com.cn, All Rights Reserved
京ICP备14022230号-1,电话/传真:010-82561037 82561614 ,Mail:gaojian@comprg.com.cn
地址:北京市海淀区远大路20号宝蓝大厦E座704,邮编:100089