《嵌入式操作系统》_framebuffer驱动_20261008

framebuffer介绍

framebuffer 帧缓冲,是linux内核虚拟出来的一个设备,向应用层提供的一个统一标准接口的显示设备。

从驱动视角来看,framebuffer是一个典型的字符设备,而且创建类 /sys/class/graphics

显示原理

裸机中lcd的显示原理

soc中有cpu、ddr、lcd控制器。

lcd显示器主要包括lcd驱动器和lcd屏幕。

lcd控制器与lcd驱动器通过排线链接,我们通过初始化lcd控制器,在ddr中划分出一部分内存作为显存,与lcd显示形成一种映射。cpu之后仅仅需要将需要显示的内容放在ddr中即可,lcd控制器会自己把ddr中的内容刷新到lcd驱动器中。

操作系统中lcd显示原理

驱动负责建立ddr与lcd显示的映射关系,需要申请内存,初始化lcd控制器,并使用不同的虚拟内存映射同一个物理内存,两个不同的虚拟地址分别是内核空间和应用空间,即mmap技术。

应用负责把要显示的内容放在ddr中。

framebuffer使用

(1)获取设备文件 /dev/fb0

(2)获取设备信息 #include <linux/fb.h>

(3)mmap做映射

(4)填充framebuffer

framebuffer应用

编写应用代码如下,使用交叉编译工具编译后放到nfs中,方便开发板运行。

cpp 复制代码
#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <linux/fb.h>
#include <sys/ioctl.h>
#include <sys/mman.h>

#define DEVICE_NAME     "/dev/fb0"
#define WIDTH           1024
#define HEIGHT          600

void draw_pixel(unsigned int width,unsigned int height,unsigned int color);

unsigned int *mapped_mem = NULL;

