]> granicus.if.org Git - esp-idf/commitdiff
fix(spi): reset gpios that used by spi when deinited
authorMichael (XIAO Xufeng) <xiaoxufeng@espressif.com>
Fri, 8 Jun 2018 07:33:04 +0000 (15:33 +0800)
committerMichael (XIAO Xufeng) <xiaoxufeng@espressif.com>
Thu, 14 Jun 2018 03:29:15 +0000 (11:29 +0800)
components/driver/gpio.c
components/driver/include/driver/gpio.h
components/driver/include/driver/spi_common.h
components/driver/spi_common.c
components/driver/spi_master.c

index e017cd87dff6628d78ba042cec370dee9bb90068..d82fae130706a683c85c8d9e5dbec773344baf95 100644 (file)
@@ -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
index f8aa33abf9d4c04e033392b56fdd5e2851e06fb3..1c4828c2776eb7d9e8de477e7a26f5bb6990d127 100644 (file)
@@ -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
index 33c701ec5761962a0a4918ed9e4226aeb243ebad..cc029db2b951ef6194d71a1c86594790aaccb171 100644 (file)
@@ -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
index 1eb1ebef834ea67e89a0b5044f7b20f225ab67e0..a26b14702495179f68900f7c548fd4b1b150f50e 100644 (file)
@@ -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)
 {
index ec54a3badeb95a808a1f8d328e79a783878c7b1b..8fa86478439dcefd7428dbb67cbde7d60ce6d881 100644 (file)
@@ -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; x<NO_CS; x++) {
         SPI_CHECK(spihost[host]->device[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);