Error: lcd_panel.io.spi: panel_io_spi_tx_color(395): spi transmit (queue) color failed

I use esp32s3 and lvgl 8.3.11
The image is successfully drawn on the QSPI display with 360x360 px

I added two tasks to freeRTOS, one controls the backlight, and the other starts Wi-Fi and creates an access point on the device.
The pseudocode is:

#include "Arduino.h"
// setup for QSPI st77916 display
#include "scr_st77916.h"
#include <lvgl.h>

// widget
#include <ui.h>

// Task for initializing and controlling PWM
void pwmTask(void *pvParameters) {
  while (true) {
    }
    backlight->setBrightness(brightness);
    vTaskDelay(5 / portTICK_PERIOD_MS);
  }
}

// Task for initializing wi-fi
void settingsTask(void *pvParameters) {
    while (true) {
      sett_loop();
      vTaskDelay(5 / portTICK_PERIOD_MS);
    }
}

void setup()
{
scr_lvgl_init();
ui_init();

// Task wi-fi
xTaskCreate(settingsTask, "Settings Task", 4096, NULL, 0, NULL);
// Task PWM
xTaskCreatePinnedToCore(pwmTask, "Task", configMINIMAL_STACK_SIZE + 1024, NULL, tskIDLE_PRIORITY, NULL, 0);
}

void loop()
{
// anything
}

The file scr_st77916.h contains display buffer settings for lvgl 8, part of the code is:

#define SCREEN_RES_HOR 280
#define SCREEN_RES_VER 280
// #define SCREEN_RES_HOR 359
// #define SCREEN_RES_VER 359

#define TFT_SPI_FREQ_HZ (30 * 1000 * 1000)

static void my_disp_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p)
{
  ESP_PanelLcd *lcd = (ESP_PanelLcd *)disp->user_data;
  const int offsetx1 = area->x1;
  const int offsetx2 = area->x2;
  const int offsety1 = area->y1;
  const int offsety2 = area->y2;
  // lcd->drawBitmap(offsetx1, offsety1, offsetx2 - offsetx1 + 1, offsety2 - offsety1 + 1, (const uint8_t *)color_p);
  lcd->drawBitmap(offsetx1 + RATIO, offsety1 + RATIO, offsetx2 - offsetx1 + 1, offsety2 - offsety1 + 1, (const uint8_t *)color_p);
}

static lv_color_t *disp_draw_buf = NULL;
static lv_color_t *buf1 = NULL;
static lv_color_t *buf2 = NULL;
static lv_disp_draw_buf_t draw_buf;
static lv_disp_drv_t disp_drv;

ESP_PanelBus_QSPI *panel_bus = new ESP_PanelBus_QSPI(TFT_CS, TFT_SCK, TFT_SDA0, TFT_SDA1, TFT_SDA2, TFT_SDA3);
panel_bus->configQspiFreqHz(TFT_SPI_FREQ_HZ);
panel_bus->begin();

lcd = new ESP_PanelLcd_ST77916(panel_bus, 16, TFT_RST);
lcd->init();
lcd->reset();
lcd->begin();

