cancel
Showing results for 
Search instead for 
Did you mean: 

STM32 SDRAM Access Results In HardFault

ÇSerp.1
Associate II

Hello, 

I am using STM32F469BIT with W9812G6KH-6I TR SDRAM and no matter what I did, I could not write to or read from SDRAM since MCU goes into hardfault whenever i want to access SDRAM. I configured FMC according to this article. I am running SDRAM @84MHz and here's my configuration:

 

Serp1_3-1738654394171.png

 

According to the datasheet:

There are 4 banks. 12 address pins and 16 data bits. Also there are UDQM and LDQM pins so i set 16 bit byte enable. 

 

Number of column address bits: 512 column, 9 bit

Number of row address bits: 4096 row, 12 bit

CAS Latency: 3 for 166MHz operation. I run my SDRAM @84MHz.

 

84MHz period: 11.9047619 ns

 

Load mode register active delay: tRSC: 2 clock cycle

Exit self-refresh delay: tXSR: 72ns / 11.9 = 6.05. I set it as 7

Self-refresh time: tRAS: 42ns / 11.9 = 3.52. I set it as 4

SDRAM common row cycle delay: tRC: 60ns / 11.9 = 5.04 = I set it as 6

Write recovery time: tWR: 2 clock cycles

SDRAM common row precharge delay: 15ns / 11.9 = 1.26. I set it as 2

Row to column delay: 15ns / 11.9 = 1.26. I set it as 2

 

After that configuration, I wrote the SDRAM initialization sequence according to the article:

 

 /* 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_BANK2; /* configure the Target Bank bits */
   Command.AutoRefreshNumber      = 1;
   Command.ModeRegisterDefinition = 0;
   HAL_SDRAM_SendCommand(&hsdram2, &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(&hsdram2, &Command, 0xfff);
   /* Step 6: Configure an Auto Refresh command */
   Command.CommandMode            = FMC_SDRAM_CMD_AUTOREFRESH_MODE; /* Set MODE bits to "011" */
   Command.AutoRefreshNumber      = 2;
   HAL_SDRAM_SendCommand(&hsdram2, &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(&hsdram2, &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/4096) * 100MHz] - 20 = 1562.5 - 20 ~ 1542 */
   HAL_SDRAM_ProgramRefreshRate(&hsdram2, 1292);
  /* USER CODE END FMC_Init 2 */

 

 

My SDRAM traces are using 3 bottom side layers of the PCB. At the very bottom (L6) and at layer 4, there are my SDRAM traces. L5 is used solid ground reference. Here are my trace lengths (in mils):

 

SDRAM_D7852.581
SDRAM_D111039.912
SDRAM_D51132.215
SDRAM_D91262.056
SDRAM_D101275.214
SDRAM_D41349.673
SDRAM_D61360.237
SDRAM_D81411.807
SDRAM_D121518.199
SDRAM_D141559.54
SDRAM_D131611.611
SDRAM_D151820.164
SDRAM_D11828.286
SDRAM_A101977.895
SDRAM_A72220.33
SDRAM_SDCLK2242.717
SDRAM_D02287.159
SDRAM_BA02332.913
SDRAM_A112350.832
SDRAM_SDNRAS2441.158
SDRAM_BA12466.166
SDRAM_A92526.322
SDRAM_D22563.21
SDRAM_A82604.551
SDRAM_SDNE2629.602
SDRAM_A62672.078
SDRAM_D32894.197
SDRAM_SDNCAS3008.92
SDRAM_A33367.106
SDRAM_A03637.23
SDRAM_A23613.267
SDRAM_NBL03637.636
SDRAM_NBL13649.59
SDRAM_A13674.717
SDRAM_A43817.872
SDRAM_SDNWE3924.864
SDRAM_A54001.376
SDRAM_SDCKE4026.356

 

After all these configurations, i wrote this code to test the SDRAM:

 

 

uint32_t *externalRAM = (uint32_t*)0xC000000;
const uint32_t size = 16 * 1024 * 1024; //16MB

  /* USER CODE BEGIN 2 */
	//write external RAM
	for (uint32_t i = 0; i < size; i++) {
		externalRAM[i] = i % 256;
	}

	//read external RAM
	for (uint32_t i = 0; i < size; i++) {
		if (externalRAM[i] != i % 256) {
			asm("nop");
			// insert error handling logic here
		}
	}
  /* USER CODE END 2 */

 

 

I set a breakpoint at externalRAM[i] = i % 256; and when I execute the code, I get hardfault.

I can see the clock generated for SDRAM is exactly 84MHz on the oscilloscope.

 

Serp1_2-1738654169518.png

 

I don't know what am i doing wrong. We designed a board with STM32H723 before with IS42S16400J-5TL SDRAM and it also did not work but when i soldered STM32F429, the SDRAM just worked fine. Since these MCU's are not pin compatible, we had to revise the board but we did not touched any SDRAM lines because they were already pin to pin and with STM32f429, it worked just fine.

 

Serp1_0-1738655046761.jpeg

 

The issue on the previous board was definitely not caused by the PCB; otherwise, the second MCU wouldn’t have worked properly. I don't think on the new board the problem is caused by the PCB but I don't know how to debug such a problem. Any help would greatly appreciated.

1 REPLY 1
ÇSerp.1
Associate II

UPDATE

My screenshot from oscilloscope was bandwidth limited. Actual clock signal is down below

 

SDS00005.png