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

Hello @Giovanni3 

Did you configure a hardware timer for HAL time base instead of systick?

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

Giovanni3_0-1762269768887.png

do you mean here?

Hello @Giovanni3 

Yes ! 

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

you say to define it as sys instead like any other unused timer? like Tim1?

No, it should be one of the timers like TIM6 for example. 

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

Do I have to change anything on the code side?