LCD Frame Buffer

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

LCD Frame Buffer

2,303 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by dustinkasel on Tue Jul 31 15:24:19 MST 2012
I have a custom designed board populated with the LPC1788 and a 32-bit wide SDRAM chip. I seem to be having bus contention issues between the LCD and my frame buffer update routine. I have found that if I allow them to access the memory space simultaneously the LCD gets out of sync and displays pseudo-random data. So if I load buffer #1 with half red data and the other half with blue, the LCD will display this beautifully. As soon as I begin accessing (asynchonrously) the SDRAM to write to buffer 2, the blue and red data start mixing randomly. Does anyone know how to synchronize my buffer updates with the LCD DMA requests so that I don't step on those requests? I thought changing the matrix arbitration register might help but that did not seem to make a difference which is also puzzling.

And on a related note, what was NXP thinking forcing users to under-clock the CPU if they want to use SDRAM?! Why is the EMC limited to 80MHz?

Thanks in advance for any advice given!
Labels (1)
0 Kudos
23 Replies

1,646 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by dustinkasel on Tue Aug 28 13:16:48 MST 2012
Yeah so there were a couple of things that came out from meeting with the engineer from NXP. First off, BA0 and BA1 are connected to A13 and A14 regardless of how many address lines you actually use. I made the assumption that these lines were the most-significant-bits of the address lines.

I also had a solder ball across RAS-CAS that wasn't helping the cause.

Finally I had to re-calculate all of the timing parameters. The SDRAM example that comes with the peripheral library is more or less worthless for real-world testing. I will admit it does run and pass it's tests on the EA board, which has the same part on the SOM as I have.

Interestingly the CAS-RAS issue manifested itself as a refresh failure. I didn't catch this right away because I was constantly reading from/writing to RAM. Once I put long delays in-between accesses that issue popped up.
0 Kudos

1,645 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Dave on Tue Aug 28 09:51:51 MST 2012
So, after our email discussion, did you ever solve your problem?  Perhaps others can benefit from your solution, Dustin...

0 Kudos

1,646 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by mc on Mon Aug 20 19:32:12 MST 2012
Hi engin,
Yes SPI is for touch panel.
0 Kudos

1,646 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by dustinkasel on Mon Aug 06 12:54:28 MST 2012
Dave, I built a project that I have sent to you via email. Can you give this a try on your board when you have time? Let me know what you see (I would expect simply a red screen). If that does work, try un-commenting the code in the while loop and see if anything changes. On my board it quickly changes to blue.

Engin, unfortunately I also have not worked with emWin.
0 Kudos

1,651 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Dave on Sun Aug 05 22:15:23 MST 2012
I cannot reply.  I have not worked with the emWin library yet.  Sorry.
0 Kudos

1,651 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by e135193 on Sun Aug 05 21:10:17 MST 2012
Hello Dave

    I clearly know my post is off topic. I have already started a new thread. However no one replys. I know that you are so proficient and you will reply at least an answer.

    The pace of this comunity is so slow. There are less senior people like you.

    Could you reply one of my threads please ?

    http://www.lpcware.com/content/forum/customising-emwin-516-any-other-7-lcd

    http://www.lpcware.com/content/forum/eas-7-lcd-interface


Engin
0 Kudos

1,651 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Dave on Sun Aug 05 14:09:25 MST 2012
Ummm, your post is a little off topic, Engin.   Perhaps you would do better with starting a new thread.  I recommend you formulate a question as the thread header, and post your question there...

Good luck,
0 Kudos

1,651 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by e135193 on Sun Aug 05 06:49:25 MST 2012
Hello

Is that enough to modify the settings below for costumising emWin for my LCD ?

Link for my LCD's datasheet : http://elinux.org/images/0/07/AT070TN83.pdf

#define HBP_TRULY_3_2   28       // Horizontal back porch in clocks
#define HFP_TRULY_3_2   10       // Horizontal front porch in clocks
#define HSW_TRULY_3_2   2        // HSYNC pulse width in clocks
#define PPL_TRULY_3_2   240      // Pixels per line
#define VBP_TRULY_3_2   2        // Vertical back porch in clocks
#define VFP_TRULY_3_2   1        // Vertical front porch in clocks
#define VSW_TRULY_3_2   2        // VSYNC pulse width in clocks
#define LPP_TRULY_3_2   320      // Lines per panel
#define IOE_TRULY_3_2   0        // Invert output enable, 1 = invert
#define IPC_TRULY_3_2   1        // Invert panel clock, 1 = invert
#define IHS_TRULY_3_2   1        // Invert HSYNC, 1 = invert
#define IVS_TRULY_3_2   1        // Invert VSYNC, 1 = invert
#define ACB_TRULY_3_2   1        // AC bias frequency in clocks (not used)
#define BPP_TRULY_3_2   16       // Bits per pixel b110 = 16 bpp 5:6:5 mode
#define CLK_TRULY_3_2   8200000  // Optimal clock rate (Hz) between 1-8.22 MHz according to SSD1289 datasheet
#define LCD_TRULY_3_2   0        // Panel type; 0: LCD TFT panel
#define DUAL_TRULY_3_2  0        // No dual panel


