2025-11-03 7:48 AM - last edited on 2025-11-03 7:55 AM by mƎALLEm
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;
}
2025-11-03 8:08 AM - edited 2025-11-03 8:14 AM
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.
2025-11-03 8:27 AM
Are you getting a Hard Fault?
The SysTick should be initialized in HAL_Init(), check why that's not working / initialized
2025-11-03 8:29 AM
It's initialized, so much so that I use it elsewhere too and it hasn't given me any problems