cancel
Showing results for 
Search instead for 
Did you mean: 

My TFT display looks ok, but after adding code to my project, not related to the display driver, the screen output is skeewed / Distorted. Need help thinking

Zainka
Associate III

HW setup is a self built board using the STM32H743V MCU and a Sharp LQ104V1DG61 TFT display. Display is setup to L8 and using CLUT table, Running on 25MHz (measured) it has a 640x480 format, RGB666 (yes I know that is not part of the supported format list in the STM datasheet, but I will come back to that one). Datasheet may be found here: https://static.davandisplay.com/document/product/LQ104V1DG61-Specs.pdf

Using STM32CubeIDE. 

The following is the initializing code

#define TH     760    // Total Horizontal time (clocks)  
 #define HSYNC   34    
 #define HBP     44        
#define HW     640  
 #define HFP     (TH-HSYNC-HBP-HW)
 
#define TV     555      // Total Vertical time (clocks)     
 #define VSYNC   10        
 #define VBP     20       
 #define VW     480    
 #define VFP     (TV-VSYNC-VBP-VW) 
 
 /* configure LTDC */
  LTDC->SSCR = ((HSYNC-1) << 16) | (VSYNC-1);
  LTDC->BPCR = ((HSYNC+HBP-1) << 16) | (VSYNC+VBP-1);
  LTDC->AWCR = ((HSYNC+HBP+HW-1) << 16) | (VSYNC+VBP+VW-1);
  LTDC->TWCR = ((HSYNC+HBP+HW+HFP-1) << 16) | (VSYNC+VBP+VW+VFP-1);
  LTDC->GCR = 0b0000 << 28; // Set HS, VS, DE and PC polarity. (1=Active High, 0=Active Low)
  LTDC->BCCR = (240 << 16) | (240 << 8) | (240); 
   
 /* configure layer 1 */
  LTDC_Layer1->WHPCR = ((HSYNC+HBP+HW-1) << 16) | (HSYNC+HBP);
  LTDC_Layer1->WVPCR = ((VSYNC+VBP+VW-1) << 16) | (VSYNC+VBP);
  LTDC_Layer1->PFCR = 0x05; 
  LTDC_Layer1->CACR = 255;                         
  LTDC_Layer1->DCCR = (0xFF << 24) | (0x00 << 16) | (0xFF << 8) | (0x00); 
  LTDC_Layer1->CFBAR = (uint32_*)Framebuffer1; 
  LTDC_Layer1->CFBLR = (HW*3 << 16) | (HW*3 + 7);
  LTDC_Layer1->CFBLNR = VW; 
  LTDC_Layer1->CR |= LTDC_LxCR_LEN;                               
 
   LTDC->SRCR = LTDC_SRCR_IMR;                                 
  LTDC->GCR |= LTDC_GCR_LTDCEN;
  
 
The framebuffer is defined as follow: 
 char Framebuffer1[640*480 + 1]; // 307200 pixels + 1
 

Some of these parametres have a range of allowed values and I have tried a few combinations , for example to enusre that the hsync-vsync phase different does not become greater than allowed value. The RGB666 format is not mentioned in the STM32 datasheet, but this should not be of any problem since the 2 extra bits pr color is simply not connected to the display, it could lead to a color missmatch but the display should still work since it has a parallell interface. The display does not care for the extra bits and the MCU does not know they are trashed. 

Well, all that mentioned, Thing and problem is. Whit the paramtetres, and several other combinations, shown above, the screen shows up perfectly. I may write text, load images and etcetra. But Sometimes when I add extra code to my program the screen gets skeewed like as if the image was a water-painting someone tried to wipe out, or as if the number of pixel pr. line changed but the MCU still think it is 640 so that the next line has an offseth to previous line. You are able to see that it tries to show the correct image but it gets corrupted

The code added does not need to have anything to do with display functionality, for example I added a few variables and the problem arised. When I removed the code, the display was OK again.

