Duplicate write to external SDRAM
Hello,
I am using STM32F469 with an external SDRAM (Alliance AS4C16M16MSA-6BIN) through FMC bus. Both STM32F469 and AS4C16M16MSA-6BIN run at 1.8V. The FMC bus is configured with 13 address pins and 16 data pins as follows:
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_3;
hsdram1.Init.WriteProtection = FMC_SDRAM_WRITE_PROTECTION_DISABLE;
hsdram1.Init.SDClockPeriod = FMC_SDRAM_CLOCK_PERIOD_2;
hsdram1.Init.ReadBurst = FMC_SDRAM_RBURST_DISABLE;
hsdram1.Init.ReadPipeDelay = FMC_SDRAM_RPIPE_DELAY_1;
/* Timing configuration for 75 MHz of SDRAM clock frequency () */
SdramTiming.LoadToActiveDelay = 2;
SdramTiming.ExitSelfRefreshDelay = 7;
SdramTiming.SelfRefreshTime = 4;
SdramTiming.RowCycleDelay = 7;
SdramTiming.WriteRecoveryTime = 2;
SdramTiming.RPDelay = 2;
SdramTiming.RCDDelay = 2;And SDRAM is configured as:
__IO uint32_t tmpmrd = 0;
/* Step 1: 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;
/* Send the command */
HAL_SDRAM_SendCommand(&hsdram1, &Command, SDRAM_TIMEOUT);
/* 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;
/* Send the command */
HAL_SDRAM_SendCommand(&hsdram1, &Command, SDRAM_TIMEOUT);
/* Step 4: Configure an Auto Refresh command */
Command.CommandMode = FMC_SDRAM_CMD_AUTOREFRESH_MODE;
Command.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
Command.AutoRefreshNumber = 4;
Command.ModeRegisterDefinition = 0;
/* Send the command */
HAL_SDRAM_SendCommand(&hsdram1, &Command, SDRAM_TIMEOUT);
/* 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_3 |\
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;
/* Send the command */
HAL_SDRAM_SendCommand(&hsdram1, &Command, SDRAM_TIMEOUT);
/* Step 6: Set the refresh rate counter */
/* Set the device refresh rate */
HAL_SDRAM_ProgramRefreshRate(&hsdram1, RefreshCount);I am running a address bus test on the SDRAM.
datum *
BSP_SDRAM_MemTestAddressBus(volatile datum * baseAddress, uint32_t nBytes)
{
uint32_t addressMask = (nBytes/sizeof(datum) - 1);
uint32_t offset;
uint32_t testoffset;
datum pattern = (datum) 0xAAAAAAA;
datum antipattern = (datum) 0x55555555;
/*
* Write the default pattern at each of power-of-two offsets
* */
for (offset = 1; (offset & addressMask) != 0; offset ++)
{
*(__IO uint32_t*) (SDRAM_DEVICE_ADDR + 4*offset) = pattern;
}
/*
* Write the default pattern at each of power-of-two offsets
* */
for (offset = 1; (offset & addressMask) != 0; offset <<= 1)
{
baseAddress[offset] = pattern;
}
/*
* Check for address bits stuck high.
* */
testoffset = 2;
baseAddress[testoffset] = antipattern;
for (offset = 1; (offset & addressMask) != 0; offset <<= 1)
{
if (baseAddress[offset] != pattern)
{
return ((datum *) &baseAddress[offset]);
}
}
baseAddress[testoffset] = pattern;
/*
* Check for address bits stuck low or shorted.
* */
for (testoffset = 1; (testoffset & addressMask) !=0; testoffset <<=1)
{
baseAddress[testoffset] = antipattern;
if (baseAddress[0] != pattern)
{
return ((datum *) &baseAddress[testoffset]);
}
for (offset = 1; (offset & addressMask) != 0; offset <<=1)
{
if ((baseAddress[offset] != pattern) && (offset != testoffset))
{
return ((datum *) &baseAddress[testoffset]);
}
}
baseAddress[testoffset] = pattern;
}
return (NULL);
}/* memTestAddressBus() */The problem is, when one address is accessed, it always duplicates the operation to another address location. The memory reading is as follows:
I simply wrote 0xAAAAAAA to the location 0xC00000004 and the data in 0xC0000000C updated at the same time.
Any suggestion on this issue? Thanks in advance.
