Tips and tricks
IDF projects are optimized for image size by default. These options tune an ESP-IDF project for LVGL speed, PSRAM usage, logging, and file system access.
Improving LVGL speed of execution
IDF projects are generally configured to optimize the final application image for size. For some LVGL applications this is not desirable and results in poor execution speed.
In this case it is worth setting some of the IDF project-wide options in
sdkconfig.defaults, such as:
CONFIG_COMPILER_OPTIMIZATION_PERF=yThis compiles the application with performance as the priority, using SIMD instructions where possible. An increase of up to 30% in overall execution speed can be observed.
It is also possible to speed up the execution of LVGL's critical code by telling the compiler to put those sections in the IRAM area of ESP32 chips with the following option:
CONFIG_LV_ATTRIBUTE_FAST_MEM_USE_IRAM=yThe CPU can also be set to always run at its maximum speed with the
CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_ option. The frequency varies from chip to
chip; for example, the P4 family supports 360 MHz:
CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_360and the ESP32/ESP32-S3 support 240 MHz:
CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240Some of these options need the IDF experimental options to be enabled:
CONFIG_IDF_EXPERIMENTAL_FEATURES=yConfiguring the PSRAM on ESP32 supported devices
Some of the high-end ESP32 chips have external memory in their module: Pseudo-Static Random Access Memory, or PSRAM. Values from 4 to 16 MB are typical, and LVGL can use a portion of this memory to:
- Copy read-only objects from flash to PSRAM to increase speed.
- Use direct mode plus dual buffers even on an ESP32 that does not have a built-in display controller.
In both scenarios the result is less time spent flushing data to the display, resulting in higher frame rates. To enable PSRAM usage, set:
CONFIG_SPIRAM=y
CONFIG_SPIRAM_MODE_HEX=y
CONFIG_SPIRAM_USE=y
CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY=y
CONFIG_SPIRAM_RODATA=yThese options can reside in the IDF project's sdkconfig.defaults.
Application crashes when enabling PPA
An application can start crashing after the CONFIG_LV_USE_PPA option is enabled. The typical
symptom is a message on the monitor console indicating an error when the ESP32 calls the
esp_msync function.
This happens because the PPA only accepts chunks of data that are aligned to the L1 cache line
size, that is, 64 bytes. Even though the PPA draw unit handles the alignment of the source buffer,
the target draw buffer area has to be aligned as well, otherwise the transfer from the PPA to it
may fail. To prevent this, make CONFIG_LV_DRAW_BUF_ALIGN a multiple of the L1 cache line size,
i.e. set it to 64 instead of the default 4.
CONFIG_LV_DRAW_BUF_ALIGN=64ESP32-P4 monitor log reports buffer underrun and frame-rate decreases
When PSRAM is enabled and the PPA is used, it is common to see frame rate degradation followed by a log message reporting that the display buffer will underrun. This happens because, depending on the IDF version, PSRAM was not enabled with the maximum supported speed.
To fix it, add the following option to sdkconfig.defaults:
CONFIG_SPIRAM_SPEED_200M=yAdditionally, the PPA burst length can be increased to raise the memory bandwidth of a particular channel and gain speed in the drawing operations:
CONFIG_LV_PPA_BURST_LENGTH=128There is a downside to increasing the burst length: if another piece of ESP-IDF code uses a DMA2D channel that is shared with the PPA, the increase may slow down that channel's consumer. Also mind that the supported burst length values are 128, 64, 32, 16, and 8 bytes; any other value results in a build error.
Enabling LVGL logs on IDF project
LVGL logs are not enabled by default. To enable them, add the following options to
sdkconfig.defaults:
CONFIG_LV_USE_LOG=y
CONFIG_LV_LOG_LEVEL_INFO=y
CONFIG_LV_LOG_PRINTF=yThe logging subsystem of LVGL relies on printf being present in ESP-IDF.
Using the File System under ESP-IDF
ESP-IDF uses the standard C file operation functions (fopen, fread) in all its storage related APIs.
This allows seamless interoperability with LVGL when enabling the LV_USE_FS_STDIO configuration.
The process is described in detail below, using SPIFFS as a demonstration.
Decide what storage system you want to use
ESP-IDF has many ready-to-use examples, like SPIFFS, SD Card and LittleFS.
Enable LVGL's STDIO file system
You can use menuconfig:
Component config → LVGL configuration → 3rd Party Libraries: enableFile system on top of stdio API- Then select
Set an upper cased letter on which the drive will accessibleand set it to65(ASCII A) - You can also set
Default driver letterto 65 to skip the prefix in file paths.
Modify the partition table
The exact configuration depends on your flash size and existing partitions, but the new final result should look something like this:
| Name | Type | SubType | Offset | Size |
|---|---|---|---|---|
| nvs | data | nvs | 0x9000 | 0x6000 |
| phy_init | data | phy | 0xf000 | 0x1000 |
| factory | app | factory | 0x10000 | 1400k |
| storage | data | spiffs | 400k |
If you are not using a custom partition.csv yet, it can be added
via menuconfig (Partition Table → Partition Table → Custom partition table CSV).
Apply changes to the build system
Some ESP file systems provide automatic generation from a host folder using CMake. The proper
line(s) must be copied to main/CMakeLists.txt.
LittleFS has extra dependencies that should be added to main/idf_component.yml.
Prepare the image files
LVGL's LVGLImage.py Python tool can be used to convert images to binary pixel map files.
It supports various formats and compression.
Meanwhile 3rd party libraries (like LodePNG and Tiny JPEG) allow using image files without conversion.
After preparing the files, they should be moved to the target device:
- If properly activated, a SPIFFS file system based on the
spiffs_imagefolder should be automatically generated and later flashed to the target - A similar mechanism for LittleFS uses the
flash_datafolder, but it's only available for Linux hosts - For the SD Card, a traditional file browser can be used
Invoke proper API calls in the application code
The core functionality requires only a few lines. The following example draws the image as well.
#include "esp_spiffs.h"
void lv_example_image_from_esp_fs(void)
{
esp_vfs_spiffs_conf_t conf = {
.base_path = "/spiffs",
.partition_label = NULL,
.max_files = 5,
.format_if_mount_failed = false
};
esp_err_t ret = esp_vfs_spiffs_register(&conf);
if(ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to register SPIFF filesystem");
return;
}
lv_obj_t * obj = lv_image_create(lv_screen_active());
lv_image_set_src(obj, "A:/spiffs/logo.bin");
lv_obj_center(obj);
}Build and flash
After calling idf.py build flash the picture should be displayed on the screen.
Changes made by menuconfig are not being tracked in the repository if the sdkconfig file is added to .gitignore, which is the default for many ESP-IDF projects.
To make your configuration permanent, add the following lines to sdkconfig.defaults:
CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_LV_USE_FS_STDIO=y
CONFIG_LV_FS_STDIO_LETTER=65
CONFIG_LV_FS_DEFAULT_DRIVER_LETTER=65Last updated on
PPA (Pixel Processing Accelerator) Support
The PPA of chips like the ESP32-P4 accelerates fill and image blending operations. LVGL has an experimental PPA draw unit, and the Espressif port can also rotate and mirror with it.
NXP
LVGL on NXP i.MX and i.MX RT chips: the eLCDIF display driver and the PXP, G2D, and VG-Lite draw units.