IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> linux驱动开发 ST7789 Framebuffer驱动移植(I.MX6ULL平台) -> 正文阅读

[系统运维]linux驱动开发 ST7789 Framebuffer驱动移植(I.MX6ULL平台)

前言

ST7789的驱动移植成功后,还需要添加Framebuffer的支持,进行硬件接口的抽象化,通过对Framebuffer的读写来直接对显存进行操作

Framebuffer

  • Framebuffer驱动是将图像设备的显示进行抽象化,可以理解为一块内存空间(帧缓冲),该空间为显示内存的映射,会被刷新到LCD上;
  • Framebuffer是一个字符驱动,设备节点 /dev/fbn 有了Framebuffer驱动接口的支持,应用GUI可以友好完成移植
框图
  • 内核自带的驱动中,fb的字符驱动源码路径drivers/video/fbdev/core/fbmem.c
  • LCD驱动中的framebuffer的配置,源码路径/drivers/video/fbdev/mxsfb.c
    在这里插入图片描述
注册framebuffer
  • 在probe函数中进行framebuffer设备的注册,定义配置fb_info

int st7789_fb(struct spi_device *spi)
{
    unsigned char *v_addr = NULL; //映射地址
    unsigned int p_addr = 0; //物理地址
    lcd_data_t *data; //附加数据
    v_addr = dma_alloc_coherent(NULL, X*Y*4, &p_addr, GFP_KERNEL);//申请连续内存(dma方式)
    if(v_addr == NULL)
    {
        printk("dma allpc error!\n");
        return -1;
    }
    fb_info = framebuffer_alloc(sizeof(lcd_data_t), NULL);//额外分配lcd_data_t类型空间,位于framebuffer后面(私有数据)
    if(fb_info == NULL)
    {
        printk("fb_info allow error!\n");
        return -1;
    }
    data = fb_info->par; //data指针指向额外分配的空间
    data->spi = spi;
    fb_info->pseudo_palette = pseudo_palette;
    fb_info->var.activate   = FB_ACTIVATE_NOW;
    fb_info->var.xres = LCD_W;//240
    fb_info->var.yres = LCD_H; //240
    fb_info->var.xres_virtual = LCD_W;
    fb_info->var.yres_virtual = LCD_H;
    fb_info->var.bits_per_pixel = 32; //32bit (采用rgb888 24位图,驱动中需要自行转化)
   
    //rgb888
    fb_info->var.red.offset = 16;
    fb_info->var.red.length = 8;
    fb_info->var.green.offset = 8;
    fb_info->var.green.length = 8;
    fb_info->var.blue.offset = 0;
    fb_info->var.blue.length = 8;
    strcpy(fb_info->fix.id, "st7789_fb");
    fb_info->fix.smem_start = p_addr; //显存的物理地址
    fb_info->fix.smem_len = LCD_W*LCD_H*4;
    fb_info->fix.type = FB_TYPE_PACKED_PIXELS;
    fb_info->fix.visual = FB_VISUAL_TRUECOLOR;
    fb_info->fix.line_length = LCD_W*4;
    fb_info->fbops = &fops;
    fb_info->screen_base = v_addr; //显存虚拟地址
    fb_info->screen_size = LCD_W*LCD_H*4; //显存大小
    printk("register framebuff!\n");
    register_framebuffer(fb_info); 
    data->thread = kthread_run(thread_func, fb_info, spi->modalias);
    return 0;    
}
内核线程
  • 内核自带的驱动通过LCD控制器进行显存的刷新,但是SPI并不支持,这里通过增加内核线程进行刷新
    在这里插入图片描述

  • 通过内核线程将framebuffer的显存发送给ST7789控制器进行显示

//内核线程
int thread_func(void *data)
{
    lcd_data_t *ldata = fb_info->par;
    while (1)
    {  
        if (kthread_should_stop())
            break;
        show_fb(fb_info, ldata->spi);//刷新显存
    }
    return 0;
}
rgb888与rgb565转换

QT采用的是RGB888 24位图32bit数据,在LCD上显示,需要将framebuffer的显存进行转换

  • RGB888
0 0 0 0 0 0 0 0R7 R6 R5 R4 R3 R2 R1 R0G7 G6 G5 G4 G3 G2 G1 G0B7 B6 B5 B4 B3 B2 B1 B0
  • RGB565
R7 R6 R5 R4 R3G7 G6 G5 G4 G3 G2B7 B6 B5 B4 B3
  • 内核线程刷屏中将位图转化,提取单色高位,丢失部分精度
//grb888 to rgb565
for (x = 0; x < fb_info->var.xres; x++)
{
    k = p[y*fb_info->var.xres+x];//取出一个像素点的32位数据
    // rgb888 --> rgb565        
    pdata = (unsigned char *)&k;
    c = pdata[0] >> 3; //蓝色
    c |= (pdata[1]>>2)<<5; //绿色
    c |= (pdata[2]>>3)<<11; //红色
    //发出像素数据的rgb565
    *((unsigned short *)memory+y*fb_info->var.yres+x) = ((c&0xff)<<8)|((c&0xff00)>>8);
}

应用程序

流程

在这里插入图片描述

app用户代码
fd_fb = open(filename, O_RDWR);
if (fd_fb < 0)
{
    printf("can't open file %s\r\n", filename);
    return -1;
}
if (ioctl(fd_fb, FBIOGET_VSCREENINFO, &var))
{
    printf("can't get var\n");
    return -1;
}
screen_size = var.xres * var.yres * var.bits_per_pixel / 8; //230400
fb_base = (unsigned char *)mmap(NULL , screen_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_fb, 0); //mmap申请一块虚拟内存
if (fb_base == NULL)
{
    printf("can't mmap\n");
    return -1;
}
  
/* 清屏: 全部设为白色 */
memset(fb_base, 0xFF, screen_size);
/* 居中设置两个正方形 */
int *color = (int *)fb_base;
for(i = 80; i < 160; i++)
{
    for(j = 80; j < 160; j++)
    {
        *(color+i*var.xres+j)   = 0x000000;
    }
}
for(i = 100; i < 140; i++)
{
    for(j = 100; j < 140; j++)
    {
        *(color+i*var.xres+j)   = 0x00FF00;
    }
}

munmap(fb_base , screen_size);//释放线程
close(fd_fb);

实验现象

驱动安装后,启动应用程序

./lcd_app /dev/fb0

在这里插入图片描述

后续章节贴完整源码

  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2022-05-13 12:00:08  更:2022-05-13 12:00:22 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 15:30:58-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码