From fbc049ed698db9f74f1f8b694ec28a747d017573 Mon Sep 17 00:00:00 2001 From: wanckl Date: Mon, 12 Jan 2026 11:47:38 +0800 Subject: [PATCH] fix(driver_spi): fixed spi still got input after re-install --- .../include/esp_private/spi_common_internal.h | 7 ++- .../esp_driver_spi/src/gpspi/spi_common.c | 50 +++++++++++++------ .../esp_driver_spi/src/gpspi/spi_slave.c | 2 +- .../esp_driver_spi/src/gpspi/spi_slave_hd.c | 2 +- .../test_apps/master/main/test_spi_bus_lock.c | 2 +- components/esp_hal_gpio/gpio_hal.c | 4 +- 6 files changed, 43 insertions(+), 24 deletions(-) diff --git a/components/esp_driver_spi/include/esp_private/spi_common_internal.h b/components/esp_driver_spi/include/esp_private/spi_common_internal.h index 2b1c6e82afe..e5583f8f8cc 100644 --- a/components/esp_driver_spi/include/esp_private/spi_common_internal.h +++ b/components/esp_driver_spi/include/esp_private/spi_common_internal.h @@ -52,7 +52,7 @@ typedef enum { /// Attributes of an SPI bus typedef struct { spi_bus_config_t bus_cfg; ///< Config used to initialize the bus - uint64_t gpio_reserve; ///< reserved output gpio bit mask + uint64_t gpio_reserve; ///< reserved gpio matrix output pins and all iomux pins bit mask uint32_t flags; ///< Flags (SPICOMMON_BUSFLAG_* flag combination of bus abilities) of the bus int max_transfer_sz; ///< Maximum length of bytes available to send bool dma_enabled; ///< To enable DMA or not @@ -211,14 +211,13 @@ esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_conf /** * @brief Free the IO used by a SPI peripheral * - * @param bus_cfg Bus config struct which defines which pins to be used. - * @param io_reserved Bitmap indicate which pin is reserved + * @param host SPI peripheral * * @return * - ESP_ERR_INVALID_ARG if parameter is invalid * - ESP_OK on success */ -esp_err_t spicommon_bus_free_io_cfg(const spi_bus_config_t *bus_cfg, uint64_t *io_reserved); +esp_err_t spicommon_bus_free_io_cfg(spi_host_device_t host); /** * @brief Initialize a Chip Select pin for a specific SPI peripheral diff --git a/components/esp_driver_spi/src/gpspi/spi_common.c b/components/esp_driver_spi/src/gpspi/spi_common.c index 3903a523140..b279a9c5870 100644 --- a/components/esp_driver_spi/src/gpspi/spi_common.c +++ b/components/esp_driver_spi/src/gpspi/spi_common.c @@ -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 */ @@ -12,7 +12,6 @@ #include "esp_attr.h" #include "esp_check.h" #include "esp_cache.h" -#include "esp_rom_gpio.h" #include "esp_heap_caps.h" #include "esp_memory_utils.h" #include "driver/spi_master.h" @@ -607,14 +606,13 @@ static void s_spi_common_bus_via_gpio(gpio_num_t gpio_num, int in_sig, int out_s { assert(GPIO_IS_VALID_GPIO(gpio_num)); //coverity check if (in_sig != -1) { - gpio_input_enable(gpio_num); - esp_rom_gpio_connect_in_signal(gpio_num, in_sig, false); + gpio_matrix_input(gpio_num, in_sig, false); } if (out_sig != -1) { // For gpio_matrix, reserve output pins, see 'esp_gpio_reserve.h' *io_mask |= BIT64(gpio_num); s_spi_common_gpio_check_reserve(gpio_num); - esp_rom_gpio_connect_out_signal(gpio_num, out_sig, false, false); + gpio_matrix_output(gpio_num, out_sig, false, false); } gpio_func_sel(gpio_num, PIN_FUNC_GPIO); } @@ -682,9 +680,9 @@ esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_conf SPI_CHECK_PIN(bus_config->miso_io_num, "miso", !(flags & SPICOMMON_BUSFLAG_MASTER) || (temp_flag & SPICOMMON_BUSFLAG_DUAL)); } //set flags for DUAL mode according to output-capability of MOSI and MISO pins. - if ((bus_config->mosi_io_num < 0 || GPIO_IS_VALID_OUTPUT_GPIO(bus_config->mosi_io_num)) && - (bus_config->miso_io_num < 0 || GPIO_IS_VALID_OUTPUT_GPIO(bus_config->miso_io_num)) && - (bus_config->miso_io_num != bus_config->mosi_io_num)) { + //DUAL mode requires both MOSI and MISO to able to input and output. + if (GPIO_IS_VALID_OUTPUT_GPIO(bus_config->mosi_io_num) && GPIO_IS_VALID_OUTPUT_GPIO(bus_config->miso_io_num) && + bus_config->miso_io_num != bus_config->mosi_io_num) { temp_flag |= SPICOMMON_BUSFLAG_DUAL; } @@ -751,7 +749,7 @@ esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_conf } else { //Use GPIO matrix if (bus_config->mosi_io_num >= 0) { - int in_sig = (!(flags & SPICOMMON_BUSFLAG_MASTER) || (temp_flag & SPICOMMON_BUSFLAG_DUAL)) ? spi_periph_signal[host].spid_in : -1; + int in_sig = spi_periph_signal[host].spid_in; // always connect input in case sio mode device is used int out_sig = ((flags & SPICOMMON_BUSFLAG_MASTER) || (temp_flag & SPICOMMON_BUSFLAG_DUAL)) ? spi_periph_signal[host].spid_out : -1; s_spi_common_bus_via_gpio(bus_config->mosi_io_num, in_sig, out_sig, &gpio_reserv); } @@ -800,20 +798,41 @@ esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_conf return ESP_OK; } -esp_err_t spicommon_bus_free_io_cfg(const spi_bus_config_t *bus_cfg, uint64_t *io_reserved) +esp_err_t spicommon_bus_free_io_cfg(spi_host_device_t host) { + spi_bus_attr_t *bus_attr = (spi_bus_attr_t *)spi_bus_get_attr(host); + assert(bus_attr); + spi_bus_config_t *bus_cfg = &bus_attr->bus_cfg; + for (uint8_t i = 0; i < sizeof(bus_cfg->iocfg) / sizeof(bus_cfg->iocfg[0]); i++) { #if !SOC_SPI_SUPPORT_OCT if (i > 4) { break; } #endif - if (GPIO_IS_VALID_GPIO(bus_cfg->iocfg[i]) && (*io_reserved & BIT64(bus_cfg->iocfg[i]))) { - *io_reserved &= ~BIT64(bus_cfg->iocfg[i]); + if (GPIO_IS_VALID_GPIO(bus_cfg->iocfg[i]) && (bus_attr->gpio_reserve & BIT64(bus_cfg->iocfg[i]))) { + bus_attr->gpio_reserve &= ~BIT64(bus_cfg->iocfg[i]); + // all reserved pins (even iomux input pins) is harmless to be disabled here. gpio_output_disable(bus_cfg->iocfg[i]); esp_gpio_revoke(BIT64(bus_cfg->iocfg[i])); } } + + // disconnect all input signals anyway + gpio_matrix_input(GPIO_MATRIX_CONST_ONE_INPUT, spi_periph_signal[host].spics_in, false); + gpio_matrix_input(GPIO_MATRIX_CONST_ONE_INPUT, spi_periph_signal[host].spiclk_in, false); + gpio_matrix_input(GPIO_MATRIX_CONST_ONE_INPUT, spi_periph_signal[host].spid_in, false); + gpio_matrix_input(GPIO_MATRIX_CONST_ONE_INPUT, spi_periph_signal[host].spiq_in, false); + gpio_matrix_input(GPIO_MATRIX_CONST_ONE_INPUT, spi_periph_signal[host].spiwp_in, false); + gpio_matrix_input(GPIO_MATRIX_CONST_ONE_INPUT, spi_periph_signal[host].spihd_in, false); +#if SOC_SPI_SUPPORT_OCT + if (host == SPI2_HOST) { // only gpspi2 supports octal pins (data4 ~ data7) + gpio_matrix_input(GPIO_MATRIX_CONST_ONE_INPUT, spi_periph_signal[host].spid4_in, false); + gpio_matrix_input(GPIO_MATRIX_CONST_ONE_INPUT, spi_periph_signal[host].spid5_in, false); + gpio_matrix_input(GPIO_MATRIX_CONST_ONE_INPUT, spi_periph_signal[host].spid6_in, false); + gpio_matrix_input(GPIO_MATRIX_CONST_ONE_INPUT, spi_periph_signal[host].spid7_in, false); + } +#endif return ESP_OK; } @@ -831,12 +850,11 @@ void spicommon_cs_initialize(spi_host_device_t host, int cs_io_num, int cs_id, i if (GPIO_IS_VALID_OUTPUT_GPIO(cs_io_num)) { out_mask |= BIT64(cs_io_num); s_spi_common_gpio_check_reserve(cs_io_num); - esp_rom_gpio_connect_out_signal(cs_io_num, spi_periph_signal[host].spics_out[cs_id], false, false); + gpio_matrix_output(cs_io_num, spi_periph_signal[host].spics_out[cs_id], false, false); } // cs_id 0 is always used by slave for input if (cs_id == 0) { - gpio_input_enable(cs_io_num); - esp_rom_gpio_connect_in_signal(cs_io_num, spi_periph_signal[host].spics_in, false); + gpio_matrix_input(cs_io_num, spi_periph_signal[host].spics_in, false); } gpio_func_sel(cs_io_num, PIN_FUNC_GPIO); } @@ -1026,7 +1044,7 @@ esp_err_t spi_bus_free(spi_host_device_t host_id) return err; } } - spicommon_bus_free_io_cfg(&bus_attr->bus_cfg, &bus_attr->gpio_reserve); + spicommon_bus_free_io_cfg(host_id); #if SOC_SPI_SUPPORT_SLEEP_RETENTION && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP const periph_retention_module_t retention_id = spi_reg_retention_info[host_id - 1].module_id; diff --git a/components/esp_driver_spi/src/gpspi/spi_slave.c b/components/esp_driver_spi/src/gpspi/spi_slave.c index e3e2bbb7b62..c8387289b22 100644 --- a/components/esp_driver_spi/src/gpspi/spi_slave.c +++ b/components/esp_driver_spi/src/gpspi/spi_slave.c @@ -324,7 +324,7 @@ esp_err_t spi_slave_free(spi_host_device_t host) if (spihost[host]->bus_attr->dma_enabled) { spicommon_dma_chan_free(host); } - spicommon_bus_free_io_cfg(&spihost[host]->bus_attr->bus_cfg, &spihost[host]->bus_attr->gpio_reserve); + spicommon_bus_free_io_cfg(host); if (spihost[host]->cfg.spics_io_num >= 0) { spicommon_cs_free_io(spihost[host]->cfg.spics_io_num, &spihost[host]->bus_attr->gpio_reserve); } diff --git a/components/esp_driver_spi/src/gpspi/spi_slave_hd.c b/components/esp_driver_spi/src/gpspi/spi_slave_hd.c index e61b84fa911..22ebfe7cd5a 100644 --- a/components/esp_driver_spi/src/gpspi/spi_slave_hd.c +++ b/components/esp_driver_spi/src/gpspi/spi_slave_hd.c @@ -337,7 +337,7 @@ esp_err_t spi_slave_hd_deinit(spi_host_device_t host_id) } #endif - spicommon_bus_free_io_cfg(&host->bus_attr->bus_cfg, &host->bus_attr->gpio_reserve); + spicommon_bus_free_io_cfg(host_id); spicommon_cs_free_io(host->cs_io_num, &host->bus_attr->gpio_reserve); free(host->hal.dmadesc_tx); free(host->hal.dmadesc_rx); diff --git a/components/esp_driver_spi/test_apps/master/main/test_spi_bus_lock.c b/components/esp_driver_spi/test_apps/master/main/test_spi_bus_lock.c index 7038eee3fd5..0b52beda80f 100644 --- a/components/esp_driver_spi/test_apps/master/main/test_spi_bus_lock.c +++ b/components/esp_driver_spi/test_apps/master/main/test_spi_bus_lock.c @@ -283,7 +283,7 @@ static void test_bus_lock(bool test_flash) #if CONFIG_IDF_TARGET_ESP32 // no need this case in other target, only esp32 need buslock to split MSPI and GPSPI2 action -TEST_CASE("spi bus lock, with flash", "[spi][test_env=external_flash]") +TEST_CASE("spi bus lock, with flash", "[external_flash][test_env=external_flash]") { test_bus_lock(true); } diff --git a/components/esp_hal_gpio/gpio_hal.c b/components/esp_hal_gpio/gpio_hal.c index 43eacf30379..deeeefbd4f2 100644 --- a/components/esp_hal_gpio/gpio_hal.c +++ b/components/esp_hal_gpio/gpio_hal.c @@ -47,7 +47,9 @@ void gpio_hal_iomux_out(gpio_hal_context_t *hal, uint32_t gpio_num, int func) void gpio_hal_matrix_in(gpio_hal_context_t *hal, uint32_t gpio_num, uint32_t signal_idx, bool in_inv) { - gpio_ll_input_enable(hal->dev, gpio_num); + if (gpio_num < GPIO_NUM_MAX) { // skip const_0/1 io num from enabling input + gpio_ll_input_enable(hal->dev, gpio_num); + } #if HAL_CONFIG(GPIO_USE_ROM_API) esp_rom_gpio_connect_in_signal(gpio_num, signal_idx, in_inv); #else