Hi! I’m having an issues with setting up my display.
I’m using LVGL v9 on ESP32s3 with st7789 attached.
My code was working fine, but after several days I can not run it anymore. I’m newbie so may be doing it wrong. So I have ESP32s3, attached to PC through USB and ESP-IDF plugin installed to vscode on linux. So Here is my code from main:
/*
- SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD
- SPDX-License-Identifier: CC0-1.0
*/#include <stdio.h>
#include <inttypes.h>
#include “sdkconfig.h”
#include “freertos/FreeRTOS.h”
#include “freertos/task.h”
#include “esp_chip_info.h”
#include “esp_flash.h”
#include “esp_system.h”
#include “…/components/lvgl_esp32_drivers/lvgl_tft/driver/esp_timer.h”#include <stdbool.h>
#include <stdlib.h>
#include <string.h>#include “esp_freertos_hooks.h”
#include “freertos/semphr.h”
#include “…/components/lvgl_esp32_drivers/lvgl_tft/driver/gpio.h”#include “…/components/lvgl/lvgl.h”
#include “…/components/lvgl_esp32_drivers/lvgl_helpers.h”#define LV_TICK_PERIOD_MS 1
SemaphoreHandle_t xGuiSemaphore;
static void lv_tick_task(void *arg);
static void guiTask(void *pvParameter);
static void create_demo_application(void);static void lv_tick_task(void *arg) {
(void) arg;lv_tick_inc(LV_TICK_PERIOD_MS);
}
static void create_demo_application(void)
{}
static void guiTask(void *pvParameter) {
(void) pvParameter; xGuiSemaphore = xSemaphoreCreateMutex(); lv_init(); /* Initialize SPI or I2C bus used by the drivers */ lvgl_driver_init(); lv_color_t* buf1 = heap_caps_malloc(DISP_BUF_SIZE * sizeof(lv_color_t), MALLOC_CAP_DMA); assert(buf1 != NULL); lv_color_t* buf2 = heap_caps_malloc(DISP_BUF_SIZE * sizeof(lv_color_t), MALLOC_CAP_DMA); assert(buf2 != NULL); static lv_disp_buf_t disp_buf; uint32_t size_in_px = DISP_BUF_SIZE; /* Initialize the working buffer depending on the selected display.*/ lv_disp_buf_init(&disp_buf, buf1, buf2, size_in_px); lv_disp_drv_t disp_drv; lv_disp_drv_init(&disp_drv); disp_drv.flush_cb = disp_driver_flush;
#if defined CONFIG_DISPLAY_ORIENTATION_PORTRAIT || defined CONFIG_DISPLAY_ORIENTATION_PORTRAIT_INVERTED
disp_drv.rotated = 1;
#endifdisp_drv.buffer = &disp_buf; lv_disp_drv_register(&disp_drv); /* Register an input device when enabled on the menuconfig */
#if CONFIG_LV_TOUCH_CONTROLLER != TOUCH_CONTROLLER_NONE
lv_indev_drv_t indev_drv;
lv_indev_drv_init(&indev_drv);
indev_drv.read_cb = touch_driver_read;
indev_drv.type = LV_INDEV_TYPE_POINTER;
lv_indev_drv_register(&indev_drv);
#endif/* Create and start a periodic timer interrupt to call lv_tick_inc */ const esp_timer_create_args_t periodic_timer_args = { .callback = &lv_tick_task, .name = "periodic_gui" }; esp_timer_handle_t periodic_timer; ESP_ERROR_CHECK(esp_timer_create(&periodic_timer_args, &periodic_timer)); ESP_ERROR_CHECK(esp_timer_start_periodic(periodic_timer, LV_TICK_PERIOD_MS * 1000)); /* Create the demo application */ create_demo_application(); while (1) { /* Delay 1 tick (assumes FreeRTOS tick is 10ms */ vTaskDelay(pdMS_TO_TICKS(10)); /* Try to take the semaphore, call lvgl related function on success */ if (pdTRUE == xSemaphoreTake(xGuiSemaphore, portMAX_DELAY)) { lv_task_handler(); xSemaphoreGive(xGuiSemaphore); } } /* A task should NEVER return */ free(buf1); free(buf2); vTaskDelete(NULL);
}
void app_main(void)
{
xTaskCreatePinnedToCore(guiTask, “gui”, 4096*2, NULL, 0, NULL, 1);printf("Hello world!\n"); /* Print chip information */ esp_chip_info_t chip_info; uint32_t flash_size; esp_chip_info(&chip_info); printf("This is %s chip with %d CPU core(s), %s%s%s%s, ", CONFIG_IDF_TARGET, chip_info.cores, (chip_info.features & CHIP_FEATURE_WIFI_BGN) ? "WiFi/" : "", (chip_info.features & CHIP_FEATURE_BT) ? "BT" : "", (chip_info.features & CHIP_FEATURE_BLE) ? "BLE" : "", (chip_info.features & CHIP_FEATURE_IEEE802154) ? ", 802.15.4 (Zigbee/Thread)" : ""); unsigned major_rev = chip_info.revision / 100; unsigned minor_rev = chip_info.revision % 100; printf("silicon revision v%d.%d, ", major_rev, minor_rev); if(esp_flash_get_size(NULL, &flash_size) != ESP_OK) { printf("Get flash size failed"); return; } printf("%" PRIu32 "MB %s flash\n", flash_size / (uint32_t)(1024 * 1024), (chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded" : "external"); printf("Minimum free heap size: %" PRIu32 " bytes\n", esp_get_minimum_free_heap_size()); for (int i = 10; i >= 0; i--) { printf("Restarting in %d seconds...\n", i); vTaskDelay(1000 / portTICK_PERIOD_MS); } printf("Restarting now.\n"); fflush(stdout); esp_restart();
}
I can compile it without any errors and I can even flash it to the board. Through idf.py menuconfig I can set the ports for SPI (HSPI/SPI3_HOST) and backlight. I can turn the backlight on and off, but I have a blackscreen. Since the last build I had an errors on DMA channel (an error, telling that my board supports auto dma only), so I’ve changed the DMA channel to auto:
bool lvgl_spi_driver_init(int host,
int miso_pin, int mosi_pin, int sclk_pin,
int max_transfer_sz,
int dma_channel,
int quadwp_pin, int quadhd_pin)
{
assert((0 <= host) && (SPI_HOST_MAX > host));
const char *spi_names = {
“SPI1_HOST”, “SPI2_HOST”, “SPI3_HOST”
};ESP_LOGI(TAG, "Configuring SPI host %s", spi_names[host]); ESP_LOGI(TAG, "MISO pin: %d, MOSI pin: %d, SCLK pin: %d, IO2/WP pin: %d, IO3/HD pin: %d", miso_pin, mosi_pin, sclk_pin, quadwp_pin, quadhd_pin); ESP_LOGI(TAG, "Max transfer size: %d (bytes)", max_transfer_sz); spi_bus_config_t buscfg = { .miso_io_num = miso_pin, .mosi_io_num = mosi_pin, .sclk_io_num = sclk_pin, .quadwp_io_num = quadwp_pin, .quadhd_io_num = quadhd_pin, .max_transfer_sz = max_transfer_sz }; ESP_LOGI(TAG, "Initializing SPI bus..."); #if defined (CONFIG_IDF_TARGET_ESP32S3) **dma_channel = SPI_DMA_CH_AUTO;** #endif esp_err_t ret = spi_bus_initialize(host, &buscfg, (spi_dma_chan_t)dma_channel); assert(ret == ESP_OK); return ESP_OK != ret;
}
But I’m still having a black screen.
Also I’ve set the custom frequency of the SPI for communicating with my st7789 (20MHz) and on the oscilloscope I can see something unclear:
I have no idea where to move to solve this problem. Appreciate any ideas!-)
Here is my idf.py monitor output:
ESP-ROM:esp32s3-20210327
Build:Mar 27 2021
rst:0xc (RTC_SW_CPU_RST),boot:0x8 (SPI_FAST_FLASH_BOOT)
Saved PC:0x40375b14
— 0x40375b14: esp_restart_noos at /home/maxim/esp/v5.4.2/esp-idf/components/esp_system/port/soc/esp32s3/system_internal.c:162SPIWP:0xee
mode:DIO, clock div:1
load:0x3fce2810,len:0x1564
load:0x403c8700,len:0x4
load:0x403c8704,len:0xd24
load:0x403cb700,len:0x2ed4
entry 0x403c8928
I (31) boot: ESP-IDF v5.4.2-dirty 2nd stage bootloader
I (31) boot: compile time Jul 3 2025 14:34:28
I (31) boot: Multicore bootloader
I (32) boot: chip revision: v0.2
I (35) boot: efuse block revision: v1.3
I (38) boot.esp32s3: Boot SPI Speed : 80MHz
I (42) boot.esp32s3: SPI Mode : DIO
I (46) boot.esp32s3: SPI Flash Size : 2MB
I (50) boot: Enabling RNG early entropy source…
I (54) boot: Partition Table:
I (57) boot: ## Label Usage Type ST Offset Length
I (63) boot: 0 nvs WiFi data 01 02 00009000 00006000
I (70) boot: 1 phy_init RF data 01 01 0000f000 00001000
I (76) boot: 2 factory factory app 00 00 00010000 00100000
I (83) boot: End of partition table
I (86) esp_image: segment 0: paddr=00010020 vaddr=3c040020 size=10e24h ( 69156) map
I (106) esp_image: segment 1: paddr=00020e4c vaddr=3fc94c00 size=02b9ch ( 11164) load
I (108) esp_image: segment 2: paddr=000239f0 vaddr=40374000 size=0c628h ( 50728) load
I (120) esp_image: segment 3: paddr=00030020 vaddr=42000020 size=321ach (205228) map
I (157) esp_image: segment 4: paddr=000621d4 vaddr=40380628 size=044fch ( 17660) load
I (161) esp_image: segment 5: paddr=000666d8 vaddr=600fe000 size=0001ch ( 28) load
I (168) boot: Loaded app from partition at offset 0x10000
I (168) boot: Disabling RNG early entropy source…
I (182) cpu_start: Multicore app
I (192) cpu_start: Pro cpu start user code
I (192) cpu_start: cpu freq: 160000000 Hz
I (192) app_init: Application information:
I (192) app_init: Project name: st7789fromScratch
I (197) app_init: App version: 1
I (200) app_init: Compile time: Jul 3 2025 17:54:11
I (205) app_init: ELF file SHA256: 06bb4a009…
I (209) app_init: ESP-IDF: v5.4.2-dirty
I (214) efuse_init: Min chip rev: v0.0
I (218) efuse_init: Max chip rev: v0.99
I (222) efuse_init: Chip rev: v0.2
I (225) heap_init: Initializing. RAM available for dynamic allocation:
I (232) heap_init: At 3FCA05D0 len 00049140 (292 KiB): RAM
I (237) heap_init: At 3FCE9710 len 00005724 (21 KiB): RAM
I (242) heap_init: At 3FCF0000 len 00008000 (32 KiB): DRAM
I (247) heap_init: At 600FE01C len 00001FCC (7 KiB): RTCRAM
I (254) spi_flash: detected chip: generic
I (256) spi_flash: flash io: dio
W (259) spi_flash: Detected size(16384k) larger than the size in the binary image header(2048k). Using the size in the binary image header.
W (271) i2c: This driver is an old driver, please migrate your application code to adaptdriver/i2c_master.h
I (281) sleep_gpio: Configure to isolate all GPIO pins in sleep state
I (288) sleep_gpio: Enable automatic switching of GPIO sleep configuration
I (294) main_task: Started on CPU0
I (304) main_task: Calling app_main()
Hello world!
This is esp32s3 chip with 2 CPU core(s), WiFi/BLE, silicon revision v0.2, 2MB external flash
Minimum free heap size: 332276 bytes
Restarting in 10 seconds…
I (324) lvgl_helpers: Display hor size: 240, ver size: 240
I (324) lvgl_helpers: Display buffer size: 9600
I (334) lvgl_helpers: Initializing SPI master for display
I (334) lvgl_helpers: Configuring SPI host SPI3_HOST
I (334) lvgl_helpers: MISO pin: -1, MOSI pin: 13, SCLK pin: 14, IO2/WP pin: -1, IO3/HD pin: -1
I (344) lvgl_helpers: Max transfer size: 19200 (bytes)
I (354) lvgl_helpers: Initializing SPI bus…
I (354) disp_spi: Adding SPI device
I (354) disp_spi: Clock speed: 20000000Hz, mode: 2, CS pin: -1
ST7789 initialization.
Enabling backlight.
I (804) st7789: Display orientation: PORTRAIT
I (804) st7789: 0x36 command value: 0xC0
Restarting in 9 seconds…
Restarting in 8 seconds…
Restarting in 7 seconds…
Restarting in 6 seconds…
Restarting in 5 seconds…
Restarting in 4 seconds…
Restarting in 3 seconds…
Restarting in 2 seconds…
Restarting in 1 seconds…
Restarting in 0 seconds…
Restarting now.