LCD AHB master interface with SDRAM in row bank colum

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

LCD AHB master interface with SDRAM in row bank colum

595 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by tjoAG on Fri Jun 08 05:44:35 MST 2012
Hi All

I'm using SDRAM as external memory. The address mapping was setup as row,bank,collumn

I uses the extermal SDRAM as frame buffer location

But when I enable the LCD controller, the data in the frame buffer kept changing. Also did the LCD controller read the data wrong!!

I have know tried setting up the SDRAM as bank,row,collumn and now everything works with the LCD controller.

Changing the DynamicConfig0 value from 0x00000480 to 0x00001480 did the trick...

Now the $1 million question. Can someone explain me why?

Has it something to do with how the LCD AHB master DMA works?

Why did it "change" the frame buffer data?

Possible to run the LCD controller with SDRAM setup as row,bank,collumn?

Thomas
Labels (1)
0 Kudos
7 Replies

531 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by tjoAG on Wed Jun 13 05:47:44 MST 2012
Hi Phil

I did try the mem test you suggested.

<code>
uint16_t data = 0x0102;
for (i=0; i<(0x01000000/2); i++)
{
   *short_wr_ptr++ = data;
   data += 0x0101;
}
</code

At address 0xA000 0000 the value 0x0102
At address 0xA002 0000 the value 0x0203
At address 0xA004 0000 the value 0x0304

But when I was finished looping the total amount of RAM the addresses was over written

At address 0xA000 0000 the value 0x0502
At address 0xA002 0000 the value 0x0603
At address 0xA004 0000 the value 0x0704

So something is set up wrong!!!
It it wasn't when the first overflow occurred.
But I think there is addressing issues

I'm pretty sure I use the correct SDRAM selection for the LPC1788 and correct shift value for the MODE register!

Thomas
0 Kudos

531 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by PhilYoung on Tue Jun 12 11:09:50 MST 2012
I just noticed the memory test code, this will not test anything.
writing a repeated pattern to memory and reading it back will never detect any addressing errors, in particular for external memory where the data bus will usually have a bus hold capability.

Try changing the memory test to simply write an ascending number to each location.

for a simple test I usually start with 0x0102 then add 0x0101 at each address, this gives a reasonable first pass detection as the overflow of the first byte prevents a regular pattern being repeated throughout memory.

regards

Phil.
0 Kudos

531 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by tjoAG on Mon Jun 11 02:48:25 MST 2012
Hi Kevin

Just adding some comments.

From the LPC1788 data sheet page 179 section 10.12.19:

"The SDRAM bank select pins BA1 and BA0 are connected to address lines A14 and A13,
respectively."

On fig 17 on page 188 a 16 bit interface is connected from CPU A[a_b:1] to SDRAM A[a_m:0] where a_b is the higest order address line on the address bus, and on the a_m is the highest order address line on the used SDRAM.

I have connected the SDRAM starting from CPU A0 to A13. Must it be moved by one address line so I use A1-A14?
0 Kudos

531 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by tjoAG on Mon Jun 11 02:19:27 MST 2012
Hi Kevin

I'm not 100% sure I program the MODE correctly, but I think so.

I'm using MICRON MT48LC8M16A2 128 Mbit SDRAM, R=12, C=9, Banks=4
Row addressing is A0-A11
Collumn addressing is A0-A8
Bank selection is BA0-Ba1

I'm running the EMC clock at 120 MHz, so according to the datasheet a CAS latency of 3 must be used.

RBC mode:

I set the Dynamic Config mode to 0x480 (RBC mode) and the use mode word is

<code>wtemp = *((volatile uint32_t *)(SDRAM_BASE_ADDR | (0x33<<(12)))); /* 8 burst, 3 CAS latency */ </code>

I then use this code, just to verify the SDRAM:

<code>
// 16 bit write
for (i=0; i<(0x01000000/2); i++)
{
  *short_wr_ptr++ = 0xAAAA;
}
/ 16 bit read
short_wr_ptr = (uint16_t *)0xA0000000;
for (i=0; i<(0x01000000/2); i++)
{
  if(*short_wr_ptr != 0xAAAA)
  {
     while(1);
  }
  short_wr_ptr++;
}
</code>

