《嵌入式系统原理及应用教程第10章.ppt》由会员分享,可在线阅读,更多相关《嵌入式系统原理及应用教程第10章.ppt(28页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、嵌入式系嵌入式系统统原理及原理及应应用用教教程程主主讲内讲内容容第第8章章 嵌入式系嵌入式系统统Boot Loader技技术术第第9章章 嵌入式嵌入式Linux操作系操作系统统移植移植第第10章章 嵌入式嵌入式Linux设备驱动设备驱动程序程序开发开发第第11章章 嵌入式嵌入式Linux应应用程序用程序设计设计10.1 嵌入式嵌入式Linux驱动驱动程序程序开发开发基基础础10.1 嵌入式嵌入式Linux驱动驱动程序程序开发开发基基础础10.1.1 嵌入式嵌入式Linux设备驱动设备驱动程序分程序分类类l静态静态加加载载的的驱动驱动程序程序l动态动态加加载载的的驱动驱动程序程序 Linux将设
2、备将设备按照功能特性按照功能特性划划分分为为三三种类种类型:字符型:字符设设备备,块设备块设备和和网络设备网络设备。10.1.2 最最简单简单的的内内核模核模块块1helloworld模模块块源代源代码码2模模块块的的编译编译3模模块块的加的加载载和卸和卸载载10.1 嵌入式嵌入式Linux驱动驱动程序程序开发开发基基础础10.1 嵌入式嵌入式Linux驱动驱动程序程序开发开发基基础础10.2 嵌入式嵌入式Linux设备驱动设备驱动重要技重要技术术10.2.1 内内存存与与I/O端口端口(1)内内核空核空间间和用和用户户空空间间(2)内内核中核中内内存分配存分配内内核中核中获获取取内内存的几存
3、的几种种方式如下。方式如下。通通过伙过伙伴算法分配大片物理伴算法分配大片物理内内存存通通过过slab缓缓冲冲区区分配小片物理分配小片物理内内存存非非连续内连续内存存区区分配分配高端高端内内存映射存映射固定固定线线性地址映射性地址映射10.1 嵌入式嵌入式Linux驱动驱动程序程序开发开发基基础础(3)I/O端口端口 根据根据CPU体系体系结构结构的不同,的不同,CPU对对IO端口的端口的编编址方式址方式有有两种两种:I/O映射方式(映射方式(I/O-mapped)和)和内内存映射方存映射方式(式(Memory-mapped)。)。下面主要下面主要讨论讨论一下一下内内存映射方式存映射方式访问访问
4、I/O端口的方法,端口的方法,我我们称们称之之为为I/O内内存操作。存操作。l I/O 内内存存区区必必须须在使用前分配在使用前分配l I/O内内存映射存映射 l 访问访问I/O内内存存l 映射到用映射到用户户空空间间 10.1 嵌入式嵌入式Linux驱动驱动程序程序开发开发基基础础10.1 嵌入式嵌入式Linux驱动驱动程序程序开发开发基基础础10.2.2 同步机制同步机制 Linux内内核中包含的同步机制包括:原子操作、信核中包含的同步机制包括:原子操作、信号号量(量(semaphore)、)、读写读写信信号号量(量(rw_semaphore)、)、自旋自旋锁锁(spinlock)、大)、
5、大内内核核锁锁(Big Kernel Lock,BKL)、读写锁读写锁(rwlock)、)、读读拷拷贝贝更新(更新(Read-Copy Update,RCU)和)和seqlock(顺顺序序锁锁)等。)等。10.1 嵌入式嵌入式Linux驱动驱动程序程序开发开发基基础础1.原子操作原子操作 原子操作主要用于原子操作主要用于实现资实现资源源计数计数,很多引用,很多引用计数计数(refcnt)就是就是通通过过原子操作原子操作实现实现的。的。原子原子类类型定型定义义如下:如下:typedef struct volatile int counter;atomic_t;原子操作通常用于原子操作通常用于实现
6、资实现资源的引用源的引用计数计数 2.信信号号量量 信信号号量在量在创创建建时时需要需要设设置一置一个个初始初始值值.3.读写读写信信号号量量 读写读写信信号号量有量有两种实现两种实现:l一一种种是通用的,不依是通用的,不依赖赖于硬件架于硬件架构构 l 一一种种是架是架构构相相关关的的10.1 嵌入式嵌入式Linux驱动驱动程序程序开发开发基基础础读写读写信信号号量的相量的相关关API有:有:DECLARE_RWSEM(name)该该宏宏声声明一明一个读写个读写信信号号量量name并对并对其其进进行初始化。行初始化。void init_rwsem(struct rw_semaphore*sem
7、);该该函函数对读写数对读写信信号号量量sem进进行初始化。行初始化。void down_read(struct rw_semaphore*sem);在在Linux中,每一中,每一个进个进程都用一程都用一个类个类型型为为task_t或或struct task_struct的的结构来结构来描述描述 10.1 嵌入式嵌入式Linux驱动驱动程序程序开发开发基基础础4.自旋自旋锁锁 一一个执个执行行单单元要想元要想访问访问被自旋被自旋锁锁保保护护的共享的共享资资源,必源,必须须先得到先得到锁锁,在,在访问访问完共享完共享资资源后,必源后,必须释须释放放锁锁。自旋自旋锁锁的的API有:有:spin_l
8、ock_init(x);10.1 嵌入式嵌入式Linux驱动驱动程序程序开发开发基基础础10.2.3 阻塞阻塞与与非阻塞非阻塞1.阻塞操作阻塞操作2.非阻塞操作非阻塞操作10.2.4 时间问题时间问题1.延延时时操作:操作:(1)长长延延时时。(。(2)短延)短延时时2.内内核定核定时时器器内内核提供核提供给驱动许给驱动许多函多函数来声数来声明、注明、注册册、以及去除、以及去除内内核定核定时时器。器。3.工作工作队队列列采用缺省工作者采用缺省工作者线线程程来实现来实现工作工作队队列列 的的API:INIT_WORK(_work,_func,_data)10.1 嵌入式嵌入式Linux驱动驱动程
9、序程序开发开发基基础础 int schedule_work(struct work_struct*work)int schedule_delayed_work(struct work_struct*work,unsigned long delay)void flush_scheduled_work(void)int cancel_delayed_work(struct work_struct*work)创创建自己的工作者建自己的工作者线线程和工作程和工作队队列,列,API:struct workqueue_struct*create_workqueue(const char*name)int
10、queue_work(struct workqueue_struct*wq,struct work_struct*work)int queue_delayed_work(struct workqueue_struct*wq,struct work_struct*work,unsigned long delay)void flush_workqueue(struct workqueue_struct*wq)void destroy_workqueue(struct workqueue_struct*wq)10.1 嵌入式嵌入式Linux驱动驱动程序程序开发开发基基础础10.2.5 中中断处断处理
11、理在在Linux系系统统里,里,对对中中断断的的处处理是理是属属于系于系统统核心部分,核心部分,因而如果因而如果设别与设别与系系统统之之间间以中以中断断方式方式进进行行数数据交据交换换,就必就必须须把把该设备该设备的的驱动驱动程序作程序作为为系系统统核心的一部分。核心的一部分。设备驱动设备驱动程序通程序通过调过调用用request_irq函函数来数来申申请请中中断断,通通过过free_irq来释来释放中放中断断。它们它们被定被定义为义为:#include int request_irq(unsigned int irq,void(*handler)(int irq,void dev_id,st
12、ruct pt_regs*regs),unsigned long flags,const char*device,void*dev_id);void free_irq(unsigned int irq,void*dev_id);10.1 嵌入式嵌入式Linux驱动驱动程序程序开发开发基基础础函函数数的的参数参数如下。如下。unsigned int irq:请请求的中求的中断号断号。irqreturn_t(*handler):安装的中:安装的中断处断处理函理函数数指指针针。unsigned long flags:中:中断处断处理的理的属属性。性。const char*dev_name:这个传递给
13、这个传递给request_irq的字串的字串用在用在/proc/interrupts来显来显示中示中断断的的拥拥有者。有者。void*dev_id:用作共享中:用作共享中断断的指的指针针。10.1 嵌入式嵌入式Linux驱动驱动程序程序开发开发基基础础10.3 字符字符设备驱动设备驱动程序程序字符字符设备驱动设备驱动程序可以分程序可以分为为三三个个主要主要组组成部分:成部分:,自动配置和初始化子程序,负责检测所要驱动的硬件设备是否存在和是否能正常工作。,服务于I/O请求的子程序,又称为驱动程序的上半部分。,中断服务子程序,又称为驱动程序的下半部分。10.3.1 字符字符设备驱动结构设备驱动结构
14、1.主次主次设备号设备号:字符:字符设备设备和和块设备块设备通通过过文件系文件系统统中的名子中的名子来来存取。存取。主主编号标识设备编号标识设备相相连连的的驱动驱动。次次编号编号被被内内核用核用来决来决定引用定引用哪个设备哪个设备。设备编号设备编号在在驱动驱动程序的程序的内内部具有固定的表示方式。部具有固定的表示方式。在建立在建立驱动时驱动时,需要做的第一件事是,需要做的第一件事是获获取一取一个个或多或多个设备编号来个设备编号来使用。使用。在在驱动驱动程序程序执执行的行的过过程中,如果不希望在使用程中,如果不希望在使用该设备该设备,要及,要及时时的的将设备编将设备编号释号释放:放:10.1 嵌
15、入式嵌入式Linux驱动驱动程序程序开发开发基基础础2.驱动驱动相相关数关数据据结构结构 大部分的基大部分的基础础性的性的驱动驱动操作包括操作包括3个个重要的重要的内内核核数数据据结构结构,它它们们是是file_operations,file,和,和inode。(1)文件操作()文件操作(file_operations)file_operation 结构结构表示了用表示了用户户程序程序怎样对设备进怎样对设备进行操作。行操作。这个结构这个结构,定,定义义在在中,是一中,是一个个函函数数指指针针的集合的集合 struct module*owner。(2)文件)文件结构结构struct file定定
16、义义于于,是,是设备驱动设备驱动中第二中第二个个最重要最重要的的数数据据结构结构。(3)inode 结构结构inode 结构结构由由内内核在核在内内部用部用来来表示文件。表示文件。10.1 嵌入式嵌入式Linux驱动驱动程序程序开发开发基基础础3.自自动动配置和初始化配置和初始化(1)初始化。)初始化。当驱动当驱动程序程序将将被加被加载载的的时时候,首先候,首先会调会调用初始函用初始函数进数进行自行自动动配置。配置。(2)清清除除处处理。理。4.中中断处断处理理 如果需要如果需要驱动驱动程序具有中程序具有中断处断处理的能力,必理的能力,必须进须进行中行中断断申申请请。l从从request_ir
17、q返回返回给请给请求函求函数数的返回的返回值值是是0指示成功,指示成功,为负为负表示表示错误码错误码。l中中断处断处理可以在理可以在驱动驱动初始化初始化时时安装或者在安装或者在设备设备第一次第一次打打开时开时。l在中在中断断的使用的使用过过程中程中还还可以可以对对其其进进行使能和禁止操作行使能和禁止操作 10.1 嵌入式嵌入式Linux驱动驱动程序程序开发开发基基础础10.3.2 字符字符设备驱动实设备驱动实例例LED驱动驱动1.LED驱动驱动程序分析程序分析 本本驱动驱动程序文件名程序文件名为为led2440.c2.驱动驱动模模块块加入加入内内核核l使用命令:使用命令:l编辑编辑Kconfi
18、g文件:文件:l修改修改Makefile文件:文件:l配置、配置、编译内编译内核核 执执行行make zImage内内核映像和核映像和驱动驱动程序模程序模块会块会先后被先后被编译编译完完毕毕。将内将内核下核下载载至至开发开发板;板;将驱动将驱动程序模程序模块块加加入到根文件系入到根文件系统统后,下后,下载载至至开发开发板。板。这样这样就可以就可以调调用用驱动驱动程序程序进进行演示了。行演示了。10.1 嵌入式嵌入式Linux驱动驱动程序程序开发开发基基础础3.LED驱动驱动演示演示(1)驱动驱动程序模程序模块块加加载载到到内内核。核。进进入入驱动驱动程序模程序模块块所在目所在目录录,执执行:行
19、:insmod -f led2440.ko(2)建立)建立设备节设备节点。点。也就是建立用也就是建立用户户程序程序关联关联到到驱动驱动程序的途程序的途径径(3)演示程序。)演示程序。建立一建立一个个LED控制的控制的简单简单演示程序演示程序led2440test 10.1 嵌入式嵌入式Linux驱动驱动程序程序开发开发基基础础10.4 网络设备驱动网络设备驱动程序程序10.4.1 Linux 网络设备简网络设备简介介1.Linux网络驱动网络驱动基基础础2.DM9000控制器控制器10.4.2 网络驱动网络驱动核心核心数数据据结构结构分成几分成几个个方面方面对对其其进进行介行介绍绍 l通用信息
20、通用信息l硬件描述信息硬件描述信息l协议协议相相关关信息信息l设备设备操作函操作函数数接口接口10.1 嵌入式嵌入式Linux驱动驱动程序程序开发开发基基础础10.4.3 网络驱动网络驱动程序分析程序分析1.初始化、初始化、清清理理网络设备网络设备网络设备网络设备初始化的工作主要是确定硬件初始化的工作主要是确定硬件设备设备的存在,以及的存在,以及将将硬件硬件设备设备加加载载到到设备链设备链表中,表中,为网络设备为网络设备的激活做准的激活做准备备。需要注意需要注意这两个变这两个变量:量:name和和owner。2.打打开开和和关闭网络设备关闭网络设备 open函函数数主要用主要用来来完成完成对网
21、络设备对网络设备中中断进断进行注行注册册、通、通过过配配置物理接口初始化置物理接口初始化设备设备,以及,以及为发为发送送数数据准据准备队备队列。列。10.1 嵌入式嵌入式Linux驱动驱动程序程序开发开发基基础础3.中中断处断处理理网络驱动网络驱动程序的中程序的中断处断处理函理函数数在在网络设备网络设备激活激活时进时进行注行注册册,主要用于,主要用于完成:完成:现场现场保保护护及中及中断屏断屏蔽、蔽、读读取取网络设备网络设备寄存器信息及判寄存器信息及判断断中中断断原原因因并处并处理、恢理、恢复复中中断现场断现场。函函数数首先需要首先需要获获得自旋得自旋锁锁,然后,然后将当将当前的寄存器地址保存
22、下前的寄存器地址保存下来来,以便,以便返回的返回的时时候候继续进继续进行被打行被打断断的作的作业业;接着就是;接着就是屏屏蔽所有的中蔽所有的中断断,读读取取中中断状态断状态寄存器寄存器并清并清除中除中断状态断状态寄存器,然后就寄存器,然后就开开始始真真正的中正的中断处断处理理了。了。当发当发生接收中生接收中断时断时,中,中断断函函数调数调用用dm9000_rx()函函数数。4.sk_buff结构结构 sk_buff的的数数据成据成员员分分为两为两部分:部分:l一部分是一部分是实际实际在在网络网络中要中要传输传输的部分,的部分,数数据据区区(Packet date storage););l一部分
23、由一部分由内内核管理服核管理服务务于于结构链结构链表。表。10.1 嵌入式嵌入式Linux驱动驱动程序程序开发开发基基础础还还有一些常用的成有一些常用的成员员如:如:sk_buff-tstamp:sk_buff-dev:sk_buff-protocol:内内核提供了一系列用于操作核提供了一系列用于操作sk_buff数数据据结构结构的函的函数数,用,用于分配、于分配、释释放、放、复复制、克隆、制、克隆、扩扩展等功能,下面介展等功能,下面介绍绍些常用的。些常用的。struct sk_buff*alloc_skb(unsigned int len,int priority)struct sk_buf
24、f*dev_alloc_skb(unsigned int len)10.1 嵌入式嵌入式Linux驱动驱动程序程序开发开发基基础础5.数数据据发发送送处处理理6.数数据接收据接收处处理理 数数据接收的主要工作有:据接收的主要工作有:检查检查接收的到的接收的到的数数据包是否正确;根据据包是否正确;根据数数据据被被长长度在度在内内核空核空间为数间为数据包申据包申请请sk_buff;把;把数数据包据包复复制到制到sk_buff,填写填写相相关关成成员员后后插插入入队队列;列;释释放放网络网络芯片中分配的芯片中分配的缓缓冲冲区区。7.其其它处它处理接口理接口 在在网络设备结构网络设备结构中中还还有一些
25、函有一些函数数接口需要接口需要实现实现,如:,如:(1)get_stats(2)set_multicast_list(3)tx_tiemout10.1 嵌入式嵌入式Linux驱动驱动程序程序开发开发基基础础10.5 设备驱动实设备驱动实例例10.5.1 ADC设备驱动实设备驱动实例例ADC是比是比较简单较简单的字符的字符设备设备,在此直接,在此直接给给出出ADC的的驱动驱动程序源代程序源代码码和注和注释说释说明。明。10.5.2 PWM设备驱动实设备驱动实例例10.5.3 触触摸摸屏设备驱动实屏设备驱动实例例1.输输入子系入子系统统 在在Linux中,中,输输入子系入子系统统(Input Su
26、bsystem)是由是由输输入子系入子系统统设备驱动层设备驱动层、输输入子系入子系统统核心核心层层(Input Core)和和输输入子系入子系统统事件事件处处理理层层(Event Handler)组组成。成。10.1 嵌入式嵌入式Linux驱动驱动程序程序开发开发基基础础设备设备的的驱动驱动的的实现实现步步骤骤如下:如下:在在驱动驱动模模块块加加载载函函数数中中设设置置Input设备设备支持支持input子系子系统统的的哪哪些事件;些事件;将将Input设备设备注注册册到到input子系子系统统中;中;在在Input设备发设备发生生输输入操作入操作时时(如:如:键盘键盘被按下被按下/抬起、抬起
27、、触触摸摸屏屏被被触触摸摸/抬起抬起/移移动动、鼠、鼠标标被移被移动动/单击单击/抬起抬起时时等等),提交所,提交所发发生的事件及生的事件及对应对应的的键值键值/坐坐标标等等状态状态。在提交在提交输输入入设备设备的事件后必的事件后必须须用下列方法使事件同用下列方法使事件同步,步,让它让它告知告知input系系统统,设备驱动设备驱动已已经发经发出了一出了一个个完整完整的的报报告:告:void input_sync(struct input_dev*dev)10.1 嵌入式嵌入式Linux驱动驱动程序程序开发开发基基础础2.触触摸摸屏驱动实现屏驱动实现S3C2440A芯片芯片内内部集成了部集成了触
28、触摸摸屏屏接口接口并与并与ADC接口相接口相连连。S3C2440A提供的提供的触触摸摸屏屏接口有接口有4种处种处理模式,分理模式,分别别是:正常是:正常转换转换模式、模式、单独单独的的X/Y位置位置转换转换模式、自模式、自动动X/Y位置位置转换转换模式和等待中模式和等待中断断模式,在此模式,在此实现实现自自动动X/Y位置位置转换转换模式和模式和等待中等待中断断模式。模式。a、驱动驱动的加的加载载和卸和卸载载:b、中、中断断服服务务以及以及触触摸摸屏状态屏状态、坐、坐标标的的转换转换。10.1 嵌入式嵌入式Linux驱动驱动程序程序开发开发基基础础触触摸摸屏转换过屏转换过程程为为:l第一步,如果
29、第一步,如果触触摸摸屏屏接收到接收到触触摸,摸,则进则进入入updown_ISR,如果如果能能获获取取ADC_LOCK则调则调用用touch_timer_fire,启动启动ADC;l第二步第二步ADC转换转换,如果小于四次,如果小于四次继续转换继续转换,如果四次完,如果四次完毕毕后,后,启动启动1个时间个时间滴答的定滴答的定时时器,停止器,停止ADC,也就是也就是说说在在这个时间这个时间滴滴答答内内,ADC是停止的,是停止的,这样这样可以防止可以防止屏屏幕抖幕抖动动;l第三步,如果第三步,如果1个时间个时间滴答到滴答到时时候,候,触触摸摸屏屏仍然仍然处处于于触触摸摸状态状态则则上上报转换数报转
30、换数据,据,并并重重启启ADC,重,重复复第二步;第二步;如果如果触触摸摸笔释笔释放了,放了,则则上上报释报释放事件,放事件,并将触并将触摸摸屏屏重新重新设设置置为为等待中等待中断状态断状态。10.1 嵌入式嵌入式Linux驱动驱动程序程序开发开发基基础础10.6 本章小本章小结结 本章介本章介绍绍了了Linux2.6内内核核驱动驱动程序的相程序的相关关技技术术和一般和一般开发开发方法。方法。讲讲述了述了Linux驱动驱动程序的功能、分程序的功能、分类类,通,通过过一一个简单个简单的的Helloworld模模块来块来引入引入Linux2.6内内核的核的模模块运块运行机制,行机制,说说明了明了驱动驱动程序的同模程序的同模块块的的关关系,以系,以及及内内核模核模块块和和驱动驱动程序的加程序的加载载使用方法。使用方法。详细阐详细阐述了述了开发驱动开发驱动程序所需技程序所需技术术,通,通过实过实例例详细讲详细讲述了字符述了字符设设备驱动备驱动程序的程序的开发过开发过程;程;对网络驱动对网络驱动程序程序进进行了分析。行了分析。