Skip to main content
Visitor II
November 3, 2025
Question

SDRAM FMC with STM32H7

  • November 3, 2025
  • 1 reply
  • 421 views

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;
}
    This topic has been closed for replies.

    1 reply

    Giovanni3Author
    Visitor II
    November 3, 2025

    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.

    Graduate II
    November 3, 2025

    Are you getting a Hard Fault?

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

    Giovanni3Author
    Visitor II
    November 3, 2025

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