LCD

[中文]


Where are the LCD drivers and reference examples for ESP series chips?


Which adapted ICs can be used by the LCD screen of ESP32 series chips?

  • For support of SPI, I80, RGB, MIPI-DSI, and other interfaces across ESP chip series, please refer to LCD Development Guide - Supported Interface Types. Some chips (such as ESP32-C5/C6/H2/H4) do not have a native I80 peripheral, but can drive an LCD by simulating I80 timing through the Parlio interface in esp_lcd.

  • For the list of LCD driver IC components officially ported by Espressif based on esp_lcd (including I2C, SPI, QSPI, I80, MIPI-DSI, 3-wire SPI + RGB, and other interfaces), please refer to LCD Development Guide - Driver and Examples.


Common issues in application development with the ESP series chips

For common issues about the LCD screen, please refer to the LCD Application Development Notes.


Notes for Driving MIPI-DSI LCD with ESP32-P4

  • ESP32-P4 supports MIPI-DSI LCD with up to 2 lanes. Each supports a maximum rate of 1.5 Gbps, totaling 3 Gbps. It also supports color formats RGB565, RGB666, and RGB888.

  • Some MIPI-DSI LCDs, such as ILI9881C and JD9365, are configured as 4-lane by default through hardware. However, most ICs support switching to 2-lane by modifying initialization registers. The register addresses and operations vary by IC model; please consult the LCD driver IC datasheet or the panel vendor. ESP32-P4 only supports 1-lane and 2-lane configurations.

  • When configuring lane_bit_rate_mbps: the maximum must not exceed 1500 Mbps; a minimum of 480 Mbps is recommended. The actual value can be calculated from resolution, refresh rate, color depth, and lane count, then determined with a 20% margin. For the calculation method, please refer to MIPI DSI LCD Detailed Guide.

  • The MIPI-DSI driver enables the communication response mechanism (frame ACK) by default. If there is a communication anomaly between the ESP and the LCD, the ESP may freeze and trigger the watchdog. At this point, please check whether the hardware connection is correct, whether the initialization command is correct, whether the reset timing is correct, or use a logic analyzer to troubleshoot communication issues.

  • Driving a MIPI-DSI screen requires a stable 2.5 V power supply for the MIPI DSI PHY (obtained via an LDO). Please refer to the LDO configuration section in the corresponding example code.


Do ESP series development boards with screens support GUI development using the Arduino IDE?

  • The official LCD driver library for Arduino development, ESP32_Display_Panel, has been released. It can be directly downloaded on the Arduino IDE. For supported development boards, please refer to the documentation.

  • Several points to note:

    • ESP32_Display_Panel relies on arduino-esp32.

    • Due to the screen drift issue with the RGB interface of ESP32-S3, it is necessary to use features from ESP-IDF release/v5.1 or later to solve the problem. However, the ESP-IDF version used in arduino-esp32 v2.x.x is v4.4.x, which cannot solve this problem. Therefore, you should use arduino-esp32 v3.x.x. For detailed instructions, please refer to Document.

    • Given that Arduino cannot adjust various parameter configurations, such as compile optimization levels, through menuconfig like ESP-IDF, it is recommended to develop a GUI based on ESP-IDF to achieve optimal performance.


