2025-07-10 7:54 AM
Hello everyone,
I’m working on a custom board built around the STM32F769BIT6. I’ve configured the SDRAM timings according to the datasheet and set the LTDC to RGB888. The same TouchGFX project runs flawlessly on the STM32F769I-Discovery board, but on my custom hardware the display begins to flicker whenever I scroll through a list.
Has anyone run into this before, or can you suggest where I should focus my debugging? Below are my SDRAM and LTDC settings. Any guidance would be greatly appreciated!
static void BSP_SDRAM_Initialization_Sequence(SDRAM_HandleTypeDef *hsdram, FMC_SDRAM_CommandTypeDef *Command)
{
__IO uint32_t tmpmrd =0;
/* Step 3: Configure a clock configuration enable command */
Command->CommandMode = FMC_SDRAM_CMD_CLK_ENABLE;
Command->CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
Command->AutoRefreshNumber = 1;
Command->ModeRegisterDefinition = 0;
/* Send the command */
HAL_SDRAM_SendCommand(hsdram, Command, SDRAM_TIMEOUT);
/* Step 4: Insert 100 us minimum delay */
/* Inserted delay is equal to 1 ms due to systick time base unit (ms) */
HAL_Delay(1);
/* Step 5: Configure a PALL (precharge all) command */
Command->CommandMode = FMC_SDRAM_CMD_PALL;
Command->CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
Command->AutoRefreshNumber = 1;
Command->ModeRegisterDefinition = 0;
/* Send the command */
HAL_SDRAM_SendCommand(hsdram, Command, SDRAM_TIMEOUT);
/* Step 6 : Configure a Auto-Refresh command */
Command->CommandMode = FMC_SDRAM_CMD_AUTOREFRESH_MODE;
Command->CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
Command->AutoRefreshNumber = 8;
Command->ModeRegisterDefinition = 0;
/* Send the command */
HAL_SDRAM_SendCommand(hsdram, Command, SDRAM_TIMEOUT);
/* Step 7: Program the external memory mode register */
tmpmrd = (uint32_t)SDRAM_MODEREG_BURST_LENGTH_1 |
SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL |
SDRAM_MODEREG_CAS_LATENCY_2 |
SDRAM_MODEREG_OPERATING_MODE_STANDARD |
SDRAM_MODEREG_WRITEBURST_MODE_SINGLE;
Command->CommandMode = FMC_SDRAM_CMD_LOAD_MODE;
Command->CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
Command->AutoRefreshNumber = 1;
Command->ModeRegisterDefinition = tmpmrd;
/* Send the command */
HAL_SDRAM_SendCommand(hsdram, Command, SDRAM_TIMEOUT);
/* Step 8: Set the refresh rate counter */
/* (15.62 us x Freq) - 20 */
/* Set the device refresh counter */
hsdram->Instance->SDRTR |= ((uint32_t)((1542)<< 1));
}
/* USER CODE END 0 */
SDRAM_HandleTypeDef hsdram1;
/* FMC initialization function */
void MX_FMC_Init(void)
{
/* USER CODE BEGIN FMC_Init 0 */
/* USER CODE END FMC_Init 0 */
FMC_SDRAM_TimingTypeDef SdramTiming = {0};
/* USER CODE BEGIN FMC_Init 1 */
/* USER CODE END FMC_Init 1 */
/** Perform the SDRAM1 memory initialization sequence
*/
hsdram1.Instance = FMC_SDRAM_DEVICE;
/* hsdram1.Init */
hsdram1.Init.SDBank = FMC_SDRAM_BANK1;
hsdram1.Init.ColumnBitsNumber = FMC_SDRAM_COLUMN_BITS_NUM_8;
hsdram1.Init.RowBitsNumber = FMC_SDRAM_ROW_BITS_NUM_12;
hsdram1.Init.MemoryDataWidth = FMC_SDRAM_MEM_BUS_WIDTH_32;
hsdram1.Init.InternalBankNumber = FMC_SDRAM_INTERN_BANKS_NUM_4;
hsdram1.Init.CASLatency = FMC_SDRAM_CAS_LATENCY_2;
hsdram1.Init.WriteProtection = FMC_SDRAM_WRITE_PROTECTION_DISABLE;
hsdram1.Init.SDClockPeriod = FMC_SDRAM_CLOCK_PERIOD_2;
hsdram1.Init.ReadBurst = FMC_SDRAM_RBURST_ENABLE;
hsdram1.Init.ReadPipeDelay = FMC_SDRAM_RPIPE_DELAY_0;
/* SdramTiming */
SdramTiming.LoadToActiveDelay = 2;
SdramTiming.ExitSelfRefreshDelay = 6;
SdramTiming.SelfRefreshTime = 4;
SdramTiming.RowCycleDelay = 6;
SdramTiming.WriteRecoveryTime = 2;
SdramTiming.RPDelay = 2;
SdramTiming.RCDDelay = 2;
if (HAL_SDRAM_Init(&hsdram1, &SdramTiming) != HAL_OK)
{
Error_Handler( );
}
/* USER CODE BEGIN FMC_Init 2 */
FMC_SDRAM_CommandTypeDef command;
/* Program the SDRAM external device */
BSP_SDRAM_Initialization_Sequence(&hsdram1, &command);
//Deactivate speculative/cache access to first FMC Bank to save FMC bandwidth
FMC_Bank1->BTCR[0] = 0x000030D2;
/* USER CODE END FMC_Init 2 */
}
void MX_LTDC_Init(void)
{
/* USER CODE BEGIN LTDC_Init 0 */
__HAL_LTDC_DISABLE(&hltdc);
/* USER CODE END LTDC_Init 0 */
LTDC_LayerCfgTypeDef pLayerCfg = {0};
/* USER CODE BEGIN LTDC_Init 1 */
/* USER CODE END LTDC_Init 1 */
hltdc.Instance = LTDC;
hltdc.Init.HSPolarity = LTDC_HSPOLARITY_AL;
hltdc.Init.VSPolarity = LTDC_VSPOLARITY_AL;
hltdc.Init.DEPolarity = LTDC_DEPOLARITY_AL;
hltdc.Init.PCPolarity = LTDC_PCPOLARITY_IPC;
hltdc.Init.HorizontalSync = 47;
hltdc.Init.VerticalSync = 0;
hltdc.Init.AccumulatedHBP = 87;
hltdc.Init.AccumulatedVBP = 31;
hltdc.Init.AccumulatedActiveW = 887;
hltdc.Init.AccumulatedActiveH = 511;
hltdc.Init.TotalWidth = 927;
hltdc.Init.TotalHeigh = 524;
hltdc.Init.Backcolor.Blue = 0;
hltdc.Init.Backcolor.Green = 0;
hltdc.Init.Backcolor.Red = 0;
if (HAL_LTDC_Init(&hltdc) != HAL_OK)
{
Error_Handler();
}
pLayerCfg.WindowX0 = 0;
pLayerCfg.WindowX1 = 800;
pLayerCfg.WindowY0 = 0;
pLayerCfg.WindowY1 = 480;
pLayerCfg.PixelFormat = LTDC_PIXEL_FORMAT_RGB888;
pLayerCfg.Alpha = 255;
pLayerCfg.Alpha0 = 0;
pLayerCfg.BlendingFactor1 = LTDC_BLENDING_FACTOR1_CA;
pLayerCfg.BlendingFactor2 = LTDC_BLENDING_FACTOR2_CA;
pLayerCfg.FBStartAdress = 0xC0000000;
pLayerCfg.ImageWidth = 800;
pLayerCfg.ImageHeight = 480;
pLayerCfg.Backcolor.Blue = 0;
pLayerCfg.Backcolor.Green = 0;
pLayerCfg.Backcolor.Red = 0;
if (HAL_LTDC_ConfigLayer(&hltdc, &pLayerCfg, 0) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN LTDC_Init 2 */
HAL_GPIO_WritePin(LCD_DISP_GPIO_Port, LCD_DISP_Pin, GPIO_PIN_RESET);
HAL_Delay(20);
HAL_GPIO_WritePin(LCD_RESET_GPIO_Port, LCD_RESET_Pin, GPIO_PIN_RESET);
HAL_Delay(20);
HAL_GPIO_WritePin(LCD_RESET_GPIO_Port, LCD_RESET_Pin, GPIO_PIN_SET);
HAL_Delay(20);
HAL_GPIO_WritePin(LCD_INIT_GPIO_Port, LCD_INIT_Pin, GPIO_PIN_RESET);
HAL_Delay(10);
HAL_GPIO_WritePin(LCD_INIT_GPIO_Port, LCD_INIT_Pin, GPIO_PIN_SET);
HAL_Delay(30);
HAL_GPIO_WritePin(LCD_DISP_GPIO_Port, LCD_DISP_Pin, GPIO_PIN_SET);
HAL_Delay(20);
HAL_LTDC_Reload(&hltdc, LTDC_RELOAD_VERTICAL_BLANKING);
__HAL_LTDC_ENABLE(&hltdc);
/* USER CODE END LTDC_Init 2 */
}
For reference, i have set HCLK to 200MHz and the LCD pixel clock to 29.2MHz.