跳轉到主要內容

影像緩衝區策略

本節介紹如何配置TouchGFX Generator以產生基於以下影像緩衝區策略之一的TouchGFX HAL:

  • 單一影像緩衝區
  • 雙影像緩衝區
  • 部份影像緩衝區

單一影像緩衝區

選取單一影像緩衝區(Single Frame Buffer)作為緩衝策略,開發人員可以讓編譯器於內部RAM中配置影像緩衝區所需的記憶體,或者也可以自行在內部RAM中指定影像緩衝區的存取位置。

依配置 (By Allocation)

選擇依配置(By Allocation)時,TouchGFX Generator將根據圖形的大小和像素位元深度來配置影像緩衝陣列。

單一影像緩衝區,依配置

產生用於設定HAL的程式碼,並將該陣列用作影像緩衝區。

TouchGFXGeneratedHAL.cpp
namespace {
// Use the section "TouchGFX_Framebuffer" in the linker script
// to specify the placement of the buffer
LOCATION_PRAGMA("TouchGFX_Framebuffer")
uint32_t frameBuf[(480 * 272 * 2 + 3) / 4] LOCATION_ATTRIBUTE("TouchGFX_Framebuffer");
}

void TouchGFXGeneratedHAL::initialize()
{
HAL::initialize();

setFrameBufferStartAddresses((void*)frameBuf, (void*)0, (void*)0);
}

依位址

當為影像緩衝區的位置選擇依位址時,TouchGFX Generator將在HAL初始化階段使用所指定的起始位址。

單一影像緩衝區,依位址

TouchGFXGeneratedHAL.cpp
void TouchGFXGeneratedHAL::initialize()
{
HAL::initialize();

setFrameBufferStartAddresses((void*)0xC0000000, (void*)0, (void*)0);
}

雙影像緩衝區 (Double Frame Buffer)

在雙影像緩衝區 (Double Frame Buffer) 配置中,TouchGFX Generator將根據所選取的影像緩衝區策略和顯示介面在HAL中產生用於影像緩衝區切換的程式碼。 在主事件循環期當中TouchGFX引擎將會用到與影像緩衝區相連的記憶體介面。

依位址

選擇依位址時,TouchGFX Generator將在HAL初始化階段使用兩個指定的起始位址。

雙影像緩衝區,依位址

TouchGFXGeneratedHAL.cpp
void TouchGFXGeneratedHAL::initialize()
{
HAL::initialize();

setFrameBufferStartAddresses((void*)0xC0000000, (void*)0xC003FC00, (void*)0);
}
Tip
將RGB並列顯示(LTDC)作為顯示介面時,起始位址將從LTDC圖層 (layer) 的設定中繼承。

依配置 (By Allocation)

選擇依配置(By Allocation) 時,TouchGFX Generator將根據圖形的大小和位元深度來配置陣列大小,這與使用單一影像緩衝區完全一樣,差別只在於配置了兩個相同大小的陣列。

單一影像緩衝區,依配置

TouchGFXGeneratedHAL.cpp
namespace {
// Use the section "TouchGFX_Framebuffer" in the linker to specify the placement of the buffer
LOCATION_PRAGMA("TouchGFX_Framebuffer")
uint32_t frameBuf[(480 * 272 * 2 + 3) / 4 * 2] LOCATION_ATTRIBUTE("TouchGFX_Framebuffer");
}

void TouchGFXGeneratedHAL::initialize()
{
HAL::initialize();

setFrameBufferStartAddresses((void*)frameBuf, (void*)(frameBuf + sizeof(frameBuf)/(sizeof(uint32_t)*2)), (void*)0);
}

局部影像緩衝區

透過選擇局部影像緩衝區策略,開發人員可以選擇數個大小不同的區塊當作影像緩衝區。 此策略使用TouchGFX所謂的影像緩衝配置器 (Frame Buffer Allocator),除了與提供指向位於外部記憶體之影像緩衝區的指標不同之外,也與在內部記憶體中配置固定大小的陣列不同。

有關影像緩衝區的概念,請參見有關影像緩衝區的文章。

Tip
STM32G0通常沒有足夠的內部RAM來作影像緩衝區。 因此「局部緩衝 (Partial Buffer)」就是這類低成本MCU的完美方案

局部影像緩衝區

由於局部緩衝區通常僅用於無TFT控制器且內部RAM很小的低成本MCU,因此局部緩衝區策略就期望開發人員能完成將緩衝內容傳輸到顯示器的實作。 參見FMC/SPI方案,以瞭解如何將像傳送到不具TFT控制器的MCU所連接的序列傳輸顯示器。

為了在TouchGFX裡使用局部緩衝區策略,開發人員需要實作以下兩個功能。 在以下由CubeMX產生的程式碼當中,TouchGFX/target/generated/TouchGFXGeneratedHAL.cpp定義了開發人員要用到的TouchGFX 引擎介面

TouchGFXGeneratedHAL.cpp
/* ******************************************************
* Functions required by Partial Frame Buffer Strategy
* ******************************************************
*
* * uint8_t isTransmittingData() must return whether or not data is currently being transmitted, over e.g. SPI.
* * 當框架想要發送一個資料塊時,將呼叫transmitFrameBufferBlock(uint8_t* pixels, uint16_t x,uint16_t y,uint16_t w,uint16_t h)。 然後使用者必須傳輸*參數表示的資料。
* * 一旦transmitFrameBufferBlock() 已經成功發送資料塊,用戶必須呼叫touchgfx::startNewTransfer()。
* 例如, 如果使用DMA傳輸資料塊,這可以在“傳輸完成”中斷處理中被呼叫。
以下函數也由TouchGFX/target/generated/TouchGFXGeneratedHAL. cpp內部的唯讀TouchGFXGeneratedHAL類中的CubeMX產生。 ```

以下函式也由CubeMx生成,置於`TouchGFX/target/generated/TouchGFXGeneratedHAL.cpp `當中,屬於`TouchGFXGeneratedHAL `唯讀類別。

<Note>
此flushFrameBuffer()函式通常用於無TFT控制器的MCU。 當使用局部緩衝區時,TouchGFX Generator可以為此緩衝區策略產生一個對應的操作方法之實作定義。
</Note>

<CodeHeader>TouchGFXGeneratedHAL.cpp</CodeHeader>

```cpp {12,16}
void TouchGFXGeneratedHAL::flushFrameBuffer(const touchgfx::Rect& rect)
{
HAL::flushFrameBuffer(rect);

// Once flushFrameBuffer() is called by the framework a block is ready for transfer
// Mark it ready for transfer and transmit it if user defined method
// isTransmittingData() does not return false

// If data is not being transmitted, transfer the data with user defined method
// transmitFrameBufferBlock().
frameBufferAllocator->markBlockReadyForTransfer();
if (!isTransmittingData())
{
touchgfx::Rect r;
const uint8_t* pixels = frameBufferAllocator->getBlockForTransfer(r);
transmitFrameBufferBlock((uint8_t*)pixels, r.x, r.y, r.width, r.height);
}
}