LPC1788 and EMC write/read issues

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

LPC1788 and EMC write/read issues

569 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by ImaginationStation on Mon Nov 18 10:01:21 MST 2013
Hello, I am using an LPC1788 and a 128MB SDRAM chip IS42S32400E-6TL

The problem is that information is either written or read incorrectly on the SDRAM and it only does it when the board with the chips are cold. It also did the same thing with other brand SDRAM chips.

I started working with this combination about 6 months ago. At the time my workbench was in a warm area where the temperatures were commonly above 25C. At the time there was not a problem, it ran flawlessly. I recently moved and my work area ended up in the basement where temperatures range between 18C and 21C. Now once the board is started up from cold it always has the problem, and if the board temperatures get high enough it will stop reading/writing to the EMC incorrectly.

I’m having a hard time figuring out if it is on the read or the write. I believe the issue may be isolated to the reads only and here’s why I believe that. In my application I initialize the EMC to be able to display things on the LCD. When I write to the memory area that maps the display area it displays correctly. But if I read from anything on the display area and rewrite to that same address some of the pixels will display incorrectly.

Since the problem doesn’t exist when it’s warm I believe it could have something to do with my SDRAM setup/initialization.

Here is my initialization sequence:

static void _EMC_Init(void) {
  volatile uint32_t CmdDly;
  volatile uint32_t Dummy;
  volatile uint32_t i;

  LPC_SC->PCONP     |= (1 << 11);   // Turn on EMC peripheral clock
  LPC_SC->EMCDLYCTL  = 0x00001010;
  LPC_EMC->Control   = 1;           // EMC enable
  LPC_EMC->Config    = 0;
  //
  // Port init
  //

  LPC_IOCON->P3_0  = 1;  // D0
  LPC_IOCON->P3_1  = 1;  // D1
  LPC_IOCON->P3_2  = 1;  // D2
  LPC_IOCON->P3_3  = 1;  // D3
  LPC_IOCON->P3_4  = 1;  // D4
  LPC_IOCON->P3_5  = 1;  // D5
  LPC_IOCON->P3_6  = 1;  // D6
  LPC_IOCON->P3_7  = 1;  // D7
  LPC_IOCON->P3_8  = 1;  // D8
  LPC_IOCON->P3_9  = 1;  // D9
  LPC_IOCON->P3_10 = 1;  // D10
  LPC_IOCON->P3_11 = 1;  // D11
  LPC_IOCON->P3_12 = 1;  // D12
  LPC_IOCON->P3_13 = 1;  // D13
  LPC_IOCON->P3_14 = 1;  // D14
  LPC_IOCON->P3_15 = 1;  // D15
  LPC_IOCON->P3_16 = 1;  // D16
  LPC_IOCON->P3_17 = 1;  // D17
  LPC_IOCON->P3_18 = 1;  // D18
  LPC_IOCON->P3_19 = 1;  // D19
  LPC_IOCON->P3_20 = 1;  // D20
  LPC_IOCON->P3_21 = 1;  // D21
  LPC_IOCON->P3_22 = 1;  // D22
  LPC_IOCON->P3_23 = 1;  // D23
  LPC_IOCON->P3_24 = 1;  // D24
  LPC_IOCON->P3_25 = 1;  // D25
  LPC_IOCON->P3_26 = 1;  // D26
  LPC_IOCON->P3_27 = 1;  // D27
  LPC_IOCON->P3_28 = 1;  // D28
  LPC_IOCON->P3_29 = 1;  // D29
  LPC_IOCON->P3_30 = 1;  // D30
  LPC_IOCON->P3_31 = 1;  // D31

  LPC_IOCON->P4_0  = 1;  // A0
  LPC_IOCON->P4_1  = 1;  // A1
  LPC_IOCON->P4_2  = 1;  // A2
  LPC_IOCON->P4_3  = 1;  // A3
  LPC_IOCON->P4_4  = 1;  // A4
  LPC_IOCON->P4_5  = 1;  // A5
  LPC_IOCON->P4_6  = 1;  // A6
  LPC_IOCON->P4_7  = 1;  // A7
  LPC_IOCON->P4_8  = 1;  // A8
  LPC_IOCON->P4_9  = 1;  // A9
  LPC_IOCON->P4_10 = 1;  // A10
  LPC_IOCON->P4_11 = 1;  // A11
  LPC_IOCON->P4_12 = 1;  // A12
  LPC_IOCON->P4_13 = 1;  // A13
  LPC_IOCON->P4_14 = 1;  // A14
  LPC_IOCON->P4_15 = 1;  // A15
  LPC_IOCON->P4_16 = 1;  // A16
  LPC_IOCON->P4_17 = 1;  // A17
  LPC_IOCON->P4_18 = 1;  // A18
  LPC_IOCON->P4_19 = 1;  // A19
  LPC_IOCON->P4_20 = 1;  // A20
  LPC_IOCON->P4_21 = 1;  // A21
  //LPC_IOCON->P4_22 = 1;  // A22
  //LPC_IOCON->P4_23 = 1;  // A23

  LPC_IOCON->P4_24 = 1;  // OE
  LPC_IOCON->P4_25 = 1;  // WE
  LPC_IOCON->P4_26 = 1;  // BLS0
  LPC_IOCON->P4_27 = 1;  // BLS1
  LPC_IOCON->P4_28 = 1;  // BLS2
  LPC_IOCON->P4_29 = 1;  // BLS3
  LPC_IOCON->P4_30 = 1;  // CS0
  LPC_IOCON->P4_31 = 1;  // CS1
  LPC_IOCON->P2_14 = 1;  // CS2
  LPC_IOCON->P2_15 = 1;  // CS3
  LPC_IOCON->P2_16 = 1;  // CAS
  LPC_IOCON->P2_17 = 1;  // RAS
  LPC_IOCON->P2_18 = 1;  // CLKOUT0
  //LPC_IOCON->P2_19 = 1;  // CLKOUT1
  LPC_IOCON->P2_20 = 1;  // DYCS0
  //LPC_IOCON->P2_21 = 1;  // DYCS1
  //LPC_IOCON->P2_22 = 1;  // DYCS2
  //LPC_IOCON->P2_23 = 1;  // DYCS3
  LPC_IOCON->P2_24 = 1;  // CKEOUT0
  //LPC_IOCON->P2_25 = 1;  // CKEOUT1
  //LPC_IOCON->P2_26 = 1;  // CKEOUT2
  //LPC_IOCON->P2_27 = 1;  // CKEOUT3
  LPC_IOCON->P2_28 = 1;  // DQMOUT0
  LPC_IOCON->P2_29 = 1;  // DQMOUT1
  LPC_IOCON->P2_30 = 1;  // DQMOUT2
  LPC_IOCON->P2_31 = 1;  // DQMOUT3
  //
  // Setup EMC config for SDRAM, timings for 60MHz bus
  //
  LPC_EMC->DynamicConfig0    = 0x00005500;  // 128MB, 4Mx32, 4 banks, 12 rows, 9 columns, buffers disabled
  LPC_EMC->DynamicRasCas0    = 0x00000202;  // 2 RAS, 2 CAS latency */
  LPC_EMC->DynamicReadConfig = 0x00000001;  // Command delayed strategy, using EMCCLKDELAY
  LPC_EMC->DynamicRP         = 0x00000001;  // n + 1 clock cycles
  LPC_EMC->DynamicRAS        = 0x00000003;  // n + 1 clock cycles
  LPC_EMC->DynamicSREX       = 0x00000005;  // n + 1 clock cycles
  LPC_EMC->DynamicAPR        = 0x00000002;  // n + 1 clock cycles
  LPC_EMC->DynamicDAL        = 0x00000003;  // n     clock cycles
  LPC_EMC->DynamicWR         = 0x00000001;  // n + 1 clock cycles
  LPC_EMC->DynamicRC         = 0x00000004;  // n + 1 clock cycles
  LPC_EMC->DynamicRFC        = 0x00000004;  // n + 1 clock cycles
  LPC_EMC->DynamicXSR        = 0x00000005;  // n + 1 clock cycles
  LPC_EMC->DynamicRRD        = 0x00000001;  // n + 1 clock cycles
  LPC_EMC->DynamicMRD        = 0x00000001;  // n + 1 clock cycles
  _DelayMs(100);
  LPC_EMC->DynamicControl    = 0x00000183;  // Issue NOP command
  _DelayMs(200);
  LPC_EMC->DynamicControl    = 0x00000103;  // Issue PALL command
  LPC_EMC->DynamicRefresh    = 0x00000002;  // n * 16 clock cycles
  for (i = 0; i < 0x80; i++);               // Wait 128 AHB clock cycles
  LPC_EMC->DynamicRefresh    = 0x0000003A;  // n * 16 clock cycles
  //
  // Init SDRAM
  //
  LPC_EMC->DynamicControl = 0x00000083;                             // Issue MODE command
Dummy = *((volatile uint32_t*)(SDRAM_BASE_ADDR | (0x22 << (10))));  // 4 burst, 2 CAS latency
  //Dummy = *((volatile uint32_t*)(SDRAM_BASE_ADDR | (0x22 << (2+2+9))));  // 4 burst, 2 CAS latency
  LPC_EMC->DynamicControl = 0x00000000;                             // Issue NORMAL command
  LPC_EMC->DynamicConfig0 = 0x00085500;                             // 128MB, 4Mx32, 4 banks, 12 rows, 9 columns, buffers (re-)enabled
  //
  // Auto calibrate timings
  //
  CmdDly = _CalibrateOsc();
  //
  // Find best delay values
  //
  _FindDelay(0);  // EMCDLY
  _FindDelay(1);  // FBCLKDLY
  _AdjustEMCTiming(CmdDly);
}
Labels (1)
0 Kudos
1 Reply

387 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by ImaginationStation on Wed Nov 20 16:52:17 MST 2013
I believe I fixed the problem, but I haven't been testing it for long enough to see if that did the trick. I did the changes around 10am EST and it has been working well since then.

Since no one suggested any options I continued digging around on the net. I was lead back to 2 posts. One of them was here where this person was told by a few to change his Data lines to Repeater mode.

http://www.lpcware.com/content/forum/sdram-working-prototype-not-production

I tried changing my Data lines to repeater mode and that did not work. I then tried changing the data lines as well as the address lines, signal lines and all SDRAM related signal lines to Repeater mode. It still did not work.

I also read elsewhere (I can't remember the exact source. I believe it may have been a datasheet) that said to make sure all Data lines are pulled low. So I set all of my Data lines to pull low and that still didn't work. I then set all of the address lines, signal lines and Data lines to pull low and that did the trick.

So all IOCON registers related to any SDRAM pin became 0x29.
Hopefully this continues to work.
0 Kudos