AnsweredAssumed Answered

SDRAM STM32F429 refresh problem

Question asked by vugs.michel on Jul 4, 2014
Latest reply on Jun 3, 2015 by Bull.Harvey
Hello

We are currently developing a product which uses a STM32F429IITx. On the pcb we also installed a SDRAM chip of 64MB ( AS4C32M16SA-7TCN ) which is connected with the mcu via FMC peripheral.

At first glance the SDRAM worked correctly. But after some time we discoverd that the chip loses data very fast. 

for example: 

//We declarate a variable test as a float in the SDRAM
__attribute__((section(".sdram_data"))) float test;

//Just some numbers
float number1 = 12.5, number 2;

int main(void)
{
     test = number1;
     number2 = test;
}

When we run this code everything works as expected. But if we place a delay (even a small one) between these two lines the data is lost:

int main(void)
{
     test = number1;
     Delay_Ms(50);
     number2 = test;
}

So this will not work.

We expect that this is happening due to the fact that de SDRAM is not refreshing correctly. But we are not able to find the cause of this in the innitialisation:

//--------------------------------------------------------------
// Init vom externen SDRAM
// Return_wert :
//  -> ERROR   , wenn SDRAM nicht gefunden wurde
//  -> SUCCESS , wenn SDRAM gefunden wurde
//--------------------------------------------------------------
ErrorStatus UB_SDRAM_Init(void)
{
  ErrorStatus ret_wert=ERROR;
  uint16_t oldwert,istwert;
  static uint8_t init_ok=0;


  if(init_ok!=0) { 
    if(init_ok==1) {
      return(SUCCESS);
    }
    else {
      return(ERROR);
    }
  }


  // IO-Lines initialisieren
  P_SDRAM_InitIO();
  // FMC initialisieren
  P_SDRAM_InitFMC();


  //-----------------------------------------
  // check ob SDRAM vorhanden ist
  // schreib-/lese-Test auf Adr 0x00
  //-----------------------------------------
  oldwert=UB_SDRAM_Read16b(0x00);
  UB_SDRAM_Write16b(0x00, 0x5A3C);
  istwert=UB_SDRAM_Read16b(0x00);
  UB_SDRAM_Write16b(0x00, oldwert);
  if(istwert==0x5A3C) ret_wert=SUCCESS; // RAM vorhanden


  // init Mode speichern
  if(ret_wert==SUCCESS) {
    init_ok=1;
  }
  else {
    init_ok=2;
  }


  return(ret_wert);
}

//--------------------------------------------------------------
// interne Funktion
// Init aller IO-Pins fuer das SRAM
//--------------------------------------------------------------
void P_SDRAM_InitIO(void)
{
     GPIO_InitTypeDef GPIO_InitStructure;


     // power enable SDRAM
     RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOH, ENABLE);
     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
     GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
     GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
     GPIO_Init(GPIOH, &GPIO_InitStructure);
     GPIO_WriteBit(GPIOH, GPIO_Pin_12, 0);




  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD |
                         RCC_AHB1Periph_GPIOE | RCC_AHB1Periph_GPIOF | RCC_AHB1Periph_GPIOG | RCC_AHB1Periph_GPIOG, ENABLE);


   
  GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;


   
  GPIO_PinAFConfig(GPIOH, GPIO_PinSource5 , GPIO_AF_FMC);
  GPIO_PinAFConfig(GPIOH, GPIO_PinSource6 , GPIO_AF_FMC);
  
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5  | GPIO_Pin_6;      


  GPIO_Init(GPIOH, &GPIO_InitStructure);


   
  GPIO_PinAFConfig(GPIOC, GPIO_PinSource0 , GPIO_AF_FMC);
  
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;      


  GPIO_Init(GPIOC, &GPIO_InitStructure);  
  
   
  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_InitStructure.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_InitStructure);


  
  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_InitStructure.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_InitStructure);


   
  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_InitStructure.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_InitStructure);


   
  GPIO_PinAFConfig(GPIOG, GPIO_PinSource0 , GPIO_AF_FMC);
  GPIO_PinAFConfig(GPIOG, GPIO_PinSource1 , GPIO_AF_FMC);
  GPIO_PinAFConfig(GPIOG, GPIO_PinSource2 , GPIO_AF_FMC);
  GPIO_PinAFConfig(GPIOG, GPIO_PinSource4 , GPIO_AF_FMC);
  GPIO_PinAFConfig(GPIOG, GPIO_PinSource5 , GPIO_AF_FMC);
  GPIO_PinAFConfig(GPIOG, GPIO_PinSource8 , GPIO_AF_FMC);
  GPIO_PinAFConfig(GPIOG, GPIO_PinSource15 , GPIO_AF_FMC);
  


  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_4 |
                                GPIO_Pin_5 | GPIO_Pin_8 | GPIO_Pin_15;


  GPIO_Init(GPIOG, &GPIO_InitStructure);
}




