search
暂无数据
Framebuffer 驱动更新时间:2025-09-23 10:54:08

一、什么是 Framebuffer

Framebuffer(帧缓存/显存)是一个用于存储一帧 LCD 图像数据的内存区域。在嵌入式系统中,Framebuffer 通常通过内存模拟实现,其大小由 LCD 的分辨率和每个像素的字节大小决定。

1、Framebuffer 的大小计算

以 480x320 的屏幕为例,在不同像素模式下,Framebuffer 的大小如下:

  1. ARGB888 (32bpp):

    • 计算公式:480 x 320 x 4 (bytes)
    • 大小:614,400 字节
  2. RGB565 (16bpp):

    • 计算公式:480 x 320 x 2 (bytes)
    • 大小:307,200 字节

二、Framebuffer的显示原理

Framebuffer 的显示原理可以概括为:LCD 控制器(LCDC)从 Framebuffer 中读取像素数据,并通过并行数据接口将数据传输到 LCD 面板进行显示。

1、显示流程图

以下是 Framebuffer 的显示流程:

img

  • Framebuffer:存储像素数据。
  • LCDC:从 Framebuffer 中读取像素数据,并将其传输到 LCD 面板。
  • LCD Panel:接收数据并显示图像。

2、数据传输接口

LCDC 通过以下信号将数据传输到 LCD 面板:

  • Clock:时钟信号,用于同步数据传输。
  • Data:像素数据,包括 R(红)、G(绿)、B(蓝)三种颜色通道。
  • Control:控制信号,用于管理数据传输的时序和状态。

三、openvela Framebuffer 接口

openvela 的 Framebuffer 接口分为上层用户接口和下层驱动接口,分别为用户和设备驱动程序提供了灵活的操作能力。以下是接口的详细说明。

1、上层用户接口

openvela 的 Framebuffer 用户接口类似于 Linux 系统,通过 VFS(虚拟文件系统)提供标准操作接口,包括 openclosereadwriteioctl 等。用户可以通过操作 /dev/fbx 设备文件,完成以下功能:

  1. 映射 Framebuffer 到用户态:

    使用 mmap 将 Framebuffer 映射到用户空间,便于直接对 Framebuffer 进行读写操作。

  2. 切换 Framebuffer:

    用户可以通过 ioctl 接口切换不同的 Framebuffer 配置或模式。

2、下层驱动接口

openvela 的 Framebuffer 驱动接口用于管理 LCD 设备,设计相对简单。开发者可以参考 video/fb.h/drivers/video/fb.c 文件中的实现。以下是 fb_register() 函数的源码,展示了与 Framebuffer 设备驱动相关的重要部分:

int fb_register(int display, int plane)
{
  FAR struct fb_chardev_s *fb;

  ...

  /* Initialize the frame buffer device. */
  ret = up_fbinitialize(display);
  if (ret < 0)
    {
      gerr("ERROR: up_fbinitialize() failed for display %d: %d\n",
           display, ret);
      goto errout_with_fb;
    }
  DEBUGASSERT((unsigned)plane <= UINT8_MAX);
  fb->plane  = plane;
  fb->vtable = up_fbgetvplane(display, plane);
  if (fb->vtable == NULL)
    {
      gerr("ERROR: up_fbgetvplane() failed, vplane=%d\n", plane);
      goto errout_with_fb;
    }
  /* Initialize the frame buffer instance. */
  ...

  ret = register_driver(devname, &fb_fops, 0666, (FAR void *)fb);
  if (ret < 0)
    {
      gerr("ERROR: register_driver() failed: %d\n", ret);
      goto errout_with_fb;
    }
  return OK;
  
errout_with_fb:
  kmm_free(fb);
  return ret;
}

