嵌入式系统原理及应用教程第10章00.ppt

上传人:豆**** 文档编号:63546385 上传时间:2022-11-25 格式:PPT 页数:24 大小:1.84MB
返回 下载 相关 举报
嵌入式系统原理及应用教程第10章00.ppt_第1页
第1页 / 共24页
嵌入式系统原理及应用教程第10章00.ppt_第2页
第2页 / 共24页
点击查看更多>>
资源描述

《嵌入式系统原理及应用教程第10章00.ppt》由会员分享,可在线阅读,更多相关《嵌入式系统原理及应用教程第10章00.ppt(24页珍藏版)》请在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)。)。下面主要讨论一下内存映射方式访问下面主要讨论一下内存映射方式访问I/O端口的方法,端口的方法,我们称之

4、为我们称之为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)、大内核锁)、大内核锁(Big Kernel

5、 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_lock_init(x);10

8、.1 嵌入式嵌入式Linux驱动程序开发基础驱动程序开发基础10.2.3 阻塞与非阻塞阻塞与非阻塞1.阻塞操作阻塞操作2.非阻塞操作非阻塞操作10.2.4 时间问题时间问题1.延时操作:延时操作:(1)长延时。()长延时。(2)短延时)短延时2.内核定时器内核定时器内核提供给驱动许多函数来声明、注册、以及去除内核定时器。内核提供给驱动许多函数来声明、注册、以及去除内核定时器。3.工作队列工作队列采用缺省工作者线程来实现工作队列采用缺省工作者线程来实现工作队列 的的API:INIT_WORK(_work,_func,_data)10.1 嵌入式嵌入式Linux驱动程序开发基础驱动程序开发基础 i

