1. 帧缓冲基础概念

1.1 什么是帧缓冲(Framebuffer)

帧缓冲(Framebuffer)是显示子系统在系统内存或专用显存中开辟的一块连续区域,用于存储一帧完整的像素数据。CPU 或 GPU 将渲染好的像素写入该区域后,显示控制器按固定时序逐行扫描读取这些数据,并转换为模拟或数字信号驱动显示器。

核心定义:帧缓冲是软件与显示硬件之间的数据桥梁——软件只需操作内存中的像素矩阵,无需关心底层时序与信号协议。

在嵌入式 Linux 中,/dev/fb0 是帧缓冲设备节点,用户空间通过 mmap() 映射该设备到进程地址空间,即可直接读写像素。

1.2 显示子系统架构

嵌入式显示子系统从软件到硬件通常分为四层,每层职责明确:

层级 组件 职责
应用层 GUI 框架(Qt、LVGL、Flutter) 绘制窗口、控件、合成图层
内核层 fbdev 驱动 / DRM 驱动 管理帧缓冲内存、配置显示控制器、处理 ioctl
硬件抽象层 显示控制器(Display Controller) 从帧缓冲读取数据、生成时序信号
物理层 LCD / HDMI / MIPI-DSI 面板 将电信号转换为可见光像素
嵌入式特点:与 PC 不同,嵌入式系统常将帧缓冲放在系统 DDR 中而非独立显存,显示控制器通过 DMA 直接访问 DDR 中的帧缓冲区域。
嵌入式显示子系统架构 应用层 Qt / LVGL / Flutter · 窗口合成 · 图形渲染 内核层 fbdev 驱动 / DRM · 帧缓冲内存管理 · ioctl 接口 硬件抽象层 显示控制器 · 时序发生器 · DMA 读取帧缓冲 物理层 LCD 面板 / HDMI 接口 / MIPI-DSI · 像素发光

1.3 像素与颜色深度

像素(Pixel)是显示的最小单位,每个像素由若干颜色通道组合而成。颜色深度(Color Depth)表示每个像素用多少比特来存储颜色信息,直接决定了可显示的色彩数量。

常见颜色深度格式

颜色深度 每像素位数 (bpp) 通道布局 色彩数 典型应用
RGB565 16 R:5 + G:6 + B:5 65,536 低成本嵌入式 LCD、低端 MCU
RGB888 24 R:8 + G:8 + B:8 16,777,216 主流嵌入式 Linux、高清显示
ARGB8888 32 A:8 + R:8 + G:8 + B:8 16,777,216 + 256 级透明度 GUI 合成、窗口透明效果
L8(灰度) 8 单通道亮度 256 墨水屏、单色 OLED
移植陷阱:U-Boot 与内核的帧缓冲颜色深度必须一致。若 U-Boot 配置 RGB565 而内核驱动设为 RGB888,会导致显示颜色完全错乱。移植前务必确认硬件面板支持的格式。

像素在内存中的排列

帧缓冲本质是一个二维数组,按行优先顺序存储。以 800×480 分辨率、RGB888 格式为例:

/* 帧缓冲大小计算 */
分辨率: 800 × 480 = 384,000 像素
每像素字节: 24 bpp ÷ 8 = 3 字节
帧缓冲总大小: 384,000 × 3 = 1,152,000 字节 ≈ 1.1 MB

/* 像素偏移计算:坐标 (x, y) 对应的内存地址 */
offset = (y × 行宽) + (x × 每像素字节)
       = (y × 800 × 3) + (x × 3)
帧缓冲像素排列与颜色深度 帧缓冲内存(连续区域) 行 0 · 行 1 · 行 2 · … · 行 479 一行 800 个像素:P0 P1 P2 … P799 RGB888 像素 (3 字节) R:8bit | G:8bit | B:8bit RGB565 像素 (2 字节) R:5bit | G:6bit | B:5bit ARGB8888 像素 (4 字节) A:8bit | R:8bit | G:8bit | B:8bit 颜色深度选择原则 高深度(32bpp)色彩丰富但占用带宽大;低深度(16bpp)节省内存但有色阶条纹

1.4 帧缓冲与显示控制器的交互流程

显示控制器按固定帧率(如 60 fps)工作,每个帧周期内执行以下步骤:

  1. VSync 同步:控制器发出垂直同步信号,开始新一帧的扫描。
  2. DMA 读取:控制器通过 DMA 从帧缓冲起始地址逐行读取像素数据。
  3. 行扫描:每读取一行,控制器将其转换为 RGB 信号发送给面板,同时发出 HSync 水平同步信号。
  4. 消隐区:行与行之间、帧与帧之间插入消隐时间(Blanking),用于面板像素充电和稳定。
  5. 帧完成:所有行扫描完毕,控制器等待下一个 VSync 信号,循环重复。
关键参数:帧缓冲驱动必须正确配置显示控制器的时序参数——前肩(Front Porch)、后肩(Back Porch)、同步脉宽(Sync Pulse Width)、行宽(Hactive)和帧高(Vactive),否则画面偏移或闪烁。
显示控制器读取帧缓冲流程 帧缓冲 DDR 内存 DMA 读取 逐行搬运 显示控制器 时序生成 LCD 面板 显示时序关键参数 • Hactive(行有效像素):800 • Vactive(帧有效行数):480 • HFP(行前肩):40 • VFP(帧前肩):10 • HBP(行后肩):88 • VBP(帧后肩):23 • HSync(行同步脉宽):48 • VSync(帧同步脉宽):3

1.5 帧缓冲在嵌入式系统中的位置

在典型的嵌入式 Linux 启动流程中,帧缓冲的初始化顺序如下:

  1. U-Boot 阶段:初始化显示控制器、配置时序、在 DDR 中分配帧缓冲、显示启动 Logo。
  2. 内核阶段:fbdev 驱动接管显示控制器,重新初始化或继承 U-Boot 的帧缓冲地址,注册 /dev/fb0。
  3. 应用阶段:GUI 框架打开 /dev/fb0,通过 mmap 映射帧缓冲,开始绘制用户界面。
移植要点:U-Boot 与内核之间传递帧缓冲信息通常通过设备树(Device Tree)中的 framebuffer 节点或 U-Boot 的 video 环境变量实现。若两者地址不一致,内核启动后会出现短暂黑屏或花屏。