从代码中可以看出,Framebuffer 针对 LCD 设备驱动程序提供了以下 3 个接口,驱动程序需要自行实现:

  1. void up_fbinitialize(int display)

    • 用于初始化硬件 LCD 控制器。
    • 例如,在 STM32 平台上,up_fbinitialize 函数需要初始化 LTDC(LCD-TFT 控制器)或 MIPI 接口,并完成 DSI 外设和 LCD IC 的初始化。
  2. FAR struct fb_vtable_s *up_fbgetvplane(int display, int vplane)

    • 获取 LCD 的 fb_vtable_s 结构体信息。
    • fb_vtable_s 是 Framebuffer 的核心结构,包含了 Framebuffer 的所有接口。通过实现该函数,LCD 控制器可以将自身信息注册到 Framebuffer 框架中。
    • 驱动程序可以参考以下示例实现:

      • drivers/video/vnc/vnc_fbdev.c
      • boards/arm/stm32f7/stm32f746g-disco/stm32_lcd.c
  3. void up_fbuninitialize(int display)

    • 执行与 up_fbinitialize 相反的操作,用于释放资源。通常可以实现为空,不执行任何操作。

3、struct fb_vtable_s 结构

fb_vtable_s 是 Framebuffer 的核心结构,定义了与视频硬件交互的接口。以下是其主要功能模块:

  1. 核心功能。

    • getvideoinfo:获取视频控制器配置和颜色平面信息。
    • getplaneinfo:获取指定颜色平面的信息。
  2. 可选功能(根据配置启用)。

    • 颜色映射(CONFIG_FB_CMAP):
      • getcmap:获取当前颜色映射表。
      • putcmap:更新颜色映射表。
    • 硬件光标(CONFIG_FB_HWCURSOR):
      • getcursor:获取光标属性。
      • setcursor:设置光标配置。
    • 显示更新(CONFIG_FB_UPDATE):
      • updatearea:通知硬件更新指定显示区域。
    • 垂直同步(CONFIG_FB_SYNC):
      • waitforvsync:等待垂直同步信号,避免屏幕撕裂。
    • 叠加管理(CONFIG_FB_OVERLAY):
      • getoverlayinfo:获取叠加层的配置信息。
      • settransp:设置叠加层的透明度。
      • setchromakey:设置叠加层的色键。
      • setcolor:用指定颜色填充叠加层。
      • setblank:启用或禁用叠加层。
      • setarea:设置叠加操作的活动区域。
      • 叠加层的 Blit 和 Blend 操作(CONFIG_FB_OVERLAY_BLIT):
        • blit:在叠加层之间执行 Blit 操作。
        • blend:在叠加层之间执行 Blend 操作。
  3. 其他控制功能。

    • 显示平移:
      • pandisplay:为多缓冲区显示执行平移操作。
    • 帧率控制:
      • setframerate:设置 Framebuffer 的刷新率。
      • getframerate:获取当前刷新率。
    • 电源管理:
      • getpower:获取面板的电源状态。
      • setpower:启用或禁用面板电源。

示例代码

以下是 struct fb_vtable_s 的部分定义示例:

struct fb_vtable_s
{
  /* Get information about the video controller configuration and the
   * configuration of each color plane.
   */

  int (*getvideoinfo)(FAR struct fb_vtable_s *vtable,
                      FAR struct fb_videoinfo_s *vinfo);
  int (*getplaneinfo)(FAR struct fb_vtable_s *vtable, int planeno,
                      FAR struct fb_planeinfo_s *pinfo);

#ifdef CONFIG_FB_CMAP
  /* The following are provided only if the video hardware supports RGB
   * color mapping
   */

  int (*getcmap)(FAR struct fb_vtable_s *vtable,
                 FAR struct fb_cmap_s *cmap);
  int (*putcmap)(FAR struct fb_vtable_s *vtable,
                 FAR const struct fb_cmap_s *cmap);
#endif

#ifdef CONFIG_FB_HWCURSOR
  /* The following are provided only if the video hardware supports a
   * hardware cursor.
   */

  int (*getcursor)(FAR struct fb_vtable_s *vtable,
                   FAR struct fb_cursorattrib_s *attrib);
  int (*setcursor)(FAR struct fb_vtable_s *vtable,
                   FAR struct fb_setcursor_s *settings);
#endif

#ifdef CONFIG_FB_UPDATE
  /* The following are provided only if the video hardware need extera
   * notification to update display content.
   */