As far as I can see from the datasheet of the FEMA LCD, there is no need for an SPI interface for LCD. Then, you do not need the code samples below for your LCD. Do you ? I guess that you need SPI interface just for touch panel interface. Am I rigth ?


static void _InitTrulyLCD(void) {
  //
  // Power LCD
  //
  LPC_GPIO2->DIR |= 1;  // Set to output
  LPC_GPIO2->SET  = 1;  // Output LCD power
  //
  // Set display CMD/DATA register select pin to output high
  //
  LPC_GPIO0->DIR |= (1 << LCD_REG_BIT);
  //
  // Display init sequence
  //
  _WriteLcdReg(0x00,0x0001);
  _DelayMs(15 * 2);
  _WriteLcdReg(0x03,0x6E3E);  // AAAC
  _WriteLcdReg(0x0C,0x0007);  // 0002
  _WriteLcdReg(0x0D,0x000E);  // 000A
  _WriteLcdReg(0x0E,0x2C00);  // 2C00
  _WriteLcdReg(0x1E,0x00AE);  // 00B8
  _DelayMs(15 * 2);

  _WriteLcdReg(0x07,0x0021);
  _DelayMs(50 * 2);
  _WriteLcdReg(0x07,0x0023);
  _DelayMs(50 * 2);
  _WriteLcdReg(0x07,0x0033);
  _DelayMs(50 * 2);

  _WriteLcdReg(0x01,0x2B3F);
  _WriteLcdReg(0x02,0x0600);
  _WriteLcdReg(0x10,0x0000);
  _DelayMs(15 * 2);
  _WriteLcdReg(0x11,0xC5B0);  // 60B0: RGB I/R
  _DelayMs(20 * 2);
  _WriteLcdReg(0x15,0x00D0);

  _WriteLcdReg(0x05,0x0000);
  _WriteLcdReg(0x06,0x0000);
  _WriteLcdReg(0x16,0xEF1C);
  _WriteLcdReg(0x17,0x0003);
  _WriteLcdReg(0x07,0x0233);
  _WriteLcdReg(0x0B,0x5310);
  _WriteLcdReg(0x0F,0x0000);
  _WriteLcdReg(0x25,0xE000);
  _DelayMs(20 * 2);

  _WriteLcdReg(0x41,0x0000);
  _WriteLcdReg(0x42,0x0000);
  _WriteLcdReg(0x48,0x0000);
  _WriteLcdReg(0x49,0x013F);
  _WriteLcdReg(0x44,0xEF00);
  _WriteLcdReg(0x45,0x0000);
  _WriteLcdReg(0x46,0x013F);
  _WriteLcdReg(0x4A,0x0000);
  _WriteLcdReg(0x4B,0x0000);
  _DelayMs(20 * 2);

  _WriteLcdReg(0x30,0x0707);
  _WriteLcdReg(0x31,0x0600);  // 0704
  _WriteLcdReg(0x32,0x0005);  // 0204
  _WriteLcdReg(0x33,0x0402);  // 0201
  _WriteLcdReg(0x34,0x0203);
  _WriteLcdReg(0x35,0x0204);
  _WriteLcdReg(0x36,0x0204);
  _WriteLcdReg(0x37,0x0401);  // 0502
  _WriteLcdReg(0x3A,0x0302);
  _WriteLcdReg(0x3B,0x0500);
  _DelayMs(20 * 2);
  _WriteLcdReg(0x22,0x0000);
  _DelayMs(20 * 2);
}


Thanks in advance

engin
0 Kudos

1,651 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Dave on Sat Aug 04 14:41:33 MST 2012
Dustin,

Reviewing your calculation for throughput:

(800*480)/8 = 48000 operations (both read and write).
Each operation is a 32-bit wide operation, or 4 bytes.
48000*4 = 192000 = number of bytes per time frame.

The scope indicates the write operation takes 2.56ms and the read operation takes 4.66ms (on my board), so processor is writing 75MB/sec and reading 41.2MB/sec...

Does this sound right to you?
0 Kudos

