From 02573a8dc952ace0fe002ae06acd70a0a9a9ec16 Mon Sep 17 00:00:00 2001 From: michael Date: Fri, 17 Nov 2017 11:25:44 +0800 Subject: [PATCH] fix(spi_master): release temporary memory when queue new trans timeout. --- components/driver/spi_master.c | 35 ++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/components/driver/spi_master.c b/components/driver/spi_master.c index 0f16ed22b..e6b9abe74 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)