Преглед изворни кода

Merge branch 'feature/lcd_isr_in_iram' into 'master'

refactor LCD unit tests into test apps

Closes IDF-4666

See merge request espressif/esp-idf!14980
morris пре 3 година
родитељ
комит
b85eeb3224
64 измењених фајлова са 732 додато и 399 уклоњено
  1. 13 0
      .gitlab/ci/target-test.yml
  2. 1 1
      components/esp_lcd/src/esp_lcd_common.c
  3. 7 1
      components/esp_lcd/src/esp_lcd_common.h
  4. 2 4
      components/esp_lcd/src/esp_lcd_panel_io_i80.c
  5. 4 4
      components/esp_lcd/src/esp_lcd_rgb_panel.c
  6. 0 3
      components/esp_lcd/test/CMakeLists.txt
  7. 0 4
      components/esp_lcd/test/test_lvgl_port.h
  8. 0 86
      components/esp_lcd/test/test_lvgl_port_v7.c
  9. 0 18
      components/esp_lcd/test/test_spi_board.h
  10. 5 0
      components/esp_lcd/test_apps/i2c_lcd/CMakeLists.txt
  11. 1 0
      components/esp_lcd/test_apps/i2c_lcd/README.md
  12. 7 0
      components/esp_lcd/test_apps/i2c_lcd/main/CMakeLists.txt
  13. 51 0
      components/esp_lcd/test_apps/i2c_lcd/main/test_app_main.c
  14. 26 0
      components/esp_lcd/test_apps/i2c_lcd/main/test_i2c_board.h
  15. 10 10
      components/esp_lcd/test_apps/i2c_lcd/main/test_i2c_lcd_panel.c
  16. 20 0
      components/esp_lcd/test_apps/i2c_lcd/pytest_i2c_lcd.py
  17. 3 0
      components/esp_lcd/test_apps/i2c_lcd/sdkconfig.ci.release
  18. 2 0
      components/esp_lcd/test_apps/i2c_lcd/sdkconfig.defaults
  19. 5 0
      components/esp_lcd/test_apps/i80_lcd/CMakeLists.txt
  20. 4 0
      components/esp_lcd/test_apps/i80_lcd/README.md
  21. 7 0
      components/esp_lcd/test_apps/i80_lcd/main/CMakeLists.txt
  22. 51 0
      components/esp_lcd/test_apps/i80_lcd/main/test_app_main.c
  23. 13 0
      components/esp_lcd/test_apps/i80_lcd/main/test_i80_board.h
  24. 57 53
      components/esp_lcd/test_apps/i80_lcd/main/test_i80_lcd_panel.c
  25. 22 0
      components/esp_lcd/test_apps/i80_lcd/pytest_i80_lcd.py
  26. 5 0
      components/esp_lcd/test_apps/i80_lcd/sdkconfig.ci.release
  27. 2 0
      components/esp_lcd/test_apps/i80_lcd/sdkconfig.defaults
  28. 5 0
      components/esp_lcd/test_apps/rgb_lcd/CMakeLists.txt
  29. 4 0
      components/esp_lcd/test_apps/rgb_lcd/README.md
  30. 7 0
      components/esp_lcd/test_apps/rgb_lcd/main/CMakeLists.txt
  31. 51 0
      components/esp_lcd/test_apps/rgb_lcd/main/test_app_main.c
  32. 41 0
      components/esp_lcd/test_apps/rgb_lcd/main/test_rgb_board.h
  33. 21 40
      components/esp_lcd/test_apps/rgb_lcd/main/test_rgb_panel.c
  34. 20 0
      components/esp_lcd/test_apps/rgb_lcd/pytest_rgb_lcd.py
  35. 5 0
      components/esp_lcd/test_apps/rgb_lcd/sdkconfig.ci.release
  36. 2 0
      components/esp_lcd/test_apps/rgb_lcd/sdkconfig.defaults
  37. 3 0
      components/esp_lcd/test_apps/rgb_lcd/sdkconfig.defaults.esp32s3
  38. 5 0
      components/esp_lcd/test_apps/spi_lcd/CMakeLists.txt
  39. 1 0
      components/esp_lcd/test_apps/spi_lcd/README.md
  40. 7 0
      components/esp_lcd/test_apps/spi_lcd/main/CMakeLists.txt
  41. 51 0
      components/esp_lcd/test_apps/spi_lcd/main/test_app_main.c
  42. 33 0
      components/esp_lcd/test_apps/spi_lcd/main/test_spi_board.h
  43. 26 96
      components/esp_lcd/test_apps/spi_lcd/main/test_spi_lcd_panel.c
  44. 20 0
      components/esp_lcd/test_apps/spi_lcd/pytest_spi_lcd.py
  45. 3 0
      components/esp_lcd/test_apps/spi_lcd/sdkconfig.ci.release
  46. 2 0
      components/esp_lcd/test_apps/spi_lcd/sdkconfig.defaults
  47. 0 5
      examples/peripherals/lcd/gc9a01/CMakeLists.txt
  48. 1 1
      examples/peripherals/lcd/gc9a01/main/idf_component.yml
  49. 0 5
      examples/peripherals/lcd/i2c_oled/CMakeLists.txt
  50. 1 1
      examples/peripherals/lcd/i2c_oled/main/idf_component.yml
  51. 0 5
      examples/peripherals/lcd/i80_controller/CMakeLists.txt
  52. 3 1
      examples/peripherals/lcd/i80_controller/README.md
  53. 34 0
      examples/peripherals/lcd/i80_controller/main/Kconfig.projbuild
  54. 43 2
      examples/peripherals/lcd/i80_controller/main/i80_controller_example_main.c
  55. 1 1
      examples/peripherals/lcd/i80_controller/main/idf_component.yml
  56. 0 5
      examples/peripherals/lcd/rgb_panel/CMakeLists.txt
  57. 1 1
      examples/peripherals/lcd/rgb_panel/main/idf_component.yml
  58. 5 8
      examples/peripherals/lcd/tjpgd/main/decode_image.c
  59. 4 6
      examples/peripherals/lcd/tjpgd/main/decode_image.h
  60. 5 7
      examples/peripherals/lcd/tjpgd/main/lcd_tjpgd_example_main.c
  61. 4 9
      examples/peripherals/lcd/tjpgd/main/pretty_effect.c
  62. 4 6
      examples/peripherals/lcd/tjpgd/main/pretty_effect.h
  63. 1 0
      pytest.ini
  64. 0 16
      tools/ci/check_copyright_ignore.txt

+ 13 - 0
.gitlab/ci/target-test.yml

@@ -154,6 +154,19 @@ component_ut_pytest_esp32s3_generic:
     - ESP32S3
     - COMPONENT_UT_GENERIC
 
+component_ut_pytest_esp32s3_octal_psram:
+  extends:
+    - .pytest_components_dir_template
+    - .rules:test:component_ut-esp32s3
+  needs:
+    - build_pytest_components_esp32s3
+  variables:
+    TARGET: esp32s3
+    ENV_MARKER: octal_psram
+  tags:
+    - ESP32S3
+    - MSPI_F8R8
+
 component_ut_pytest_esp32c3_generic:
   extends:
     - .pytest_components_dir_template

+ 1 - 1
components/esp_lcd/src/esp_lcd_common.c

@@ -1,5 +1,5 @@
 /*
- * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
  *
  * SPDX-License-Identifier: Apache-2.0
  */

+ 7 - 1
components/esp_lcd/src/esp_lcd_common.h

@@ -1,13 +1,16 @@
 /*
- * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
  *
  * SPDX-License-Identifier: Apache-2.0
  */
 #pragma once
 
 #include <stddef.h>
+#include "sdkconfig.h"
 #include "soc/soc_caps.h"
 #include "hal/dma_types.h"
+#include "esp_intr_alloc.h"
+#include "esp_heap_caps.h"
 #if SOC_LCDCAM_SUPPORTED
 #include "hal/lcd_hal.h"
 #endif
