diff --git a/components/driver/gpio.c b/components/driver/gpio.c index e017cd87d..d82fae130 100644 --- a/components/driver/gpio.c +++ b/components/driver/gpio.c @@ -339,6 +339,21 @@ esp_err_t gpio_config(const gpio_config_t *pGPIOConfig) return ESP_OK; } +esp_err_t gpio_reset_pin(gpio_num_t gpio_num) +{ + assert(gpio_num >= 0 && GPIO_IS_VALID_GPIO(gpio_num)); + gpio_config_t cfg = { + .pin_bit_mask = BIT(gpio_num), + .mode = GPIO_MODE_DISABLE, + //for powersave reasons, the GPIO should not be floating, select pullup + .pull_up_en = true, + .pull_down_en = false, + .intr_type = GPIO_INTR_DISABLE, + }; + gpio_config(&cfg); + return ESP_OK; +} + void IRAM_ATTR gpio_intr_service(void* arg) { //GPIO intr process diff --git a/components/driver/include/driver/gpio.h b/components/driver/include/driver/gpio.h index f8aa33abf..1c4828c27 100644 --- a/components/driver/include/driver/gpio.h +++ b/components/driver/include/driver/gpio.h @@ -248,6 +248,18 @@ typedef intr_handle_t gpio_isr_handle_t; */ esp_err_t gpio_config(const gpio_config_t *pGPIOConfig); +/** + * @brief Reset an gpio to default state (select gpio function, enable pullup and disable input and output). + * + * @param gpio_num GPIO number. + * + * @note This function also configures the IOMUX for this pin to the GPIO + * function, and disconnects any other peripheral output configured via GPIO + * Matrix. + * + * @return Always return ESP_OK. + */ +esp_err_t gpio_reset_pin(gpio_num_t gpio_num); /** * @brief GPIO set interrupt trigger type diff --git a/components/driver/include/driver/spi_common.h b/components/driver/include/driver/spi_common.h index 33c701ec5..cc029db2b 100644 --- a/components/driver/include/driver/spi_common.h +++ b/components/driver/include/driver/spi_common.h @@ -144,14 +144,26 @@ 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 - * + * @deprecated Use spicommon_bus_free_io_cfg instead. + * * @param host SPI peripheral to be freed + * * @return * - ESP_ERR_INVALID_ARG if parameter is invalid * - ESP_OK on success */ +esp_err_t spicommon_bus_free_io(spi_host_device_t host) __attribute__((deprecated)); -esp_err_t spicommon_bus_free_io(spi_host_device_t host); +/** + * @brief Free the IO used by a SPI peripheral + * + * @param bus_cfg Bus config struct which defines which pins to be used. + * + * @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); /** * @brief Initialize a Chip Select pin for a specific SPI peripheral @@ -168,12 +180,19 @@ void spicommon_cs_initialize(spi_host_device_t host, int cs_io_num, int cs_num, /** * @brief Free a chip select line + * @deprecated Use spicommon_cs_io, which inputs the gpio num rather than the cs id instead. * * @param host SPI peripheral * @param cs_num CS id to free */ -void spicommon_cs_free(spi_host_device_t host, int cs_num); +void spicommon_cs_free(spi_host_device_t host, int cs_num) __attribute__((deprecated)); +/** + * @brief Free a chip select line + * + * @param cs_gpio_num CS gpio num to free + */ +void spicommon_cs_free_io(int cs_gpio_num); /** * @brief Setup a DMA link chain diff --git a/components/driver/spi_common.c b/components/driver/spi_common.c index 1eb1ebef8..a26b14702 100644 --- a/components/driver/spi_common.c +++ b/components/driver/spi_common.c @@ -285,6 +285,22 @@ esp_err_t spicommon_bus_free_io(spi_host_device_t host) return ESP_OK; } +esp_err_t spicommon_bus_free_io_cfg(const spi_bus_config_t *bus_cfg) +{ + int pin_array[] = { + bus_cfg->mosi_io_num, + bus_cfg->miso_io_num, + bus_cfg->sclk_io_num, + bus_cfg->quadwp_io_num, + bus_cfg->quadhd_io_num, + }; + for (int i = 0; i < sizeof(pin_array)/sizeof(int); i ++) { + const int io = pin_array[i]; + if (io >= 0 && GPIO_IS_VALID_GPIO(io)) gpio_reset_pin(io); + } + return ESP_OK; +} + void spicommon_cs_initialize(spi_host_device_t host, int cs_io_num, int cs_num, int force_gpio_matrix) { if (!force_gpio_matrix && cs_io_num == spi_periph_signal[host].spics0_iomux_pin && cs_num == 0) { @@ -307,6 +323,12 @@ void spicommon_cs_free(spi_host_device_t host, int cs_io_num) reset_func_to_gpio(spi_periph_signal[host].spics_out[cs_io_num]); } +void spicommon_cs_free_io(int cs_gpio_num) +{ + assert(cs_gpio_num>=0 && GPIO_IS_VALID_GPIO(cs_gpio_num)); + gpio_reset_pin(cs_gpio_num); +} + //Set up a list of dma descriptors. dmadesc is an array of descriptors. Data is the buffer to point to. void spicommon_setup_dma_desc_links(lldesc_t *dmadesc, int len, const uint8_t *data, bool isrx) { diff --git a/components/driver/spi_master.c b/components/driver/spi_master.c index ec54a3bad..8fa864784 100644 --- a/components/driver/spi_master.c +++ b/components/driver/spi_master.c @@ -85,6 +85,7 @@ typedef struct { uint32_t flags; int dma_chan; int max_transfer_sz; + spi_bus_config_t bus_cfg; #ifdef CONFIG_PM_ENABLE esp_pm_lock_handle_t pm_lock; #endif @@ -146,6 +147,7 @@ esp_err_t spi_bus_initialize(spi_host_device_t host, const spi_bus_config_t *bus goto cleanup; } memset(spihost[host], 0, sizeof(spi_host_t)); + memcpy( &spihost[host]->bus_cfg, bus_config, sizeof(spi_bus_config_t)); #ifdef CONFIG_PM_ENABLE err = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "spi_master", &spihost[host]->pm_lock); @@ -237,6 +239,7 @@ esp_err_t spi_bus_free(spi_host_device_t host) for (x=0; xdevice[x]==NULL, "not all CSses freed", ESP_ERR_INVALID_STATE); } + spicommon_bus_free_io_cfg(&spihost[host]->bus_cfg); if ( spihost[host]->dma_chan > 0 ) { spicommon_dma_chan_free ( spihost[host]->dma_chan ); @@ -395,6 +398,10 @@ esp_err_t spi_bus_remove_device(spi_device_handle_t handle) SPI_CHECK(handle->host->cur_cs == NO_CS || handle->host->device[handle->host->cur_cs]!=handle, "Have unfinished transactions", ESP_ERR_INVALID_STATE); SPI_CHECK(uxQueueMessagesWaiting(handle->ret_queue)==0, "Have unfinished transactions", ESP_ERR_INVALID_STATE); + //return + int spics_io_num = handle->cfg.spics_io_num; + if (spics_io_num >= 0) spicommon_cs_free_io(spics_io_num); + //Kill queues vQueueDelete(handle->trans_queue); vQueueDelete(handle->ret_queue);