嵌入式LINUX设备驱动程序课件_第1页
嵌入式LINUX设备驱动程序课件_第2页
嵌入式LINUX设备驱动程序课件_第3页
嵌入式LINUX设备驱动程序课件_第4页
嵌入式LINUX设备驱动程序课件_第5页
已阅读5页,还剩47页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

嵌入式LINUX设备驱动程序课件本讲主要内容嵌入式linux设备驱动的基本框架与实现数码管显示驱动程序分析帧缓冲显示驱动实现方法。Linux系统中的设备文件Linux将所有外部设备看成是一类特殊文件,称之为“设备文件”。如果说系统调用是Linux内核和应用程序之间的接口,那么设备驱动程序则可以看成是Linux内核与外部设备之间的接口。设备驱动程序向应用程序屏蔽了硬件在实现上的细节,使得应用程序可以像操作普通文件一样来操作外部设备Linux设备驱动在系统中的层次设备驱动的作用设备驱动是位于应用和物理设备之间的软件层,负责完成二者间的I/O操作;在LINUX系统里,对用户程序,设备驱动隐藏了设备的具体细节,为不同设备提供了一致的接口;设备驱动是嵌入式系统开发的重要内容之一设备驱动完成的主要功能对设备的初始化和释放;将数据从内核传递到硬件设备,以及从硬件读取数据;读取应用程序传送给设备文件的数据,并回送应用程序请求的数据。这需要在用户空间、内核空间、总线以及外设之间传输数据;检查和处理设备出现的错误。设备驱动的分类Linux支持3种不同类型的设备字符设备块设备网络接口字符设备能够像字节流一样被访问的设备,一般不需要缓存技术,也不支持随机访问。典型的字符设备有:鼠标、键盘、I/O设备等。设备驱动的分类块设备支持面向块访问的设备,每块包含2的N次幂字节数据,典型的块大小为512或1024B;大多数块设备允许随机访问,而且常常采用buffer、cache等缓存技术;块设备的访问常常通过文件系统来进行;典型的块设备有:如磁盘、硬盘、光盘驱动器等。设备驱动的分类网络接口能够和其他主机交换数据的设备接口。网络接口只是面向数据包而不是数据流,它没有被映射为任何设备文件,其访问要通过BSD套接口进行。设备驱动的分类主设备号与次设备号LINUX系统中,设备由一个主设备号和一个次设备号来唯一标识;主设备号唯一标识了设备类型,即设备驱动程序类型,它是块设备表或字符设备表中设备表项的索引。一些典型设备的主设备号已经基本固定下来,例如,软驱的主设备号为2,IDE硬盘的主设备号为3等等。设备宏操作MAJOR()可以获取主设备号。主设备号与次设备号次设备号用于标识使用同一设备驱动程序的不同硬件,并仅由设备驱动程序解释

当应用程序操作某个设备文件时,Linux内核根据其主设备号调用相应的驱动程序,并从用户态进入内核态驱动程序判断次设备号,并完成相应的硬件操作。

用户空间和内核空间Linux运行在2种模式下内核模式用户模式内核模式对应内核空间,而用户模式对应用户空间。驱动程序作为内核的一部分,它对应内核空间,应用程序不能直接访问其数据,用户空间和内核空间用户空间和内核空间的数据传递:copy_to_user(void*to,constvoid*from,unsignedlongcount);copy_from_user(void*to,constvoid*from,unsignedlongcount);__copy_to_user()__copy_from_user()第一种方法在复制数据的同时,会进行地址空间的有效性检查。内核设备驱动模块设备驱动程序以两种方式添加到内核:Buildin直接把驱动程序编译到内核代码中Module以模块的方式加载驱动程序加载:insmoddriver.o卸载:rmmoddriver查看:lsmodLinux设备节点的添加设备节点位于/dev路径下可用如下命令添加dev节点,b代表块设备,C表示字符设备mknod/dev/hda1b(/c)1271 块设备,主设备号127,次设备号1Linux设备驱动代码的分布/char:字符设备驱动源码;/block:块设备驱动源码;/cdrom:LinuxCDROM驱动源码。这里可以找到某些特殊的CDROM设备(如SoundblasterCDROM)。IDE接口的CD驱动位于drivers/ide/ide-cd.c中而SCSICD驱动位于drivers/scsi/scsi.c中。/pci:它包含了PCI伪设备驱动源码。这里可以找到关于PCI子系统映射与初始化的代码。Linux设备驱动代码的分布/scsi:所有的SCSI代码以及Linux支持的SCSI设备的设备驱动。/net:包含网络驱动源码。/sound:所有的声卡驱动源码。/video:所有的视频卡驱动源码。Linux设备驱动的代码结构驱动程序的注册与注销设备的打开与释放设备的读写操作设备的控制操作设备的中断和轮询处理等

