lpcware

LPC178x EMC and SDRAM

Discussion created by lpcware Employee on Jun 15, 2016
Latest reply on Jun 15, 2016 by lpcware
Content originally posted in LPCWare by Ariekanarie on Thu Sep 06 06:54:38 MST 2012
Hey Hello you all,

I'm kind of new at this forum and I'm facing problems with my setup of the EMC and the used microcontroller lpc1787FBD208.

The SDRAM which I want to interface with is a A43L0616B of AMIC. (http://www.amictechnology.com/pdf/A43L0616B.pdf)
This is a 512k x 16 bit x 2 banks chip (16 Mbit)

Unfortunately I can't find some requested settings in the Datasheet, like tXSR and tSREX. I made up the value for those.
I've set up the remaining values as they are stated in the Datasheet of the SDRAM.

I'm running the CPU clock at 120 MHz and therefore it will devide it to 60 MHz for the EMCClock. All EMC pins have the IOCON value "0x00000031" which means: Pull-up enabled, Hysteresis enabled, EMC function selected.

The initialize code for the SDRAM is stated down here:
<code>
#include "SDRAM.h"

extern Delay(uint32_t);

#define NS_2_CLKS(ns) ((((EMCClock/10000) * ns)/100000))
#define ROW_BANK_COLUMN
#define SDRAM_BASE_ADDR    (0xA0000000)    /* SDRAM Bank 0  */
#define SDRAM_SIZE         (0x200000)      /* 16Mbit Length */


uint32_t EMC_SDRAM_REFRESH(uint32_t time)
{
uint32_t emc_freq = CLKPWR_GetCLK(CLKPWR_CLKTYPE_EMC);
if((LPC_SC->EMCCLKSEL &0x01)&0x01)
return (((uint64_t)((uint64_t)time * (emc_freq/2))/16000000ull)+1);
else
return (((uint64_t)((uint64_t)time * emc_freq)/16000000ull)+1);
}

void init_SDRAM()
{
uint32_t Temp = Temp;
uint32_t CAS_Latency, RAS_Latency;  // these can be 1, 2, or 3 clks                        
int i;

LPC_SC->PCONP   |= 0x00000800;//Enable Power EMC
LPC_EMC->Control = 0x00000001;//EMC enable
LPC_EMC->Config  = 0x00000000;//Little Endian
LPC_EMC->DynamicConfig0 = 0;//buffers disabled

LPC_SC->EMCDLYCTL |= (8<<0);
/*Set data read delay*/
LPC_SC->EMCDLYCTL |=(8<<8);
LPC_SC->EMCDLYCTL |= (0x08 <<16);


//  LPC1787FBD208Amic A43L0616B
//  PinDescriptionPinDescription
LPC_IOCON->P2_16 |= 0x01; //  87EMC_CAS<-->16nCAS
LPC_IOCON->P2_17 |= 0x01; //  95EMC_RAS<-->17nRAS
LPC_IOCON->P2_18 |= 0x01; //  59EMC_CLK0<-->35CLK
LPC_IOCON->P2_20 |= 0x01; //  73EMC_DYCS0<-->18nCS
LPC_IOCON->P2_24 |= 0x01; //  53EMC_CKE0<-->34CKE
LPC_IOCON->P2_28 |= 0x01; //  49EMC_DQM0<-->14LDQM
LPC_IOCON->P2_29 |= 0x01; //  43EMC_DQM1<-->36UDQM
// D0-15
LPC_IOCON->P3_0 |= 0x01; //  197EMC_D[0]<-->2DQ0
LPC_IOCON->P3_1 |= 0x01; //  201EMC_D[1]<-->3DQ1
LPC_IOCON->P3_2 |= 0x01; //  207EMC_D[2]<-->5DQ2
LPC_IOCON->P3_3 |= 0x01; //  3EMC_D[3]<-->6DQ3
LPC_IOCON->P3_4 |= 0x01; //  13EMC_D[4]<-->8DQ4
LPC_IOCON->P3_5 |= 0x01; //  17EMC_D[5]<-->9DQ5
LPC_IOCON->P3_6 |= 0x01; //  23EMC_D[6]<-->11DQ6
LPC_IOCON->P3_7 |= 0x01; //  27EMC_D[7]<-->12DQ7
LPC_IOCON->P3_8 |= 0x01; //  191EMC_D[8]<-->39DQ8
LPC_IOCON->P3_9 |= 0x01; //  199EMC_D[9]<-->40DQ9
LPC_IOCON->P3_10 |= 0x01;//  205EMC_D[10]<-->42DQ10
LPC_IOCON->P3_11 |= 0x01;//  208EMC_D[11]<-->43DQ11
LPC_IOCON->P3_12 |= 0x01;//  1EMC_D[12]<-->45DQ12
LPC_IOCON->P3_13 |= 0x01;//  7EMC_D[13]<-->46DQ13
LPC_IOCON->P3_14 |= 0x01;//  21EMC_D[14]<-->48DQ14
LPC_IOCON->P3_15 |= 0x01;//  28EMC_D[15]<-->49DQ15
//A0-13
LPC_IOCON->P4_0 |= 0x01; //  75EMC_A[0]<-->21A0
LPC_IOCON->P4_1 |= 0x01; //  79EMC_A[1]<-->22A1
LPC_IOCON->P4_2 |= 0x01; //  83EMC_A[2]<-->23A2
LPC_IOCON->P4_3 |= 0x01; //  97EMC_A[3]<-->24A3
LPC_IOCON->P4_4 |= 0x01; //  103EMC_A[4]<-->27A4
LPC_IOCON->P4_5 |= 0x01; //  107EMC_A[5]<-->28A5
LPC_IOCON->P4_6 |= 0x01; //  113EMC_A[6]<-->29A6
LPC_IOCON->P4_7 |= 0x01; //  121EMC_A[7]<-->30A7
LPC_IOCON->P4_8 |= 0x01; //  127EMC_A[8]<-->31A8
LPC_IOCON->P4_9 |= 0x01; //  131EMC_A[9]<-->32A9
LPC_IOCON->P4_10 |= 0x01;//  135EMC_A[10]<-->20A10/AP
LPC_IOCON->P4_13 |= 0x01;//  155EMC_A[13]<-->19BA

LPC_IOCON->P4_25 |= 0x01; //  179EMC_WE<-->15nWE


if( SystemCoreClock > 80000000 )   // longer delay constant, and shorter CAS and RAS latency
{                                //                                                     
LPC_SC->EMCCLKSEL = 0x00000001;  // EMC uses a clock rate at 1/2 CPU clock rate...
}
   else
{
LPC_SC->EMCCLKSEL = 0x00000000;  // EMC uses a clock rate equal to CPU clock rate...    
}

CAS_Latency = 2;
  RAS_Latency = 2;

//Configure memory layout, but MUST DISABLE BUFFERs during configuration
  #ifdef ROW_BANK_COLUMN
      LPC_EMC->DynamicConfig0 = 0x00000080;  // row, bank, column, 16Mb(1Mx16), 2 banks, row length=11, column length= 8
   #else
      LPC_EMC->DynamicConfig0 = 0x00001080;  // bank, row, column, 16Mb(1Mx16), 2 banks, row length=11, column length= 8
   #endif 

LPC_EMC->DynamicRasCas0 = RAS_Latency + (CAS_Latency<<8);    // reset value is 3 and 3
LPC_EMC->DynamicReadConfig = 0x00000001;     /* Command delayed strategy, using EMCCLKDELAY */
LPC_EMC->DynamicRP         = NS_2_CLKS(20);     //20ns from datasheet tRP(min)
LPC_EMC->DynamicRAS        = NS_2_CLKS(44);     //44ns from datasheet tRAS(min)
LPC_EMC->DynamicSREX       = NS_2_CLKS(70);    //Made up value???? 
LPC_EMC->DynamicAPR        = NS_2_CLKS(20);     //20ns from datasheet tRCD(min)
LPC_EMC->DynamicDAL  = 0x00000002;       //1 tCK from datasheet tCDL(min)
LPC_EMC->DynamicWR         = 0x00000001; //n+1 tCK = 2 / From datasheet tRDL(min)
LPC_EMC->DynamicRC         = NS_2_CLKS(64);     //64ns from datasheet tRC(min)
LPC_EMC->DynamicRFC        = NS_2_CLKS(64);     //64ns from datasheet tRC(min)
LPC_EMC->DynamicXSR        = NS_2_CLKS(70);     //Made up value
LPC_EMC->DynamicRRD        = NS_2_CLKS(14);     //14ns from datasheet tRRD(min)
LPC_EMC->DynamicMRD        = 0x00000001;      //n+1 tCK =2 tCK

LPC_EMC->DynamicControl    = 0x00000183; /* Issue NOP command */

Delay(2);//2 ms delay, datasheet stated minimum 200 us

LPC_EMC->DynamicControl    = 0x00000103;     /* Issue PALL command */
LPC_EMC->DynamicRefresh    = 0x00000001;     /* ( n * 16 ) -> 16 clock cycles */

for(i = 0; i < 0x80; i++);         /* wait 128 AHB clock cycles */

LPC_EMC->DynamicRefresh    = EMC_SDRAM_REFRESH(15);    //57 at 60MHz <= 15.625uS ( 32ms / 2048 row ) */

for(i = 0; i < 0x80; i++);         /* wait 128 AHB clock cycles */

  LPC_EMC->DynamicControl    = 0x00000083;  /* Issue MODE command */

#ifdef ROW_BANK_COLUMN  // shift includes bank                                             
      Temp = *((volatile uint32_t *)(SDRAM_BASE_ADDR|((0x03+(CAS_Latency<<4))<<12)));
   #else                   // shift excludes bank                                             
      Temp = *((volatile uint32_t *)(SDRAM_BASE_ADDR|((0x03+(CAS_Latency<<4))<<10)));
   #endif

for(i = 0; i < 0x80; i++);         /* wait 128 AHB clock cycles */

LPC_EMC->DynamicControl    = 0x00000000;        /* Issue NORMAL command */

//[re]enable buffers
  LPC_EMC->DynamicConfig0 |= 0x00080000;          /* 16Mbit, 1Mx16, 2 banks, row=11, column=8 */


LPC_SC->EMCCAL = (1<<14);
while((LPC_SC->EMCCAL & (1<<15))!=(1<<15));//After calibration start, the value 0x9A (154) is saved
//but not used
}

</code>
At the end of above code I start the calibration. When I read the value out of the register I see value 0x9A. The datasheet of the Microcontroller stated that 0x86 is normal at room temperature( which it is in here). At this point I don;t know what it means and what I must do with this fact.

The function which I'm using to verify the working of my code is as follows:
<code>
void App_DoMain()
{
uint32_t i=0;
  volatile uint32_t *wr_ptr;
  volatile uint16_t *short_wr_ptr;
uint16_t temp1[1000];

debug_frmwrk_init();
  print_menu();
_DBG_("Init SDRAM...");
init_SDRAM();

wr_ptr = (uint32_t *)SDRAM_BASE_ADDR;   
short_wr_ptr = (uint16_t *)wr_ptr;
/* Clear content before 16 bit access test */
_DBG_("Clear content of SRAM...");
for ( i= 0; i < SDRAM_SIZE/2; i++ )
{
*short_wr_ptr++ = 0x0000;
}

/* 16 bit write */
_DBG_("Writing in 16 bits format...");
for (i=0; i<(SDRAM_SIZE/2); i++)
{
if(i%2==0)
*short_wr_ptr++ = 0x5AA5;
else
*short_wr_ptr++ = 0xA55A;
}

/* Verifying */
short_wr_ptr = (uint16_t *)wr_ptr;
for ( i= 0; i < SDRAM_SIZE/2; i++ )
{
if(i<1000)
temp1=*short_wr_ptr;

short_wr_ptr++;
}

/* 16-bit half word comparison succeed. */

_DBG_("Verifying complete, testing terminated!");
while(1);
}
</code>

First I try to clear the chip,
than I try to fill the chip with the given values
After that I try to read out the values.

Unfortunately the only values that are read out is 0xFFFF, while I wrote values like 0xA55A and 0x5AA5 to the SDRAM.
I've connected a oscilloscope to one address line and data line and see that there are signals transmitted to the chip. During the reading period I can confirm that the Data line is High the whole time.

Cause of the effect that the Microcontroller receives 0xFFFF I think that I may conclude that the writing cyclus isn't set up properly in anyway.

I've double checked the connections between the SDRAM and the LPC1787 which is on a self designed PCB. Besides that I've tried to get it to work at 24 Mhz, but this wasn't helping me either. The final application for this is to drive a GLCD, but this will not work until the SDRAM with EMC is fixed :)

I hope you guys can help me out of this in any way with your vision.
I'm trying to fix this problem for a few days now.
The topic by Dave (http://www.lpcware.com/content/forum/dk-57vts-lpc1788-configuring-emc-sdram) and Scieslik (http://www.lpcware.com/content/forum/sdram-write-issue) have helped me to understand a lot of the working of the EMC Pherhiperal. Thanks for that!
Unfortunately it is not enough to understand the problem I'm facing.

Thanks in advance.

With Kind regards,
Arjan

Outcomes