Skip to main content
Lars Beiderbecke
Senior III
December 27, 2020
Solved

New SDRAM model does not work with STM32F7 (but old one does)

  • December 27, 2020
  • 6 replies
  • 3077 views

I've migrated to a new custom board, which uses a STM32F746IE and a new SDRAM model, NDS36PT5-20ET by Insignis. And although I could make a MT48LC16M16A2 by Micron work in the previous board, I have no luck with the Insignis SDRAM.

The Insignis SDRAM is rated for 200 MHz. I'm using a system clock of 200 MHz, so the SDRAM is clocked at 100 MHz. Based on the timings in the datasheet, I configured CubeMX like this:

0693W000006GvOuQAK.pngEach FMC cycle is 10 ns, so I divided the datasheet time by 10 ns and rounded up. The Write recovery time would be 1 cycle, but CubeMX sets this to 2. I also chose a CL of 3, since the datasheet doesn't list any Clock cycle time for CL 2.

Similarly, I initialize the SDRAM with this function in main():

static void SDRAM_Init()
{
 FMC_SDRAM_CommandTypeDef Command;
 
 __IO uint32_t tmpmrd =0;
 /* Step 3: Configure a clock configuration enable command */
 Command.CommandMode = FMC_SDRAM_CMD_CLK_ENABLE;
 Command.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
 Command.AutoRefreshNumber = 1;
 Command.ModeRegisterDefinition = 0;
 HAL_SDRAM_SendCommand(&hsdram1, &Command, SDRAM_TIMEOUT);
 
 /* Step 4: Insert 100 us minimum delay */
 /* Inserted delay is equal to 1 ms due to systick time base unit (ms) */
 HAL_Delay(1);
 
 /* Step 5: Configure a PALL (precharge all) command */
 Command.CommandMode = FMC_SDRAM_CMD_PALL;
 Command.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
 Command.AutoRefreshNumber = 1;
 Command.ModeRegisterDefinition = 0;
 HAL_SDRAM_SendCommand(&hsdram1, &Command, SDRAM_TIMEOUT);
 
 /* Step 6 : Configure a Auto-Refresh command */
 Command.CommandMode = FMC_SDRAM_CMD_AUTOREFRESH_MODE;
 Command.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
 Command.AutoRefreshNumber = 2; // Insignis SDRAM
 Command.ModeRegisterDefinition = 0;
 HAL_SDRAM_SendCommand(&hsdram1, &Command, SDRAM_TIMEOUT);
 
 /* Step 7: Program the external memory mode register */
 tmpmrd = (uint32_t)SDRAM_MODEREG_BURST_LENGTH_1 |
 SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL |
 SDRAM_MODEREG_CAS_LATENCY_3 |
 //SDRAM_MODEREG_CAS_LATENCY_2 |
 SDRAM_MODEREG_OPERATING_MODE_STANDARD |
 SDRAM_MODEREG_WRITEBURST_MODE_SINGLE;
 
 Command.CommandMode = FMC_SDRAM_CMD_LOAD_MODE;
 Command.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
 Command.AutoRefreshNumber = 1;
 Command.ModeRegisterDefinition = tmpmrd;
 HAL_SDRAM_SendCommand(&hsdram1, &Command, SDRAM_TIMEOUT);
 
 /* Step 8: Set the refresh rate counter: (64 ms / 8192 x Freq) - 20 */
 hsdram1.Instance->SDRTR |= ((uint32_t)761); // 2HCLK, Insignis SDRAM, 100 MHz
}

My quick and dirty test program

uint32_t i;
 for (i = 0; i < 16384; i += 2) {
 *(__IO uint16_t *) (SDRAM_BASE + i) = i & 0xffff;
 }
 
 for (i = 0; i < 16384; i += 2) {
 uint16_t data = *(__IO uint16_t *) (SDRAM_BASE + i);
 if (data != (i & 0xffff)) {
 while (1); // breakpoint here
 }
 }

shows an error when reading the first value: 0x3ffe instead of 0 (and that consistently).

To rule out any layout errors, I used the Insignis SDRAM in the older board, in which I got the Micron SDRAM to work. The Insignis still would not run with the old board (same error as in the new board).

For either board, what could be wrong with my configuration above?

This topic has been closed for replies.
Best answer by Lars Beiderbecke

Thanks for your info. You were right that something else is amiss.

I created a test project in CubeMX, where I only enabled FMC, in which case FMC_SDNE0 is assigned to PC2. But in my board design, PC2 was already assigned to GPIO_INPUT, so FMC_SDNE0 was assigned to PH3 -- I didn't realize that was even possible.

So the timing et al. is not the problem, but I was missing the enable signal to the SDRAM!

Thanks for your remark, that made me recheck my layout.

6 replies

Lars Beiderbecke
Senior III
December 29, 2020

Since I still don't know how to deal with the fact that the 200 MHz SDRAM IC is only clocked at 100 MHz, I tried to double all timings and recalculate the clocks needed in CubeMX. I couldn't enter the Write recovery time value of 2, since that violates the internal working of SDRAMs, and had to enter 5 instead.

Alas, my updated values still don't work; again, the 16-bit value at address 0xc0000000 is 0x3ffe instead of 0.

Tesla DeLorean
Guru
December 29, 2020

Likely something else amiss.

Make sure the GPIO's are NOT using an overly aggressive slew rate.

At 100 MHz is should take fewer cycles to hit minimum timing windows.

I have no personal experience with Insignis parts, or if this is a suitable drop-in replacement.

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
Lars Beiderbecke
Lars BeiderbeckeAuthorBest answer
Senior III
December 30, 2020

Thanks for your info. You were right that something else is amiss.

I created a test project in CubeMX, where I only enabled FMC, in which case FMC_SDNE0 is assigned to PC2. But in my board design, PC2 was already assigned to GPIO_INPUT, so FMC_SDNE0 was assigned to PH3 -- I didn't realize that was even possible.

So the timing et al. is not the problem, but I was missing the enable signal to the SDRAM!

Thanks for your remark, that made me recheck my layout.