mirror of
https://github.com/espressif/esp-idf.git
synced 2026-04-27 19:13:21 +00:00
Merge branch 'feature/i80_example_improvement' into 'master'
fix(i80_controller): fixe crash issue when using file system See merge request espressif/esp-idf!46243
This commit is contained in:
@@ -9,7 +9,7 @@ This example can be taken as a skeleton of porting the LVGL library onto the `es
|
||||
|
||||
The whole porting code is located in [i80_controller_example_main.c](main/i80_controller_example_main.c), and the UI demo code is located in [lvgl_demo_ui.c](main/lvgl_demo_ui.c).
|
||||
|
||||
The UI will display two images (one Espressif logo and another Espressif text), which have been converted into C arrays by the [online converting tool](https://lvgl.io/tools/imageconverter), and will be compiled directly into application binary.
|
||||
The UI will display two images (one Espressif logo and another Espressif text). You can choose to load images from a [LittleFS file system](https://github.com/joltwallet/esp_littlefs) or from embedded binary data. See [Image Resource](#image-resource) for more details.
|
||||
|
||||
This example is constructed by [IDF component manager](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/tools/idf-component-manager.html), all the external dependency will be handled by the CMake build system automatically. In this case, it will help download the lvgl from the [ESP Component Registry](https://components.espressif.com/component/lvgl/lvgl), with the version specified in the [manifest file](main/idf_component.yml).
|
||||
|
||||
@@ -97,10 +97,29 @@ I (638) example: Display LVGL animation
|
||||
|
||||
## Image Resource
|
||||
|
||||
This example supports two ways of reading images
|
||||
This example supports two ways of loading images, which can be selected via `LCD image source from` in the menuconfig:
|
||||
|
||||
* from the [SPIFFS file system](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/storage/spiffs.html). This is the suggested way we use in the example. It may take a little bit longer to load the image because of the bottleneck of the SPI flash read speed, but it will save the binary size.
|
||||
* from the embedded binary (i.e., pre-decode the image into an array and pack it together with the application firmware). By this way, you can get faster image loading speed at the cost of bloating your application binary. What's worse, if you enabled the [XIP from PSRAM](https://github.com/espressif/esp-idf/tree/master/examples/system/xip_from_psram) feature, it will increase the PSRAM usage as well.
|
||||
### File System (recommended)
|
||||
|
||||
Load images from a [LittleFS file system](https://github.com/joltwallet/esp_littlefs). This approach saves binary size, though it may have slightly slower image loading due to SPI flash read speed.
|
||||
|
||||
When this option is selected, the build system will:
|
||||
|
||||
1. Use a custom partition table [partitions_lvgl_example.csv](partitions_lvgl_example.csv) that includes a `storage` partition for LittleFS.
|
||||
2. Automatically generate a LittleFS image from the PNG files in [main/images/filesystem](main/images/filesystem) and flash it to the `storage` partition.
|
||||
|
||||
At runtime, the application mounts the LittleFS partition at `/littlefs` and LVGL accesses the images via its POSIX FS interface (e.g., `S:/littlefs/esp_logo.png`, where `S` is the drive letter).
|
||||
|
||||
The following LVGL features are enabled for file system support (see [sdkconfig.ci.image_in_fs](sdkconfig.ci.image_in_fs)):
|
||||
|
||||
* `LV_USE_LODEPNG`: Decode PNG images at runtime.
|
||||
* `LV_USE_FS_POSIX`: Enable POSIX file system interface in LVGL.
|
||||
* `LV_FS_POSIX_LETTER`: Set to `83` (ASCII for `S`) as the drive letter.
|
||||
* `PARTITION_TABLE_CUSTOM` : Use the custom partition table.
|
||||
|
||||
### Embedded Binary (default)
|
||||
|
||||
Pre-decode images into C arrays (via the [online converting tool](https://lvgl.io/tools/imageconverter)) and pack them together with the application firmware. This gives faster image loading speed at the cost of a larger application binary. If you have enabled the [XIP from PSRAM](https://github.com/espressif/esp-idf/tree/master/examples/system/xip_from_psram) feature, it will also increase the PSRAM usage.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
|
||||
@@ -4,10 +4,9 @@ if(CONFIG_EXAMPLE_LCD_IMAGE_FROM_EMBEDDED_BINARY)
|
||||
endif()
|
||||
|
||||
idf_component_register(SRCS "i80_controller_example_main.c" "lvgl_demo_ui.c" ${embedded_images}
|
||||
PRIV_REQUIRES esp_lcd spiffs esp_psram
|
||||
PRIV_REQUIRES esp_lcd esp_psram
|
||||
INCLUDE_DIRS ".")
|
||||
|
||||
if(CONFIG_EXAMPLE_LCD_IMAGE_FROM_FILE_SYSTEM)
|
||||
# Create a partition to store the image resources in the filesystem
|
||||
spiffs_create_partition_image(storage ./images/filesystem FLASH_IN_PROJECT)
|
||||
littlefs_create_partition_image(storage ./images/filesystem FLASH_IN_PROJECT)
|
||||
endif()
|
||||
|
||||
@@ -3,7 +3,7 @@ menu "Example Configuration"
|
||||
config EXAMPLE_LCD_I80_COLOR_IN_PSRAM
|
||||
bool "Allocate color data from PSRAM"
|
||||
depends on SOC_PSRAM_DMA_CAPABLE
|
||||
default y
|
||||
default n
|
||||
help
|
||||
Enable this option if you want to allocate the LVGL draw buffer from PSRAM.
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: CC0-1.0
|
||||
*/
|
||||
@@ -17,7 +17,7 @@
|
||||
#include "esp_lcd_panel_vendor.h"
|
||||
#include "esp_lcd_nt35510.h"
|
||||
#include "esp_lcd_panel_ops.h"
|
||||
#include "esp_spiffs.h"
|
||||
#include "esp_littlefs.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "lvgl.h"
|
||||
|
||||
@@ -72,7 +72,7 @@ static const char *TAG = "example";
|
||||
#define EXAMPLE_LVGL_TICK_PERIOD_MS 2
|
||||
#define EXAMPLE_LVGL_TASK_MAX_DELAY_MS 500
|
||||
#define EXAMPLE_LVGL_TASK_MIN_DELAY_MS 1000 / CONFIG_FREERTOS_HZ
|
||||
#define EXAMPLE_LVGL_TASK_STACK_SIZE (4 * 1024)
|
||||
#define EXAMPLE_LVGL_TASK_STACK_SIZE (8 * 1024)
|
||||
#define EXAMPLE_LVGL_TASK_PRIORITY 2
|
||||
#define EXAMPLE_LVGL_DRAW_BUF_LINES 100
|
||||
|
||||
@@ -130,33 +130,31 @@ static void example_lvgl_port_task(void *arg)
|
||||
void example_init_filesystem(void)
|
||||
{
|
||||
ESP_LOGI(TAG, "Initializing filesystem");
|
||||
esp_vfs_spiffs_conf_t conf = {
|
||||
.base_path = "/spiffs",
|
||||
esp_vfs_littlefs_conf_t conf = {
|
||||
.base_path = "/littlefs",
|
||||
.partition_label = "storage",
|
||||
.max_files = 5,
|
||||
.format_if_mount_failed = true
|
||||
.format_if_mount_failed = true,
|
||||
.dont_mount = false,
|
||||
};
|
||||
|
||||
// Use settings defined above to initialize and mount SPIFFS filesystem.
|
||||
// Note: esp_vfs_spiffs_register is an all-in-one convenience function.
|
||||
esp_err_t ret = esp_vfs_spiffs_register(&conf);
|
||||
esp_err_t ret = esp_vfs_littlefs_register(&conf);
|
||||
|
||||
if (ret != ESP_OK) {
|
||||
if (ret == ESP_FAIL) {
|
||||
ESP_LOGE(TAG, "Failed to mount or format filesystem");
|
||||
} else if (ret == ESP_ERR_NOT_FOUND) {
|
||||
ESP_LOGE(TAG, "Failed to find SPIFFS partition");
|
||||
ESP_LOGE(TAG, "Failed to find LittleFS partition");
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Failed to initialize SPIFFS (%s)", esp_err_to_name(ret));
|
||||
ESP_LOGE(TAG, "Failed to initialize LittleFS (%s)", esp_err_to_name(ret));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
size_t total = 0, used = 0;
|
||||
ret = esp_spiffs_info(conf.partition_label, &total, &used);
|
||||
ret = esp_littlefs_info(conf.partition_label, &total, &used);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to get SPIFFS partition information (%s). Formatting...", esp_err_to_name(ret));
|
||||
esp_spiffs_format(conf.partition_label);
|
||||
ESP_LOGE(TAG, "Failed to get LittleFS partition information (%s). Formatting...", esp_err_to_name(ret));
|
||||
esp_littlefs_format(conf.partition_label);
|
||||
return;
|
||||
} else {
|
||||
ESP_LOGI(TAG, "Partition size: total: %zu, used: %zu", total, used);
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
dependencies:
|
||||
lvgl/lvgl: "9.2.2"
|
||||
espressif/esp_lcd_nt35510: "^1.0.0"
|
||||
joltwallet/littlefs: "~=1.20.0"
|
||||
|
||||
@@ -59,7 +59,7 @@ static void anim_timer_cb(lv_timer_t *timer)
|
||||
// Create new image and make it transparent
|
||||
img_text = lv_image_create(scr);
|
||||
#if CONFIG_EXAMPLE_LCD_IMAGE_FROM_FILE_SYSTEM
|
||||
lv_image_set_src(img_text, "S:/spiffs/esp_text.png");
|
||||
lv_image_set_src(img_text, "S:/littlefs/esp_text.png");
|
||||
#elif CONFIG_EXAMPLE_LCD_IMAGE_FROM_EMBEDDED_BINARY
|
||||
lv_image_set_src(img_text, &esp_text);
|
||||
#endif
|
||||
@@ -123,7 +123,7 @@ void example_lvgl_demo_ui(lv_disp_t *disp)
|
||||
// Create image
|
||||
img_logo = lv_image_create(scr);
|
||||
#if CONFIG_EXAMPLE_LCD_IMAGE_FROM_FILE_SYSTEM
|
||||
lv_image_set_src(img_logo, "S:/spiffs/esp_logo.png");
|
||||
lv_image_set_src(img_logo, "S:/littlefs/esp_logo.png");
|
||||
#elif CONFIG_EXAMPLE_LCD_IMAGE_FROM_EMBEDDED_BINARY
|
||||
lv_image_set_src(img_logo, &esp_logo);
|
||||
#endif
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
nvs, data, nvs, 0x9000, 0x6000,
|
||||
phy_init, data, phy, 0xf000, 0x1000,
|
||||
factory, app, factory, 0x10000, 1M,
|
||||
storage, data, spiffs, , 0xF0000,
|
||||
storage, data, littlefs, , 0xF0000,
|
||||
|
||||
|
@@ -0,0 +1,26 @@
|
||||
# SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
import pytest
|
||||
from pytest_embedded import Dut
|
||||
from pytest_embedded_idf.utils import idf_parametrize
|
||||
from pytest_embedded_idf.utils import soc_filtered_targets
|
||||
|
||||
|
||||
@pytest.mark.generic
|
||||
@pytest.mark.parametrize(
|
||||
'config',
|
||||
[
|
||||
'image_in_bin',
|
||||
'image_in_fs',
|
||||
],
|
||||
indirect=True,
|
||||
)
|
||||
@idf_parametrize('target', soc_filtered_targets('SOC_LCD_I80_SUPPORTED == 1'), indirect=['target'])
|
||||
def test_i80_lcd_lvgl(dut: Dut) -> None:
|
||||
dut.expect_exact('Calling app_main()')
|
||||
dut.expect_exact('example: Initialize Intel 8080 bus')
|
||||
dut.expect_exact('example: Initialize LVGL library')
|
||||
dut.expect_exact('example: Install LVGL tick timer')
|
||||
dut.expect_exact('example: Create LVGL task')
|
||||
dut.expect_exact('example: Starting LVGL task')
|
||||
dut.expect_exact('example: Display LVGL animation')
|
||||
@@ -1,4 +1,5 @@
|
||||
CONFIG_LV_CONF_SKIP=y
|
||||
CONFIG_LV_USE_CLIB_MALLOC=y
|
||||
CONFIG_LV_USE_OBSERVER=y
|
||||
CONFIG_LV_USE_SYSMON=y
|
||||
CONFIG_LV_USE_PERF_MONITOR=y
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
CONFIG_EXAMPLE_PIN_NUM_PCLK=5
|
||||
CONFIG_EXAMPLE_PIN_NUM_CS=3
|
||||
CONFIG_EXAMPLE_PIN_NUM_DC=4
|
||||
CONFIG_EXAMPLE_PIN_NUM_RST=2
|
||||
CONFIG_EXAMPLE_PIN_NUM_BK_LIGHT=1
|
||||
CONFIG_EXAMPLE_PIN_NUM_DATA0=6
|
||||
CONFIG_EXAMPLE_PIN_NUM_DATA1=7
|
||||
CONFIG_EXAMPLE_PIN_NUM_DATA2=8
|
||||
CONFIG_EXAMPLE_PIN_NUM_DATA3=9
|
||||
CONFIG_EXAMPLE_PIN_NUM_DATA4=10
|
||||
CONFIG_EXAMPLE_PIN_NUM_DATA5=11
|
||||
CONFIG_EXAMPLE_PIN_NUM_DATA6=12
|
||||
CONFIG_EXAMPLE_PIN_NUM_DATA7=13
|
||||
CONFIG_EXAMPLE_PIN_NUM_DATA8=14
|
||||
CONFIG_EXAMPLE_PIN_NUM_DATA9=15
|
||||
CONFIG_EXAMPLE_PIN_NUM_DATA10=16
|
||||
CONFIG_EXAMPLE_PIN_NUM_DATA11=17
|
||||
CONFIG_EXAMPLE_PIN_NUM_DATA12=18
|
||||
CONFIG_EXAMPLE_PIN_NUM_DATA13=19
|
||||
CONFIG_EXAMPLE_PIN_NUM_DATA14=20
|
||||
CONFIG_EXAMPLE_PIN_NUM_DATA15=21
|
||||
CONFIG_EXAMPLE_PIN_NUM_BK_LIGHT=2
|
||||
CONFIG_EXAMPLE_PIN_NUM_RST=-1
|
||||
CONFIG_EXAMPLE_PIN_NUM_CS=4
|
||||
CONFIG_EXAMPLE_PIN_NUM_DC=5
|
||||
CONFIG_EXAMPLE_PIN_NUM_PCLK=18
|
||||
CONFIG_EXAMPLE_PIN_NUM_DATA0=19
|
||||
CONFIG_EXAMPLE_PIN_NUM_DATA1=21
|
||||
CONFIG_EXAMPLE_PIN_NUM_DATA2=0
|
||||
CONFIG_EXAMPLE_PIN_NUM_DATA3=22
|
||||
CONFIG_EXAMPLE_PIN_NUM_DATA4=23
|
||||
CONFIG_EXAMPLE_PIN_NUM_DATA5=33
|
||||
CONFIG_EXAMPLE_PIN_NUM_DATA6=32
|
||||
CONFIG_EXAMPLE_PIN_NUM_DATA7=27
|
||||
CONFIG_EXAMPLE_PIN_NUM_DATA8=12
|
||||
CONFIG_EXAMPLE_PIN_NUM_DATA9=13
|
||||
CONFIG_EXAMPLE_PIN_NUM_DATA10=14
|
||||
CONFIG_EXAMPLE_PIN_NUM_DATA11=15
|
||||
CONFIG_EXAMPLE_PIN_NUM_DATA12=26
|
||||
CONFIG_EXAMPLE_PIN_NUM_DATA13=25
|
||||
CONFIG_EXAMPLE_PIN_NUM_DATA14=16
|
||||
CONFIG_EXAMPLE_PIN_NUM_DATA15=17
|
||||
|
||||
@@ -2,6 +2,7 @@ CONFIG_SPIRAM=y
|
||||
CONFIG_SPIRAM_MODE_HEX=y
|
||||
CONFIG_SPIRAM_SPEED_200M=y
|
||||
CONFIG_IDF_EXPERIMENTAL_FEATURES=y
|
||||
CONFIG_EXAMPLE_LCD_I80_COLOR_IN_PSRAM=y
|
||||
|
||||
CONFIG_EXAMPLE_PIN_NUM_BK_LIGHT=48
|
||||
CONFIG_EXAMPLE_PIN_NUM_RST=35
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
CONFIG_EXAMPLE_PIN_NUM_PCLK=5
|
||||
CONFIG_EXAMPLE_PIN_NUM_CS=3
|
||||
CONFIG_EXAMPLE_PIN_NUM_DC=4
|
||||
CONFIG_EXAMPLE_PIN_NUM_RST=2
|
||||
CONFIG_EXAMPLE_PIN_NUM_BK_LIGHT=1
|
||||
CONFIG_EXAMPLE_PIN_NUM_DATA0=6
|
||||
CONFIG_EXAMPLE_PIN_NUM_DATA1=7
|
||||
CONFIG_EXAMPLE_PIN_NUM_DATA2=8
|
||||
CONFIG_EXAMPLE_PIN_NUM_DATA3=9
|
||||
CONFIG_EXAMPLE_PIN_NUM_DATA4=10
|
||||
CONFIG_EXAMPLE_PIN_NUM_DATA5=11
|
||||
CONFIG_EXAMPLE_PIN_NUM_DATA6=12
|
||||
CONFIG_EXAMPLE_PIN_NUM_BK_LIGHT=0
|
||||
CONFIG_EXAMPLE_PIN_NUM_RST=18
|
||||
CONFIG_EXAMPLE_PIN_NUM_CS=19
|
||||
CONFIG_EXAMPLE_PIN_NUM_DC=38
|
||||
CONFIG_EXAMPLE_PIN_NUM_PCLK=33
|
||||
CONFIG_EXAMPLE_PIN_NUM_DATA0=1
|
||||
CONFIG_EXAMPLE_PIN_NUM_DATA1=10
|
||||
CONFIG_EXAMPLE_PIN_NUM_DATA2=2
|
||||
CONFIG_EXAMPLE_PIN_NUM_DATA3=11
|
||||
CONFIG_EXAMPLE_PIN_NUM_DATA4=3
|
||||
CONFIG_EXAMPLE_PIN_NUM_DATA5=12
|
||||
CONFIG_EXAMPLE_PIN_NUM_DATA6=4
|
||||
CONFIG_EXAMPLE_PIN_NUM_DATA7=13
|
||||
CONFIG_EXAMPLE_PIN_NUM_DATA8=14
|
||||
CONFIG_EXAMPLE_PIN_NUM_DATA9=15
|
||||
CONFIG_EXAMPLE_PIN_NUM_DATA10=16
|
||||
CONFIG_EXAMPLE_PIN_NUM_DATA11=17
|
||||
CONFIG_EXAMPLE_PIN_NUM_DATA12=18
|
||||
CONFIG_EXAMPLE_PIN_NUM_DATA13=19
|
||||
CONFIG_EXAMPLE_PIN_NUM_DATA14=20
|
||||
CONFIG_EXAMPLE_PIN_NUM_DATA15=21
|
||||
CONFIG_EXAMPLE_PIN_NUM_DATA8=5
|
||||
CONFIG_EXAMPLE_PIN_NUM_DATA9=14
|
||||
CONFIG_EXAMPLE_PIN_NUM_DATA10=6
|
||||
CONFIG_EXAMPLE_PIN_NUM_DATA11=15
|
||||
CONFIG_EXAMPLE_PIN_NUM_DATA12=7
|
||||
CONFIG_EXAMPLE_PIN_NUM_DATA13=16
|
||||
CONFIG_EXAMPLE_PIN_NUM_DATA14=8
|
||||
CONFIG_EXAMPLE_PIN_NUM_DATA15=17
|
||||
|
||||
@@ -4,7 +4,7 @@ CONFIG_SPIRAM_SPEED_80M=y
|
||||
# Enabling the following configurations can help increase the PCLK frequency in the case when
|
||||
# the Frame Buffer is allocated from the PSRAM and fetched by EDMA
|
||||
CONFIG_SPIRAM_XIP_FROM_PSRAM=y
|
||||
|
||||
CONFIG_EXAMPLE_LCD_I80_COLOR_IN_PSRAM=y
|
||||
|
||||
CONFIG_EXAMPLE_PIN_NUM_PCLK=2
|
||||
CONFIG_EXAMPLE_PIN_NUM_CS=0
|
||||
|
||||
Reference in New Issue
Block a user