@@ -16,6 +19,9 @@
 extern "C" {
 #endif
 
+#define LCD_INTR_ALLOC_FLAGS     ESP_INTR_FLAG_INTRDISABLED
+#define LCD_MEM_ALLOC_CAPS       MALLOC_CAP_DEFAULT
+
 #define LCD_PERIPH_CLOCK_PRE_SCALE (2) // This is the minimum divider that can be applied to LCD peripheral
 
 #if SOC_LCDCAM_SUPPORTED

+ 2 - 4
components/esp_lcd/src/esp_lcd_panel_io_i80.c

@@ -16,8 +16,6 @@
 #include "freertos/queue.h"
 #include "esp_attr.h"
 #include "esp_check.h"
-#include "esp_intr_alloc.h"
-#include "esp_heap_caps.h"
 #include "esp_pm.h"
 #include "esp_lcd_panel_io_interface.h"
 #include "esp_lcd_panel_io.h"
@@ -149,7 +147,7 @@ esp_err_t esp_lcd_new_i80_bus(const esp_lcd_i80_bus_config_t *bus_config, esp_lc
     ESP_GOTO_ON_ERROR(ret, err, TAG, "select periph clock %d failed", bus_config->clk_src);
     // install interrupt service, (LCD peripheral shares the same interrupt source with Camera peripheral with different mask)
     // interrupt is disabled by default
-    int isr_flags = ESP_INTR_FLAG_INTRDISABLED | ESP_INTR_FLAG_SHARED;
+    int isr_flags = LCD_INTR_ALLOC_FLAGS | ESP_INTR_FLAG_SHARED;
     ret = esp_intr_alloc_intrstatus(lcd_periph_signals.buses[bus_id].irq_id, isr_flags,
                                     (uint32_t)lcd_ll_get_interrupt_status_reg(bus->hal.dev),
                                     LCD_LL_EVENT_TRANS_DONE, lcd_default_isr_handler, bus, &bus->intr);
@@ -246,7 +244,7 @@ esp_err_t esp_lcd_new_panel_io_i80(esp_lcd_i80_bus_handle_t bus, const esp_lcd_p
     uint32_t pclk_prescale = bus->resolution_hz / io_config->pclk_hz;
     ESP_GOTO_ON_FALSE(pclk_prescale > 0 && pclk_prescale <= LCD_LL_CLOCK_PRESCALE_MAX, ESP_ERR_NOT_SUPPORTED, err, TAG,
                       "prescaler can't satisfy PCLK clock %u", io_config->pclk_hz);
-    i80_device = calloc(1, sizeof(lcd_panel_io_i80_t) + io_config->trans_queue_depth * sizeof(lcd_i80_trans_descriptor_t));
+    i80_device = heap_caps_calloc(1, sizeof(lcd_panel_io_i80_t) + io_config->trans_queue_depth * sizeof(lcd_i80_trans_descriptor_t), LCD_MEM_ALLOC_CAPS);
     ESP_GOTO_ON_FALSE(i80_device, ESP_ERR_NO_MEM, err, TAG, "no mem for i80 panel io");
     // create two queues for i80 device
     i80_device->trans_queue = xQueueCreate(io_config->trans_queue_depth, sizeof(lcd_i80_trans_descriptor_t *));

+ 4 - 4
components/esp_lcd/src/esp_lcd_rgb_panel.c

@@ -16,8 +16,6 @@
 #include "freertos/semphr.h"
 #include "esp_attr.h"
 #include "esp_check.h"
-#include "esp_intr_alloc.h"
-#include "esp_heap_caps.h"
 #include "esp_pm.h"
 #include "esp_lcd_panel_interface.h"
 #include "esp_lcd_panel_rgb.h"
@@ -107,7 +105,7 @@ esp_err_t esp_lcd_new_rgb_panel(const esp_lcd_rgb_panel_config_t *rgb_panel_conf
         num_dma_nodes++;
     }
     // DMA descriptors must be placed in internal SRAM (requested by DMA)
-    rgb_panel = heap_caps_calloc(1, sizeof(esp_rgb_panel_t) + num_dma_nodes * sizeof(dma_descriptor_t), MALLOC_CAP_DMA);
+    rgb_panel = heap_caps_calloc(1, sizeof(esp_rgb_panel_t) + num_dma_nodes * sizeof(dma_descriptor_t), MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
     ESP_GOTO_ON_FALSE(rgb_panel, ESP_ERR_NO_MEM, err, TAG, "no mem for rgb panel");
     rgb_panel->num_dma_nodes = num_dma_nodes;
     rgb_panel->panel_id = -1;
@@ -150,7 +148,7 @@ esp_err_t esp_lcd_new_rgb_panel(const esp_lcd_rgb_panel_config_t *rgb_panel_conf
     ret = lcd_rgb_panel_select_periph_clock(rgb_panel, rgb_panel_config->clk_src);
     ESP_GOTO_ON_ERROR(ret, err, TAG, "select periph clock failed");
     // install interrupt service, (LCD peripheral shares the interrupt source with Camera by different mask)
-    int isr_flags = ESP_INTR_FLAG_SHARED;
+    int isr_flags = LCD_INTR_ALLOC_FLAGS | ESP_INTR_FLAG_SHARED;
     ret = esp_intr_alloc_intrstatus(lcd_periph_signals.panels[panel_id].irq_id, isr_flags,
                                     (uint32_t)lcd_ll_get_interrupt_status_reg(rgb_panel->hal.dev),
                                     LCD_LL_EVENT_VSYNC_END, lcd_default_isr_handler, rgb_panel, &rgb_panel->intr);
@@ -284,6 +282,8 @@ static esp_err_t rgb_panel_init(esp_lcd_panel_t *panel)
     lcd_ll_enable_auto_next_frame(rgb_panel->hal.dev, rgb_panel->flags.stream_mode);
     // trigger interrupt on the end of frame
     lcd_ll_enable_interrupt(rgb_panel->hal.dev, LCD_LL_EVENT_VSYNC_END, true);
+    // enable intr
+    esp_intr_enable(rgb_panel->intr);
     ESP_LOGD(TAG, "rgb panel(%d) start, pclk=%uHz", rgb_panel->panel_id, rgb_panel->timings.pclk_hz);
 err:
     return ret;

+ 0 - 3
components/esp_lcd/test/CMakeLists.txt

@@ -1,3 +0,0 @@
-idf_component_register(SRC_DIRS .
-                       PRIV_INCLUDE_DIRS .
-                       PRIV_REQUIRES cmock test_utils esp_lcd)

+ 0 - 4
components/esp_lcd/test/test_lvgl_port.h

@@ -1,4 +0,0 @@
-#include "esp_lcd_panel_ops.h"
-#include "lvgl.h"
-
-void test_lvgl_task_loop(esp_lcd_panel_handle_t panel_handle, int h_res, int v_res, lv_disp_t **disp);

+ 0 - 86
components/esp_lcd/test/test_lvgl_port_v7.c

@@ -1,86 +0,0 @@
-#include "freertos/FreeRTOS.h"
-#include "freertos/task.h"
-#include "unity.h"
-#include "test_utils.h"
-#include "esp_freertos_hooks.h"
-#include "soc/soc_caps.h"
-#if CONFIG_LV_USE_USER_DATA
-#include "test_lvgl_port.h"
-
-static void my_lvgl_flush(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_map)
-{
-    esp_lcd_panel_handle_t panel_handle = (esp_lcd_panel_handle_t) drv->user_data;
-
-    int offsetx1 = area->x1;
-    int offsetx2 = area->x2;
-    int offsety1 = area->y1;
-    int offsety2 = area->y2;
-
-    esp_lcd_panel_draw_bitmap(panel_handle, offsetx1, offsety1, offsetx2 + 1, offsety2 + 1, color_map);
-}
-
-static void increase_lvgl_tick(void)
-{
-    lv_tick_inc(portTICK_PERIOD_MS);
-}
-
-static void create_demo_application(lv_disp_t *disp)
-{
-    // Get the current screen
-    lv_obj_t *scr = lv_disp_get_scr_act(disp);
-    // Create a Label on the currently active screen
-    lv_obj_t *label =  lv_label_create(scr, NULL);
-    // Modify the Label's text
-    lv_label_set_text(label, "Hello World");
-    // Align the Label to the center
-    lv_obj_align(label, NULL, LV_ALIGN_IN_TOP_MID, 0, 0);
-
-    // new screen_spinner
-    lv_obj_t *screen_spinner = lv_spinner_create(scr, NULL);
-    lv_obj_align(screen_spinner, label, LV_ALIGN_OUT_BOTTOM_MID, 15, 20);
-    lv_obj_set_size(screen_spinner, 100, 100);
-    lv_spinner_set_arc_length(screen_spinner, 60);
-    lv_spinner_set_spin_time(screen_spinner, 1000);
-    lv_spinner_set_type(screen_spinner, LV_SPINNER_TYPE_SPINNING_ARC);
-    lv_spinner_set_dir(screen_spinner, LV_SPINNER_DIR_FORWARD);
-
-    lv_obj_t *bar = lv_bar_create(scr, NULL);
-    lv_obj_set_size(bar, 100, 20);
-    lv_obj_align(bar, screen_spinner, LV_ALIGN_OUT_BOTTOM_MID, 0, 0);
-    lv_bar_set_anim_time(bar, 2000);
-    lv_bar_set_value(bar, 100, LV_ANIM_ON);
-}
-
-void test_lvgl_task_loop(esp_lcd_panel_handle_t panel_handle, int h_res, int v_res, lv_disp_t **disp)
-{
-    static lv_disp_buf_t disp_buf;
-    // alloc frame buffer used by LVGL
-    lv_color_t *buf1 = heap_caps_malloc(h_res * 20 * sizeof(lv_color_t), MALLOC_CAP_DMA);
-    TEST_ASSERT_NOT_NULL(buf1);
-    lv_color_t *buf2 = heap_caps_malloc(h_res * 20 * sizeof(lv_color_t), MALLOC_CAP_DMA);
-    TEST_ASSERT_NOT_NULL(buf2);
-    lv_disp_buf_init(&disp_buf, buf1, buf2, h_res * 20);
-    // register display driver
-    lv_disp_drv_t disp_drv;
-    lv_disp_drv_init(&disp_drv);
-    disp_drv.hor_res = h_res;
-    disp_drv.ver_res = v_res;
-    disp_drv.flush_cb = my_lvgl_flush;
-
-    disp_drv.buffer = &disp_buf;
-    disp_drv.user_data = panel_handle; // LV_USE_USER_DATA is disabled by default, need to enable it in menuconfig
-    *disp = lv_disp_drv_register(&disp_drv);
-
-    // Tick interface for LVGL
-    esp_register_freertos_tick_hook(increase_lvgl_tick);
-
-    // create a demo UI on that screen
-    create_demo_application(*disp);
-
-    while (1) {
-        vTaskDelay(pdMS_TO_TICKS(10));
-        lv_task_handler(); // The task running lv_task_handler should have lower priority than that running `lv_tick_inc`
-    }
-}
-
-#endif // CONFIG_LV_USE_USER_DATA

+ 0 - 18
components/esp_lcd/test/test_spi_board.h

@@ -1,18 +0,0 @@
-#include "sdkconfig.h"
-
-#define TEST_LCD_H_RES          (240)
-#define TEST_LCD_V_RES          (280)
-
-#define TEST_LCD_BK_LIGHT_GPIO  (18)
-#define TEST_LCD_RST_GPIO       (5)
-#define TEST_LCD_CS_GPIO        (0)
-#define TEST_LCD_DC_GPIO        (19)
-#define TEST_LCD_PCLK_GPIO      (2)
-#define TEST_LCD_DATA0_GPIO     (4)
-#define TEST_LCD_DATA1_GPIO     (7)
-#define TEST_LCD_DATA2_GPIO     (8)
-#define TEST_LCD_DATA3_GPIO     (9)
-#define TEST_LCD_DATA4_GPIO     (10)
-#define TEST_LCD_DATA5_GPIO     (11)
-#define TEST_LCD_DATA6_GPIO     (12)
-#define TEST_LCD_DATA7_GPIO     (13)

+ 5 - 0
components/esp_lcd/test_apps/i2c_lcd/CMakeLists.txt

@@ -0,0 +1,5 @@
+# This is the project CMakeLists.txt file for the test subproject
+cmake_minimum_required(VERSION 3.5)
+
+include($ENV{IDF_PATH}/tools/cmake/project.cmake)
+project(i2c_lcd_panel_test)

+ 1 - 0
components/esp_lcd/test_apps/i2c_lcd/README.md

@@ -0,0 +1 @@
+This test app is used to test LCDs with I2C interface.

+ 7 - 0
components/esp_lcd/test_apps/i2c_lcd/main/CMakeLists.txt

@@ -0,0 +1,7 @@
+set(srcs "test_app_main.c"
+         "test_i2c_lcd_panel.c")
+
+idf_component_register(SRCS ${srcs}
+                       PRIV_REQUIRES esp_lcd unity)
+
+target_link_libraries(${COMPONENT_LIB} INTERFACE "-u test_app_include_i2c_lcd")

+ 51 - 0
components/esp_lcd/test_apps/i2c_lcd/main/test_app_main.c

@@ -0,0 +1,51 @@
+/*
+ * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: CC0-1.0
+ */
+
+#include "unity.h"
+#include "unity_test_runner.h"
+#include "esp_heap_caps.h"
+
+// Some resources are lazy allocated in the LCD driver, the threadhold is left for that case
+#define TEST_MEMORY_LEAK_THRESHOLD (-300)
+
+static size_t before_free_8bit;
+static size_t before_free_32bit;
+
+static void check_leak(size_t before_free, size_t after_free, const char *type)
+{
+    ssize_t delta = after_free - before_free;
+    printf("MALLOC_CAP_%s: Before %u bytes free, After %u bytes free (delta %d)\n", type, before_free, after_free, delta);
+    TEST_ASSERT_MESSAGE(delta >= TEST_MEMORY_LEAK_THRESHOLD, "memory leak");
+}
+
+void setUp(void)
+{
+    before_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT);
+    before_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT);
+}
+
+void tearDown(void)
+{
+    size_t after_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT);
+    size_t after_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT);
+    check_leak(before_free_8bit, after_free_8bit, "8BIT");
+    check_leak(before_free_32bit, after_free_32bit, "32BIT");
+}
+
+void app_main(void)
+{
+    //  ___ ____   ____   _     ____ ____    _____         _
+    // |_ _|___ \ / ___| | |   / ___|  _ \  |_   _|__  ___| |_
+    //  | |  __) | |     | |  | |   | | | |   | |/ _ \/ __| __|
+    //  | | / __/| |___  | |__| |___| |_| |   | |  __/\__ \ |_
+    // |___|_____|\____| |_____\____|____/    |_|\___||___/\__|
+    printf(" ___ ____   ____   _     ____ ____    _____         _\r\n");
+    printf("|_ _|___ \\ / ___| | |   / ___|  _ \\  |_   _|__  ___| |_\r\n");
+    printf(" | |  __) | |     | |  | |   | | | |   | |/ _ \\/ __| __|\r\n");
+    printf(" | | / __/| |___  | |__| |___| |_| |   | |  __/\\__ \\ |_\r\n");
+    printf("|___|_____|\\____| |_____\\____|____/    |_|\\___||___/\\__|\r\n");
+    unity_run_menu();
+}

+ 26 - 0
components/esp_lcd/test_apps/i2c_lcd/main/test_i2c_board.h

@@ -0,0 +1,26 @@
+/*
+ * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define TEST_LCD_H_RES          128
+#define TEST_LCD_V_RES          64
+
+#define TEST_I2C_SDA_GPIO       0
+#define TEST_I2C_SCL_GPIO       2
+
+#define TEST_I2C_HOST_ID        0
+
+#define TEST_I2C_DEV_ADDR       0x3C
+
+#define TEST_LCD_PIXEL_CLOCK_HZ (400 * 1000)
+
+#ifdef __cplusplus
+}
+#endif

+ 10 - 10
components/esp_lcd/test/test_i2c_lcd_panel.c → components/esp_lcd/test_apps/i2c_lcd/main/test_i2c_lcd_panel.c

@@ -1,24 +1,24 @@
+/*
+ * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
 #include <stdio.h>
 #include <string.h>
-#include "sdkconfig.h"
 #include "unity.h"
-#include "test_utils.h"
 #include "driver/i2c.h"
 #include "driver/gpio.h"
 #include "esp_lcd_panel_io.h"
 #include "esp_lcd_panel_vendor.h"
 #include "esp_lcd_panel_ops.h"
 #include "esp_system.h"
+#include "test_i2c_board.h"
 
-#define TEST_LCD_H_RES          (128)
-#define TEST_LCD_V_RES          (64)
-#define TEST_I2C_SDA_GPIO       (3)
-#define TEST_I2C_SCL_GPIO       (4)
-#define TEST_I2C_HOST_ID        (0)
-#define TEST_I2C_DEV_ADDR       (0x3C)
-#define TEST_LCD_PIXEL_CLOCK_HZ (400 * 1000)
+void test_app_include_i2c_lcd(void)
+{
+}
 
-TEST_CASE("lcd panel with i2c interface (ssd1306)", "[lcd]")
+TEST_CASE("lcd_panel_with_i2c_interface_(ssd1306)", "[lcd]")
 {
     const uint8_t pattern[][16] = {{
             0x00, 0x7E, 0x42, 0x42, 0x42, 0x42, 0x7E, 0x00,

+ 20 - 0
components/esp_lcd/test_apps/i2c_lcd/pytest_i2c_lcd.py

@@ -0,0 +1,20 @@
+# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
+# SPDX-License-Identifier: CC0-1.0
+
+import pytest
+from pytest_embedded import Dut
+
+
+@pytest.mark.supported_targets
+@pytest.mark.generic
+@pytest.mark.parametrize(
+    'config',
+    [
+        'release',
+    ],
+    indirect=True,
+)
+def test_i2c_lcd(dut: Dut) -> None:
+    dut.expect_exact('Press ENTER to see the list of tests')
+    dut.write('*')
+    dut.expect_unity_test_output()

+ 3 - 0
components/esp_lcd/test_apps/i2c_lcd/sdkconfig.ci.release

@@ -0,0 +1,3 @@
+CONFIG_COMPILER_OPTIMIZATION_SIZE=y
+CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y
+CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y

+ 2 - 0
components/esp_lcd/test_apps/i2c_lcd/sdkconfig.defaults

@@ -0,0 +1,2 @@
+CONFIG_FREERTOS_HZ=1000
+CONFIG_ESP_TASK_WDT=n

+ 5 - 0
components/esp_lcd/test_apps/i80_lcd/CMakeLists.txt

@@ -0,0 +1,5 @@
+# This is the project CMakeLists.txt file for the test subproject
+cmake_minimum_required(VERSION 3.5)
+
+include($ENV{IDF_PATH}/tools/cmake/project.cmake)
+project(i80_lcd_panel_test)

+ 4 - 0
components/esp_lcd/test_apps/i80_lcd/README.md

@@ -0,0 +1,4 @@
+| Supported Targets | ESP32 | ESP32-S2 | ESP32-S3 |
+| ----------------- | ----- | -------- | -------- |
+
+This test app is used to test LCDs with intel 8080 interface.

+ 7 - 0
components/esp_lcd/test_apps/i80_lcd/main/CMakeLists.txt

@@ -0,0 +1,7 @@
+set(srcs "test_app_main.c"
+         "test_i80_lcd_panel.c")
+
+idf_component_register(SRCS ${srcs}
+                       PRIV_REQUIRES esp_lcd unity)
+
+target_link_libraries(${COMPONENT_LIB} INTERFACE "-u test_app_include_i80_lcd")

+ 51 - 0
components/esp_lcd/test_apps/i80_lcd/main/test_app_main.c

@@ -0,0 +1,51 @@
+/*
+ * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: CC0-1.0
+ */
+
+#include "unity.h"
+#include "unity_test_runner.h"
+#include "esp_heap_caps.h"
+
+// Some resources are lazy allocated in LCD driver, the threadhold is left for that case
+#define TEST_MEMORY_LEAK_THRESHOLD (-300)
+
+static size_t before_free_8bit;
+static size_t before_free_32bit;
+
+static void check_leak(size_t before_free, size_t after_free, const char *type)
+{
+    ssize_t delta = after_free - before_free;
+    printf("MALLOC_CAP_%s: Before %u bytes free, After %u bytes free (delta %d)\n", type, before_free, after_free, delta);
+    TEST_ASSERT_MESSAGE(delta >= TEST_MEMORY_LEAK_THRESHOLD, "memory leak");
+}
+
+void setUp(void)
+{
+    before_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT);
+    before_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT);
+}
+
+void tearDown(void)
+{
+    size_t after_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT);
+    size_t after_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT);
+    check_leak(before_free_8bit, after_free_8bit, "8BIT");
+    check_leak(before_free_32bit, after_free_32bit, "32BIT");
+}
+
+void app_main(void)
+{
+    //  _  ___   ___    _     ____ ____    _____         _
+    // (_)( _ ) / _ \  | |   / ___|  _ \  |_   _|__  ___| |_
+    // | |/ _ \| | | | | |  | |   | | | |   | |/ _ \/ __| __|
+    // | | (_) | |_| | | |__| |___| |_| |   | |  __/\__ \ |_
+    // |_|\___/ \___/  |_____\____|____/    |_|\___||___/\__|
+    printf(" _  ___   ___    _     ____ ____    _____         _\r\n");
+    printf("(_)( _ ) / _ \\  | |   / ___|  _ \\  |_   _|__  ___| |_r\n");
+    printf("| |/ _ \\| | | | | |  | |   | | | |   | |/ _ \\/ __| __|\r\n");
+    printf("| | (_) | |_| | | |__| |___| |_| |   | |  __/\\__ \\ |_\r\n");
+    printf("|_|\\___/ \\___/  |_____\\____|____/    |_|\\___||___/\\__|\r\n");
+    unity_run_menu();
+}