When I use the above SDRAM init code (RBC), the RAM validation work.
I know it is not a in depth RAM test, but if that doesn't work something is wrong.


BRC:

In BRC mode I'm doing this instead:
I set the Dynamic Config mode to 0x1480 (BRC mode) and the use mode word is

<code>wtemp = *((volatile uint32_t *)(SDRAM_BASE_ADDR | (0x33<<(10)))); /* 8 burst, 3 CAS latency */ </code>

Then I have memory holes at:

0xA040 0000 - 0xA071 ffff
0xA0C0 0000 - 0xA100 0000

The other location seems to work.

When I run in the RBC mode, the data in SDRAM keeps changing when the LCD gets enabled
When I run in the BRC mode, the data is SDRAM dont keep changing when the LCD gets enabled. Data is shown fine on the display, but I have memory hole where I can write read?!!!

The MODE  word can still be wrong?
What about the MD (LP SDRAM) setting?
Do I read the SDRAM datasheet wrong?
Is the SDRAM connected wrong to the CPU. Maybe I set the wrong collumn, bank, burts length in the MODE word?

Please see below for the used pins and complete init code.

/Thomas

CPU pin | SDRAM
-----------------
A0 <--------> A0
A1 <--------> A1
A2 <--------> A2
A3 <--------> A3
A4 <--------> A4
A5 <--------> A5
A6 <--------> A6
A7 <--------> A7
A8 <--------> A8
A9 <--------> A9
A10 <-------> A10
A11 <-------> A10
A12 <-------> BA0
A13 <------>  BA1

<code>
uint32_t i, dwtemp;
TIM_TIMERCFG_Type TIM_ConfigStruct;

/* Initialize EMC */
InitSDRAMPins();
TIM_ConfigStruct.PrescaleOption = TIM_PRESCALE_USVAL;
TIM_ConfigStruct.PrescaleValue= 1;

// Set configuration for Tim_config and Tim_MatchConfig
TIM_Init(LPC_TIM0, TIM_TIMER_MODE,&TIM_ConfigStruct);

//Configure memory layout, but MUST DISABLE BUFFERs during configuration
LPC_EMC->DynamicConfig0    = 0x00000480; /* 128B, 8Mx16, row=12, 4 banks,  column=9 */

// Configure timing for  Micron SDRAM MT48LC8M16A2-75 */
// Timing for 120MHz Bus: 8.333333 ns/clk
LPC_EMC->DynamicRasCas0    = 0x00000303; // 3 RAS, 3 CAS latency to run more then 100 MHz bus
LPC_EMC->DynamicReadConfig = 0x00000001; // Command delayed strategy, using EMCCLKDELAY
LPC_EMC->DynamicRP         = 0x00000002; // Min 20ns. (n + 1) -> 3 clock cycles
LPC_EMC->DynamicRAS        = 0x00000005; // Min 44 ns.(n + 1) -> 6 clock cycles
LPC_EMC->DynamicSREX       = 0x00000009; // Min 75 ns. ( n + 1 ) -> 10 clock cycles
LPC_EMC->DynamicAPR        = 0x00000002; // ??? ( n + 1 ) -> 2 clock cycles  5
LPC_EMC->DynamicDAL        = 0x00000004; // tWR + tRP: min 35 ns (n + 1) -> 5 clock cycles
LPC_EMC->DynamicWR         = 0x00000001; // Min 15 ns. ( n + 1 ) -> 2 clock cycles
LPC_EMC->DynamicRC         = 0x00000007; // Min 66 ns. ( n + 1 ) -> 8 clock cycles
LPC_EMC->DynamicRFC        = 0x00000007; // Min 66 ns. ( n + 1 ) -> 8 clock cycles
LPC_EMC->DynamicXSR        = 0x00000009; // Min 75 ns. ( n + 1 ) -> 10 clock cycles
LPC_EMC->DynamicRRD        = 0x00000001; // Min 15 ns. ( n + 1 ) -> 2 clock cycles
LPC_EMC->DynamicMRD        = 0x00000001; // 2 tCK. ( n + 1 ) -> 2 clock cycles

