LPC43xx with EMC SDRAM fails under higher load

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

LPC43xx with EMC SDRAM fails under higher load

698 Views
zzzmqp
Contributor III

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!

Labels (1)
Tags (3)
0 Kudos
1 Reply

398 Views
zzzmqp
Contributor III

On this board, EMC_CLK0 drives the SDRAM clock pin.

References I found in AN11508:

When x32 data width SDRAM is used, EMC_CLK1 or EMC_CLK3 may be used to drive SDRAM clock while EMC_CLK01 and EMC_CLK23 are used for FBCLK.

The key to running the EMC at full speed is to use EMC_CLK01 (CLK0 pin with SFSCLK0 = function 5) and EMC_CLK23 (CLK2 pin with SFSCLK2 = function 5) for the four byte lane feedback clocks, while using EMC_CLK1 (CLK1 pin) and / or EMC_CLK2 (CLK3 pin) to drive the SDRAM clocks.

I can't change the EMC_CLKx pin to CLK1 or CLK3 to try as this is a BGA256 package, but can using EMC_CLK0 be the reason for the issue described above?

0 Kudos