19设备驱动的注册方法1result=devfs_register_chrdev(0,MOD_NAME,&keypad_fops)if(result<0){ return-ENODEV; }devfs_handle=devfs_register(NULL,MOD_NAME,,result,0,,&keypad_fops,NULL);MOD_NAME:设备驱动的名称;keypad_fops:文件操作指针。优点:无需手动创建设备节点,由系统自动完成。对于块设备的注册,具有类似函数:devfs_register_blkdev以及操作过程。设备驱动的注册方法2result=register_chrdev(0,MOD_NAME,&keypad_fops);或者result=register_blkdev(0,MOD_NAME,&keypad_fops);

if(result<0){ return-ENODEV; }mknod/dev/MOD_NAMECMAJORMINOR设备驱动的注销方法1devfs_unregister_chrdev(MAJOR,MOD_NAME);或者devfs_unregister_blkdev(MAJOR,MOD_NAME);devfs_unregister(devfs_handle); 方法2unregister_chrdev(Major,MOD_NAME);或者unregister_blkdev(Major,MOD_NAME);rm/dev/MOD_NAME设备的打开与释放设备的打开与释放要通过文件操作结构体中定义的相关函数open()和release()来完成;主要完成设备的初始化工作以及设备的释放。文件操作结构体的定义structfile_operations{ structmodule*owner; ssize_t(*read)(structfile*,char*,size_t,loff_t*); ssize_t(*write)(structfile*,constchar*,size_t,loff_t*); unsignedint(*poll)(structfile*,structpoll_table_struct*); int(*ioctl)(structinode*,structfile*,unsignedint,unsignedlong); int(*mmap)(structfile*,structvm_area_struct*); 文件操作结构体的定义 int(*open)(structinode*,structfile*); int(*release)(structinode*,structfile*); int(*fsync)(structfile*,structdentry*,intdatasync);};文件操作结构体的主要函数open:用于打开文件设备release:在关闭文件的调用read:用于从设备中读取数据write:向设备发送数据poll:查询设备是否可读或可写ioctl:提供执行设备特定命令的方法fasync:用于设备的异步通知操作设备的读写字符设备的读写操作可以直接使用read()和write()函数来完成,块设备的读写,需要调用block_read()和block_write()函数,这2个函数向设备请求表中增加读写请求;块设备的读写是对内存缓冲区进行操作,如果内存缓冲区中没有要读入的数据,或者缓冲区中的数据需要写入设备,可以通过调用数据结构blk_dev_struct中的函数request_fn()完成。设备的控制操作对设备的控制操作可通过文件操作数据结构中的ioctl()函数来完成。控制操作与具体的设备有密切关系,需要根据设备实际情况进行具体分析。设备的轮询和中断处理轮询方式对于不支持中断的硬件设备,读写时需要轮流查询设备的状态,以便决定随后的数据操作。如果轮询处理方式的驱动程序被链接到内核,则意味着查询过程中,内核一直处于闲置状态。解决办法是使用内核定时器,进行定期查询。设备的轮询和中断处理中断处理方式硬件在需要的时候,向内核发出中断请求信号,而内核则负责把中断信号传递给相应的设备驱动。驱动程序必须在设备驱动的初始化时申请中断资源,并注册中断处理函数:申请:request_irq(irq,irq_handler,flag,dev_name,dev_id);释放:free_irq(irq,dev_id);其中irq为申请的中断线号,irq_handler为注册的中断处理函数,dev_id用于共享中断信号线。典型字符驱动程序框架staticstructfile_operationsdemo_fops={ read: demo_read write: demo_write open: demo_open ……};intinit_module(void){ returndemo_init();}用于注册设备驱动、申请中断线,初始化等voidcleanup_module(void){ demo_cleanup();}用于注销设备驱动、释放中断线等接口函数的实现……Example1PXA270开发系统的按键驱动程序与数码显示驱动数码显示源代码按键驱动源代码调试驱动程序,使用printk输出信息,信息的优先级依次为:KERN_EMERGKERN_ALERTKERN_CRITKERN_ERRKERN_WARNINGKERN_NOTICEKERN_INFOKERN_DEBUG如果要在终端输出信息,编译选项:-Wall–O2根据/kernel/printk.c的不同设置,不显示的信息会出现在/var/log/messages中驱动调试方法参见LinuxDeviceDriverschapter3帧缓冲设备驱动程序LCD分类LCD可由为液晶照明的方式有两种:传送式和反射式传送式屏幕要使用外加光源照明,称为背光(backlight),照明光源要安装在LCD的背后。传送式LCD在正常光线及暗光线下,显示效果都很好,但在户外,尤其在日光下,很难辩清显示内容。反射式屏幕,则不需要外加照明电源,使用周围环境的光线(或在某些笔记本中,使用前部照明系统的光线)。这样,反射式屏幕就没有背光,所以,此种屏幕在户外或光线充足的室内,才会有出色的显示效果,但在一般室内光线下,这种显示屏的显示效果就不及背光传送式的。