How can I improve the display frame rate of LCD screens?

  • For a detailed introduction to frame rates, please refer to the ESP-IoT-Solution Programming Guide - LCD Overview. Generally speaking, due to the computational performance of the ESP, the “interface frame rate” is often much higher than the “rendering frame rate”, so this issue can be described as “how to improve the rendering frame rate of the LCD”. This issue can be considered from the following three aspects:

    • Improve the performance of ESP. When developing with ESP-IDF, ESP can be configured through menuconfig, but it is not configured to the best performance by default. Here, taking ESP32-S3 as an example, we can increase the CPU frequency to the highest 240 MHz, increase the frequency of FreeRTOS tick to 1000, and increase the bandwidth of Flash or PSRAM. In addition, we can also increase the data cache line size, set the compilation optimization level to -O2, and so on.

    • Improve the performance of LVGL. LVGL itself can also be configured through menuconfig or the lv_conf.h file, such as setting LVGL to use the malloc and memcpy memory operation functions in ESP-IDF, enabling the fast memory compilation option, etc.

    • Optimize application design. You can make full use of CPU resources by adjusting the priority of tasks or specifying CPU cores for LVGL and other tasks, especially for ESPs with dual cores. Besides, you can also optimize the design of the GUI, such as avoiding the use of complex animations and layers with transparency overlay effects as much as possible.

  • Taking ESP32-S3R8 as an example, the following ESP configuration items can improve the frame rate (ESP-IDF release/v5.1):

    • CONFIG_FREERTOS_HZ=1000

    • CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y

    • CONFIG_ESPTOOLPY_FLASHMODE_QIO=y

    • CONFIG_ESPTOOLPY_FLASHFREQ_120M=y [should be consistent with PSRAM]

    • CONFIG_SPIRAM_MODE_OCT=y

    • CONFIG_IDF_EXPERIMENTAL_FEATURES=y and CONFIG_SPIRAM_SPEED_120M=y [should be consistent with FLASH]

    • CONFIG_SPIRAM_FETCH_INSTRUCTIONS=y

    • CONFIG_SPIRAM_RODATA=y

    • CONFIG_ESP32S3_DATA_CACHE_LINE_64B=y

    • CONFIG_COMPILER_OPTIMIZATION_PERF=y

  • On ESP32-P4, you can adjust the following configurations to increase the frame rate (applicable to ESP-IDF release/v5.4 and later; release/v6.0 is recommended):

    • CONFIG_CACHE_L2_CACHE_256KB=y

    • CONFIG_CACHE_L2_CACHE_LINE_128B=y

    • CONFIG_SPIRAM_XIP_FROM_PSRAM=y

    • CONFIG_COMPILER_OPTIMIZATION_PERF=y

  • The following LVGL configuration items can help improve the frame rate:

    • LVGL v8: CONFIG_LV_MEM_CUSTOM=y, CONFIG_LV_MEMCPY_MEMSET_STD=y, CONFIG_LV_ATTRIBUTE_FAST_MEM=y

    • LVGL v9: CONFIG_LV_OS_FREERTOS=y, CONFIG_LV_USE_CLIB_MALLOC=y, CONFIG_LV_USE_CLIB_STRING=y, CONFIG_LV_USE_CLIB_SPRINTF=y, CONFIG_LV_DEF_REFR_PERIOD=15

  • If higher frame rates, better rotation performance, and improved anti-tearing behavior are required, it is recommended to use the esp_lvgl_adapter component.


Is there any example code for I2S driving I80 LCD with ESP32/ESP32-S2?

In earlier ESP-IDF versions (v4.x and before), ESP32/ESP32-S2 drove LCD via the I80 (8080) parallel interface by reusing the I2S peripheral to simulate I80 timing. Starting from ESP-IDF v5.0, this was unified to the I80 interface of the esp_lcd component (esp_lcd_new_i80_bus), which no longer depends on I2S and provides a more standardized API.

To drive an I80 LCD, please refer directly to the i80_controller example in LCD examples, and ESP-IDF Programming Guide - I80 LCD.



How can I enable PSRAM 120M Octal (DDR) on ESP32-S3R8?

  • ESP-IDF v5.1 or later versions are required.

  • Enable configuration items through menuconfig: IDF_EXPERIMENTAL_FEATURES, SPIRAM_SPEED_120M, SPIRAM_MODE_OCT.

  • The ESP32-S3-WROOM-1-N16R16V module currently does not support this feature. If enabled, the chip may freeze upon power-up and then reset.

  • Please note it is an experimental feature still in testing and may come with the following temperature risks:

    • The chip may not work properly even with ECC enabled when the temperature is above 65°C.

    • Temperature changes may also cause program crashes when accessing PSRAM/flash. For more details, please refer to SPI Flash and External SPI RAM Configuration.


Does ESP32-S3 require an external PSRAM to use the RGB screen?

  • In general, yes. RGB screens require the ESP to provide at least one full-screen-sized frame buffer. However, the resolution of RGB screens is usually large, and ESP32-S3’s SRAM might not meet this requirement.

  • It’s not recommended to use a Quad PSRAM due to its relatively low bandwidth, as this could make the PCLK of the RGB LCD cannot be set to the required frequency.

  • It’s recommended to use an Octal PSRAM and set the clock to 80 MHz or above.


