cancel
Showing results for 
Search instead for 
Did you mean: 

Data is written to SDRAM at the correct address and at a wrong address with 32 byte offset simultaneously. What could be the reason for this?

Jan1
Associate II

Hello,

I have an STM32F746 in an own PCB design. A 128 Mb DRAM IS42S32400F is connected to the FMC pins, similar as on the STM32F746G-DISCO board. I can write and read data but there are errors which occur in a systematic way:

I start writing 16 bit data at address 0xC000 0000.

Data is stored at the the correct address. But, the strange thing is that the same data appears simultaneously at a second location either 32 byte above or below the intended address. How can this happen? How can data be stored at two locations with one write command?

A memory dump screenshot is attached.

I have double-checked all connections and fiddled with timing - but no success.

In my design I didn't care about matched trace lengths. Controller and SDRAM are about 4 cm apart. Could this be a reason?

I can also observe the same problem on an LCD sreen since the SDRAM is also my frame buffer.

The test loop is very simple:

while (1)

   {

       *(uint16_t*) (LCD_FB_START_ADDRESS + 2 + (2 * (y * 800 + x))) = x;

       x++;

       if (x == 800)

       {

           x = 0;

           y++;

           if (y == 480)

               y = 0;

       }

       HAL_Delay(1);

   }

I hope that anyone can give me a hint. I'm new in the STM32.

Regards

Jan

15 REPLIES 15

>>How can this happen?

One of the address pins is screwed up, ie stuck at one/zero, not connected, not configured, etc.

Turn off caching while testing.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Jan1
Associate II

Thank you, Clive Two.Zero,

I checked again the connections and the signals on the 12 address lines. All of them look normal. The error also happens in the same way if I use an other memory section.

Turning off the cache did not change anything.

I agree with you that there must be some logical reason (no timing or signal delay problem) since the error is absolutely reproducible. It even looks the same at 50 or 100 MHz clock.

Data is written at 3 locations simultaneously: at the intended address, 20h above or below and 2000h above. But may be I'm wrong and it is written correctly and read wrongly?

I'm afraid there is some difference between the MT48LC4M32 of the original application and my IS42S32400F memory. Has anyone used the IS42S32400F with the FMC?

Regards

Jan

It is more probably read back wrongly.

Rather than hope someone turns up with the same chip and configuration, perhaps post the pin/peripheral initialization code, and circuit specifics, for review.

Presumably the DISCO works fine with equivalent configuration.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Jan1
Associate II

Yes, DISCO works fine with the same project, except that SDCKE0/SDNE0 are moved from PH2/PC2 to PH3/PC3.

This is my setup for FMC and SDRAM:

/* FMC initialization */
void FMC_Init(void)
{
  FMC_SDRAM_TimingTypeDef SdramTiming;
  //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_8;
  hsdram1.Init.RowBitsNumber = FMC_SDRAM_ROW_BITS_NUM_12;
  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_3;
  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_0;
  /* SdramTiming */
  SdramTiming.LoadToActiveDelay = 2;
  SdramTiming.ExitSelfRefreshDelay = 7;
  SdramTiming.SelfRefreshTime = 4;
  SdramTiming.RowCycleDelay = 7;
  SdramTiming.WriteRecoveryTime = 3;
  SdramTiming.RPDelay = 2;
  SdramTiming.RCDDelay = 2;
  if (HAL_SDRAM_Init(&hsdram1, &SdramTiming) != HAL_OK)
  {
    Error_Handler( );
  }
}
/* SDRAM initialization */
void SDRAM_Init(uint32_t RefreshCount)
{
  uint32_t  tmpmrd =0;
  /* Step 1:  Configure a clock configuration enable command */
  Command.CommandMode             = FMC_SDRAM_CMD_CLK_ENABLE;	//CKE
  Command.CommandTarget           = FMC_SDRAM_CMD_TARGET_BANK1;
  Command.AutoRefreshNumber       = 1;
  Command.ModeRegisterDefinition  = 0;
  HAL_SDRAM_SendCommand(&hsdram1, &Command, SDRAM_TIMEOUT); 	 /* Send the command */
  /* Step 2: Insert 100 us minimum delay */
  /* Inserted delay is equal to 1 ms due to systick time base unit (ms) */
  HAL_Delay(1);
  /* Step 3: 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);     /* Send the command */
  /* Step 4: Configure an Auto Refresh command */
  Command.CommandMode             = FMC_SDRAM_CMD_AUTOREFRESH_MODE;
  Command.CommandTarget           = FMC_SDRAM_CMD_TARGET_BANK1;
  Command.AutoRefreshNumber       = 8;
  Command.ModeRegisterDefinition  = 0;
  HAL_SDRAM_SendCommand(&hsdram1, &Command, SDRAM_TIMEOUT);     /* Send the command */
  /* Step 5: Program the external memory mode register */
  tmpmrd = (uint32_t)SDRAM_MODEREG_BURST_LENGTH_1          |
                     SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL   |
                     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);     /* Send the command */
  /* Step 6: Set the refresh rate counter */
  HAL_SDRAM_ProgramRefreshRate(&hsdram1, RefreshCount);	        /* Set the device refresh rate */
}

