]> granicus.if.org Git - esp-idf/commitdiff
fix(spi_master): release temporary memory when queue new trans timeout.
authormichael <xiaoxufeng@espressif.com>
Fri, 17 Nov 2017 03:25:44 +0000 (11:25 +0800)
committermichael <xiaoxufeng@espressif.com>
Fri, 17 Nov 2017 04:15:19 +0000 (12:15 +0800)
components/driver/spi_master.c

index 0f16ed22b403764dab8026b0e3de0cab524aa18d..e6b9abe74f10318350be6d8169cbb0b1798c3040 100644 (file)
@@ -627,6 +627,7 @@ static void IRAM_ATTR spi_intr(void *arg)
 
 esp_err_t spi_device_queue_trans(spi_device_handle_t handle, spi_transaction_t *trans_desc,  TickType_t ticks_to_wait)
 {
+    esp_err_t ret = ESP_OK;
     BaseType_t r;
     SPI_CHECK(handle!=NULL, "invalid dev handle", ESP_ERR_INVALID_ARG);
     //check transmission length 
@@ -662,7 +663,10 @@ esp_err_t spi_device_queue_trans(spi_device_handle_t handle, spi_transaction_t *
         //if rxbuf in the desc not DMA-capable, malloc a new one. The rx buffer need to be length of multiples of 32 bits to avoid heap corruption.
         ESP_LOGV( SPI_TAG, "Allocate RX buffer for DMA" );
         trans_buf.buffer_to_rcv = heap_caps_malloc((trans_desc->rxlength+31)/8, MALLOC_CAP_DMA);
-        if ( trans_buf.buffer_to_rcv==NULL ) return ESP_ERR_NO_MEM;
+        if ( trans_buf.buffer_to_rcv==NULL ) {
+            ret = ESP_ERR_NO_MEM;
+            goto clean_up;
+        }
     }
     
     const uint32_t *txdata;
@@ -678,25 +682,40 @@ esp_err_t spi_device_queue_trans(spi_device_handle_t handle, spi_transaction_t *
         ESP_LOGV( SPI_TAG, "Allocate TX buffer for DMA" );
         trans_buf.buffer_to_send = heap_caps_malloc((trans_desc->length+7)/8, MALLOC_CAP_DMA);
         if ( trans_buf.buffer_to_send==NULL ) {
-            // free malloc-ed buffer (if needed) before return.
-            if ( (void*)trans_buf.buffer_to_rcv != trans_desc->rx_buffer && (void*)trans_buf.buffer_to_rcv != &trans_desc->rx_data[0] ) {
-                free( trans_buf.buffer_to_rcv );
-            }   
-            return ESP_ERR_NO_MEM;
+            ret = ESP_ERR_NO_MEM;
+            goto clean_up;
         }
         memcpy( trans_buf.buffer_to_send, txdata, (trans_desc->length+7)/8 );
     } else { 
         // else use the original buffer (forced-conversion) or assign to NULL
         trans_buf.buffer_to_send = (uint32_t*)txdata;
     }
+    
 #ifdef CONFIG_PM_ENABLE
     esp_pm_lock_acquire(handle->host->pm_lock);
 #endif
-
     r=xQueueSend(handle->trans_queue, (void*)&trans_buf, ticks_to_wait);
-    if (!r) return ESP_ERR_TIMEOUT;
+    if (!r) {
+        ret = ESP_ERR_TIMEOUT;
+#ifdef CONFIG_PM_ENABLE
+        //Release APB frequency lock
+        esp_pm_lock_release(handle->host->pm_lock);
+#endif
+        goto clean_up;
+    }
     esp_intr_enable(handle->host->intr);
     return ESP_OK;
+
+clean_up:
+    // free malloc-ed buffer (if needed) before return.
+    if ( (void*)trans_buf.buffer_to_rcv != trans_desc->rx_buffer && (void*)trans_buf.buffer_to_rcv != &trans_desc->rx_data[0] ) {
+        free( trans_buf.buffer_to_rcv );
+    }   
+    if ( (void*)trans_buf.buffer_to_send!= trans_desc->tx_buffer && (void*)trans_buf.buffer_to_send != &trans_desc->tx_data[0] ) {
+        free( trans_buf.buffer_to_send );
+    }   
+    assert( ret != ESP_OK );
+    return ret;
 }
 
 esp_err_t spi_device_get_trans_result(spi_device_handle_t handle, spi_transaction_t **trans_desc, TickType_t ticks_to_wait)