TIM_Waitms(100);   /* wait 100ms */
LPC_EMC->DynamicControl    = 0x00000183; /* Issue NOP command */
TIM_Waitms(200);   /* wait 200ms */
LPC_EMC->DynamicControl    = 0x00000103; /* Issue PALL command */
LPC_EMC->DynamicRefresh    = 0x000007ff; /* ( n * 16 ) -> 32 clock cycles */

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

//Timing for 120MHz Bus
LPC_EMC->DynamicRefresh    = 0x1d; // ( n * 16 ) -> 1872 clock cycles -> 15.60uS at 120MHz <= 15.625uS ( 64ms / 4096 row )

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

//Timing for 48/60/72MHZ Bus
dwtemp = *((volatile uint32_t *)(SDRAM_BASE_ADDR | (0x33<<(12)))); /* 8 burst, 3 CAS latency */
LPC_EMC->DynamicControl    = 0x00000000; /* Issue NORMAL command */

//[re]enable buffers
LPC_EMC->DynamicConfig0
</code>
0 Kudos

531 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by wellsk on Fri Jun 08 16:19:00 MST 2012
I can guess that the mode word was just programmed wrong when in one of the modes.
If this happens, DRAM may appear to work, especially for single locations. But once you do a DRAM burst (which the LCD does), you'll see bad data.

>But Im running the SDRAM in RBC mode so why does the LCD controller not work in that mode??
If you are not doing it now, try shifting the mode offset for the mode operation right by 2 when in RBC mode to see if it works.

You can test DRAM burst by using the ARM STM/LDM instructions to write and read DRAM. If this works for RBD and BRC configurations and you are sure you are programming the mode word correctly, I can't tell you what's wrong, but maybe some of the other developers might have some ideas.
0 Kudos

531 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by tjoAG on Fri Jun 08 12:58:08 MST 2012
Hi

I see. But Im running the SDRAM in RBC mode so why does the LCD controller not work in that mode??
Normal SDRAM access work fine. Reading and writting fine.
But the when the LCD controller is enabled the data is changing in the SDRAM.

Switching to BRC mode makes the LCD controller not alternating the SDRAM contens?

Thomas
0 Kudos

531 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by wellsk on Fri Jun 08 09:38:55 MST 2012
The DRAM and LCD controller will work in both modes. When switching between BRC or RBC modes in the DRAM controller, you'll also need to tweak the mode word operation.
It sounds like maybe your mode word is statically setup for one specific mapping mode.

For example, if your mode word is 0x31 (ie, CAS3, burst 1) and you have a device with COLS=10, ROWS=9, BANKS=2 (all in bits)
In RBC mode, the mode would be programmed as * (volatile unsigned long *) (DRAM_BASE_ADDRESS + (0x31 << (COLS + BUSSIZE + 0))
In BRC mode, the mode would be programmed as * (volatile unsigned long *) (DRAM_BASE_ADDRESS + (0x31 << (COLS + BUSSIZE + BANKS))
Note: BUSSIZE = 0, 1, or 2 --for-- 8, 16, or 32-bit DRAM configurations

You can also look at the LPC32x0 DRAM application note. It mostly applies to the lpc17xx device too...
http://www.lpcware.com/content/nxpfile/an10935-using-sdrddr-sdram-memories-lpc32xx

The LPC32x0 code (which uses the same controller) does something like this...
#if SDRAM_USE_PERFORMANCE_MODE==1
        /* Performance mode : Row - Bank - Col mapping */
        modeshift = SDRAM_COLS + bus32 + 1 + SDRAM_BANK_BITS;
        bankshift = SDRAM_COLS + bus32 + 1;
#else
        /* Low power mode : Bank - Row - Col mapping */
        modeshift = SDRAM_COLS + bus32 + 1;
        bankshift = SDRAM_COLS + SDRAM_ROWS + bus32 + 1;
#endif
0 Kudos