Chinaunix首页 | 论坛 | 博客
  • 博客访问: 159914
  • 博文数量: 9
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 729
  • 用 户 组: 普通用户
  • 注册时间: 2013-05-08 14:00
文章分类

全部博文(9)

文章存档

2015年(1)

2014年(2)

2013年(6)

分类: LINUX

2013-07-19 16:48:40

           通过上一个小章节的探讨,大家应该对LCD工作原理应该有了个大概的理解吧,其实这东西内容都是比较细致的,(我来罗嗦两句,那个上一章连那个啥啥LCD的几种类型都还没说呢)。接下来给大家说一下相关的FB结构体,和驱动编写的步骤。(本来SC2410核心就有LCD核心驱动,源码部分有兴趣的去看看,其中将FRAMEBUFFER以平台驱动形式注册的,源码是我们无穷无尽的动力来源,里面的算法,逻辑组织,框架思想真心值得我们去探索。还记得本科的时候学习操作系统课的时候,在进程同步与互斥部分,在实现多读者和少写者,读者优先的时候,LINUX 内核同步机制下,直接用一个原子量好像是0x0100000,写者仅当原子量为初始值的时候才能访问临界区,而最多允许这么个读者,言简意概啊)
            废话不多说,首先介绍一下FRAMBUFFER的核心数据结构struct fb_info *fb,具体请参考源码fb.h,或者网上搜一下,(我觉得一篇文章不是来贴代码的最终要的是来留下一个思想一个指导);首先附上一张图,图片来源于网络,接下来解析再进行详细的说明。
           

          每一个fb_info都对应一个帧设备和帧缓冲区,其中如图所显示的结构是组成它的核心。首先说一下fb_ops,这个函数我们自己的驱动程序中需要重写其中的方法,假如大家有做过简单的字符驱动程序的时候,这个类似于我们注册的file_opreations。现在重点说明一下几个重点的函数操作。
            (一)fb_ops
            (1)fb_mmap,本函数实际上在系统调用mmap2中被调用的用于对显示帧缓冲区的映射到进程地址空间,在下节的应用程序编程中我们将使用到。
            (2)fb_ioctl,本函数对应的系统调用IOCTL读取或者修改LCD硬件控制部分参数,可以通过如命令ioctl(LCD,FBIOGET_VSCREENINFO,&fb_var)来实现对可改变参数区的数据读取,
当然了前提是你已经做好了相应的响应参数驱动程序代码。一般本操作的实现通过SWITCH语句的,大家自己写驱动的时候可以参照一下已做好的核心驱动源码部分。
            (3)fb_get_fix,fb_get_var,fb_set_var函数,一般假如你的程序很简单的话,实现如下几个就可以了,具体函数意思就如英文所述,强烈建议在初次编写时使用。
            (二)fb_fix_SCREENINFO,fb_var_screeninfo
              这两个结构体实质上是保存了我们的帧设备的具体信息,前者我们只能读取,后者是能进行修改的部分,如屏幕的显示尺寸啊。具体就不附代码了。大家在设置参数的时候可能会有些迷茫,可以参考下源码再来对自己的参数设置。
              (三)fb_cmap
                这个就是所谓的调色板信息了,我们在上一个章节的伪代码里面有设置颜色的位数,这里我们自己编写的驱动程序需要提供类似于LCD核心驱动提供的ioctl 中的FBIOPUTCMAP的命令选项来进行颜色设置。假如想做一个简单的驱动,这里可以在初始化部分设置好了,不再提供颜色配置。
                
