驱动_LCD驱动框架

 

 


 

 

 

 


 

LCD驱动具体编写:

        1) 分配一个fb_info结构体       

        2) 设置fb_info (fix , var , fbops )

        3) 设置硬件相关的操作

        4) 使能LCD,并注册fb_info: register_framebuffer()


 

 


 
 
重要函数:

①:fbmem.c
 
 
struct fb_info *framebuffer_alloc(size_t size, struct device *dev);  
//功能: 向内核申请一段大小为sizeof(struct fb_info) + size的空间,其中size的大小代表设备的私有数据空间,并用fb_info的par域指向该私有空间。
//参数: 参数一:空间大小       参数二: dev->dev(父类)
//申请一个fb_info结构体

 

   void *dma_alloc_writecombine(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp); //分配DMA缓存区给显存

//返回值为:申请到的DMA缓冲区的虚拟地址,若为NULL,表示分配失败,则需要使用dma_free_writecombine()释放内存,避免内存泄漏
//参数如下: //*dev:指针,这里填0,表示这个申请的缓冲区里没有内容 //size:分配的地址大小(字节单位) //*handle:申请到的物理起始地址 //gfp:分配出来的内存参数,标志定义在<linux/gfp.h>,常用标志如下: //GFP_ATOMIC 用来从中断处理和进程上下文之外的其他代码中分配内存. 从不睡眠. //GFP_KERNEL 内核内存的正常分配. 可能睡眠. //GFP_USER 用来为用户空间页来分配内存; 它可能睡眠.








int register_framebuffer(struct fb_info *fb_info);  
//向内核中注册fb_info结构体,若内存不够,注册失败会返回负数

int unregister_framebuffer(struct fb_info *fb_info) ;
//注销内核中fb_info结构体

 






  error:
      

 

 

 

 
 

 

 

 

 

    ②: xxfb.c 

   struct fb_info *framebuffer_alloc(size_t size, struct device *dev); //申请一个fb_info结构体,

   int register_framebuffer(struct fb_info *fb_info);//向内核中注册fb_info结构体,若内存不够,注册失败会返回负数

 

 

// 分配显存,并告诉fb_info
fb_info->screen_base = dma_alloc_writecombine(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp)  

 

 

 

   error:

         int  unregister_framebuffer(struct fb_info *fb_info);   

       struct fb_info * framebuffer_release(size_t size, struct device *dev);

 

 

 

 


 重要结构体

struct fb_info {                            //  记录缓冲区设备的全部信息
  ... ...
  struct fb_var_screeninfo var; //可变的参数
  struct fb_fix_screeninfo fix; //固定的参数
  ... ...
  struct fb_ops *fbops; //操作函数
  ... ...
  char __iomem *screen_base;  //显存虚拟起始地址
  unsigned long   screen_size;   //显存虚拟地址长度

  void *pseudo_palette;
  //假的16色调色板,里面存放了16色的数据,可以通过8bpp数据来找到调色板里面的16色颜色索引值,模拟出16色颜色来,节省内存,不需要的话就指向一个不用的数组即可

 

  struct device *device;/* This is the parent */  父设备(父类)

 

  ... ...
};

 

struct fb_fix_screeninfo {    //记录控制器不可修改的参数(缓冲区的物理地址和长度)

       char id[16];               //id名字,字符串形式的标识符
       unsigned long smem_start;  //控制器物理起始地址                          
       __u32         smem_len;    //控制器长度,字节为单位
       __u32 type;                //lcd类型,默认值0即可
       __u32 type_aux;            //附加类型,为0,分界
       __u32 visual;              //画面设置,常用参数如下
    // FB_VISUAL_MONO01             0   单色,0:白色,1:黑色
    // FB_VISUAL_MONO10             1    单色,1:白色,0:黑色
    // FB_VISUAL_TRUECOLOR          2     真彩(TFT:真彩)
    // FB_VISUAL_PSEUDOCOLOR     3     伪彩
    // FB_VISUAL_DIRECTCOLOR        4     直彩

    __u16 xpanstep;                /*如果没有硬件panning就赋值为0 */
    __u16 ypanstep;                /*如果没有硬件panning就赋值为0 */
    __u16 ywrapstep;               /*如果没有硬件ywrap就赋值为0   */

    __u32 line_length;             /*一行的字节数 ,例:(RGB565)240*320,那么这里就等于240*16/8 */

    /*以下成员都可以不需要*/
    unsigned long mmio_start;      /*内存映射IO的起始地址,用于应用层直接访问寄存器,可以不需要*/                                   
        __u32 mmio_len;                /* 内存映射IO的长度,可以不需要*/
        __u32 accel;                 
        __u16 reserved[3];       /* 保留 */
};

 

 

struct  fb_var_screeninfo  {              //记录控制器可以修改的参数 (分辨率,像素位数)

   __u32  xres;              /*可见屏幕一行有多少个像素点(就是分辨率X)*/
     __u32 yres;        /*可见屏幕一列有多少个像素点(就是分辨率Y)*/
    __u32 xres_virtual;     /*虚拟屏幕一行有多少个像素点*/       
    __u32 yres_virtual;     /*虚拟屏幕一列有多少个像素点*/
    __u32 xoffset;          /*虚拟到可见屏幕之间的行偏移,若可见和虚拟的分辨率一样,就直接设为0*/
    __u32 yoffset;          /*虚拟到可见屏幕之间的列偏移*/
    __u32 bits_per_pixel;   /*每个像素的位数即BPP,比如:RGB565则填入16*/
    __u32 grayscale;        /*非0时,指的是灰度,真彩直接填0即可*/

