首页 > 其他分享 >基于QEMU的LCD驱动详解

基于QEMU的LCD驱动详解

时间:2024-07-17 16:57:18浏览次数:15  
标签:info 缓冲 fb LCD 详解 内核 Framebuffer QEMU 设备

1. 使用QEMU的优点

  • 概述:使用QEMU模型LCD屏幕,可以只写驱动程序,不需要设置LCD硬件相关,也不需要映射Framebuffer。

    • 使用QEMU可以非常方便地调试内核、查看驱动程序执行过程

    • 有助于深入研究内核及驱动

Linux驱动 = 驱动框架 + 硬件操作。 如果硬件操作足够简单,我们就可以把精力放在驱动程序的框架上,这才是Linux的核心。 

对于硬件操作,你至少要做这些事情:

  • 设置引脚用于LCD

  • 阅读LCD手册,阅读LCD控制器手册,根据LCD参数设置LCD控制器

    • 设置LCD控制器时,你还需要了解所用的主控芯片的时钟系统

  • 分配Framebuffer,把Framebuffer地址告诉LCD控制器

总之,非常复杂。如果你换了芯片,这些工作又得重来一次。 如果你本身已经对阅读芯片手册很熟悉,对硬件操作很熟悉,那么学习时没必要把时间浪费在这方面。 使用QEMU,虚拟出一款简单的LCD控制器,可以简化硬件操作,让我们把精力放在驱动框架上。

2. 虚拟LCD相关的控制器手册

概述:这些设置是在构建QEMU这个软件的时候配置的一些相关信息

实现了一个虚拟的LCD控制器,它的操作很简单。 只有4个寄存器,手册如下:

虚拟的LCD芯片参数:目虚拟的LCD分辨率为500x300,16bpp。暂时未支持其他参数。

3. 上机实验_基于QEMU

3.1 实验思路

概述:使用 QEMU思路:QEMU是虚拟的LCD,需要调用内核的驱动程序进行驱动,我们更改驱动程序需要再内核目录例如(linux/drivers/video/fbdev)更改对应的驱动程序,主要是将写好的驱动程序放入此目录中,然后修改makefile文件,如下:

最后,即可重新执行make zImage编译内核,内核里就含有新的驱动程序了。

然后调用一些测试函数,例如fb_test,即可判断驱动是否更改成功。

3.2 驱动代码分析

声明用到的一些头文件

声明用到的变量和操作函数,定义LCD控制器结构体,声明两个变量指向LCD控制器和Framebuffer信息,定义Framebuffer操作函数集合。


入口函数:分配fb内存,设置fb,包括分辨率,像素深度,各个颜色偏移量和位数,

计算内存大小依据:

DMA(Direct Memory Access,直接内存访问)是一种硬件特性,它允许某些硬件子系统(如网络接口卡、图形卡、声卡等)直接访问系统内存,而无需中央处理单元(CPU)的介入。这种能力使得这些硬件设备能够独立于CPU执行内存读写操作,从而提高系统的整体性能和效率。

分配DMA一致性内存的目的是为了让Framebuffer能够被显示控制器等硬件设备直接访问,同时确保CPU能够看到由DMA操作引起的内存更改,而无需进行额外的缓存同步操作。

设置fb类型(颜色方面),颜色视觉类型(真彩色),给结构体赋值具体操作函数

register_framebuffer(myfb_info); 作用是将之前初始化和配置的Framebuffer设备注册到Linux内核中。注册Framebuffer设备是Linux驱动程序开发中的一个重要步骤,具体作用如下:

总结:注册相当于在内核空间将自己的参数和操作函数登记,此时内核空间可以对其进行内存,中断,分配资源,处理,同步等管理,

  1. 设备识别:注册后,内核会识别Framebuffer设备作为一个可用的显示设备,可以在/var/log目录下的某些日志文件中看到它被识别和注册的信息。

  2. 文件系统集成:注册Framebuffer设备会在/dev目录下创建一个设备文件(如/dev/fb0),用户空间程序可以通过这个文件与Framebuffer设备进行交互。

  3. 统一访问接口:注册过程将Framebuffer的固定和可变属性、操作函数等信息注册到内核的统一框架中,为其他内核组件或用户空间程序提供统一的访问接口。

  4. 驱动程序钩子:注册Framebuffer设备时,会将fb_info结构体中的fbops(Framebuffer操作)钩子函数注册到内核,这些函数定义了如何操作Framebuffer,例如屏幕的打开、关闭、读写等。

  5. 内存管理:注册后,Framebuffer的内存区域会被内核纳入管理,确保内存的合法访问和同步。

  6. 硬件同步:注册Framebuffer设备后,内核可以协调不同用户空间程序对Framebuffer的访问,确保显示内容的正确更新和硬件状态的同步。

  7. 中断处理:如果Framebuffer硬件支持中断,注册时也可以设置中断处理函数,以便在特定事件发生时进行处理。

  8. 资源分配:注册Framebuffer设备时,可能还会涉及到对其他硬件资源的请求和管理,如中断号、DMA通道等。

  9. 启动显示:注册Framebuffer设备后,系统可以启动显示过程,如有必要,还可以设置显示模式或分辨率。

  10. 错误处理:如果在注册过程中出现问题,内核将记录错误信息,并且Framebuffer设备将不会对用户空间程序可用。