----------------------------------------------------------------------------------------------------------------------------------------------------------

            接下来,我们要了解内核是如何管理我们的缓冲帧设备的,具体源码在FBMEM.c文件中,它是FB设备驱动的中间层,为上层提供系统调用,为底层提供接口。实质上这个中间层为我们系统中的所有FB设备驱动提供了一个统计计数和一个接口。我们写好的驱动工作最终通过register_framebuffer(&fb_info)函数向其注册,现在附上一个网络图,供大家进行理解。
                            


      这里还是举一个简单的例子来进行说明一下,我们在应用层调用mmap后,会进入到FBMEM.c 的fb_mmap(struct file *file, struct vm_area_struct * vma)中,接下来
         int fbidx = iminor(file->f_path.dentry->d_inode);//提取打开文件的次设备号
         struct fb_info *info = registered_fb[fbidx];
         struct fb_ops *fb = info->fb_ops;
          register_fb 数组就是已经注册的FB驱动的restore.第三句就将提取我们编写的驱动程序的FB_OPS.后面的代码就省啦,接下来的代码部分有检查,最终将驱动程序调用的数据返还用户空间, 
        start = info->fix.smem_start;
         len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.smem_len);

有兴趣的自己往下看啦。
        
---------------------------------------------------------------------------------------------------------------------------------------------------------

               通过以上的叙述,不知道大家有木有一点眉目了,现在来说一下LCD的简单驱动程序开发过程,可能我们做出来的驱动程序只能像小鸡吃米一样,做不出太多的事情,但是坚持总会有收获的,这里我将简单叙述一下如何编写一个LCD驱动。在此先叙述一下内核提供的LCD驱动源码是如何来编写的,当然了我们做的驱动程序并不用那么复杂。但是一个结构是不能缺少的struct devices 
                LCD核心驱动首先将LCD设备和驱动注册为一个平台设备和驱动程序,具体的平台驱动模型大家有兴趣大家有兴趣看一看,这里摘抄大神的分析,整个LCD DEVICES和DEVICES的调用路径:
              do_exit--->kernel_init--->__exception_text_end-->platform_driver_register--->driver_register--->bus_add_driver--->driver_attach--->bus_for_each_dev--->_driver_attach--->driver_probe_device--->platform_drv_probe--->s3c2410fb_probe--->s3c24xxfb_probe --->register_framebuffer--->fb_notifier_call_chain--->blocking_notifier_call_chain--->_blocking_notifier_call_chain--->notifier_call_chain--->fbcon_event_notify--->fbcon_takeover--->take_over_console--->visual_init--->fbcon_init--->s3c2410fb_set_par
                ps:本段路径来源于网络,非本人所写
            这里简要的进行一些说明和介绍,首先进行平台设备的注册,然后再每加载一个设备驱动的时候,都会对每个设备调用总线的platform_match函数,匹配成功后会调用所谓的probe函数,接下来的大家可以自己进行分析。
                那么我们在自己编写的驱动程序的时候首先要注意啦,我们编写可木有这么复杂的噢,
                fb_info->node = i;//前面省了些代码,I最开始是从0开始分配的
                fb_info->dev = device_create_drvdata(fb_class, fb_info->device,MKDEV(FB_MAJOR, i), NULL,"fb%d", i);
               这两行代码来自于register_framebuffer函数,看到现在是不是觉得可以瞬间秒杀这个驱动程序了。
                开发步骤:
                (1)最开始的时候在模块初始化部分,调用上一章节的void init_devices初始化设备。
                (2)接着编写fb_ops完成你要实现的部分功能,初次尝试的时候可以只实现啊,少量的功能。(写的快没力气了)
                (3)初始化FB_INFO结构,注意node值的赋值意义,系统怎么判断要调用这个FOPS呢,就是看这个数字的。在这个看上面代码,主设备号已经被分配啦,#DEFINE FB_MAJOR 29
                 (4)向fbmem.c注册等。模块结束部分等。
                  注意,要做这个自己的驱动实验,要阻止核心LCD的注册。
                  下一节将描述两个常用的小程序,第一个是如何截取LCD屏幕的画面,第二个是如何在LCD屏中显示一定格式的图片。当然为了方便我全部用的是640*480 BMP格式的图片,颜色数当然是到程序中做判断了。
                      
                    
                
                





















               
阅读(2592) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~