How can I increase the upper limit of PCLK settings on ESP32-S3 while ensuring normal RGB screen display?

  • Typically, the upper limit of PCLK settings is constrained by the bandwidth of the PSRAM. Therefore, you need to enhance the PSRAM bandwidth:

    • Use a higher frequency PSRAM clock or a wider PSRAM bus (Octal).

    • Reduce the PSRAM bandwidth occupied by other peripherals like Wi-Fi, flash, etc.

    • Decrease the Data Cache Line Size to 32 Bytes (set to 64 Bytes when using RGB Bounce Buffer mode).

  • Enable the Bounce Buffer mode of the RGB driver. The larger the buffer, the better the effect. For usage, please refer to the documentation. Please note that in this mode, the CPU first moves PSRAM data to SRAM, and then the GDMA transfers data to the RGB peripheral. Therefore, it is necessary to enable CONFIG_ESP32S3_DATA_CACHE_LINE_64B=y. Otherwise, it may cause the screen to drift.

  • Based on limited testing, for Quad PSRAM at 80 MHz, the highest PCLK setting is around 11 MHz; for Octal PSRAM at 80 MHz, the highest PCLK setting is around 22 MHz; for Octal PSRAM at 120 MHz, the highest PCLK setting is around 30 MHz.

  • For applications using LVGL, the task of RGB peripheral initialization can be assigned to the same core as the task of LVGL lv_timer_handler(). This significantly increases the upper limit of PCLK settings.


Which image decoding formats are supported by LCD applications on ESP series chips?

  • Software JPEG decoding: ESP-IDF includes the built-in tjpgd software decoder for JPEG. For an application example, please refer to esp-idf/examples/peripherals/lcd/tjpgd.

  • Hardware JPEG decoding: ESP32-S31 and ESP32-P4 integrate a hardware JPEG codec (SOC_JPEG_CODEC_SUPPORTED), and support hardware-accelerated JPEG decoding through the esp_driver_jpeg component, which is significantly faster than software decoding.

  • Via esp_lvgl_adapter + esp_lv_decoder: It is recommended to use esp_lvgl_adapter together with esp_lv_decoder, which supports the following formats:

    • Standard formats: JPG, PNG, QOI

    • Sliced formats (optimized for embedded memory): SJPG, SPNG, SQOI

    • Hardware acceleration (supported chips only): JPEG, PJPG

  • Based on LVGL built-in libraries: LVGL itself also provides decoding support for PNG, BMP, GIF, and other formats. For details, please refer to LVGL libs.

  • EAF animation format: An Espressif custom animation format, originally designed for screen refreshing with the esp_emote_gfx component (segmented decoding), and also adapted to LVGL. Refer to the LVGL EAF Player Example.


