LVGL Test

LVGL Introduction

LVGL (Light and Versatile Graphics Library) is an open-source graphical user interface (GUI) library designed to provide efficient, low-resource-consumption graphical display solutions for embedded devices. It is widely used in low-power, resource-constrained embedded systems, supports multiple hardware platforms, and offers a rich set of graphical interface components and animation effects.

LVGL is completely open-source, which offers several significant advantages. First, it gives you full control over the library, as you can not only view, modify, compile, and debug the underlying source code but also acquire it in its entirety. Once downloaded, it belongs to you. This independence from a single vendor is immensely valuable. Additionally, being open-source encourages collaboration and knowledge sharing, with developers worldwide contributing to the software's improvement, making it more reliable and feature-rich to solve a wide range of real-world problems.

LVGL is released under the MIT license, which allows users to freely use, modify, and distribute the software without being subject to complex restrictions or conditions. This provides flexibility for developers and businesses to integrate the software into their own projects, even for commercial purposes, as long as they retain the original author's attribution.

VDMA Introduction

AXI VDMA (abbreviated as VDMA) is a soft-core IP provided by Xilinx, used to convert data streams from AXI Stream format to Memory Map format or from Memory Map format to AXI Stream format. In other words, VDMA is designed to provide video read/write transfer functionality from the AXI4 domain to the AXI4-Stream domain, enabling high-speed data movement between system memory (primarily DDR3) and AXI4-Stream-based target video IPs. Its functionality is somewhat similar to AXI DMA (DMA), primarily providing high-bandwidth data transfer between PS-side memory and AXI4-Stream type target peripheral memories. VDMA is an upgraded version of DMA tailored for video and image applications. Compared to DMA, VDMA adds features such as a Frame Buffer mechanism and GenLock (dynamic synchronization locking). VDMA integrates video-specific functions like frame synchronization and 2D DMA transfers, making it highly suitable for image and video processing on the ZYNQ architecture and shortening the development cycle for developers.

LCD Touchscreen

The LCD screen used here has a resolution of 1024*600, an RGB888 interface, and a GT911 touch chip. The specific parameters of the LCD screen are shown in the figure below:

image-20250822102741030

Create Vivado Project

In this design, the core task of the image display process is to implement the driving and display functions of the LVGL graphics library on an RGB LCD. The overall system architecture, as shown in the figure, is primarily accomplished through the collaboration of the Processing System (PS) and Programmable Logic (PL).

The specific process is as follows:

Overall Framework:

image-20250805090638457

This will be based on the previously created Vivado project, which already includes functionalities like HDMI and PL_NET. For their configurations, you can refer to the previous setup steps. Here, we will primarily add or modify some configurations:

Supplement the Zynq PS related configurations:

image-20250822103808391

Here, FCLK_CLK0 is used for LVGL, FCLK_CLK1 is for HDMI, and FCLK_CLK2 is for PL_NET1.

image-20250822104302196

Here, HP0 is used for HDMI, and HP1 is for LVGL.

image-20250822104725441

Add 7 GPIO pins via EMIO for the control signals of the LCD screen and touch panel.

image-20250822105528683

Add VDMA. Search for and add the VDMA module, then double-click to open its configuration page.

image-20250731162618441

This project only uses the read function of the VDMA, so the Enable Write Channel feature is unchecked here. The frame buffer is set to 2. Since the content we are displaying is RGB888 (24-bit color), the Stream Data Width is changed to 24. The Line Buffer Depth is changed to 2048, and the Read Burst Size is modified to 64.

image-20250731162840942

Add the Video Out module. The purpose of this module is to convert the AXI4-Stream data flow into a standard video format output, corresponding to the RGB LCD screen.

image-20250731165810614

Change Clock Mode to Independent. For Timing Mode: since we will use the Video Timing Controller module to provide video timing later, select Slave mode here:

image-20250731170337068

Add the Video Timing Controller module: Search for and add the Video Timing Controller module, then double-click to open its configuration page.

 

image-20250731170526406

Page one:

image-20250731170702535

Page two:

On the second page, we set the resolution. Here, we will first set it to 1024x600. Select CUSTOM, and fill in the other parameters as shown in the figure below. These configurations can be modified later through the Vitis code on the PS side.

For a description of the corresponding parameters, you can refer to: Video Beginner Series 16: Understanding Video Timing with the VTC IP

image-20250731170858279

Modify the parameters according to the figure below. The modification method will be described later.

 

Add the clk_wiz module: Search for and add the clk_wiz module, then double-click to open its configuration page:

image-20250731174318633

Configure as shown in the figure below: The AXI interface needs to be enabled so that the output frequency can be controlled via Vitis.

image-20250731174348654

image-20250731174411056

 

At this point, we have all the necessary modules. The next step is to connect them.

 

Left-click the 'plus' sign on the vid_io_out port of the Video Out module to expand its contents. Select the vid_active_video, vid_data, vid_hsync, and vid_vsync signals, then right-click and select 'Make External' to bring out the signals.

image-20250731171911618

Rename these signals to lcd_de, lcd_data, lcd_hsync, and lcd_vsync respectively. (Select the signal and modify its name in the 'Name' field in the left pane).

