[精选]Linux设备驱动程序课件.pptx

上传人:lil****205 文档编号:96463993 上传时间:2023-11-29 格式:PPTX 页数:63 大小:548.07KB
返回 下载 相关 举报
[精选]Linux设备驱动程序课件.pptx_第1页
第1页 / 共63页
[精选]Linux设备驱动程序课件.pptx_第2页
第2页 / 共63页
点击查看更多>>
资源描述

《[精选]Linux设备驱动程序课件.pptx》由会员分享,可在线阅读,更多相关《[精选]Linux设备驱动程序课件.pptx(63页珍藏版)》请在得力文库 - 分享文档赚钱的网站上搜索。

1、Linux设备驱动设备驱动广州嵌入式软件公共技术支持中心2007年07月设备驱动概述设备驱动概述l操作系统是通过各种驱动程序来驾驭硬件设备,它为用操作系统是通过各种驱动程序来驾驭硬件设备,它为用户屏蔽了各种各样的设备户屏蔽了各种各样的设备,硬件设备的抽象。硬件设备的抽象。l设备驱动程序设备驱动程序:处理和管理硬件控制器的软件。处理和管理硬件控制器的软件。l设备驱动程序是操作系统内核和机器硬件之间的接口。设备驱动程序是操作系统内核和机器硬件之间的接口。设备驱动概述设备驱动概述l设备由两局部组成,一个是被称为控制器的电器局部,设备由两局部组成,一个是被称为控制器的电器局部,另一个是机械局部。另一个

2、是机械局部。l一组存放器组被赋予到各个控制器。一组存放器组被赋予到各个控制器。I/O端口包含端口包含4组存组存放器,即状态存放器,控制存放器,数据输入存放器,放器,即状态存放器,控制存放器,数据输入存放器,数据输出存放器。数据输出存放器。状态存放器拥有可以被状态存放器拥有可以被CPU读取的读取的状态状态位,用位,用来来指示当前命令是否执行完毕,或者字节是否可以指示当前命令是否执行完毕,或者字节是否可以被读出或写入,以及任何错误提示。被读出或写入,以及任何错误提示。控制存放器则用于启动一条命令指令或者改变控制存放器则用于启动一条命令指令或者改变设备的设备的工作工作模式。模式。数据输入存放器用于获

3、取输入的数据。数据输入存放器用于获取输入的数据。数据输出存放器则向数据输出存放器则向CPU发送结果。发送结果。l处理器和设备之间的基本界面是控制和状态存放器。处理器和设备之间的基本界面是控制和状态存放器。设备驱动概述设备驱动概述l存放器拥有在存放器拥有在I/O空间明确定义的地址范围。空间明确定义的地址范围。l通常这些地址在启动时被分配。通常这些地址在启动时被分配。如果设备是静态加载的如果设备是静态加载的,各个设备的地址范围可能被预各个设备的地址范围可能被预分配。这意味内核包含了已存在设备的驱动分配。这意味内核包含了已存在设备的驱动程序。通程序。通过运行过运行“cat/proc/ioports命

4、令检查其所使用的地命令检查其所使用的地址范围。第一列输出显示了端口的范围而第二列则是址范围。第一列输出显示了端口的范围而第二列则是拥用这些端口的设备。拥用这些端口的设备。设备驱动概述设备驱动概述l设备驱动的概念是非常抽象的并且处于一台计算设备驱动的概念是非常抽象的并且处于一台计算上所运行软件的最低层。上所运行软件的最低层。l由于直接到设备的硬件特性的限由于直接到设备的硬件特性的限制。每个设备驱制。每个设备驱动都只管理一种单一类型的设备。动都只管理一种单一类型的设备。l如果一个应用如果一个应用程序向设备提出操作要求。内程序向设备提出操作要求。内核会联系到对应的设备驱动,设备驱动接着向特核会联系到

5、对应的设备驱动,设备驱动接着向特定的设备发出命令。定的设备发出命令。l设备驱设备驱动是一个函数集合:包含了许多调用入口,动是一个函数集合:包含了许多调用入口,类似于类似于open,close,read,write,ioctl,llseek等。等。设备驱动概述设备驱动概述lLinuxLinux操作系统把设备纳入文件系统的范畴来管理。操作系统把设备纳入文件系统的范畴来管理。l文件操作是对设备操作的组织和抽象。设备操作则是对文件操作是对设备操作的组织和抽象。设备操作则是对文件操作的最终实现。文件操作的最终实现。l每个设备都对应一个文件名,在内核中也就对应一个索每个设备都对应一个文件名,在内核中也就对