// old setup
size_t lv_cache_rows = 72;
size_t lv_buffer_size = SCREEN_RES_HOR * SCREEN_RES_VER;
disp_draw_buf = (lv_color_t *)heap_caps_malloc(lv_cache_rows * SCREEN_RES_HOR * 2, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
assert(disp_draw_buf);
buf1 = (lv_color_t *)heap_caps_malloc(lv_buffer_size, MALLOC_CAP_SPIRAM);
assert(buf1);
lv_init();
lv_disp_draw_buf_init(&draw_buf, disp_draw_buf, buf1, SCREEN_RES_HOR * lv_cache_rows);

// new setup
drawBufSize = screenWidth * screenHeight;
buf1= (lv_color_t*)heap_caps_malloc(drawBufSize, MALLOC_CAP_SPIRAM);
assert(buf1);
buf2 = (lv_color_t*)heap_caps_malloc(drawBufSize, MALLOC_CAP_SPIRAM);
assert(buf2);

lv_init();
lv_disp_draw_buf_init(&draw_buf, buf1, buf2, SCREEN_RES_HOR * SCREEN_RES_VER);

With the old setup configuration I get this picture, and the pwm backlight works, but in the serial port there is this error:

E (3347) lcd_panel.io.spi: panel_io_spi_tx_color(395): spi transmit (queue) color failed

I tried to set the buffers as I set for the same display in lvgl 9.3 new setup, but in this case the display does not display anything except snow and the esp32s3 constantly reboots.
I managed to select the size 280x280, when the image is loaded and the animation starts working.

But I would like to understand the problem and set the buffers correctly.

In the code, the image is formed as a bitmap
lcd->drawBitmap(offsetx1 + RATIO, offsety1 + RATIO, offsetx2 - offsetx1 + 1, offsety2 - offsety1 + 1, (const uint8_t *)color_p);
I use the Arduino framework

Arduino Core 3.3.0 based on ESP-IDF v5.5.0 for Platformio

And a fairly old library for QSPI panels

Dependency Graph
|-- ESP32_IO_Expander @ 0.0.2
|-- ESP32_Display_Panel @ 0.1.4

For example, for lvgl 9.3 for the same device I use this display update function

void my_disp_flush(lv_display_t *disp, const lv_area_t *area, uint8_t *px_map) // LVGL 9.3
{
uint32_t w = lv_area_get_width(area);
uint32_t h = lv_area_get_height(area);
gfx->draw16bitRGBBitmap(area->x1, area->y1, (uint16_t *)px_map, w, h); // LVGL 9.3
lv_disp_flush_ready(disp);
}

But in version 8.3.11 it doesn’t work.

I didn’t manage to migrate to ESP32_Display_Panel 1.0.3

Help with migration to ESP32_Display_Panel Release v1.0.3 or 1.0.4 · esp-arduino-libs/ESP32_Display_Panel · Discussion #231 · GitHub

I decided to try using LovyanGFX to output graphics in lvgl 8.3.11.
If the function is like this:

// #define ESP32_LCD_WIDTH                  280
// #define ESP32_LCD_HEIGHT                 280
#define ESP32_LCD_WIDTH                  360
#define ESP32_LCD_HEIGHT                 360

static lv_color_t *disp_draw_buf = NULL;
static lv_color_t *buf1 = NULL;
static lv_color_t *buf2 = NULL;
static lv_disp_draw_buf_t draw_buf;
static lv_disp_drv_t disp_drv;

// LovyanGFX
void my_disp_flush( lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p )
{
    uint32_t w = lv_area_get_width(area);
    uint32_t h = lv_area_get_height(area);
    gfx.setAddrWindow( area->x1, area->y1, w, h );
    gfx.pushPixelsDMA(( uint16_t * )color_p, w * h, false);  // false = swap
    gfx.endWrite();
    lv_disp_flush_ready(disp);
}

and

void scr_lvgl_init()
{
  lv_init();

  size_t lv_cache_rows = 50;
  size_t lv_buffer_size = GUITION_ESP32_LCD_WIDTH * GUITION_ESP32_LCD_HEIGHT;
  static void* buf1 = (lv_color_t*)heap_caps_malloc(lv_buffer_size, MALLOC_CAP_SPIRAM);
  static void* buf2 = (lv_color_t*)heap_caps_malloc(lv_buffer_size, MALLOC_CAP_SPIRAM);

// lv_color_t *buf1 = (lv_color_t*)heap_caps_malloc((lv_buffer_size * sizeof(lv_color_t)) / 4, MALLOC_CAP_DMA | MALLOC_CAP_SPIRAM);
// lv_color_t *buf2 = (lv_color_t*)heap_caps_malloc((lv_buffer_size * sizeof(lv_color_t)) / 4, MALLOC_CAP_DMA | MALLOC_CAP_SPIRAM);

  lv_disp_draw_buf_init(&draw_buf, buf1, buf2, ESP32_LCD_WIDTH * lv_cache_rows);
  lv_disp_drv_init(&disp_drv);
  disp_drv.hor_res = ESP32_LCD_WIDTH;
  disp_drv.ver_res = ESP32_LCD_HEIGHT;
  disp_drv.flush_cb = my_disp_flush;
  disp_drv.draw_buf = &draw_buf;
  lv_disp_drv_register(&disp_drv);

}

And with the speed of the QSPI being 30 MHz, I get this weird and broken:

When I reduce the frequency of the QSPI to 5 mhz, the image is like this.

If I start outputting not through DMA, but as an image

void my_disp_flush( lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p )
{
    uint32_t w = lv_area_get_width(area);
    uint32_t h = lv_area_get_height(area);
    gfx.pushImage(area->x1, area->y1, w, h, (uint16_t*)color_p);
    lv_disp_flush_ready(disp);
}

That display is quite normal, but some elements still break, and here the QSPI speed of 5 or 30 MHz does not affect, the result is the same:

static void guiTask(void *pvParameter)
{
    SemaphoreHandle_t xGuiSemaphore = xSemaphoreCreateMutex();
    scr_lvgl_init();

    while (1)
    {
        vTaskDelay(pdMS_TO_TICKS(2));
        /* Try to take the semaphore, call lvgl related function on success */
        if (pdTRUE == xSemaphoreTake(xGuiSemaphore, portMAX_DELAY))
        {
            lv_task_handler();
            // lv_timer_handler();
            xSemaphoreGive(xGuiSemaphore);
        }
    }

    vTaskDelete(NULL);
}

The super-cycle is as follows:

void loop()
{
    // lv_timer_handler(); /* Let the GUI do its work */
    // delay(2);
} // LOOP

The image simply loads onto 1/4 of the screen and after 4-5 seconds the device reboots and even the USB drops out, although this has never happened before :roll_eyes:

#define GUITION_ESP32_LCD_WIDTH                  280
#define GUITION_ESP32_LCD_HEIGHT                 280
#define RATIO  (360 - GUITION_ESP32_LCD_WIDTH) / 2

void my_disp_flush( lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p )
{
    uint32_t w = lv_area_get_width(area);
    uint32_t h = lv_area_get_height(area);
    gfx.pushImage(area->x1 + RATIO, area->y1 + RATIO, w, h, (uint16_t*)color_p);
    lv_disp_flush_ready(disp);
}

Also a mutex is used and the image is loaded on 1/3 and the device also reboots cyclically:

Guru Meditation Error: Core 0 panic’ed (Unhandled debug exception).
Debug exception reason: Stack canary watchpoint triggered (Display Task)

Nothing works, neither DMA nor mutex works :slightly_frowning_face:
Perhaps, qspi does not allow to work with images normally and it is better to choose 8 or 16 bit 8080-interface?