1,651 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by dustinkasel on Fri Aug 03 10:06:39 MST 2012
For anyone interested, I was able to bring an FAE in to look at this issue. Not surprisingly, it stumped him as well. I have attached a test application if anyone (Dave) would like to try it out. You'll probably need to select a different GPIO in the while loop based on what you have easy access to. The low pulse length will be the write time; high pulse length will be the read time.

Throughput in MB/s = (48000 words / pulse length) * 4

Thanks for everyone's help!
0 Kudos

1,651 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Dave on Thu Aug 02 16:07:47 MST 2012
Sure... I'll give it a shot.
0 Kudos

1,651 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by dustinkasel on Thu Aug 02 15:11:58 MST 2012
If I post a performance test project would you be able/willing to try it out on your board? For measurement I am just toggling a GPIO so you would need access to an unused one.

Thanks for all your help so far Dave!
0 Kudos

1,651 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Dave on Thu Aug 02 12:16:29 MST 2012
Gotchya - you're using the exact same device I'm using...

I missed the part about the display earlier - you're using a FEMA display - funny, so am I... ( do you know George? )

'cept mine is 640x480...

One thing I did find during development of my own board was that I needed to adjust my delays a bit higher to remove some speckling on the display - my SDRAM memory test indicated no errors, but from time to time there were random pixels being set on the display...


Increasing the values for both the feedback clock and the command outputs eliminated the problem

<code>
         //DelayConstant = 0x00000B05;      // dev kit works at 0B05...                         
         DelayConstant = 0x00000F07;      // SBC R1 works at 0F07...                        

   *
   *
   *

   // Setup delays  (Note:  UM has an error in Table #140 - should look like this:                                         
   // [Ref: LPC178x_7x_UM_1.4 page 183 ]                                                                                   
   // ----------------------------------------------------------------------------------------------------------------------
   // Bit      Symbol         Description                                                                              Reset
   //                                                                                                                  Value
   // ----------------------------------------------------------------------------------------------------------------------
   // 4:0      CMDDLY         Programmable delay value for EMC outputs in command delayed mode. See                    0x10
   //                         Section 10.12.6. The delay amount is roughly (CMDDLY+1) * 250 picoseconds.                   
   // 7:5      -              Reserved. Read value is undefined, only zero should be written.                          NA  
   // 12:8     FBCLKDLY       Programmable delay value for the feedback clock that controls input data sampling. See   0x02
   //                         Section 10.5.3. The delay amount is roughly (FBCLKDLY+1) * 250 picoseconds.                  
   // 15:13    -              Reserved. Read value is undefined, only zero should be written.                          NA  
   // 20:16    CLKOUT0DLY     Programmable delay value for the CLKOUT0 output. This would typically be used in clock   0x00
   //                         delayed mode. See Section 10.12.6 The delay amount is roughly (CLKOUT0DLY+1) *               
   //                         250 picoseconds.                                                                             
   // 23:21    -              Reserved. Read value is undefined, only zero should be written.                          NA  
   // 28:24    CLKOUT1DLY     Programmable delay value for the CLKOUT1 output. This would typically be used in clock   0x00
   //                         delayed mode. See Section 10.12.6 The delay amount is roughly (CLKOUT1DLY+1) *               
   //                         250 picoseconds.                                                                             
   // 31:29    -              Reserved. Read value is undefined, only zero should be written.                          NA  
   //                                                                                                                      
   //  ---X XXXX ---X XXXX ---X XXXX ---X XXXX => DelayConstant = 0x00000C04                                               
   //  0000 0000 0000 0000 0000 1100 0000 0100 => CMDDLY=0x04=1250ps & FBCLKDLY=0x0C=3.25ns                                
   LPC_SC->EMCDLYCTL   = DelayConstant;
</code>
0 Kudos

1,651 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by dustinkasel on Thu Aug 02 10:33:46 MST 2012
Yeah, I didn't mean your code is now sitting in project files, I just meant I dropped your code in a dummy project to try it out.

The exact part number of the chip I'm using is: MT48LC2M32B2P-6:G TR

I think my next step will be to try this out on a development board to verify my trace routing isn't to blame. My board is not impedance matched (controlled dielectric) but the trace width and length was tuned during the layout. In my experience, controlled-dielectric doesn't really become a necessity until you hit several hundred megahertz.
0 Kudos

1,651 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Dave on Thu Aug 02 10:07:06 MST 2012
Sorry, I didn't mean that you should "copy" my code, I meant you should verify your values... each SDRAM device has a table with timing constants.  Your device is probably not the same as my device...  By the way, what is your device anyway???

I use my device with multiple display pages, and never have any contention - I also run my devices at 120Mhz...  again, no problems...

This indicates to me that it is possible, and more than probably you haven't programmed the EMC, the SDRAM, or the LCD controller the way you think you have...