6、应一个索引节点。引节点。l对文件操作的系统调用大都适用于设备文件。对文件操作的系统调用大都适用于设备文件。l从应用程序的角度看,设备文件逻辑上的空间是一个线从应用程序的角度看,设备文件逻辑上的空间是一个线性空间起始地址为性空间起始地址为0 0,每读取一个字节加,每读取一个字节加1 1。从这个。从这个逻辑空间到具体设备物理空间如磁盘的磁道、扇区逻辑空间到具体设备物理空间如磁盘的磁道、扇区的映射则是由内核提供,并被划分为文件操作和设备驱的映射则是由内核提供,并被划分为文件操作和设备驱动两个层次。动两个层次。设备驱动概述设备驱动概述lLinuxLinux将设备分成两大类。将设备分成两大类。一类像键盘

7、那样以字符字节为单位,逐个字符一类像键盘那样以字符字节为单位,逐个字符进行输入输出的设备,称为字符设备。进行输入输出的设备,称为字符设备。一类是像磁盘那样以块或扇区为单位,成块进行输一类是像磁盘那样以块或扇区为单位,成块进行输入输出的设备,称为块设备。入输出的设备,称为块设备。文件系统通常都建立在块设备上。文件系统通常都建立在块设备上。设备驱动概述设备驱动概述l文件操作和设备驱动是对一个具体的设备操作的不同层文件操作和设备驱动是对一个具体的设备操作的不同层次。从这种观点出发,从概念上可以把一个系统划分为次。从这种观点出发,从概念上可以把一个系统划分为应用、文件系统和设备驱动三个层次。应用、文件

8、系统和设备驱动三个层次。设备驱动概述设备驱动概述设备驱动概述设备驱动概述l要使一项设备可以被应用程序访问,首先要在系统中建要使一项设备可以被应用程序访问,首先要在系统中建立一个代表此设备的设备文件,这是通过系统调用立一个代表此设备的设备文件,这是通过系统调用mknodemknode实现的。此外,更重要的是在设备驱动层要实现的。此外,更重要的是在设备驱动层要有这种设备的驱动程序。有这种设备的驱动程序。设备驱动概述设备驱动概述l设备文件:设备文件:任何设备都被当作路径任何设备都被当作路径/dev的设备文件处理,并通的设备文件处理,并通过这些设备文件提供访问硬件的方法。过这些设备文件提供访问硬件的方

9、法。每个设备文件除了设备名外,还有类型、主设备号、每个设备文件除了设备名外,还有类型、主设备号、次设备号这三个属性。次设备号这三个属性。设备文件是通过设备文件是通过mknodmknod系统调用创立的。其原型为:系统调用创立的。其原型为:mknodmknodconst char*filename,int mode,dev_t const char*filename,int mode,dev_t devdevmknod/dev/led0 c 253 0 mknod/dev/led0 c 253 0 设备驱动概述设备驱动概述l主设备号和次设备号:主设备号和次设备号:主设备号标识设备对应的驱动程序。一

10、般主设备号标识设备对应的驱动程序。一般“一个主一个主设备号对应一个驱动程序设备号对应一个驱动程序次设备号用于确定设备文件所指的设备。次设备号用于确定设备文件所指的设备。可通过可通过lsl“设备文件名命令查看设备的主次设设备文件名命令查看设备的主次设备号,以及设备的类型。备号,以及设备的类型。设备驱动概述设备驱动概述l主设备号和次设备号的内部表达:主设备号和次设备号的内部表达:Dev_t类型用于保存设备号,称为设备编号。类型用于保存设备号,称为设备编号。/linux/types.h文件中定义。文件中定义。目前设备编号目前设备编号dev_t是一个是一个32位的整数,其中位的整数,其中12位位表示主

11、设备号,表示主设备号,20位表示次设备号。位表示次设备号。通过设备编号获取主次设备号:通过设备编号获取主次设备号:MAJORdev_tdev;MINORdev_tdev;通过主次设备号合成设备编号:通过主次设备号合成设备编号:MKDEVintmajor,intminor;Dev_t格式以后可能会发生变化,但只要使用这些格式以后可能会发生变化,但只要使用这些宏,就可保证设备驱动程序的正确性。宏,就可保证设备驱动程序的正确性。一些重要的数据结构一些重要的数据结构l大局部驱动程序涉及三个重要的内核数据结构:大局部驱动程序涉及三个重要的内核数据结构:文件操作文件操作file_operations结构体