image-20250731173509721

Connect the clk of the VTC (Video Timing Controller) module to the clk_out1 pixel clock. Since this clk and the pixel clock need to be highly synchronized, the clk of the AXI4-Stream to Video Out module should also be connected to this pixel clock.

image-20250731174550095

Add the connection for the GEN_CLKEN of the Video Timing module as shown in the figure below.

image-20250731175434383

Click 'Run Connection Automation' to automatically connect the remaining traces.

image-20250731175455968

In the pop-up settings dialog, check all the items, and the system will automatically connect the remaining signal lines and add the necessary modules for us.

Add a Constant module to provide a constant '1', which will be used to connect the ce and aclken enable signals of our various modules.

image-20250731175728700

image-20250731175858429

The final connection diagram is as follows: The highlighted IPs are the new ones added in this project.

image-20250902140013062

Save the project, then click Source → Design Sources. Right-click the block design we created and click 'Create HDL Wrapper'.

image-20250801090722040

Configure the pin assignments according to the schematic:

image-20250801143429974

The completed .xdc file:

Compile and synthesize the project, generate the bitstream, then go to File → Export → Export Hardware to export the .xsa file.

Create Vitis Project

Create a New Platform Project:

image-20250730115142359

image-20250730115513634

Select the .xsa file you just exported and change the operating system to freertos:

image-20250804174649206

Create a New Application Project:

image-20250730115853514

image-20250730120012260

Select an empty file here

image-20250730120108384

Add and Modify Files:

Create clk_wiz File

Create a clk_wiz folder under src: used to set the output clock frequency of the IP core.

image-20250730134515934

image-20250804091526290

Add the .c file

Create display_ctrl file

Code source: https://github.com/Digilent/Zybo-hdmi-out/tree/master/sdk/displaydemo/src/display_ctrl

image-20250804094923894

In vga_modes.h, you need to modify the following parameters according to your screen resolution:

image-20250822114919485

Configure according to the timing table above:

Create Touch File

Create touch.c and touch.h, using the GT911 touch screen:

image-20250804102146048

About GT911

This chip is a capacitive touch screen driver IC that supports a 100Hz contact scan rate, 5-point touch, and 18*10 detection channels. The GT911 connects to the FPGA via 4 wires: SDA, SCL, RST, and INT. Among them, SDA and SCL are for I2C communication, RST is the reset pin (active low), and INT is the interrupt signal. The GT911 uses standard I2C communication with a maximum rate of 400KHz. The I2C device address for the GT911 can be 0X14 or 0X5D. Within 5ms after a reset, if the INT pin is high, the address 0X14 is used; otherwise, 0X5D is used. For this project, we will use 0xBA as the device address.

The code is as follows:

Create VDMA files:

Create vdma.c and vdma.h:

image-20250804103508171

For the specific code implementation, you can refer to the example provided by Xilinx.

image-20250804104355196

image-20250804104443461

image-20250804104459768

VDMA Code:

Create DMA File:

Similar to VDMA, the code can be based on the example provided by Xilinx.

image-20250804105359842

Modify the code based on the template:

It is important to note that there is a limit to the length of data a single DMA channel can transfer (found in the DMA BSP code: xdmaps.c).

The amount of data that needs to be transferred in a single operation varies with the LCD resolution. For example, at a 1024*600 resolution with RGB888 format, a single DMA transfer requires 1024 * 600 * 3 = 1843200 bytes.

At high resolutions, the length of the data to be transferred may exceed the maximum capacity of a single DMA channel. In this case, you can either increase the burst size and burst len, or split the data transfer across multiple DMA channels.

DMA section code:

Porting LVGL Files

LVGL_V9.2.2 Source Code Download Link

Create two folders under src: lvgl/lvgl and lvgl/lvgl_app,

image-20250801150638056

Copy lvgl-9.2.2/src and lvgl-9.2.2/examples to src/lvgl/lvgl;

Copy lvgl-9.2.2/lv_version.h, lvgl-9.2.2/lv_version.h.in, lvgl-9.2.2/lvgl.h to src/lvgl/lvgl

image-20250805093929984

 

Copy lvgl-9.2.2/lv_conf_template.h to src/lvgl and rename it to lv_conf.h

image-20250805093950548

Modify the content of the lv_conf.h file according to the following images:

image-20250801152055815

 

image-20250801152205535

 

image-20250801152226076

 

image-20250801152245671

Delete all files and folders except porting under src/lvgl/lvgl/examples, and delete the osal folder under the porting file

In the FreeRTOS configuration of the platform project, set tick_rate to 1000, meaning one tick every 1ms; set use_tick_hook to true

image-20250801153442257

Add the following to main.c:

 

Modify the following four files:

Change #if 0 to #if 1 in all four files,

Modify the lv_port_indev_template.c file as follows:

In the lv_port_disp_template.c file, modify the screen width and height and add the following (keep the rest unchanged):

Adding main.c

image-20250730133911127

All files created at the end are as follows:

image-20250801155705429

Compilation and Debugging

Connect the touchscreen and ZYNQ development board,

Use TYPE-C to connect the development board's JTAG port to the computer, perform Build and debug, and observe the LCD display.

image-20250822144736415