feat(esp_lcd): Add PSRAM support in SPI LCD panel IO

When the color buffer resides in PSRAM, set the SPI_TRANS_DMA_USE_PSRAM
flag.

Closes https://github.com/espressif/esp-idf/issues/18282
Merges https://github.com/espressif/esp-idf/pull/18283
This commit is contained in:
Daniel Kampert
2026-02-26 11:06:25 +01:00
committed by morris
parent 799c800494
commit 4cb1dc08c2
3 changed files with 41 additions and 10 deletions
@@ -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: Apache-2.0
*/
@@ -23,6 +23,7 @@
#include "esp_log.h"
#include "esp_check.h"
#include "esp_lcd_common.h"
#include "esp_memory_utils.h"
static const char *TAG = "lcd_panel.io.spi";
@@ -346,11 +347,14 @@ static esp_err_t panel_io_spi_tx_color(esp_lcd_panel_io_t *io, int lcd_cmd, cons
// use 8 lines for transmitting command, address and data
lcd_trans->base.flags |= (SPI_TRANS_MULTILINE_CMD | SPI_TRANS_MULTILINE_ADDR | SPI_TRANS_MODE_OCT);
}
// command is short, using polling mode
ret = spi_device_polling_transmit(spi_panel_io->spi_dev, &lcd_trans->base);
ESP_GOTO_ON_ERROR(ret, err, TAG, "spi transmit (polling) command failed");
}
bool color_in_psram = color && color_size && esp_ptr_external_ram(color);
// if the color buffer is big, we want to split it into chunks, and queue the chunks one by one
do {
size_t chunk_size = color_size;
@@ -366,6 +370,10 @@ static esp_err_t panel_io_spi_tx_color(esp_lcd_panel_io_t *io, int lcd_cmd, cons
spi_panel_io->num_trans_inflight--;
}
memset(lcd_trans, 0, sizeof(lcd_spi_trans_descriptor_t));
if (color_in_psram) {
// When the color buffer resides in PSRAM, set the DMA PSRAM flag
lcd_trans->base.flags |= SPI_TRANS_DMA_USE_PSRAM;
}
// SPI per-transfer size has its limitation, if the color buffer is too big, we need to split it into multiple chunks
if (chunk_size > spi_panel_io->spi_trans_max_bytes) {
@@ -75,9 +75,9 @@ void test_spi_lcd_common_initialize(esp_lcd_panel_io_handle_t *io_handle, esp_lc
#define TEST_IMG_SIZE (200 * 200 * sizeof(uint16_t))
static void lcd_panel_test(esp_lcd_panel_io_handle_t io_handle, esp_lcd_panel_handle_t panel_handle)
static void lcd_panel_test(esp_lcd_panel_io_handle_t io_handle, esp_lcd_panel_handle_t panel_handle, bool use_psram)
{
uint8_t *img = heap_caps_malloc(TEST_IMG_SIZE, MALLOC_CAP_DMA);
uint8_t *img = heap_caps_malloc(TEST_IMG_SIZE, MALLOC_CAP_DMA | (use_psram ? MALLOC_CAP_SPIRAM : MALLOC_CAP_INTERNAL));
TEST_ASSERT_NOT_NULL(img);
esp_lcd_panel_reset(panel_handle);
@@ -114,10 +114,6 @@ static void lcd_panel_test(esp_lcd_panel_io_handle_t io_handle, esp_lcd_panel_ha
printf("turn off the panel\r\n");
esp_lcd_panel_disp_on_off(panel_handle, false);
TEST_ESP_OK(esp_lcd_panel_del(panel_handle));
TEST_ESP_OK(esp_lcd_panel_io_del(io_handle));
TEST_ESP_OK(spi_bus_free(TEST_SPI_HOST_ID));
TEST_ESP_OK(gpio_reset_pin(TEST_LCD_BK_LIGHT_GPIO));
free(img);
}
@@ -175,7 +171,15 @@ TEST_CASE("lcd_panel_with_8-line_spi_interface_(st7789)", "[lcd]")
.bits_per_pixel = 16,
};
TEST_ESP_OK(esp_lcd_new_panel_st7789(io_handle, &panel_config, &panel_handle));
lcd_panel_test(io_handle, panel_handle);
lcd_panel_test(io_handle, panel_handle, false);
#if SOC_PSRAM_DMA_CAPABLE && CONFIG_PSRAM
printf("test with PSRAM\r\n");
lcd_panel_test(io_handle, panel_handle, true);
#endif
TEST_ESP_OK(esp_lcd_panel_del(panel_handle));
TEST_ESP_OK(esp_lcd_panel_io_del(io_handle));
TEST_ESP_OK(spi_bus_free(TEST_SPI_HOST_ID));
TEST_ESP_OK(gpio_reset_pin(TEST_LCD_BK_LIGHT_GPIO));
}
TEST_CASE("lcd_panel_with_8-line_spi_interface_(nt35510)", "[lcd]")
@@ -189,7 +193,15 @@ TEST_CASE("lcd_panel_with_8-line_spi_interface_(nt35510)", "[lcd]")
.bits_per_pixel = 16,
};
TEST_ESP_OK(esp_lcd_new_panel_nt35510(io_handle, &panel_config, &panel_handle));
lcd_panel_test(io_handle, panel_handle);
lcd_panel_test(io_handle, panel_handle, false);
#if SOC_PSRAM_DMA_CAPABLE && CONFIG_PSRAM
printf("test with PSRAM\r\n");
lcd_panel_test(io_handle, panel_handle, true);
#endif
TEST_ESP_OK(esp_lcd_panel_del(panel_handle));
TEST_ESP_OK(esp_lcd_panel_io_del(io_handle));
TEST_ESP_OK(spi_bus_free(TEST_SPI_HOST_ID));
TEST_ESP_OK(gpio_reset_pin(TEST_LCD_BK_LIGHT_GPIO));
}
#endif // SOC_SPI_SUPPORT_OCT
@@ -204,7 +216,15 @@ TEST_CASE("lcd_panel_with_1-line_spi_interface_(st7789)", "[lcd]")
.bits_per_pixel = 16,
};
TEST_ESP_OK(esp_lcd_new_panel_st7789(io_handle, &panel_config, &panel_handle));
lcd_panel_test(io_handle, panel_handle);
lcd_panel_test(io_handle, panel_handle, false);
#if SOC_PSRAM_DMA_CAPABLE && CONFIG_PSRAM
printf("test with PSRAM\r\n");
lcd_panel_test(io_handle, panel_handle, true);
#endif
TEST_ESP_OK(esp_lcd_panel_del(panel_handle));
TEST_ESP_OK(esp_lcd_panel_io_del(io_handle));
TEST_ESP_OK(spi_bus_free(TEST_SPI_HOST_ID));
TEST_ESP_OK(gpio_reset_pin(TEST_LCD_BK_LIGHT_GPIO));
}
TEST_CASE("spi_lcd_send_colors_to_fixed_region", "[lcd]")
@@ -0,0 +1,3 @@
CONFIG_SPIRAM=y
CONFIG_SPIRAM_MODE_HEX=y
CONFIG_SPIRAM_SPEED_200M=y