2025-11-28 12:38 AM - last edited on 2025-11-28 12:48 AM by mƎALLEm
Hello
I'm using TouchGFX on the STM32H757I-EVAL board and facing D-Cache related issues.
The framebuffers are in SDRAM, other data is placed in AXI SRAM. D-Cache is enabled, the caching policies setup in the MPU are:
The cache maintenance operations in TouchGFXGeneratedHal.cpp invalidate the entire cache, which seems a bit heavy handed, but work fine so far:
void TouchGFXGeneratedHAL::InvalidateCache()
{
// Because DMA2D access main memory directly, the DCache must be invalidated
// becuase it could hold a wrong image of the framebuffer. That's done
// using the function SCB_CleanInvalidateDCache(). Remember to enable
// "CPU Cache" in the "System Core" settings for "Cortex M7" in CubeMX
// in order for this function call to work.
if (SCB->CCR & SCB_CCR_DC_Msk)
{
SCB_CleanInvalidateDCache();
}
}
void TouchGFXGeneratedHAL::FlushCache()
{
// If the framebuffer is placed in Write-Back cached memory (e.g. SRAM) then
// the DCache must be flushed prior to DMA2D accessing it. That's done
// using the function SCB_CleanInvalidateDCache(). Remember to enable
// "CPU Cache" in the "System Core" settings for "Cortex M7" in CubeMX in
// order for this function call to work.
if (SCB->CCR & SCB_CCR_DC_Msk)
{
SCB_CleanInvalidateDCache();
}
}
I've reimplemented the cache maintenance operations in TouchGFXHAL.cpp and restricted them to the framebuffers:
void TouchGFXHAL::InvalidateCache()
{
SCB_CleanInvalidateDCache_by_Addr((uint32_t *)m_frameBuffer, 2 * frameBufferSize);
}
void TouchGFXHAL::FlushCache()
{
SCB_CleanInvalidateDCache_by_Addr((uint32_t*)m_frameBuffer, 2 * frameBufferSize);
}
After this change, I sometimes get ghosting artefacts or hardfaults when rendering text. The issues persist even when I change the SDRAM caching policy to non cachable and only disappear when the AXI SRAM is made non cacheable.
I'm aware that DMA2D is reading data from AXI SRAM, but since AXI SRAM caching policy is write through, the data written by the CPU is put to main memory without requiring a clean operation. The memory barrier imposed by SCB_CleanInvalidateDCache_by_Addr() should suffice to make sure all pending write through operations have finished before DMA2D starts.
A possible explanation could be that DMA2A copies data from SDRAM to AXI SRAM which the CPU wont't see if the buffer in the AXI SRAM isn't invalidated after DMA2A has finished. So I checked wheter DMA2D is writing to addresses below the SDRAM by adding assertions shown below, which never failed.
void STM32DMA::setupDataFill(const BlitOp& blitOp)
{
assert((uint32_t)blitOp.pDst >= 0xD0000000);
...
void STM32DMA::setupDataCopy(const BlitOp& blitOp)
{
assert((uint32_t)blitOp.pDst >= 0xD0000000);
...
So I wonder why restricting cache maintenance to the framebuffer isn't enough? What am I missing? Any ideas?