Esp32 LVGL 8.3 initialization problem ili9341

I’ve got problem with display anything on display and got stuck totally. I’m trying to run display on esp32 with lvgl 8.3.4 and lvgl_esp32_drivers from master branch but after initialization I get only flickering white/black screen with no image (its looks like the white screen is flickering with display refreshrate). I did not have any errors.


What MCU/Processor/Board and compiler are you using?

esp32 wrover with espidf 4.4.3

What do you want to achieve?

Proper display initialization

What have you tried so far?

Code to reproduce


#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_freertos_hooks.h"
#include "freertos/event_groups.h"
#include "display.h"

#include "../lvgl_tft/disp_driver.h"
#include "../lvgl_helpers.h"
#include "sdkconfig.h"

static struct display_ctx disp_ctx = 
    .backlight = NULL, 
    .disp = NULL, 
    .indev = NULL, 
    .is_valid = false

static lv_disp_draw_buf_t draw_buf;
static lv_disp_drv_t disp_drv;
static lv_color_t buf_1[320 * 10];

disp_backlight_config_t backlight_config;
disp_backlight_h backlight_h = NULL;

static lv_indev_drv_t indev_drv;
lv_indev_t* indev = NULL;
lv_disp_t* disp = NULL;

static const char *TAG = "Display";

void display_task(void* param)
    ESP_LOGI(TAG, "Display task created");
        vTaskDelay(10 / portTICK_RATE_MS);

void IRAM_ATTR lv_tick_task(void)

lv_disp_t* init_display()
    lv_disp_draw_buf_init(&draw_buf, buf_1, NULL, LV_HOR_RES*10);

    disp_drv.hor_res = LV_HOR_RES;
    disp_drv.ver_res = LV_VER_RES;
    disp_drv.draw_buf = &draw_buf;
    disp_drv.flush_cb = disp_driver_flush;
    disp = lv_disp_drv_register(&disp_drv);

    if(disp == NULL)
        disp_ctx.is_valid = false;
        return NULL;

    xTaskCreate(display_task, "DisplayTask", 4096, NULL, 1, NULL);
    disp_ctx.is_valid = true;
    ESP_LOGI(TAG, "Display created");

    return disp;

disp_backlight_h* init_backlight()
    ESP_LOGI(TAG, "Initializing backlight");
    backlight_config.gpio_num = CONFIG_LV_DISP_PIN_BCKL;
    backlight_config.pwm_control = true;
    backlight_config.channel_idx = 0;
    backlight_config.timer_idx = 0;
    backlight_h = disp_backlight_new(&backlight_config);
    if(backlight_h == NULL)
        ESP_LOGE(TAG, "Cannot init baclight");
        disp_ctx.is_valid = false;
        return NULL;
    ESP_LOGI(TAG, "Backlight initialized");
    disp_ctx.is_valid = true;
    return &backlight_h;

void set_backlight(int percentage)
    disp_backlight_set(backlight_h, percentage);

lv_indev_t* init_indev()
    ESP_LOGI(TAG, "Creating indev");

    indev_drv.type = LV_INDEV_TYPE_POINTER;
    indev_drv.read_cb = touch_driver_read;
    indev = lv_indev_drv_register(&indev_drv);
    if(indev == NULL)
        ESP_LOGE(TAG, "Cannot register indev driver");  
        disp_ctx.is_valid = false;      
        return NULL;

    ESP_LOGI(TAG, "Indev created");
    disp_ctx.is_valid = true;
    return indev;

display_ctx* create_display_ctx()
    ESP_LOGI(TAG, "Creating display context");
    disp_ctx.disp = init_display();
    disp_ctx.backlight = init_backlight();
    disp_ctx.indev = init_indev();
    if(!disp_ctx.is_valid || disp_ctx.disp == NULL || 
        disp_ctx.backlight == NULL || disp_ctx.indev == NULL)
        ESP_LOGE(TAG, "Cannot create display context");
        return NULL;

    ESP_LOGI(TAG, "Display context created");
    return &disp_ctx;

esp_err_t dispose(display_ctx** ctx)
    ESP_LOGI(TAG, "Disposing ");
    *ctx = NULL;
    disp_ctx.is_valid = false;
    disp_ctx.disp = NULL;
    disp_ctx.indev = NULL;
    disp_ctx.backlight = NULL;
    disp = NULL;
    indev = NULL;

    return ESP_OK;


#ifndef __DISPLAY_H__
#define __DISPLAY_H__

#include "esp_log.h"
#include "esp_err.h"
#include "lvgl.h"
#include "esp_lcd_backlight.h"

#ifdef	__cplusplus
extern "C" {

typedef struct display_ctx 
    bool is_valid; // should be allways checked and modified
    lv_disp_t* disp;
    lv_indev_t* indev;
    disp_backlight_h* backlight;
} display_ctx;

// Creating display context is recommended for create diaplay
display_ctx* create_display_ctx();
lv_disp_t* init_display();
lv_indev_t* init_indev();
disp_backlight_h* init_backlight();
void set_backlight(int percentage);
esp_err_t dispose(display_ctx** ctx);

#ifdef	__cplusplus


Logs from serial port:

I (4640) Display: Creating display context
I (4640) lvgl_helpers: Display buffer size: 0
I (4650) lvgl_helpers: Initializing SPI master for display
I (4660) lvgl_helpers: Configuring SPI host SPI2_HOST
I (4660) lvgl_helpers: MISO pin: -1, MOSI pin: 23, SCLK pin: 18, IO2/WP pin: -1, IO3/HD pin: -1
I (4670) lvgl_helpers: Max transfer size: 0 (bytes)
I (4680) lvgl_helpers: Initializing SPI bus…
I (4680) disp_spi: Adding SPI device
I (4690) disp_spi: Clock speed: 40000000Hz, mode: 0, CS pin: 5
I (4890) ILI9341: Initialization.
I (5090) ILI9341: Display orientation: LANDSCAPE
I (5090) ILI9341: 0x36 command value: 0x28
I (5090) disp_backlight: Setting LCD backlight: 100%
I (5090) lvgl_helpers: Initializing SPI master for touch
I (5100) lvgl_helpers: Configuring SPI host SPI3_HOST
I (5100) lvgl_helpers: MISO pin: 12, MOSI pin: 13, SCLK pin: 14, IO2/WP pin: -1, IO3/HD pin: -1
I (5110) lvgl_helpers: Max transfer size: 0 (bytes)
I (5120) lvgl_helpers: Initializing SPI bus…
I (5120) XPT2046: XPT2046 Initialization
I (5130) gpio: GPIO[26]| InputEn: 1| OutputEn: 0| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
I (5140) Display: Display task created
I (5140) Display: Display created
I (5150) Display: Initializing backlight
I (5150) Display: Backlight initialized
I (5150) Display: Creating indev
I (5160) Display: Indev created
I (5160) Display: Display context created
I (5170) disp_backlight: Setting LCD backlight: 100%

Can somebody tell me where I did mistake?

I found the problem. After updating lvgl from 7 to 8, lvgl drivers lost definitions for #define DISP_BUF_SIZE. I forgot that changed LV_HOR_RES_MAX to LV_HOR_RES but it doesn’t work properly. Temporarly hardcoded this variable to display horizontal dimmension.


1 Like