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;
}
3 REPLIES 3
Giovanni3
Associate II

I solved it by replacing Hal_delay with OsDelay, however I can't write to SDRAM. When I try to copy something to the defined address 0xD0000000, the program crashes and doesn't continue. I'm using the default mapping, but I also tried the other addresses 0xC0000000 and 0x70000000, but nothing works.
I noticed that I'm also having problems with Hal_Delay. How do I fix it? The code gets stuck if I use HAl_Delay.

Are you getting a Hard Fault?

The SysTick should be initialized in HAL_Init(), check why that's not working / initialized

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

It's initialized, so much so that I use it elsewhere too and it hasn't given me any problems