I designed a board which is containing two SDRAM (IS42S16320F: www .kynix. com/Parts/231117/IS42S16320F-6BL.html) and STM32F476ZIT6 MCU (and other components also). I can access the SDRAM but the data is changing independently from the code. My board has six layers and distance between RAM and MCU is just 2.8cm. And there is also another high speed components on the board. Anyway, I've solder the RAM, series resistors (22R), MCU, and power components to debug the board then I realized this issue. Here is my schematic, layer stack-up, trace lengths and code;
Trace lengths in mm;
I've just soldered the U5 and it is in second SDRAM interface in FMC that mean FMC_Bank2_SDRAM so it's address is 0xD0000000. Here is my initialization and read/write codes;
Data is not same with the written value while reading. And in the endless loop the data is changing independently. Is there a problem with refreshing/timing values or initialization sequence of SDRAM. Here is the link of the SDRAM www .issi. com/WW/pdf/42-45R-S_86400F-16320F.pdf. Thanks in advance any help.
Trace lengths in mm;
Code:
Data Bus Trace Lengths | Address Bus Trace Lengths | Control Traces Lengths
D0 = 39,998 | A0 = 50,301 | CKE = 53,983
D1 = 27,51 | A1 = 49,345 | CLK = 44,827
D2 = 46,56 | A2 = 49,567 | NRAS = 50,664
D3 = 50,625 | A3 = 48,266 | NCAS = 46,541
D4 = 46,072 | A4 = 42,726 | NE = 55,028
D5 = 46,629 | A5 = 43,585 | NWRE = 51,462
D6 = 46,61 | A6 = 44,654 | NBL0 = 51,449
D7 = 42,588 | A7 = 47,963 | NBL1 = 61,992
D8 = 42,862 | A8 = 49,552 | BA0 = 30,563
D9 = 39,407 | A9 = 48,685 | BA1 = 30,449
D10 = 36,655 | A10 = 47,991
D11 = 33,025 | A11 = 52,05
D12 = 30,672 | A12 = 39,684
D13 = 24,976
D14 = 23,563
D15 = 21,279
I've just soldered the U5 and it is in second SDRAM interface in FMC that mean FMC_Bank2_SDRAM so it's address is 0xD0000000. Here is my initialization and read/write codes;
Code:
/** ****************************************************************************
* @brief Configures all SDRAM memory I/Os pins.
* @param None.
* @retval None.
* @note Used pins from MCU for PHD;
*
+------------------------------------------------------------------------------+
| SDRAM Pins Assignment |
+------------------+-------------------+-------------------+-------------------+
| PD0 <-> FMC_D2 | PE0 <-> FMC_NBL0 | PF0 <-> FMC_A0 | PG0 <-> FMC_A10 |
| PD1 <-> FMC_D3 | PE1 <-> FMC_NBL1 | PF1 <-> FMC_A1 | PG1 <-> FMC_A11 |
| PD8 <-> FMC_D13 | PE7 <-> FMC_D4 | PF2 <-> FMC_A2 | PG4 <-> FMC_BA0 |
| PD9 <-> FMC_D14 | PE8 <-> FMC_D5 | PF3 <-> FMC_A3 | PG5 <-> FMC_BA1 |
| PD10 <-> FMC_D15 | PE9 <-> FMC_D6 | PF4 <-> FMC_A4 | PG8 <-> FMC_SDCLK|
| PD14 <-> FMC_D0 | PE10 <-> FMC_D7 | PF5 <-> FMC_A5 | PG15 <-> FMC_NCAS |
| PD15 <-> FMC_D1 | PE11 <-> FMC_D8 | PF11 <-> FMC_NRAS |-------------------+
+------------------| PE12 <-> FMC_D9 | PF12 <-> FMC_A6 |
| PE13 <-> FMC_D10 | PF13 <-> FMC_A7 |
| PE14 <-> FMC_D11 | PF14 <-> FMC_A8 |
| PE15 <-> FMC_D12 | PF15 <-> FMC_A9 |
+-------------------+-------------------+
| PB5 <-> FMC_SDCKE1 | -> SDRAM_U2
| PB6 <-> FMC_SDNE1 | -> SDRAM_U2
| PC3 <-> FMC_SDCKE0 | -> SDRAM_U1
| PC2 <-> FMC_SDNE0 | -> SDRAM_U1
| PC0 <-> FMC_SDNWE | -> COMMON
+---------------------------------------+
* ****************************************************************************
*/
void SDRAM_GPIOInit(void)
{
GPIO_InitTypeDef gpio;
/* Enable all GPIO port clocks */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC |
RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_GPIOD |
RCC_AHB1Periph_GPIOE | RCC_AHB1Periph_GPIOF |
RCC_AHB1Periph_GPIOG, ENABLE);
/* Common GPIO configuration */
gpio.GPIO_Mode = GPIO_Mode_AF;
gpio.GPIO_Speed = GPIO_Speed_50MHz;
gpio.GPIO_OType = GPIO_OType_PP;
gpio.GPIO_PuPd = GPIO_PuPd_NOPULL;
/* GOIOB configuration */
GPIO_PinAFConfig(GPIOB, GPIO_PinSource5, GPIO_AF_FMC);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_FMC);
gpio.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6;
GPIO_Init(GPIOB, &gpio);
/* GPIOC configuration */
GPIO_PinAFConfig(GPIOC, GPIO_PinSource0, GPIO_AF_FMC);
GPIO_PinAFConfig(GPIOC, GPIO_PinSource2, GPIO_AF_FMC);
GPIO_PinAFConfig(GPIOC, GPIO_PinSource3, GPIO_AF_FMC);
gpio.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_2 | GPIO_Pin_3;
GPIO_Init(GPIOC, &gpio);
/* GPIOD configuration */
GPIO_PinAFConfig(GPIOD, GPIO_PinSource0, GPIO_AF_FMC);
GPIO_PinAFConfig(GPIOD, GPIO_PinSource1, GPIO_AF_FMC);
GPIO_PinAFConfig(GPIOD, GPIO_PinSource8, GPIO_AF_FMC);
GPIO_PinAFConfig(GPIOD, GPIO_PinSource9, GPIO_AF_FMC);
GPIO_PinAFConfig(GPIOD, GPIO_PinSource10, GPIO_AF_FMC);
GPIO_PinAFConfig(GPIOD, GPIO_PinSource14, GPIO_AF_FMC);
GPIO_PinAFConfig(GPIOD, GPIO_PinSource15, GPIO_AF_FMC);
gpio.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_8 |
GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_14 |
GPIO_Pin_15;
GPIO_Init(GPIOD, &gpio);
/* GPIOE configuration */
GPIO_PinAFConfig(GPIOE, GPIO_PinSource0, GPIO_AF_FMC);
GPIO_PinAFConfig(GPIOE, GPIO_PinSource1, GPIO_AF_FMC);
GPIO_PinAFConfig(GPIOE, GPIO_PinSource7, GPIO_AF_FMC);
GPIO_PinAFConfig(GPIOE, GPIO_PinSource8, GPIO_AF_FMC);
GPIO_PinAFConfig(GPIOE, GPIO_PinSource9, GPIO_AF_FMC);
GPIO_PinAFConfig(GPIOE, GPIO_PinSource10, GPIO_AF_FMC);
GPIO_PinAFConfig(GPIOE, GPIO_PinSource11, GPIO_AF_FMC);
GPIO_PinAFConfig(GPIOE, GPIO_PinSource12, GPIO_AF_FMC);
GPIO_PinAFConfig(GPIOE, GPIO_PinSource13, GPIO_AF_FMC);
GPIO_PinAFConfig(GPIOE, GPIO_PinSource14, GPIO_AF_FMC);
GPIO_PinAFConfig(GPIOE, GPIO_PinSource15, GPIO_AF_FMC);
gpio.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | 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_Init(GPIOE, &gpio);
/* GPIOF configuration */
GPIO_PinAFConfig(GPIOF, GPIO_PinSource0, GPIO_AF_FMC);
GPIO_PinAFConfig(GPIOF, GPIO_PinSource1, GPIO_AF_FMC);
GPIO_PinAFConfig(GPIOF, GPIO_PinSource2, GPIO_AF_FMC);
GPIO_PinAFConfig(GPIOF, GPIO_PinSource3, GPIO_AF_FMC);
GPIO_PinAFConfig(GPIOF, GPIO_PinSource4, GPIO_AF_FMC);
GPIO_PinAFConfig(GPIOF, GPIO_PinSource5, GPIO_AF_FMC);
GPIO_PinAFConfig(GPIOF, GPIO_PinSource11, GPIO_AF_FMC);
GPIO_PinAFConfig(GPIOF, GPIO_PinSource12, GPIO_AF_FMC);
GPIO_PinAFConfig(GPIOF, GPIO_PinSource13, GPIO_AF_FMC);
GPIO_PinAFConfig(GPIOF, GPIO_PinSource14, GPIO_AF_FMC);
GPIO_PinAFConfig(GPIOF, GPIO_PinSource15, GPIO_AF_FMC);
gpio.GPIO_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_Init(GPIOF, &gpio);
/* GPIOG configuration */
GPIO_PinAFConfig(GPIOG, GPIO_PinSource0, GPIO_AF_FMC);
GPIO_PinAFConfig(GPIOG, GPIO_PinSource1, GPIO_AF_FMC);
GPIO_PinAFConfig(GPIOG, GPIO_PinSource8, GPIO_AF_FMC);
GPIO_PinAFConfig(GPIOG, GPIO_PinSource15, GPIO_AF_FMC);
gpio.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_8 |
GPIO_Pin_15;
GPIO_Init(GPIOG, &gpio);
}
void SDRAM_InitSequence(uint32_t target_bank, uint32_t fmc_bank)
{
__IO FMC_SDRAMCommandTypeDef sdCMD;
__IO uint32_t tmp;
/* Configure a clock configuration enable command */
sdCMD.FMC_CommandMode = FMC_Command_Mode_CLK_Enabled;
sdCMD.FMC_CommandTarget = target_bank;
sdCMD.FMC_AutoRefreshNumber = 1;
sdCMD.FMC_ModeRegisterDefinition = 0;
/* Wait until the SDRAM controller is ready */
while(FMC_GetFlagStatus(fmc_bank, FMC_FLAG_Busy) != RESET)
{}
/* Send the command */
FMC_SDRAMCmdConfig(&sdCMD);
/* Insert a 100ms delay */
Delay(100);
/* Configure a PALL (precharge all) command */
sdCMD.FMC_CommandMode = FMC_Command_Mode_PALL;
sdCMD.FMC_CommandTarget = target_bank;
sdCMD.FMC_AutoRefreshNumber = 1;
sdCMD.FMC_ModeRegisterDefinition = 0;
/* Wait until the SDRAM controller is ready */
while(FMC_GetFlagStatus(fmc_bank, FMC_FLAG_Busy) != RESET)
{}
/* Send the command */
FMC_SDRAMCmdConfig(&sdCMD);
/* Configure a Auto-Refresh command */
sdCMD.FMC_CommandMode = FMC_Command_Mode_AutoRefresh;
sdCMD.FMC_CommandTarget = target_bank;
sdCMD.FMC_AutoRefreshNumber = 1;
sdCMD.FMC_ModeRegisterDefinition = 0;
/* Wait until the SDRAM controller is ready */
while(FMC_GetFlagStatus(fmc_bank, FMC_FLAG_Busy) != RESET)
{}
/* Send the first command */
FMC_SDRAMCmdConfig(&sdCMD);
/* Wait until the SDRAM controller is ready */
while(FMC_GetFlagStatus(fmc_bank, FMC_FLAG_Busy) != RESET)
{}
/* Send the second command */
FMC_SDRAMCmdConfig(&sdCMD);
/* Program the external memory mode register */
tmp = (uint32_t)SDRAM_MODEREG_BURST_LENGTH_2 |
SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL |
SDRAM_MODEREG_CAS_LATENCY_3 |
SDRAM_MODEREG_OPERATING_MODE_STANDARD |
SDRAM_MODEREG_WRITEBURST_MODE_SINGLE;
/* Configure a Load Mode Register command */
sdCMD.FMC_CommandMode = FMC_Command_Mode_LoadMode;
sdCMD.FMC_CommandTarget = target_bank;
sdCMD.FMC_AutoRefreshNumber = 1;
sdCMD.FMC_ModeRegisterDefinition = tmp;
/* Wait until the SDRAM controller is ready */
while(FMC_GetFlagStatus(fmc_bank, FMC_FLAG_Busy) != RESET)
{}
/* Send the command */
FMC_SDRAMCmdConfig(&sdCMD);
/* Set the refresh rate counter */
/* 64ms/8192=7,81us; ((7,81 x Freq) - 20) = 683 */
/* Save the device refresh counter */
FMC_SetRefreshCount(683);
/* Wait until SDRAM controller is ready */
while(FMC_GetFlagStatus(fmc_bank, FMC_FLAG_Busy) != RESET)
{}
}
void SDRAM_Init(void)
{
FMC_SDRAMInitTypeDef SDRAM;
FMC_SDRAMTimingInitTypeDef Timing;
/* Configure the GPIO for FMC Bank */
SDRAM_GPIOInit();
/* Enable FMC clock */
RCC_AHB3PeriphClockCmd(RCC_AHB3Periph_FMC, ENABLE);
/* FMC Configuration */
/* FMC SDRAM Bank Configuration */
/* Timing configuration for 90 MHz of SD Clock frequency (180MHz / 2) */
/* TMRD: 2 cycle */
Timing.FMC_LoadToActiveDelay = 2;
/* TXSR: min 67ns (7x11.11ns) */
Timing.FMC_ExitSelfRefreshTime = 7;
/* TRAS: min 37ns (4x11.11ns) max 100000ns */
Timing.FMC_SelfRefreshTime = 4;
/* TRC: min 8cycle */
Timing.FMC_RowCycleDelay = 8;
/* TWR: min 14ns (2x11.11ns) */
Timing.FMC_WriteRecoveryTime = 2;
/* TRP: 20ns (2x11.11ns) */
Timing.FMC_RPDelay = 2;
/* TRCD: 20ns (2x11.11ns) */
Timing.FMC_RCDDelay = 2;
/* FMC SDRAM control configuration */
SDRAM.FMC_Bank = FMC_Bank2_SDRAM;
/* Row addressing [9:0] */
SDRAM.FMC_ColumnBitsNumber = FMC_ColumnBits_Number_10b;
/* Column addressing [12:0] */
SDRAM.FMC_RowBitsNumber = FMC_RowBits_Number_13b;
SDRAM.FMC_SDMemoryDataWidth = FMC_SDMemory_Width_16b;
SDRAM.FMC_InternalBankNumber = FMC_InternalBank_Number_4;
SDRAM.FMC_CASLatency = FMC_CAS_Latency_3;
SDRAM.FMC_WriteProtection = FMC_Write_Protection_Disable;
SDRAM.FMC_SDClockPeriod = FMC_SDClock_Period_2;
SDRAM.FMC_ReadBurst = FMC_Read_Burst_Disable;
SDRAM.FMC_ReadPipeDelay = FMC_ReadPipe_Delay_1;
SDRAM.FMC_SDRAMTimingStruct = &Timing;
/* Initialization of FMC SDRAM Bank2 */
FMC_SDRAMInit(&SDRAM);
/* Init sequence for SDRAM Bank2 */
SDRAM_InitSequence(FMC_Command_Target_bank2, FMC_Bank2_SDRAM);
}
#define IS42S16320F_SIZE (uint32_t)0x10000
#define SDRAM_ADDR (uint32_t)0xD0000000
__IO uint32_t counter = 0;
__IO uint8_t ubReadByte = 0;
const uint8_t ubWriteByte = 0x3C;
int main(void)
{
/* Initialize the SysTick */
SystemCoreClockUpdate();
if (SysTick_Config(SystemCoreClock / 1000))
{
while(1);
}
/* SDRAM Initialization */
SDRAM_Init();
/* Disable write protection */
FMC_SDRAMWriteProtectionConfig(FMC_Bank2_SDRAM, DISABLE);
/* Erase SDRAM memory */
for (counter = 0; counter < IS42S16320F_SIZE; counter++)
{
*(__IO uint8_t *)(SDRAM_ADDR + counter) = (uint8_t)0x00;
}
/* Write data value to SDRAM memory */
for (counter = 0; counter < IS42S16320F_SIZE; counter++)
{
*(__IO uint8_t *)(SDRAM_ADDR + counter) = ubWriteByte;
}
/* Read back SDRAM memory and check content correction */
for (counter = 0; counter < IS42S16320F_SIZE; counter++)
{
ubReadByte = *(__IO uint8_t *)(SDRAM_ADDR + counter);
if (ubWriteByte != ubReadByte)
break;
}
/*
In this stage I'm expecting no change on data in the SDRAM but when
I watch the memory sections data is changing. The pictures about that
added the end of the question.
*/
while(1)
{
}
}
Data is not same with the written value while reading. And in the endless loop the data is changing independently. Is there a problem with refreshing/timing values or initialization sequence of SDRAM. Here is the link of the SDRAM www .issi. com/WW/pdf/42-45R-S_86400F-16320F.pdf. Thanks in advance any help.