s3c2410的字符型设备驱动程序设计(共10页).doc

上传人:飞****2 文档编号:16270946 上传时间:2022-05-16 格式:DOC 页数:10 大小:235KB
返回 下载 相关 举报
s3c2410的字符型设备驱动程序设计(共10页).doc_第1页
第1页 / 共10页
s3c2410的字符型设备驱动程序设计(共10页).doc_第2页
第2页 / 共10页
点击查看更多>>
资源描述

《s3c2410的字符型设备驱动程序设计(共10页).doc》由会员分享,可在线阅读,更多相关《s3c2410的字符型设备驱动程序设计(共10页).doc(10页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。

1、精选优质文档-倾情为你奉上 福建工程学院 课程设计报告 实验课题: s3c2410的字符型设备驱动程序设计 指导老师:陈老师 日期:2011年5月24号一、 实验原理:1 Linux系统下驱动程序的相关概念: Linux系统中,设备驱动程序是操作系统内核的重要组成部分,它与硬件设备之间建立了标准的抽象接口。通过这个接口,用户可以像处理普通文件一样,对硬件设备进行打开(open)、关闭(close)、读写(read/write)等操作。通过分析和设计设备驱动程序,可以深入理解Linux系统和进行系统开发。Linux设备分为字符设备、块设备和网络设备。本课程设计研究字符型设备驱动程序设计。 Lin

2、ux系统为每一个设备分配了一个主设备号和 次设备号,主设备号标识设备对应驱动程序 ,次设备号标识具体设备的实例。例如一块开发板上有2个串口终端 / dev/ tty0, / dev/ tty1 ,它们的主设备号都是4,次设备号分别为0和1。每一类设备使用的主设备号是独一无二的,系统增加一个驱动程序就要赋予它一个主设备号,这一赋值过程在驱动程序的初始化过程中进行。2设备驱动程序的组成 设备驱动在加载时首先需要调用入口函数 init module ( ) ,该函数完成设备驱动的初始化工作 ,比如寄 存器置位、结构体赋值等一系列工作,其中最重要的一个工作就是向内核注册该设备 ,字符设备调用函数reg

3、ister_chrdev 完成注册。注册成功后 ,该设备获得了系统分配或向系统申请的主设备号、自定义的次设备号,并建立起与设备文件的关联。设备驱动在卸载时需要回收相应的资源 ,将设备的响应寄存器值复位并从系统中注销该设备。系统调用部分则是对设备的 操作过程 , 比如 open、read、write、ioctl等操作。设备驱动程序可以分成以下 3个主要部分: (1) 自动配置和初始化子程序。负责检测所需驱动的硬件设备是否存在以及是否能正常工作 ,这部分驱动程序仅在初始化时被调用一次。(2) 服务 I/O 就是请求子程序,是驱动程序的上半部分,这部分是系统调用的结果。 (3) 中断服务程序又称驱动

4、程序的下半部分,设备在 I/O请求结束或其他状态改变时产生中断。因为设备驱动程序一般支持同一类型的若干个设备 ,所以调用中断服务子程序时都带有一个或多个参数以唯一标识请求服务的设备。 3字符设备驱动程序中重要的数据结构和函数对于每个系统调用,驱动程序中都有一个与之对应的函数。对于字符设备驱动程序 ,这些函数集合在一个file_op erations类型的数据结构中,它定义了常见文件I/O 函数的入口.编写字符设备驱动程序就是为具体硬件的 file_ operations结构编写各个函数 ,大多数的驱动程序只是利用了其中的一部分 对于驱动程序中不提供的功能,把相应位置的值设为 NULL ) ,对

