[STM32U5] [NUCLEO-U575ZI-Q Evaluation] Transplant LVGL8.2 to ILI9488 display part

STM32U575 has a running frequency of 150MHz, and today I tried ILI9488 to transplant LVGL8.2
1. Hardware preparation: NUCLEO-U575ZI development board, ILI9488SPILCD screen.
2. Software preparation: atomic lvgl8.2 source code, MDK5, stm32cubeMX
【Transplantation process】
1. Configure spi1, open stm32cubeMX and configure spi as follows:
[attach]2085158[/attach]

2. Configure TIM6 timer
[attach]2085162[/attach]
3. Clock and other configurations are not described here. Then generate the mdk project.
4. Open the project with mdk, add the ili9488 driver, see the attachment for the program: 5. Create a new LVGL folder under the project directory, and create a GUI folder and a GUI_APP folder under this folder, and finally create a new one under the GUI folder lvgl folder. The specific folder structure is shown in the following figure:

6. Copy the LVGL source code to the project /GUI/lvgl path
7. Add the grouping as shown in the figure below

8. Add all .c files under the core folder to the /lvgl/src/core group. 9. Add the draw folder to the /lvgl/src/draw group except nxp_pxp, nxp_vglite, sdl and stm32_dma2d folders All .c files.
10. Add all .c files in the extra folder except the lib folder to the lvgl/src/extra group
11. Add all .c files under the font folder to the lvgl/src/font group
12. Add all .c files under the draw/stm32_dma2d and draw/sdl folders to the /lvgl/src/gpu group.
13. Add all .c files under the hal folder to the /lvgl/src/hal group.
14. Add all .c files under the misc folder to the lvgl/src/misc group.
15. Add all .c files under the widgets folder to the lvgl/src/widgets group.
16. Add the lv_port_disp_template.c and lv_port_indev_template.c files in the /lvgl/examples/porting directory to the lvgl/examples/porting group.
17. Add header file path To transplant LVGL, you only need to add the key header file path, because the lvgl.h file has saved us a lot of operations including header files. The added header file path is as follows As shown in the figure

18. Add timer
Add back in the callback function of Timer6 as follows:

/* USER CODE BEGIN 1 */

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)

{

        if(htim->Instance==TIM6)

                {

       lv_tick_inc(1); /* lvgl 1ms time base*/

                }



}

/* USER CODE END 1 */

19. Configure display driver
lv_port_disp_template.c/h (display related) in the /lvgl/examples/porting group The conditional compilation directive #if 0 in both files
Change it to #if 1, as shown in the source code below:
before fixing:
#if 0 /* lv_port_disp_template.c/h
After modification:
#if 1 /* Change #if 0 to #if 1 */
Modify the lv_port_disp_template.c file
This file is used to configure the display, it can connect the user’s underlying display driver with the LVGL display driver. We open the official lv_port_disp_template.c file
Add ili9488 driver header file reference:
#include “ILI9488.h”
set screen resolution
#define MY_DISP_HOR_RES (320) /* wide */
#define MY_DISP_VER_RES (480) /* high */

Set comment out lv_disp_draw_buf_t draw_buf_dsc_1, lv_disp_draw_buf_t draw_buf_dsc_2, keep
/* Example for 3) also set disp_drv.full_refresh = 1 below*/
static lv_disp_draw_buf_t draw_buf_dsc_3;
static lv_color_t buf_3_1[MY_DISP_HOR_RES * MY_DISP_VER_RES]; /*A screen sized buffer*/
static lv_color_t buf_3_2[MY_DISP_HOR_RES * MY_DISP_VER_RES]; /*Another screen sized buffer*/
lv_disp_draw_buf_init( & draw_buf_dsc_3, buf_3_1, buf_3_2, MY_DISP_VER_RES * 480); /*Initialize the display buffer*/

Modify the block display function as follows:

static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
{
    /*The most simple case (but also the slowest) to put all pixels to the screen one-by-one*/

    int32_t x;
    int32_t y;
                uint16_t width=320;
                uint16_t height=480;
                uint32_t i, n, cnt, buf_size, h, w;
                uint8_t r,g,b;
                w = area->x2- area->x1;
                h = area->y2- area->y1;
                setAddrWindow(area->x1, area->y1, area->x2, area->y2); //Set display block size
                n = w*h*3;
                n = w*h*3;
       //Split and send to the screen
        if (n <= 65535){
                cnt = 1;
                buf_size = n;
        }
        else {
                cnt = n/3;
                buf_size = 3;
                uint8_t min_cnt = n/(65535) + 1;
                for (i=min_cnt; i < n/3; i ++ ){
                        if(n%i == 0){
                                cnt = i;
                                buf_size = n/i;
                                break;
                        }
                }
        }
        
        DC_DATA();
        CS_A();
                while(cnt>0)
                {
                        uint8_t frm_buf[buf_size];
                        for (i=0; i < buf_size/3; i ++ )
                        {
                                r = (((color_p->full & 0xF800) >> 11) * 255) / 31;
                                g = (((color_p->full & 0x07E0) >> 5) * 255) / 63;
                                b = (color_p->full & 0x001F * 255) / 31;
                                frm_buf[i*3] = r;
                                frm_buf[i*3 + 1] = g;
                                frm_buf[i*3 + 2] = b;
                                 color_p++;
                        }
                        //HAL_SPI_Transmit( & amp;hspi1, frm_buf, buf_size, HAL_MAX_DELAY);
                        HAL_SPI_Transmit( &hspi1, frm_buf, buf_size, 10);
                        cnt -= 1;
                }
                CS_D();
               
        
    /*IMPORTANT!!!
     *Inform the graphics library that you are ready with the flushing*/
    lv_disp_flush_ready(disp_drv);
}

20. Add lv_demo_widgets() in the official demo;
Copy the widgets in the demo to the GUI_APP directory, add the demo/widgets directory, and add all the C files in the widgets directory:
[attach]2085172[/attach]
Then add the path to the folder of the header files.
21. Modify main.c to add back the user code to realize the function:

 ILI9488_Init();



        lv_init(); /* lvgl ? */

 lv_port_disp_init(); /* lvgl ?, lv_init()? */



 lv_obj_t *label = lv_label_create(lv_scr_act());

 lv_label_set_text(label,"Hello STM32U575!!!\\
 HELLO 21ic!!!");

 lv_obj_center(label);

 lv_demo_widgets();

  /* USER CODE END 2 */

        

  /* Infinite loop */

  /* USER CODE BEGIN WHILE */

  while (1)

  {

                lv_timer_handler(); /* LVGL ? RTOS ? */

                HAL_Delay(5);

    /* USER CODE END WHILE */



    /* USER CODE BEGIN 3 */

  }

  /* USER CODE END 3 */

Realize the effect as shown in the figure

At this point, the transplantation of lvgl’s display screen has come to an end. It’s just a touch unfinished.
———————
Author: lulugl
Link: https://bbs.21ic.com/icview-3288468-1-1.html
Source: 21ic.com
This article has won the original/original award label, the copyright belongs to 21ic, and anyone is prohibited from reprinting without permission.