Skip to main content
Graduate II
March 18, 2025
Question

800 x 800 Display with STM32U5G9VJT6Q - possible?

  • March 18, 2025
  • 5 replies
  • 1940 views

Hi,

we are trying to get a 800x800 display to work with the STM32U5G9VJT6Q, using either RGB888 or RGB565 in Video Mode (Burst).

According to what we read it is definitely possible. Did we miss something?

Could someone please confirm that is definitely possible?

Much appreciated

Thank you

    This topic has been closed for replies.

    5 replies

    Technical Moderator
    March 18, 2025

    Dear @Ricko ,

     

    This application Note may help you with more details : Introduction to LCD-TFT display controller (LTDC) on STM32 MCUs - Application note

    The Pixel clock Frequency is key . do you know your target Refresh Rate ?   it is also Key element  for the computation.

    Hope it helps you.

    STOne-32.

    RickoAuthor
    Graduate II
    March 18, 2025

    Thank you @STOne-32 

    the refresh rate is 60Hz and the pixel clock calculated is 44MHz (values in the attached excel screenshot).

    I did read that document a while back and from table 17 on page 31 (screenshot below) it seems to be ok and plenty of headroom (max allowed is 116MHz in the screenshot attached).

    When I set the LTDC to 44MHz the CubeMX clock configurator auto-generates a DSI byte clock of 33MHz (264MHz DSI clock lane using 2 lanes). And that also seems well within the STM32U5G9 specs.

    All that seems to suggest that I can drive the display specs I mentioned above.

     

    Two questions please:

    1. Are those calculations correct?

    2. Also, whether I set colour to RGB888 or RGB565 (in LTDC and in DSI panels in CubeMX), the auto-calculated DSI byte clock is automatically calculated to 33MHz. Should it not change with the higher RGB (i.e. RGB888)?

     

    Thank you :)

     

    Ricko_3-1742285702547.png

     

    Ricko_0-1742285185887.png

     

    Technical Moderator
    March 19, 2025

    Dear @Ricko ,

    Your calculation is correct. and indeed Table 17 is the key one - you select your configuration at each Column and to ensure not exceeding the Maximum Pixel clock. for example, for Color Depth 24 bpp using LTDC and DMA2D up to 48MHz.  Regarding STM32CubeMX clock generation, you can force a manual configuration as well, let us know if you need further assistance.

    Hope it helps you.

    Ciao

    STOne-32.

    RickoAuthor
    Graduate II
    March 19, 2025

    Thank you @STOne-32 

    my understanding is that in that scenario around 33MHz for the DSI byte clock is the minimum value. How much faster can I set the DSI byte clock while keeping the pixel clock at 44MHz? Can I push it to the DSI HOST's PHY maximum allowable or do I need to keep it around that 33MHz?

    What is the logic/reasoning and pros/cons to decide the upper limit in this specific example?

    Thank you :)

     

     

    Graduate II
    March 19, 2025

    LTDC clock is based on pixels ... 880x840x60 = 44,352MHz , but DSI clock is based on data to send and here seems you miss. For RGB888 video mode simple calc is 800x800x24x60 = 921,6Mbit/s for 2 lanes per lane around 460Mbit plus sync ahead . byte clock is 480Mbit/8 minimum.

    Graduate
    October 21, 2025

    Hi Ricko,

    Did you get your display working? I'm having similar problems with a Tailor Pixels display (TTH040BRT-02C) which also uses JD9365DA-H3. I am sure I have the timings correct but the display remains blank.

    I know that LP commands are being processed correctly as I am enabling the TE output to check the frame timing and this is correct. I've also used the LP command to activate the display built in self test which works, but oddly only if the D-PHY bus is stopped, the JD98365 datasheet is poor so this may just be how it's supposed to operate. 

    I'm using STM32F469 and have taken into account the maximum supported pixel frequency as per AN4861 and discussed earlier in this post.

    I have been succesful using Tailor Pixels TTH345BRS display, but this uses FL7705 controller.

    Do let us know how you got on with driving your display. :)

     

     

    RickoAuthor
    Graduate II
    November 11, 2025

    Hi@RobNewbury 

    Apologies, I haven't logged in for weeks so I just saw your message.

    Interestingly I was using a Taylor Pixels Display too...

    I got it kind of working... the image was split in two halves and the right half of the image was displaying on the left half of the display... and the right half of the image was displaying on the left half of the display.

    It took months only to get to that point so the project was then dropped. 

    Did you get yours working?

    Thank you

    Rick

     

     

    Graduate
    November 12, 2025

    Hi @Ricko 

    Thanks for getting back to me. Yes I have got both my Tailor Pixels displays working! But it's probably a bit like having a baby, it was so painful getting there, I can't remember what I did to make them work, otherwise you would never try again!

    That said, luckily I wrote it down.

    1. For the TTH040BRT-02C display (this uses Jadard JD9365DA-H3) and is 720x720 pixels.
      The problem was that I had incorrectly set the DSI packet size to 800. I had thought that the packet size needed to include all the sync's as well as the active pixels, however this assumption seems to be wrong so the JD9365DA-H3 was just ignoring any data sent to it on the DSI-PHY.
      I changed the setting to 720 (which is the active pixel width) and it all worked great!
    2. For the TTH345BRS display (uses FL7705 display controller) and is 800 x800. I was trying to initialise the display in HS mode. This worked 70% of the time, so I changed to sending the initialisation in LP mode and all is now ok.

    Interesting what you say about the screen vertical lock. I've seen this also, but only on some screens. I found that by adusting the pixel clock (which also adjusts the vertical sync timing) you can walk the vertical sync to the edge of the screen. However I don't understand why this only happens with some and not all rendered screens. I have a hunch that it may be some sort of timing issue to do with TouchGFX double buffer access beating with Vsync? As I find it's not a problem if you render direct to GRAM without involving TouchGFX.
    It's one of my next jobs (after sorting out TouchGFX TBS's) to address this. I'll let you know how I get on.

    By the way I've been working on this 2 years (on and off) and only now do I consider the project to be far enough on to order prototype PCB's, up untill now I've been interfacing to a DISCO board. ... So don't give up!

    Graduate
    November 13, 2025

    @Ricko Hi Rick, It's a bit tricky to define what got the display working as there are number of parameters that need to configured correctly and work in unison before the display will do anyting sensible at all. Besides, it sounds like you have gone beyond that stage, i.e. to get the display to render, even if it's not synced correctly, you must have written a display driver to initialise the display and set up the LTDC plus DSI accordingly using CubeMX.
    We're also using different procesors, mine is STM32F649, yours is STM32U5G9VJT6Q I believe, so the HAL etc., will be different.

    What I found helpful was to add some test code in a user area in Main.c.

    I added this code immediately after the initialization code.

    It does the following:-

    1. Invokes the inbuilt pattern generator of the DSI, this will verify that the DSI and display is working ok regardless of the LTDC and framebuffer setup.
    2. Write the pixel values for RED, then GREEN, then BLUE (I'm using 16 bit RGB) direct to the frame buffer. This will tell you if the frame buffer and LTDC are seup correctly regardless of any higher level configuration.
    /* USER CODE BEGIN 2 */
    
     /* for test, show pattern generator for 2s */
    
     HAL_DSI_PatternGeneratorStart(&hdsi,0,0);
    
     HAL_Delay(2000);
    
     HAL_DSI_PatternGeneratorStop(&hdsi);
    
    
    
    // Now check the colours
    
     uint8_t *framebuffer;
    
     framebuffer =(uint8_t *)0xc0000000;
    
    // Red Screen
    
     uint8_t *fb = framebuffer;
    
     while(fb < (uint8_t*)(framebuffer + (720*720*2)))
    
     {
    
     *fb++ = 0x00; // Write red colour
    
     *fb++ = 0xf8; //
    
     }
    
     HAL_Delay(2000);
    
    //Green Screen
    
     fb = framebuffer;
    
     while(fb < (uint8_t*)(framebuffer + (720*720*2)))
    
     {
    
     *fb++ = 0xE0; // Write green colour
    
     *fb++ = 0x07; //
    
     }
    
     HAL_Delay(2000);
    
     //Blue Screen
    
     fb = framebuffer;
    
     while(fb < (uint8_t*)(framebuffer + (720*720*2)))
    
     {
    
     *fb++ = 0x1F; // Write blue colour
    
     *fb++ = 0x00; //
    
    
    
     }
    
     HAL_Delay(2000);
    
    
    
     /* USER CODE END 2 */

    I hope this helps.

    RickoAuthor
    Graduate II
    November 17, 2025

    Thank you @RobNewbury ! :)

     

     

    Graduate
    December 16, 2025

    @Kelly3 To be clear, my set up is a bit different to yours as I'm using STM32F469, I have successfully interfaced to two different displays, one uses FL7705 controller and the other JD9365A controller, I have written bespoke drivers for both types of display controller. I'm also using 2 lanes MIPI DSI, I now have both display types working well but it took a lot of effort and time to get this far.

     Initially I tried to initialise in HS mode but the display was initialising correctly only about 50% of the time. I switched to LP mode and then found that I got bus errors, I can't remember what the error was but it sounds like this may be a similar issue to the one that you are having.

    What I found was that when initialising in LP mode, the LTDC needs to be started before calling the display initialisation code, but when in HS mode, the LTDC needs to be started after calling the display initialisation code.

    Below is my function MX_LTDC_Init from main.c and is generated by CubeMX, I have added code in USER CODE BEGIN LTDC_Init 2.
    My display initialisation code is the function  TTH345BRS_Init()

    When I switched to LP mode to initialise the display, I had to move the macro that starts the LTDC, __HAL_LTDC_ENABLE(&hltdc) to be before the call to the display initialistaion function TTH345BRS_Init().

    On the other hand, in HS mode, the LTDC needs to be enabled after the display is initialised and is how CubeMX had originally configured the code. I dare say this works with some displays in both HS and LP mode. 

    I hope this helps.

     

    static void MX_LTDC_Init(void)

    {

     

    /* USER CODE BEGIN LTDC_Init 0 */

    LTDC->IER |= LTDC_IER_LIE; // Enable LTDC interrupts

    /* USER CODE END LTDC_Init 0 */

     

    LTDC_LayerCfgTypeDef pLayerCfg = {0};

     

    /* USER CODE BEGIN LTDC_Init 1 */

     

    /* USER CODE END LTDC_Init 1 */

    hltdc.Instance = LTDC;

    hltdc.Init.HSPolarity = LTDC_HSPOLARITY_AL;

    hltdc.Init.VSPolarity = LTDC_VSPOLARITY_AL;

    hltdc.Init.DEPolarity = LTDC_DEPOLARITY_AL;

    hltdc.Init.PCPolarity = LTDC_PCPOLARITY_IPC;

    hltdc.Init.HorizontalSync = 59;

    hltdc.Init.VerticalSync = 7;

    hltdc.Init.AccumulatedHBP = 119;

    hltdc.Init.AccumulatedVBP = 27;

    hltdc.Init.AccumulatedActiveW = 919;

    hltdc.Init.AccumulatedActiveH = 827;

    hltdc.Init.TotalWidth = 979;

    hltdc.Init.TotalHeigh = 847;

    hltdc.Init.Backcolor.Blue = 0;

    hltdc.Init.Backcolor.Green = 0;

    hltdc.Init.Backcolor.Red = 0;

    if (HAL_LTDC_Init(&hltdc) != HAL_OK)

    {

    Error_Handler();

    }

    pLayerCfg.WindowX0 = 0;

    pLayerCfg.WindowX1 = 800;

    pLayerCfg.WindowY0 = 0;

    pLayerCfg.WindowY1 = 800;

    pLayerCfg.PixelFormat = LTDC_PIXEL_FORMAT_RGB565;

    pLayerCfg.Alpha = 255;

    pLayerCfg.Alpha0 = 0;

    pLayerCfg.BlendingFactor1 = LTDC_BLENDING_FACTOR1_PAxCA;

    pLayerCfg.BlendingFactor2 = LTDC_BLENDING_FACTOR2_PAxCA;

    pLayerCfg.FBStartAdress = 0xc0000000;

    pLayerCfg.ImageWidth = 800;

    pLayerCfg.ImageHeight = 800;

    pLayerCfg.Backcolor.Blue = 0;

    pLayerCfg.Backcolor.Green = 0;

    pLayerCfg.Backcolor.Red = 0;

    if (HAL_LTDC_ConfigLayer(&hltdc, &pLayerCfg, 0) != HAL_OK)

    {

    Error_Handler();

    }

    /* USER CODE BEGIN LTDC_Init 2 */

     

    DSI_LPCmdTypeDef LPCmd;

    LPCmd.LPGenShortWriteNoP = DSI_LP_GSW0P_DISABLE;

    LPCmd.LPGenShortWriteOneP = DSI_LP_GSW1P_DISABLE;

    LPCmd.LPGenShortWriteTwoP = DSI_LP_GSW2P_DISABLE;

    LPCmd.LPGenShortReadNoP = DSI_LP_GSR0P_DISABLE;

    LPCmd.LPGenShortReadOneP = DSI_LP_GSR1P_DISABLE;

    LPCmd.LPGenShortReadTwoP = DSI_LP_GSR2P_DISABLE;

    LPCmd.LPGenLongWrite = DSI_LP_GLW_DISABLE;

    LPCmd.LPDcsShortWriteNoP = DSI_LP_DSW0P_DISABLE;

    LPCmd.LPDcsShortWriteOneP = DSI_LP_DSW1P_DISABLE;

    LPCmd.LPDcsShortReadNoP = DSI_LP_DSR0P_DISABLE;

    LPCmd.LPDcsLongWrite = DSI_LP_DLW_DISABLE;

    HAL_DSI_ConfigCommand(&hdsi, &LPCmd);

     

    HAL_DSI_Start(&hdsi);

     

    clear_screen();

    __HAL_LTDC_ENABLE(&hltdc);

    TTH345BRS_Init(TTH345BRS_FORMAT_RGB888,TTH345BRS_ORIENTATION_LANDSCAPE);

     

    // HAL_LTDC_SetPitch(&hltdc, 1024, 0);

     

     

    /* USER CODE END LTDC_Init 2 */

     

    }

     

     

    Graduate
    December 17, 2025

    @RobNewbury ,Thank you for your sharing!  I tried start DSI -> start LTDC-> initial display in LP mode, The display can't be initialized.  I guess F4 might be different from U5.

    In your code, DCS long write, DCS short write, generic long write and generic short write are LP mode disabled, i.e. they are all set  to HS mode.  Is the above code for initial display in HS mode? 

    Are you using burst video mode? or other mode? 

     

    Graduate
    December 17, 2025

    @Kelly3 I'm using HAL_DSI_ShortWrite() and HAL_DSI_LongWrite(), I'm using these in LP mode, I'm not aware that these functions are LP mode disabled, I am definetly using LP mode and they are working for me?

    I'm using burst video mode, below is my DSI set up. Check that the VACT value is correct for your display. My other display is 720 pixels and I had the VACT set to 800 pixels, the display wouldn't initialise until I changed VACT to 720. I had thought that the VACT should include VS period in pixel clock cycles, however that is not the case.

    Another mistake I had made was to initialise the display to RGB888 and the DSI to RGB565.

    I hope that you get your display working.  

    RobNewbury_0-1766006424074.png

    RobNewbury_1-1766007930969.png

     

    This is my DSI write code.

    void DSI_IO_WriteCmd(uint32_t NbrParams, uint8_t* pParams)

    {

    HAL_StatusTypeDef status;

    status = HAL_ERROR;

     

    if (NbrParams <= 1)

    {

    status = HAL_DSI_ShortWrite(&hdsi, LCD_TTH345BRS_ID, DSI_DCS_SHORT_PKT_WRITE_P1, pParams[0], pParams[1]);

    }

    else

    {

    status = HAL_DSI_LongWrite(&hdsi, LCD_TTH345BRS_ID, DSI_DCS_LONG_PKT_WRITE, NbrParams, pParams[NbrParams], pParams);

    }

    }