+ 13 - 0
components/esp_lcd/test/test_i80_board.h → components/esp_lcd/test_apps/i80_lcd/main/test_i80_board.h

@@ -1,5 +1,14 @@
+/*
+ * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
 #include "sdkconfig.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 #define TEST_LCD_H_RES         (240)
 #define TEST_LCD_V_RES         (280)
 
@@ -70,3 +79,7 @@
 #define TEST_LCD_DATA14_GPIO   (16)
 #define TEST_LCD_DATA15_GPIO   (17)
 #endif
+
+#ifdef __cplusplus
+}
+#endif

+ 57 - 53
components/esp_lcd/test/test_i80_lcd_panel.c → components/esp_lcd/test_apps/i80_lcd/main/test_i80_lcd_panel.c

@@ -1,7 +1,14 @@
+/*
+ * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: CC0-1.0
+ */
+
 #include <stdio.h>
 #include <string.h>
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
 #include "unity.h"
-#include "test_utils.h"
 #include "esp_lcd_panel_io.h"
 #include "esp_lcd_panel_vendor.h"
 #include "esp_lcd_panel_ops.h"
@@ -9,8 +16,51 @@
 #include "driver/gpio.h"
 #include "test_i80_board.h"
 
+void test_app_include_i80_lcd(void)
+{
+}
+
+#if SOC_I2S_LCD_I80_VARIANT
+#include "driver/i2s.h"
+
+TEST_CASE("i80_and_i2s_driver_co-existence", "[lcd][i2s]")
+{
+    esp_lcd_i80_bus_handle_t i80_bus = NULL;
+    esp_lcd_i80_bus_config_t bus_config = {
+        .dc_gpio_num = TEST_LCD_DC_GPIO,
+        .wr_gpio_num = TEST_LCD_PCLK_GPIO,
+        .data_gpio_nums = {
+            TEST_LCD_DATA0_GPIO,
+            TEST_LCD_DATA1_GPIO,
+            TEST_LCD_DATA2_GPIO,
+            TEST_LCD_DATA3_GPIO,
+            TEST_LCD_DATA4_GPIO,
+            TEST_LCD_DATA5_GPIO,
+            TEST_LCD_DATA6_GPIO,
+            TEST_LCD_DATA7_GPIO,
+        },
+        .bus_width = 8,
+        .max_transfer_bytes = 20,
+    };
+    TEST_ESP_OK(esp_lcd_new_i80_bus(&bus_config, &i80_bus));
+
+    i2s_config_t i2s_config = {
+        .mode = I2S_MODE_MASTER | I2S_MODE_TX,
+        .sample_rate = 36000,
+        .bits_per_sample = 16,
+        .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
+        .communication_format = I2S_COMM_FORMAT_STAND_I2S,
+        .dma_desc_num = 6,
+        .dma_frame_num = 60,
+    };
+    // I2S driver won't be installed as the same I2S port has been used by LCD
+    TEST_ASSERT_EQUAL(ESP_ERR_INVALID_STATE, i2s_driver_install(0, &i2s_config, 0, NULL));
+    TEST_ESP_OK(esp_lcd_del_i80_bus(i80_bus));
+}
+#endif // SOC_I2S_LCD_I80_VARIANT
+
 #if SOC_LCDCAM_SUPPORTED