5、于字符设备来说 ,要提供的主要入口有: open ( ) 、release ( ) 、read ( ) 、write( ) 、lseek ( ) 、ioctl ( )等。本课程设计中用到的主要有 open ( )、read ( )、write( )、release ( )函数。int (*open)(struct inode*,struct file*); 该操作用来打开设备文件。int (*release)(struct inode*,struct file*); 该操作用来释放文件结构。ssize_t(*read)(structfile*,char_user*,size_t,loff_t*

6、); 该操作用来从设备中读取数据。ssize_t(*read)(structfile*,char_user*,size_t,loff_t*); 该操作发送数据给设备。4驱动程序的注册和卸载驱动程序有一个初始化函数 ,在安装驱动程序时会调用它。在初始化函数中会将驱动程序的 file_operations与主设备号一起向内核进行注册。对字符设备使用如下函数进行注册:int register_chrdev ( unsigned int major, const char* name, struct file_operations* fop s) ; 其中,major是为设备驱动程序向系统申请的主设备

7、号,如果为 0则系统动态地分配 l个主设备号, name是设备名。fop s是 file_operation s对各个调用入口点的说明。此函数返回0表示成功;返回 - 1是表示出 错;返回 - E INVAL 表示申请的主设备号非法;返回- EBU SY表示所申请的主设备号正在被其他设备驱动程序使用。模块在调用 rmmod 函数时被卸载 ,此时的入口点是 cleanup_module函数或宏 module_exit,并在其中完成对设备的注销。类似的,字符设备的卸载函数定义为:int unregister_chrdev ( unsigned int major, const char* name

8、) ;二、 实验目的:了解、掌握字符型驱动程序的设计过程、编译、加载以及测试过程,包括了解file_operation数据结构、驱动程序的注册与注销、makefile文件的编写。 三、 实验步骤:写入驱动程序源程序fakedev.c,本程序设计思维为设备输入一串字符,再输出同样的字符。设备驱动程序的主体流程为:module_init-fakedev_init_module-register_chrdev-fakedev_fops-fakkdev_open/release/read/write. 源代码fakedev.c#include /*预定义和必要的头文件*/#include #inclu

9、de #include #include #include #include #include #include #include #include #include #include #include #define DEVICE_NAME fake deviceMODULE_LICENSE(Dual BSD/GPL); /*用宏来声明该模块的许可协议*/struct fake_device /* 该设备其他的私有数据和信号量的信息的定义 */int usage;char *data;int new_msg;struct fake_device fakedev; int fakedev_ma

10、jor = 200; /*指定设备主设备号为200*/ /*以下为file_operation数据结构*/static int fakedev_open(struct inode *inode, struct file *file) /*定义了fakedev_open即打开操作函数,这里函数定义为只打印一行消息*/ printk (fakedev_device_open(%p,%p)n, inode, file); return 0;static int fakedev_release(struct inode *inode, struct file *file) /*定义了 fakedev_

11、release即释放文件结构函数。*/static void fakedev_device_release(%p,%p)n, inode, file);static ssize_t fakedev_read(struct file *f,char *buf,int size,loff_t off) /*定义了 fakedev_read即从设备中读取数据的函数*/ int length;int count=size;if(count0)return -EINVAL;if(fakedev.usage)return -EBUSY;fakedev.usage=1;if(fakedev.data =0

12、)return 0;length = strlen(fakedev.data);if (length count)count=length;copy_to_user(buf,fakedev.data,count+1);fakedev.new_msg=0;fakedev.usage=0;return count;static ssize_t fakedev_write(struct file *f,const char *buf,int size,loff_t off) /*定义fakedev_write函数即发送数据给设备函数*/ int count=size;if(count0)return

13、 -EINVAL;if(fakedev.usage|fakedev.new_msg)return -EBUSY;fakedev.usage = 1;kfree(fakedev.data);fakedev.data = kmalloc(sizeof(char)*(count + 1),GFP_KERNEL);if(!fakedev.data)return -ENOMEM;copy_from_user(fakedev.data,buf,count + 1);fakedev.usage = 0;fakedev.new_msg = 1;return count;struct file_operatio

