【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; /* 清除傳輸完成標志 */
博客導航
本文來自博客園,作者:膝蓋中箭衛兵,轉載請注明原文鏈接:http://www.rzrgm.cn/Skyrim-sssuuu/p/19169329

浙公網安備 33010602011771號
https://orcid.org/0000-0001-5102-772X