-TEST_CASE("lcd i80 device swap color bytes", "[lcd]")
+TEST_CASE("lcd_i80_device_swap_color_bytes", "[lcd]")
 {
     esp_lcd_i80_bus_handle_t i80_bus = NULL;
     esp_lcd_i80_bus_config_t bus_config = {
@@ -72,7 +122,7 @@ TEST_CASE("lcd i80 device swap color bytes", "[lcd]")
     TEST_ESP_OK(esp_lcd_del_i80_bus(i80_bus));
 }
 
-TEST_CASE("lcd i80 device clock mode", "[lcd]")
+TEST_CASE("lcd_i80_device_clock_mode", "[lcd]")
 {
     esp_lcd_i80_bus_handle_t i80_bus = NULL;
     esp_lcd_i80_bus_config_t bus_config = {
@@ -131,8 +181,7 @@ TEST_CASE("lcd i80 device clock mode", "[lcd]")
 }
 #endif // SOC_LCDCAM_SUPPORTED
 
-#if SOC_LCD_I80_SUPPORTED
-TEST_CASE("lcd i80 bus and device allocation", "[lcd]")
+TEST_CASE("lcd_i80_bus_and_device_allocation", "[lcd]")
 {
     esp_lcd_i80_bus_handle_t i80_buses[SOC_LCD_I80_BUSES] = {};
     esp_lcd_i80_bus_config_t bus_config = {
@@ -176,7 +225,7 @@ TEST_CASE("lcd i80 bus and device allocation", "[lcd]")
     }
 }
 
-TEST_CASE("lcd i80 bus exclusively owned by one device", "[lcd]")
+TEST_CASE("lcd_i80_bus_exclusively_owned_by_one_device", "[lcd]")
 {
     esp_lcd_i80_bus_handle_t i80_bus_handle = NULL;
     esp_lcd_i80_bus_config_t bus_config = {
@@ -211,7 +260,7 @@ TEST_CASE("lcd i80 bus exclusively owned by one device", "[lcd]")
     TEST_ESP_OK(esp_lcd_del_i80_bus(i80_bus_handle));
 }
 
-TEST_CASE("lcd panel i80 io test", "[lcd]")
+TEST_CASE("lcd_panel_i80_io_test", "[lcd]")
 {
     esp_lcd_i80_bus_handle_t i80_bus = NULL;
     esp_lcd_i80_bus_config_t bus_config = {
@@ -257,9 +306,6 @@ TEST_CASE("lcd panel i80 io test", "[lcd]")
         .bits_per_pixel = 16,
     };
 
-// On esp32, GPIO16 and GPIO17 are connected to PSRAM, and we don't have other spare GPIOs can be used in the test
-// so we skip the 16bit test on esp32 when PSRAM is enabled
-#if !CONFIG_ESP32_SPIRAM_SUPPORT
     printf("testing bus-width=16bit, cmd/param bit-width=8bit\r\n");
     bus_config.bus_width = 16;
     TEST_ESP_OK(esp_lcd_new_i80_bus(&bus_config, &i80_bus));
@@ -292,7 +338,6 @@ TEST_CASE("lcd panel i80 io test", "[lcd]")
     TEST_ESP_OK(esp_lcd_panel_del(panel_handle));
     TEST_ESP_OK(esp_lcd_panel_io_del(io_handle));
     TEST_ESP_OK(esp_lcd_del_i80_bus(i80_bus));
-#endif
 
     printf("testing bus-width=8bit, cmd/param bit-width=8bit\r\n");
     bus_config.bus_width = 8;
@@ -327,7 +372,7 @@ TEST_CASE("lcd panel i80 io test", "[lcd]")
     TEST_ESP_OK(esp_lcd_del_i80_bus(i80_bus));
 }
 
-TEST_CASE("lcd panel with i80 interface (st7789, 8bits)", "[lcd]")
+TEST_CASE("lcd_panel_with_i80_interface_(st7789, 8bits)", "[lcd]")
 {
 #define TEST_IMG_SIZE (100 * 100 * sizeof(uint16_t))
     uint8_t *img = heap_caps_malloc(TEST_IMG_SIZE, MALLOC_CAP_DMA);
@@ -407,44 +452,3 @@ TEST_CASE("lcd panel with i80 interface (st7789, 8bits)", "[lcd]")
     free(img);
 #undef TEST_IMG_SIZE
 }
-
-#endif // SOC_LCD_I80_SUPPORTED
-
-#if SOC_I2S_LCD_I80_VARIANT
-#include "driver/i2s.h"
-
-TEST_CASE("i80 and i2s driver coexistance", "[lcd][i2s]")
-{
-    esp_lcd_i80_bus_handle_t i80_bus = NULL;
-    esp_lcd_i80_bus_config_t bus_config = {
-        .dc_gpio_num = TEST_LCD_DC_GPIO,
-        .wr_gpio_num = TEST_LCD_PCLK_GPIO,
-        .data_gpio_nums = {
-            TEST_LCD_DATA0_GPIO,
-            TEST_LCD_DATA1_GPIO,
-            TEST_LCD_DATA2_GPIO,
-            TEST_LCD_DATA3_GPIO,
-            TEST_LCD_DATA4_GPIO,
-            TEST_LCD_DATA5_GPIO,
-            TEST_LCD_DATA6_GPIO,
-            TEST_LCD_DATA7_GPIO,
-        },
-        .bus_width = 8,
-        .max_transfer_bytes = 20,
-    };
-    TEST_ESP_OK(esp_lcd_new_i80_bus(&bus_config, &i80_bus));
-
-    i2s_config_t i2s_config = {
-        .mode = I2S_MODE_MASTER | I2S_MODE_TX,
-        .sample_rate = 36000,
-        .bits_per_sample = 16,
-        .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
-        .communication_format = I2S_COMM_FORMAT_STAND_I2S,
-        .dma_desc_num = 6,
-        .dma_frame_num = 60,
-    };
-    // I2S driver won't be installed as the same I2S port has been used by LCD
-    TEST_ASSERT_EQUAL(ESP_ERR_INVALID_STATE, i2s_driver_install(0, &i2s_config, 0, NULL));
-    TEST_ESP_OK(esp_lcd_del_i80_bus(i80_bus));
-}
-#endif // SOC_I2S_LCD_I80_VARIANT

+ 22 - 0
components/esp_lcd/test_apps/i80_lcd/pytest_i80_lcd.py

@@ -0,0 +1,22 @@
+# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
+# SPDX-License-Identifier: CC0-1.0
+
+import pytest
+from pytest_embedded import Dut
+
+
+@pytest.mark.esp32
+@pytest.mark.esp32s2
+@pytest.mark.esp32s3
+@pytest.mark.generic
+@pytest.mark.parametrize(
+    'config',
+    [
+        'release',
+    ],
+    indirect=True,
+)
+def test_i80_lcd(dut: Dut) -> None:
+    dut.expect_exact('Press ENTER to see the list of tests')
+    dut.write('*')
+    dut.expect_unity_test_output()

+ 5 - 0
components/esp_lcd/test_apps/i80_lcd/sdkconfig.ci.release

@@ -0,0 +1,5 @@
+CONFIG_PM_ENABLE=y
+CONFIG_FREERTOS_USE_TICKLESS_IDLE=y
+CONFIG_COMPILER_OPTIMIZATION_SIZE=y
+CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y
+CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y

+ 2 - 0
components/esp_lcd/test_apps/i80_lcd/sdkconfig.defaults

@@ -0,0 +1,2 @@
+CONFIG_FREERTOS_HZ=1000
+CONFIG_ESP_TASK_WDT=n

+ 5 - 0
components/esp_lcd/test_apps/rgb_lcd/CMakeLists.txt

@@ -0,0 +1,5 @@
+# This is the project CMakeLists.txt file for the test subproject
+cmake_minimum_required(VERSION 3.5)
+
+include($ENV{IDF_PATH}/tools/cmake/project.cmake)
+project(rgb_lcd_panel_test)

+ 4 - 0
components/esp_lcd/test_apps/rgb_lcd/README.md

@@ -0,0 +1,4 @@
+| Supported Targets | ESP32-S3 |
+| ----------------- | -------- |
+
+This test app is used to test RGB565 interfaced LCDs.

+ 7 - 0
components/esp_lcd/test_apps/rgb_lcd/main/CMakeLists.txt

@@ -0,0 +1,7 @@
+set(srcs "test_app_main.c"
+         "test_rgb_panel.c")
+
+idf_component_register(SRCS ${srcs}
+                       PRIV_REQUIRES esp_lcd unity)
+
+target_link_libraries(${COMPONENT_LIB} INTERFACE "-u test_app_include_rgb_lcd")

+ 51 - 0
components/esp_lcd/test_apps/rgb_lcd/main/test_app_main.c

@@ -0,0 +1,51 @@
+/*
+ * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: CC0-1.0
+ */
+
+#include "unity.h"
+#include "unity_test_runner.h"
+#include "esp_heap_caps.h"
+
+// Some resources are lazy allocated in LCD driver, the threadhold is left for that case
+#define TEST_MEMORY_LEAK_THRESHOLD (-300)
+
+static size_t before_free_8bit;
+static size_t before_free_32bit;
+
+static void check_leak(size_t before_free, size_t after_free, const char *type)
+{
+    ssize_t delta = after_free - before_free;
+    printf("MALLOC_CAP_%s: Before %u bytes free, After %u bytes free (delta %d)\n", type, before_free, after_free, delta);
+    TEST_ASSERT_MESSAGE(delta >= TEST_MEMORY_LEAK_THRESHOLD, "memory leak");
+}
+
+void setUp(void)
+{
+    before_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT);
+    before_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT);
+}
+
+void tearDown(void)
+{
+    size_t after_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT);
+    size_t after_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT);
+    check_leak(before_free_8bit, after_free_8bit, "8BIT");
+    check_leak(before_free_32bit, after_free_32bit, "32BIT");
+}
+
+void app_main(void)
+{
+    //  ____   ____ ____    _     ____ ____    _____         _
+    // |  _ \ / ___| __ )  | |   / ___|  _ \  |_   _|__  ___| |_
+    // | |_) | |  _|  _ \  | |  | |   | | | |   | |/ _ \/ __| __|
+    // |  _ <| |_| | |_) | | |__| |___| |_| |   | |  __/\__ \ |_
+    // |_| \_\\____|____/  |_____\____|____/    |_|\___||___/\__|
+    printf(" ____   ____ ____    _     ____ ____    _____         _\r\n");
+    printf("|  _ \\ / ___| __ )  | |   / ___|  _ \\  |_   _|__  ___| |_\r\n");
+    printf("| |_) | |  _|  _ \\  | |  | |   | | | |   | |/ _ \\/ __| __|\r\n");
+    printf("|  _ <| |_| | |_) | | |__| |___| |_| |   | |  __/\\__ \\ |_\r\n");
+    printf("|_| \\_\\\\____|____/  |_____\\____|____/    |_|\\___||___/\\__|\r\n");
+    unity_run_menu();
+}