... and the FMC port settings:

static void HAL_FMC_MspInit(void)
{
  GPIO_InitTypeDef GPIO_InitStruct;
  if (FMC_Initialized) {
    return;
  }
  FMC_Initialized = 1;
  __HAL_RCC_FMC_CLK_ENABLE();   /* Peripheral clock enable */
  /** FMC GPIO Configuration  
  PF0   ------> FMC_A0
  PF1   ------> FMC_A1
  PF2   ------> FMC_A2
  PF3   ------> FMC_A3
  PF4   ------> FMC_A4
  PF5   ------> FMC_A5
  PC2   ------> FMC_SDNE0
  PH2   ------> FMC_SDCKE0
  PH5   ------> FMC_SDNWE
  PF11   ------> FMC_SDNRAS
  PF12   ------> FMC_A6
  PF13   ------> FMC_A7
  PF14   ------> FMC_A8
  PF15   ------> FMC_A9
  PG0   ------> FMC_A10
  PG1   ------> FMC_A11
  PE7   ------> FMC_D4
  PE8   ------> FMC_D5
  PE9   ------> FMC_D6
  PE10   ------> FMC_D7
  PE11   ------> FMC_D8
  PE12   ------> FMC_D9
  PE13   ------> FMC_D10
  PE14   ------> FMC_D11
  PE15   ------> FMC_D12
  PD8   ------> FMC_D13
  PD9   ------> FMC_D14
  PD10   ------> FMC_D15
  PD14   ------> FMC_D0
  PD15   ------> FMC_D1
  PG4   ------> FMC_BA0
  PG5   ------> FMC_BA1
  PG8   ------> FMC_SDCLK
  PD0   ------> FMC_D2
  PD1   ------> FMC_D3
  PG15   ------> FMC_SDNCAS
  PE0   ------> FMC_NBL0
  PE1   ------> FMC_NBL1
  */
  GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
  GPIO_InitStruct.Alternate = GPIO_AF12_FMC;
  HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
 
  GPIO_InitStruct.Pin = GPIO_PIN_2;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
  GPIO_InitStruct.Alternate = GPIO_AF12_FMC;
  HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
 
  GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_5;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
  GPIO_InitStruct.Alternate = GPIO_AF12_FMC;
  HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);
 
  GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_8|GPIO_PIN_15;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
  GPIO_InitStruct.Alternate = GPIO_AF12_FMC;
  HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);
 
  GPIO_InitStruct.Pin = GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_0|GPIO_PIN_1;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
  GPIO_InitStruct.Alternate = GPIO_AF12_FMC;
  HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
 
  GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_0|GPIO_PIN_1;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
  GPIO_InitStruct.Alternate = GPIO_AF12_FMC;
  HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
}

I have also attached the relevant parts of schematic and PCB.

Any help would be appreciated.

Regards

Jan

0690X000006DgnKQAS.png0690X000006DgnFQAS.png

Jan1
Associate II

Just to close this topic, I replaced the IS42S32400F by a MT48LC4M32B2P and everything works fine - without knowing why.

DM.7
Associate III

I have found a very similar problem to this, but the duplication was once, 1MB up the SRAM. Stepping through the disassembly, I would see it doing a store to an address 0xC0035B10, but that value would also "get written" to 0xC0135B10.

I am still debugging it, but I have found that disabling instruction access to a different memory region in the MPU has stopped it happening. Disabling the cache also stopped it happening for me. Unfortunately, no MPU config above.

It is on an H747 with IS42S32160D. I will also try repeating it on the Disco board to see if it is the same.

It's is unlikely to be writing to TWO locations. What's more probable is that it writes to ONE location, and TWO locations decoded to that same location.

The span here 0x100000 (1MB) suggests internal address bit A20 isn't decoded properly. Perhaps stuck at one, or stuck at zero, or just disconnected completely.

Check how the FMC is configured, and the pins. Perhaps double check the netlist, and probe continuity on a test PCB

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
DM.7
Associate III

The fact that I can change 1 bit in the program and the behaviour goes away, I think, suggests that it is not an obvious hardware problem like an address bit being stuck. I can read and write to both locations in the fixed version so the functionality is there.

Perhaps you can create a compelling working / failing case so the engineers at ST can understand what's happening, or where the problem is.

Not sure why the cache should create a wrap-around issue. The 32-byte issue the OP mentioned might relate to the cache line width, but not clear how that would get tagged into two distinct address spaces.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..