注册Framebuffer设备是显示系统正常工作的必要条件,它确保了硬件设备与软件接口的正确连接和协调。在Framebuffer驱动程序的生命周期中,通常在模块加载时进行注册,在模块卸载时进行反注册。

映射LCD控制寄存器到内核空间,设置LCD控制器相关参数

出口函数则是反注册和释放内存,以及解除LCD控制器的内核空间映射。

4. 结合APP分析LCD驱动程序

4.1 open

这段代码是Linux内核中的一个片段,描述了打开一个帧缓冲设备(framebuffer device)的过程。帧缓冲设备是用于图形显示的设备,比如连接到计算机的显示器或LCD屏幕。下面是对这段代码的逐行解释:

  1. app: open("/dev/fb0", ...):这是应用程序调用open系统调用的示例,尝试打开设备文件/dev/fb0/dev/fb0是帧缓冲设备的一个常见设备文件,...表示还有其他参数传递给open函数。

  2. 主设备号: 29, 次设备号: 0:这些是设备号,用于唯一标识系统中的设备。主设备号用于标识设备驱动程序,次设备号用于标识特定的设备实例。

  3. fb_open:这是内核中处理打开帧缓冲设备的函数。

  4. struct fb_info *info;:声明一个指向fb_info结构的指针,fb_info是内核中用于存储帧缓冲设备信息的结构体。

  5. info = get_fb_info(fbidx);:调用get_fb_info函数获取帧缓冲设备的相关信息。fbidx是帧缓冲设备的索引号,通常由设备文件名(如/dev/fb0中的0)决定。

  6. if (info->fbops->fb_open) {:检查fb_info结构中的fbops成员是否有定义fb_open方法。fbopsfb_info中的一个结构,包含了帧缓冲设备操作的函数指针。

  7. res = info->fbops->fb_open(info,1);:如果fb_open方法存在,则调用它来执行实际的打开操作。传递给fb_open的参数info是帧缓冲设备的相关信息,1通常表示以非阻塞方式打开设备。

  8. if (res):检查fb_open调用的返回值。如果返回值非零,表示打开操作失败。

  9. module_put(info->fbops->owner);:如果打开失败,调用module_put来减少模块的引用计数。info->fbops->owner是指向模块所有者的指针,这通常是一个指向模块结构的指针。

这段代码是内核中处理设备文件打开请求的一部分,涉及到设备驱动程序的加载和初始化。当应用程序尝试打开一个设备文件时,内核会找到相应的设备驱动程序并调用它的fb_open函数来完成打开操作。如果打开成功,应用程序就可以与设备进行通信;如果失败,则会释放与设备驱动程序相关的资源。

4.2 获得可变信息(含有分辨率等)

这段代码描述了在Linux内核中,应用程序通过ioctl系统调用来获取帧缓冲设备(framebuffer device)的虚拟屏幕信息(virtual screen information)的过程。下面是对这段代码的逐行解释:

  1. app: ioctl(fd, FBIOGET_VSCREENINFO, &fb_info->var);:这是在应用程序中调用ioctl函数的示例。fd是文件描述符,它是之前通过open系统调用获得的。FBIOGET_VSCREENINFOioctl命令,用于获取帧缓冲的虚拟屏幕信息。&fb_info->var是指向一个结构体的地址,该结构体用于接收获取到的屏幕信息。

  2. fb_ioctl:这是内核中处理帧缓冲设备ioctl请求的函数。

  3. struct fb_info *info = file_fb_info(file);:这行代码获取与文件描述符关联的帧缓冲信息结构体。file是指向文件对象的指针,它通过文件描述符fd获得。

  4. do_fb_ioctl(info, cmd, arg);:这行代码调用一个函数来执行实际的ioctl操作。info是帧缓冲信息结构体的指针,cmdioctl命令,arg是指向用户提供的参数的指针。

  5. var = info->var;:这行代码将帧缓冲信息结构体中的var成员(包含虚拟屏幕信息)赋值给局部变量var。这个成员是由硬件相关的驱动程序设置的。

  6. ret = copy_to_user(argp, &var, sizeof(var)) ? -EFAULT : 0;:这行代码尝试将var结构体的内容复制到用户空间的内存地址argpcopy_to_user函数用于在内核空间和用户空间之间复制数据。如果复制失败(即返回非零值),则ret被设置为-EFAULT,表示发生了访问错误;如果复制成功,则ret被设置为0

整个流程是:应用程序通过ioctl请求获取帧缓冲设备的屏幕信息,内核接收到请求后,找到对应的帧缓冲信息结构体,并将其中的屏幕信息复制到用户提供的内存地址。如果复制成功,内核会返回0,表示操作成功;如果复制失败,内核会返回错误码-EFAULT

4.3 获得固定信息(含有显存信息)

这段代码描述了应用程序使用ioctl系统调用来获取帧缓冲设备(framebuffer device)的固定屏幕信息(fixed screen information)的过程。下面是对这段代码的逐行解释:

  1. app: ioctl(fd, FBIOGET_FSCREENINFO, &fb_info->fix);:这是在应用程序中调用ioctl函数的示例。fd是文件描述符,它是之前通过open系统调用获得的。FBIOGET_FSCREENINFOioctl命令,用于获取帧缓冲的固定屏幕信息。&fb_info->fix是指向一个结构体的地址,该结构体用于接收获取到的屏幕信息。

  2. fb_ioctl:这是内核中处理帧缓冲设备ioctl请求的函数。

  3. struct fb_info *info = file_fb_info(file);:这行代码获取与文件描述符关联的帧缓冲信息结构体。file是指向文件对象的指针,它通过文件描述符fd获得。

  4. do_fb_ioctl(info, cmd, arg);:这行代码调用一个函数来执行实际的ioctl操作。info是帧缓冲信息结构体的指针,cmdioctl命令,arg是指向用户提供的参数的指针。

  5. fix = info->fix;:这行代码将帧缓冲信息结构体中的fix成员(包含固定屏幕信息)赋值给局部变量fix。这个成员是由硬件相关的驱动程序设置的,通常包含屏幕的物理特性,如屏幕的宽度、高度、内存布局等。

  6. ret = copy_to_user(argp, &fix, sizeof(fix)) ? -EFAULT : 0;:这行代码尝试将fix结构体的内容复制到用户空间的内存地址argpcopy_to_user函数用于在内核空间和用户空间之间复制数据。如果复制失败(即返回非零值),则ret被设置为-EFAULT,表示发生了访问错误;如果复制成功,则ret被设置为0

整个流程是:应用程序通过ioctl请求获取帧缓冲设备的固定屏幕信息,内核接收到请求后,找到对应的帧缓冲信息结构体,并将其中的固定屏幕信息复制到用户提供的内存地址。如果复制成功,内核会返回0,表示操作成功;如果复制失败,内核会返回错误码-EFAULT

固定屏幕信息(fix)通常包括:

  • id:帧缓冲设备的标识符。
  • smem_start:帧缓冲内存的起始物理地址。
  • smem_len:帧缓冲内存的长度。
  • type:帧缓冲的类型。
  • type_aux:辅助类型信息。
  • visual:颜色空间的视觉表示。
  • xpanstepypanstep:水平和垂直的扫描步长。
  • ywrapstep:行的包装步长。
  • line_length:每行的字节长度。

4.4  mmap

这段代码展示了在应用程序和Linux内核中使用mmap系统调用来映射帧缓冲设备的内存到用户空间的过程。下面是对这段代码的逐行解释:

应用程序代码解释:

  1. void *ptr = mmap(0, ...);:这是应用程序中调用mmap函数的示例,用于创建一个内存映射。

  2. fb_info->var.yres_virtual * fb_info->fix.line_length:这是映射的大小,计算方法为帧缓冲的虚拟垂直分辨率(yres_virtual)乘以每行的字节长度(fix.line_length)。yres_virtual通常大于实际屏幕的垂直分辨率(yres),以支持额外的显示功能,如双缓冲或额外的帧缓冲。

  3. PROT_WRITE | PROT_READ:这些标志指定映射的内存区域应该是可读写的。

  4. MAP_SHARED:这个标志表示映射应该是共享的,即对映射区域的修改对其他映射同一文件的进程可见。

  5. fd:这是之前通过open系统调用获得的帧缓冲设备的文件描述符。

  6. 0:这是文件中映射开始的偏移量,通常设置为0以从文件的开始处映射。

内核代码解释:

  1. fb_mmap:这是内核中处理帧缓冲设备mmap请求的函数。

  2. struct fb_info *info = file_fb_info(file);:这行代码获取与文件描述符关联的帧缓冲信息结构体。

  3. start = info->fix.smem_start;:这行代码获取帧缓冲的起始物理地址,从fix结构体中的smem_start成员获得。

  4. len = info->fix.smem_len;:这行代码获取帧缓冲的内存长度,从fix结构体中的smem_len成员获得。

  5. return vm_iomap_memory(vma, start, len);:这行代码调用vm_iomap_memory函数来实际创建内存映射。vma是虚拟内存区域的结构体,start是物理地址的起始位置,len是要映射的内存长度。这个函数处理物理内存到虚拟内存的映射,并返回指向映射区域的指针。

整个流程是:应用程序请求映射帧缓冲设备的内存到用户空间,内核接收到请求后,找到对应的帧缓冲信息结构体,并使用vm_iomap_memory函数来创建内存映射。这样,应用程序就可以直接读写帧缓冲的内存,而不需要通过readwrite系统调用来进行。这种直接访问方式通常用于性能敏感的图形显示操作。

标签:info,缓冲,fb,LCD,详解,内核,Framebuffer,QEMU,设备
From: https://blog.csdn.net/xace007/article/details/140486817

相关文章

  • FastJson详解
    文章目录一、FastJson介绍二、FastJson序列化API1、序列化Java对象2、序列化List集合3、序列化Map集合三、FashJson反序列化API1、反序列化Java对象2、反序列化List集合3、反序列化Map集合(带泛型)四、SerializerFeature枚举1、默认字段为null的不显示2、格式化五、@JSo......
  • 光电显示技术-LCD篇
    LCD显示技术本文对应资料:1.视频资料,2.PPT资料1.技术简介TFT-LCD是每一个子像素均由单独的薄膜晶体管(TFT)驱动实现显示,该方法在非晶硅显示面板上大规模的被使用,使得TFT-LCD成为目前主流的显示器件,下图是TFT的显示结构。图1TFT-LCD显示结构该结构主要由前面的面板,后方主要由......
  • 以电商、消费行业为例,详解火山引擎数智平台如何应用湖仓一体架构
    更多技术交流、求职机会,欢迎关注字节跳动数据平台微信公众号,回复【1】进入官方交流群。 随着互联网的不断发展,企业数据的使用场景也发生巨大变化,湖仓一体逐渐成为一种被广泛应用的底层数据架构。 详细来说,湖仓一体架构是一种将数据湖和数据仓库的优势结合起来的新型数据架......
  • SIP消息结构详解
    SIP协议的消息由三部分构成,分别是起始行(请求行+状态行)、消息头和消息体(正文)一.起始行1.请求消息起始行 起始行:由方法名、请求URI和协议版本组成,自身内部用逗号分割,三者之间用空格分隔。例如:INVITE sip:[email protected];user=phone SIP/2.0方法名:SIP协议定义了一系列......
  • linux下使用fdisk进行磁盘分区详解
     转载:https://www.cnblogs.com/renshengdezheli/p/13941563.html目录一.前言二.关于磁盘分区的结构三.fdisk命令详解四.使用fdisk进行磁盘分区4.1磁盘分区规划4.2fdisk进行磁盘分区4.3格式化分区4.4创建挂载点/挂载目录4.5挂载分区4.6设置开机自动挂载分区......
  • 【数据结构与算法】选择排序篇----详解直接插入排序和哈希排序【图文讲解】
     欢迎来到CILMY23的博客......
  • icacls 命令使用详解
    icacls(InteractiveCommand-LineAccessControlLists)是Windows系统中用于查看和修改文件、目录权限的命令行工具。它允许管理员或具有适当权限的用户对文件和目录的访问控制列表(ACL)进行细粒度控制。以下是icacls命令的详细使用说明及操作实例。一、icacls命令的基本语法icacls......
  • Java中的响应式编程与Reactor框架使用详解
    Java中的响应式编程与Reactor框架使用详解大家好,我是微赚淘客系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿!一、引言响应式编程是一种面向数据流和变化传播的编程范式,它适用于处理异步数据流和事件驱动的场景。Reactor框架是在Java中实现响应式编程的强大工具,本文将深入......
  • 从基础到高级应用,详解用Python实现容器化和微服务架构
    本文分享自华为云社区《Python微服务与容器化实践详解【从基础到高级应用】》,作者:柠檬味拥抱。Python中的容器化和微服务架构实践在现代软件开发中,容器化和微服务架构已经成为主流。容器化技术使得应用程序可以在任何环境中一致运行,而微服务架构通过将应用拆分成多个独立的服务......
  • 71、Flink 的 Hybrid Source 详解
    HybridSource1.概述HybridSource解决了从异构数据源顺序读取输入以生成单个输入流的问题。示例:从S3读取前几天的有界输入,然后使用Kafka的最新无界输入,当有界文件输入完成而不中断应用程序时HybridSource会从FileSource切换到KafkaSource。在HybridSource......