What I have done is to check for heap/memory errors, could not find any, Memory usage is 68%. 

I think its a RAM issue still which screws up the framebuffer, it seems to have something to do if the position of the Framebuffer1 is changed , but I cant find any reason for that though and the Buffer is always withing the RAM D1 section

What I need is some ideas for further investigation. Maybe you have seen similar behaviour with your own code sometime, All I hope for is some thoughts for what could alter the behaviour of a perfectly working display like that

Thanks in advance

1 ACCEPTED SOLUTION

Accepted Solutions

Perfect you make own reply. I use in all projects framebuffer in SDRAM started on zero addr, then this issue dont see, but yes LTDC have limitation for place start . Then use __attribute__((aligned (8)))

For details read https://www.st.com/resource/en/application_note/dm00287603-lcdtft-display-controller-ltdc-on-stm32-mcus-stmicroelectronics.pdf

 page 47

View solution in original post

8 REPLIES 8

Make sure downstream code isn't ballsing up the PLL clocks into LTDC

Unpack the PLLs and PIXCLKs clock chains, compare working vs not-working

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Zainka
Associate III

The clock remains unchanged. I have used a Freq.Counter to monitor the clock and it is very stable, 25MHz sharp. The PLL clock registry does also remain unchanged.

I have some more information regarding the suspected memory issue.

The only change I do in the code is to add a variable or mor correct an array

static char States[25];

Thats the one change that is inserted. Did some experiments here, When the array size is 25 and above, the display is corrupted, 24 and below it is ok. The memory status window says that only 68% of the memory section D1 is used,. When compiling the States array is allocated before the Framebuffer1 thus moving it in memory. I have no clue for why that should affect the display but somehow it does. Display registers are setup correctly, PLLs are correct, the layer 1 frame address register has the correct address, and so on.

Checked the map file

Map when display ok

0x0000000024004b78                Framebuffer1
 *fill*         0x000000002404fb79        0x3

Map when display corrupted (witharray with size 25)

0x0000000024004b94                Framebuffer1
 *fill*         0x000000002404fb95        0x3

Are there RAM segments within the RAM D1 segment, could it be that the rather large Framebuffer1 (size 0x4b001) buffer "breaks" on some boundary ?... No, that sound silly, I really have no clue, and what is the purpose of the "fill" segment?

MM..1
Chief III

Try show image when fail and check iRQ code. Or show code what you add.

Zainka
Associate III

There are no error interrupts

Here is the images showing corrupted and OK image

The only different is that the array size mentioned is 24 and not 25 for OK immage. Memory usage is 68%

0693W0000059EU8QAM.jpg0693W0000059EU3QAM.jpg 

EDIT:

Looking at the corrupted image you see that it is the same image as for the ok display. However, i noticed now that the 4 last lines are not part of the image. I guess this possibly indicates sync issue for when display expects first data and when the MCU transmits it.

You will see a similar behaviour if one deliberately program the frame start and stop addresses for layer 1 with wrong values (Either horizontal or line or both in register L1_WHPCR and L1_WVPCR), then you will also see this skew. But in the tests above these remains unchanged and should not be affected by the introduced code, and the clock/timing setup for LTDC is as mentioned earlier also unchanged.

I wonder if it could be sync issues with the enable signal but struggles to see how the code i insert (declaing the array) possible could affect this in any ways.

The display supports two settings for how to control the data enable signal, either by pulling it high when data is transmitted or by counting clocks while always keeping data enable low. I will recode and see if this might fix anything as soon as i get the time. Right now my rather old oscilloscope have trigger issues so I am not able to measure it properly.

MM..1
Chief III

I use HAL to init Layers and not direct registers, but as first you need check ltdc work with CLUT properly.

Init in main only all hw and set half framebuffer to one color second to other :

init clut

memset((void *)Framebuffer1,20,640*240); //color 20 clut

memset((void *)(Framebuffer1+640*240),190,640*240); //color 190 clut

