cancel
Showing results for 
Search instead for 
Did you mean: 

After enabling the SCB cache, screen flickering occurs during display refresh.

Lyu.1
Senior

Hi,Master

MCU: STM32H743II

LVGL: V9.1

Problem Description:

I have an external SDRAM with a size of 32MB.The program is configured as follows:

void sys_cache_enable(void)
{
    SCB_EnableICache(); 
    SCB_EnableDCache(); 
    SCB->CACR |= 1 << 2;
}
void mpu_memory_protection(void)
{
    // RAM 512K
    mpu_set_protection( 0x24000000,                 
                        MPU_REGION_SIZE_512KB,      
                        MPU_REGION_NUMBER1,         
                        MPU_REGION_FULL_ACCESS,     
                        MPU_ACCESS_SHAREABLE,       
                        MPU_ACCESS_CACHEABLE,       
                        MPU_ACCESS_NOT_BUFFERABLE); 
    
    // EXSDRAM 32M
    mpu_set_protection( 0XC0000000,                
                        MPU_REGION_SIZE_32MB,       
                        MPU_REGION_NUMBER2,         
                        MPU_REGION_FULL_ACCESS,     
                        MPU_ACCESS_SHAREABLE,      
                        MPU_ACCESS_CACHEABLE,       
                        MPU_ACCESS_NOT_BUFFERABLE);     
}

The LVGL related frame buffers are stored in the external SDRAM as shown below.

static color_t render_buff1[1024 * 600];
static color_t render_buff2[1024 * 600];
static color_t frame_buff[1024 * 600];
// LVGL uses double buffering for rendering.
lv_display_set_buffers(disp, render_buff1, render_buff2, 
                       sizeof(render_buff1), 
                       LV_DISPLAY_RENDER_MODE_PARTIAL);

The process is as follows:

     render                dma2d                ltdc
lvgl-------->double buff---------->frame_buff---------->lcd
// render: Switch between double buffers for rendering.
// dma2d: DMA2D is executed in the LVGL disp_flush callback. The code snippet is as follows:

SCB_CleanDCache_by_Addr((uint32_t*)disp->buf_1->data, 1024 * 600 * sizeof(color_t));
SCB_CleanDCache_by_Addr((uint32_t*)disp->buf_2->data, 1024 * 600 * sizeof(color_t));

__HAL_RCC_DMA2D_CLK_ENABLE();           /* Enable DMA2D clock */                   
DMA2D->CR &= ~(DMA2D_CR_START);         /* Stop DMA2D first */                 
DMA2D->CR = DMA2D_M2M;                  /* Memory-to-memory mode */               
DMA2D->FGPFCCR = LTDC_PIXFORMAT;        /* Set color format */               
DMA2D->FGOR = 0;                        /* Foreground layer line offset is 0 */               
DMA2D->OOR = offline;                   /* Set line offset */               
DMA2D->FGMAR = (uint32_t)color;         /* Source address */               
DMA2D->OMAR = addr;                     /* Output memory address */               
DMA2D->NLR = (pey - psy + 1) | ((pex - psx + 1) << 16); /* Set the number of lines register */
DMA2D->CR |= DMA2D_CR_START;            /* Start DMA2D */                    

In LVGL's flush_wait_cb, wait for the DMA transfer to complete.

int to = 100000;
while(to-- > 0) {              
	if ((DMA2D->ISR & (DMA2D_FLAG_TC))) break;
	delay_us(1);
}
DMA2D->IFCR |= DMA2D_FLAG_TC;
SCB_CleanDCache_by_Addr((uint32_t*)frame_buff, 1024 * 600 * sizeof(color_t));

The flickering issue described above occurs when these functions are enabled. When I comment out sys_cache_enable(), mpu_memory_protection(), and SCB_CleanDCache_by_Addr(), the problem disappears.

I don't know what is causing this issue. I need help. Thank you very much!

2 REPLIES 2
mƎALLEm
ST Employee

Hello,

Try first to enable the MPU background configuration to prevent the CM7 speculative access to the unused/uninitialized external memory regions. It's recommended for all products having CM7 as core. See this thread as example.

This is the MPU background config provided in all the examples in CubeH7:

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);
	
  /* Other MPU regions config come after */

  /* Enable the MPU */
  HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
} 

 You need to set that configuration as the first region in your MPU config.

It could be not the solution for your issue but this MPU configuration is mandatory.

Becarefull, about this value in the struct as you are not using this value in your implementation:

MPU_InitStruct.SubRegionDisable = 0x87;

 

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.

Okay, thank you very much for your guidance. I will give it a try.