9、nt 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 queue_work(st

10、ruct 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 中断处理中断处理在在Linux系统里,对

11、中断的处理是属于系统核心部分,系统里,对中断的处理是属于系统核心部分,因而如果设别与系统之间以中断方式进行数据交换,因而如果设别与系统之间以中断方式进行数据交换,就必须把该设备的驱动程序作为系统核心的一部分。就必须把该设备的驱动程序作为系统核心的一部分。设备驱动程序通过调用设备驱动程序通过调用request_irq函数来申请中断,函数来申请中断,通过通过free_irq来释放中断。它们被定义为:来释放中断。它们被定义为:#include int request_irq(unsigned int irq,void(*handler)(int irq,void dev_id,struct pt_r

12、egs*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 字符设备驱动结构字符设备驱动结构1.主次

14、设备号主次设备号:字符设备和块设备通过文件系统中的名子来存取。:字符设备和块设备通过文件系统中的名子来存取。主编号标识设备相连的驱动。主编号标识设备相连的驱动。次编号被内核用来决定引用哪个设备。次编号被内核用来决定引用哪个设备。设备编号在驱动程序的内部具有固定的表示方式。设备编号在驱动程序的内部具有固定的表示方式。在建立驱动时,需要做的第一件事是获取一个或多个设备编号来使用。在建立驱动时,需要做的第一件事是获取一个或多个设备编号来使用。在驱动程序执行的过程中,如果不希望在使用该设备,要及时的将设备编在驱动程序执行的过程中,如果不希望在使用该设备,要及时的将设备编号释放:号释放: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_

17、irq返回给请求函数的返回值是返回给请求函数的返回值是0指示成功,指示成功,为负表示错误码。为负表示错误码。l中断处理可以在驱动初始化时安装或者在设备第一次中断处理可以在驱动初始化时安装或者在设备第一次打开时。打开时。l在中断的使用过程中还可以对其进行使能和禁止操作在中断的使用过程中还可以对其进行使能和禁止操作 10.1 嵌入式嵌入式Linux驱动程序开发基础驱动程序开发基础10.3.2 字符设备驱动实例字符设备驱动实例LED驱动驱动1.LED驱动程序分析驱动程序分析 本驱动程序文件名为本驱动程序文件名为led2440.c2.驱动模块加入内核驱动模块加入内核l使用命令:使用命令:cp-f le

18、d2440.c /linux-2.6.32.4/drivers/char/l编辑编辑Kconfig文件:文件: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

20、 网络驱动核心数据结构网络驱动核心数据结构分成几个方面对其进行介绍分成几个方面对其进行介绍 l通用信息通用信息l硬件描述信息硬件描述信息l协议相关信息协议相关信息l设备操作函数接口设备操作函数接口10.1 嵌入式嵌入式Linux驱动程序开发基础驱动程序开发基础10.4.3 网络驱动程序分析网络驱动程序分析1.初始化、清理网络设备初始化、清理网络设备网络设备初始化的工作主要是确定硬件设备的存在,以及网络设备初始化的工作主要是确定硬件设备的存在,以及将硬件设备加载到设备链表中,为网络设备的激活做准备。将硬件设备加载到设备链表中,为网络设备的激活做准备。需要注意这两个变量:需要注意这两个变量:nam

21、e和和owner。2.打开和关闭网络设备打开和关闭网络设备 open函数主要用来完成对网络设备中断进行注册、通过配函数主要用来完成对网络设备中断进行注册、通过配置物理接口初始化设备,以及为发送数据准备队列。置物理接口初始化设备,以及为发送数据准备队列。10.1 嵌入式嵌入式Linux驱动程序开发基础驱动程序开发基础3.中断处理中断处理网络驱动程序的中断处理函数在网络设备激活时进行注册,主要用于网络驱动程序的中断处理函数在网络设备激活时进行注册,主要用于完成:现场保护及中断屏蔽、读取网络设备寄存器信息及判断中断原因完成:现场保护及中断屏蔽、读取网络设备寄存器信息及判断中断原因并处理、恢复中断现场

22、。并处理、恢复中断现场。函数首先需要获得自旋锁,然后将当前的寄存器地址保存下来,以便函数首先需要获得自旋锁,然后将当前的寄存器地址保存下来,以便返回的时候继续进行被打断的作业;接着就是屏蔽所有的中断,读取中返回的时候继续进行被打断的作业;接着就是屏蔽所有的中断,读取中断状态寄存器并清除中断状态寄存器,然后就开始真正的中断处理了。断状态寄存器并清除中断状态寄存器,然后就开始真正的中断处理了。当发生接收中断时,中断函数调用当发生接收中断时,中断函数调用dm9000_rx()函数。函数。4.sk_buff结构结构 sk_buff的数据成员分为两部分:的数据成员分为两部分:l一部分是实际在网络中要传输

23、的部分,数据区(一部分是实际在网络中要传输的部分,数据区(Packet date storage););l一部分由内核管理服务于结构链表。一部分由内核管理服务于结构链表。10.1 嵌入式嵌入式Linux驱动程序开发基础驱动程序开发基础还有一些常用的成员如:还有一些常用的成员如:sk_buff-tstamp:sk_buff-dev:sk_buff-protocol:内核提供了一系列用于操作内核提供了一系列用于操作sk_buff数据结构的函数,用数据结构的函数,用于分配、释放、复制、克隆、扩展等功能,下面介绍于分配、释放、复制、克隆、扩展等功能,下面介绍些常用的。些常用的。struct sk_bu

24、ff*alloc_skb(unsigned int len,int priority)struct sk_buff*dev_alloc_skb(unsigned int len)10.1 嵌入式嵌入式Linux驱动程序开发基础驱动程序开发基础5.数据发送处理数据发送处理6.数据接收处理数据接收处理 数据接收的主要工作有:检查接收的到的数据包是否正确;根据数据数据接收的主要工作有:检查接收的到的数据包是否正确;根据数据被长度在内核空间为数据包申请被长度在内核空间为数据包申请sk_buff;把数据包复制到;把数据包复制到sk_buff,填写相关成员后插入队列;释放网络芯片中分配的缓冲区。填写相关成

25、员后插入队列;释放网络芯片中分配的缓冲区。7.其它处理接口其它处理接口 在网络设备结构中还有一些函数接口需要实现,如:在网络设备结构中还有一些函数接口需要实现,如:(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 触摸屏设

26、备驱动实例触摸屏设备驱动实例1.输入子系统输入子系统 在在Linux中,输入子系统中,输入子系统(Input Subsystem)是由输入子系统是由输入子系统设备驱动层、输入子系统核心层设备驱动层、输入子系统核心层(Input Core)和输入子系统事和输入子系统事件处理层件处理层(Event Handler)组成。组成。10.1 嵌入式嵌入式Linux驱动程序开发基础驱动程序开发基础设备的驱动的实现步骤如下:设备的驱动的实现步骤如下:在驱动模块加载函数中设置在驱动模块加载函数中设置Input设备支持设备支持input子系子系统的哪些事件;统的哪些事件;将将Input设备注册到设备注册到input子系统中;子系统中;在在Input设备发生输入操作时设备发生输入操作时(如:键盘被按下如:键盘被按下/抬起、抬起、触摸屏被触摸触摸屏被触摸/抬起抬起/移动、鼠标被移动移动、鼠标被移动/单击单击/抬起时等抬起时等),提交所发生的事件及对应的键值,提交所发生的事件及对应的键值/坐标等状态。坐标等状态。在提交输入设备的事件后必须用下列方法使事件同在提交输入设备的事件后必须用下列方法使事件同步,让它告知步,让它告知input系统,设备驱动已经发出了一个完整系统,设备驱动已经发出了一个完整的报告:的报告:void input_sync(struct input_dev*dev)

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

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

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

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