12、结构体文件对象文件对象file结构体结构体索引节点索引节点inode结构体结构体一些重要的数据结构一些重要的数据结构l文件操作结构体文件操作结构体file_operations结构体结构体file_operations在头文件在头文件linux/fs.h中定义,中定义,用来存储驱动内核模块提供的对设备进行各种操作用来存储驱动内核模块提供的对设备进行各种操作的函数的指针。的函数的指针。结构体的每个域都对应着驱动模块用来处理某个被结构体的每个域都对应着驱动模块用来处理某个被请求的事务的函数的地址。请求的事务的函数的地址。structfile_operationsstructmodule*owner

13、;loff_t*llseekstructfile*,loff_t,int;ssize_t*readstructfile*,char_user*,size_t,loff_t*;ssize_t*writestructfile*,constchar_user*,size_t,loff_t*;。一些重要的数据结构一些重要的数据结构lfile_operations重要的成员重要的成员Structmodule*owner,指向拥有该结构体的模,指向拥有该结构体的模块的指针。块的指针。方法方法llseek用来修改文件的当前读写位置,把新位用来修改文件的当前读写位置,把新位置作为返回值返回。置作为返回值返回。

14、方法方法read用来从设备中读取数据。非负返回值表示用来从设备中读取数据。非负返回值表示成功读取的直接数。成功读取的直接数。方法方法write向设备发送数据。向设备发送数据。方法方法ioctl提供一种执行设备特定命令的方法。提供一种执行设备特定命令的方法。一些重要的数据结构一些重要的数据结构lfile_operations重要的成员重要的成员驱动内核模块是不需要实现每个函数的。相对应的驱动内核模块是不需要实现每个函数的。相对应的file_operations的项就为的项就为NULL。Gcc的语法扩展,使得可以定义该结构体:的语法扩展,使得可以定义该结构体:structfile_operatio

15、nsfops=read:device_read,write:device_write,open:device_open,release:device_release;这种语法清晰,没有显示声明的结构体成员都被这种语法清晰,没有显示声明的结构体成员都被gcc初始化为初始化为NULL。一些重要的数据结构一些重要的数据结构lfile_operations重要的成员重要的成员标准标准C的标记化结构体的初始化方法:的标记化结构体的初始化方法:structfile_operationsfops=.read=device_read,.write=device_write,.open=device_open,

16、.release=device_release;推荐使用该方法,提高移植性,方法允许对结构体成员进行重推荐使用该方法,提高移植性,方法允许对结构体成员进行重新排列。没有显示声明的结构体成员同样都被新排列。没有显示声明的结构体成员同样都被gcc初始化为初始化为NULL。指向结构体指向结构体file_operations的指针通常命名为的指针通常命名为fops。一些重要的数据结构一些重要的数据结构l文件对象文件对象file结构体结构体文件对象文件对象file代表着一个翻开的文件。代表着一个翻开的文件。进程通过文件进程通过文件描述符描述符fdfd与已翻开文件的与已翻开文件的filefile结构相联系

17、。进程通结构相联系。进程通过它对文件的线性逻辑空间进行操作。例如:过它对文件的线性逻辑空间进行操作。例如:file-file-f_op-readf_op-read;Struct file Struct file 在在中定义。中定义。指向结构体指向结构体struct file的指针通常命名为的指针通常命名为filp,或者,或者file。建议使用文件指针。建议使用文件指针filp。一些重要的数据结构一些重要的数据结构l文件对象文件对象file结构体的成员结构体的成员Structfile_operations*f_op;与文件相关的操作结构体指针。与文件相关的操作与文件相关的操作结构体指针。与文件相

18、关的操作是在翻开文件的时候确定下来的,也就是确定该指是在翻开文件的时候确定下来的,也就是确定该指针的值。可在需要的时候,改变指针所指向的文件针的值。可在需要的时候,改变指针所指向的文件操作结构体。用操作结构体。用C语言实现面向对象编程的方法重语言实现面向对象编程的方法重载。载。其他成员可先忽略,后面具体实例分析。因为设备其他成员可先忽略,后面具体实例分析。因为设备驱动模块并不自己直接填充结构体驱动模块并不自己直接填充结构体file,只是使用,只是使用file中的数据。中的数据。一些重要的数据结构一些重要的数据结构l索引节点索引节点inode结构结构文件翻开,在内存建立副本后,由唯一的索引节点文

