AnsweredAssumed Answered

LPC43xx with EMC SDRAM fails under higher load

Question asked by zzzmqp on Aug 11, 2016
Latest reply on Aug 13, 2016 by zzzmqp

Dear LPC Community,

 

I use a LPC4357 at 204MHz with an external SDRAM at 102MHz.

The SDRAM is a Micron MT48LC8M32B2 (datasheet link).

 

I ~thought~ all was working fine (with quite frequent writes and reads of a few hundred to a few kBytes as a shared buffer between the cores - all DMA transfers), but now another function was added which reads larger chunks up 512kB and writes them to an SD card (also using some direct DMA transfer and the SDMMC DMA mode as part of the SDIF driver). The read also 'works' (the 512kB are written correct on the card) but afterwards the data in the SDRAM gets corrupted, at least for a while. I see 'gaps' (blank areas) and repeats of data from earlier in the SDRAM but can't really make out what exactly happens.

 

Here's my SDRAM initialization code:

 

#define  BUFFER_BASE  0x28000000

#define  MS 8350  // for() loop count to delay 1 ms (measured)

void SDRAM_Init (void) {
  uint32_t pclk, temp;
  uint64_t tmpclk;
  uint32_t i = 0;
  uint32_t MODE;
  uint32_t OFFSET;

  Chip_SCU_PinMuxSet( 2  ,  9  ,  (SCU_PINIO_FAST | SCU_MODE_FUNC3));  //A0
  Chip_SCU_PinMuxSet(  2  ,  10  ,  (SCU_PINIO_FAST | SCU_MODE_FUNC3));  //A1
  Chip_SCU_PinMuxSet(  2  ,  11  ,  (SCU_PINIO_FAST | SCU_MODE_FUNC3));  //A2
  Chip_SCU_PinMuxSet(  2  ,  12  ,  (SCU_PINIO_FAST | SCU_MODE_FUNC3));  //A3
  Chip_SCU_PinMuxSet(  2  ,  13  ,  (SCU_PINIO_FAST | SCU_MODE_FUNC3));  //A4
  Chip_SCU_PinMuxSet(  1  ,  0  ,  (SCU_PINIO_FAST | SCU_MODE_FUNC2));  //A5
  Chip_SCU_PinMuxSet(  1  ,  1  ,  (SCU_PINIO_FAST | SCU_MODE_FUNC2));  //A6
  Chip_SCU_PinMuxSet(  1  ,  2  ,  (SCU_PINIO_FAST | SCU_MODE_FUNC2));  //A7
  Chip_SCU_PinMuxSet(  2  ,  8  ,  (SCU_PINIO_FAST | SCU_MODE_FUNC3));  //A8
  Chip_SCU_PinMuxSet(  2  ,  7  ,  (SCU_PINIO_FAST | SCU_MODE_FUNC3));  //A9
  Chip_SCU_PinMuxSet(  2  ,  6  ,  (SCU_PINIO_FAST | SCU_MODE_FUNC2));  //A10
  Chip_SCU_PinMuxSet(  2  ,  2  ,  (SCU_PINIO_FAST | SCU_MODE_FUNC2));  //A11
  Chip_SCU_PinMuxSet(  2  ,  1  ,  (SCU_PINIO_FAST | SCU_MODE_FUNC2));  //A12
  Chip_SCU_PinMuxSet(  2  ,  0  ,  (SCU_PINIO_FAST | SCU_MODE_FUNC2));  //A13
  Chip_SCU_PinMuxSet(  6  ,  8  ,  (SCU_PINIO_FAST | SCU_MODE_FUNC1));  //A14

  Chip_SCU_PinMuxSet(  1  ,  7  ,  (SCU_PINIO_FAST | SCU_MODE_FUNC3));  //D0
  Chip_SCU_PinMuxSet(  1  ,  8  ,  (SCU_PINIO_FAST | SCU_MODE_FUNC3));  //D1
  Chip_SCU_PinMuxSet(  1  ,  9  ,  (SCU_PINIO_FAST | SCU_MODE_FUNC3));  //D2
  Chip_SCU_PinMuxSet(  1  ,  10  ,  (SCU_PINIO_FAST | SCU_MODE_FUNC3));  //D3
  Chip_SCU_PinMuxSet(  1  ,  11  ,  (SCU_PINIO_FAST | SCU_MODE_FUNC3));  //D4
  Chip_SCU_PinMuxSet(  1  ,  12  ,  (SCU_PINIO_FAST | SCU_MODE_FUNC3));  //D5
  Chip_SCU_PinMuxSet(  1  ,  13  ,  (SCU_PINIO_FAST | SCU_MODE_FUNC3));  //D6
  Chip_SCU_PinMuxSet(  1  ,  14  ,  (SCU_PINIO_FAST | SCU_MODE_FUNC3));  //D7
  Chip_SCU_PinMuxSet(  5  ,  4  ,  (SCU_PINIO_FAST | SCU_MODE_FUNC2));  //D8
  Chip_SCU_PinMuxSet(  5  ,  5  ,  (SCU_PINIO_FAST | SCU_MODE_FUNC2));  //D9
  Chip_SCU_PinMuxSet(  5  ,  6  ,  (SCU_PINIO_FAST | SCU_MODE_FUNC2));  //D10
  Chip_SCU_PinMuxSet(  5  ,  7  ,  (SCU_PINIO_FAST | SCU_MODE_FUNC2));  //D11
  Chip_SCU_PinMuxSet(  5  ,  0  ,  (SCU_PINIO_FAST | SCU_MODE_FUNC2));  //D12
  Chip_SCU_PinMuxSet(  5  ,  1  ,  (SCU_PINIO_FAST | SCU_MODE_FUNC2));  //D13
  Chip_SCU_PinMuxSet(  5  ,  2  ,  (SCU_PINIO_FAST | SCU_MODE_FUNC2));  //D14
  Chip_SCU_PinMuxSet(  5  ,  3  ,  (SCU_PINIO_FAST | SCU_MODE_FUNC2));  //D15
  Chip_SCU_PinMuxSet(  0X0D  ,  2  ,  (SCU_PINIO_FAST | SCU_MODE_FUNC2));  //D16
  Chip_SCU_PinMuxSet(  0X0D  ,  3  ,  (SCU_PINIO_FAST | SCU_MODE_FUNC2));  //D17
  Chip_SCU_PinMuxSet(  0X0D  ,  4  ,  (SCU_PINIO_FAST | SCU_MODE_FUNC2));  //D18
  Chip_SCU_PinMuxSet(  0X0D  ,  5  ,  (SCU_PINIO_FAST | SCU_MODE_FUNC2));  //D19
  Chip_SCU_PinMuxSet(  0X0D  ,  6  ,  (SCU_PINIO_FAST | SCU_MODE_FUNC2));  //D20
  Chip_SCU_PinMuxSet(  0X0D  ,  7  ,  (SCU_PINIO_FAST | SCU_MODE_FUNC2));  //D21
  Chip_SCU_PinMuxSet(  0X0D  ,  8  ,  (SCU_PINIO_FAST | SCU_MODE_FUNC2));  //D22
  Chip_SCU_PinMuxSet(  0X0D  ,  9  ,  (SCU_PINIO_FAST | SCU_MODE_FUNC2));  //D23
  Chip_SCU_PinMuxSet(  0X0E  ,  5  ,  (SCU_PINIO_FAST | SCU_MODE_FUNC3));  //D24
  Chip_SCU_PinMuxSet(  0X0E  ,  6  ,  (SCU_PINIO_FAST | SCU_MODE_FUNC3));  //D25
  Chip_SCU_PinMuxSet(  0X0E  ,  7  ,  (SCU_PINIO_FAST | SCU_MODE_FUNC3));  //D26
  Chip_SCU_PinMuxSet(  0X0E  ,  8  ,  (SCU_PINIO_FAST | SCU_MODE_FUNC3));  //D27
  Chip_SCU_PinMuxSet(  0X0E  ,  9  ,  (SCU_PINIO_FAST | SCU_MODE_FUNC3));  //D28
  Chip_SCU_PinMuxSet(  0X0E  ,  10  ,  (SCU_PINIO_FAST | SCU_MODE_FUNC3));  //D29
  Chip_SCU_PinMuxSet(  0X0E  ,  11  ,  (SCU_PINIO_FAST | SCU_MODE_FUNC3));  //D30
  Chip_SCU_PinMuxSet(  0X0E  ,  12  ,  (SCU_PINIO_FAST | SCU_MODE_FUNC3));  //D31

  Chip_SCU_PinMuxSet(  6  ,  11  ,  (SCU_PINIO_FAST | SCU_MODE_FUNC3));  // CKEOUT0
  Chip_SCU_ClockPinMuxSet(0, (SCU_PINIO_FAST | SCU_MODE_FUNC0));  // CLK0 connected to EMC_CLK0
  Chip_SCU_ClockPinMuxSet(1, (SCU_PINIO_FAST | SCU_MODE_FUNC0));  // CLK1 connected to EMC_CLK1
  Chip_SCU_ClockPinMuxSet(2, (SCU_PINIO_FAST | SCU_MODE_FUNC0));  // CLK2 connected to EMC_CLK3
  Chip_SCU_ClockPinMuxSet(3, (SCU_PINIO_FAST | SCU_MODE_FUNC0));  // CLK3 connected to EMC_CLK2
  
  Chip_SCU_PinMuxSet(  6  ,  12  ,  (SCU_PINIO_FAST | SCU_MODE_FUNC3));  //DQMOUT0
  Chip_SCU_PinMuxSet(  6  ,  10  ,  (SCU_PINIO_FAST | SCU_MODE_FUNC3));  //DQMOUT1
  Chip_SCU_PinMuxSet(  0X0D,  0  ,  (SCU_PINIO_FAST | SCU_MODE_FUNC2));  //DQMOUT2
  Chip_SCU_PinMuxSet(  0X0E,  13  ,  (SCU_PINIO_FAST | SCU_MODE_FUNC3));  //DQMOUT3
  
  Chip_SCU_PinMuxSet(  6  ,  4  ,  (SCU_PINIO_FAST | SCU_MODE_FUNC3));  //CAS
  Chip_SCU_PinMuxSet(  6  ,  5  ,  (SCU_PINIO_FAST | SCU_MODE_FUNC3));  //RAS
  
  Chip_SCU_PinMuxSet(  1  ,  6  ,  (SCU_PINIO_FAST | SCU_MODE_FUNC3));  //WE
  Chip_SCU_PinMuxSet(  6  ,  9  ,  (SCU_PINIO_FAST | SCU_MODE_FUNC3));  //DYCS0
  
  /* Select EMC clock-out */
  LPC_SCU->SFSCLK[0] = SCU_PINIO_FAST;
  LPC_SCU->SFSCLK[1] = SCU_PINIO_FAST;
  LPC_SCU->SFSCLK[2] = SCU_PINIO_FAST;
  LPC_SCU->SFSCLK[3] = SCU_PINIO_FAST;

  /* Setup EMC Delays */
  LPC_SCU->EMCDELAYCLK = 0x7777; // ~3.5 ns delay

  LPC_CCU1->CLKCCU[CLK_MX_EMC_DIV].CFG |= (1 << 5);
  LPC_CREG->CREG6 |= (1 << 16);

  pclk = Chip_Clock_GetEMCRate();

  LPC_EMC->CONTROL   = 0x00000001;
  LPC_EMC->CONFIG    = 0x00000000;
  LPC_EMC->DYNAMICCONFIG0    = 1 << 14 | 0 << 12 | 2 << 9 | 1 << 7; /* RBC 256Mb, 8Mx32, 4 banks, row=12, column=9 */
  LPC_EMC->DYNAMICRASCAS0     = (3UL);         //RAS latency
  LPC_EMC->DYNAMICRASCAS0   |= (3UL << 8);    //CAS latency
  LPC_EMC->DYNAMICREADCONFIG = 0x00000001; /* Command delayed strategy, using EMCCLKDELAY */

  LPC_EMC->DYNAMICRP         = NS2CLK(pclk, 20);
  LPC_EMC->DYNAMICRAS        = NS2CLK(pclk, 42);
  LPC_EMC->DYNAMICSREX       = NS2CLK(pclk, 63);
  LPC_EMC->DYNAMICAPR        = 0x00000005;
  LPC_EMC->DYNAMICDAL        = 0x00000005;
  LPC_EMC->DYNAMICWR         = 2;
  LPC_EMC->DYNAMICRC         = NS2CLK(pclk, 63);
  LPC_EMC->DYNAMICRFC        = NS2CLK(pclk, 63);
  LPC_EMC->DYNAMICXSR        = NS2CLK(pclk, 63);
  LPC_EMC->DYNAMICRRD        = NS2CLK(pclk, 14);
  LPC_EMC->DYNAMICMRD        = 0x00000002;

  for(i = 0; i < 100*MS; i++);  /* wait 100ms */
  LPC_EMC->DYNAMICCONTROL    = 0x00000183; /* Issue NOP command */

  for(i = 0; i < 200*MS; i++);  /* wait 200ms */
  LPC_EMC->DYNAMICCONTROL    = 0x00000103; /* Issue PALL command */

  LPC_EMC->DYNAMICREFRESH    = EMC_SDRAM_REFRESH(pclk,70); /* ( n * 16 ) -> 32 clock cycles */

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

  tmpclk = (uint64_t)15625*(uint64_t)pclk/1000000000/16;
  LPC_EMC->DYNAMICREFRESH    = tmpclk; /* ( n * 16 ) -> 736 clock cycles -> 15.330uS at 48MHz <= 15.625uS ( 64ms / 4096 row ) */

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

  //Timing for 48/60/72MHZ Bus
   MODE = (2 << 0) | (0 << 3) | (3 << 4) | (0 << 9);  // burst = 4, seq. mode, latency = 3, write burst = 0
   OFFSET = 9 + 2 + 2;  // RBC: 9 col + 32 bit (=2) + 2 bank select
   temp = *((volatile uint32_t *)(BUFFER_BASE + (MODE << OFFSET)));
   temp = temp;
  
  LPC_EMC->DYNAMICCONTROL    = 0x00000000; /* Issue NORMAL command */

  //[re]enable buffers
  LPC_EMC->DYNAMICCONFIG0    |= 1<<19;
}

 

 

Please, does anyone see what the issue may be? Or if not this code, what else can cause this problem?

 

Thank you!

Outcomes