LVGL

[中文]

1. Overview

LVGL (Light and Versatile Graphics Library) is a free, open-source, and resource-efficient embedded graphics library. It offers rich and powerful modular widgets for building beautiful user interfaces on any MCU, MPU, or display type, while supporting multiple input devices. It has become one of the most popular GUI libraries for embedded systems.

Official website: https://lvgl.io

The SDK integrates LVGL v8.3.9 and LVGL v9.3.0. Source code is located under .../ap/components/lvgl/.... Choose the version by configuring the macros CONFIG_LVGL_V8 or CONFIG_LVGL_V9.

2. Reference Projects

Multiple LVGL demo projects are available under ../projects/lvgl/.... Build command: make bk7258 PROJECT=lvgl/xxx.

Project

LCD Resolution

Data Format

Description

86box

480×480

RGB565

86-box demo

benchmark_v9

480×480

RGB565

LVGL official demo (v9.3.0)

freetype_font

400×400

RGB565

Vector-font demo (QSPI LCD)

widgets

480×480

RGB565

LVGL official demo (v8.3.9)

widgets_v9

800×480

RGB565

LVGL official demo (v9.3.0)

3. Development Workflow

LVGL integration is pre-configured in the SDK. Developers do not need to create an LVGL startup thread manually; input devices, display, and file-system support are already adapted. The general workflow is:

  1. Configure LCD parameters according to the selected panel interface and pin assignment. Refer to the display module for details.

// RGB LCD configuration example
bk_display_rgb_ctlr_config_t rgb_ctlr_config = {
    .lcd_device = &lcd_device_st7701s,
    .clk_pin = GPIO_0,
    .cs_pin = GPIO_12,
    .sda_pin = GPIO_1,
    .rst_pin = GPIO_6,
};
  1. Create the LCD display controller, configure LVGL parameters, and call lv_vendor_init().

lv_vnd_config_t lv_vnd_config = {0};

lv_vnd_config.width = rgb_ctlr_config.lcd_device->width;
lv_vnd_config.height = rgb_ctlr_config.lcd_device->height;
lv_vnd_config.render_mode = RENDER_PARTIAL_MODE;
lv_vnd_config.rotation = ROTATE_NONE;
for (int i = 0; i < CONFIG_LVGL_FRAME_BUFFER_NUM; i++) {
    lv_vnd_config.frame_buffer[i] = frame_buffer_display_malloc(lv_vnd_config.width * lv_vnd_config.height * sizeof(bk_color_t));
    if (lv_vnd_config.frame_buffer[i] == NULL) {
        LOGE("lv_frame_buffer[%d] malloc failed\r\n", i);
        return BK_FAIL;
    }
}

bk_display_rgb_new(&lv_vnd_config.handle, &rgb_ctlr_config);
lv_vendor_init(&lv_vnd_config);

Attention

Initialize the LCD controller before lv_vendor_init() and store its handle in lv_vnd_config_t so LVGL can access it when refreshing the display.

  1. Enable the LCD controller and backlight, and enable touch if present.

bk_display_open(lv_vnd_config.handle);
lcd_backlight_open(GPIO_7);

#if (CONFIG_TP)
    drv_tp_open(lv_vnd_config.width, lv_vnd_config.height, TP_MIRROR_NONE);
#endif
  1. Build the UI with LVGL widgets and start the LVGL thread via lv_vendor_start().

lv_vendor_disp_lock();
hor_page_load_main();
lv_vendor_disp_unlock();

lv_vendor_start();

Attention

  1. LVGL is not thread-safe. If UI updates run in different tasks, wrap them with lv_vendor_disp_lock() / lv_vendor_disp_unlock() to avoid crashes.

  2. Complex UIs, especially those using FreeType, may require larger LVGL stack size to prevent stack overflow.

4. Configuration Parameters

typedef struct {
    lv_coord_t width;               /**< Horizontal resolution */
    lv_coord_t height;              /**< Vertical resolution */
    lvgl_render_mode_t render_mode; /**< Partial mode uses SRAM draw buffer; other modes use PSRAM. */
    media_rotate_t rotation;        /**< 0: 0°, 1: 90°, 2: 180°, 3: 270° */
    bk_display_ctlr_handle_t handle;

    /**< Fields below normally stay default */
    uint32_t draw_pixel_size;       /**< V8: pixels; V9: bytes */
    void *draw_buf_2_1;             /**< LVGL draw buffer 1 */
    void *draw_buf_2_2;             /**< LVGL draw buffer 2 (optional high-performance mode) */
    frame_buffer_t *frame_buffer[CONFIG_LVGL_FRAME_BUFFER_NUM];
} lv_vnd_config_t;

Only six fields typically need customization:

Key LVGL parameters

Parameter

Description

width

LVGL horizontal resolution

height

LVGL vertical resolution

render_mode

Rendering mode (see lvgl_render_mode_t). Partial mode uses ~1/10 screen SRAM as draw buffer and flushes blocks to the display buffer. Other modes use PSRAM; full mode draws entire frames and is the slowest.

rotation

Screen rotation (media_rotate_t)

handle

LCD controller handle created before LVGL init

frame_buffer

Display frame buffers (default count = 2, configurable via macro)

5. Development Notes

Development notes

Topic

Description

Image decoding

Enable LV_USE_PNG, LV_USE_SJPG, LV_USE_GIF in lv_conf.h. For high-resolution images, also enable LV_PNG_USE_PSRAM, LV_SJPG_USE_PSRAM, LV_GIF_USE_PSRAM to decode in PSRAM.

File system

LVGL integrates LITTLEFS and FATFS via VFS. Enable CONFIG_VFS and choose CONFIG_FATFS or CONFIG_LITTLEFS. Call lv_vendor_fs_init() / lv_vendor_fs_deinit() to mount/unmount.

img_utility

Enable CONFIG_LV_IMG_UTILITY_CUSTOMIZE to use PSRAM pre-decoding and hardware JPEG decode.

FreeType fonts

Package fonts into BIN files, flash them to the user partition, and set CONFIG_LV_USE_FREETYPE.

Partition size adjustment

Modify auto_partitions.csv under partitions/bk7258 (ensure alignment). Run make clean before rebuilding.

Resource tools

Use the packaging tool matching the selected file system. Contact FAE if needed.