+ 41 - 0
components/esp_lcd/test_apps/rgb_lcd/main/test_rgb_board.h

@@ -0,0 +1,41 @@
+/*
+ * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define TEST_LCD_H_RES         480
+#define TEST_LCD_V_RES         272
+
+#define TEST_LCD_VSYNC_GPIO    48
+#define TEST_LCD_HSYNC_GPIO    47
+#define TEST_LCD_DE_GPIO       45
+#define TEST_LCD_PCLK_GPIO     21
+#define TEST_LCD_DATA0_GPIO    3  // B0
+#define TEST_LCD_DATA1_GPIO    4  // B1
+#define TEST_LCD_DATA2_GPIO    5  // B2
+#define TEST_LCD_DATA3_GPIO    6  // B3
+#define TEST_LCD_DATA4_GPIO    7  // B4
+#define TEST_LCD_DATA5_GPIO    8  // G0
+#define TEST_LCD_DATA6_GPIO    9  // G1
+#define TEST_LCD_DATA7_GPIO    10 // G2
+#define TEST_LCD_DATA8_GPIO    11 // G3
+#define TEST_LCD_DATA9_GPIO    12 // G4
+#define TEST_LCD_DATA10_GPIO   13 // G5
+#define TEST_LCD_DATA11_GPIO   14 // R0
+#define TEST_LCD_DATA12_GPIO   15 // R1
+#define TEST_LCD_DATA13_GPIO   16 // R2
+#define TEST_LCD_DATA14_GPIO   17 // R3
+#define TEST_LCD_DATA15_GPIO   18 // R4
+#define TEST_LCD_DISP_EN_GPIO  -1
+
+#define TEST_LCD_PIXEL_CLOCK_HZ (10 * 1000 * 1000)
+
+#ifdef __cplusplus
+}
+#endif

+ 21 - 40
components/esp_lcd/test/test_rgb_panel.c → components/esp_lcd/test_apps/rgb_lcd/main/test_rgb_panel.c

@@ -1,40 +1,21 @@
+/*
+ * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
 #include <stdio.h>
 #include <string.h>
 #include "unity.h"
-#include "test_utils.h"
 #include "esp_lcd_panel_rgb.h"
 #include "esp_lcd_panel_ops.h"
-#include "soc/soc_caps.h"
+#include "esp_system.h"
+#include "test_rgb_board.h"
 
-#define TEST_LCD_H_RES         (480)
-#define TEST_LCD_V_RES         (272)
-
-#define TEST_LCD_VSYNC_GPIO    (48)
-#define TEST_LCD_HSYNC_GPIO    (47)
-#define TEST_LCD_DE_GPIO       (45)
-#define TEST_LCD_PCLK_GPIO     (21)
-#define TEST_LCD_DATA0_GPIO    (3)  // B0
-#define TEST_LCD_DATA1_GPIO    (4)  // B1
-#define TEST_LCD_DATA2_GPIO    (5)  // B2
-#define TEST_LCD_DATA3_GPIO    (6)  // B3
-#define TEST_LCD_DATA4_GPIO    (7)  // B4
-#define TEST_LCD_DATA5_GPIO    (8)  // G0
-#define TEST_LCD_DATA6_GPIO    (9)  // G1
-#define TEST_LCD_DATA7_GPIO    (10) // G2
-#define TEST_LCD_DATA8_GPIO    (11) // G3
-#define TEST_LCD_DATA9_GPIO    (12) // G4
-#define TEST_LCD_DATA10_GPIO   (13) // G5
-#define TEST_LCD_DATA11_GPIO   (14) // R0
-#define TEST_LCD_DATA12_GPIO   (15) // R1
-#define TEST_LCD_DATA13_GPIO   (16) // R2
-#define TEST_LCD_DATA14_GPIO   (17) // R3
-#define TEST_LCD_DATA15_GPIO   (18) // R4
-#define TEST_LCD_DISP_EN_GPIO  (39)
+void test_app_include_rgb_lcd(void)
+{
+}
 
-#if SOC_LCD_RGB_SUPPORTED
-// RGB driver consumes a huge memory to save frame buffer, only test it with PSRAM enabled
-#if CONFIG_SPIRAM_USE_MALLOC
-TEST_CASE("lcd rgb lcd panel", "[lcd]")
+TEST_CASE("lcd_rgb_lcd_panel", "[lcd]")
 {
 #define TEST_IMG_SIZE (100 * 100 * sizeof(uint16_t))
     uint8_t *img = malloc(TEST_IMG_SIZE);
@@ -43,6 +24,8 @@ TEST_CASE("lcd rgb lcd panel", "[lcd]")
     esp_lcd_panel_handle_t panel_handle = NULL;
     esp_lcd_rgb_panel_config_t panel_config = {
         .data_width = 16,
+        .psram_trans_align = 64,
+        .clk_src = LCD_CLK_SRC_PLL160M,
         .disp_gpio_num = TEST_LCD_DISP_EN_GPIO,
         .pclk_gpio_num = TEST_LCD_PCLK_GPIO,
         .vsync_gpio_num = TEST_LCD_VSYNC_GPIO,
@@ -67,17 +50,18 @@ TEST_CASE("lcd rgb lcd panel", "[lcd]")
             TEST_LCD_DATA15_GPIO,
         },
         .timings = {
-            .pclk_hz = 12000000,
+            .pclk_hz = TEST_LCD_PIXEL_CLOCK_HZ,
             .h_res = TEST_LCD_H_RES,
             .v_res = TEST_LCD_V_RES,
-            .hsync_back_porch = 43,
-            .hsync_front_porch = 2,
-            .hsync_pulse_width = 1,
-            .vsync_back_porch = 12,
-            .vsync_front_porch = 1,
+            .hsync_back_porch = 68,
+            .hsync_front_porch = 20,
+            .hsync_pulse_width = 5,
+            .vsync_back_porch = 18,
+            .vsync_front_porch = 4,
             .vsync_pulse_width = 1,
+            .flags.pclk_active_neg = 1, // RGB data is clocked out on falling edge
         },
-        .flags.fb_in_psram = 1,
+        .flags.fb_in_psram = 1, // allocate frame buffer in PSRAM
     };
     // Test stream mode and one-off mode
     for (int i = 0; i < 2; i++) {
@@ -99,6 +83,3 @@ TEST_CASE("lcd rgb lcd panel", "[lcd]")
     free(img);
 #undef TEST_IMG_SIZE
 }
-
-#endif // CONFIG_SPIRAM_USE_MALLOC
-#endif // SOC_LCD_RGB_SUPPORTED

+ 20 - 0
components/esp_lcd/test_apps/rgb_lcd/pytest_rgb_lcd.py

@@ -0,0 +1,20 @@
+# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
+# SPDX-License-Identifier: CC0-1.0
+
+import pytest
+from pytest_embedded import Dut
+
+
+@pytest.mark.esp32s3
+@pytest.mark.octal_psram
+@pytest.mark.parametrize(
+    'config',
+    [
+        'release',
+    ],
+    indirect=True,
+)
+def test_rgb_lcd(dut: Dut) -> None:
+    dut.expect_exact('Press ENTER to see the list of tests')
+    dut.write('*')
+    dut.expect_unity_test_output()

+ 5 - 0
components/esp_lcd/test_apps/rgb_lcd/sdkconfig.ci.release

@@ -0,0 +1,5 @@
+CONFIG_PM_ENABLE=y
+CONFIG_FREERTOS_USE_TICKLESS_IDLE=y
+CONFIG_COMPILER_OPTIMIZATION_SIZE=y
+CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y
+CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y

+ 2 - 0
components/esp_lcd/test_apps/rgb_lcd/sdkconfig.defaults

@@ -0,0 +1,2 @@
+CONFIG_FREERTOS_HZ=1000
+CONFIG_ESP_TASK_WDT=n

+ 3 - 0
components/esp_lcd/test_apps/rgb_lcd/sdkconfig.defaults.esp32s3

@@ -0,0 +1,3 @@
+CONFIG_ESP32S3_SPIRAM_SUPPORT=y
+CONFIG_SPIRAM_MODE_OCT=y
+CONFIG_SPIRAM_SPEED_80M=y

+ 5 - 0
components/esp_lcd/test_apps/spi_lcd/CMakeLists.txt

@@ -0,0 +1,5 @@
+# This is the project CMakeLists.txt file for the test subproject
+cmake_minimum_required(VERSION 3.5)
+
+include($ENV{IDF_PATH}/tools/cmake/project.cmake)
+project(spi_lcd_panel_test)

+ 1 - 0
components/esp_lcd/test_apps/spi_lcd/README.md

@@ -0,0 +1 @@
+This test app is used to test LCDs with SPI interface.

+ 7 - 0
components/esp_lcd/test_apps/spi_lcd/main/CMakeLists.txt

@@ -0,0 +1,7 @@
+set(srcs "test_app_main.c"
+         "test_spi_lcd_panel.c")
+
+idf_component_register(SRCS ${srcs}
+                       PRIV_REQUIRES esp_lcd unity)
+
+target_link_libraries(${COMPONENT_LIB} INTERFACE "-u test_app_include_spi_lcd")

+ 51 - 0
components/esp_lcd/test_apps/spi_lcd/main/test_app_main.c

@@ -0,0 +1,51 @@
+/*
+ * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: CC0-1.0
+ */
+
+#include "unity.h"
+#include "unity_test_runner.h"
+#include "esp_heap_caps.h"
+
+// Some resources are lazy allocated in the LCD driver, the threadhold is left for that case
+#define TEST_MEMORY_LEAK_THRESHOLD (-300)
+
+static size_t before_free_8bit;
+static size_t before_free_32bit;
+
+static void check_leak(size_t before_free, size_t after_free, const char *type)
+{
+    ssize_t delta = after_free - before_free;
+    printf("MALLOC_CAP_%s: Before %u bytes free, After %u bytes free (delta %d)\n", type, before_free, after_free, delta);
+    TEST_ASSERT_MESSAGE(delta >= TEST_MEMORY_LEAK_THRESHOLD, "memory leak");
+}
+
+void setUp(void)
+{
+    before_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT);
+    before_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT);
+}
+
+void tearDown(void)
+{
+    size_t after_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT);
+    size_t after_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT);
+    check_leak(before_free_8bit, after_free_8bit, "8BIT");
+    check_leak(before_free_32bit, after_free_32bit, "32BIT");
+}
+
+void app_main(void)
+{
+    //  ____  ____ ___   _     ____ ____    _____         _
+    // / ___||  _ \_ _| | |   / ___|  _ \  |_   _|__  ___| |_
+    // \___ \| |_) | |  | |  | |   | | | |   | |/ _ \/ __| __|
+    //  ___) |  __/| |  | |__| |___| |_| |   | |  __/\__ \ |_
+    // |____/|_|  |___| |_____\____|____/    |_|\___||___/\__|
+    printf(" ____  ____ ___   _     ____ ____    _____         _\r\n");
+    printf("/ ___||  _ \\_ _| | |   / ___|  _ \\  |_   _|__  ___| |_\r\n");
+    printf("\\___ \\| |_) | |  | |  | |   | | | |   | |/ _ \\/ __| __|\r\n");
+    printf(" ___) |  __/| |  | |__| |___| |_| |   | |  __/\\__ \\ |_\r\n");
+    printf("|____/|_|  |___| |_____\\____|____/    |_|\\___||___/\\__|\r\n");
+    unity_run_menu();
+}

