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

Merge branch 'refactor/not_turn_on_disp_inside_init' into 'master'

lcd: don't turn on disp in esp_lcd_panel_init

Closes IDFGH-6896 and IDFGH-7191

See merge request espressif/esp-idf!17738
morris пре 3 година
родитељ
комит
cecea95b32
34 измењених фајлова са 193 додато и 57 уклоњено
  1. 2 1
      components/esp_lcd/include/esp_lcd_panel_io.h
  2. 14 2
      components/esp_lcd/include/esp_lcd_panel_ops.h
  3. 4 4
      components/esp_lcd/interface/esp_lcd_panel_interface.h
  4. 2 1
      components/esp_lcd/src/esp_lcd_panel_io_spi.c
  5. 6 8
      components/esp_lcd/src/esp_lcd_panel_nt35510.c
  6. 7 2
      components/esp_lcd/src/esp_lcd_panel_ops.c
  7. 8 9
      components/esp_lcd/src/esp_lcd_panel_ssd1306.c
  8. 6 8
      components/esp_lcd/src/esp_lcd_panel_st7789.c
  9. 4 4
      components/esp_lcd/src/esp_lcd_rgb_panel.c
  10. 2 0
      components/esp_lcd/test_apps/i2c_lcd/main/test_i2c_lcd_panel.c
  11. 4 1
      components/esp_lcd/test_apps/i80_lcd/main/test_i80_lcd_panel.c
  12. 3 1
      components/esp_lcd/test_apps/spi_lcd/main/test_spi_lcd_panel.c
  13. 13 1
      components/hal/esp32/include/hal/rmt_ll.h
  14. 13 1
      components/hal/esp32c3/include/hal/rmt_ll.h
  15. 13 1
      components/hal/esp32h2/include/hal/rmt_ll.h
  16. 13 1
      components/hal/esp32s2/include/hal/rmt_ll.h
  17. 13 1
      components/hal/esp32s3/include/hal/rmt_ll.h
  18. 1 0
      components/heap/heap_caps.c
  19. 4 0
      components/soc/esp32/include/soc/Kconfig.soc_caps.in
  20. 2 1
      components/soc/esp32/include/soc/soc_caps.h
  21. 8 0
      components/soc/esp32c3/include/soc/Kconfig.soc_caps.in
  22. 2 0
      components/soc/esp32c3/include/soc/soc_caps.h
  23. 8 0
      components/soc/esp32h2/include/soc/Kconfig.soc_caps.in
  24. 3 1
      components/soc/esp32h2/include/soc/soc_caps.h
  25. 4 0
      components/soc/esp32s2/include/soc/Kconfig.soc_caps.in
  26. 1 0
      components/soc/esp32s2/include/soc/soc_caps.h
  27. 8 0
      components/soc/esp32s3/include/soc/Kconfig.soc_caps.in
  28. 2 0
      components/soc/esp32s3/include/soc/soc_caps.h
  29. 6 0
      docs/en/migration-guides/peripherals.rst
  30. 7 9
      examples/peripherals/lcd/gc9a01/main/esp_lcd_panel_gc9a01.c
  31. 3 0
      examples/peripherals/lcd/gc9a01/main/gc9a01_example_main.c
  32. 1 0
      examples/peripherals/lcd/i2c_oled/main/i2c_oled_example_main.c
  33. 3 0
      examples/peripherals/lcd/i80_controller/main/i80_controller_example_main.c
  34. 3 0
      examples/peripherals/lcd/tjpgd/main/lcd_tjpgd_example_main.c

+ 2 - 1
components/esp_lcd/include/esp_lcd_panel_io.h

@@ -98,7 +98,8 @@ typedef struct {
         unsigned int dc_as_cmd_phase: 1; /*!< D/C line value is encoded into SPI transaction command phase */
         unsigned int dc_low_on_data: 1;  /*!< If this flag is enabled, DC line = 0 means transfer data, DC line = 1 means transfer command; vice versa */
         unsigned int octal_mode: 1;      /*!< transmit with octal mode (8 data lines), this mode is used to simulate Intel 8080 timing */
-    } flags;
+        unsigned int lsb_first: 1;       /*!< transmit LSB bit first */
+    } flags; /*!< Extra flags to fine-tune the SPI device */
 } esp_lcd_panel_io_spi_config_t;
 
 /**

+ 14 - 2
components/esp_lcd/include/esp_lcd_panel_ops.h

@@ -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
  */
@@ -110,6 +110,17 @@ esp_err_t esp_lcd_panel_set_gap(esp_lcd_panel_handle_t panel, int x_gap, int y_g
  */
 esp_err_t esp_lcd_panel_invert_color(esp_lcd_panel_handle_t panel, bool invert_color_data);
 
+/**
+ * @brief Turn on or off the display
+ *
+ * @param[in] panel LCD panel handle, which is created by other factory API like `esp_lcd_new_panel_st7789()`
+ * @param[in] on_off True to turns on display, False to turns off display
+ * @return
+ *          - ESP_OK on success
+ *          - ESP_ERR_NOT_SUPPORTED if this function is not supported by the panel
+ */
+esp_err_t esp_lcd_panel_disp_on_off(esp_lcd_panel_handle_t panel, bool on_off);
+
 /**
  * @brief Turn off the display
  *
@@ -119,7 +130,8 @@ esp_err_t esp_lcd_panel_invert_color(esp_lcd_panel_handle_t panel, bool invert_c
  *          - ESP_OK on success
  *          - ESP_ERR_NOT_SUPPORTED if this function is not supported by the panel
  */
-esp_err_t esp_lcd_panel_disp_off(esp_lcd_panel_handle_t panel, bool off);
+esp_err_t esp_lcd_panel_disp_off(esp_lcd_panel_handle_t panel, bool off)
+__attribute__((deprecated("use esp_lcd_panel_disp_on_off instead")));
 
 #ifdef __cplusplus
 }