19、件翻开,在内存建立副本后,由唯一的索引节点inode描述。描述。与与file结构不同。结构不同。file结构是进程使用的结构,进程每翻开一个文结构是进程使用的结构,进程每翻开一个文件,就建立一个件,就建立一个file结构。不同的进程翻开同一结构。不同的进程翻开同一个文件,建立不同的个文件,建立不同的file结构。结构。Inode结构是内核使用的结构,文件在内存建立结构是内核使用的结构,文件在内存建立副本,就建立一个副本,就建立一个inode结构来描述。一个文件结构来描述。一个文件在内存里面只有一个在内存里面只有一个inode结构对应。结构对应。一些重要的数据结构一些重要的数据结构l索引节点索引

20、节点inode结构结构Inode结构包含大量描述文件信息的成员变量。结构包含大量描述文件信息的成员变量。但是对于描述设备文件的但是对于描述设备文件的inode,跟设备驱动有关,跟设备驱动有关的成员只有两个。的成员只有两个。Dev_ti_rdev;包含真正的设备编号。包含真正的设备编号。Structcdev*i_cdev;指向指向cdev结构体的指针。结构体的指针。cdev是表示字符设备的内核数据结构。是表示字符设备的内核数据结构。从从inode中获得主设备号和次设备号的宏:中获得主设备号和次设备号的宏:Unsignedintiminorstructinode*inode;Unsignedint

21、imajorstructinode*inode;驱动程序中的内存分配驱动程序中的内存分配l在在Linux内核模式下,不能使用用户态的内核模式下,不能使用用户态的malloc和和free函数申请和释放内存。函数申请和释放内存。l内核编程最常用的内存申请和释放函数为内核编程最常用的内存申请和释放函数为kmalloc和和kfree,其原型为:,其原型为:include/linux/kernel.hvoid void*kmalloc*kmallocunsigned unsigned int int len,len,int int prioritypriority;void kfreevoid kfre

22、evoid*_ptrvoid*_ptr;priority参数参数:通常设置为通常设置为GFP_KERNEL,可能会引起睡眠,可能会引起睡眠.如果在中断效劳程序里申请内存则要用如果在中断效劳程序里申请内存则要用GFP_ATOMIC参数,参数,在中断中是不允许睡眠的。在中断中是不允许睡眠的。初始化和卸载函数初始化和卸载函数l驱动程序是内核的一局部,因此我们需要给其添驱动程序是内核的一局部,因此我们需要给其添加模块初始化函数,该函数用来完成对所控设备加模块初始化函数,该函数用来完成对所控设备的初始化工作,并调用的初始化工作,并调用register_chrdev函函数注册字符设备数注册字符设备.int

23、 register_chrdevunsigned int major,const char*name,struct file_operations*fops;major 是给定的主设备号。为0代表什么?name 是驱动的名字将出现在/proc/devices,fops 是设备驱动的file_operations 结构。register_chrdev 将给设备分配 0-255 的次设备号,并且为每一个建立一个缺省的 cdev 结构。l与模块初始化函数对应的就是模块卸载函数,需与模块初始化函数对应的就是模块卸载函数,需要调用要调用register_chrdev的的反函数反函数设备操作函数集的定义设

24、备操作函数集的定义lfile_operations结构体,驱动程序只是利用其中结构体,驱动程序只是利用其中的一局部。的一局部。l对于字符设备来说,要提供的主要入口有:对于字符设备来说,要提供的主要入口有:open、release、read、write、ioctl等。等。设备操作函数集的定义设备操作函数集的定义lopen函数函数对设备特殊文件进行对设备特殊文件进行open系统调用时,将调用驱系统调用时,将调用驱动程序的动程序的open函数:函数:int int*open*openstruct inode*,struct file*struct inode*,struct file*;参数参数in

25、ode为设备特殊文件的为设备特殊文件的inode索引结点索引结点结构的指针,结构的指针,参数参数file是指向这一设备的文件结构的指针。是指向这一设备的文件结构的指针。open的主要任务是确定硬件处在就绪状态、验证的主要任务是确定硬件处在就绪状态、验证次设备号的合法性次设备号的合法性次设备号可以用次设备号可以用MINORinode-i-rdev取得取得、控制使用设备的进程数、根据执、控制使用设备的进程数、根据执行情况返回状态码行情况返回状态码0表示成功,负数表示存在错误表示成功,负数表示存在错误等;等;设备操作函数集的定义设备操作函数集的定义lrelease函数函数当最后一个翻开设备的用户进程