//--------------------------------------------------------------
// interne Funktion
// Init vom FMC fuer das SDRAM
//--------------------------------------------------------------
void P_SDRAM_InitFMC(void)
{
  FMC_SDRAMInitTypeDef  FMC_SDRAMInitStructure;
  FMC_SDRAMTimingInitTypeDef  FMC_SDRAMTimingInitStructure;


  RCC_AHB3PeriphClockCmd(RCC_AHB3Periph_FMC, ENABLE);


  //---------------------------------------------------------
  // FMC auf 180MHz/2 = 90MHz einstellen
  // 90MHz = 11,11 ns
  // Alle Timings laut Datasheet und Speedgrade -7 (=7ns)
  //---------------------------------------------------------
  FMC_SDRAMTimingInitStructure.FMC_LoadToActiveDelay = 2;    // tMRD=2CLK
  FMC_SDRAMTimingInitStructure.FMC_ExitSelfRefreshDelay = 7; // tXSR min=70ns
  FMC_SDRAMTimingInitStructure.FMC_SelfRefreshTime = 4;      // tRAS min=42ns
  FMC_SDRAMTimingInitStructure.FMC_RowCycleDelay = 7;        // tRC  min=63ns
  FMC_SDRAMTimingInitStructure.FMC_WriteRecoveryTime = 2;    // tWR =2CLK 
  FMC_SDRAMTimingInitStructure.FMC_RPDelay = 2;              // tRP  min=15ns
  FMC_SDRAMTimingInitStructure.FMC_RCDDelay = 2;             // tRCD min=15ns


  FMC_SDRAMInitStructure.FMC_Bank = FMC_Bank2_SDRAM;
  FMC_SDRAMInitStructure.FMC_ColumnBitsNumber = FMC_ColumnBits_Number_8b;
  FMC_SDRAMInitStructure.FMC_RowBitsNumber = FMC_RowBits_Number_12b;
  FMC_SDRAMInitStructure.FMC_SDMemoryDataWidth = SDRAM_MEMORY_WIDTH;
  FMC_SDRAMInitStructure.FMC_InternalBankNumber = FMC_InternalBank_Number_4;
  FMC_SDRAMInitStructure.FMC_CASLatency = SDRAM_CAS_LATENCY;
  FMC_SDRAMInitStructure.FMC_WriteProtection = FMC_Write_Protection_Disable;
  FMC_SDRAMInitStructure.FMC_SDClockPeriod = SDRAM_CLOCK_PERIOD;
  FMC_SDRAMInitStructure.FMC_ReadBurst = SDRAM_READBURST;
  FMC_SDRAMInitStructure.FMC_ReadPipeDelay = FMC_ReadPipe_Delay_1;
  FMC_SDRAMInitStructure.FMC_SDRAMTimingStruct = &FMC_SDRAMTimingInitStructure;


  FMC_SDRAMInit(&FMC_SDRAMInitStructure);


  P_SDRAM_InitSequence();
}




