LTDC 顯示器介面
本情境介紹如何在使用 LCD-TFT 平行顯示器介面時,設定 STM32 LTDC 顯示器控制器以及 TouchGFX Generator。
TouchGFX Generator 可產生全部 TouchGFX AL,其設定 LTDC 將像素從影格緩衝記憶體傳輸到顯示器,並將顯示器與 TouchGFX Engine 同步。
設定
在 STM32CubeMX 類別清單中從多媒體群組啟用 LTDC。
一旦啟用 LTDC,平行 RGB (LTDC) 選項可透過 TouchGFX Generator 的顯示器區段選取。
透過 STM32CubeMX 啟用 LTDC 後,必須設定以下參數:
- 設定LTDC(GPIO與相關時間參數)以符合連接的顯示器規格
- 設定LTDC以符合所需的TouchGFX應用程式需求。
TouchGFX Generator 可從 STM32CubeMX 讀取各種設定,並在依賴關係區段提供警告、建議或錯誤清單。 下圖顯示在 STM32CubeMX 中初始啟用 LTDC 時存在的依賴關係清單:
Note
參數和層設定
必須在 LTDC 區塊中設定以下參數:
相依關係 | 描述 |
---|---|
層數 | TouchGFX只能利用單一影像層。 |
視窗位置 | 預設情況下,LTDC層的水平和垂直視窗位置為0。 視窗的水平和垂直停止必須設置為語顯示相等尺寸。 |
Alpha常數為0 | LTDC影像層的Alpha常數預設為0。 此設定需大於0,最好是255,除非在應用當中需具有一個永久可得的全域Alpha設定。 |
下圖可看到在滿足警示警息的LTDC設定之後,相依關係群組便從TouchGFX Generator介面中消失。
Note
TouchGFX驅動程式/VSYNC信號
一旦平行 RGB (LTDC) 被選為顯示器介面,開發人員可以存取 LTDC Application Tick Driver,使用 LTDC 中斷來驅動 TouchGFX Engine 主循環。 這是使用 LTDC 時驅動 TouchGFX Engine 主循環的建議方法。
Note
以下程式碼是產生的 LTDC 中斷處理程序 (用於單一或雙重影像緩衝區策略),當顯示器準備好時,就會自動發出訊號並解鎖 TouchGFX Engine 主循環。
TouchGFXGeneratedHAL.cpp
extern "C"
{
void HAL_LTDC_LineEventCallback(LTDC_HandleTypeDef* hltdc)
{
if (!HAL::getInstance())
{
return;
}
if (LTDC->LIPCR == lcd_int_active_line)
{
//進入作用中區域
HAL_LTDC_ProgramLineEvent(hltdc, lcd_int_porch_line);
HAL::getInstance()->vSync();
OSWrappers::signalVSync();
// 立即交換影像緩衝區而不等待任務加入排程。
// 註:任務在喚醒時也會交換,但操作受到保護,
// 如果已經交換,則不會產生任何影響。
HAL::getInstance()->swapFrameBuffers();
GPIO::set(GPIO::VSYNC_FREQ);
}
else
{
//離開作用中區域
HAL_LTDC_ProgramLineEvent(hltdc, lcd_int_active_line);
// 通知框架顯示更新已完成。
HAL::getInstance()->frontPorchEntered();
GPIO::clear(GPIO::VSYNC_FREQ);
}
}
}
LTDC 影像緩衝區位址設定
生成的TouchGFX HAL將在運行時自動配置LTDC層色彩影像緩衝起始位址,因此不應在LTDC配置中設定數值。
GFXMMU 設定
使用局部緩衝區-LTDC 驅動顯示器影像緩衝區策略時,必須啟用並設定 GFXMMU。 GFXMMU 用於將 LTDC 讀取的影像緩衝區位址對映到實體記憶體中局部影像緩衝區塊的位址。
首先,在 STM32CubeMX 中的多媒體區段啟用 GFXMMU,然後啟用位址轉換。 對於 16 位元和 32 位元影像緩衝區像素格式,區塊大小建議設定為 16 位元組。 對於 24 位元影像緩衝區像素格式,需要 12 位元組的區塊大小。
Note
Caution
TouchGFX Generator 將自動產生一個位址查找表 (LUT),該表根據 GFXMMU 設定和 LTDC 層設定來對映位址。
啟用 GFXMMU 後,可以在 TouchGFX Generator 中設定使用的局部區塊數量 (或局部影像緩衝區塊與顯示器相符的次數)。
此參數將直接影響影像緩衝區塊使用的 RAM 數量。 區塊的數量必須是 2 的次方,例如 2、4 和 8,分別會導致影像緩衝區塊的大小為總顯示尺寸的 1/2、1/4 和 1/8。
影像緩衝區分配
使用局部緩衝區-LTDC 驅動顯示器影像緩衝區策略時,影像緩衝區分配策略的語意與平常不同。
如果選擇按分配,TouchGFX Engine 將直接繪製到實體局部影像緩衝區塊中,而 LTDC 則透過 GFXMMU 位址 LUT 進行讀取。
如果選擇按位址,只能指定其中一個 GFXMMU 虛擬緩衝區的位址,TouchGFX Engine 將在渲染時透過 GFXMMU 的虛擬緩衝區進行繪製,而不會直接繪製到實體影像緩衝區塊中。
緩衝區位置-按分配
建議的影像緩衝區分配策略是按分配。 如此一來,TouchGFX Engine 可直接繪製到實體局部影像緩衝區塊中,而 LTDC 則透過 GFXMMU 位址 LUT 進行讀取。
緩衝區位置-按位址
此選項僅建議用於特定平台,這些平台在使用 RGB888 影像緩衝區格式和透過 GPU2D (NeoChrome) 加速渲染時受到限制。
部分使用 GPU2D (NeoChrome) 加速渲染的 MCU 不支援寫入 24 位元 RGB888 影像緩衝區。 在這種情況下,GFXMMU 用於將自 32 位元 ARGB8888 格式讀取/寫入的資料, 封裝成實體影像緩衝區塊所需的 RGB888 格式。
Further reading
為了實現此操作,必須將 LTDC 像素格式設定為使用 ARGB8888 影像緩衝區格式,並使用 GFXMMU 的虛擬緩衝區之一 GFXMMU_VIRTUAL_BUFFERX_BASE
作為影像緩衝區位址。 務必使用與在 GFXMMU 中設定 相同的 GFXMMU 緩衝位址。 設定 GFXMMU 以使用 12 位元組的區塊大小,並為緩衝區啟用封裝,如下所示:
這些選項將反映在 TouchGFX Generator UI 中:
必須在連結器指令碼中定義具有正確大小 (即每像素 3 個位元組) 的實體 24 位元影格緩衝記憶體區域,並且必須使用此區域的起始位址來設定 GFXMMU 的實體緩衝區位址。
Note
支援的影像緩衝區策略
- 單一
- 雙重
- 局部-LTDC 驅動顯示器
Further reading
單一
使用具有單一影像緩衝區策略的 LTDC 驅動顯示器,將在 HAL 中產生以下程式碼,以允許 TouchGFX Engine 遵循顯示器的更新週期來最佳化渲染過程:
TouchGFXGeneratedHAL.cpp
uint16_t TouchGFXGeneratedHAL::getTFTCurrentLine()
{
// CPSR 暫存器 (bits 15:0) 指定 TFT 控制器的目前行數。
uint16_t curr = (uint16_t)(LTDC->CPSR & LTDC_CPSR_CYPOS_Msk);
uint16_t backPorchY = (uint16_t)(LTDC->BPCR & LTDC_BPCR_AVBP_Msk) + 1;
// getTFTCurrentLine() 函數的分配策略是返回
// 範圍在 0-totalheight 內的值。 如果我們仍在後沿區域,則回傳 0。
return (curr < backPorchY) ? 0 : (curr - backPorchY);
}
在 LTDC 中斷處理程序中,LTDC 影像緩衝區位址將不會被交換,當顯示器更新週期退出作用中區域時 (即顯示器已讀取完影像緩衝區的最後一行),TouchGFX Engine 可以完成目前影格的渲染。
參考實作
TouchGFX 開發板設定 STM32U5G9J Discovery Kit 2 包含雙重影像緩衝區策略的參考實作。 在 TouchGFX Generator 中將影像緩衝區策略變更為單一影像緩衝區並產生程式碼,以查看使用單一影像緩衝區策略的範例:
雙重
當使用具有雙重影像緩衝區策略的 LTDC 驅動顯示器時,LTDC 影像緩衝區位址將在 LTDC 中斷處理程序中交換到另一個影像緩衝區。 這使得 TouchGFX Engine 能夠在交換 LTDC 影像緩衝區位址後立即渲染下一個影格,同時 LTDC 正在從另一個影像緩衝區讀取目前影格。
參考實作
TouchGFX 開發板設定 STM32U5G9J Discovery Kit 2 包含參考實作:
局部-LTDC 驅動顯示器
使用具有局部影像緩衝區策略的 LTDC 驅動顯示器類似於使用單一影像緩衝區策略,但 TouchGFX Engine 只會渲染到局部影像緩衝區塊。 由於相同的影像緩衝區塊重複用於渲染顯示器的所有部分,因此有效管理渲染過程以避免螢幕撕裂和錯過硬性期限非常重要。 為了實現此操作,TouchGFX Generator 將在 HAL 中產生以下程式碼,其允許 TouchGFX Engine 設定 LTDC 行中斷向 TouchGFX Engine 發出訊號,告知何時渲染顯示器的下一部分:
TouchGFXGeneratedHAL.cpp
void TouchGFXGeneratedHAL::waitForLTDCLines(uint16_t numberOfLines)
{
// CPSR 暫存器 (bits 15:0) 指定 TFT 控制器的目前行數。
uint16_t curr = LTDC->CPSR & LTDC_CPSR_CYPOS_Msk;
// AWCR 暫存器 (10:0) 指定累計作用中高度。
uint16_t max = (LTDC->AWCR & LTDC_AWCR_AAH_Msk) - 1;
// 計算要設定中斷的行數。
curr += numberOfLines;
if (curr > max)
{
curr -= max;
}
// Configure line interrupt
HAL_LTDC_ProgramLineEvent(&hltdc, curr);
// 等待 VSync 訊號,此訊號會在我們方才設定的中斷行數發出。
OSWrappers::waitForVSync();
}
函數 TouchGFXGeneratedHAL::waitForLTDCLines(uint16_t)
從 TouchGFX Engine 繪圖循環呼叫。 請求的具體行數取決於一組參數。 根據在 TouchGFX Generator 中設定的局部區塊數量,這些參數將會被指派一組適當的預設值。
由於影像緩衝區塊重複用於渲染顯示器的所有部分,因此會利用 VSYNC 訊號 (此訊號通常表示 LTDC 掃描線已離開作用中區域) 來向 TouchGFX Engine 發出訊號以開始渲染顯示器的下一部分:
TouchGFXGeneratedHAL.cpp
extern "C"
{
void HAL_LTDC_LineEventCallback(LTDC_HandleTypeDef* hltdc)
{
OSWrappers::signalVSync();
}
}
參考實作
The TouchGFX Board Setup STM32H7S78 DK Partial Framebuffer includes a reference implementation: