Skip to main content
CiuppaPT
Associate III
September 16, 2025
Solved

Horizontal glitches on LTDC display during I2C/FRAM transfers with DMA

  • September 16, 2025
  • 6 replies
  • 1547 views

 

Hi,
I am working with an STM32F769 MCU driving a 480×272 RGB565 TFT display through LTDC.

Architecture:

  • Framebuffer in external SDRAM (IS42S16800F-7TL, 16 MB) connected via FMC.

  • LTDC + DMA2D used for graphics update (TouchGFX).

  • I²C + DMA used to read/write parameters on an external FRAM.

  • System managed with FreeRTOS.

Problem:
When a long I²C DMA transfer is running (FRAM read/write for parameter storage), I see horizontal glitches on the display: objects temporarily shift to the right (as if some pixels were missing).

The curious part is that the phenomenon only happens if I change the initialization sequence in main() from this:

 

MX_LTDC_Init();
HAL_Delay(1000); // avoid flickering on display
MX_TouchGFX_Init();
HAL_Delay(200); // avoid flickering on display
osKernelInitialize();

…to this:

MX_LTDC_Init();
HAL_Delay(1000); // avoid flickering on display
MX_TouchGFX_Init();
HAL_Delay(200); // avoid flickering on display
__NOP(); // added
__NOP(); // added
osKernelInitialize();

adding only 2 _NOP();
really can’t explain why just adding, in this init sequence, two NOP  instructions makes the glitch appear.

Best answer by mƎALLEm

@CiuppaPT wrote:

Couldn’t this be the cause of our problem? Reference from AN4861.

CiuppaPT_0-1758211241052.png

 


The first MPU config, I provided to you (the background config) prevents that issue to occur. Moreover, the workaround of that limitation was already implemented in the system_stm32f7xx.c file / line 632:

 /*
 * Disable the FMC bank1 (enabled after reset).
 * This, prevents CPU speculation access on this bank which blocks the use of FMC during
 * 24us. During this time the others FMC master (such as LTDC) cannot use it!
 */
 FMC_Bank1->BTCR[0] = 0x000030d2;
 
 (void)(tmp);
}

Now, as I said, try to reorganize your MPU config.

6 replies

mƎALLEm
Technical Moderator
September 18, 2025

Hello,

Did you set the MPU background configuration to prevent speculative access of CM7?

You can refer to this post.

"To give better visibility on the answered topics, please click on ""Accept as Solution"" on the reply which solved your issue or answered your question."
CiuppaPT
CiuppaPTAuthor
Associate III
September 18, 2025

I tried everything, but none of the things I tried worked; I list them below. The only one that had any effect was commenting out the call in main()

/* Enable D-Cache--------------------------------------------------- ----- -*/
SCB_EnableDCache();

1) Raised the priority of the LTDC and DMA2D over the I2C DMA (failed)
2) Moved the buffer accessed by the I2C before DMA transfers from the external SDRAM to the internal SRAM1 (failed)
3) Set the property in MPU_Config to NON_CAHABLE for the FRAME_BUFFER of the display located at address 0xC0000000 (failed)
4) Inserted the InvalidateCache() method in both of the following...
TouchGFXGeneratedHAL::beginFrame()
TouchGFXGeneratedHAL::endFrame()
(failed)

At this point, I would be satisfied to understand why only disabling the D-CACHE seems to have a definitive effect on the problem.

Thank you

mƎALLEm
Technical Moderator
September 18, 2025

You didn't confirm if you enabled the MPU background configuration:

void MPU_Config(void)
{
 MPU_Region_InitTypeDef MPU_InitStruct;

 /* Disable the MPU */
 HAL_MPU_Disable();

 /* Configure the MPU as Strongly ordered for not defined regions */
 MPU_InitStruct.Enable = MPU_REGION_ENABLE;
 MPU_InitStruct.BaseAddress = 0x00;
 MPU_InitStruct.Size = MPU_REGION_SIZE_4GB;
 MPU_InitStruct.AccessPermission = MPU_REGION_NO_ACCESS;
 MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
 MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
 MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;
 MPU_InitStruct.Number = MPU_REGION_NUMBER0;
 MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
 MPU_InitStruct.SubRegionDisable = 0x87;
 MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;

 HAL_MPU_ConfigRegion(&MPU_InitStruct);

 /* Enable the MPU */
 HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
}
"To give better visibility on the answered topics, please click on ""Accept as Solution"" on the reply which solved your issue or answered your question."
Osman SOYKURT
Technical Moderator
September 18, 2025

Hello @CiuppaPT ,

Have you tried to raise LTDC priority? 

Osman SOYKURTST Software Developer | TouchGFX
CiuppaPT
CiuppaPTAuthor
Associate III
September 18, 2025

I tried everything, but none of the things I tried worked; I list them below. The only one that had any effect was commenting out the call in main()

 

/* Enable D-Cache--------------------------------------------------- ----- -*/
SCB_EnableDCache();

 

1) Raised the priority of the LTDC and DMA2D over the I2C DMA (failed)
2) Moved the buffer accessed by the I2C before DMA transfers from the external SDRAM to the internal SRAM1 (failed)
3) Set the property in MPU_Config to NON_CAHABLE for the FRAME_BUFFER of the display located at address 0xC0000000 (failed)
4) Inserted the InvalidateCache() method in both of the following...
TouchGFXGeneratedHAL::beginFrame()
TouchGFXGeneratedHAL::endFrame()
(failed)

At this point, I would be satisfied to understand why only disabling the D-CACHE seems to have a definitive effect on the problem.

Thank you

CiuppaPT
CiuppaPTAuthor
Associate III
September 18, 2025

My Toolchain :
STM32CubeIDE Version: 1.18.0 Build: 24413_20250227_1633 (UTC)
TouchGFX  "Version": "4.23.2"

CiuppaPT
CiuppaPTAuthor
Associate III
September 18, 2025

I share also Linker script file

/* Memories definition */
MEMORY
{
 RAM_DMA					(xrw)						: ORIGIN = 0x20000000, LENGTH = 128K
 RAM 					(xrw) 					: ORIGIN = 0x20020000, LENGTH = (512K - 128K)
 FLASH 					(rx) 					: ORIGIN = 0x08000000, LENGTH = (1024K - 8) 	/* flash size has been halved to allow for dual-bank */
 FLASH_METADATA			(rx)						: ORIGIN = 0x080FFFF8,	 LENGTH = 8
 QUADSPI 					(rx) 						: ORIGIN = 0x90000000, LENGTH = 16M /* external flash size has been halved to allow for dual-bank */
 QUADSPI_COMMON_DATA 	(rx)						: ORIGIN = 0x92000000, LENGTH = 32M
 /* the fist 256K are declared for the HMI frame buffer and cannot be used by others */
 EXTERNAL_RAM_DS 			(xrw)						: ORIGIN = 0xC0040000, LENGTH = 512K
 /*EXTERNAL_RAM_FREERTOS_HEAP(xrw) 					: ORIGIN = 0xC00C0000, LENGTH = 512K */
 /*EXTERNAL_RAM_LWIP 	(xrw)						: ORIGIN = 0xC0140000, LENGTH = 16K */
 /*EXTERNAL_RAM_DATA			(xrw)					: ORIGIN = 0xC0144000, LENGTH = (16M - 256K -512K - 512K - 16K) */
 
 /* aumentato da 512K a 768K */
 EXTERNAL_RAM_FREERTOS_HEAP (xrw) : ORIGIN = 0xC00C0000, LENGTH = 1M
 /* LWIP rimane invariato */
 EXTERNAL_RAM_LWIP (xrw) : ORIGIN = 0xC01C0000, LENGTH = 32K

 EXTERNAL_RAM_LWIP_HEAP (xrw) : ORIGIN = 0XC01C8000, LENGTH = 32K
 EXTERNAL_RAM_DATA (xrw) : ORIGIN = 0xC01D0000, LENGTH = (16M - 256K - 1M - 512K - 32K - 32K) 

}
CiuppaPT
CiuppaPTAuthor
Associate III
September 18, 2025

Couldn’t this be the cause of our problem? Reference from AN4861.

CiuppaPT_0-1758211241052.png

 

mƎALLEm
mƎALLEmBest answer
Technical Moderator
September 18, 2025

@CiuppaPT wrote:

Couldn’t this be the cause of our problem? Reference from AN4861.

CiuppaPT_0-1758211241052.png

 


The first MPU config, I provided to you (the background config) prevents that issue to occur. Moreover, the workaround of that limitation was already implemented in the system_stm32f7xx.c file / line 632:

 /*
 * Disable the FMC bank1 (enabled after reset).
 * This, prevents CPU speculation access on this bank which blocks the use of FMC during
 * 24us. During this time the others FMC master (such as LTDC) cannot use it!
 */
 FMC_Bank1->BTCR[0] = 0x000030d2;
 
 (void)(tmp);
}

Now, as I said, try to reorganize your MPU config.

"To give better visibility on the answered topics, please click on ""Accept as Solution"" on the reply which solved your issue or answered your question."
CiuppaPT
CiuppaPTAuthor
Associate III
September 19, 2025

While we rearrange the MPU_config, adding ...to FMC init

 FMC_Bank1->BTCR[0] = 0x000030d2;

seems to fix the glitch permanently.

For now, thank you very much for your attention.

CiuppaPT
CiuppaPTAuthor
Associate III
September 18, 2025

My system_stm32f7xx.c ends at line 268 ( CMSIS Device version number V1.2.8 ) and not include line line 632 with the...

 FMC_Bank1->BTCR[0] = 0x000030d2;

 

mƎALLEm
Technical Moderator
September 18, 2025

Ok, what you have is a generic file but you can refer to any system_stm32f7xx.c used for F769 eval board: Projects\STM32F769I_EVAL\Examples\FMC\FMC_SDRAM\Src\system_stm32f7xx.c

Meanwhile, the MPU background config will prevent that speculative access issue even if that workaround is not implemented in your system_stm32f7xx.c file.

"To give better visibility on the answered topics, please click on ""Accept as Solution"" on the reply which solved your issue or answered your question."