Why do I get drift (overall drift of the display) when ESP32-S3 is driving an RGB LCD screen?

  • Reasons

    • The PCLK setting of the RGB peripheral is too high, and the bandwidth of PSRAM or GDMA cannot be satisfied.

    • PSRAM and flash share a set of SPI interfaces. PSRAM is disabled during writes to flash (such as via Wi-Fi, OTA, Bluetooth LE).

    • Reading a large amount of flash/PSRAM data results in insufficient PSRAM bandwidth.

  • Solutions

    • Improve PSRAM and flash bandwidth. For example, use a higher frequency or larger bit width under the conditions allowed by the hardware.

    • Enable CONFIG_COMPILER_OPTIMIZATION_PERF.

    • Reduce the Data Cache Line Size to 32 Bytes (set to 64 Bytes when using the RGB Bounce Buffer mode).

    • Enable CONFIG_SPIRAM_FETCH_INSTRUCTIONS and CONFIG_SPIRAM_RODATA.

    • (Not Recommended) Enable CONFIG_LCD_RGB_RESTART_IN_VSYNC to automatically recover after screen drifting, but this cannot completely avoid the issue and may reduce the frame rate.

  • Applications

    • While ensuring the screen display is normal, try to reduce the frequency of PCLK and decrease the bandwidth utilization of PSRAM.

    • If you need to use Wi-Fi, Bluetooth LE, and continuous flash writing operations, please adopt the XIP on PSRAM + RGB Bounce buffer method. Here, XIP on PSRAM is used to load the code segment and read-only segment data into PSRAM, and the flash writing operation will not disable PSRAM after it is turned on. RGB Bounce buffer is used to block the frame buffer data and transfer it from PSRAM to SRAM through the CPU, and then use GDMA to transfer data to the RGB peripheral. Compared with directly using PSRAM GDMA, it can achieve higher transmission bandwidth. The setup steps are as follows:

      • Make sure the ESP-IDF version is release/v5.0 or newer (released after 2022.12.12), as older versions do not support the XIP on PSRAM function. (release/v4.4 supports this function through patching, but it is not recommended)

      • Confirm whether CONFIG_SPIRAM_FETCH_INSTRUCTIONS and CONFIG_SPIRAM_RODATA can be enabled in the PSRAM configuration. If the read-only data segment is too large (such as a large number of images), it may cause insufficient PSRAM space. At this time, you can use the file system or make the images into a bin to load into the designated partition.

      • Check if there is any memory (SRAM) left, and it takes about [10 × screen_width × 4] bytes.

      • Set Data cache line size to 64 Bytes (you can set Data cache size to 32 KB to save memory).

      • Set CONFIG_FREERTOS_HZ to 1000.

      • If all the above conditions are met, you can refer to the documentation to modify the RGB driver to Bounce Buffer mode. If drift still occurs after enabling, you can try to increase the buffer, but this will consume more SRAM memory.

      • If you still have the drift problem when dealing with Wi-Fi, you can try to turn off CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP in PSRAM, which takes up much SRAM space.

      • The effects of this setting include higher CPU usage, possible interrupt watchdog reset, and higher memory overhead.

      • Since the Bounce Buffer transfers data from PSRAM to SRAM through the CPU in GDMA interrupts, the program should avoid performing operations that disable interrupts for an extended period (such as calling portENTER_CRITICAL()), as it can still result in screen drifting.

    • For the drift caused by short-term operations of flash, such as before and after Wi-Fi connection, you can call esp_lcd_rgb_panel_set_pclk() before the operation to reduce the PCLK (such as 6 MHz) and delay about 20 ms (the time for RGB to complete one frame), and then increase PCLK to the original level after the operation. This operation may cause the screen to flash blank in a short-term.

    • If unavoidable, you can enable CONFIG_LCD_RGB_RESTART_IN_VSYNC or use the esp_lcd_rgb_panel_restart() to reset the RGB timing to prevent permanent drifting.

    • For guidance on how to avoid RGB screen drift issues in Arduino, please refer to the link.


Why is there vertical dislocation when I drive SPI/8080 LCD screen to display LVGL?

If you use DMA interrupt transfer, the flush-complete callback should be called after the DMA transfer finishes, not immediately after draw_bitmap().

  • LVGL v8: Call lv_disp_flush_ready() in the DMA transfer complete interrupt.

  • LVGL v9: Call lv_display_flush_ready() in the DMA transfer complete interrupt.


When I use ESP32-C3 to drive the LCD display through the SPI interface, is it possible to use RTC_CLK as the SPI clock, so that the LCD display can normally display static pictures in Deep-sleep mode?

  • Deep-sleep mode: The CPU and most peripherals are powered down, only the RTC memory is operational. For more details, please refer to the “Low Power Management” section in the ESP32-C3 Datasheet.

  • The SPI of ESP32-C3 only supports two clock sources, APB_CLK and XTAL_CLK, and does not support RTC_CLK. Therefore, the LCD screen cannot display static pictures in Deep-sleep mode. For details, please refer to ESP32-C3 Technical Reference Manual > Reset and Clock [PDF].

  • For the LCD screen driven by the SPI interface, the driver IC generally has built-in GRAM. Thus, the static pictures can be displayed normally without the ESP continuously outputting the SPI clock, but the pictures cannot be updated during this period.


Are 9-bit bus and 18-bit color depth supported if I use the ILI9488 LCD screen to test the screen example?

The ILI9488 driver chip can support 9-bit bus and 18-bit color depth. However, Espressif’s driver can only support 8-bit bus and 16-bit color depth for now.