帧缓冲(Framebuffer)帧缓冲(framebuffer)-显示缓冲区是Linux为显示设备提供的一个接口,是把显存抽象后的一种设备,他允许上层应用程序在图形模式下直接对显示缓冲区进行读写操作。

Xwindow绘制窗口,显示汉字都是通过fb帧缓冲设备Linux可支持最多32个/dev/fb0~/dev/fb31缺省是/dev/fb0可以直接拷贝位图到fb来显示到屏幕cp/bitmap/penguin.bin/dev/fb0帧缓冲设备驱动原理帧缓冲设备属于字符设备,其目的就是通过配置PXA270的寄存器,在一段指定的内存与LCD之间建立一个自动传输的通道。这样,任何程序只要修改这段内存中的数据,就可以改变LCD上的显示内容。

帧缓冲设备的文件操作层接口staticstructfile_operationsfb_fops={

owner:THIS_MODULE,

read:fb_read,/*读操作*/

write:fb_write,/*写操作*/

ioctl:fb_ioctl,/*控制操作*/

mmap:fb_mmap,/*映射操作*/

open:fb_open,/*打开操作*/

release:fb_release,/*关闭操作*/

};

其中的成员函数都在文件linux/driver/video/fbmem.c中定义

帧缓冲设备的文件操作层接口控制操作函数fb_ioctl通过以下参数来传递控制命令FBIOGET_VSCREENINFOFBIOPUT_VSCREENINFOFBIOGET_FSCREENINFO映射操作函数fb_mmap将显示缓存映射到用户空间帧缓冲设备的驱动层接口—fb_infostructfb_info{charmodename; /*defaultvideomode*/charfontname; /*defaultfontname*/……structfb_var_screeninfovar;/*Currentvar*/structfb_fix_screeninfofix;/*Currentfix*/……structfb_ops*fbops;char*screen_base;/*Virtualaddress*/……};帧缓冲设备的驱动层接口—fb_infoModename:设备名称;Fontname:显示字体;fb_var_screeninfo:记录用户可修改的显示控制器参数,包括屏幕分辨率和每个像素点的比特数,其中的xres定义屏幕一行有多少个象素点,yres定义屏幕一列有多少个象素点,bits_per_pixel定义每个象素点用多少个字节表示;帧缓冲设备的驱动层接口—fb_infofb_fix_screeninfo:记录用户不能修改的显示控制器的参数,如屏幕缓冲区的物理地址,长度。当对帧缓冲设备进行映射操作的时候,就是从fb_fix_screeninfo中取得缓冲区物理地址的。Fb_ops:指向底层操作的函数的指针;结构体fb_info的定义如何写帧缓冲设备驱动遵循设备驱动程序的结构,设备注册、定义file_operations接口、初始化LCDC寄存器初始化一个fb_info结构,填充其中的成员变量,并调用register_framebuffer(&fb_info),将fb_info登记入内核。

实现定义的各个接口函数帧缓冲驱动程序—初始化函数新的FB驱动程序,需要向fbmem.c(drivers/video)中的结构体fb_drivers中添加相应的参数来给出初始化函数的入口。staticstruct{ constchar*name; int(*init)(void); int(*setup)(char*);}fb_drivers[]__initdata={#ifdefCONFIG_FB_PXA… {"pxa",pxafb_init,pxafb_setup},#endif……}帧缓冲驱动程序—初始化函数dbmx1fb_init的主要操作初始化相关的寄存器初始化一个fb_info结构,填充其中的成员变量利用register_framebuffer()向内核注册该设备。

如何写帧缓冲的应用程序在应用程序中,操作帧缓冲设备的一般步骤如下:1.

打开/dev/fb设备文件。2.

用ioctrl操作取得当前显示屏幕的参数,如屏幕分辨率,每个像素点的比特数。根据屏幕参数可计算屏幕缓冲区的大小。3.

将屏幕缓冲区映射到用户空间。4.

映射后就可以直接读写屏幕缓冲区,进行绘图和图片显示典型应用的代码结构(1)intmain()

{

intfbfd=0;

structfb_var_screeninfovinfo;

structfb_fix_screeninfofinfo;

longintscreens

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论