cancel
Showing results for 
Search instead for 
Did you mean: 

SDRAM FMC with STM32H7

Giovanni3
Associate II

Hi everyone, my custom board previously had an STM32F746BGT6. Since we were looking for a microcontroller with a graphics accelerator, we opted for the STM32H743BIT6 (which is pin-to-pin compatible). All the peripherals work, but I'm having trouble initializing the SDRAM (IS42S16160G-6TL). I set the clock to 216 MHz on Cube, and with a prescale of 2 and an oscilloscope, I get 108 MHz. However, the program crashes (neither returns an error nor continues) when I send the PALL configuration.
I'm keeping the same declarations in the previous version (STM32F746BGT6), which is currently working. How can I fix this?

static 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_BANK2;
  hsdram1.Init.ColumnBitsNumber = FMC_SDRAM_COLUMN_BITS_NUM_9;
  hsdram1.Init.RowBitsNumber = FMC_SDRAM_ROW_BITS_NUM_13;
  hsdram1.Init.MemoryDataWidth = FMC_SDRAM_MEM_BUS_WIDTH_16;
  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_2;
  /* 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 */
	printf("Pre Init SDRAM\n");
	HAL_StatusTypeDef status = SDRAM_InitSequence();	
	if(status == HAL_OK) printf("Sdram Inizializzata Correttamente\n");
	else printf("Errore durante l'inizializzazione della Sdram\n");
  /* USER CODE END FMC_Init 2 */
}
HAL_StatusTypeDef SDRAM_InitSequence(void)
{
	FMC_SDRAM_CommandTypeDef Command;
	
	// STEP 1: Clock enable command
	Command.CommandMode            = FMC_SDRAM_CMD_CLK_ENABLE;
	Command.CommandTarget          = FMC_SDRAM_CMD_TARGET_BANK2;
	Command.AutoRefreshNumber      = 8;
	Command.ModeRegisterDefinition = 0;
	if (HAL_SDRAM_SendCommand(&hsdram1, &Command, SDRAM_TIMEOUT) != HAL_OK)
	{
		printf("Errore: CLK_ENABLE command failed\n");
		return HAL_ERROR;
	}
	printf("CLK Enable OK\n");
	// Attesa minima >100 µs (datasheet richiede 200 µs tip.)
	HAL_Delay(100); // 1 ms è più che sufficiente

	// STEP 2: Precharge all command
	Command.CommandMode            = FMC_SDRAM_CMD_PALL;
	Command.CommandTarget          = FMC_SDRAM_CMD_TARGET_BANK2;
	Command.AutoRefreshNumber      = 8;
	Command.ModeRegisterDefinition = 0;
	if (HAL_SDRAM_SendCommand(&hsdram1, &Command, SDRAM_TIMEOUT) != HAL_OK)
	{
		printf("Errore: PALL command failed\n");
		return HAL_ERROR;
	}
	printf("PALL OK\n");
	// STEP 3: Auto-refresh command (8 cicli)
	Command.CommandMode            = FMC_SDRAM_CMD_AUTOREFRESH_MODE;
	Command.CommandTarget          = FMC_SDRAM_CMD_TARGET_BANK2;
	Command.AutoRefreshNumber      = 8;
	Command.ModeRegisterDefinition = 0;
	if (HAL_SDRAM_SendCommand(&hsdram1, &Command, SDRAM_TIMEOUT) != HAL_OK)
	{
		printf("Errore: AUTOREFRESH command failed\n");
		return HAL_ERROR;
	}
	printf("AUTOREFRESH OK\n");
	// STEP 4: Load mode register
	uint32_t mode_reg = (uint32_t)(
		SDRAM_MODEREG_BURST_LENGTH_1          |   // Burst di 1 parola
		SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL   |   // Accesso sequenziale
		SDRAM_MODEREG_CAS_LATENCY_2           |   // CAS latency = 3
		SDRAM_MODEREG_OPERATING_MODE_STANDARD |
		SDRAM_MODEREG_WRITEBURST_MODE_SINGLE      // Write burst single
	);

	Command.CommandMode            = FMC_SDRAM_CMD_LOAD_MODE;
	Command.CommandTarget          = FMC_SDRAM_CMD_TARGET_BANK2;
	Command.AutoRefreshNumber      = 1;
	Command.ModeRegisterDefinition = mode_reg;
	if (HAL_SDRAM_SendCommand(&hsdram1, &Command, SDRAM_TIMEOUT) != HAL_OK)
	{
		printf("Errore: LOAD MODE command failed\n");
		return HAL_ERROR;
	}
	printf("LOAD OK\n");
	// STEP 5: NORMAL MODE command (mancante nel tuo codice)
	Command.CommandMode            = FMC_SDRAM_CMD_NORMAL_MODE;
	Command.CommandTarget          = FMC_SDRAM_CMD_TARGET_BANK2;
	Command.AutoRefreshNumber      = 1;
	Command.ModeRegisterDefinition = 0;
	if (HAL_SDRAM_SendCommand(&hsdram1, &Command, SDRAM_TIMEOUT) != HAL_OK)
	{
		printf("Errore: NORMAL MODE command failed\n");
		return HAL_ERROR;
	}
	printf("NORMAL OK \n");
	// STEP 6: Programma il refresh rate
	uint32_t refresh_count = 781;  // ˜ (64ms / 8192) * 100MHz - 20
	if (HAL_SDRAM_ProgramRefreshRate(&hsdram1, refresh_count) != HAL_OK)
	{
		printf("Errore: Refresh rate program failed\n");
		return HAL_ERROR;
	}
	printf(" Sequenza inizializzazione SDRAM completata correttamente\n");
	return HAL_OK;
}
10 REPLIES 10

No, nothing to change. 

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.
Saket_Om