帧缓存策略
本节介绍了如何配置TouchGFX Generator,以生成使用以下帧缓存策略之一的TouchGFX HAL:
- 单帧缓存
- 双帧缓存
- 部分帧缓存
点击这里阅读更多关于帧缓存的内容。
单帧缓存
通过选择单帧缓存作为缓冲策略,开发人员既可以由编译器在内部RAM中分配帧缓存区域,也可以自行在RAM中指定帧缓存存储位置。
按分配来
选择按分配时,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);
}
双帧缓存
在双帧缓存配置中,TouchGFX Generator将根据所选帧缓存策略和显示接口在HAL中生成用于帧缓存切换的代码。 在主事件循环期间,TouchGFX Engine将会用到与帧缓存相连的存储器接口。
按地址
选择按地址时,TouchGFX Generator将在HAL初始化期间使用两个指定的起始地址。
TouchGFXGeneratedHAL.cpp
void TouchGFXGeneratedHAL::initialize()
{
HAL::initialize();
setFrameBufferStartAddresses((void*)0xC0000000, (void*)0xC003FC00, (void*)0);
}
Tip
Tip
按分配来
选择按分配时,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不使用与显示尺寸相同的帧缓存。 相反,用户可以选择具有给定尺寸的若干块作为帧缓存。 TouchGFX利用帧缓存分配器来控制这些块的使用。
使用此策略时,无需提供指向外部内存(帧缓存所在位置)的指针,也不需要在内部内存中分配帧缓存数组。
有关帧缓存概念的一般概述,请参见有关帧缓存的文章。
Tip
由于部分帧缓存通常仅用于无TFT控制器且内部RAM很小的低成本MCU,因此部分帧缓存策略期望开发人员实现将帧缓存内容传输到显示屏的操作。 参见FMC/SPI方案,以了解如何将像素通过无TFT控制器的MCU的串口传输到显示屏等。
为了在TouchGFX里使用部分帧缓存策略链接显示屏,开发人员需要提供用于以下两个功能的实现。 下面显示的代码由CubeMX生成,存放在TouchGFX/target/generated/TouchGFXGeneratedHAL.cpp
文件中,它定义了TouchGFX 引擎和显示驱动程序之间的接口。
TouchGFXGeneratedHAL.cpp
/* ******************************************************
* 部分帧缓存策略所需的功能
* ******************************************************
*
* int touchgfxDisplayDriverTransmitActive()无论当前是否正在通过SPI传输数据必须返回。
* 当框架想要发送一个数据块时
* 将调用touchgfxDisplayDriverTransmitBlock(const uint8_t* 像素, uint16_t x, uint16_t y, uint16_t w, uint16_t h)。 然后用户必须传输参数表示的数据。
*/
extern "C" int touchgfxDisplayDriverTransmitActive();
extern "C" int touchgfxDisplayDriverShouldTransferBlock(uint16_t bottom);
extern "C" void touchgfxDisplayDriverTransmitBlock(const uint8_t* pixels, uint16_t x, uint16_t y, uint16_t w, uint16_t h);
extern "C" void touchgfxSignalVSync(void);
对于TouchGFX 设计器中提供的STM32G071 TouchGFX应用程序模板,这些功能在Core/Src/MB1642BDisplayDriver.c
中实现。(此处仅显示一个):
Core/Src/MB1642BDisplayDriver.c
int touchgfxDisplayDriverTransmitActive(void)
{
return IsTransmittingBlock_;
}
采用这种策略,CubeMX还在TouchGFX/target/generated/TouchGFXGeneratedHAL.cpp
中的只读TouchGFXGeneratedHAL
类中生成TouchGFXGeneratedHAL::flushFrameBuffer(Rect&)
。
Note
TouchGFXGeneratedHAL.cpp
void TouchGFXGeneratedHAL::flushFrameBuffer(const touchgfx::Rect& rect)
{
HAL::flushFrameBuffer(rect);
// Try transmitting a block
PartialFrameBufferManager::tryTransmitBlock();
}