嵌入式系统第8章嵌入式设备驱动.ppt
提纲l1、Linux下设备驱动程序简介 l2、设备驱动程序结构 l3、设备驱动实验l实验一:编写一个简单的驱动程序 l实验二:设计和实现一个KED&LED驱动程序 l实验三:静态编译驱动程序,连接到内核 l实验四:使用中断方式的驱动程序设计 11、Linux下设备驱动程序简介l系统调用是操作系统内核和应用程序之间的接口 l设备驱动程序是操作系统内核和机器硬件之间的接口 lLinux设备驱动的特点是可以以模块的形式加载各种设备类型 l因为嵌入式设备往往具有大量的独有外设,开发人员需要把很多精力放在设备驱动方面 21.1 Linux设备的分类 l字符设备l以字节为单位逐个进行I/O操作 l字符设备中的缓存是可有可无 l不支持随机访问 l如串口设备/dev/cua0和/dev/cua1 l块设备 l块设备的存取是通过buffer、cache来进行 l可以进行随机访问 l例如IDE硬盘设备/dev/hda l可以支持可安装文件系统l网络设备 l通过BSD套接口访问 31.2 Linux设备文件 lLinux抽象了对硬件的处理,所有的硬件设备都可以作为普通文件一样来看待 l可以使用和操作文件相同的、标准的系统调用接口来完成打开、关闭、读写和I/O控制操作 l对用户来说,设备文件与普通文件并无区别 41.3 主设备号和次设备号 l主设备号:标识该设备的种类,也标识了该设备所使用的驱动程序l次设备号:标识使用同一设备驱动程序的不同硬件设备 l所有已经注册(即已经加载了驱动程序)的硬件设备的主设备号可以从/proc/devices文件中得到 l 51.4 Linux设备驱动代码的分布 l/block l/char l/cdrom l/pci l/scsi l/net l/sound 注:IDE接口的CD驱动位于drivers/block/ide-cd.c中,而SCSI CD驱动位于drivers/scsi/scsi.c中 61.5 Linux设备驱动程序的特点 l设备驱动是内核的一部分,影响内核稳定l为内核或其从属子系统提供一个标准接口l使用标准的内核服务如内存分配、中断和等待队列等 l大多数Linux设备驱动可以动态可加载 lLinux设备驱动程序可配置 l驱动程序维护其控制的设备,该设备即使不存在也不影响系统的运行,此时设备驱动只是占用少量系统内存,不会对系统造成什么危害 72、设备驱动程序结构 lLinux的设备驱动程序与外界的接口可以分成三部分:l与操作系统内核的接口 l与系统引导的接口 l与设备的接口 lLinux设备驱动程序的代码结构大致可以分为如下几个部分:l驱动程序的注册与注销、设备的打开与释放、设备的读写操作、设备的控制操作、设备的中断和轮询处理。82.1驱动程序的注册与注销 l注册 lregister_chrdev();/在fs/devices.clregister_blkdev();/在fs/block_dev.cl注销 lunregister_chrdev()lunregister_blkdev()92.2 打开、释放、读、写、控制等10lLinux内核将通过file_operations结构访问驱动程序提供的函数 l字符设备的读写直接使用函数read()和write()l块设备需要调用函数block_read()和block_write()lioctl()的用法与具体设备密切关联,因此需要根据设备的实际情况进行具体分析 112.3 设备的轮询和中断处理 l轮询l内核定期对设备的状态进行查询 l消耗不少的内核资源 l如果设备驱动被连接进入内核,这时使用轮询方式将会带来灾难性的后果 l中断l设备驱动向内核注册其使用的中断 l内核负责把硬件产生的中断传递给相应的设备驱动 l设备驱动在其中断处理过程中做得越少越好 12l问题:l如何查看设备驱动所对应的中断号及类型?133、设备驱动试验l实验一:编写一个简单的驱动程序 l实验二:设计和实现一个KED&LED实验 l实验三:动态加载和静态编译驱动到内核 l实验四:使用中断方式的驱动程序设计 14实验一:编写简单的驱动程序(1)l1)任务:在XSBase开发板上编写一个简单的字符设备驱动程序。该字符设备具备4个基本操作:xsbase_open()、xsbase_write()、xsbase_read()、xsbase_release(),实现向这个新建的字符设备先写入一些数据,然后再从这个设备中读取这些数据。15实验一:编写简单的驱动程序(2)l2)主要数据结构和全局变量 l系统fs/devices.c的struc device_struct结构 l创建一个xsbase.c文件,其中包含一些必要的头文件、宏和全局变量 16实验一:编写简单的驱动程序(3)l主要接口函数 lfile_operations 结构的实例 注:这种结构的声明方法是一种标记化格式声明,便于移植。17实验一:编写简单的驱动程序(4)lxsbase_open()和xsbase_release()18实验一:编写简单的驱动程序(5)lxsbase_read()19实验一:编写简单的驱动程序(6)lxsbase_write()20实验一:编写简单的驱动程序(7)l3)模块加载:是两种将驱动加入内核的方式之一l编写init_module()res=register_chrdev(0,xsbase,&chr_fops);if(xsbase_major=0)xsbase_major=res;l编写cleanup_module()unregister_chrdev(xsbase_major,xsbase);21实验一:编写简单的驱动程序(8)l4)驱动安装过程l新建xsbase.c文件,实现主要数据结构和函数接口。l编译生成xsbase.ol把目标文件加载到内核 l在Minicom中使用ZMODEM协议发送文件l执行22实验一:编写简单的驱动程序(9)l创建一个设备文件 l测试lOVER23实验二:编写KED&LED驱动(1)l在这个实验中,通过设计和实现一个KED&LED驱动程序,来控制目标板上的一组LED灯,在安装完驱动后,运行测试程序,就能点亮LED灯。24实验二:编写KED&LED驱动(2)25实验三:静态编译驱动到内核(1)l在确定自己代码位置的前提下,建立自己的源码目录、文件、Makefile、Config.in等。l修改上层的config.in文件,把自己的驱动加入到内核配置系统中。l修改上层Makefile,把自己的程序加入到内核编译系统中。l确保自己的初始化函数被调用。ldrivers/char/mem.c中的chr_dev_init()或drivers/block/ll_rw_blk.c中的blk_dev_init()l用宏module_init来申明你的初始化函数 26实验三:静态编译驱动到内核(2)l驱动位置和目录结构 27实验三:静态编译驱动到内核(3)l修改配置文件 l1)drivers/xsbase/Config.in 28实验三:静态编译驱动到内核(4)l2)arch/arm/config.in l编写Makefile l1)drivers/xsbase/Makefile 29实验三:静态编译驱动到内核(5)l2)drivers/Makefile l3)Makefile30实验四:中断方式的驱动程序(1)l注册中断处理程序 l什么叫中断信号线(IRQ号)?l何时请求IRQ号更合适?l初始化时l设备第一次打开时 31实验四:中断方式的驱动程序(2)l编写中断处理程序 32实验四:中断方式的驱动程序(3)l中断处理机制的实现 33实验四:中断方式的驱动程序(4)l中断控制 这些函数更新可编程中断控制器(PIC)中指定中断的掩码,因而,这样就可以在所有的处理器上禁止或者启动 IRQ。对这些函数的调用是可以嵌套的如果 disable_irq()被成功调用两次,在 IRQ 真正重新打开之前,需要执行两次 enable_irq()调用。34驱动设计中涉及的一些具体问题驱动设计中涉及的一些具体问题 l用户空间和内核空间 l/proc文件系统 35363738