int main() {
    int fd = -1, ret = -1;
    struct fb_var_screeninfo vinfo;
    struct fb_fix_screeninfo finfo;

    //获取设备文件描述符
    fd = open(DEVICE_NAME, O_RDWR);

    if (fd == -1) {
        perror("Error opening device");
        return 1;
    }
    printf("Framebuffer device opened successfully: %s\n", DEVICE_NAME);

    //获取设备信息
    ret = ioctl(fd, FBIOGET_VSCREENINFO, &vinfo);
    if (ret == -1) {
        perror("Error getting video screen info");
        close(fd);
        return 1;
    }

    ret = ioctl(fd, FBIOGET_FSCREENINFO, &finfo);
    if (ret == -1) {
        perror("Error getting fixed screen info");
        close(fd);
        return 1;
    }

    printf("Video screen info:\n");
    printf("  xres: %d\n", vinfo.xres);
    printf("  yres: %d\n", vinfo.yres);
    printf("  bits_per_pixel: %d\n", vinfo.bits_per_pixel);

    printf("  xres_virtual: %d\n", vinfo.xres_virtual);
    printf("  yres_virtual: %d\n", vinfo.yres_virtual);
    printf("  xoffset: %d\n", vinfo.xoffset);
    printf("  yoffset: %d\n", vinfo.yoffset);

    printf("Fixed screen info:\n");
    printf("  smem_start: %p\n", (void*)finfo.smem_start);
    printf("  smem_len: %u\n", finfo.smem_len);

    //mmap映射地址
    
    mapped_mem = mmap(NULL, finfo.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

    if (mapped_mem == MAP_FAILED) {
        perror("Error mapping framebuffer memory");
        close(fd);
        return 1;
    }
    printf("Framebuffer memory mapped to: %p\n", mapped_mem);

    draw_pixel(WIDTH, HEIGHT, 0x00FF0000); 
    close(fd);
    printf("Framebuffer device closed successfully: %s\n", DEVICE_NAME);
    return 0;
}



void draw_pixel(unsigned int width,unsigned int height,unsigned int color) {
    unsigned int x,y;
    for(y=0;y<height;y++) {
        for(x=0;x<width;x++) {
            //在此处添加绘制像素的代码
            *(mapped_mem + y * width + x) = color;
        }
    }
}

重要头文件<linux/fb.h>

该头文件在交叉编译工具中自带

可用命令宏定义

cpp 复制代码
#define FBIOGET_VSCREENINFO	0x4600  // Get video screen info
#define FBIOPUT_VSCREENINFO	0x4601  // Set video screen info
#define FBIOGET_FSCREENINFO	0x4602  // Get fixed screen info

不可变参数结构体

可变参数结构体

虚拟分辨率:我们可以设置不同大小的frambuffer,在显示器上实现缩小或者放大后的部分显示

framebuffer驱动

驱动框架

驱动框架fbmem.c

kernel/drivers/video/fbmem.c中注册了字符设备,并且创建了graphics类,提供了

int register_framebuffer(struct fb_info *fb_info)

int unregister_framebuffer(struct fb_info *fb_info)

接口给驱动编写者来注册fb设备

proc_creat函数为fb创建了proc文件,可以通过cat /proc/fb来验证

系统创建好了fb结构体 fb_info

建立了指针组成的数组,一共是32个

__read_mostly:优化,告诉编译器这玩意一般用来读

registered_fb的数组下标就是次设备号,也是fb_info结构体中node成员数值

注册接口就是把填充好的fb_info结构体填充到内核信息中,也就是说驱动负责填充fb_info之后申请注册即可。

fb_var_to_videomode开始确定显示模式,跳入modedb.c文件中执行

属性功能fbsys.c

kernel/drivers/video/fbsys.c文件处理fb在/sys目录下的属性与功能

显示模式modedb.c

kernel/drivers/video/modedb.c文件用于管理显示模式(VGA、HDMI、DP)

这里定义了一些常见的显示模式,没有你想要的那也没关系

这里通过fb_info结构体里面的var结构体信息填充mode结构体

通知信息fb_notify.c

kernel/drivers/video/fb_notify.c文件用于管理fb通知消息

硬件驱动

驱动主体s3cfb.c

kernel/drivers/video/samsung/s3cfb.c文件是驱动主体,真正开始实现硬件初始化,初始化为platform类设备,具体硬件函数调用s3cfb_fimd6x.c

分辨率、长宽、像素位、帧频率、极性

开机动画:

硬件控制s3cfb_fimd6x.c

kernel/drivers/video/samsung/s3cfb_fimd6x.c文件提供大量对lcd的硬件控制函数

平台驱动mach-x210.c

kernel/arch/arm/mach-s5pv210/mach-x210.c文件提供platform_devices

创建平台总线类设备,并注册

硬件信息devs.c

kernel/arch/arm/plat-s5p/devs.c文件提供硬件描述信息

相关推荐
垆边人似月.10 小时前
华为题:矩阵中的最长递增路径
算法·深度优先
Ruiery10 小时前
Linux 6.6内核内存管理深度解析(三):页表与缺页处理 — 虚拟地址怎么按需映射到物理页
linux·运维·服务器
研发小能10 小时前
DevOps 流水线怎么选?自研、开源拼装还是企业级平台
运维·开源·devops·嘉为蓝鲸
ouynagda10 小时前
iMX6ull Linux 嵌入式驱动开发笔记(LCD / ADXL345 / SPI 子系统)
linux·arm开发·驱动开发·笔记·嵌入式硬件
小诗懂技术10 小时前
linux驱动中断,相关中断的方式与适用场景
linux·arm开发·驱动开发·算法
不会就选b10 小时前
算法日常・每日刷题--<动态规划>25
算法
xiaoqiMikko10 小时前
Linux 实战(九·完):重定向、sudo、通配符的坑 + 报错速查表 —— 三台真机实测
linux·centos
迪康Defender10 小时前
终端安全行为分析:审计日志如何转化为业务报表?落地实践与避坑指南
运维·经验分享·安全·信息可视化·自动化·安全威胁分析·运维开发
H.莓飛10 小时前
【C++】模板初阶
linux·开发语言·c++·visual studio
kmomo..10 小时前
Linux SPI 驱动开发学习笔记:从框架到实战
linux·驱动开发·学习