DMA2D 寄存器详解:从 CR 到 BGOR

DMA2D 说白了就是一个专门干图像搬运和处理的硬件加速器。你想想看,如果每次刷图都要 CPU 一个个像素去搬,那画面卡顿是必然的。我刚开始接触 ST 的 DMA2D 时,也觉得寄存器好多,看着头大。但实际用起来,核心就那么几个。

今天咱们就把 DMA2D 的五个关键寄存器掰开揉碎。分别是:控制寄存器(CR)、帧缓冲寄存器(FB)、像素格式寄存器(PFCR)、前景层寄存器(FGOR)、背景层寄存器(BGOR)。

核心观点:DMA2D 的寄存器配置,决定了图像数据怎么搬、搬到哪里、用什么格式搬。配错了,画面花屏;配对了,丝滑流畅。

2.1 控制寄存器(CR)—— DMA2D 的开关与模式选择

CR 寄存器,全称 Control Register。它是 DMA2D 的总开关,也是模式选择器。我习惯把它比作汽车的档位——你挂什么档,车就怎么跑。

CR 寄存器里最重要的几个位域:

  • START 位(bit 0):启动传输。写 1 开始,硬件自动清 0 表示完成。
  • MODE 位(bits 17:16):选择工作模式。00 是寄存器到存储器(纯填充),01 是存储器到存储器(纯拷贝),10 是存储器到存储器带 PFC(像素格式转换),11 是带混合的存储器到存储器。
  • TCF 位(bit 1):传输完成标志。中断里判断这个位,就知道活干完了。

我在项目中遇到过一个问题:启动 DMA2D 后,CPU 直接去读目标内存,结果读到的是旧数据。为什么?因为 DMA2D 还没干完活。后来我学乖了,启动后要么等中断,要么轮询 TCF 位。

个人习惯:我一般用中断方式处理 DMA2D 完成事件。轮询虽然简单,但在刷屏场景下会阻塞 CPU,浪费性能。

2.2 帧缓冲寄存器(FB)—— 目标地址在哪?

FB 寄存器,全称 Frame Buffer Register。它存的是 DMA2D 输出数据的目标地址。说白了,就是告诉硬件:「处理完的图,放到这个内存地址去。」

对于 LVGL 来说,这个地址通常就是显示器的帧缓冲起始地址。比如你用的是 LTDC,那 FB 就指向 LTDC 的帧缓冲区。

配置时要注意:

  • 地址必须 4 字节对齐。我见过有人传了个奇数地址,结果 DMA2D 直接罢工。
  • 如果开启了双缓冲,FB 地址要在两个缓冲区间切换。
  • 地址是物理地址,不是虚拟地址。在带 MMU 的系统里要特别注意。
避坑指南:我曾经在 FreeRTOS 下用 DMA2D,传了个堆上动态分配的内存地址。结果那个地址是虚拟地址,DMA2D 根本访问不到。后来改用内存池固定分配物理连续内存,问题解决。

2.3 像素格式寄存器(PFCR)—— 颜色深度怎么配?

PFCR 寄存器,全称 Pixel Format Control Register。它决定了 DMA2D 怎么解释每个像素的字节。

这个寄存器里最重要的就是 PFC 控制位,它定义了输入和输出的像素格式。常见的格式有:

格式值 像素格式 说明
000 ARGB8888 32位,A8R8G8B8
001 RGB888 24位,R8G8B8
010 RGB565 16位,R5G6B5
011 ARGB1555 16位,A1R5G5B5
100 ARGB4444 16位,A4R4G4B4
110 AL88 16位,L8A8(亮度+Alpha)
111 L8 8位,单色亮度

你想想看,如果源图是 RGB565,但显示器的帧缓冲是 ARGB8888,那 DMA2D 就得做格式转换。PFCR 就是干这个的。

我个人的建议是:LVGL 的显示缓冲尽量和 DMA2D 输出格式一致,这样可以省掉格式转换的开销。比如你的屏幕是 RGB565,那 LVGL 的 buffer 也用 RGB565,DMA2D 直接拷贝就行,不用转。

2.4 前景层寄存器(FGOR)—— 图像混合的前景配置

FGOR 寄存器,全称 Foreground Offset Register。它用在 DMA2D 的混合模式下,控制前景图像的起始偏移。

什么叫混合模式?就是两张图叠在一起,比如背景是桌面,前景是一个窗口,DMA2D 可以帮你把这两张图按 Alpha 值混合成一张图。

FGOR 里主要配两个东西:

  • 偏移量(bits 15:0):前景图像在源内存中的行起始偏移,单位是字节。
  • 颜色模式:前景图像的像素格式,这个在 PFCR 里已经配了,但 FGOR 会关联到前景的 Alpha 处理。

我记得有一次做相册应用,需要把一张 PNG 图标叠加到背景图上。当时 FGOR 配错了偏移,结果图标显示位置偏了半个屏幕。查了半天才发现是行偏移没算对。

计算技巧:FGOR 的偏移值 = 图像宽度(像素)× 每像素字节数。比如 800 像素宽的 RGB565 图,偏移就是 800 × 2 = 1600 字节。

2.5 背景层寄存器(BGOR)—— 混合的另一半

BGOR 寄存器,全称 Background Offset Register。它和 FGOR 是对称的,控制背景图像的起始偏移。

在混合模式下,DMA2D 会同时读取前景和背景两路数据,然后按 Alpha 值混合输出到帧缓冲。BGOR 就是告诉硬件:「背景图从这里开始读。」

BGOR 的配置和 FGOR 完全一样:

  • 偏移量(bits 15:0):背景图像的行起始偏移。
  • 颜色模式:背景图像的像素格式。

这里有个容易踩的坑:前景和背景的像素格式可以不同。比如前景是带 Alpha 的 ARGB8888,背景是不透明的 RGB565。DMA2D 会自动处理格式差异,但前提是 PFCR 里配对了两种格式。

我曾经踩过的坑:做 GUI 动画时,背景图是 1024×600 的 RGB565,前景是一个 100×100 的 ARGB8888 图标。我忘了配 BGOR 的行偏移,结果背景图显示出来是斜的。后来发现 BGOR 默认是 0,而背景图实际需要按 1024×2 字节每行来偏移。

2.6 知识结构总览

下面这张图把五个寄存器的关系和分工画清楚了。你可以把它当作配置 DMA2D 时的检查清单。

DMA2D 核心寄存器结构图 DMA2D 核心 CR 控制寄存器 FB 帧缓冲寄存器 PFCR 像素格式 FGOR 前景偏移 BGOR 背景偏移 配置顺序建议: 1. 先配 PFCR,确定像素格式 2. 再配 FB、FGOR、BGOR,确定地址和偏移 3. 最后写 CR 的 MODE 和 START,启动传输 4. 等待 TCF 标志或中断,确认传输完成

2.7 寄存器配置速查表

为了方便你实际编码时快速查阅,我把五个寄存器的关键配置项整理成了一张表:

寄存器 关键位域 作用 常见配置值
CR MODE[1:0], START 模式选择 + 启动 0x01(纯拷贝)或 0x03(混合)
FB FB[31:0] 输出目标地址 帧缓冲物理地址
PFCR PFC[2:0] 像素格式定义 0x02(RGB565)或 0x00(ARGB8888)
FGOR LO[15:0] 前景行偏移 宽度 × 每像素字节数
BGOR LO[15:0] 背景行偏移 宽度 × 每像素字节数