26、执行当最后一个翻开设备的用户进程执行close系统系统调用时,内核将调用驱动程序的调用时,内核将调用驱动程序的release函数:函数:void void*release*release struct inode*,struct file struct inode*,struct file*;release函数的主要任务是清理未结束的输入函数的主要任务是清理未结束的输入/输出操输出操作、释放资源、用户自定义排他标志的复位等作、释放资源、用户自定义排他标志的复位等.设备操作函数集的定义设备操作函数集的定义lread函数函数lRead的任务的任务,就是从设备拷贝数据到用户空间。就是从设备拷贝数据到

27、用户空间。当对设备特殊文件进行当对设备特殊文件进行read系统调用时,将调系统调用时,将调用驱动程序用驱动程序read函数:函数:ssize_t readstruct file*filp,char _user*buff,size_t count,loff_t*offp;filp 是文件对象指针,count 是请求的传输数据大小.buff 参数对write来说是指向持有被写入数据的缓存,对read则是放入新数据的空缓存.offp 是指向一个“long offset type的指针,它指出用户正在存取的文件位置.返回值是“signed size type类型;设备操作函数集的定义设备操作函数集的定

28、义lwrite函数函数Write的任务,则从用户空间拷贝数据到设备。的任务,则从用户空间拷贝数据到设备。当设备特殊文件进行当设备特殊文件进行write系统调用时,将调用系统调用时,将调用驱动程序的驱动程序的write函数:函数:ssize_t writestruct file*filp,const char _user *buff,size_t count,loff_t*offp;filp 是文件对象指针,count 是请求的传输数据大小.buff 参数对write来说是指向持有被写入数据的缓存,对read则是放入新数据的空缓存.offp 是指向一个“long offset type的指针,它

29、指出用户正在存取的文件位置.返回值是“signed size type类型;设备操作函数集的定义设备操作函数集的定义lread和和write方法的方法的buff参数是用户空间指针,参数是用户空间指针,不能被内核代码直接解引用。不能被内核代码直接解引用。_user字符串只是字符串只是形式上的说明,说明是用户空间地址。形式上的说明,说明是用户空间地址。l驱动必须能够存取用户空间缓存以完成它的工作。驱动必须能够存取用户空间缓存以完成它的工作。内核如何解决这个问题?内核如何解决这个问题?为平安起见,内核提供专用的函数来完成对用户空间为平安起见,内核提供专用的函数来完成对用户空间的存取。这些专用函数在的

30、存取。这些专用函数在中声明。unsignedlongcopy_to_uservoid_user*to,constvoid*from,unsignedlongcount;unsignedlongcopy_from_uservoid*to,constvoid_user*from,unsignedlongcount;大多数读写函数都会调用这两个函数,用于跟应用程序空间交流大多数读写函数都会调用这两个函数,用于跟应用程序空间交流信息。信息。Read和和Write方法方法l典型的典型的Read函数对参数的使用。函数对参数的使用。S3C2410的I/O介绍lS3C2410 有117 个复用功能输入输出端口

31、引脚,这些引脚是:lPortAGPA:32 个输入/输出端口lPortBGPB:11 个输入/输出端口lPortCGPC:16 个输入/输出端口lPortDGPD:16 个输入/输出端口lPortEGPE:16 个输入/输出端口lPortFGPF:8 个输入/输出端口lPortGGPG:16 个输入/输出端口lPortHGPH:11 个输入/输出端口S3C2410的I/O介绍l端口控制说明l端口配置存放器GPACONGPHCON大局部的引脚是复用的,所以必须对于每个引脚要求定义一个功能,端口配置存放器定义了每个引脚的功能。l端口数据存放器GPADATGPHDAT如果端口配置成输出端口,数据能够

32、被写到端口数据存放器的对应位,然后通过管脚输出。如果端口配置成输入端口,能从端口数据存放器对应的位中读出管脚上的电平l端口上拉存放器GPBUPGPHUP端口上拉存放器控制着每个端口组的上拉存放器的使能或禁止,当对应位为0,这个引脚的上拉存放器是允许的,当为1 时,上拉存放器是禁止的。MIZI提供的提供的S3C2410.Hl使用一个使用一个32位的数来表示端口的使用情况。位的数来表示端口的使用情况。l模式模式|上拉上拉|端口端口|端口引脚端口引脚lMODE|PULLUP|PORT|OFSl不需要自己手动组合,通过宏定义以及不需要自己手动组合,通过宏定义以及SHIFT和和MASK组合。见程序组合。