+ 33 - 0
components/esp_lcd/test_apps/spi_lcd/main/test_spi_board.h

@@ -0,0 +1,33 @@
+/*
+ * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define TEST_LCD_H_RES          240
+#define TEST_LCD_V_RES          280
+
+#define TEST_LCD_BK_LIGHT_GPIO  18
+#define TEST_LCD_RST_GPIO       5
+#define TEST_LCD_CS_GPIO        0
+#define TEST_LCD_DC_GPIO        19
+#define TEST_LCD_PCLK_GPIO      2
+#define TEST_LCD_DATA0_GPIO     4
+#define TEST_LCD_DATA1_GPIO     7
+#define TEST_LCD_DATA2_GPIO     8
+#define TEST_LCD_DATA3_GPIO     9
+#define TEST_LCD_DATA4_GPIO     10
+#define TEST_LCD_DATA5_GPIO     11
+#define TEST_LCD_DATA6_GPIO     12
+#define TEST_LCD_DATA7_GPIO     13
+
+#define TEST_LCD_PIXEL_CLOCK_HZ (20 * 1000 * 1000)
+
+#ifdef __cplusplus
+}
+#endif

+ 26 - 96
components/esp_lcd/test/test_spi_lcd_panel.c → components/esp_lcd/test_apps/spi_lcd/main/test_spi_lcd_panel.c

@@ -1,8 +1,12 @@
+/*
+ * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
 #include <stdio.h>
 #include <string.h>
 #include "sdkconfig.h"
 #include "unity.h"
-#include "test_utils.h"
 #include "driver/spi_master.h"
 #include "driver/gpio.h"
 #include "esp_lcd_panel_io.h"
@@ -12,16 +16,22 @@
 #include "soc/soc_caps.h"
 #include "test_spi_board.h"
 
-#define TEST_SPI_HOST_ID        (1)
-#define TEST_LCD_PIXEL_CLOCK_HZ (20 * 1000 * 1000) // 20MHz
+#define TEST_SPI_HOST_ID  SPI2_HOST
 
-static void lcd_initialize_spi(esp_lcd_panel_io_handle_t *io_handle, esp_lcd_panel_io_color_trans_done_cb_t on_color_trans_done, void *user_ctx, int cmd_bits, int param_bits, bool oct_mode)
+void test_app_include_spi_lcd(void)
 {
+}
+
+void test_spi_lcd_common_initialize(esp_lcd_panel_io_handle_t *io_handle, esp_lcd_panel_io_color_trans_done_cb_t on_color_trans_done,
+                                    void *user_data, int cmd_bits, int param_bits, bool oct_mode)
+{
+    // turn off backlight
     gpio_config_t bk_gpio_config = {
         .mode = GPIO_MODE_OUTPUT,
         .pin_bit_mask = 1ULL << TEST_LCD_BK_LIGHT_GPIO
     };
     TEST_ESP_OK(gpio_config(&bk_gpio_config));
+    gpio_set_level(TEST_LCD_BK_LIGHT_GPIO, 0);
 
     spi_bus_config_t buscfg = {
         .sclk_io_num = TEST_LCD_PCLK_GPIO,
@@ -52,7 +62,7 @@ static void lcd_initialize_spi(esp_lcd_panel_io_handle_t *io_handle, esp_lcd_pan
         .lcd_cmd_bits = cmd_bits,
         .lcd_param_bits = param_bits,
         .on_color_trans_done = on_color_trans_done,
-        .user_ctx = user_ctx
+        .user_ctx = user_data,
     };
     if (oct_mode) {
         io_config.flags.octal_mode = 1;
@@ -67,8 +77,6 @@ static void lcd_panel_test(esp_lcd_panel_io_handle_t io_handle, esp_lcd_panel_ha
     uint8_t *img = heap_caps_malloc(TEST_IMG_SIZE, MALLOC_CAP_DMA);
     TEST_ASSERT_NOT_NULL(img);
 
-    // turn off backlight
-    gpio_set_level(TEST_LCD_BK_LIGHT_GPIO, 0);
     esp_lcd_panel_reset(panel_handle);
     esp_lcd_panel_init(panel_handle);
     esp_lcd_panel_invert_color(panel_handle, true);
@@ -94,10 +102,10 @@ static void lcd_panel_test(esp_lcd_panel_io_handle_t io_handle, esp_lcd_panel_ha
 #undef TEST_IMG_SIZE
 }
 
-TEST_CASE("lcd panel spi io test", "[lcd]")
+TEST_CASE("lcd_panel_spi_io_test", "[lcd]")
 {
     esp_lcd_panel_io_handle_t io_handle = NULL;
-    lcd_initialize_spi(&io_handle, NULL, NULL, 8, 8, false);
+    test_spi_lcd_common_initialize(&io_handle, NULL, NULL, 8, 8, false);
     esp_lcd_panel_io_tx_param(io_handle, 0x1A, NULL, 0);
     esp_lcd_panel_io_tx_param(io_handle, 0x1B, (uint8_t[]) {
         0x11, 0x22, 0x33
@@ -106,7 +114,7 @@ TEST_CASE("lcd panel spi io test", "[lcd]")
     TEST_ESP_OK(esp_lcd_panel_io_del(io_handle));
     TEST_ESP_OK(spi_bus_free(TEST_SPI_HOST_ID));
 
-    lcd_initialize_spi(&io_handle, NULL, NULL, 16, 16, false);
+    test_spi_lcd_common_initialize(&io_handle, NULL, NULL, 16, 16, false);
     esp_lcd_panel_io_tx_param(io_handle, 0x1A01, NULL, 0);
     esp_lcd_panel_io_tx_param(io_handle, 0x1B02, (uint16_t[]) {
         0x11, 0x22, 0x33
@@ -116,7 +124,7 @@ TEST_CASE("lcd panel spi io test", "[lcd]")
     TEST_ESP_OK(spi_bus_free(TEST_SPI_HOST_ID));
 
 #if SOC_SPI_SUPPORT_OCT
-    lcd_initialize_spi(&io_handle, NULL, NULL, 8, 8, true);
+    test_spi_lcd_common_initialize(&io_handle, NULL, NULL, 8, 8, true);
     esp_lcd_panel_io_tx_param(io_handle, 0x1A, NULL, 0);
     esp_lcd_panel_io_tx_param(io_handle, 0x1B, (uint8_t[]) {
         0x11, 0x22, 0x33
@@ -125,7 +133,7 @@ TEST_CASE("lcd panel spi io test", "[lcd]")
     TEST_ESP_OK(esp_lcd_panel_io_del(io_handle));
     TEST_ESP_OK(spi_bus_free(TEST_SPI_HOST_ID));
 
-    lcd_initialize_spi(&io_handle, NULL, NULL, 16, 16, true);
+    test_spi_lcd_common_initialize(&io_handle, NULL, NULL, 16, 16, true);
     esp_lcd_panel_io_tx_param(io_handle, 0x1A01, NULL, 0);
     esp_lcd_panel_io_tx_param(io_handle, 0x1B02, (uint16_t[]) {
         0x11, 0x22, 0x33
@@ -137,11 +145,11 @@ TEST_CASE("lcd panel spi io test", "[lcd]")
 }
 
 #if SOC_SPI_SUPPORT_OCT
-TEST_CASE("lcd panel with 8-line spi interface (st7789)", "[lcd]")
+TEST_CASE("lcd_panel_with_8-line_spi_interface_(st7789)", "[lcd]")
 {
     esp_lcd_panel_io_handle_t io_handle = NULL;
     esp_lcd_panel_handle_t panel_handle = NULL;
-    lcd_initialize_spi(&io_handle, NULL, NULL, 8, 8, true);
+    test_spi_lcd_common_initialize(&io_handle, NULL, NULL, 8, 8, true);
     esp_lcd_panel_dev_config_t panel_config = {
         .reset_gpio_num = TEST_LCD_RST_GPIO,
         .color_space = ESP_LCD_COLOR_SPACE_RGB,
@@ -151,11 +159,11 @@ TEST_CASE("lcd panel with 8-line spi interface (st7789)", "[lcd]")
     lcd_panel_test(io_handle, panel_handle);
 }
 
-TEST_CASE("lcd panel with 8-line spi interface (nt35510)", "[lcd]")
+TEST_CASE("lcd_panel_with_8-line_spi_interface_(nt35510)", "[lcd]")
 {
     esp_lcd_panel_io_handle_t io_handle = NULL;
     esp_lcd_panel_handle_t panel_handle = NULL;
-    lcd_initialize_spi(&io_handle, NULL, NULL, 16, 16, true);
+    test_spi_lcd_common_initialize(&io_handle, NULL, NULL, 16, 16, true);
     esp_lcd_panel_dev_config_t panel_config = {
         .reset_gpio_num = TEST_LCD_RST_GPIO,
         .color_space = ESP_LCD_COLOR_SPACE_RGB,
@@ -166,11 +174,11 @@ TEST_CASE("lcd panel with 8-line spi interface (nt35510)", "[lcd]")
 }
 #endif // SOC_SPI_SUPPORT_OCT
 
-TEST_CASE("lcd panel with 1-line spi interface (st7789)", "[lcd]")
+TEST_CASE("lcd_panel_with_1-line_spi_interface_(st7789)", "[lcd]")
 {
     esp_lcd_panel_io_handle_t io_handle = NULL;
     esp_lcd_panel_handle_t panel_handle = NULL;
-    lcd_initialize_spi(&io_handle, NULL, NULL, 8, 8, false);
+    test_spi_lcd_common_initialize(&io_handle, NULL, NULL, 8, 8, false);
     esp_lcd_panel_dev_config_t panel_config = {
         .reset_gpio_num = TEST_LCD_RST_GPIO,
         .color_space = ESP_LCD_COLOR_SPACE_RGB,
@@ -179,81 +187,3 @@ TEST_CASE("lcd panel with 1-line spi interface (st7789)", "[lcd]")
     TEST_ESP_OK(esp_lcd_new_panel_st7789(io_handle, &panel_config, &panel_handle));
     lcd_panel_test(io_handle, panel_handle);
 }
-
-// The following test shows a porting example of LVGL GUI library
-// To run the LVGL tests, you need to clone the LVGL library into components directory firstly
-#if CONFIG_LV_USE_USER_DATA
-#include "test_lvgl_port.h"
-
-static bool notify_lvgl_ready_to_flush(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_io_event_data_t *edata, void *user_ctx)
-{
-    lv_disp_t *disp = *(lv_disp_t **)user_ctx;
-    lv_disp_flush_ready(&disp->driver);
-    return false;
-}
-
-static void lvgl_gui_test(esp_lcd_panel_io_handle_t io_handle, esp_lcd_panel_handle_t panel_handle, lv_disp_t **disp)
-{
-    // initialize LVGL graphics library
-    lv_init();
-    // turn off backlight
-    gpio_set_level(TEST_LCD_BK_LIGHT_GPIO, 0);
-    esp_lcd_panel_reset(panel_handle);
-    esp_lcd_panel_init(panel_handle);
-    esp_lcd_panel_invert_color(panel_handle, true);
-    // the gap is LCD panel specific, even panels with the same driver IC, can have different gap value
-    esp_lcd_panel_set_gap(panel_handle, 0, 20);
-    // turn on backlight
-    gpio_set_level(TEST_LCD_BK_LIGHT_GPIO, 1);
-
-    test_lvgl_task_loop(panel_handle, TEST_LCD_H_RES, TEST_LCD_V_RES, disp);
-}
-
-#if SOC_SPI_SUPPORT_OCT
-TEST_CASE("lvgl gui with 8-line spi interface (st7789)", "[lcd][lvgl][ignore]")
-{
-    lv_disp_t *disp = NULL;
-    esp_lcd_panel_io_handle_t io_handle = NULL;
-    esp_lcd_panel_handle_t panel_handle = NULL;
-    lcd_initialize_spi(&io_handle, notify_lvgl_ready_to_flush, &disp, 8, 8, true);
-    esp_lcd_panel_dev_config_t panel_config = {
-        .reset_gpio_num = TEST_LCD_RST_GPIO,
-        .color_space = ESP_LCD_COLOR_SPACE_RGB,
-        .bits_per_pixel = 16,
-    };
-    TEST_ESP_OK(esp_lcd_new_panel_st7789(io_handle, &panel_config, &panel_handle));
-    lvgl_gui_test(io_handle, panel_handle, &disp);
-}
-
-TEST_CASE("lvgl gui with 8-line spi interface (nt35510)", "[lcd][lvgl][ignore]")
-{
-    lv_disp_t *disp = NULL;
-    esp_lcd_panel_io_handle_t io_handle = NULL;
-    esp_lcd_panel_handle_t panel_handle = NULL;
-    lcd_initialize_spi(&io_handle, notify_lvgl_ready_to_flush, &disp, 16, 16, true);
-    esp_lcd_panel_dev_config_t panel_config = {
-        .reset_gpio_num = TEST_LCD_RST_GPIO,
-        .color_space = ESP_LCD_COLOR_SPACE_RGB,
-        .bits_per_pixel = 16,
-    };
-    TEST_ESP_OK(esp_lcd_new_panel_nt35510(io_handle, &panel_config, &panel_handle));
-    lvgl_gui_test(io_handle, panel_handle, &disp);
-}
-#endif // SOC_SPI_SUPPORT_OCT
-
-TEST_CASE("lvgl gui with 1-line spi interface (st7789)", "[lcd][lvgl][ignore]")
-{
-    lv_disp_t *disp = NULL;
-    esp_lcd_panel_io_handle_t io_handle = NULL;
-    esp_lcd_panel_handle_t panel_handle = NULL;
-    lcd_initialize_spi(&io_handle, notify_lvgl_ready_to_flush, &disp, 8, 8, false);
-    esp_lcd_panel_dev_config_t panel_config = {
-        .reset_gpio_num = TEST_LCD_RST_GPIO,
-        .color_space = ESP_LCD_COLOR_SPACE_RGB,
-        .bits_per_pixel = 16,
-    };
-    TEST_ESP_OK(esp_lcd_new_panel_st7789(io_handle, &panel_config, &panel_handle));
-    lvgl_gui_test(io_handle, panel_handle, &disp);
-}
-
-#endif // CONFIG_LV_USE_USER_DATA

+ 20 - 0
components/esp_lcd/test_apps/spi_lcd/pytest_spi_lcd.py

@@ -0,0 +1,20 @@
+# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
+# SPDX-License-Identifier: CC0-1.0
+
+import pytest
+from pytest_embedded import Dut
+
+
+@pytest.mark.supported_targets
+@pytest.mark.generic
+@pytest.mark.parametrize(
+    'config',
+    [
+        'release',
+    ],
+    indirect=True,
+)
+def test_spi_lcd(dut: Dut) -> None:
+    dut.expect_exact('Press ENTER to see the list of tests')
+    dut.write('*')
+    dut.expect_unity_test_output()

+ 3 - 0
components/esp_lcd/test_apps/spi_lcd/sdkconfig.ci.release

@@ -0,0 +1,3 @@
+CONFIG_COMPILER_OPTIMIZATION_SIZE=y
+CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y
+CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y

+ 2 - 0
components/esp_lcd/test_apps/spi_lcd/sdkconfig.defaults

@@ -0,0 +1,2 @@
+CONFIG_FREERTOS_HZ=1000
+CONFIG_ESP_TASK_WDT=n

+ 0 - 5
examples/peripherals/lcd/gc9a01/CMakeLists.txt

@@ -2,8 +2,3 @@ cmake_minimum_required(VERSION 3.5)
 
 include($ENV{IDF_PATH}/tools/cmake/project.cmake)
 project(lcd_gc9a01)
-
-# As the upstream LVGL library has build warnings in esp-idf build system, this is only for temporarily workaround
-# Will remove this workaround when upstream LVGL fixes the warnings in the next release
-idf_component_get_property(lvgl_lib lvgl__lvgl COMPONENT_LIB)
-target_compile_options(${lvgl_lib} PRIVATE "-Wno-empty-body" "-Wno-strict-prototypes")

+ 1 - 1
examples/peripherals/lcd/gc9a01/main/idf_component.yml

@@ -1,3 +1,3 @@
 dependencies:
   idf: ">=4.4"
-  lvgl/lvgl: "~8.0.2"
+  lvgl/lvgl: "~8.2.0"

+ 0 - 5
examples/peripherals/lcd/i2c_oled/CMakeLists.txt

@@ -2,8 +2,3 @@ cmake_minimum_required(VERSION 3.5)
 
 include($ENV{IDF_PATH}/tools/cmake/project.cmake)
 project(i2c_oled)
-
-# As the upstream LVGL library has build warnings in esp-idf build system, this is only for temporarily workaround
-# Will remove this workaround when upstream LVGL fixes the warnings in the next release
-idf_component_get_property(lvgl_lib lvgl__lvgl COMPONENT_LIB)
-target_compile_options(${lvgl_lib} PRIVATE "-Wno-empty-body" "-Wno-strict-prototypes")

+ 1 - 1
examples/peripherals/lcd/i2c_oled/main/idf_component.yml

@@ -1,3 +1,3 @@
 dependencies:
   idf: ">=4.4"
-  lvgl/lvgl: "~8.0.2"
+  lvgl/lvgl: "~8.2.0"

+ 0 - 5
examples/peripherals/lcd/i80_controller/CMakeLists.txt

@@ -2,8 +2,3 @@ cmake_minimum_required(VERSION 3.5)
 
 include($ENV{IDF_PATH}/tools/cmake/project.cmake)
 project(i80_controller)
-
-# As the upstream LVGL library has build warnings in esp-idf build system, this is only for temporarily workaround
-# Will remove this workaround when upstream LVGL fixes the warnings in the next release
-idf_component_get_property(lvgl_lib lvgl__lvgl COMPONENT_LIB)
-target_compile_options(${lvgl_lib} PRIVATE "-Wno-empty-body" "-Wno-strict-prototypes")

+ 3 - 1
examples/peripherals/lcd/i80_controller/README.md

@@ -19,7 +19,7 @@ This example uses the [esp_timer](https://docs.espressif.com/projects/esp-idf/en
 ### Hardware Required
 
 * An ESP development board
-* An Intel 8080 interfaced (so called MCU interface or parallel interface) LCD
+* An Intel 8080 interfaced (so called MCU interface or parallel interface) LCD (this example can use ST7789 or NT35510)
 * An USB cable for power supply and programming
 
 ### Hardware Connection
@@ -58,6 +58,8 @@ Run `idf.py set-target <target-name>` to select one supported target that can ru
 
 Run `idf.py menuconfig` to open a terminal UI where you can tune specific configuration for this example in the `Example Configuration` menu.
 
+* `i80 LCD controller model`: Choose the LCD model to use by the example. If you choose `NT35510`, there will be another relevant configuration `NT35510 Data Width`, to choose the data line width for your NT35510 LCD module.
+
 * `Allocate color data from PSRAM`: Select this option if you want to allocate the LVGL draw buffers from PSRAM.
 
 Run `idf.py -p PORT build flash monitor` to build, flash and monitor the project. A fancy animation will show up on the LCD as expected.

+ 34 - 0
examples/peripherals/lcd/i80_controller/main/Kconfig.projbuild

@@ -8,4 +8,38 @@ menu "Example Configuration"
             Enable this option if you wish to allocate the color buffer used by LVGL from PSRAM.
             Unmatched PSRAM band width with LCD requirement can lead to blurred image display.
 
+    choice EXAMPLE_LCD_I80_CONTROLLER_MODEL
+        prompt "i80 LCD controller model"
+        default EXAMPLE_LCD_I80_CONTROLLER_ST7789
+        help
+            Select LCD controller model
+
+        config EXAMPLE_LCD_I80_CONTROLLER_ST7789
+            bool "ST7789"
+
+        config EXAMPLE_LCD_I80_CONTROLLER_NT35510
+            bool "NT35510"
+    endchoice
+
+    if EXAMPLE_LCD_I80_CONTROLLER_NT35510
+        choice EXAMPLE_LCD_NT35510_DATA_WIDTH
+            prompt "NT35510 Data Width"
+            default EXAMPLE_LCD_NT35510_DATA_WIDTH_8
+            help
+                Select NT35510 Data Width (8 or 16), a.k.a, the number of data lines.
+
+            config EXAMPLE_LCD_NT35510_DATA_WIDTH_8
+                bool "8"
+
+            config EXAMPLE_LCD_NT35510_DATA_WIDTH_16
+                bool "16"
+        endchoice
+
+    endif
+
+    config EXAMPLE_LCD_I80_BUS_WIDTH
+        int
+        default 16 if EXAMPLE_LCD_NT35510_DATA_WIDTH_16
+        default 8
+
 endmenu

+ 43 - 2
examples/peripherals/lcd/i80_controller/main/i80_controller_example_main.c

@@ -38,6 +38,16 @@ static const char *TAG = "example";
 #define EXAMPLE_PIN_NUM_DATA5          11
 #define EXAMPLE_PIN_NUM_DATA6          12
 #define EXAMPLE_PIN_NUM_DATA7          13
+#if CONFIG_EXAMPLE_LCD_I80_BUS_WIDTH > 8
+#define EXAMPLE_PIN_NUM_DATA8          14
+#define EXAMPLE_PIN_NUM_DATA9          15
+#define EXAMPLE_PIN_NUM_DATA10         16
+#define EXAMPLE_PIN_NUM_DATA11         17
+#define EXAMPLE_PIN_NUM_DATA12         18
+#define EXAMPLE_PIN_NUM_DATA13         19
+#define EXAMPLE_PIN_NUM_DATA14         20
+#define EXAMPLE_PIN_NUM_DATA15         21
+#endif
 #define EXAMPLE_PIN_NUM_PCLK           5
 #define EXAMPLE_PIN_NUM_CS             3
 #define EXAMPLE_PIN_NUM_DC             4
@@ -48,8 +58,13 @@ static const char *TAG = "example";
 #define EXAMPLE_LCD_H_RES              240
 #define EXAMPLE_LCD_V_RES              280
 // Bit number used to represent command and parameter
+#if CONFIG_EXAMPLE_LCD_I80_CONTROLLER_ST7789
 #define EXAMPLE_LCD_CMD_BITS           8
 #define EXAMPLE_LCD_PARAM_BITS         8
+#elif CONFIG_EXAMPLE_LCD_I80_CONTROLLER_NT35510
+#define EXAMPLE_LCD_CMD_BITS           16
+#define EXAMPLE_LCD_PARAM_BITS         16
+#endif
 
 #define EXAMPLE_LVGL_TICK_PERIOD_MS    2
 
@@ -110,8 +125,18 @@ void app_main(void)
             EXAMPLE_PIN_NUM_DATA5,
             EXAMPLE_PIN_NUM_DATA6,
             EXAMPLE_PIN_NUM_DATA7,
+#if CONFIG_EXAMPLE_LCD_I80_BUS_WIDTH > 8
+            EXAMPLE_PIN_NUM_DATA8,
+            EXAMPLE_PIN_NUM_DATA9,
+            EXAMPLE_PIN_NUM_DATA10,
+            EXAMPLE_PIN_NUM_DATA11,
+            EXAMPLE_PIN_NUM_DATA12,
+            EXAMPLE_PIN_NUM_DATA13,
+            EXAMPLE_PIN_NUM_DATA14,
+            EXAMPLE_PIN_NUM_DATA15,
+#endif
         },
-        .bus_width = 8,
+        .bus_width = CONFIG_EXAMPLE_LCD_I80_BUS_WIDTH,
         .max_transfer_bytes = EXAMPLE_LCD_H_RES * 100 * sizeof(uint16_t),
         .psram_trans_align = EXAMPLE_PSRAM_DATA_ALIGNMENT,
         .sram_trans_align = 4,
@@ -135,18 +160,34 @@ void app_main(void)
     };
     ESP_ERROR_CHECK(esp_lcd_new_panel_io_i80(i80_bus, &io_config, &io_handle));
 
-    ESP_LOGI(TAG, "Install LCD driver of st7789");
     esp_lcd_panel_handle_t panel_handle = NULL;
+#if CONFIG_EXAMPLE_LCD_I80_CONTROLLER_ST7789
+    ESP_LOGI(TAG, "Install LCD driver of st7789");
     esp_lcd_panel_dev_config_t panel_config = {
         .reset_gpio_num = EXAMPLE_PIN_NUM_RST,
         .color_space = ESP_LCD_COLOR_SPACE_RGB,
         .bits_per_pixel = 16,
     };
     ESP_ERROR_CHECK(esp_lcd_new_panel_st7789(io_handle, &panel_config, &panel_handle));
+#elif CONFIG_EXAMPLE_LCD_I80_CONTROLLER_NT35510
+    ESP_LOGI(TAG, "Install LCD driver of nt35510");
+    esp_lcd_panel_dev_config_t panel_config = {
+        .reset_gpio_num = EXAMPLE_PIN_NUM_RST,
+        .color_space = ESP_LCD_COLOR_SPACE_BGR,
+        .bits_per_pixel = 16,
+    };
+    ESP_ERROR_CHECK(esp_lcd_new_panel_nt35510(io_handle, &panel_config, &panel_handle));
+#endif
 
     esp_lcd_panel_reset(panel_handle);
     esp_lcd_panel_init(panel_handle);
+    // Set inversion, x/y coordinate order, x/y mirror according to your LCD module spec
+#if CONFIG_EXAMPLE_LCD_I80_CONTROLLER_ST7789
     esp_lcd_panel_invert_color(panel_handle, true);
+#elif CONFIG_EXAMPLE_LCD_I80_CONTROLLER_NT35510
+    esp_lcd_panel_swap_xy(panel_handle, true);
+    esp_lcd_panel_mirror(panel_handle, true, false);
+#endif
     // the gap is LCD panel specific, even panels with the same driver IC, can have different gap value
     esp_lcd_panel_set_gap(panel_handle, 0, 20);
 

+ 1 - 1
examples/peripherals/lcd/i80_controller/main/idf_component.yml

@@ -1,3 +1,3 @@
 dependencies:
   idf: ">=4.4"
-  lvgl/lvgl: "~8.0.2"
+  lvgl/lvgl: "~8.2.0"

+ 0 - 5
examples/peripherals/lcd/rgb_panel/CMakeLists.txt

@@ -2,8 +2,3 @@ cmake_minimum_required(VERSION 3.5)
 
 include($ENV{IDF_PATH}/tools/cmake/project.cmake)
 project(rgb_panel)
-
-# As the upstream LVGL library has build warnings in esp-idf build system, this is only for temporarily workaround
-# Will remove this workaround when upstream LVGL fixes the warnings in the next release
-idf_component_get_property(lvgl_lib lvgl__lvgl COMPONENT_LIB)
-target_compile_options(${lvgl_lib} PRIVATE "-Wno-empty-body" "-Wno-strict-prototypes")

+ 1 - 1
examples/peripherals/lcd/rgb_panel/main/idf_component.yml

@@ -1,3 +1,3 @@
 dependencies:
   idf: ">=4.4"
-  lvgl/lvgl: "~8.0.2"
+  lvgl/lvgl: "~8.2.0"

+ 5 - 8
examples/peripherals/lcd/tjpgd/main/decode_image.c

@@ -1,11 +1,8 @@
-/* SPI Master example: jpeg decoder.
-
-   This example code is in the Public Domain (or CC0 licensed, at your option.)
-
-   Unless required by applicable law or agreed to in writing, this
-   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-   CONDITIONS OF ANY KIND, either express or implied.
-*/
+/*
+ * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: CC0-1.0
+ */
 
 /*
 The image used for the effect on the LCD in the SPI master example is stored in flash

+ 4 - 6
examples/peripherals/lcd/tjpgd/main/decode_image.h

@@ -1,10 +1,8 @@
 /*
-   This example code is in the Public Domain (or CC0 licensed, at your option.)
-
-   Unless required by applicable law or agreed to in writing, this
-   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-   CONDITIONS OF ANY KIND, either express or implied.
-*/
+ * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: CC0-1.0
+ */
 
 #pragma once
 #include <stdint.h>