14、ns fakedev_fops = /*定义该字符设备的具体文件操作,包括read、write、open、release*/.read = fakedev_read, .write = fakedev_write,.open = fakedev_open,.release = fakedev_release,;static int fakedev_init_module(void) /*定义fakedev_init_module,即字符设备向 系统注册函数*/ int result;result = register_chrdev(fakedev(fakedev_major,DEVICE_NA

15、ME,&fakedev_fops);if (result 0)return result;if (fakedev_major = 0)fakedev_major = result;printk(KERN_INFO Register FAKEDEV.major-number=%dn,result);return 0;static void fakedev_cleanup_module(void) /*定义fake_exit_module,即字符设备向系统注销函数*/ printk(KERN_INFO Unregister FAKEDEVn);unregister_chrdev(fakedev_m

16、ajor, DEVICE_NAME);module_init(fakedev_init_module); /*包含了注册、注销两个函数的指针*/module_exit(fakedev_cleanup_module);Makefile文件:在linux2.6内核中,模块的编译需要配置过的内核代码,编译过程首先会到内核源码目录下,读取顶层的makefile文件,然后再返回模块代码所在目录进行编译.可根据网络上公开的针对字符设备驱动程序的makefile模板进行该模块makefile文件设计。 Makefile文件# Makefile2.6ifneq ($(KERNELRELEASE),)#kbui

17、ld syntax. dependency relationshsip of files and target modules are listed here.obj-m := fakedev.o /*指定模块源文件*/elsePWD := $(shell pwd)KVER ?= $(shell uname -r)KDIR := /lib/modules/$(KVER)/build /*指定内核源码的路径*/all : $(MAKE) -C $(KDIR) M=$(PWD)clean : rm -rf .*.cmd *.o *.mod.c *.ko .tmp_versionsendif通过执行

18、makefile来编译驱动程序的源文件fakedev.c,以得到可执行目标文件。截图如下:由截图可见:编译之后得到可加载模块fakedev.ko。fakedev源程序的测试程序fakedev_test.c。测试的例程:运行之前需要使用mkond命令来创建设备文件,然后执行不带参数的insmod,将上面编译得到的可加载模块fakedev.ko装载到内核。测试代码fakedev_test.c#include /*所需头文件与预定义*/#include#include#include#include#include#define MAX_LENGTH 100int mian (int argc, c

19、har *argv)char strMAX_LENGTH;char p;printf(please enter the words(max char num:%d):n,MAX_LENGTH -1);p = fgets(str,MAX_LENGTH,stdin); /*接收控制台输入的一组字符串*/int fakedev_fd=open(/dev/fakedev,O_RDWR);/*通过open系统调用打开虚拟设 if (fakedev_fd=-1) 备并获得文件描述符fakedev_fd*/perror(open);exit (1);write (fakedev_fd,p,strlen(p)

20、; /*通过write系统调用将字符串缓存到该设备中*/char bufMAX_LENGTH; /*将字符取出来打印到标准输出*/read(fakedev_fd,buf,MAX_LENGTH -1);printf(Get strings from fakedev:n%sn, buf);close (fakedev_fd);return 0;截图如下: 由上图可看到:mknod命令指定了主设备号200,其余的参数:-m600设置为设备文件的读写权限;字符c代表这是一个字符设备;200之后的1为次设备号。使用insmod命令将fakedev.ko加载之后,就可以从/proc/devices看到设备

21、文件fake device( 在源代码中已经被定义)测试运行程序:运行test,就可在终端中摸拟本设计程序的功能。如若能够在输入一行字符串之后,终端能自行输出同样的字符串,则说明该程序设计正确。即输入: #./test 测试结果达到了我们需要的效果:输入字符22之后,通过write系统调用将其写入/dev/fakedev设备中,再通过read系统调用从该设备中得到了该字符串。四 实验总结:本文结合简单字符设备驱动程序的开发,详细讨论了嵌入式 L inux系统中字符设备驱动程序的设计方法和关键技术 ,对类似的其他字符设备驱动程序开发过程可以起到一定的启发作用。在编译过程中会遇到找不到头文件的问题,这时可以通过寻找添加头文件以求编译通过。专心-专注-专业

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 教育专区 > 教案示例

本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知淘文阁网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

工信部备案号:黑ICP备15003705号© 2020-2023 www.taowenge.com 淘文阁