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 中的帧缓冲区域。
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)
1.4 帧缓冲与显示控制器的交互流程
显示控制器按固定帧率(如 60 fps)工作,每个帧周期内执行以下步骤:
- VSync 同步:控制器发出垂直同步信号,开始新一帧的扫描。
- DMA 读取:控制器通过 DMA 从帧缓冲起始地址逐行读取像素数据。
- 行扫描:每读取一行,控制器将其转换为 RGB 信号发送给面板,同时发出 HSync 水平同步信号。
- 消隐区:行与行之间、帧与帧之间插入消隐时间(Blanking),用于面板像素充电和稳定。
- 帧完成:所有行扫描完毕,控制器等待下一个 VSync 信号,循环重复。
关键参数:帧缓冲驱动必须正确配置显示控制器的时序参数——前肩(Front Porch)、后肩(Back Porch)、同步脉宽(Sync Pulse Width)、行宽(Hactive)和帧高(Vactive),否则画面偏移或闪烁。
1.5 帧缓冲在嵌入式系统中的位置
在典型的嵌入式 Linux 启动流程中,帧缓冲的初始化顺序如下:
- U-Boot 阶段:初始化显示控制器、配置时序、在 DDR 中分配帧缓冲、显示启动 Logo。
- 内核阶段:fbdev 驱动接管显示控制器,重新初始化或继承 U-Boot 的帧缓冲地址,注册
/dev/fb0。 - 应用阶段:GUI 框架打开
/dev/fb0,通过mmap映射帧缓冲,开始绘制用户界面。
移植要点:U-Boot 与内核之间传递帧缓冲信息通常通过设备树(Device Tree)中的
framebuffer 节点或 U-Boot 的 video 环境变量实现。若两者地址不一致,内核启动后会出现短暂黑屏或花屏。