When using ESP32-S3 to drive an RGB screen, why does it halt or reset (TG1WDT_SYS_RST) when running esp_lcd_new_rgb_panel() or esp_lcd_panel_init()?

  • Please check if the pins occupied by PSRAM in ESP chips or modules conflict with the RGB pins. If there is a conflict, modify the RGB pin configuration.

  • If using ESP32-S3R8, avoid using GPIO35, GPIO36, and GPIO37 pins.


When using ESP32-S3 to drive an RGB screen, an abnormal color inversion is observed, i.e., black turns into white, and white turns into black. How to handle this?

Please check whether the initialization register of the screen driver IC has set the invert_color function. For example, in ST7789, this can be corrected by configuring the Inversion register:

  • INVOFF (20h): Display Inversion Off

  • INVON (21h): Display Inversion On


How to handle color inaccuracies, such as missing colors, when driving an RGB screen with ESP32-S3?

It’s likely that the RGB configuration is incorrect. This problem can be troubleshot in the following ways:

  • Check for RGB/BGR setting errors: For example, if the screen is set to red (0xC0, 0x0, 0x0), but the screen actually displays black.

  • Check whether the RGB and BGR registers are set: For example, in ST7789, it can be corrected through the MADCTL (36h) register (when MADCTL (36h) = 1, it is BGR; when MADCTL (36h) = 0, it is RGB).

  • Check for LVGL SWAP16 setting errors: If the screen is configured to red (0xC0, 0x0, 0x0), but the screen actually displays blue, please go to menuconfig → Component config → LVGL configuration → Color settings.

  • If there’s missing colors in the RGB TTL screen display, it is necessary to set R, G, B displays separately, and check whether the channel with waveform and RGB data line design are compliant.


The spaces in the LVGL’s label are correctly inputted, for example “Indoor temperature 25.5℃”, but the spaces are not displayed on the screen. What could be the reason and how to troubleshoot this?

This pertains to the missing display of the LVGL label. Enable the following debug items and missing characters will be filled with squares to prevent map loss:

  • Component configLVGL configurationFont usageEnable drawing placeholders when glyph dsc is not found


When LVGL v8 continuously loads different images stored on flash, the speed is too slow. For example, how to avoid the slow speed issue when cycling through three images on the home screen?

  • The reason for the slow speed is that the corresponding image caching mechanism is not turned on, so each images need to be parsed by the parser each time it is used.

  • Enable the corresponding image caching mechanism via the #define LV_IMG_CACHE_DEF_SIZE 1 macro, where 1 represents the number of cached images. Please note that this operation will consume more memory.


LVGL v8 fails to load PNG, JPEG images from flash. What’s the reason for a blank screen?

  • First, it is necessary to check the status of the remaining memory. LVGL needs to perform two steps to load images: loadpng_get_raw_size and loadpng_convert. If the memory is not enough, it will directly return error code 83.

  • The memory requirements should also be estimated in advance: loadpng_get_raw_size needs memory equivalent to the image size, loadpng_convert requires memory of image length * width * 3 bytes. Enabling the image caching mechanism will cause large image_cache, which will simultaneously lead to memory strain.


How to convert a GIF animation into C language code?

Convert the GIF to Map option, with the Color format set to CF_RAW.


Can the screen be set to transparent when displaying GIF animations?

Yes. But GIF only has a 1 bit Alpha descriptor, so it can only be fully transparent or opaque, and there is no semi-transparency.


Which image format is better for the LVGL interface? Is there any reference?

You can refer to the table below:

Image format

Transparent support

Size

Decoding speed

PNG

Perfectly supported

Moderate

Moderate

BMP

Limited support

Large

Fastest, no decoding required

JPG

Not supported

Small

Fast

When converting images to MAP format via LVGL imageconverter, if using non-RAW formats such as CF_TRUE_COLOR for conversion, subsequent LVGL loading will not require re-decoding, but it will occupy a larger code segment.


When using some third-party libraries such as FreeType and Lottie with LVGL, why does the screen go blank despite the program loading normally?

