zoukankan      html  css  js  c++  java
  • 《驱动学习

    https://www.cnblogs.com/sky-heaven/p/8670477.html

    https://www.cnblogs.com/lifexy/p/7603327.html

    https://www.cnblogs.com/silencehuan/p/11202496.html

    https://www.cnblogs.com/lubiao/p/4850258.html

     1.LCD驱动概念

      LCD是Liquid Crystal Display的简称,也就是经常所说的液晶显示器。LCD能够支持彩色图像的显示和视频的播放,是一种非常重要的输出设备。如果我们的系统要用GUI(图形界面接口),比如minigui,MicroWindows。这时LCD设备驱动程序就应该编写成frambuffer接口,而不是编写成仅仅操作底层的LCD控制器接口。

      framebuffer是Linux系统为显示设备提供的一个接口,它将显示缓冲区抽象,屏蔽图像硬件的底层差异,允许上层应用程序在图形模式下直接对显示缓冲区进行操作。framebuffer又叫帧缓冲,是Linux为操作显示设备提供的一个用户接口。用户应用程序可以通过framebuffer透明地访问不同类型的显示设备。从这个方面来说,framebuffer是硬件设备显示缓冲区的抽象。Linux抽象出framebuffer这个帧缓冲区可以供用户应用程序直接读写,通过更改framebuffer中的内容,就可以立刻显示在LCD显示屏上。

      framebuffer是一个标准的字符设备,主设备号是29,次设备号根据缓冲区的数目而定。framebuffer对应/dev/fb%d设备文件。根据显卡的多少,设备文件可能是/dev/fb0、/dev/fb1等。缓冲区设备也是一种普通的内存设备,可以直接对其进行读写。对用户程序而言,它和/dev下面的其他设备没有什么区别,用户可以把frameBuffer看成一块内存,既可以写,又可以读。显示器将根据内存数据显示对应的图像界面。这一切都由LCD控制器和响应的驱动程序来完成。

    2、fb与应用程序的交互

      对于用户程序而言,它和其他的设备并没有什么区别,用户可以把fb看成是一块内存,既可以向内存中写数据,也可以读数据。fb的显示缓冲区位于内核空间,应用程序可以把此空间映射到自己的用户空间,在进行操作。

      在应用程序中,操作/dev/fbn的一般步骤如下:
      (1)打开/dev/fbn设备文件。
      (2)用ioctl()操作取得当前显示屏幕的参数,如屏幕分辨率、每个像素点的比特数。根据屏幕参数可计算屏幕缓冲区的大小。
      (3)用mmap()函数,将屏幕缓冲区映射到用户空间。
      (4)映射后就可以直接读/写屏幕缓冲区,进行绘图和图片显示了。

    3、LCD驱动框架

      在linux中,fb设备驱动的源码主要在Fb.h (includelinux)和Fbmem.c (driversvideo)两个文件中,它们是fb设备驱动的中间层,为上层提供系统调用,为底层驱动提供接口。

      

      其中结构体成员因为太多就不列出来。具体可查看源码。

    4.LCD驱动核心层(fbmem.c)源码分析

      一般分析一个驱动,先从他得入口函数开始分析fbmem_init()

    static int __init fbmem_init(void)
    {
        proc_create("fb", 0, NULL, &fb_proc_fops);
    
        if (register_chrdev(FB_MAJOR,"fb",&fb_fops))  
            printk("unable to get major %d for fb devs
    ", FB_MAJOR);
    
        fb_class = class_create(THIS_MODULE, "graphics");
        if (IS_ERR(fb_class)) {
            printk(KERN_WARNING "Unable to create fb class; errno = %ld
    ", PTR_ERR(fb_class));
            fb_class = NULL;
        }
        return 0;
    }

    #define FB_MAJOR  29   /* /dev/fb* framebuffers */

      register_chrdev(FB_MAJOR,"fb",&fb_fops)向内核注册了一个主设备号为29,名字叫“fb”,fb_fops的file_operations的结构体变量。

      通过cat /proc/devices 也能找到这个字符设备:  

      

       和我们之前的驱动程序一样,但是没有使用创建设备节点,为什么?

      因为需要注册了LCD驱动后,才会有设备节点,所以这里的代码没有 ,后面会分析哪里有。

      

      应用程序要使用某个设备,就要先open这个设备。所以接下来分析一下fb_fops中的fb_open

    extern struct fb_info *registered_fb[FB_MAX];
    static
    int fb_open(struct inode *inode, struct file *file) { int fbidx = iminor(inode); struct fb_info *info; int res = 0; if (fbidx >= FB_MAX) return -ENODEV; info = registered_fb[fbidx]; if (!info) request_module("fb%d", fbidx); info = registered_fb[fbidx]; if (!info) return -ENODEV; mutex_lock(&info->lock); if (!try_module_get(info->fbops->owner)) { res = -ENODEV; goto out; } file->private_data = info; if (info->fbops->fb_open) { res = info->fbops->fb_open(info,1); if (res) module_put(info->fbops->owner); } #ifdef CONFIG_FB_DEFERRED_IO if (info->fbdefio) fb_deferred_io_open(info, inode, file); #endif out: mutex_unlock(&info->lock); return res; }

       从上面的三行红色代码大概可以看出,把次设备号作为下标,在registered_fb数组中找到保存着的LCD驱动信息,再赋值给info,然后去调用具体LCD的open函数。

      所以接下来就要了解一下,怎么把LCD驱动信息放到registered_fb数组中(查看在哪里对registered_fb进行赋值)。

      通过查找,只有一条registered_fb[i] = fb_info(register_framebuffer()函数中)

      所以驱动设备是通过register_framebuffer()函数进行一个注册的,而且还在这里创建了设备节点device_create()。

      

      现在就可以通过查看哪些函数调用了register_framebuffer()函数,然后分析一下LCD设备是怎么向驱动核心层注册的。

      

       可以看到有很多设备都已经注册了。就拿我们熟悉的s3c24xx来分析一下吧。

    static int __init s3c24xxfb_probe(struct platform_device *pdev,
                      enum s3c_drv_type drv_type)
    {
      /**/  
        ret = register_framebuffer(fbinfo);
      /**/  
    }

      probe函数,很熟悉。就是驱动设备总线模型了。和我们上节分析的platform机制一样,当与设备匹配成功,就进入probe函数,初始化驱动设备。

    5.总结

      1.当我们加载某个lcd硬件设备模块,就会通过platform机制一样,当与设备匹配成功,就进入probe函数,初始化驱动设备。

      2.probe函数中调用了registered_fb[i] = fb_infodevice_create(),这两个分别注册了LCD硬件信息和创建了设备节点。

      3.应用程序通过open函数打开某个LCD设备的时候,会调用fb_open。

      4.fb_open中通过获取次设备号,在registered_fb数组中找到相对应LCD设备信息。最后调用LCD设备信息中open函数。

  • 相关阅读:
    Hibernate Tool建Entity
    MySQL新建用户和库表
    用友U8年度账结转 常用凭证丢失
    U890采购入库单修改供应商
    robocopy
    sql的left join 、right join 、inner join之间的区别
    Linux永久修改系统时间
    UF清log
    下拉式选单连动设定
    SQL取最大值编码(自动编码)
  • 原文地址:https://www.cnblogs.com/zhuangquan/p/11665931.html
Copyright © 2011-2022 走看看