收藏 分销(赏)

linux嵌入式系统驱动程序.ppt

上传人:仙人****88 文档编号:14755125 上传时间:2026-11-14 格式:PPT 页数:31 大小:469.50KB 下载积分:10 金币
下载 相关
linux嵌入式系统驱动程序.ppt_第1页
第1页 / 共31页
linux嵌入式系统驱动程序.ppt_第2页
第2页 / 共31页


点击查看更多>>
资源描述
单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,信息学院,嵌入式,Linux,驱动程序开发,目前,,Linux,软件工程师大致可分为两个层次:,(,1,),Linux,应用软件,工程师(,Application Software,Engineer,):主要利用,C,库函数和,Linux API,进行应用软,件的编写;,(,2,),Linux,固件,工程师(,Firmware Engineer,):主要进行,Bootloader,、,Linux,的移植及,Linux,设备驱动程序的设计。,一般而言,固件工程师的要求要高于应用软件工程师的层,次,而其中的,Linux,设备驱动编程又是,Linux,程序设计中,比较复杂的部分。,编写驱动程序难度大的主要原因包括如下几个方面:,(,1,)设备驱动属于,Linux,内核的部分,编写,Linux,设备驱动需要有一定的,Linux,操作系统,内核,基础;,(,2,)编写,Linux,设备驱动需要对,硬件的原理,有相当的了解,大多数情况下我们是针对一个,特定的嵌入式硬件平台,编写驱动的;,(,3,),Linux,设备驱动中广泛涉及到多进程并发的同步、互斥等控制,容易出现,bug,;,(,4,)由于属于内核的一部分,,Linux,设备驱动的调试也相当复杂。,设备驱动程序是操作系统内核和机器硬件之间的,接口,。设备驱动程序为应用程序,屏蔽,了硬件的细节,这样在应用程序看来,硬件设备只是一个,设备文件,,应用程序可以象操作普通文件一样对硬件设备进行操作。设备驱动程序是内核的,一部分,,它完成以下的功能,:,什么是设备驱动,1.,对设备,初始化,和,释放,;,2.,把数据从内核传送到硬件和从硬件读取数据;,3.,读取应用程序传送给设备文件的数据和回送应用程序请求的数据;,4.,检测和处理设备出现的错误。,设备,驱动,内核,应用程序之间的,调用,关系:,Linux,内核体系结构,Linux,对硬件设备支持两个标准接口,:,块,特别设备文件和,字符,特别设备文件,通过块,(,字符,),特别设备文件存取的设备称为块,(,字符,),设备或具有块,(,字符,),设备接口。,块设备接口,仅支持面向块的,I/O,操作,所有,I/O,操作都通过在内核地址空间中的,I/O,缓冲区,进行,它可以运行几乎在,任意长度,和,任意位置,上的,I/O,请求,即提供,随机存取,的功能。,字符设备接口,支持面向字符的,I/O,操作,它,不经过,系统的,快速缓存,所以它们负责管理自己的缓冲区结构。字符设备接口只支持,顺序存取,的功能,一般不能进行任意长度的,I/O,请求,而是限制,I/O,请求的长度必须是设备要求的基本块长的倍数。,设备程序驱动程序可以分为三个主要组成,:,(,1,),自动配置和初始化子程序,负责检测所要驱动的硬件设备是否存在和是否能正常工作。如果该设备正常,则对这个设备及其相关的设备驱动程序需要的,软件状态,进行初始化。,这部分驱动程序仅在初始化的时候被调用一次。,(,2,),服务于,I/O,请求的子程序,又称为驱动程序的,上半部分,。调用这部分是由于,系统调节调用,的,结果。,这部分程序在执行的时候,系统仍认为是和进行调用的进程属于,同一个进程,只是由,用户态变成了核心态,具有进行此系统调用的用户程序的运行环境,因此可以在其中调用,sleep(),等与进程运行环境有关的函数。,(,3,),中断服务子程序,又称为驱动程序的下半部分。,设备驱动程序的开发过程,由于嵌入式设备由于硬件种类非常丰富,在默认的,内核发布版,中不一定包括所有驱动程序。所以进行嵌入式,Linux,系统的开发,很大的工作量是为各种设备,编写驱动程序,。除非系统不使用操作系统,程序直接操纵硬件。,嵌入式,Linux,系统驱动程序开发,与普通,Linux,开发没有区别。可以在硬件生产厂家或者,Internet,上寻找驱动程序,也可以根据,相近的,硬件驱动程序来改写,以加快开发速度。实现一个嵌入式,Linux,设备驱动的大致流程如下:,(,1,),查看原理图。,理解设备的,工作原理,。一般嵌入式处理器的生产商提供参考电路,也可以根据需要自行设计。,(,2,),定义设备号。,设备由一个主设备号和一个次设备号来标识。主设备号,惟一标识,了设备类型,即设备驱动程序类型,它是块设备表或字符设备表中设备表项的索引。次设备号仅由设备驱动程序解释,区分被一个设备驱动控制下的某个独立的设备。,(,3,),实现初始化函数。,在驱动程序中实现驱动的,注册,和,卸载,。,(,4,),设计所要实现的文件操作。,定义,file_operations,结构。,(,5,),实现所需的文件操作调用,。如,read,、,write,等。,(,6,),实现中断服务。,并用,request_irq,向内核注册,中断并不是每个设备驱动所必需的。,(,7,),编译该驱动程序到内核中,或者用,insmod,命令加载模块。,(,8,),测试该设备。,编写应用程序,对驱动程序进行测试。,Linux,字符型驱动程序框架,Linux,设备驱动程序的代码结构大致可以分为如下几个部分:,注册设备。,在系统初启,或者模块加载时,将设备,登记,到相应的,设备数组,,并返回设备的主驱动号;,定义功能函数。,对于每一个驱动程序函数来说,都有一些和此设备密切相关的,功能,函数,无论是块设备或字符设备,都存在着,open(),,,read(),,,write(),,,ioctrl,(),这一类的操作。当系统使用这些调用时,将自动使用驱动函数中,特定的模块,,以实现具体的操作。对于特定的设备,系统调用对应的函数是一定的。,卸载设备,一个最简单字符驱动程序,,由下面,7,个函数和,1,个结构体就可组成。,Open,(),,Release,(),,Write,(),,Read,(),,Ioctl,(),,Init,(),,Exit,()和,Struct,file_operations,(,设备驱动程序接口,它的定义位于,include/,linux/fs.h,中,)。,static,int,my_open(struct,inode,*,inode,struct,file*,filp,),设备打开时的操作,static,int,my_release(struct,inode,*,inode,struct,file*,filp,),设备关闭时的操作,static,int,my_write(struct,file*,file,const char*buffer,size_t,count,loff_t,*,ppos,),设备写入时的操作,static,int,my_read(struct,file*,file,const char*buffer,size_t,count,loff_t,*,ppos,),设备读取时的操作,Static,int,my_ioctl(struct,inode,*,inode,struct,file*,filp,unsigned,int,cmd,unsigned long,arg,),设备的控制操作,static,int,_init,my_init(void,),初始化硬件,注册设备,创建设备节点,static void _exit,my_exit(void,),删除设备节点,注销设备,static,struct,file_operations,my_fops,=,对文件操作结构体成员定义初始值,open(),函数,对设备特殊文件进行,open(),系统调用时,将调用驱动程序的,open(),函数:,int,(*,open)(struct,inode,*,struct,file*);,参数,inode,为设备特殊文件的,inode,(,索引结点,),结构的,指针,;,参数,file,是指向这一设备的,文件结构,的指针。,open(),的主要任务是确定硬件处在就绪状态、验证次设备号的合法性,(,次设备号可以用,MINOR(inode,-i-,rdev,),取得,),、控制使用设备的进程数、根据执行情况返回状态码,(0,表示成功,负数表示存在错误,),等;,release(),函数,当最后一个打开设备的用户进程执行,close(),系统调用时,内核将调用驱动程序的,release(),函数:,void(*release)(,struct,inode,*,struct,file*);,release,函数的主要任务是清理未结束的输入,/,输出操作、释放资源、用户自定义排他标志的复位等。,write(),函数,当设备特殊文件进行,write(),系统调用时,将调用驱动程序的,write(),函数:,ssize_t,(*write)(,struct,file*,const char*,size_t,loff_t,*);,向设备发送数据。如果没有这个函数,,write,系统调用会向调用程序返回一个,-EINVAL,。,如果返回值非负,则表示成功写入的字节数。,read(),函数,当对设备特殊文件进行,read(),系统调用时,将调用驱动程序,read(),函数:,ssize_t,(*read)(,struct,file*,char*,size_t,loff_t,*);,用来从设备中读取数据。当该函数指针被赋为,NULL,值时,将导致,read,系统调用出错,并返回,-EINVAL,(“,Invalid argument,,非法参数”)。函数返回非负值表示成功读取的字节数(返回值为“,signed size”,数据类型,通常就是目标平台上的固有整数类型)。,ioctl,(),函数,该函数是特殊的控制函数,可以通过它向设备传递控制信息或从设备取得状态信息,函数原型为:,int,(*,ioctl,)(,struct,inode,*,struct,file*,unsigned,int,unsigned long);,unsigned,int,参数为设备驱动程序,要执行的,命令的代码,由用户自定义,,unsigned long,参数为相应的命令,提供参数,,类型可以是整型、指针等。如果设备不提供,ioctl,入口点,则对于任何内核未预先定义的请求,,ioctl,系统调用将返回错误(,-ENOTTY,,“,No such,ioctl,for device,,该设备无此,ioctl,命令”)。如果该设备方法返回一个非负值,那么该值会被,返回给调用程序,以表示调用成功。,驱动程序的实现驱动程序框架,#include,#include,#include,#include,/*,printk,()*/,#include,/*everything.*/,#include,/*error codes*/,#include,/*,size_t,*/,#include,#include,/*O_ACCMODE*/,#include,/*COPY_TO_USER*/,#include,/*,cli,(),*_flags*/,#define,DEVICE_NAMEdemo,#define,demo_MAJOR,250,#define,demo_MINOR,0,static,ssize_t,demo_write(,struct,file*,filp,const,char,*buffer,size_t,count),copy_from_user(drv_buf,buffer,count);,WRI_LENGTH=count;,printk(user,write data to drivern);,/your code here,return,count;,static,ssize_t,demo_read(,struct,file*,filp,char,*buffer,size_t,count,loff_t,*,ppos,),if,(count,MAX_BUF_LEN),count=MAX_BUF_LEN;,copy_to_user(buffer,drv_buf,count,);,printk(user,read data from drivern);,return,count;,static,int,demo_ioctl(,struct,inode,*,inode,struct,file*,file,unsigned,int,cmd,unsigned,long,arg,),printk(ioctl,runingn,);,switch,(cmd,),case,1:printk(runing command 1,n);,break,;,case,2:printk(runing command 2,n);,break,;,default,:,printk(error,cmd,number,n);,break,;,return,0;,static,int,demo_open(,struct,inode,*,inode,struct,file*,file,),MOD_INC_USE_COUNT;,sprintf(drv_buf,device,open,sucess!n,);,printk(device,open,sucess!n,);,return,0;,static,int,demo_release(,struct,inode,*,inode,struct,file*,filp,),MOD_DEC_USE_COUNT;,printk(device,releasen);,return,0;,static,struct,file_operations,demo_fops,=,owner:THIS_MODULE,write:,demo_write,read:,demo_read,ioctl,:,demo_ioctl,open:,demo_open,release:,demo_release,;,static,int,_init,demo_init(,void,),SET_MODULE_OWNER(&demo_fops,);,result=,register_chrdev(demo_MAJOR,demo,&,demo_fops,);,if,(result 0),return,result;,printk(DEVICE_NAME,initializedn);,return,0;,static,void,_exit,demo_exit(,void,),unregister_chrdev(demo_MAJOR,demo);,printk(DEVICE_NAME,unloadedn);,module_init(demo_init,);,module_exit(demo_exit,);,#include,模块头文件,#include,驱动要写入内核,与内核相关的头文件,#include,文件系统头文件,#include,初始化头文件,#include,延时头文件,#include,与处理器相关的中断,#include,操作系统中断,#include,与处理器相关的入口,#include,与处理器相关的,IO,口操作,#include,同上,#include,与处理器相关的硬件,#include,同上,#include,设备驱动文件,#include,轮询文件,#include,操作系统相关的,IO,口文件,#include,标准输入输出,#include,标准库,#include,用于读写,#include IO,控制,#include,变量类型的头文件,因为,linux,要兼容各种长度的变量,#include,文件操作的头文件,#include,同上,#include,同上,#include,时间编程的头文件,#include,错误代码头文件,测试程序实例,/,test.c,#include,#include,#include,int,main(),int,fd,;,fd,=open(/dev/demo,O_RDWR);,if,(fd,0),exit(fd,);,/your code here,read(fd,buffer,size);,write(fd,buffer,size);,.,close(fd,);,return,0;,
展开阅读全文

开通  VIP、SVIP  下载更划算
下载10份以上建议开通 VIP 会员
下载20份以上建议开通SVIP会员


开通VIP      成为共赢上传

当前位置:首页 > 包罗万象 > 大杂烩

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        关注我们

©2010-2026 宁波自信网络信息技术有限公司  版权所有

客服电话:0574-28810668  投诉电话:18658249818

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :微信公众号    抖音    微博    LOFTER 

客服