+ 5 - 7
examples/peripherals/lcd/tjpgd/main/lcd_tjpgd_example_main.c

@@ -1,11 +1,9 @@
-/* LCD tjpgd example
+/*
+ * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: CC0-1.0
+ */
 
-   This example code is in the Public Domain (or CC0 licensed, at your option.)
-
-   Unless required by applicable law or agreed to in writing, this
-   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-   CONDITIONS OF ANY KIND, either express or implied.
-*/
 #include <stdio.h>
 #include "freertos/FreeRTOS.h"
 #include "freertos/task.h"

+ 4 - 9
examples/peripherals/lcd/tjpgd/main/pretty_effect.c

@@ -1,13 +1,8 @@
 /*
-   This code generates an effect that should pass the 'fancy graphics' qualification
-   as set in the comment in the spi_master code.
-
-   This example code is in the Public Domain (or CC0 licensed, at your option.)
-
-   Unless required by applicable law or agreed to in writing, this
-   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-   CONDITIONS OF ANY KIND, either express or implied.
-*/
+ * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: CC0-1.0
+ */
 
 #include <math.h>
 #include "pretty_effect.h"

+ 4 - 6
examples/peripherals/lcd/tjpgd/main/pretty_effect.h

@@ -1,10 +1,8 @@
 /*
-   This example code is in the Public Domain (or CC0 licensed, at your option.)
-
-   Unless required by applicable law or agreed to in writing, this
-   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-   CONDITIONS OF ANY KIND, either express or implied.
-*/
+ * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: CC0-1.0
+ */
 
 #pragma once
 #include <stdint.h>