There are several complete examples on how to program the EMC and SDRAM here - Wolfgang has even uploaded his entire driver set here I believe...

The trick is to make sure you have the timing values set properly, and that you are configuring the LCD controller properly...

Not sure how much more I can help without actually doing it for you...

Oh, one more thing - you indicated you are using a custom board - how confident are you in the design?  Trace spacing, signal grouping, matched trace lengths, trace widths, dah, dah, dah...   All of this comes into play, and can really screw things up if you don't have them just right.

Oh, and another thing - what's the maximum frequency of the SDRAM part you are using?

Just thinking out loud...

Hope this helps,
0 Kudos

1,651 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by dustinkasel on Thu Aug 02 09:00:51 MST 2012
Dave, I actually tried your initialization code line for line in a test application and saw little difference in performance. I am seeing a maximum throughput of ~35MB/s with the CPU at 120MHz and the EMC at 60MHz. This means it's taking an average of 7 clock cycles to transfer one word. Are these numbers reasonable?
0 Kudos

1,651 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Dave on Wed Aug 01 15:45:06 MST 2012
Comments 14-19 address the missing MODE command...  lol

Timing is certainly important - can you verify your values for these registers, as I have shown here:
<code>
   // *** Taken from the MT48LC2M32B2 data sheet, page 47 ***                                  
   // configure timing, from Table 18:                                                         
   // -6 (6ns part) timings (see marking on actual chip: MT48LC2M32B2-6)                       
   // NOTE: all timing values for LPC1788 are in units of CLK counts                           
   // ------------------------------------------------------------------------------------------
   LPC_EMC->DynamicRP   = NS_2_CLKS(18);     // tRP: precharge command period             (18ns)
   LPC_EMC->DynamicRAS  = NS_2_CLKS(42);     // tRAS: active to precharge command period  (42ns)
   LPC_EMC->DynamicSREX = NS_2_CLKS(70);     // tXSR: self-refresh exit time              (70ns)
   LPC_EMC->DynamicAPR  = NS_2_CLKS(18);     // tAPR: last-data-out to active command time     
                                             // note: no tAPR value, using tRCD value     (18ns)
   LPC_EMC->DynamicDAL  = CAS_Latency+2;     // tDAL: data-in to active command time           
                                             //       for CL=3, tDAL = 5 tCK                   
                                             //       for CL=2, tDAL = 4 tCK                   
                                             //       for CL=1, tDAL = 3 tCK                   
   LPC_EMC->DynamicWR   = (1+NS_2_CLKS(6));  // tWR: write recovery time is (12ns) UNLESS we're
                                             //      using AUTO PRECHARGE, then it's   (tCK+6ns)
   LPC_EMC->DynamicRC   = NS_2_CLKS(60);     // tRC: ACTIVE-to-ACTIVE command period      (60ns)
   LPC_EMC->DynamicRFC  = NS_2_CLKS(60);     // tRFC: AUTO REFRESH period                 (60ns)
   LPC_EMC->DynamicXSR  = NS_2_CLKS(70);     // tXSR: Exit self refresh to ACTIVE command (70ns)
   LPC_EMC->DynamicRRD  = NS_2_CLKS(12);     // tRRD: active bank A to active bank B command   
                                             //       latency                             (12ns)
   LPC_EMC->DynamicMRD  = 2-1;               // tMRD: LOAD MODE REGISTER command to ACTIVE or  
                                             // REFRESH command time                      (2tCK)

</code>
0 Kudos

1,651 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by dustinkasel on Wed Aug 01 14:17:26 MST 2012
Thanks Dave. One thing about your post, right before you send the MODE register, shouldn't you have to send the MODE command? I didn't see that line of code anywhere.

Unfortunately this didn't resolve my problem. I have checked the clock output, it running 84MHz as I thought it was.

One new piece of information is that it currently takes about 13 ms to write 48,000 words. This means it's taking 270ns or ~23 clock cycles to complete one write. Does this imply a timing error somewhere?
0 Kudos

1,651 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Dave on Wed Aug 01 12:02:04 MST 2012
Back when this forum first got started I posted a thread about setting up the EMC to talk to an LCD...

There is a lot of good stuff in that thread.  There is also a discussion on the shift, and how far...

You can find the thread here: http://lpcware.com/content/forum/dk-57vts-lpc1788-configuring-emc-sdram

Have a look and see what you think.

0 Kudos

1,651 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by dustinkasel on Wed Aug 01 10:21:45 MST 2012
Thanks for the post Dave. I did try your suggestion, it didn't seem to have any effect. Can you explain to me why the value of ConfigPointer needs to be shifted left?

Do you see anything else I should look into?
0 Kudos