diff --git a/components/driver/spi_master.c b/components/driver/spi_master.c index 0f16ed22b4..e6b9abe74f 100644 --- a/components/driver/spi_master.c +++ b/components/driver/spi_master.c @@ -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)