33、见程序MIZI提供的提供的S3C2410.Hl端口的表示端口的表示l#definePORTA_OFS0l#definePORTB_OFS1l#definePORTC_OFS2l#definePORTD_OFS3l#definePORTE_OFS4l#definePORTF_OFS5l#definePORTG_OFS6l#definePORTH_OFS7MIZI提供的提供的S3C2410.Hl端口引脚的表示端口引脚的表示l#defineGPIO_A0MAKE_GPIO_NUMPORTA_OFS,0l#defineGPIO_A1MAKE_GPIO_NUMPORTA_OFS,1l#defineGPI

34、O_A2MAKE_GPIO_NUMPORTA_OFS,2l#defineGPIO_A3MAKE_GPIO_NUMPORTA_OFS,3l。l#defineMAKE_GPIO_NUMp,opGPIO_PORT_SHIFTT|oGPIO_OFS_SHIFTMIZI提供的提供的S3C2410.Hlset_gpio_ctrlxl功能:配置端口引脚的功能,设置功能:配置端口引脚的功能,设置IO口控制存放器口控制存放器和上拉存放器和上拉存放器l用法:用法:set_gpio_ctrl模式模式|上拉上拉?|IO脚脚l模式模式|是否上拉是否上拉|IO脚,在脚,在S3C2410.h中都有其定义中都有其定义好的名字

35、。好的名字。lset_gpio_ctrlGPIO_E11|GPIO_PULLUP_DIS|GPIO_MODE_OUT;MIZI提供的提供的S3C2410.Hlwrite_gpio_bitx,vl功能:把端口功能:把端口对应的端口数据存放器对应的端口数据存放器x位设置为位设置为vlwrite_gpio_bitGPIO_E11,0;lread_gpio_bitxl功能:把端口数据存放器功能:把端口数据存放器x位的状态位的状态读入,函数读入,函数返回值既是其状态返回值既是其状态lread_gpio_bitGPIO_G11;MIZI提供的提供的S3C2410.Hlwrite_gpio_regx,vl功

36、能:把端口数据存放器功能:把端口数据存放器x设置为设置为vlread_gpio_regxl功能:读取端口数据存放器功能:读取端口数据存放器x,函数返回值既是,函数返回值既是其数据其数据l按驱动的框架写好驱动,实现初始化、卸载函数,按驱动的框架写好驱动,实现初始化、卸载函数,以及以及file_opertation操作集。操作集。l对于对于led使用的使用的gpio函数,内核没有输出作为公函数,内核没有输出作为公开符号,所以需要手动修改内核代码,代码放在开符号,所以需要手动修改内核代码,代码放在arch/arm/march-s3c2410/gpio.c,输出符号:,输出符号:EXPORT_SYMB

37、OLs3c2410_gpio_setpin;EXPORT_SYMBOLs3c2410_gpio_cfgpin;EXPORT_SYMBOLs3c2410_gpio_pullup;l编写驱动模块的编写驱动模块的Makefile。l交叉编译驱动模块交叉编译驱动模块lNFS加载驱动模块,进行测试。加载驱动模块,进行测试。嵌入式键盘驱动广州嵌入式软件公共技术支持中心广州嵌入式软件公共技术支持中心梁老师2007年7月注册中断效劳例程注册中断效劳例程 l中断线是一个珍贵且常常有限的资源中断线是一个珍贵且常常有限的资源,特别当它特别当它们只有们只有1515个时。内核维护一个中断线的注册表。个时。内核维护一个中

38、断线的注册表。l要使用中断线,就要进行中断线的申请,也就是要使用中断线,就要进行中断线的申请,也就是IRQIRQInterrupt ReQuirementInterrupt ReQuirement,因此我们也常,因此我们也常把申请一条中断线称为申请一个把申请一条中断线称为申请一个IRQIRQ或者是申请或者是申请一个中断号。一个中断号。lIRQIRQ线是从线是从0 0开始顺序编号的;第一条开始顺序编号的;第一条IRQIRQ线通常表线通常表示成示成IRQ0IRQ0。IRQnIRQn的缺省向量是的缺省向量是n+32n+32。注册中断效劳例程注册中断效劳例程 l并不是每个设备都可以向中断线上发中断信号