//--------------------------------------------------------------
// interne Funktion
// Initsequenz fuer das SDRAM
//--------------------------------------------------------------
void P_SDRAM_InitSequence(void)
{
  FMC_SDRAMCommandTypeDef FMC_SDRAMCommandStructure;
  uint32_t tmpr = 0;


  FMC_SDRAMCommandStructure.FMC_CommandMode = FMC_Command_Mode_CLK_Enabled;
  FMC_SDRAMCommandStructure.FMC_CommandTarget = FMC_Command_Target_bank2;
  FMC_SDRAMCommandStructure.FMC_AutoRefreshNumber = 1;
  FMC_SDRAMCommandStructure.FMC_ModeRegisterDefinition = 0;
  
  while(FMC_GetFlagStatus(FMC_Bank2_SDRAM, FMC_FLAG_Busy) != RESET);


  FMC_SDRAMCmdConfig(&FMC_SDRAMCommandStructure);


  P_SDRAM_delay(10);




  FMC_SDRAMCommandStructure.FMC_CommandMode = FMC_Command_Mode_PALL;
  FMC_SDRAMCommandStructure.FMC_CommandTarget = FMC_Command_Target_bank2;
  FMC_SDRAMCommandStructure.FMC_AutoRefreshNumber = 1;
  FMC_SDRAMCommandStructure.FMC_ModeRegisterDefinition = 0;
  
  while(FMC_GetFlagStatus(FMC_Bank2_SDRAM, FMC_FLAG_Busy) != RESET);


  FMC_SDRAMCmdConfig(&FMC_SDRAMCommandStructure);


  FMC_SDRAMCommandStructure.FMC_CommandMode = FMC_Command_Mode_AutoRefresh;
  //FMC_SDRAMCommandStructure.FMC_CommandMode = FMC_Command_Mode_Selfrefresh;
  FMC_SDRAMCommandStructure.FMC_CommandTarget = FMC_Command_Target_bank2;
  FMC_SDRAMCommandStructure.FMC_AutoRefreshNumber = 4;
  FMC_SDRAMCommandStructure.FMC_ModeRegisterDefinition = 0;


  while(FMC_GetFlagStatus(FMC_Bank2_SDRAM, FMC_FLAG_Busy) != RESET);


  FMC_SDRAMCmdConfig(&FMC_SDRAMCommandStructure);


  while(FMC_GetFlagStatus(FMC_Bank2_SDRAM, FMC_FLAG_Busy) != RESET);


  FMC_SDRAMCmdConfig(&FMC_SDRAMCommandStructure);




  tmpr = (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;


  FMC_SDRAMCommandStructure.FMC_CommandMode = FMC_Command_Mode_LoadMode;
  FMC_SDRAMCommandStructure.FMC_CommandTarget = FMC_Command_Target_bank2;
  FMC_SDRAMCommandStructure.FMC_AutoRefreshNumber = 1;
  FMC_SDRAMCommandStructure.FMC_ModeRegisterDefinition = tmpr;
  
  while(FMC_GetFlagStatus(FMC_Bank2_SDRAM, FMC_FLAG_Busy) != RESET);


  FMC_SDRAMCmdConfig(&FMC_SDRAMCommandStructure);


  //-----------------------------------------------
  // FMC_CLK = 90MHz
  // Refresh_Rate = 7.81us
  // Counter = (FMC_CLK * Refresh_Rate) - 20
  //-----------------------------------------------
  FMC_SetRefreshCount(683);
  //FMC_SetRefreshCount(500);
 
  while(FMC_GetFlagStatus(FMC_Bank2_SDRAM, FMC_FLAG_Busy) != RESET);
}




//--------------------------------------------------------------
// interne Funktion
// kleine Pause
//--------------------------------------------------------------
static void P_SDRAM_delay(volatile uint32_t nCount)
{
  volatile uint32_t index = 0;
  for(index = (100000 * nCount); index != 0; index--);
}


Does someone knows what goes wrong here?

My sincerly


Outcomes