start ltdc

while(1);

When this work your problem is other as ltdc.

And WTF is??? The only different is that the array size mentioned is 24 and not 25 for OK immage.

Where to begin...

I used HAL initially until the problem arise but switched after a while with struggles. The problem with HAL is that you loose connection with the HW. It kinda takes the fundamentals out of the fundament.... Using direct registers gives you two very important benefits, you learn a lot about the chip you are using, it educates you so to say, and in my opinion it makes debugging far far more easier. As mentioned I started out using HAL but switching to registers makes the code more readable. One may like it... or not. And just for the records, I had the same issues and behavior when using HAL. ;) But now I at-least know the fundamentals of the LTDC registers.

The code I run today is much like as you describes it, Its just the framebuffer filled with some known data. Its no problem with the CLUT either. The image in my example is an indexed image using the CLUT table loaded. I have of-course also tried with the buffer filled with a single value or a known pattern and this works without problems.

And WTF???? That was my reaction when the problem first arise and I start debugging to figure out what was going on.

And WTF??? is my reaction now after some further investigation. So, I understand your reaction.

The array that I referee to is just a test array I use to debug this issue, as described in a previous post. Off-course it is not the real problem, there is no link between declaring the array and the display misbehavior. But... It do, or more correctly, must be the trigger of the issue which IS the problem.

Thing is, as-mentioned initially the issues seemed to be related with where in memory the FrameBuffer is stored. Some further tests shows that the display is corrupted if address of FrameBuffer1[0] ends on hex 4 or C and so on, but works perfectly if stored on address ending on 0 or 8..... Could it be related with the ALIGN tag in the linker-script.? It is for RAM_D1 set to 4 so all variables are stored on a boundary of 4.

Map snippets with differnt FrameBuffer1 addresses
Works
                0x0000000024004ba8                Framebuffer1
 *fill*         0x000000002404fba9        0x3 
 
*******************************
Does not work
                0x0000000024004bac                Framebuffer1
 *fill*         0x000000002404fbad        0x3 
 
 
*******************************
Works
                0x0000000024004bb0                Framebuffer1
 *fill*         0x000000002404fbb1        0x3 
 
*******************************
Does not work
                0x0000000024004bb4                Framebuffer1
 *fill*         0x000000002404fbb3        0x3

I know it sound silly but for each change in address by 0x4, the display switch between working and not working.

This also explains why Status[24] worked and Status[25] to Status[27] did not work, (these where the numbers I tried) since every increase or decrease by 4 in array size would change the FrameBuffer1 address by four.

However, WHY???? the LTDC does not work when the FrameBuffer1 is on the "Wrong" address is difficult to understand right know. I am sure there is an explanation somewhere. Something withe the ltdc register fetching data from memory which does not work well with memory alignment? (that thought was just a blind-shot), Or is it related to the fact that the AXI Bus is 64bit wide...??? Or the FiFo beeing 64bit wide

Secondly. Why does the linker script have align 4 for a RAM section? I think that sounds like a waste. For Flash section I can understand it but SRAM?

The linker script was generated by STM32Cube.

Perfect you make own reply. I use in all projects framebuffer in SDRAM started on zero addr, then this issue dont see, but yes LTDC have limitation for place start . Then use __attribute__((aligned (8)))

For details read https://www.st.com/resource/en/application_note/dm00287603-lcdtft-display-controller-ltdc-on-stm32-mcus-stmicroelectronics.pdf

 page 47

So thats the case. When starting out this project I was wondering if I needed to have external RAM but since I wanted to use many of the pheripheral features there simply was no room for an SDRAM and I could manage by using the internal RAM when it came to space. I only use one full size frame buffer anyway, the other layer is smaller.

Mucho gracias to you pointing this out for me. I owe you one :beer_mug:

And the ALIGN option in the linker script is needed since STM32xx/Coretx is a 32 bit architecture... I guess (basic question prob.)