First, consider whether the task stack settings are incorrect:

  • FreeType: When using esp_lvgl_adapter, first confirm the stack configuration: for LVGL v8, set CONFIG_ESP_MAIN_TASK_STACK_SIZE to 32768 (font initialization runs on the calling thread); for LVGL v9, set CONFIG_LV_DRAW_THREAD_STACK_SIZE to 32768 (font rendering runs on the draw thread). In addition, the following two Kconfig options can reduce resource usage:

    • ESP_LVGL_ADAPTER_FREETYPE_SMALL_RENDER_POOL: Reduces the FreeType render pool from 16 KB to 4 KB, and can also reduce the LVGL v9 draw thread stack requirement.

    • ESP_LVGL_ADAPTER_FREETYPE_MINIMAL_BUILD: Trims FreeType build modules and keeps only what is needed for common TTF/OTF paths (removes Type1/CID/BDF/PCF and other legacy drivers and compressed-stream helpers), which significantly reduces flash usage. Do not enable this if your project needs any of the trimmed formats.

    Reference example: lvgl_freetype_font.

  • Lottie: Generally, more than 30 KB of task stack needs to be allocated. Refer to lottie porting.


What are some good solutions if the internal RAM of ESP32-S3, driving an SPI screen, is insufficient to allocate space for the entire screen buffer?

Use PSRAM as a framebuffer, and then use a small SRAM buffer to transfer data to the framebuffer in multiple batches (SPI DMA can’t directly transfer PSRAM data). After completing the transfer, use the framebuffer to render directly. Compared to rendering directly with a small buffer and then sending data, this can prevent tearing and speed up rendering. For specific implementation, please refer to esp_lvgl_adapter.


How to deal with diagonal tearing on the SPI screen after the hardware is rotated 90 or 270 degrees?

It is recommended to enable the LVGL sw_rotate flag in normal mode and use LVGL software rotation. However, please note that sw_rotate conflicts with full_refresh and direct_mode, so do not use them together. For example, calling sw_rotate under full_refresh will directly return without any effect.

Note

sw_rotate, full_refresh, and direct_mode are LVGL v8 APIs. Rotation in LVGL v9 works differently; please refer to LVGL v9 Rotation Notes.


Using the ESP32-S2 USB camera and I80 LCD simultaneously may result in the LCD display showing missing images or behaving abnormally. How can this be resolved?

Please refer to this code to increase the startup delay time of I2S.


How to solve the unexpected crash when operating LVGL controls through non-LVGL tasks?

LVGL APIs are not thread-safe. When operating LVGL controls from a non-LVGL task, you must protect the calls with a lock.

  • If you use the esp_lvgl_adapter component, use the lock APIs it provides:

    if (esp_lv_adapter_lock(-1) == ESP_OK) {
        /* LVGL API calls */
        esp_lv_adapter_unlock();
    }
    
  • If you use the legacy esp_lvgl_port component, the corresponding APIs are lvgl_port_lock(0) and lvgl_port_unlock().


Does ESP32-S3 support RGB888?

Parallel RGB888 is not supported (ESP32-P4 supports parallel RGB888), only RGB565 is supported. Serial RGB888 output can be configured with the following settings:

esp_lcd_rgb_panel_config_t panel_conf = {
...
.data_width = 8,
.bits_per_pixel = 24,
...
}

How can I disable the left and right swipe functionality when operating the LVGL tabview?

Please add the following code: lv_obj_clear_flag(lv_tabview_get_content(tabview), LV_OBJ_FLAG_SCROLLABLE);.


Does LVGL support multiple indev inputs?

Yes. All input devices are managed in a linked list, supporting multiple input devices of the same and different types. For application examples, please refer to the component espressif/esp_lvgl_adapter. The component currently supports input device types such as touch, button, and knob.


Does LVGL support multi-touch?

LVGL multi-touch support varies by version:

  • LVGL v8: Native multi-touch is not supported; each indev can report only one touch point.

  • LVGL v9: Multi-pointer input is supported. Multiple touch indevs can be registered for the same display, and each touch point can control different widgets independently.

When using esp_lvgl_adapter, you can enable multi-touch mode when registering a touch device (LVGL v9 only):

