【LTDC】DMA2D —— 嵌入式系统的 GPU
引言
ST 公司设计了一个专门用于图像处理的 DMA:DMA2D,可以之际通过 DMA2D 搬运或填充图像,而不经过 CPU,极大减轻了 CPU 的负担。为了学习 DMA2D,我也专门写了这篇文章,现在就让我们来看看吧!
DMA2D
工作模式
DMA2D 拥有四种工作模式,分别是:
- 寄存器到存储器
- 存储器到存储器
- 存储器到存储器并执行 PFC
- 存储器到存储器并执行 PFC 混合
由于我现在只用到了前两个,所以就先只学习前两个。
寄存器到存储器
寄存器到存储器模式,用于以预定义颜色填充用户自定义区域,也就是可以实现快速的单色填充显示,例如清屏操作。
存储器到存储器
此模式下,DMA2D 不执行任何图形数据转换。前景层输入 FIFO 充当缓冲区,数据从 DMA2D 中定义的源存储单元传输到 DMA2D 寻址的目标存储单元,可以用于快速图像填充。
层缓冲开窗
显示层开窗: 窗口显示区域的显存的首地址由 DMA2D_OMAR 寄存器指定,窗口的宽度和高度由 DMA2D_NRL 寄存器的 PL 和NL 指定,行偏移由 DMA2D_OOR 寄存器指定,通过这三个寄存器的配置,就可以确定窗口的显示位置和大小。
前景层开窗: 和上面的显示层开窗类似,不过 DMA2D_OMAR 寄存器变为了 DMA2D_FGMAR 寄存器;DMA2D_OOR 寄存器变为了 DMA2D_FGOR 寄存器;DMA2D_NRL 寄存器两个层共用。配置好就可以完成对前景层的开窗。
寄存器到存储器模式: DMA2D 可以将 DMA2D_OCOLR 指定的颜色,自动填充到开窗区域,完成单色填充。
存储器到存储器模式: 需要完成前景层和显示层的开窗,完成配置后,图像数据从前景层拷贝到显示层(仅限窗口范围内),从而显示到 LCD 上面。

寄存器
由于 HAL 库的层层封装和各种安全检测,会使得 HAL 库的 DMA2D 的函数调用后速度会减慢,所谓唯快不破,所以 DMA2D 的寄存器操作是必不可少的。
DMA2D 控制寄存器 DMA2D_CR

- MODE[1:0]: 表示 DMA2D 的工作模式,00:存储器到存储器模式;01:存储器到存储器模式并执行PFC;10:存储器到存储器并执行混合;01:寄存器到存储器模式。
- START: 控制 DMA2D 的启动,1:启动;0:停止。
DMA2D 输出 PFC 控制寄存器 DMA2D_OPFCCR

CM[2:0]: 设置寄存器到存储器模式下的颜色格式,000:ARGB8888;001:RGB888;011:ARGB1555;100:ARGB1444。
前景层 PFC 控制寄存器 DMA2D_FGPFCRC

只需关心最低 4位。
CM[3:0]: 用于设置存储器到存储器模式下的颜色格式,0000:ARGB8888;0001:RGB888;0010: RGB565;0011:ARGB1555;0100:ARGB4444;0101:L8;0110:AL44;0111:AL88;1000:L4;1001:A8;1010:A4。
DMA2D 输出偏移寄存器 DMA2D_OOR

LO[13:0]: 设置输出行偏移,作用于显示层,以像素为单位表示。此值用于生成地址。行偏移将添加到各行末尾,用于确定下一行的起始地址。同样的,前景层的输出偏移寄存器为 DMA2D_FGOR,作用相同。
DMA2D 输出存储器地址寄存器 DMA2D_OMAR

MA[31:0]: 设置输出存储器地址,也就是 FIFO 所存储的数据地址,需要根据开窗的起始坐标来设置。以 800 * 480的 LCD 屏为例,假定帧缓存数组为:g_ltdc_framebuf,设置窗口的起始地址为:sx(<800),sy(<480),颜色格式为 RGB565 ,每个像素 2个字节,那么 MA 的设置值应该为:
MA[3:0] = g_ltdc_framebuf + 2 * (800 * sy + sx)
同样的,还有前景层的输出存储器地址寄存器 DMA2D_ FGMAR,作用和计算方法相同,控制的是前景层的存储器地址。
DMA2D 行数寄存器 DMA2D_NLR