+ 1 - 0
pytest.ini

@@ -22,6 +22,7 @@ markers =
   flash_suspend: support flash suspend feature
   ip101: connected via wired 10/100M ethernet
   lan8720: connected via LAN8720 ethernet transceiver
+  octal_psram: runners with octal psram
 
 # log related
 log_cli = True

+ 0 - 16
tools/ci/check_copyright_ignore.txt

@@ -485,17 +485,6 @@ components/esp_hid/test/test_esp_hid.c
 components/esp_hw_support/include/esp_clk.h
 components/esp_hw_support/include/soc/esp_himem.h
 components/esp_hw_support/include/soc/esp_spiram.h
-components/esp_ipc/include/esp_ipc.h
-components/esp_ipc/test/test_ipc.c
-components/esp_ipc/test/test_ipc_isr.c
-components/esp_lcd/test/test_i2c_lcd_panel.c
-components/esp_lcd/test/test_i80_board.h
-components/esp_lcd/test/test_i80_lcd_panel.c
-components/esp_lcd/test/test_lvgl_port.h
-components/esp_lcd/test/test_lvgl_port_v7.c
-components/esp_lcd/test/test_rgb_panel.c
-components/esp_lcd/test/test_spi_board.h
-components/esp_lcd/test/test_spi_lcd_panel.c
 components/esp_local_ctrl/include/esp_local_ctrl.h
 components/esp_local_ctrl/proto-c/esp_local_ctrl.pb-c.c
 components/esp_local_ctrl/proto-c/esp_local_ctrl.pb-c.h
@@ -2301,11 +2290,6 @@ examples/peripherals/i2s/i2s_adc_dac/main/audio_example_file.h
 examples/peripherals/i2s/i2s_adc_dac/tools/generate_audio_file.py
 examples/peripherals/i2s/i2s_audio_recorder_sdcard/main/i2s_recorder_main.c
 examples/peripherals/i2s/i2s_basic/main/i2s_example_main.c
-examples/peripherals/lcd/tjpgd/main/decode_image.c
-examples/peripherals/lcd/tjpgd/main/decode_image.h
-examples/peripherals/lcd/tjpgd/main/lcd_tjpgd_example_main.c
-examples/peripherals/lcd/tjpgd/main/pretty_effect.c
-examples/peripherals/lcd/tjpgd/main/pretty_effect.h
 examples/peripherals/ledc/ledc_basic/main/ledc_basic_example_main.c
 examples/peripherals/ledc/ledc_fade/main/ledc_fade_example_main.c
 examples/peripherals/mcpwm/mcpwm_bldc_hall_control/main/mcpwm_bldc_hall_control_example_main.c