+ 4 - 4
components/esp_lcd/interface/esp_lcd_panel_interface.h

@@ -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
  */
@@ -110,15 +110,15 @@ struct esp_lcd_panel_t {
     esp_err_t (*invert_color)(esp_lcd_panel_t *panel, bool invert_color_data);
 
     /**
-     * @brief Turn off the display
+     * @brief Turn on or off the display
      *
      * @param[in] panel LCD panel handle, which is created by other factory API like `esp_lcd_new_panel_st7789()`
-     * @param[in] off Whether to turn off the screen
+     * @param[in] on_off True to turns on display, False to turns off display
      * @return
      *          - ESP_OK on success
      *          - ESP_ERR_NOT_SUPPORTED if this function is not supported by the panel
      */
-    esp_err_t (*disp_off)(esp_lcd_panel_t *panel, bool off);
+    esp_err_t (*disp_on_off)(esp_lcd_panel_t *panel, bool on_off);
 };
 
 #ifdef __cplusplus

+ 2 - 1
components/esp_lcd/src/esp_lcd_panel_io_spi.c

@@ -72,7 +72,8 @@ esp_err_t esp_lcd_new_panel_io_spi(esp_lcd_spi_bus_handle_t bus, const esp_lcd_p
     ESP_GOTO_ON_FALSE(spi_panel_io, ESP_ERR_NO_MEM, err, TAG, "no mem for spi panel io");
 
     spi_device_interface_config_t devcfg = {
-        .flags = SPI_DEVICE_HALFDUPLEX, // only use TX path, so half duplex is enough
+        // currently the driver only supports TX path, so half duplex is enough
+        .flags = SPI_DEVICE_HALFDUPLEX | (io_config->flags.lsb_first ? SPI_DEVICE_TXBIT_LSBFIRST : 0),
         .clock_speed_hz = io_config->pclk_hz,
         .mode = io_config->spi_mode,
         .spics_io_num = io_config->cs_gpio_num,

+ 6 - 8
components/esp_lcd/src/esp_lcd_panel_nt35510.c

@@ -33,7 +33,7 @@ static esp_err_t panel_nt35510_invert_color(esp_lcd_panel_t *panel, bool invert_
 static esp_err_t panel_nt35510_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y);
 static esp_err_t panel_nt35510_swap_xy(esp_lcd_panel_t *panel, bool swap_axes);
 static esp_err_t panel_nt35510_set_gap(esp_lcd_panel_t *panel, int x_gap, int y_gap);
-static esp_err_t panel_nt35510_disp_off(esp_lcd_panel_t *panel, bool off);
+static esp_err_t panel_nt35510_disp_on_off(esp_lcd_panel_t *panel, bool off);
 
 typedef struct {
     esp_lcd_panel_t base;
@@ -105,7 +105,7 @@ esp_err_t esp_lcd_new_panel_nt35510(const esp_lcd_panel_io_handle_t io, const es
     nt35510->base.set_gap = panel_nt35510_set_gap;
     nt35510->base.mirror = panel_nt35510_mirror;
     nt35510->base.swap_xy = panel_nt35510_swap_xy;
-    nt35510->base.disp_off = panel_nt35510_disp_off;
+    nt35510->base.disp_on_off = panel_nt35510_disp_on_off;
     *ret_panel = &(nt35510->base);
     ESP_LOGD(TAG, "new nt35510 panel @%p", nt35510);
 
@@ -166,8 +166,6 @@ static esp_err_t panel_nt35510_init(esp_lcd_panel_t *panel)
     esp_lcd_panel_io_tx_param(io, LCD_CMD_COLMOD << 8, (uint16_t[]) {
         nt35510->colmod_cal,
     }, 2);
-    // turn on display
-    esp_lcd_panel_io_tx_param(io, LCD_CMD_DISPON << 8, NULL, 0);
 
     return ESP_OK;
 }
@@ -272,15 +270,15 @@ static esp_err_t panel_nt35510_set_gap(esp_lcd_panel_t *panel, int x_gap, int y_
     return ESP_OK;
 }
 
-static esp_err_t panel_nt35510_disp_off(esp_lcd_panel_t *panel, bool off)
+static esp_err_t panel_nt35510_disp_on_off(esp_lcd_panel_t *panel, bool on_off)
 {
     nt35510_panel_t *nt35510 = __containerof(panel, nt35510_panel_t, base);
     esp_lcd_panel_io_handle_t io = nt35510->io;
     int command = 0;
-    if (off) {
-        command = LCD_CMD_DISPOFF;
-    } else {
+    if (on_off) {
         command = LCD_CMD_DISPON;
+    } else {
+        command = LCD_CMD_DISPOFF;
     }
     esp_lcd_panel_io_tx_param(io, command << 8, NULL, 0);
     return ESP_OK;

+ 7 - 2
components/esp_lcd/src/esp_lcd_panel_ops.c

@@ -58,8 +58,13 @@ esp_err_t esp_lcd_panel_invert_color(esp_lcd_panel_handle_t panel, bool invert_c
     return panel->invert_color(panel, invert_color_data);
 }
 
-esp_err_t esp_lcd_panel_disp_off(esp_lcd_panel_handle_t panel, bool off)
+esp_err_t esp_lcd_panel_disp_on_off(esp_lcd_panel_handle_t panel, bool on_off)
 {
     ESP_RETURN_ON_FALSE(panel, ESP_ERR_INVALID_ARG, TAG, "invalid panel handle");
-    return panel->disp_off(panel, off);
+    return panel->disp_on_off(panel, on_off);
+}
+
+esp_err_t esp_lcd_panel_disp_off(esp_lcd_panel_handle_t panel, bool off)
+{
+    return esp_lcd_panel_disp_on_off(panel, !off);
 }

+ 8 - 9
components/esp_lcd/src/esp_lcd_panel_ssd1306.c

@@ -46,7 +46,7 @@ static esp_err_t panel_ssd1306_invert_color(esp_lcd_panel_t *panel, bool invert_
 static esp_err_t panel_ssd1306_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y);
 static esp_err_t panel_ssd1306_swap_xy(esp_lcd_panel_t *panel, bool swap_axes);
 static esp_err_t panel_ssd1306_set_gap(esp_lcd_panel_t *panel, int x_gap, int y_gap);
-static esp_err_t panel_ssd1306_disp_off(esp_lcd_panel_t *panel, bool off);
+static esp_err_t panel_ssd1306_disp_on_off(esp_lcd_panel_t *panel, bool off);
 
 typedef struct {
     esp_lcd_panel_t base;
@@ -91,7 +91,7 @@ esp_err_t esp_lcd_new_panel_ssd1306(const esp_lcd_panel_io_handle_t io, const es
     ssd1306->base.set_gap = panel_ssd1306_set_gap;
     ssd1306->base.mirror = panel_ssd1306_mirror;
     ssd1306->base.swap_xy = panel_ssd1306_swap_xy;
-    ssd1306->base.disp_off = panel_ssd1306_disp_off;
+    ssd1306->base.disp_on_off = panel_ssd1306_disp_on_off;
     *ret_panel = &(ssd1306->base);
     ESP_LOGD(TAG, "new ssd1306 panel @%p", ssd1306);
 
@@ -144,9 +144,6 @@ static esp_err_t panel_ssd1306_init(esp_lcd_panel_t *panel)
     esp_lcd_panel_io_tx_param(io, SSD1306_CMD_SET_CHARGE_PUMP, (uint8_t[]) {
         0x14 // enable charge pump
     }, 1);
-    esp_lcd_panel_io_tx_param(io, SSD1306_CMD_DISP_ON, NULL, 0);
-    // SEG/COM will be ON after 100ms after sending DISP_ON command
-    vTaskDelay(pdMS_TO_TICKS(100));
     return ESP_OK;
 }
 
@@ -227,16 +224,18 @@ static esp_err_t panel_ssd1306_set_gap(esp_lcd_panel_t *panel, int x_gap, int y_
     return ESP_OK;
 }
 
-static esp_err_t panel_ssd1306_disp_off(esp_lcd_panel_t *panel, bool off)
+static esp_err_t panel_ssd1306_disp_on_off(esp_lcd_panel_t *panel, bool on_off)
 {
     ssd1306_panel_t *ssd1306 = __containerof(panel, ssd1306_panel_t, base);
     esp_lcd_panel_io_handle_t io = ssd1306->io;
     int command = 0;
-    if (off) {
-        command = SSD1306_CMD_DISP_OFF;
-    } else {
+    if (on_off) {
         command = SSD1306_CMD_DISP_ON;
+    } else {
+        command = SSD1306_CMD_DISP_OFF;
     }
     esp_lcd_panel_io_tx_param(io, command, NULL, 0);
+    // SEG/COM will be ON/OFF after 100ms after sending DISP_ON/OFF command
+    vTaskDelay(pdMS_TO_TICKS(100));
     return ESP_OK;
 }

+ 6 - 8
components/esp_lcd/src/esp_lcd_panel_st7789.c

@@ -33,7 +33,7 @@ static esp_err_t panel_st7789_invert_color(esp_lcd_panel_t *panel, bool invert_c
 static esp_err_t panel_st7789_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y);
 static esp_err_t panel_st7789_swap_xy(esp_lcd_panel_t *panel, bool swap_axes);
 static esp_err_t panel_st7789_set_gap(esp_lcd_panel_t *panel, int x_gap, int y_gap);
-static esp_err_t panel_st7789_disp_off(esp_lcd_panel_t *panel, bool off);
+static esp_err_t panel_st7789_disp_on_off(esp_lcd_panel_t *panel, bool off);
 
 typedef struct {
     esp_lcd_panel_t base;
@@ -102,7 +102,7 @@ esp_err_t esp_lcd_new_panel_st7789(const esp_lcd_panel_io_handle_t io, const esp
     st7789->base.set_gap = panel_st7789_set_gap;
     st7789->base.mirror = panel_st7789_mirror;
     st7789->base.swap_xy = panel_st7789_swap_xy;
-    st7789->base.disp_off = panel_st7789_disp_off;
+    st7789->base.disp_on_off = panel_st7789_disp_on_off;
     *ret_panel = &(st7789->base);
     ESP_LOGD(TAG, "new st7789 panel @%p", st7789);
 
@@ -162,8 +162,6 @@ static esp_err_t panel_st7789_init(esp_lcd_panel_t *panel)
     esp_lcd_panel_io_tx_param(io, LCD_CMD_COLMOD, (uint8_t[]) {
         st7789->colmod_cal,
     }, 1);
-    // turn on display
-    esp_lcd_panel_io_tx_param(io, LCD_CMD_DISPON, NULL, 0);
 
     return ESP_OK;
 }
@@ -256,15 +254,15 @@ static esp_err_t panel_st7789_set_gap(esp_lcd_panel_t *panel, int x_gap, int y_g
     return ESP_OK;
 }
 
-static esp_err_t panel_st7789_disp_off(esp_lcd_panel_t *panel, bool off)
+static esp_err_t panel_st7789_disp_on_off(esp_lcd_panel_t *panel, bool on_off)
 {
     st7789_panel_t *st7789 = __containerof(panel, st7789_panel_t, base);
     esp_lcd_panel_io_handle_t io = st7789->io;
     int command = 0;
-    if (off) {
-        command = LCD_CMD_DISPOFF;
-    } else {
+    if (on_off) {
         command = LCD_CMD_DISPON;
+    } else {
+        command = LCD_CMD_DISPOFF;
     }
     esp_lcd_panel_io_tx_param(io, command, NULL, 0);
     return ESP_OK;

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

@@ -60,7 +60,7 @@ static esp_err_t rgb_panel_invert_color(esp_lcd_panel_t *panel, bool invert_colo
 static esp_err_t rgb_panel_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y);
 static esp_err_t rgb_panel_swap_xy(esp_lcd_panel_t *panel, bool swap_axes);
 static esp_err_t rgb_panel_set_gap(esp_lcd_panel_t *panel, int x_gap, int y_gap);
-static esp_err_t rgb_panel_disp_off(esp_lcd_panel_t *panel, bool off);
+static esp_err_t rgb_panel_disp_on_off(esp_lcd_panel_t *panel, bool off);
 static esp_err_t lcd_rgb_panel_select_periph_clock(esp_rgb_panel_t *panel, lcd_clock_source_t clk_src);
 static esp_err_t lcd_rgb_panel_create_trans_link(esp_rgb_panel_t *panel);
 static esp_err_t lcd_rgb_panel_configure_gpio(esp_rgb_panel_t *panel, const esp_lcd_rgb_panel_config_t *panel_config);
@@ -190,7 +190,7 @@ esp_err_t esp_lcd_new_rgb_panel(const esp_lcd_rgb_panel_config_t *rgb_panel_conf
     rgb_panel->base.reset = rgb_panel_reset;
     rgb_panel->base.init = rgb_panel_init;
     rgb_panel->base.draw_bitmap = rgb_panel_draw_bitmap;
-    rgb_panel->base.disp_off = rgb_panel_disp_off;
+    rgb_panel->base.disp_on_off = rgb_panel_disp_on_off;
     rgb_panel->base.invert_color = rgb_panel_invert_color;
     rgb_panel->base.mirror = rgb_panel_mirror;
     rgb_panel->base.swap_xy = rgb_panel_swap_xy;
@@ -374,13 +374,13 @@ static esp_err_t rgb_panel_set_gap(esp_lcd_panel_t *panel, int x_gap, int y_gap)
     return ESP_OK;
 }
 
-static esp_err_t rgb_panel_disp_off(esp_lcd_panel_t *panel, bool off)
+static esp_err_t rgb_panel_disp_on_off(esp_lcd_panel_t *panel, bool on_off)
 {
     esp_rgb_panel_t *rgb_panel = __containerof(panel, esp_rgb_panel_t, base);
     if (rgb_panel->disp_gpio_num < 0) {
         return ESP_ERR_NOT_SUPPORTED;
     }
-    if (off) { // turn off screen
+    if (!on_off) { // turn off screen
         gpio_set_level(rgb_panel->disp_gpio_num, !rgb_panel->flags.disp_en_level);
     } else { // turn on screen
         gpio_set_level(rgb_panel->disp_gpio_num, rgb_panel->flags.disp_en_level);

+ 2 - 0
components/esp_lcd/test_apps/i2c_lcd/main/test_i2c_lcd_panel.c

@@ -56,6 +56,8 @@ TEST_CASE("lcd_panel_with_i2c_interface_(ssd1306)", "[lcd]")
     TEST_ESP_OK(esp_lcd_new_panel_ssd1306(io_handle, &panel_config, &panel_handle));
     TEST_ESP_OK(esp_lcd_panel_reset(panel_handle));
     TEST_ESP_OK(esp_lcd_panel_init(panel_handle));
+    // turn on display
+    TEST_ESP_OK(esp_lcd_panel_disp_on_off(panel_handle, true));
 
     for (int i = 0; i < TEST_LCD_H_RES / 16; i++) {
         for (int j = 0; j < TEST_LCD_V_RES / 8; j++) {

+ 4 - 1
components/esp_lcd/test_apps/i80_lcd/main/test_i80_lcd_panel.c

@@ -437,6 +437,8 @@ TEST_CASE("lcd_panel_with_i80_interface_(st7789, 8bits)", "[lcd]")
     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 display
+    esp_lcd_panel_disp_on_off(panel_handle, true);
     // turn on backlight
     gpio_set_level(TEST_LCD_BK_LIGHT_GPIO, 1);
 
@@ -447,7 +449,8 @@ TEST_CASE("lcd_panel_with_i80_interface_(st7789, 8bits)", "[lcd]")
         memset(img, color_byte, TEST_IMG_SIZE);
         esp_lcd_panel_draw_bitmap(panel_handle, x_start, y_start, x_start + 100, y_start + 100, img);
     }
-    esp_lcd_panel_disp_off(panel_handle, true); // turn off screen
+    // turn off screen
+    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));

+ 3 - 1
components/esp_lcd/test_apps/spi_lcd/main/test_spi_lcd_panel.c

@@ -79,6 +79,8 @@ static void lcd_panel_test(esp_lcd_panel_io_handle_t io_handle, esp_lcd_panel_ha
     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 display
+    esp_lcd_panel_disp_on_off(panel_handle, true);
     // turn on backlight
     gpio_set_level(TEST_LCD_BK_LIGHT_GPIO, 1);
 
@@ -90,7 +92,7 @@ static void lcd_panel_test(esp_lcd_panel_io_handle_t io_handle, esp_lcd_panel_ha
         esp_lcd_panel_draw_bitmap(panel_handle, x_start, y_start, x_start + 200, y_start + 200, img);
     }
     // turn off screen
-    esp_lcd_panel_disp_off(panel_handle, true);
+    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));

+ 13 - 1
components/hal/esp32/include/hal/rmt_ll.h

@@ -459,7 +459,19 @@ static inline uint32_t rmt_ll_tx_get_interrupt_status(rmt_dev_t *dev, uint32_t c
  */
 static inline uint32_t rmt_ll_tx_get_interrupt_status_raw(rmt_dev_t *dev, uint32_t channel)
 {
-    return dev->int_raw.val & RMT_LL_EVENT_TX_MASK(channel);
+    return dev->int_raw.val & (RMT_LL_EVENT_TX_MASK(channel) | RMT_LL_EVENT_TX_ERROR(channel));
+}
+
+/**
+ * @brief Get interrupt raw status for RX channel
+ *
+ * @param dev Peripheral instance address
+ * @param channel RMT RX channel number
+ * @return Interrupt raw status
+ */
+static inline uint32_t rmt_ll_rx_get_interrupt_status_raw(rmt_dev_t *dev, uint32_t channel)
+{
+    return dev->int_raw.val & (RMT_LL_EVENT_RX_MASK(channel) | RMT_LL_EVENT_RX_ERROR(channel));
 }
 
 /**

+ 13 - 1
components/hal/esp32c3/include/hal/rmt_ll.h

@@ -637,7 +637,19 @@ static inline uint32_t rmt_ll_tx_get_interrupt_status(rmt_dev_t *dev, uint32_t c
  */
 static inline uint32_t rmt_ll_tx_get_interrupt_status_raw(rmt_dev_t *dev, uint32_t channel)
 {
-    return dev->int_raw.val & RMT_LL_EVENT_TX_MASK(channel);
+    return dev->int_raw.val & (RMT_LL_EVENT_TX_MASK(channel) | RMT_LL_EVENT_TX_ERROR(channel));
+}
+
+/**
+ * @brief Get interrupt raw status for RX channel
+ *
+ * @param dev Peripheral instance address
+ * @param channel RMT RX channel number
+ * @return Interrupt raw status
+ */
+static inline uint32_t rmt_ll_rx_get_interrupt_status_raw(rmt_dev_t *dev, uint32_t channel)
+{
+    return dev->int_raw.val & (RMT_LL_EVENT_RX_MASK(channel) | RMT_LL_EVENT_RX_ERROR(channel));
 }
 
 /**

+ 13 - 1
components/hal/esp32h2/include/hal/rmt_ll.h

@@ -637,7 +637,19 @@ static inline uint32_t rmt_ll_tx_get_interrupt_status(rmt_dev_t *dev, uint32_t c
  */
 static inline uint32_t rmt_ll_tx_get_interrupt_status_raw(rmt_dev_t *dev, uint32_t channel)
 {
-    return dev->int_raw.val & RMT_LL_EVENT_TX_MASK(channel);
+    return dev->int_raw.val & (RMT_LL_EVENT_TX_MASK(channel) | RMT_LL_EVENT_TX_ERROR(channel));
+}
+
+/**
+ * @brief Get interrupt raw status for RX channel
+ *
+ * @param dev Peripheral instance address
+ * @param channel RMT RX channel number
+ * @return Interrupt raw status
+ */
+static inline uint32_t rmt_ll_rx_get_interrupt_status_raw(rmt_dev_t *dev, uint32_t channel)
+{
+    return dev->int_raw.val & (RMT_LL_EVENT_RX_MASK(channel) | RMT_LL_EVENT_RX_ERROR(channel));
 }
 
 /**

+ 13 - 1
components/hal/esp32s2/include/hal/rmt_ll.h

@@ -600,7 +600,19 @@ static inline uint32_t rmt_ll_tx_get_interrupt_status(rmt_dev_t *dev, uint32_t c
  */
 static inline uint32_t rmt_ll_tx_get_interrupt_status_raw(rmt_dev_t *dev, uint32_t channel)
 {
-    return dev->int_raw.val & RMT_LL_EVENT_TX_MASK(channel);
+    return dev->int_raw.val & (RMT_LL_EVENT_TX_MASK(channel) | RMT_LL_EVENT_TX_ERROR(channel));
+}
+
+/**
+ * @brief Get interrupt raw status for RX channel
+ *
+ * @param dev Peripheral instance address
+ * @param channel RMT RX channel number
+ * @return Interrupt raw status
+ */
+static inline uint32_t rmt_ll_rx_get_interrupt_status_raw(rmt_dev_t *dev, uint32_t channel)
+{
+    return dev->int_raw.val & (RMT_LL_EVENT_RX_MASK(channel) | RMT_LL_EVENT_RX_ERROR(channel));
 }
 
 /**

+ 13 - 1
components/hal/esp32s3/include/hal/rmt_ll.h

@@ -674,7 +674,19 @@ static inline uint32_t rmt_ll_tx_get_interrupt_status(rmt_dev_t *dev, uint32_t c
  */
 static inline uint32_t rmt_ll_tx_get_interrupt_status_raw(rmt_dev_t *dev, uint32_t channel)
 {
-    return dev->int_raw.val & RMT_LL_EVENT_TX_MASK(channel);
+    return dev->int_raw.val & (RMT_LL_EVENT_TX_MASK(channel) | RMT_LL_EVENT_TX_ERROR(channel));
+}
+
+/**
+ * @brief Get interrupt raw status for RX channel
+ *
+ * @param dev Peripheral instance address
+ * @param channel RMT RX channel number
+ * @return Interrupt raw status
+ */
+static inline uint32_t rmt_ll_rx_get_interrupt_status_raw(rmt_dev_t *dev, uint32_t channel)
+{
+    return dev->int_raw.val & (RMT_LL_EVENT_RX_MASK(channel) | RMT_LL_EVENT_RX_ERROR(channel));
 }
 
 /**

+ 1 - 0
components/heap/heap_caps.c

@@ -574,6 +574,7 @@ void heap_caps_dump_all(void)
 size_t heap_caps_get_allocated_size( void *ptr )
 {
     heap_t *heap = find_containing_heap(ptr);
+    assert(heap);
     size_t size = multi_heap_get_allocated_size(heap->heap, ptr);
     return size;
 }

+ 4 - 0
components/soc/esp32/include/soc/Kconfig.soc_caps.in

@@ -431,6 +431,10 @@ config SOC_RMT_SUPPORT_REF_TICK
     bool
     default y
 
+config SOC_RMT_SUPPORT_APB
+    bool
+    default y
+
 config SOC_RMT_CHANNEL_CLK_INDEPENDENT
     bool
     default y

+ 2 - 1
components/soc/esp32/include/soc/soc_caps.h

@@ -68,7 +68,7 @@
 #define SOC_MCPWM_SUPPORTED         1
 #define SOC_SDMMC_HOST_SUPPORTED    1
 #define SOC_BT_SUPPORTED            1
-#define SOC_BLUEDROID_SUPPORTED	    1
+#define SOC_BLUEDROID_SUPPORTED     1
 #define SOC_CLASSIC_BT_SUPPORTED    1
 #define SOC_PCNT_SUPPORTED          1
 #define SOC_WIFI_SUPPORTED          1
@@ -238,6 +238,7 @@
 #define SOC_RMT_CHANNELS_PER_GROUP      8  /*!< Total 8 channels */
 #define SOC_RMT_MEM_WORDS_PER_CHANNEL   64 /*!< Each channel owns 64 words memory */
 #define SOC_RMT_SUPPORT_REF_TICK        1  /*!< Support set REF_TICK as the RMT clock source */
+#define SOC_RMT_SUPPORT_APB             1  /*!< Support set APB as the RMT clock source */
 #define SOC_RMT_CHANNEL_CLK_INDEPENDENT 1  /*!< Can select different source clock for each channel */
 
 /*-------------------------- RTCIO CAPS --------------------------------------*/

+ 8 - 0
components/soc/esp32c3/include/soc/Kconfig.soc_caps.in

@@ -423,6 +423,14 @@ config SOC_RMT_SUPPORT_XTAL
     bool
     default y
 
+config SOC_RMT_SUPPORT_APB
+    bool
+    default y
+
+config SOC_RMT_SUPPORT_RC_FAST
+    bool
+    default y
+
 config SOC_RTC_CNTL_CPU_PD_DMA_BUS_WIDTH
     int
     default 128

+ 2 - 0
components/soc/esp32c3/include/soc/soc_caps.h

@@ -197,6 +197,8 @@
 #define SOC_RMT_SUPPORT_TX_SYNCHRO            1  /*!< Support coordinate a group of TX channels to start simultaneously */
 #define SOC_RMT_SUPPORT_TX_CARRIER_ALWAYS_ON  1  /*!< TX carrier can be modulated all the time */
 #define SOC_RMT_SUPPORT_XTAL                  1  /*!< Support set XTAL clock as the RMT clock source */
+#define SOC_RMT_SUPPORT_APB                   1  /*!< Support set APB as the RMT clock source */
+#define SOC_RMT_SUPPORT_RC_FAST               1  /*!< Support set RC_FAST clock as the RMT clock source */
 
 /*-------------------------- RTC CAPS --------------------------------------*/
 #define SOC_RTC_CNTL_CPU_PD_DMA_BUS_WIDTH       (128)

+ 8 - 0
components/soc/esp32h2/include/soc/Kconfig.soc_caps.in

@@ -415,6 +415,14 @@ config SOC_RMT_SUPPORT_XTAL
     bool
     default y
 
+config SOC_RMT_SUPPORT_AHB
+    bool
+    default y
+
+config SOC_RMT_SUPPORT_RC_FAST
+    bool
+    default y
+
 config SOC_RTC_CNTL_CPU_PD_DMA_BUS_WIDTH
     int
     default 128

+ 3 - 1
components/soc/esp32h2/include/soc/soc_caps.h

@@ -40,7 +40,7 @@
 #define SOC_TWAI_SUPPORTED              1
 #define SOC_BT_SUPPORTED                1
 #define SOC_BLUEDROID_SUPPORTED                0
-#define SOC_ESP_NIMBLE_CONTROLLER	1
+#define SOC_ESP_NIMBLE_CONTROLLER   1
 #define SOC_ASYNC_MEMCPY_SUPPORTED      1
 #define SOC_USB_SERIAL_JTAG_SUPPORTED   1
 #define SOC_SUPPORTS_SECURE_DL_MODE         1
@@ -208,6 +208,8 @@
 #define SOC_RMT_SUPPORT_TX_SYNCHRO            1  /*!< Support coordinate a group of TX channels to start simultaneously */
 #define SOC_RMT_SUPPORT_TX_CARRIER_ALWAYS_ON  1  /*!< TX carrier can be modulated all the time */
 #define SOC_RMT_SUPPORT_XTAL                  1  /*!< Support set XTAL clock as the RMT clock source */
+#define SOC_RMT_SUPPORT_AHB                   1  /*!< Support set AHB clock as the RMT clock source */
+#define SOC_RMT_SUPPORT_RC_FAST               1  /*!< Support set RC_FAST clock as the RMT clock source */
 
 /*-------------------------- RTC CAPS --------------------------------------*/
 #define SOC_RTC_CNTL_CPU_PD_DMA_BUS_WIDTH       (128)

+ 4 - 0
components/soc/esp32s2/include/soc/Kconfig.soc_caps.in

@@ -463,6 +463,10 @@ config SOC_RMT_SUPPORT_REF_TICK
     bool
     default y
 
+config SOC_RMT_SUPPORT_APB
+    bool
+    default y
+
 config SOC_RMT_CHANNEL_CLK_INDEPENDENT
     bool
     default y

+ 1 - 0
components/soc/esp32s2/include/soc/soc_caps.h

@@ -216,6 +216,7 @@
 #define SOC_RMT_SUPPORT_TX_SYNCHRO            1  /*!< Support coordinate a group of TX channels to start simultaneously */
 #define SOC_RMT_SUPPORT_TX_CARRIER_ALWAYS_ON  1  /*!< TX carrier can be modulated all the time */
 #define SOC_RMT_SUPPORT_REF_TICK              1  /*!< Support set REF_TICK as the RMT clock source */
+#define SOC_RMT_SUPPORT_APB                   1  /*!< Support set APB as the RMT clock source */
 #define SOC_RMT_CHANNEL_CLK_INDEPENDENT       1  /*!< Can select different source clock for each channel */
 
 /*-------------------------- RTCIO CAPS --------------------------------------*/

+ 8 - 0
components/soc/esp32s3/include/soc/Kconfig.soc_caps.in

@@ -515,6 +515,14 @@ config SOC_RMT_SUPPORT_XTAL
     bool
     default y
 
+config SOC_RMT_SUPPORT_RC_FAST
+    bool
+    default y
+
+config SOC_RMT_SUPPORT_APB
+    bool
+    default y
+
 config SOC_RMT_SUPPORT_DMA
     bool
     default y

+ 2 - 0
components/soc/esp32s3/include/soc/soc_caps.h

@@ -208,6 +208,8 @@
 #define SOC_RMT_SUPPORT_TX_SYNCHRO            1  /*!< Support coordinate a group of TX channels to start simultaneously */
 #define SOC_RMT_SUPPORT_TX_CARRIER_ALWAYS_ON  1  /*!< TX carrier can be modulated all the time */
 #define SOC_RMT_SUPPORT_XTAL                  1  /*!< Support set XTAL clock as the RMT clock source */
+#define SOC_RMT_SUPPORT_RC_FAST               1  /*!< Support set RC_FAST clock as the RMT clock source */
+#define SOC_RMT_SUPPORT_APB                   1  /*!< Support set APB as the RMT clock source */
 #define SOC_RMT_SUPPORT_DMA                   1  /*!< RMT peripheral can connect to DMA channel */
 
 /*-------------------------- LCD CAPS ----------------------------------------*/

+ 6 - 0
docs/en/migration-guides/peripherals.rst

@@ -116,3 +116,9 @@ I2C
     - ``rmt_set_intr_enable_mask`` and ``rmt_clr_intr_enable_mask`` are removed, as the interrupt is handled by the driver, user doesn't need to take care of it.
     - ``rmt_set_pin`` is removed, as ``rmt_set_gpio`` can do the same thing.
     - ``rmt_memory_rw_rst`` is removed, user can use ``rmt_tx_memory_reset`` and ``rmt_rx_memory_reset`` for TX and RX channel respectively.
+
+LCD
+---
+
+- The LCD panel initialization flow is slightly changed. Now the :cpp:func:`esp_lcd_panel_init` won't turn on the display automatically. User needs to call :cpp:func:`esp_lcd_panel_disp_on_off` to manually turn on the display. Note, this is different from turning on backlight. With this breaking change, user can flush a predefined pattern to the screen before turning on the screen. This can help avoid random noise on the screen after a power on reset.
+- :cpp:func:`esp_lcd_panel_disp_off` is deprecated, please use :cpp:func:`esp_lcd_panel_disp_on_off` instead.

+ 7 - 9
examples/peripherals/lcd/gc9a01/main/esp_lcd_panel_gc9a01.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
  */
@@ -27,7 +27,7 @@ static esp_err_t panel_gc9a01_invert_color(esp_lcd_panel_t *panel, bool invert_c
 static esp_err_t panel_gc9a01_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y);
 static esp_err_t panel_gc9a01_swap_xy(esp_lcd_panel_t *panel, bool swap_axes);
 static esp_err_t panel_gc9a01_set_gap(esp_lcd_panel_t *panel, int x_gap, int y_gap);
-static esp_err_t panel_gc9a01_disp_off(esp_lcd_panel_t *panel, bool off);
+static esp_err_t panel_gc9a01_disp_on_off(esp_lcd_panel_t *panel, bool off);
 
 typedef struct {
     esp_lcd_panel_t base;
@@ -93,7 +93,7 @@ esp_err_t esp_lcd_new_panel_gc9a01(const esp_lcd_panel_io_handle_t io, const esp
     gc9a01->base.set_gap = panel_gc9a01_set_gap;
     gc9a01->base.mirror = panel_gc9a01_mirror;
     gc9a01->base.swap_xy = panel_gc9a01_swap_xy;
-    gc9a01->base.disp_off = panel_gc9a01_disp_off;
+    gc9a01->base.disp_on_off = panel_gc9a01_disp_on_off;
     *ret_panel = &(gc9a01->base);
     ESP_LOGD(TAG, "new gc9a01 panel @%p", gc9a01);
 
@@ -217,8 +217,6 @@ static esp_err_t panel_gc9a01_init(esp_lcd_panel_t *panel)
         cmd++;
     }
 
-    // turn on display
-    esp_lcd_panel_io_tx_param(io, LCD_CMD_DISPON, NULL, 0);
     return ESP_OK;
 }
 
@@ -310,15 +308,15 @@ static esp_err_t panel_gc9a01_set_gap(esp_lcd_panel_t *panel, int x_gap, int y_g
     return ESP_OK;
 }
 
-static esp_err_t panel_gc9a01_disp_off(esp_lcd_panel_t *panel, bool off)
+static esp_err_t panel_gc9a01_disp_on_off(esp_lcd_panel_t *panel, bool on_off)
 {
     gc9a01_panel_t *gc9a01 = __containerof(panel, gc9a01_panel_t, base);
     esp_lcd_panel_io_handle_t io = gc9a01->io;
     int command = 0;
-    if (off) {
-        command = LCD_CMD_DISPOFF;
-    } else {
+    if (on_off) {
         command = LCD_CMD_DISPON;
+    } else {
+        command = LCD_CMD_DISPOFF;
     }
     esp_lcd_panel_io_tx_param(io, command, NULL, 0);
     return ESP_OK;

+ 3 - 0
examples/peripherals/lcd/gc9a01/main/gc9a01_example_main.c

@@ -124,6 +124,9 @@ void app_main(void)
     ESP_ERROR_CHECK(esp_lcd_panel_invert_color(panel_handle, true));
     ESP_ERROR_CHECK(esp_lcd_panel_mirror(panel_handle, true, false));
 
+    // user can flush pre-defined pattern to the screen before we turn on the screen or backlight
+    ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel_handle, true));
+
     ESP_LOGI(TAG, "Turn on LCD backlight");
     gpio_set_level(EXAMPLE_PIN_NUM_BK_LIGHT, EXAMPLE_LCD_BK_LIGHT_ON_LEVEL);
 

+ 1 - 0
examples/peripherals/lcd/i2c_oled/main/i2c_oled_example_main.c

@@ -124,6 +124,7 @@ void app_main(void)
 
     ESP_ERROR_CHECK(esp_lcd_panel_reset(panel_handle));
     ESP_ERROR_CHECK(esp_lcd_panel_init(panel_handle));
+    ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel_handle, true));
 
     ESP_LOGI(TAG, "Initialize LVGL library");
     lv_init();

+ 3 - 0
examples/peripherals/lcd/i80_controller/main/i80_controller_example_main.c

@@ -191,6 +191,9 @@ void app_main(void)
     // 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);
 
+    // user can flush pre-defined pattern to the screen before we turn on the screen or backlight
+    ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel_handle, true));
+
     ESP_LOGI(TAG, "Turn on LCD backlight");
     gpio_set_level(EXAMPLE_PIN_NUM_BK_LIGHT, EXAMPLE_LCD_BK_LIGHT_ON_LEVEL);
 

+ 3 - 0
examples/peripherals/lcd/tjpgd/main/lcd_tjpgd_example_main.c

@@ -145,6 +145,9 @@ void app_main(void)
     // Initialize LCD panel
     ESP_ERROR_CHECK(esp_lcd_panel_init(panel_handle));
 
+    // Turn on the screen
+    ESP_ERROR_CHECK(esp_lcd_panel_disp_on_off(panel_handle, true));
+
     // Swap x and y axis (Different LCD screens may need different options)
     ESP_ERROR_CHECK(esp_lcd_panel_swap_xy(panel_handle, true));