控制每行的像素和行数,该寄存器对前景层和显示层都有效,配置该寄存器可设置开窗大小。
NL[15:0]: 设置待传输区域的行数,用于确定窗口的亮度。
PL[13:0]: 设置待传输区域的每行像素数,用于确定窗口的宽度。
DMA2D 输出颜色寄存器 DMA2D_OCOLR

该寄存器用于配置寄存器到存储器模式下,填充时所用的颜色值,一个 32位寄存器,可支持 ARGb8888 格式,也支持 RGB555 格式。
DMA2D 中断状态寄存器 DMA2D_ISR

该寄存器表示了 DMA2D 的各种标识,这里只关心 TCIF 位,表示 DMA2D 的传输完成中断标志,中断完成时置一。
使用DMA2D 的中断标志位清零寄存器: DMA2D_IFCR,用于清除 DMA2D_ISR 寄存器对应位的标志。通过向该寄存器的第 1位(CTCIF)写 1,可以用于清除 DMA2D_ISR 寄存器的 TCIF 位标志,其他同上。
DMA2D 程序操作
寄存器到存储器模式(填充单一颜色)
点击查看代码
__HAL_RCC_DMA2D_CLK_ENABLE(); /* 使能DM2D时钟 */
DMA2D->CR &= ~(DMA2D_CR_START); /* 先停止DMA2D */
DMA2D->CR = DMA2D_R2M; /* 寄存器到存储器模式 */
DMA2D->OPFCCR = LTDC_PIXFORMAT; /* 设置颜色格式 */
DMA2D->OOR = offline; /* 设置行偏移 */
DMA2D->OMAR = addr; /* 输出存储器地址 */
DMA2D->NLR = (pey - psy + 1) | ((pex - psx + 1) << 16); /* 设定行数寄存器 */
DMA2D->OCOLR = color; /* 设定输出颜色寄存器 */
DMA2D->CR |= DMA2D_CR_START; /* 启动DMA2D */
while ((DMA2D->ISR & (DMA2D_FLAG_TC)) == 0) /* 等待传输完成 */
{
timeout++;
if (timeout > 0X1FFFFF)
break; /* 超时退出 */
}
DMA2D->IFCR |= DMA2D_FLAG_TC; /* 清除传输完成标志 */
存储器到存储器模式(填充较为复杂的图案)
点击查看代码
__HAL_RCC_DMA2D_CLK_ENABLE(); /* 使能DM2D时钟 */
DMA2D->CR &= ~(DMA2D_CR_START); /* 先停止DMA2D */
DMA2D->CR = DMA2D_M2M; /* 存储器到存储器模式 */
DMA2D->FGPFCCR = LTDC_PIXFORMAT; /* 设置颜色格式 */
DMA2D->FGOR = 0; /* 前景层行偏移为0 */
DMA2D->OOR = offline; /* 设置行偏移 */
DMA2D->FGMAR = (uint32_t)color; /* 源地址 */
DMA2D->OMAR = addr; /* 输出存储器地址 */
DMA2D->NLR = (pey - psy + 1) | ((pex - psx + 1) << 16); /* 设定行数寄存器 */
DMA2D->CR |= DMA2D_CR_START; /* 启动DMA2D */
while ((DMA2D->ISR & (DMA2D_FLAG_TC)) == 0) /* 等待传输完成 */
{
timeout++;
if (timeout > 0X1FFFFF)
break; /* 超时退出 */
}
DMA2D->IFCR |= DMA2D_FLAG_TC; /* 清除传输完成标志 */
博客导航
本文来自博客园,作者:膝盖中箭卫兵,转载请注明原文链接:https://www.cnblogs.com/Skyrim-sssuuu/p/19169329

浙公网安备 33010602011771号
https://orcid.org/0000-0001-5102-772X