Board
Waveshare Development Board With 3.49inch IPS
Hardware Description
ESP32-S3 High-Performance Development Board With 3.49inch IPS Capacitive Touch Display, 172 × 640 Resolution, Integrated With ESP32-S3R8 Dual-core Processor
ESP32-S3 with QSPI LCD panel (AXS15231B 172×640), 8MB PSRAM
IDE Name
VSCode, esp_lvgl_port 2.7.1, LVGL 9.4.0, ESP-IDF 5.5.2
Operating System
Windows 10
Description
The lvgl_port_display_cfg_t struct exposes a trans_size field:
uint32_t trans_size; /*!< Allocated buffer will be in SRAM to move framebuf (optional) */
In the LVGL8 version (esp_lvgl_port_disp.c), this field is used to:
- Allocate a DMA-capable SRAM buffer (trans_buf) via heap_caps_malloc(..., MALLOC_CAP_DMA)
- In the flush callback, copy framebuffer data from PSRAM to trans_buf in chunks, calling draw_bitmap per chunk with semaphore synchronization between transfers
In the LVGL9 version (esp_lvgl_port_disp.c), this field is completely ignored. The lvgl_port_display_ctx_t struct does not contain trans_buf or trans_size. The flush callback passes the entire PSRAM buffer directly to esp_lcd_panel_draw_bitmap() in a single call.
Impact:
For SPI-connected panels with full-screen PSRAM buffers (e.g., 172×640×2 = 220KB for full_refresh mode), the single draw_bitmap call attempts a 220KB SPI DMA transfer from PSRAM, which fails:
panel_io_spi_tx_color(395): spi transmit (queue) color failed
LVGL then hangs in wait_for_flushing and the watchdog triggers every 5 seconds.
Users setting trans_size to enable chunking get no error, no warning — the code compiles and runs, but trans_size has no effect whatsoever.
Workaround:
A panel wrapper that intercepts draw_bitmap, copies chunks from PSRAM to a small DMA-capable SRAM buffer via memcpy, and calls the real panel's draw_bitmap per chunk. The wrapper also manually calls lv_disp_flush_ready() after the last chunk and disables the auto-registered on_color_trans_done callback.
Expected behavior:
Either:
- Implement trans_size chunking in the LVGL9 flush callback (port the LVGL8 logic), or
- Remove the trans_size field from the config struct and document that PSRAM framebuffers require a custom panel wrapper for SPI panels, or
- Emit a warning at runtime when trans_size > 0 and LVGL9 is used, so users know it's not implemented
Option 1 would be ideal — the LVGL8 implementation already works and the pattern is straightforward.
Sketch
Other Steps to Reproduce
No response
I have checked existing issues, README.md and ESP32 Forum
Board
Waveshare Development Board With 3.49inch IPS
Hardware Description
ESP32-S3 High-Performance Development Board With 3.49inch IPS Capacitive Touch Display, 172 × 640 Resolution, Integrated With ESP32-S3R8 Dual-core Processor
ESP32-S3 with QSPI LCD panel (AXS15231B 172×640), 8MB PSRAM
IDE Name
VSCode, esp_lvgl_port 2.7.1, LVGL 9.4.0, ESP-IDF 5.5.2
Operating System
Windows 10
Description
The lvgl_port_display_cfg_t struct exposes a trans_size field:
uint32_t trans_size; /*!< Allocated buffer will be in SRAM to move framebuf (optional) */
In the LVGL8 version (esp_lvgl_port_disp.c), this field is used to:
In the LVGL9 version (esp_lvgl_port_disp.c), this field is completely ignored. The lvgl_port_display_ctx_t struct does not contain trans_buf or trans_size. The flush callback passes the entire PSRAM buffer directly to esp_lcd_panel_draw_bitmap() in a single call.
Impact:
For SPI-connected panels with full-screen PSRAM buffers (e.g., 172×640×2 = 220KB for full_refresh mode), the single draw_bitmap call attempts a 220KB SPI DMA transfer from PSRAM, which fails:
panel_io_spi_tx_color(395): spi transmit (queue) color failed
LVGL then hangs in wait_for_flushing and the watchdog triggers every 5 seconds.
Users setting trans_size to enable chunking get no error, no warning — the code compiles and runs, but trans_size has no effect whatsoever.
Workaround:
A panel wrapper that intercepts draw_bitmap, copies chunks from PSRAM to a small DMA-capable SRAM buffer via memcpy, and calls the real panel's draw_bitmap per chunk. The wrapper also manually calls lv_disp_flush_ready() after the last chunk and disables the auto-registered on_color_trans_done callback.
Expected behavior:
Either:
Option 1 would be ideal — the LVGL8 implementation already works and the pattern is straightforward.
Sketch
Other Steps to Reproduce
No response
I have checked existing issues, README.md and ESP32 Forum