    struct fb_bitfield red;//fb缓存的R位域, fb_bitfield结构体成员如下:
   __u32 offset;          //区域偏移值,比如RGB565中的R,就在第11位
   __u32 length;          //区域长度,比如RGB565的R,共有5位
   __u32 msb_right;       //msb_right ==0,表示数据左边最大, msb_right!=0,表示数据右边最大


    struct fb_bitfield green;        /*fb缓存的G位域*/
    struct fb_bitfield blue;         /*fb缓存的B位域*/

   /*以下参数都可以不填,默认为0*/
    struct fb_bitfield transp; /*透明度,不需要填0即可*/    
 
    __u32 nonstd;              /* != 0表示非标准像素格式*/
    __u32 activate;            /*设为0即可*/
    __u32 height;              /*外设高度(单位mm),一般不需要填*/
    __u32 width;               /*外设宽度(单位mm),一般不需要填*/
    __u32 accel_flags;         /*过时的参数,不需要填*/

    /* 除了pixclock本身外,其他的都以像素时钟为 单位*/ 
    __u32 pixclock;        /*像素时钟(皮秒)*/
    __u32 left_margin;     /*行切换,从同步到绘图之间的延迟*/
    __u32 right_margin;    /*行切换,从绘图到同步之间的延迟*/
    __u32   upper_margin;  /*帧切换,从同步到绘图之间的延迟*/
    __u32l  ower_margin;   /*帧切换,从绘图到同步之间的延迟*/
    __u32   hsync_len;     /*水平同步的长度*/
    __u32   vsync_len;     /*垂直同步的长度*/
    __u32   sync;
    __u32   vmode;
    __u32   rotate;
    __u32   reserved[5];   /*保留*/

}


static struct fb_ops  = {      // 底层硬件操作函数的集合

.owner = THIS_MODULE //被使用时阻止模块被卸载

      int (*fb_check_var)(struct fb_var_screeninfo *var, struct fb_info *info);    //检查可变参数并进行设置  

     int (*fb_set_par)(struct fb_info *info);              //根据设置的值进行更新,使之有效  

     int (*fb_blank)(int blank, struct fb_info *info);   //显示空白  
         .fb_setcolreg  //设置调色板fb_info-> pseudo_palette,自己构造该函数,     //设置颜色寄存器  

         .fb_fillrect    //填充矩形,用/drivers/video/ cfbfillrect.c里的函数即可, //矩形填充  

         .fb_copyarea    //复制数据, 用/drivers/video/cfbcopyarea.c里的函数即可  //复制数据  
 
         .fb_imageblit   //绘画图形, 用/drivers/video/imageblit.c里的函数即可    //图形填充  
}; 


 


 时序参数:

                     ① 控制器输出时序

 

    

帧参数:

     VSYNC:垂直同步时钟

     VSPW  :垂直同步脉宽  VBPD:垂直后肩  LINEVAL:垂直有效  VFPD:垂直前肩

     INT_FRSyn :帧同步中断

     VDEN :   视频数据使能  

 

行参数:

    HSYNC:水平同步时钟  VCLK :像素时钟

       HSPW  :水平同步脉宽   HBPD:水平后肩  HOZVAL:水平有效  HFPD:水平前肩

    VD :  视频数据

    VDEN :  视频数据使能信号

    LDEN :   行结束信号

 

                     ② 液晶屏输出时序

 

     


 

 

 

 

 

<程序控制>

1.打开设备   

  int fd = open("/dev/fd0",O_RDWR);


2.获取到lcd屏的信息xres,yres,bpp    

  应用:  ioctl(fd,FBIOGET_VSCREENINFO,&var);
---------------------------------------------------------------------------------
  驱动:  static long fb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)

 

3.映射显存到应用空间

  char *addr  = mmap(NULL, length,  PROT_READ|PROT_WRITE,  MAP_SHARED, int fd, 0);

  framebuffer_ptr =(char *)mmap( NULL,//如果此值为NULL,则表示用内核来自动给你分配一块虚拟空间
  screensize, //空间大小
  PROT_READ|PROT_WRITE,//权限
  MAP_SHARED, //是否可以共享
  framebuffer_fd, //文件描述符
  0); //从哪个地方开始

 

4. 得到图片的数据,将数据写入到映射的虚拟地址指向的空间

  运行程序的格式:./lcd_test   dev/fbx   pic.bmp 

  /*1.打开一副图片*/
  pic_fd =open(argv[2],O_RDWR);
  printf("pic_fd=%d\n",pic_fd);

  /*2.获取图片大小*/
  len =lseek(pic_fd, 0, SEEK_END);
  printf("len =%ld\n",len);

  /*3.读取图片数据*/
  read(pic_fd,buffer,len);

  /*4.初始化lcd*/
  fd=init_lcd(argv[1]);

  //5.buffer存放了bmp图片数据,framebuffer_ptr映射后返回的显存的地址
  draw_bmp(buffer,(unsigned short *) framebuffer_ptr);

    代码示例:https://www.cnblogs.com/panda-w/p/10992943.html

 

 

<笔记>

1. 

 

 

 

 

 

 

 

转载于:https://www.cnblogs.com/panda-w/p/10922283.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值