From 476004e4b8f22e9e000706b5117cb9fb2a0bb380 Mon Sep 17 00:00:00 2001 From: Song Ruo Jing Date: Mon, 9 Feb 2026 15:18:14 +0800 Subject: [PATCH] fix(gpio): add esp_gpio_reserve check to gpio_config --- components/esp_driver_gpio/src/gpio.c | 30 +++++++++++++++++++ .../test_apps/gpio/main/test_gpio.c | 30 +++++-------------- .../test_apps/gpio/main/test_rtcio.c | 1 + .../gpio_extensions/main/test_gpio_etm.c | 9 +++++- .../gpio_extensions/main/test_gpio_filter.c | 1 + .../gpio_extensions/main/test_hysteresis.c | 2 ++ .../test_apps/gptimer/main/test_gptimer_etm.c | 17 ++++++++++- .../gptimer/main/test_gptimer_sleep.c | 1 + .../test_apps/i2s/main/test_i2s_etm.c | 9 +++++- .../test_apps/parlio/main/test_parlio_rx.c | 13 ++++---- .../pulse_cnt/main/test_pulse_cnt_simulator.c | 1 + .../test_apps/rmt/main/test_rmt_cache_safe.c | 1 + .../test_apps/rmt/main/test_rmt_rx.c | 1 + .../esp_hal_gpio/esp32/include/hal/gpio_ll.h | 15 +++++++++- .../esp32c2/include/hal/gpio_ll.h | 15 +++++++++- .../esp32c3/include/hal/gpio_ll.h | 15 +++++++++- .../esp32c5/include/hal/gpio_ll.h | 15 +++++++++- .../esp32c6/include/hal/gpio_ll.h | 15 +++++++++- .../esp32c61/include/hal/gpio_ll.h | 15 +++++++++- .../esp32h2/include/hal/gpio_ll.h | 15 +++++++++- .../esp32h21/include/hal/gpio_ll.h | 15 +++++++++- .../esp32h4/include/hal/gpio_ll.h | 14 ++++++++- .../esp32p4/include/hal/gpio_ll.h | 15 +++++++++- .../esp32s2/include/hal/gpio_ll.h | 13 ++++++++ .../esp32s3/include/hal/gpio_ll.h | 13 ++++++++ .../esp32s31/include/hal/gpio_ll.h | 13 ++++++++ .../esp_hal_gpio/include/hal/gpio_hal.h | 11 ++++++- .../spi_lcd/main/test_spi_lcd_panel.c | 7 ++++- 28 files changed, 278 insertions(+), 44 deletions(-) diff --git a/components/esp_driver_gpio/src/gpio.c b/components/esp_driver_gpio/src/gpio.c index 63e106e94f..4928348175 100644 --- a/components/esp_driver_gpio/src/gpio.c +++ b/components/esp_driver_gpio/src/gpio.c @@ -364,6 +364,36 @@ esp_err_t gpio_config(const gpio_config_t *pGPIOConfig) do { if (((gpio_pin_mask >> io_num) & BIT(0))) { + // This function will set the pin to a certain mode, instead of adding new modes to current status + // If GPIO_MODE_DEF_OUTPUT flag is not set, output will be disabled; Same for GPIO_MODE_DEF_INPUT flag + // Also the func sel will always be set to GPIO function in this function + // so IO conflict check is tight here + uint64_t bit_mask = BIT64(io_num); + bool conflict = false; + // No need to reserve any pin for reading pad level (and do input check first, since output needs reserve IO which will make esp_gpio_is_reserved return true) + // but if the pin has been used as an IOMUX input, neither it can be configured to GPIO function, nor input can be disabled + if (esp_gpio_is_reserved(bit_mask) && gpio_hal_input_is_enabled(gpio_context.gpio_hal, io_num)) { + conflict = true; + } + // Currently, we have no way to know if an IO has been used as a GPIO matrix input (no reserve for this case), + // so we cannot check such case and skip if input will be disabled + if ((pGPIOConfig->mode) & GPIO_MODE_DEF_OUTPUT) { + // need to reserve the pin if it is used as an output + uint64_t old_busy_mask = esp_gpio_reserve(bit_mask); + if (old_busy_mask & bit_mask) { + conflict = true; + } + } else { + // gpio output will be disabled, so should skip for any reserved output pins + if (esp_gpio_is_reserved(bit_mask) && !gpio_hal_input_is_enabled(gpio_context.gpio_hal, io_num)) { + conflict = true; + } + } + if (conflict) { + ESP_LOGW(GPIO_TAG, "conflict found for GPIO[%"PRIu32"]", io_num); + // Right now, we just give a warning + // Later, we should skip the pin and continue with the next one + } #if SOC_RTCIO_PIN_COUNT > 0 if (rtc_gpio_is_valid_gpio(io_num)) { diff --git a/components/esp_driver_gpio/test_apps/gpio/main/test_gpio.c b/components/esp_driver_gpio/test_apps/gpio/main/test_gpio.c index 706e355bc9..851c7e9e28 100644 --- a/components/esp_driver_gpio/test_apps/gpio/main/test_gpio.c +++ b/components/esp_driver_gpio/test_apps/gpio/main/test_gpio.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -50,6 +50,7 @@ static volatile int edge_intr_times = 0; // use this to get how many times the static gpio_config_t test_init_io(gpio_num_t num) { TEST_ASSERT(GPIO_IS_VALID_OUTPUT_GPIO(num)); + TEST_ESP_OK(gpio_reset_pin(num)); gpio_config_t io_conf = { .intr_type = GPIO_INTR_DISABLE, .mode = GPIO_MODE_OUTPUT, @@ -808,13 +809,8 @@ TEST_CASE("GPIO_input_and_output_of_USB_pins_test", "[gpio]") for (int i = 0; i < sizeof(test_pins) / sizeof(int); i++) { int pin = test_pins[i]; - gpio_config_t io_conf = { - .intr_type = GPIO_INTR_DISABLE, - .mode = GPIO_MODE_INPUT_OUTPUT, - .pin_bit_mask = BIT64(pin), - .pull_down_en = GPIO_PULLDOWN_DISABLE, - .pull_up_en = GPIO_PULLUP_DISABLE, - }; + gpio_config_t io_conf = test_init_io(pin); + io_conf.mode = GPIO_MODE_INPUT_OUTPUT; gpio_config(&io_conf); // test pin @@ -893,13 +889,8 @@ static void gpio_deep_sleep_hold_test_first_stage(void) TEST_ESP_OK(esp_sleep_enable_timer_wakeup(2000000)); - gpio_config_t io_conf = { - .intr_type = GPIO_INTR_DISABLE, - .mode = GPIO_MODE_INPUT_OUTPUT, - .pin_bit_mask = (1ULL << io_num), - .pull_down_en = GPIO_PULLDOWN_DISABLE, - .pull_up_en = GPIO_PULLUP_DISABLE, - }; + gpio_config_t io_conf = test_init_io(io_num); + io_conf.mode = GPIO_MODE_INPUT_OUTPUT; TEST_ESP_OK(gpio_config(&io_conf)); const bool initial_level = gpio_get_level(io_num); @@ -938,13 +929,8 @@ static void gpio_deep_sleep_hold_test_second_stage(void) #endif TEST_ESP_OK(gpio_hold_dis(io_num)); - gpio_config_t io_conf = { - .intr_type = GPIO_INTR_DISABLE, - .mode = GPIO_MODE_INPUT_OUTPUT, - .pin_bit_mask = (1ULL << io_num), - .pull_down_en = GPIO_PULLDOWN_DISABLE, - .pull_up_en = GPIO_PULLUP_DISABLE, - }; + gpio_config_t io_conf = test_init_io(io_num); + io_conf.mode = GPIO_MODE_INPUT_OUTPUT; TEST_ESP_OK(gpio_config(&io_conf)); #if !CONFIG_ESP32P4_SELECTS_REV_LESS_V3 // DIG-399 diff --git a/components/esp_driver_gpio/test_apps/gpio/main/test_rtcio.c b/components/esp_driver_gpio/test_apps/gpio/main/test_rtcio.c index bb7bbfa86c..4abca5361d 100644 --- a/components/esp_driver_gpio/test_apps/gpio/main/test_rtcio.c +++ b/components/esp_driver_gpio/test_apps/gpio/main/test_rtcio.c @@ -290,6 +290,7 @@ static void rtcio_deep_sleep_hold_test_first_stage(void) TEST_ESP_OK(esp_sleep_enable_timer_wakeup(2000000)); + gpio_reset_pin(io_num); gpio_config_t io_conf = { .intr_type = GPIO_INTR_DISABLE, .mode = GPIO_MODE_INPUT_OUTPUT, diff --git a/components/esp_driver_gpio/test_apps/gpio_extensions/main/test_gpio_etm.c b/components/esp_driver_gpio/test_apps/gpio_extensions/main/test_gpio_etm.c index 3abfb25655..065d76b8c7 100644 --- a/components/esp_driver_gpio/test_apps/gpio_extensions/main/test_gpio_etm.c +++ b/components/esp_driver_gpio/test_apps/gpio_extensions/main/test_gpio_etm.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -89,6 +89,9 @@ TEST_CASE("gpio_etm_self_trigger", "[gpio_etm]") TEST_ESP_OK(esp_etm_del_task(gpio_task)); TEST_ESP_OK(esp_etm_del_event(gpio_event)); TEST_ESP_OK(esp_etm_del_channel(etm_channel_a)); + + TEST_ESP_OK(gpio_reset_pin(output_gpio)); + TEST_ESP_OK(gpio_reset_pin(input_gpio)); } TEST_CASE("gpio_etm_self_trigger_multi_action", "[gpio_etm]") @@ -204,4 +207,8 @@ TEST_CASE("gpio_etm_self_trigger_multi_action", "[gpio_etm]") TEST_ESP_OK(esp_etm_del_event(gpio_event_b)); TEST_ESP_OK(esp_etm_del_channel(etm_channel_a)); TEST_ESP_OK(esp_etm_del_channel(etm_channel_b)); + + TEST_ESP_OK(gpio_reset_pin(output_gpio)); + TEST_ESP_OK(gpio_reset_pin(input_gpio1)); + TEST_ESP_OK(gpio_reset_pin(input_gpio2)); } diff --git a/components/esp_driver_gpio/test_apps/gpio_extensions/main/test_gpio_filter.c b/components/esp_driver_gpio/test_apps/gpio_extensions/main/test_gpio_filter.c index e85d42d19a..08dbda9841 100644 --- a/components/esp_driver_gpio/test_apps/gpio_extensions/main/test_gpio_filter.c +++ b/components/esp_driver_gpio/test_apps/gpio_extensions/main/test_gpio_filter.c @@ -180,6 +180,7 @@ TEST_CASE("GPIO flex glitch filter enable/disable", "[gpio_filter]") TEST_ESP_OK(gpio_del_glitch_filter(filter)); TEST_ESP_OK(dedic_gpio_del_bundle(bundle)); vSemaphoreDelete(sem); + TEST_ESP_OK(gpio_reset_pin(test_gpio)); } #endif // SOC_HAS(DEDICATED_GPIO) diff --git a/components/esp_driver_gpio/test_apps/gpio_extensions/main/test_hysteresis.c b/components/esp_driver_gpio/test_apps/gpio_extensions/main/test_hysteresis.c index 95680ecce3..1cc63ba8cd 100644 --- a/components/esp_driver_gpio/test_apps/gpio_extensions/main/test_hysteresis.c +++ b/components/esp_driver_gpio/test_apps/gpio_extensions/main/test_hysteresis.c @@ -69,6 +69,8 @@ TEST_CASE("GPIO Input hysteresis filter", "[gpio_filter][timeout=50][ignore]") gpio_isr_handler_remove(TEST_GPIO_HYS_IO); gpio_uninstall_isr_service(); + TEST_ESP_OK(gpio_reset_pin(TEST_GPIO_HYS_IO)); + TEST_ESP_OK(gpio_reset_pin(TEST_GPIO_WAVE_IO)); // should shot ISR exactly 10 times TEST_ASSERT_UINT32_WITHIN(1, 10, intr_cnt); } diff --git a/components/esp_driver_gptimer/test_apps/gptimer/main/test_gptimer_etm.c b/components/esp_driver_gptimer/test_apps/gptimer/main/test_gptimer_etm.c index 07def5904b..77ce1150f9 100644 --- a/components/esp_driver_gptimer/test_apps/gptimer/main/test_gptimer_etm.c +++ b/components/esp_driver_gptimer/test_apps/gptimer/main/test_gptimer_etm.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -99,6 +99,9 @@ TEST_CASE("gptimer_etm_alarm_event_with_interrupt_enabled", "[gptimer][etm]") TEST_ESP_OK(gptimer_disable(gptimer)); TEST_ESP_OK(gptimer_del_timer(gptimer)); + // reset gpio + TEST_ESP_OK(gpio_reset_pin(output_gpio)); + // delete etm primitives TEST_ESP_OK(gpio_etm_task_rm_gpio(gpio_task, output_gpio)); TEST_ESP_OK(esp_etm_del_task(gpio_task)); @@ -184,6 +187,9 @@ TEST_CASE("gptimer_etm_alarm_event_without_interrupt", "[gptimer][etm]") TEST_ESP_OK(gptimer_disable(gptimer)); TEST_ESP_OK(gptimer_del_timer(gptimer)); + // reset gpio + TEST_ESP_OK(gpio_reset_pin(output_gpio)); + // delete etm primitives TEST_ESP_OK(gpio_etm_task_rm_gpio(gpio_task, output_gpio)); TEST_ESP_OK(esp_etm_del_task(gpio_task)); @@ -282,6 +288,9 @@ TEST_CASE("gptimer_auto_reload_by_etm", "[gptimer][etm]") TEST_ESP_OK(gptimer_disable(gptimer)); TEST_ESP_OK(gptimer_del_timer(gptimer)); + // reset gpio + TEST_ESP_OK(gpio_reset_pin(output_gpio)); + // delete etm primitives TEST_ESP_OK(gpio_etm_task_rm_gpio(gpio_task, output_gpio)); TEST_ESP_OK(esp_etm_del_task(gpio_task)); @@ -366,6 +375,9 @@ TEST_CASE("gptimer_etm_task_capture", "[gptimer][etm]") TEST_ESP_OK(gptimer_disable(gptimer)); TEST_ESP_OK(gptimer_del_timer(gptimer)); + // reset gpio + TEST_ESP_OK(gpio_reset_pin(input_gpio)); + // delete etm primitives TEST_ESP_OK(esp_etm_del_task(gptimer_task)); TEST_ESP_OK(esp_etm_del_event(gpio_event)); @@ -458,6 +470,9 @@ TEST_CASE("gptimer_start_stop_by_etm_task", "[gptimer][etm]") TEST_ESP_OK(gptimer_disable(gptimer)); TEST_ESP_OK(gptimer_del_timer(gptimer)); + // reset gpio + TEST_ESP_OK(gpio_reset_pin(input_gpio)); + // delete etm primitives TEST_ESP_OK(esp_etm_del_task(gptimer_task_start)); TEST_ESP_OK(esp_etm_del_task(gptimer_task_stop)); diff --git a/components/esp_driver_gptimer/test_apps/gptimer/main/test_gptimer_sleep.c b/components/esp_driver_gptimer/test_apps/gptimer/main/test_gptimer_sleep.c index 83977a7cbc..49f7637cb1 100644 --- a/components/esp_driver_gptimer/test_apps/gptimer/main/test_gptimer_sleep.c +++ b/components/esp_driver_gptimer/test_apps/gptimer/main/test_gptimer_sleep.c @@ -238,6 +238,7 @@ static void test_gptimer_etm_sleep_retention(bool back_up_before_sleep) TEST_ESP_OK(esp_etm_del_event(gptimer_event)); TEST_ESP_OK(esp_etm_channel_disable(etm_channel_a)); TEST_ESP_OK(esp_etm_channel_disable(etm_channel_b)); + TEST_ESP_OK(gpio_reset_pin(output_gpio)); TEST_ESP_OK(esp_etm_del_channel(etm_channel_a)); TEST_ESP_OK(esp_etm_del_channel(etm_channel_b)); } diff --git a/components/esp_driver_i2s/test_apps/i2s/main/test_i2s_etm.c b/components/esp_driver_i2s/test_apps/i2s/main/test_i2s_etm.c index 01bf1cf806..f2f739e315 100644 --- a/components/esp_driver_i2s/test_apps/i2s/main/test_i2s_etm.c +++ b/components/esp_driver_i2s/test_apps/i2s/main/test_i2s_etm.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -90,6 +90,11 @@ static void s_gpio_init(void) TEST_ESP_OK(gpio_set_level(TEST_GPIO_ETM_NUM, 0)); } +static void s_gpio_deinit(void) +{ + TEST_ESP_OK(gpio_reset_pin(TEST_GPIO_ETM_NUM)); +} + TEST_CASE("i2s_etm_event_test", "[etm]") { uint32_t *buf = calloc(1, TEST_BUFF_SIZE); @@ -150,6 +155,7 @@ TEST_CASE("i2s_etm_event_test", "[etm]") TEST_ESP_OK(esp_etm_del_task(gpio_task_handle)); TEST_ESP_OK(esp_etm_del_channel(etm_channel)); + s_gpio_deinit(); s_i2s_deinit(); } @@ -235,5 +241,6 @@ TEST_CASE("i2s_etm_task_test", "[etm]") TEST_ESP_OK(esp_etm_del_channel(i2s_etm_start_chan)); TEST_ESP_OK(esp_etm_del_channel(i2s_etm_stop_chan)); + s_gpio_deinit(); s_i2s_deinit(); } diff --git a/components/esp_driver_parlio/test_apps/parlio/main/test_parlio_rx.c b/components/esp_driver_parlio/test_apps/parlio/main/test_parlio_rx.c index ec2ca9a23a..b1cf2e1535 100644 --- a/components/esp_driver_parlio/test_apps/parlio/main/test_parlio_rx.c +++ b/components/esp_driver_parlio/test_apps/parlio/main/test_parlio_rx.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -213,14 +213,12 @@ static void level_delimiter_sender_task_spi(void *args) TEST_ESP_OK(spi_bus_add_device(TEST_SPI_HOST, &dev_cfg, &dev_handle)); // Initialize CS gpio - gpio_set_level(TEST_VALID_GPIO, 0); - gpio_config_t cs_cfg = { - .pin_bit_mask = BIT64(TEST_VALID_GPIO), - .mode = GPIO_MODE_OUTPUT, - }; - gpio_config(&cs_cfg); + gpio_set_level(TEST_VALID_GPIO, 0); // output enable set in following code // Connect SPI signals to parlio rx signals + gpio_reset_pin(TEST_CLK_GPIO); + gpio_reset_pin(TEST_VALID_GPIO); + gpio_reset_pin(TEST_DATA0_GPIO); connect_signal_internally(TEST_CLK_GPIO, spi_periph_signal[TEST_SPI_HOST].spiclk_out, soc_parlio_signals[0].rx_units[0].clk_in_sig); @@ -582,6 +580,7 @@ TEST_CASE("parallel_rx_unit_receive_external_memory_test", "[parlio_rx]") TEST_CASE("parallel_rx_unit_receive_timeout_test", "[parlio_rx]") { printf("init a gpio to simulate valid signal\r\n"); + TEST_ESP_OK(gpio_reset_pin(TEST_VALID_GPIO)); gpio_config_t test_gpio_conf = { .mode = GPIO_MODE_OUTPUT, .pin_bit_mask = BIT64(TEST_VALID_GPIO), diff --git a/components/esp_driver_pcnt/test_apps/pulse_cnt/main/test_pulse_cnt_simulator.c b/components/esp_driver_pcnt/test_apps/pulse_cnt/main/test_pulse_cnt_simulator.c index a92c49d39d..84d2383307 100644 --- a/components/esp_driver_pcnt/test_apps/pulse_cnt/main/test_pulse_cnt_simulator.c +++ b/components/esp_driver_pcnt/test_apps/pulse_cnt/main/test_pulse_cnt_simulator.c @@ -15,6 +15,7 @@ // helper function to initialize a gpio for simulation void test_gpio_init_for_simulation(int gpio_sig) { + gpio_reset_pin(gpio_sig); gpio_config_t config = { .mode = GPIO_MODE_OUTPUT, .pin_bit_mask = 1ULL << gpio_sig, diff --git a/components/esp_driver_rmt/test_apps/rmt/main/test_rmt_cache_safe.c b/components/esp_driver_rmt/test_apps/rmt/main/test_rmt_cache_safe.c index 57148b8fab..75c19c1f63 100644 --- a/components/esp_driver_rmt/test_apps/rmt/main/test_rmt_cache_safe.c +++ b/components/esp_driver_rmt/test_apps/rmt/main/test_rmt_cache_safe.c @@ -187,6 +187,7 @@ static void test_rmt_rx_cache_safe(size_t mem_block_symbols, bool with_dma, rmt_ TEST_ESP_OK(rmt_disable(rx_channel)); printf("delete channels and encoder\r\n"); TEST_ESP_OK(rmt_del_channel(rx_channel)); + TEST_ESP_OK(gpio_reset_pin(TEST_RMT_GPIO_NUM_A)); free(remote_codes); } diff --git a/components/esp_driver_rmt/test_apps/rmt/main/test_rmt_rx.c b/components/esp_driver_rmt/test_apps/rmt/main/test_rmt_rx.c index badab650d9..1ca44fcb7b 100644 --- a/components/esp_driver_rmt/test_apps/rmt/main/test_rmt_rx.c +++ b/components/esp_driver_rmt/test_apps/rmt/main/test_rmt_rx.c @@ -298,6 +298,7 @@ static void test_rmt_partial_receive(size_t mem_block_symbols, int test_symbols_ TEST_ESP_OK(rmt_disable(rx_channel)); printf("delete channels and encoder\r\n"); TEST_ESP_OK(rmt_del_channel(rx_channel)); + TEST_ESP_OK(gpio_reset_pin(TEST_RMT_GPIO_NUM_A)); free(receive_user_buf); } diff --git a/components/esp_hal_gpio/esp32/include/hal/gpio_ll.h b/components/esp_hal_gpio/esp32/include/hal/gpio_ll.h index c073f74f84..e53a68e67d 100644 --- a/components/esp_hal_gpio/esp32/include/hal/gpio_ll.h +++ b/components/esp_hal_gpio/esp32/include/hal/gpio_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -364,6 +364,19 @@ static inline void gpio_ll_input_enable(gpio_dev_t *hw, uint32_t gpio_num) PIN_INPUT_ENABLE(DR_REG_IO_MUX_BASE + GPIO_PIN_MUX_REG_OFFSET[gpio_num]); } +/** + * @brief Check if input mode is enabled on GPIO. + * + * @param hw Peripheral GPIO hardware instance address. + * @param gpio_num GPIO number + * @return true if input mode is enabled, false otherwise + */ +__attribute__((always_inline)) +static inline bool gpio_ll_input_is_enabled(gpio_dev_t *hw, uint32_t gpio_num) +{ + return REG_GET_BIT(DR_REG_IO_MUX_BASE + GPIO_PIN_MUX_REG_OFFSET[gpio_num], FUN_IE) ? true : false; +} + /** * @brief Disable output mode on GPIO. * diff --git a/components/esp_hal_gpio/esp32c2/include/hal/gpio_ll.h b/components/esp_hal_gpio/esp32c2/include/hal/gpio_ll.h index 33efd2cd6e..5a9a7d24a9 100644 --- a/components/esp_hal_gpio/esp32c2/include/hal/gpio_ll.h +++ b/components/esp_hal_gpio/esp32c2/include/hal/gpio_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -220,6 +220,19 @@ static inline void gpio_ll_input_enable(gpio_dev_t *hw, uint32_t gpio_num) PIN_INPUT_ENABLE(IO_MUX_GPIO0_REG + (gpio_num * 4)); } +/** + * @brief Check if input mode is enabled on GPIO. + * + * @param hw Peripheral GPIO hardware instance address. + * @param gpio_num GPIO number + * @return true if input mode is enabled, false otherwise + */ +__attribute__((always_inline)) +static inline bool gpio_ll_input_is_enabled(gpio_dev_t *hw, uint32_t gpio_num) +{ + return GET_PERI_REG_MASK(IO_MUX_GPIO0_REG + (gpio_num * 4), FUN_IE) ? true : false; +} + /** * @brief Enable GPIO pin filter * diff --git a/components/esp_hal_gpio/esp32c3/include/hal/gpio_ll.h b/components/esp_hal_gpio/esp32c3/include/hal/gpio_ll.h index ee017567c6..530000d911 100644 --- a/components/esp_hal_gpio/esp32c3/include/hal/gpio_ll.h +++ b/components/esp_hal_gpio/esp32c3/include/hal/gpio_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -203,6 +203,19 @@ static inline void gpio_ll_input_enable(gpio_dev_t *hw, uint32_t gpio_num) PIN_INPUT_ENABLE(IO_MUX_GPIO0_REG + (gpio_num * 4)); } +/** + * @brief Check if input mode is enabled on GPIO. + * + * @param hw Peripheral GPIO hardware instance address. + * @param gpio_num GPIO number + * @return true if input mode is enabled, false otherwise + */ +__attribute__((always_inline)) +static inline bool gpio_ll_input_is_enabled(gpio_dev_t *hw, uint32_t gpio_num) +{ + return GET_PERI_REG_MASK(IO_MUX_GPIO0_REG + (gpio_num * 4), FUN_IE) ? true : false; +} + /** * @brief Enable GPIO pin filter * diff --git a/components/esp_hal_gpio/esp32c5/include/hal/gpio_ll.h b/components/esp_hal_gpio/esp32c5/include/hal/gpio_ll.h index c166151b41..abb564288b 100644 --- a/components/esp_hal_gpio/esp32c5/include/hal/gpio_ll.h +++ b/components/esp_hal_gpio/esp32c5/include/hal/gpio_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -234,6 +234,19 @@ static inline void gpio_ll_input_enable(gpio_dev_t *hw, uint32_t gpio_num) IO_MUX.gpio[gpio_num].fun_ie = 1; } +/** + * @brief Check if input mode is enabled on GPIO. + * + * @param hw Peripheral GPIO hardware instance address. + * @param gpio_num GPIO number + * @return true if input mode is enabled, false otherwise + */ +__attribute__((always_inline)) +static inline bool gpio_ll_input_is_enabled(gpio_dev_t *hw, uint32_t gpio_num) +{ + return IO_MUX.gpio[gpio_num].fun_ie ? true : false; +} + /** * @brief Enable GPIO pin filter * diff --git a/components/esp_hal_gpio/esp32c6/include/hal/gpio_ll.h b/components/esp_hal_gpio/esp32c6/include/hal/gpio_ll.h index 4faf0fd093..3555142344 100644 --- a/components/esp_hal_gpio/esp32c6/include/hal/gpio_ll.h +++ b/components/esp_hal_gpio/esp32c6/include/hal/gpio_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -234,6 +234,19 @@ static inline void gpio_ll_input_enable(gpio_dev_t *hw, uint32_t gpio_num) PIN_INPUT_ENABLE(IO_MUX_GPIO0_REG + (gpio_num * 4)); } +/** + * @brief Check if input mode is enabled on GPIO. + * + * @param hw Peripheral GPIO hardware instance address. + * @param gpio_num GPIO number + * @return true if input mode is enabled, false otherwise + */ +__attribute__((always_inline)) +static inline bool gpio_ll_input_is_enabled(gpio_dev_t *hw, uint32_t gpio_num) +{ + return GET_PERI_REG_MASK(IO_MUX_GPIO0_REG + (gpio_num * 4), FUN_IE) ? true : false; +} + /** * @brief Enable GPIO pin filter * diff --git a/components/esp_hal_gpio/esp32c61/include/hal/gpio_ll.h b/components/esp_hal_gpio/esp32c61/include/hal/gpio_ll.h index f606dd8adc..c937b139fb 100644 --- a/components/esp_hal_gpio/esp32c61/include/hal/gpio_ll.h +++ b/components/esp_hal_gpio/esp32c61/include/hal/gpio_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -235,6 +235,19 @@ static inline void gpio_ll_input_enable(gpio_dev_t *hw, uint32_t gpio_num) IO_MUX.gpion[gpio_num].gpion_fun_ie = 1; } +/** + * @brief Check if input mode is enabled on GPIO. + * + * @param hw Peripheral GPIO hardware instance address. + * @param gpio_num GPIO number + * @return true if input mode is enabled, false otherwise + */ +__attribute__((always_inline)) +static inline bool gpio_ll_input_is_enabled(gpio_dev_t *hw, uint32_t gpio_num) +{ + return IO_MUX.gpion[gpio_num].gpion_fun_ie ? true : false; +} + /** * @brief Enable GPIO pin filter * diff --git a/components/esp_hal_gpio/esp32h2/include/hal/gpio_ll.h b/components/esp_hal_gpio/esp32h2/include/hal/gpio_ll.h index 72a9d23d34..933d9d0160 100644 --- a/components/esp_hal_gpio/esp32h2/include/hal/gpio_ll.h +++ b/components/esp_hal_gpio/esp32h2/include/hal/gpio_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -235,6 +235,19 @@ static inline void gpio_ll_input_enable(gpio_dev_t *hw, uint32_t gpio_num) PIN_INPUT_ENABLE(IO_MUX_GPIO0_REG + (gpio_num * 4)); } +/** + * @brief Check if input mode is enabled on GPIO. + * + * @param hw Peripheral GPIO hardware instance address. + * @param gpio_num GPIO number + * @return true if input mode is enabled, false otherwise + */ +__attribute__((always_inline)) +static inline bool gpio_ll_input_is_enabled(gpio_dev_t *hw, uint32_t gpio_num) +{ + return GET_PERI_REG_MASK(IO_MUX_GPIO0_REG + (gpio_num * 4), FUN_IE) ? true : false; +} + /** * @brief Enable GPIO pin filter * diff --git a/components/esp_hal_gpio/esp32h21/include/hal/gpio_ll.h b/components/esp_hal_gpio/esp32h21/include/hal/gpio_ll.h index 82d98b5343..31122c4576 100644 --- a/components/esp_hal_gpio/esp32h21/include/hal/gpio_ll.h +++ b/components/esp_hal_gpio/esp32h21/include/hal/gpio_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -233,6 +233,19 @@ static inline void gpio_ll_input_enable(gpio_dev_t *hw, uint32_t gpio_num) IO_MUX.gpio[gpio_num].fun_ie = 1; } +/** + * @brief Check if input mode is enabled on GPIO. + * + * @param hw Peripheral GPIO hardware instance address. + * @param gpio_num GPIO number + * @return true if input mode is enabled, false otherwise + */ +__attribute__((always_inline)) +static inline bool gpio_ll_input_is_enabled(gpio_dev_t *hw, uint32_t gpio_num) +{ + return IO_MUX.gpio[gpio_num].fun_ie ? true : false; +} + /** * @brief Enable GPIO pin filter * diff --git a/components/esp_hal_gpio/esp32h4/include/hal/gpio_ll.h b/components/esp_hal_gpio/esp32h4/include/hal/gpio_ll.h index 60e843ae52..035b658b99 100644 --- a/components/esp_hal_gpio/esp32h4/include/hal/gpio_ll.h +++ b/components/esp_hal_gpio/esp32h4/include/hal/gpio_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -241,6 +241,18 @@ static inline void gpio_ll_input_enable(gpio_dev_t *hw, uint32_t gpio_num) IO_MUX.gpio[gpio_num].fun_ie = 1; } +/** + * @brief Check if input mode is enabled on GPIO. + * + * @param hw Peripheral GPIO hardware instance address. + * @param gpio_num GPIO number + * @return true if input mode is enabled, false otherwise + */ +static inline bool gpio_ll_input_is_enabled(gpio_dev_t *hw, uint32_t gpio_num) +{ + return IO_MUX.gpio[gpio_num].fun_ie ? true : false; +} + /** * @brief Enable GPIO pin filter * diff --git a/components/esp_hal_gpio/esp32p4/include/hal/gpio_ll.h b/components/esp_hal_gpio/esp32p4/include/hal/gpio_ll.h index 33fe754eb7..642dd4a8d0 100644 --- a/components/esp_hal_gpio/esp32p4/include/hal/gpio_ll.h +++ b/components/esp_hal_gpio/esp32p4/include/hal/gpio_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -249,6 +249,19 @@ static inline void gpio_ll_input_enable(gpio_dev_t *hw, uint32_t gpio_num) IO_MUX.gpio[gpio_num].fun_ie = 1; } +/** + * @brief Check if input mode is enabled on GPIO. + * + * @param hw Peripheral GPIO hardware instance address. + * @param gpio_num GPIO number + * @return true if input mode is enabled, false otherwise + */ +__attribute__((always_inline)) +static inline bool gpio_ll_input_is_enabled(gpio_dev_t *hw, uint32_t gpio_num) +{ + return IO_MUX.gpio[gpio_num].fun_ie ? true : false; +} + /** * @brief Enable GPIO pin filter * diff --git a/components/esp_hal_gpio/esp32s2/include/hal/gpio_ll.h b/components/esp_hal_gpio/esp32s2/include/hal/gpio_ll.h index b54c426a74..9593eb6ef5 100644 --- a/components/esp_hal_gpio/esp32s2/include/hal/gpio_ll.h +++ b/components/esp_hal_gpio/esp32s2/include/hal/gpio_ll.h @@ -218,6 +218,19 @@ static inline void gpio_ll_input_enable(gpio_dev_t *hw, uint32_t gpio_num) PIN_INPUT_ENABLE(IO_MUX_GPIO0_REG + (gpio_num * 4)); } +/** + * @brief Check if input mode is enabled on GPIO. + * + * @param hw Peripheral GPIO hardware instance address. + * @param gpio_num GPIO number + * @return true if input mode is enabled, false otherwise + */ +__attribute__((always_inline)) +static inline bool gpio_ll_input_is_enabled(gpio_dev_t *hw, uint32_t gpio_num) +{ + return GET_PERI_REG_MASK(IO_MUX_GPIO0_REG + (gpio_num * 4), FUN_IE) ? true : false; +} + /** * @brief Enable GPIO pin filter * diff --git a/components/esp_hal_gpio/esp32s3/include/hal/gpio_ll.h b/components/esp_hal_gpio/esp32s3/include/hal/gpio_ll.h index 81096a97f4..b7546d5127 100644 --- a/components/esp_hal_gpio/esp32s3/include/hal/gpio_ll.h +++ b/components/esp_hal_gpio/esp32s3/include/hal/gpio_ll.h @@ -207,6 +207,19 @@ static inline void gpio_ll_input_enable(gpio_dev_t *hw, uint32_t gpio_num) PIN_INPUT_ENABLE(IO_MUX_GPIO0_REG + (gpio_num * 4)); } +/** + * @brief Check if input mode is enabled on GPIO. + * + * @param hw Peripheral GPIO hardware instance address. + * @param gpio_num GPIO number + * @return true if input mode is enabled, false otherwise + */ +__attribute__((always_inline)) +static inline bool gpio_ll_input_is_enabled(gpio_dev_t *hw, uint32_t gpio_num) +{ + return GET_PERI_REG_MASK(IO_MUX_GPIO0_REG + (gpio_num * 4), FUN_IE) ? true : false; +} + /** * @brief Enable GPIO pin filter * diff --git a/components/esp_hal_gpio/esp32s31/include/hal/gpio_ll.h b/components/esp_hal_gpio/esp32s31/include/hal/gpio_ll.h index b36cb2fd33..48eb78b2fa 100644 --- a/components/esp_hal_gpio/esp32s31/include/hal/gpio_ll.h +++ b/components/esp_hal_gpio/esp32s31/include/hal/gpio_ll.h @@ -258,6 +258,19 @@ static inline void gpio_ll_input_enable(gpio_dev_t *hw, uint32_t gpio_num) IO_MUX.gpio[gpio_num].fun_ie = 1; } +/** + * @brief Check if input mode is enabled on GPIO. + * + * @param hw Peripheral GPIO hardware instance address. + * @param gpio_num GPIO number + * @return true if input mode is enabled, false otherwise + */ +__attribute__((always_inline)) +static inline bool gpio_ll_input_is_enabled(gpio_dev_t *hw, uint32_t gpio_num) +{ + return IO_MUX.gpio[gpio_num].fun_ie ? true : false; +} + /** * @brief Enable GPIO pin filter * diff --git a/components/esp_hal_gpio/include/hal/gpio_hal.h b/components/esp_hal_gpio/include/hal/gpio_hal.h index 4613cbb77d..7664aa83ba 100644 --- a/components/esp_hal_gpio/include/hal/gpio_hal.h +++ b/components/esp_hal_gpio/include/hal/gpio_hal.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -144,6 +144,15 @@ void gpio_hal_intr_disable(gpio_hal_context_t *hal, uint32_t gpio_num); */ #define gpio_hal_input_enable(hal, gpio_num) gpio_ll_input_enable((hal)->dev, gpio_num) +/** + * @brief Check if input mode is enabled on GPIO. + * + * @param hal Context of the HAL layer + * @param gpio_num GPIO number + * @return true if input mode is enabled, false otherwise + */ +#define gpio_hal_input_is_enabled(hal, gpio_num) gpio_ll_input_is_enabled((hal)->dev, gpio_num) + /** * @brief Disable output mode on GPIO. * diff --git a/components/esp_lcd/test_apps/spi_lcd/main/test_spi_lcd_panel.c b/components/esp_lcd/test_apps/spi_lcd/main/test_spi_lcd_panel.c index 6f41b80052..d9a3a3fdeb 100644 --- a/components/esp_lcd/test_apps/spi_lcd/main/test_spi_lcd_panel.c +++ b/components/esp_lcd/test_apps/spi_lcd/main/test_spi_lcd_panel.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -133,6 +133,7 @@ TEST_CASE("lcd_panel_spi_io_test", "[lcd]") esp_lcd_panel_io_tx_param(io_handle, 0x1C, NULL, 0); TEST_ESP_OK(esp_lcd_panel_io_del(io_handle)); TEST_ESP_OK(spi_bus_free(TEST_SPI_HOST_ID)); + TEST_ESP_OK(gpio_reset_pin(TEST_LCD_BK_LIGHT_GPIO)); test_spi_lcd_common_initialize(&io_handle, NULL, NULL, 16, 16, false); esp_lcd_panel_io_tx_param(io_handle, 0x1A01, NULL, 0); @@ -142,6 +143,7 @@ TEST_CASE("lcd_panel_spi_io_test", "[lcd]") esp_lcd_panel_io_tx_param(io_handle, 0x1C03, NULL, 0); TEST_ESP_OK(esp_lcd_panel_io_del(io_handle)); TEST_ESP_OK(spi_bus_free(TEST_SPI_HOST_ID)); + TEST_ESP_OK(gpio_reset_pin(TEST_LCD_BK_LIGHT_GPIO)); #if SOC_SPI_SUPPORT_OCT test_spi_lcd_common_initialize(&io_handle, NULL, NULL, 8, 8, true); @@ -152,6 +154,7 @@ TEST_CASE("lcd_panel_spi_io_test", "[lcd]") esp_lcd_panel_io_tx_param(io_handle, 0x1C, NULL, 0); TEST_ESP_OK(esp_lcd_panel_io_del(io_handle)); TEST_ESP_OK(spi_bus_free(TEST_SPI_HOST_ID)); + TEST_ESP_OK(gpio_reset_pin(TEST_LCD_BK_LIGHT_GPIO)); test_spi_lcd_common_initialize(&io_handle, NULL, NULL, 16, 16, true); esp_lcd_panel_io_tx_param(io_handle, 0x1A01, NULL, 0); @@ -161,6 +164,7 @@ TEST_CASE("lcd_panel_spi_io_test", "[lcd]") esp_lcd_panel_io_tx_param(io_handle, 0x1C03, NULL, 0); TEST_ESP_OK(esp_lcd_panel_io_del(io_handle)); TEST_ESP_OK(spi_bus_free(TEST_SPI_HOST_ID)); + TEST_ESP_OK(gpio_reset_pin(TEST_LCD_BK_LIGHT_GPIO)); #endif // SOC_SPI_SUPPORT_OCT } @@ -275,5 +279,6 @@ TEST_CASE("spi_lcd_send_colors_to_fixed_region", "[lcd]") TEST_ESP_OK(esp_lcd_panel_del(panel_handle)); TEST_ESP_OK(esp_lcd_panel_io_del(io_handle)); TEST_ESP_OK(spi_bus_free(TEST_SPI_HOST_ID)); + TEST_ESP_OK(gpio_reset_pin(TEST_LCD_BK_LIGHT_GPIO)); free(color_data); }