esp_lv_adapter_touch_config_t touch_cfg = ESP_LV_ADAPTER_TOUCH_DEFAULT_CONFIG(disp, touch_handle);
touch_cfg.multi_touch.mode = ESP_LV_ADAPTER_TOUCH_MODE_MULTI_CONTROL;
touch_cfg.multi_touch.pointers = 2;  /* Must be >= 2, and not exceed CONFIG_ESP_LCD_TOUCH_MAX_POINTS */
lv_indev_t *touch = esp_lv_adapter_register_touch(&touch_cfg);

Does a high CPU usage rate reported by LVGL have any impact?

The CPU usage calculated by LVGL statistics is the duration of the LVGL rendering task within 500 ms, and it does not represent the real CPU usage. Please use FreeRTOS’s vTaskGetRunTimeStats to calculate the real usage.


Can ESP32-S3 enter Light-sleep mode after enabling the RGB screen driver?

Using the esp_lcd RGB driver directly: When initializing the RGB interface, if CONFIG_PM_ENABLE is enabled, the driver automatically holds the ESP_PM_NO_LIGHT_SLEEP lock, preventing the system from entering Light-sleep mode. To enter Light-sleep, you must first call esp_lcd_panel_del() to delete the RGB panel (releasing the lock), then reinitialize after waking from sleep.

Using the esp_lvgl_adapter component: This component provides two Light-sleep usage modes. The LVGL UI state (widget tree) is retained during sleep, so the UI does not need to be rebuilt.

Manual sleep: The application controls the full sleep/wake flow:

  1. Before entering sleep, call esp_lv_adapter_sleep_prepare() to pause the adapter and wait for the current frame refresh to complete.

  2. Call esp_lcd_panel_del() to release display hardware resources.

  3. Call esp_light_sleep_start() to enter Light-sleep.

  4. After waking, reinitialize the LCD hardware, then call esp_lv_adapter_sleep_recover() to rebind the panel and resume the adapter.

Automatic sleep (auto_sleep): Configure an idle timeout at initialization. The adapter automatically triggers sleep after LVGL has been idle longer than the specified time:

esp_lv_adapter_config_t cfg = ESP_LV_ADAPTER_DEFAULT_CONFIG();
cfg.auto_sleep.enable = true;
cfg.auto_sleep.idle_timeout_ms = 5000;  /* Auto-sleep after 5 s of idle */

/* Pause mode: the adapter releases the lock and pauses LVGL; the system
   enters tickless light sleep; panel sleep/backlight is handled by user callbacks */
cfg.auto_sleep.mode = ESP_LV_ADAPTER_AUTO_SLEEP_MODE_PAUSE;
cfg.auto_sleep.callbacks.on_enter_sleep = panel_sleep_cb;
cfg.auto_sleep.callbacks.on_exit_sleep  = panel_wake_cb;

/* User mode: the on_enter_sleep callback owns the full
   sleep_prepare → LCD deinit → light_sleep_start → LCD init → sleep_recover flow */
/* cfg.auto_sleep.mode = ESP_LV_ADAPTER_AUTO_SLEEP_MODE_USER; */

ESP_ERROR_CHECK(esp_lv_adapter_init(&cfg));

In Pause mode, registered touch/button/knob inputs automatically notify the adapter to wake; custom wake sources can call esp_lv_adapter_request_wake() or esp_lv_adapter_request_wake_from_isr().


Is it supported to drive segment LCD screens?

ESP chips can’t directly drive the segment LCD screen through the GPIO pin, because this function requires cycling between high and low voltage levels, with an AC voltage from 2.7 V to 5.0 V and typical values of 3.0 V, 3.3 V, 4.5 V, and 5.0 V. However, the chips do not support voltage range adjustment.


When driving an RGB LCD with ESP32-P4, the screen shows abnormal colors. How to troubleshoot?

ESP32-P4 has multiple VDDPST power domains. Each VDDPST controls the maximum output level of GPIOs in the corresponding region (for the GPIO-to-VDDPST mapping, please refer to the ESP32-P4 Datasheet). If the corresponding VDDPST supply is insufficient or not configured correctly, some GPIOs may have a maximum output level of 1.8 V, causing insufficient RGB interface signal levels and abnormal screen colors. Please check that the VDDPST for the GPIOs used by the RGB interface is configured to the correct voltage (typically 3.3 V).