39、的,并不是每个设备都可以向中断线上发中断信号的,只有对某一条确定的中断线拥有了控制权,才可只有对某一条确定的中断线拥有了控制权,才可以向这条中断线上发送信号。以向这条中断线上发送信号。l计算机的外部设备越来越多,所以计算机的外部设备越来越多,所以15条中断线已条中断线已经不够用了,中断线是非常珍贵的资源。经不够用了,中断线是非常珍贵的资源。l只有当设备需要中断的时候才申请占用一个只有当设备需要中断的时候才申请占用一个IRQ,或者是在申请,或者是在申请IRQ时采用共享中断的方式,这时采用共享中断的方式,这样可以让更多的设备使用中断。样可以让更多的设备使用中断。注册中断效劳例程注册中断效劳例程 l

40、在在实现中断注册接口实现中断注册接口:int request_irqunsigned int irq,irqreturn_t*handlerint,void*,struct pt_regs*,unsigned long flags,const char*dev_name,void*dev_id;void free_irqunsigned int irq,void*dev_id;lrequest_irq的返回值是的返回值是0指示申请成功,为负指示申请成功,为负值时表示错误码。函数返回值时表示错误码。函数返回-EBUSY表示已经有表示已经有另一个驱动占用了所要申请的中断线。另一个驱动占用了所要申请

41、的中断线。注册中断效劳例程注册中断效劳例程 lrequest_irq的参数说明:的参数说明:unsigned int irq,要申请的中断号。要申请的中断号。对某些设备,如传统对某些设备,如传统PC设备上的系统时钟或键盘,设备上的系统时钟或键盘,这个值通常是预先确定的。这个值通常是预先确定的。而对于大多数其它设备来说,这个值要么可以通过而对于大多数其它设备来说,这个值要么可以通过探测获取,要么可以动态确定。探测获取,要么可以动态确定。irqreturn_t*handlerint,void*,struct pt_regs*,要安装的中断处理函数指针。后面介绍。注册中断效劳例程注册中断效劳例程 l

42、request_irq的参数说明:的参数说明:unsigned long flags,与中断管理相关的位掩码选项。const char*dev_name,用在/proc/interrupts 中显示中断的拥有者。void*dev_id这个指针用于共享的中断线。做为驱动程序的私有数据区可用来识别那个设备产生的中断。不使用共享中断线方式时,可设置为NULL。注册中断效劳例程注册中断效劳例程 lflags参数的详细说明:参数的详细说明:Flags的每个位有不同含义SA_INTERRUPT当该位被设置时,表示这是一个“快速中断。快速中断处理例程运行时,屏蔽中断。SA_SHIRQ这个位表示中断可以在设备

43、间共享。proc 文件系统中的中断信息文件系统中的中断信息l/proc/interrupts反映系统的中断信息反映系统的中断信息第一列是 IRQ 号给出每个中断线发生中断的次数。给出每个中断线发生中断的次数。给出处理中断的可编程中断控制器。给出处理中断的可编程中断控制器。给出在该中断号上注册中断处理例程的设备名称。给出在该中断号上注册中断处理例程的设备名称。实现中断处理例程实现中断处理例程l首先中断处理例程也是普通的首先中断处理例程也是普通的C程序。程序。l特别之处:特别之处:在中断时间内运行,不能向用户空间发送或者接收数在中断时间内运行,不能向用户空间发送或者接收数据。据。不能做任何导致休眠

44、的操作。不能做任何导致休眠的操作。不能调用不能调用schedule函数。函数。无论快速还是慢速中断处理例程,都应该设计成执行无论快速还是慢速中断处理例程,都应该设计成执行时间尽可能短。时间尽可能短。实现中断处理例程实现中断处理例程l中断处理函数的参数和返回值中断处理函数的参数和返回值irqreturn_t*handlerint,void*,structpt_regs*irqreturn_tshort_interruptintirq,void*dev_id,structpt_regs*regsIrq中断号中断号Dev_id驱动程序可用的数据区,通常可传递指向描述设备的数驱动程序可用的数据区,通常