  int (*updatearea)(FAR struct fb_vtable_s *vtable,
                    FAR const struct fb_area_s *area);
#endif

#ifdef CONFIG_FB_SYNC
  /* The following are provided only if the video hardware signals
   * vertical sync.
   */

  int (*waitforvsync)(FAR struct fb_vtable_s *vtable);
#endif

#ifdef CONFIG_FB_OVERLAY
  /* Get information about the video controller configuration and the
   * configuration of each overlay.
   */

  int (*getoverlayinfo)(FAR struct fb_vtable_s *vtable, int overlayno,
                        FAR struct fb_overlayinfo_s *oinfo);

  /* The following are provided only if the video hardware supports
   * transparency
   */

  int (*settransp)(FAR struct fb_vtable_s *vtable,
                   FAR const struct fb_overlayinfo_s *oinfo);

  /* The following are provided only if the video hardware supports
   * chromakey
   */

  int (*setchromakey)(FAR struct fb_vtable_s *vtable,
                      FAR const struct fb_overlayinfo_s *oinfo);

  /* The following are provided only if the video hardware supports
   * filling the overlay with a color.
   */

  int (*setcolor)(FAR struct fb_vtable_s *vtable,
                  FAR const struct fb_overlayinfo_s *oinfo);

  /* The following allows to switch the overlay on or off */

  int (*setblank)(FAR struct fb_vtable_s *vtable,
                  FAR const struct fb_overlayinfo_s *oinfo);

  /* The following allows to set the active area for subsequently overlay
   * operations.
   */

  int (*setarea)(FAR struct fb_vtable_s *vtable,
                 FAR const struct fb_overlayinfo_s *oinfo);

# ifdef CONFIG_FB_OVERLAY_BLIT
  /* The following are provided only if the video hardware supports
   * blit operation between overlays.
   */

  int (*blit)(FAR struct fb_vtable_s *vtable,
              FAR const struct fb_overlayblit_s *blit);

  /* The following are provided only if the video hardware supports
   * blend operation between overlays.
   */

  int (*blend)(FAR struct fb_vtable_s *vtable,
               FAR const struct fb_overlayblend_s *blend);
#endif

  /* Pan display for multiple buffers. */

  int (*pandisplay)(FAR struct fb_vtable_s *vtable,
                    FAR struct fb_planeinfo_s *pinfo);

  /* Specific Controls ******************************************************/

  /* Set the frequency of the Framebuffer update panel (0: disable refresh) */

  int (*setframerate)(FAR struct fb_vtable_s *vtable, int rate);

  /* Get the frequency of the Framebuffer update panel (0: disable refresh) */

  int (*getframerate)(FAR struct fb_vtable_s *vtable);

  /* Get the panel power status (0: full off). */

  int (*getpower)(FAR struct fb_vtable_s *vtable);

  /* Enable/disable panel power (0: full off). */

  int (*setpower)(FAR struct fb_vtable_s *vtable, int power);
};

开发者可以根据具体硬件需求实现这些接口,以满足 Framebuffer 的功能需求。

四、启用 Framebuffer

启用 Framebuffer 需要完成以下步骤:

1、开启 Framebuffer 编译选项

在配置文件中启用以下选项:

CONFIG_VIDEO_FB

2、注册 Framebuffer

在系统启动的初始化阶段,调用 fb_register 函数注册 Framebuffer。以下是示例代码:

#include <nuttx/video/fb.h>  

#ifdef CONFIG_VIDEO_FB  
    ret = fb_register(0, 0);  
    if (ret < 0)  
    {  
        syslog(LOG_ERR, "ERROR fb_register() failed: %d\n", ret);  
    }  
#endif

3、处理 VSync

为了避免屏幕撕裂并提高渲染性能,建议在实现中处理 VSync(垂直同步)。VSync 的具体实现和优化方法,请参考 VSync

五、相关仓

以下是与 Framebuffer 驱动相关的代码仓库链接:

  • fb.c:Framebuffer 驱动的实现文件。
  • fb.h:Framebuffer 驱动的接口定义。
文档内容是否有帮助?
有帮助
无帮助