zoukankan      html  css  js  c++  java
  • LCD驱动分析(一)字符设备驱动框架分析

    参考:S3C2440 LCD驱动(FrameBuffer)实例开发<一>

         S3C2440 LCD驱动(FrameBuffer)实例开发<二>

    LCD驱动也是字符设备驱动,也遵循字符设备驱动的流程:

    a. 分配主设备号

    b. 构建file_operations结构体中的open,write,read...等函数

    c. 调用register_chrdev()函数注册字符设备

    d. 调用class_register()注册类

    e. 调用device_create()创建设备,linux会在sysfs目录下自动创建字符设备。

    以上的步骤同样适用于分析输入子系统,只不过上面的各个步骤可能分散在不同的文件与函数中完成。

    1.linux/drivers/video/fbmem.c中的fbmem_init()函数完成a,b,c,d完成以上四步。

     1 static const struct file_operations fb_fops = {
     2     .owner =    THIS_MODULE,
     3     .read =        fb_read,
     4     .write =    fb_write,
     5     .unlocked_ioctl = fb_ioctl,
     6     .mmap =        fb_mmap,
     7     .open =        fb_open,
     8     .release =    fb_release,
     9     .llseek =    default_llseek,
    10 };
    11 static int __init fbmem_init(void)
    12 {
    13     proc_create("fb", 0, NULL, &fb_proc_fops);
    14 
    15     if (register_chrdev(FB_MAJOR,"fb",&fb_fops))
    16         printk("unable to get major %d for fb devs
    ", FB_MAJOR);
    17 
    18     fb_class = class_create(THIS_MODULE, "graphics");
    19     if (IS_ERR(fb_class)) {
    20         printk(KERN_WARNING "Unable to create fb class; errno = %ld
    ", PTR_ERR(fb_class));
    21         fb_class = NULL;
    22     }
    23     return 0;
    24 }

    2. 那么谁来调用device_create()创建设备?这里直接给出结论,后面再分析过程。

    fbmem.c中定义的fb_info结构体的全局指针数组,fb_info结构体是LCD驱动的关键。register_framebuffer()函数中会调用device_create()函数创建设备节点。

    struct fb_info *registered_fb[FB_MAX] __read_mostly; //FB_MAX=32

    int register_framebuffer(struct fb_info *fb_info)

      -->ret = do_register_framebuffer(fb_info);

        -->找到空的registered_fb[i]

        -->fb_info->dev = device_create(fb_class, fb_info->device,       MKDEV(FB_MAJOR, i), NULL, "fb%d", i);

        -->设置fb_info

        -->registered_fb[i] = fb_info;

    3. 如何打开设备?

    fb_open(struct inode *inode, struct file *file)

      -->int fbidx = iminor(inode);

      -->struct fb_info *info=get_fb_info(fbidx);//根据此设备号找到fb_info结构体

      -->fb_info = registered_fb[fbidx];

      --> file->private_data = info;

      --> if (info->fbops->fb_open) res = info->fbops->fb_open(info,1);//如果结构体中定义了open函数,执行新的open函数

    4.如何读取设备?这里的关键是info->screen_base,设置为LCD控制器帧缓冲区的起始地址。

    fb_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)

      -->struct fb_info *info = file_fb_info(file);//找到打开的fb_info结构体

      --> if (info->fbops->fb_read)//如果fb_info中定义的读函数,则执行新的读函数

        return info->fbops->fb_read(info, buf, count, ppos);

      //没有定义新的读函数则执行下面

      -->src = (u8 __iomem *) (info->screen_base + p);//设置源地址

      -->buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count, GFP_KERNEL);//设置目的地址

      -->dst = buffer;

      -->fb_memcpy_fromfb(dst, src, c);//读到用户空间

      -->copy_to_user(buf, buffer, c)

  • 相关阅读:
    Chrome 无法登录 GitHub,响应时间过长,可行解决办法
    npm install报错 npm ERR! cb() never called! 检查镜像源!
    Win10 移动文件的时候“卡”在“正在暂停/取消”解决办法
    VS code 彻底关闭插件自动更新功能
    箭头函数 函数中的this指向
    ES6 ES6变量的声明
    范围内的拖拽事件
    div拖拽移动事件
    事件对象的属性 div点击移动事件
    tab切换之循环遍历
  • 原文地址:https://www.cnblogs.com/yangjiguang/p/6080116.html
Copyright © 2011-2022 走看看