Trouble with SDRAM and STM32F469
Hi all!
I am struggling to couple STM32F469ZGT6 (running at 180 MHz) with SDRAM type IS42S16160J-6TL from ISSI (datasheet here: https://www.issi.com/WW/pdf/42-45S83200J-16160J.pdf ).
SDRAM is organized in 4 banks, each having 8192 rows x 512 columns x 16 bits wide data bus, and is connected to MCU like this:

FMC is configured in CubeMX like this:

…following instructions from here: https://community.st.com/t5/stm32-mcus/how-to-set-up-the-fmc-peripheral-to-interface-with-the-sdram/ta-p/49457
FMC is initialized like this (part of the code was generated by CubeMX and part was manually added, following above instructions):
/* FMC initialization function */
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_BANK1;
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 = 7;
SdramTiming.SelfRefreshTime = 5;
SdramTiming.RowCycleDelay = 6;
SdramTiming.WriteRecoveryTime = 3;
SdramTiming.RPDelay = 2;
SdramTiming.RCDDelay = 2;
if (HAL_SDRAM_Init(&hsdram1, &SdramTiming) != HAL_OK)
{
Error_Handler( );
}
/* USER CODE BEGIN FMC_Init 2 */
FMC_SDRAM_CommandTypeDef Command;
/* Step 1 and Step 2 already done in HAL_SDRAM_Init() */
/* Step 3: Configure a clock configuration enable command */
Command.CommandMode = FMC_SDRAM_CMD_CLK_ENABLE; /* Set MODE bits to "001" */
Command.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1; /* <--FIXED THIS configure the Target Bank bits */
Command.AutoRefreshNumber = 1;
Command.ModeRegisterDefinition = 0;
HAL_SDRAM_SendCommand(&hsdram1, &Command, 0xfff);
HAL_Delay(1); /* Step 4: Insert 100 us minimum delay - Min HAL Delay is 1ms */
/* Step 5: Configure a PALL (precharge all) command */
Command.CommandMode = FMC_SDRAM_CMD_PALL; /* Set MODE bits to "010" */
HAL_SDRAM_SendCommand(&hsdram1, &Command, 0xfff);
/* Step 6: Configure an Auto Refresh command */
Command.CommandMode = FMC_SDRAM_CMD_AUTOREFRESH_MODE; /* Set MODE bits to "011" */
Command.AutoRefreshNumber = 8;///CHANGED: 2 -> 8/////////////////////////////////////////////////////////////////////////////////////////////////////////////
HAL_SDRAM_SendCommand(&hsdram1, &Command, 0xfff);
/* Step 7: Program the external memory mode register */
Command.CommandMode = FMC_SDRAM_CMD_LOAD_MODE;/*set the MODE bits to "100" */
Command.ModeRegisterDefinition = (uint32_t)0 | 0<<3 | 2<<4 | 0<<7 | 1<<9;
HAL_SDRAM_SendCommand(&hsdram1, &Command, 0xfff);
/* Step 8: Set the refresh rate counter - refer to section SDRAM refresh timer register in RM0455 */
/* Set the device refresh rate
* COUNT = [(SDRAM self refresh time / number of row) x SDRAM CLK] – 20
= [(64ms/8192) * 90MHz] - 20 = 703.125 - 20 ~ 683 */
HAL_SDRAM_ProgramRefreshRate(&hsdram1, 683);
/* USER CODE END FMC_Init 2 */
}
FMC should position SDRAM at address 0xC0000000.
After HAL initialization, I am running simple test code:
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* Configure the peripherals common clocks */
PeriphCommonClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_FMC_Init();
MX_I2C1_Init();
MX_QUADSPI_Init();
MX_RTC_Init();
MX_SDIO_SD_Init();
MX_SPI1_Init();
MX_SPI2_Init();
MX_USART1_UART_Init();
MX_USART2_UART_Init();
MX_USART3_UART_Init();
MX_USART6_UART_Init();
MX_USB_OTG_HS_PCD_Init();
MX_DAC_Init();
MX_ADC1_Init();
/* USER CODE BEGIN 2 */
uint32_t *pointer = (uint32_t *)0xC0000000;
*pointer = 0x111;
pointer +=1;
*pointer = 0x222;
pointer +=1;
*pointer = 0x333;
pointer = (uint32_t *)0xC0000000;
printf(" P1 = %d\r\n", *pointer);
pointer +=1;
printf(" P2 = %d\r\n", *pointer);
pointer +=1;
printf(" P3 = %d\r\n", *pointer);
.....
…. unfortunately this does not work. I get P1 = 0, P2 = 0, P3 = 0.
I was trying to solve my problem by searching the web.
There are a few suggestions which I came upon.
First, to modify scatter file, so my scatter file looks like this now:

; *************************************************************
; *** Scatter-Loading Description File generated by uVision ***
; *************************************************************
LR_IROM1 0x08000000 0x00100000 { ; load region size_region
ER_IROM1 0x08000000 0x00100000 { ; load address = execution address
*.o (RESET, +First)
*(InRoot$$Sections)
.ANY (+RO)
.ANY (+XO)
}
RW_IRAM1 0x20000000 0x00050000 { ; RW data
.ANY (+RW +ZI)
}
RW_IRAM2 0x10000000 0x00010000 {
.ANY (+RW +ZI)
}
; External SDRAM
EXT_SDRAM 0xC0000000 UNINIT 0x200 {
.ANY (+RW)
}
}
…here I added uninitialized memory area “EXT_SDRAM” length of only 0x200, just for the test. This did not help.
Fun fact: When I increase length to 0x2000000 my I2C HAL initialization fails on this line of code:
/* Check the minimum allowed PCLK1 frequency */
if (I2C_MIN_PCLK_FREQ(pclk1, hi2c->Init.ClockSpeed) == 1U)
{
return HAL_ERROR;
}
…..i still have to investigate this behaviour. So far no clue.
Not to diverge from the main problem, main point is with value 0x200 I don’t have faults, but my test code is returning zeros. Used SDRAM has size 32 Mb = 33.554.432 Bytes ( 0x2000000)= 268.435.456 bits.
…..further googling led me to discovery that my system_stm32f4xx.c has commented this line
here /* #define DATA_IN_ExtSDRAM */ , which should be uncommented.
So I uncommented it.
Unfortunately to no avail. Test code still returns zeroes.
This uncommenting enabled ruining of following function: void SystemInit_ExtMemCtl(void)
….which has following lines:
...
/* Connect PDx pins to FMC Alternate function */
GPIOD->AFR[0] = 0x000000CC;
GPIOD->AFR[1] = 0xCC000CCC;
/* Configure PDx pins in Alternate function mode */
GPIOD->MODER = 0xA02A000A;
/* Configure PDx pins speed to 50 MHz */
GPIOD->OSPEEDR = 0xA02A000A;
/* Configure PDx pins Output type to push-pull */
GPIOD->OTYPER = 0x00000000;
/* No pull-up, pull-down for PDx pins */
GPIOD->PUPDR = 0x00000000;
...
…I find it strange that frequency 50 MHz is mentioned here. My SDRAM will receive clock HCLK/2 = 90 Mhz. I still need to investigate what is going on here.
I am beginning to run out of ideas what to do next, and am digging deeper and deeper into countless pages of ARM, SMT32, KEIL’s manual, without any breakthroughs.
Does anybody see what went wrong here, and what to try next?
By looking this guy https://www.youtube.com/watch?v=h28D4AaPSjg I get the impression SDRAM interfacing is plug and play. I (or he) must have missed something.