45、可传递指向描述设备的数据结构指针。据结构指针。structpt_regs*regs,保存了处理器进入中断代码之前的,保存了处理器进入中断代码之前的cpu存存放器的值。一般驱动可不要。放器的值。一般驱动可不要。矩阵式键盘原理矩阵式键盘原理l矩阵式键盘一般适用于按键数量较多的场合,它由行线和矩阵式键盘一般适用于按键数量较多的场合,它由行线和列线组成,按键位于行、列的交叉点上。列线组成,按键位于行、列的交叉点上。l如下图,一个如下图,一个44的行、列结构可以构成一个有的行、列结构可以构成一个有16个按键个按键的键盘。的键盘。矩阵式键盘原理矩阵式键盘原理l按键设置在行、列交叉点上,行、列分别连接到按键

46、设置在行、列交叉点上,行、列分别连接到按键开关的两端。行线通过上拉电阻接到十按键开关的两端。行线通过上拉电阻接到十5V上。上。l平时无按键动作时,行线处于高电平状态平时无按键动作时,行线处于高电平状态;而当有而当有健按下时,行线电平状态将由通过此按键的列线健按下时,行线电平状态将由通过此按键的列线电平决定电平决定:列线电平如果为低,行线电平为低列线电平如果为低,行线电平为低;列列线电平如果为高,则行线电平亦为高。这一点是线电平如果为高,则行线电平亦为高。这一点是识别矩阵式键盘是否被按下的关键所在。识别矩阵式键盘是否被按下的关键所在。矩阵式键盘原理矩阵式键盘原理l矩阵键盘按键的识别方法分两步进行

47、矩阵键盘按键的识别方法分两步进行:l识别键盘哪一行的键被按下。让所有列线均为识别键盘哪一行的键被按下。让所有列线均为低电平,检查各行线电平是否为低。如果有行线低电平,检查各行线电平是否为低。如果有行线为低,则说明该行有键被按下,否则说明无键被为低,则说明该行有键被按下,否则说明无键被按下。按下。l如果某行有键被按下,识别键盘哪一列的键被如果某行有键被按下,识别键盘哪一列的键被按下亦称之为扫描法。逐列置低电平,并置按下亦称之为扫描法。逐列置低电平,并置其余各列为高电平其余各列为高电平.检查各行线电平的变化。如果检查各行线电平的变化。如果行电平变为低电平,则可确定此行此列交叉点处行电平变为低电平,

48、则可确定此行此列交叉点处按键被按下。按键被按下。键盘的硬件实现键盘的硬件实现l4X4矩阵键盘矩阵键盘l四个输入引脚:四个输入引脚:lEINT0-GPF0-INPUTlEINT2-GPF2-INPUTlEINT11-GPG3-INPUTlEINT19-GPG11-INPUTl四个输出引脚:四个输出引脚:lKEYSCAN0-GPE11-OUTPUTlKEYSCAN1-GPG6-OUTPUTlKEYSCAN2-GPE13-OUTPUTlKEYSCAN3-GPG2-OUTPUT键盘的驱动实现l引入结构体引入结构体key_info对按键进行描述对按键进行描述lstaticstructkey_infoli

49、ntirq_no;/外部中断号外部中断号lunsignedintgpio_port;/输入端口,输入端口,EINTlunsignedintgpio_port_kscan;/输出端口,输出端口,OUTPUTlintkey_no;/按键序号,或者名字按键序号,或者名字lkey_info_tab16=ll键盘初始化程序lstaticint_initmatrix4_buttons_initvoidll注册字符设备注册字符设备register_chrdev;l初始化按键对应的输出端口初始化按键对应的输出端口buttons_io_port_init;l采用中断机制,注册中断号采用中断机制,注册中断号req

50、uest_irqs;l键盘初始化程序l/*初始化初始化kscan口为输出口为输出0*/lstaticvoidbuttons_io_port_initvoidllinti;lfori=0;isizeofkscan/sizeofkscan1;i+lset_gpio_ctrlkscani|GPIO_PULLUP_DIS|GPIO_MODE_OUT;lwrite_gpio_bitkscani,0;ll请求注册中断请求注册中断lstaticintrequest_irqsvoidllfori=0;i使用中断个数使用中断个数;i+l设置与外部中断号相对应的设置与外部中断号相对应的GPIO端口以端口以及模式及

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

当前位置:首页 > 技术资料 > 其他杂项

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

工信部备案号:黑ICP备15003705号-8 |  经营许可证:黑B2-20190332号 |   黑公网安备:91230400333293403D

© 2020-2023 www.deliwenku.com 得利文库. All Rights Reserved 黑龙江转换宝科技有限公司 

黑龙江省互联网违法和不良信息举报
举报电话:0468-3380021 邮箱:hgswwxb@163.com