Note also: Unlike ESP32-S3 (PCLK up to about 30 MHz), the RGB interface clock frequency on ESP32-S31 and ESP32-P4 has no such 30 MHz upper limit, so they can support higher interface frame rates and larger-resolution RGB screens.


Does ESP32-P4 support HDMI signal output?

ESP32-P4 does not support direct HDMI signal output. However, HDMI signal output can be achieved through an MIPI-DSI to HDMI bridge chip. Currently, the MIPI-DSI to HDMI chip supported by Espressif is LT8912B. For more information, refer to example code.


In LVGL applications, how to rotate the RGB or MIPI-DSI interface screen by 90 degrees/270 degrees? How to avoid tearing? How to further improve the frame rate?

  • It is recommended to use the esp_lvgl_adapter component. This component provides features such as high-efficiency rotation, tear prevention, frame rate enhancement, and supports LVGL v8 and v9 versions.

  • Refer to the example code esp_lvgl_adapter example.


Can ESP32-P4 generate MIPI-DSI signals (LP and HP) when no MIPI peripheral is connected?

Theoretically possible, but with limitations: Signals can be output during the LP (Low Power) phase; however, during the HP (High Performance) phase, because the driver enables frame ACK by default and has no timeout mechanism, when the FIFO is full it will continuously wait for ACK (BTA), causing the link to freeze. If only capturing waveform segments can satisfy your requirements, then it’s feasible. If continuous output is needed, you must modify the MIPI-DSI driver inside IDF; currently it cannot be achieved through external configuration alone.


GIF animations in EAF format play slowly on ESP32-S3/P4. How to optimize?

  • You can change the EAF encoding format to JPEG (set in the conversion tool), which will increase file size but decode faster;

  • For larger resolution screens (such as 466×466), LVGL rendering burden is heavy;

  • Compared with EAF + LVGL, using the esp_emote_gfx component directly for screen refreshing (segmented decoding) is more efficient. EAF was originally designed for esp_emote_gfx, and is only additionally adapted to LVGL;

  • AVI with JPEG-encoded frames is smoother on an LCD than GIF;

  • P4 revision v3.1 improves CPU frequency and PSRAM bandwidth, enabling LVGL and MP4 to stably reach 15 frames under 1080p RGB888.


ESP32-P4 drives a MIPI-DSI LCD with no image and no other error logs. How to troubleshoot?

First, check whether the SPIRAM clock rate is configured to 200 MHz or above (CONFIG_SPIRAM_SPEED_200M=y). Driving a MIPI-DSI interface screen requires higher PSRAM bandwidth; when bandwidth is insufficient, the screen may fail to display without reporting an error.

Next, check whether the DSI data pins (DSI_DATAN0/DSI_DATAP0) and clock pins (DSI_CLKN/DSI_CLKP) are correctly connected to the panel.


ESP32-P4 drives a MIPI-DSI LCD with twisted or misaligned images. How to handle this?

This issue is generally caused by a mismatch between lane_bit_rate_mbps and the actual pixel_clock, or between lane_bit_rate_mbps and the rate required by the panel. Recalculate lane_bit_rate_mbps based on resolution, refresh rate, color depth, and lane count (with about a 20% margin). For the calculation method, please refer to MIPI DSI LCD Detailed Guide. Note that on ESP32-P4, lane_bit_rate_mbps must not exceed 1500, and a minimum of 480 is recommended.


ESP32-P4 drives a MIPI-DSI LCD with a flashing blue screen and the message “can’t fetch data from external memory fast enough, underrun happens”. How to handle this?

This issue is caused by insufficient PSRAM bandwidth. You can try the following:

  • Lower lane_bit_rate_mbps and dpi_clock_freq_mhz (pixel clock frequency).

  • If using the RGB888 color format, consider switching to RGB565 to reduce bandwidth demand.

  • Enable the following configuration items to improve PSRAM bandwidth:

    • CONFIG_SPIRAM_XIP_FROM_PSRAM=y

    • CONFIG_CACHE_L2_CACHE_256KB=y

    • CONFIG_CACHE_L2_CACHE_LINE_128B=y

    • CONFIG_COMPILER_OPTIMIZATION_PERF=y