From 05fb10182df920a2e54b112f9af61822ca6ae49f Mon Sep 17 00:00:00 2001 From: wanckl Date: Thu, 9 Jul 2026 19:33:03 +0800 Subject: [PATCH 1/3] fix(hw_support): spi buslock fix unregister dev api issue --- components/esp_driver_spi/src/gpspi/spi_master.c | 1 + components/esp_hw_support/spi_bus_lock.c | 11 +++++++++++ components/spi_flash/esp_flash_spi_init.c | 10 +++++++--- components/spi_flash/include/esp_flash_spi_init.h | 1 + .../include/esp_private/esp_flash_internal.h | 4 +++- components/spi_flash/spi_flash_os_func_app.c | 8 +++++++- 6 files changed, 30 insertions(+), 5 deletions(-) diff --git a/components/esp_driver_spi/src/gpspi/spi_master.c b/components/esp_driver_spi/src/gpspi/spi_master.c index 1602f59ddd5..e2dc26bec85 100644 --- a/components/esp_driver_spi/src/gpspi/spi_master.c +++ b/components/esp_driver_spi/src/gpspi/spi_master.c @@ -596,6 +596,7 @@ esp_err_t spi_bus_remove_device(spi_device_handle_t handle) //catch design errors and aren't meant to be triggered during normal operation. SPI_CHECK(uxQueueMessagesWaiting(handle->trans_queue) == 0, "Have unfinished transactions", ESP_ERR_INVALID_STATE); SPI_CHECK(handle->host->cur_cs == DEV_NUM_MAX || handle->host->device[handle->host->cur_cs] != handle, "Have unfinished transactions", ESP_ERR_INVALID_STATE); + SPI_CHECK(handle->host->device_acquiring_lock != handle, "Device has acquired the bus", ESP_ERR_INVALID_STATE); if (handle->ret_queue) { SPI_CHECK(uxQueueMessagesWaiting(handle->ret_queue) == 0, "Have unfinished transactions", ESP_ERR_INVALID_STATE); } diff --git a/components/esp_hw_support/spi_bus_lock.c b/components/esp_hw_support/spi_bus_lock.c index 7a17a22052a..97fbf150611 100644 --- a/components/esp_hw_support/spi_bus_lock.c +++ b/components/esp_hw_support/spi_bus_lock.c @@ -705,10 +705,16 @@ void spi_bus_lock_unregister_dev(spi_bus_lock_dev_handle_t dev_handle) spi_bus_lock_t* lock = dev_handle->parent; BUS_LOCK_DEBUG_EXECUTE_CHECK(atomic_load(&lock->dev[id]) == (intptr_t)dev_handle); + BUS_LOCK_DEBUG_EXECUTE_CHECK(lock->acquiring_dev != dev_handle); + BUS_LOCK_DEBUG_EXECUTE_CHECK((lock_status_fetch(lock) & dev_handle->mask) == 0); if (lock->last_dev == dev_handle) { lock->last_dev = NULL; } + if (lock->acquiring_dev == dev_handle) { + lock->acquiring_dev = NULL; + lock->acq_dev_bg_active = false; + } atomic_store(&lock->dev[id], (intptr_t)NULL); if (dev_handle->semphr) { @@ -735,6 +741,11 @@ void spi_bus_lock_set_bg_control(spi_bus_lock_handle_t lock, bg_ctrl_func_t bg_e lock->bg_arg = arg; } +IRAM_ATTR spi_bus_lock_handle_t spi_bus_lock_get_parent(spi_bus_lock_dev_handle_t dev_handle) +{ + return (dev_handle ? dev_handle->parent : NULL); +} + IRAM_ATTR int spi_bus_lock_get_dev_id(spi_bus_lock_dev_handle_t dev_handle) { return (dev_handle ? dev_lock_get_id(dev_handle) : -1); diff --git a/components/spi_flash/esp_flash_spi_init.c b/components/spi_flash/esp_flash_spi_init.c index 64106ccabea..bcee28e21fc 100644 --- a/components/spi_flash/esp_flash_spi_init.c +++ b/components/spi_flash/esp_flash_spi_init.c @@ -439,17 +439,21 @@ esp_err_t spi_bus_remove_flash_device(esp_flash_t *chip) return ESP_ERR_INVALID_ARG; } + spi_bus_lock_dev_handle_t dev_handle = NULL; + esp_err_t ret = esp_flash_deinit_os_functions(chip, &dev_handle); + if (ret != ESP_OK) { + return ret; + } + // Disable GPSPI clocks before cleanup deinit_gpspi_clock(chip); - spi_bus_lock_dev_handle_t dev_handle = NULL; - esp_flash_deinit_os_functions(chip, &dev_handle); if (dev_handle) { spi_bus_lock_unregister_dev(dev_handle); } free(chip->host); free(chip); - return ESP_OK; + return ret; } /* The default (ie initial boot) no-OS ROM esp_flash_os_functions_t */ diff --git a/components/spi_flash/include/esp_flash_spi_init.h b/components/spi_flash/include/esp_flash_spi_init.h index 13aed8ce6f6..9840d771976 100644 --- a/components/spi_flash/include/esp_flash_spi_init.h +++ b/components/spi_flash/include/esp_flash_spi_init.h @@ -51,6 +51,7 @@ esp_err_t spi_bus_add_flash_device(esp_flash_t **out_chip, const esp_flash_spi_d * * @return * - ESP_ERR_INVALID_ARG: The chip is invalid. + * - ESP_ERR_INVALID_STATE: The chip is still acquiring the SPI bus lock. * - ESP_OK: success. */ esp_err_t spi_bus_remove_flash_device(esp_flash_t *chip); diff --git a/components/spi_flash/include/esp_private/esp_flash_internal.h b/components/spi_flash/include/esp_private/esp_flash_internal.h index b8e14e452ec..e3523c0e3df 100644 --- a/components/spi_flash/include/esp_private/esp_flash_internal.h +++ b/components/spi_flash/include/esp_private/esp_flash_internal.h @@ -70,7 +70,9 @@ esp_err_t esp_flash_init_os_functions(esp_flash_t *chip, int host_id, spi_bus_lo * @param chip The chip to deinit os functions * @param out_dev_handle The SPI bus lock passed from `esp_flash_init_os_functions`. The caller should deinitialize * the lock. - * @return always ESP_OK. + * @return + * - ESP_ERR_INVALID_STATE: the chip is still acquiring the SPI bus lock. + * - ESP_OK: success. */ esp_err_t esp_flash_deinit_os_functions(esp_flash_t* chip, spi_bus_lock_dev_handle_t* out_dev_handle); diff --git a/components/spi_flash/spi_flash_os_func_app.c b/components/spi_flash/spi_flash_os_func_app.c index e633b18b083..b38af2aefb2 100644 --- a/components/spi_flash/spi_flash_os_func_app.c +++ b/components/spi_flash/spi_flash_os_func_app.c @@ -488,9 +488,15 @@ esp_err_t esp_flash_init_os_functions(esp_flash_t *chip, int host_id, spi_bus_lo esp_err_t esp_flash_deinit_os_functions(esp_flash_t* chip, spi_bus_lock_dev_handle_t* out_dev_handle) { + *out_dev_handle = NULL; if (chip->os_func_data) { + app_func_arg_t *ctx = (app_func_arg_t*)chip->os_func_data; + spi_bus_lock_dev_handle_t dev_handle = ctx->dev_lock; + if (dev_handle && spi_bus_lock_get_acquiring_dev(spi_bus_lock_get_parent(dev_handle)) == dev_handle) { + return ESP_ERR_INVALID_STATE; + } // SPI bus lock is possibly not used on SPI1 bus - *out_dev_handle = ((app_func_arg_t*)chip->os_func_data)->dev_lock; + *out_dev_handle = dev_handle; free(chip->os_func_data); } chip->os_func = NULL; From 6c857b01c7287759b22d3dd4f9a0236daa8e5a8c Mon Sep 17 00:00:00 2001 From: Eric Wang Date: Tue, 28 Jul 2026 13:29:17 -0700 Subject: [PATCH 2/3] fix(driver_spi): avoid NULL memcpy when private DMA buffer setup fails Closes https://github.com/espressif/esp-idf/pull/18898 --- components/esp_driver_spi/src/gpspi/spi_master.c | 2 +- components/esp_driver_spi/src/gpspi/spi_slave.c | 2 +- components/esp_driver_spi/src/gpspi/spi_slave_hd.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/components/esp_driver_spi/src/gpspi/spi_master.c b/components/esp_driver_spi/src/gpspi/spi_master.c index e2dc26bec85..7b09f236cfc 100644 --- a/components/esp_driver_spi/src/gpspi/spi_master.c +++ b/components/esp_driver_spi/src/gpspi/spi_master.c @@ -1165,7 +1165,7 @@ static SPI_MASTER_ISR_ATTR void uninstall_priv_desc(spi_trans_priv_t* trans_buf) // copy data from temporary DMA-capable buffer back to trans_desc buffer and free the temporary one. void *orig_rx_buffer = (trans_desc->flags & SPI_TRANS_USE_RXDATA) ? trans_desc->rx_data : trans_desc->rx_buffer; - if (trans_buf->buffer_to_rcv != orig_rx_buffer) { + if (trans_buf->buffer_to_rcv && trans_buf->buffer_to_rcv != orig_rx_buffer) { memcpy(orig_rx_buffer, trans_buf->buffer_to_rcv, (trans_desc->rxlength + 7) / 8); free(trans_buf->buffer_to_rcv); } diff --git a/components/esp_driver_spi/src/gpspi/spi_slave.c b/components/esp_driver_spi/src/gpspi/spi_slave.c index 9beff65602a..ec041bb5c43 100644 --- a/components/esp_driver_spi/src/gpspi/spi_slave.c +++ b/components/esp_driver_spi/src/gpspi/spi_slave.c @@ -413,7 +413,7 @@ static void SPI_SLAVE_ISR_ATTR spi_slave_uninstall_priv_trans(spi_host_device_t if (trans->tx_buffer && (trans->tx_buffer != priv_trans->tx_buffer)) { free(priv_trans->tx_buffer); } - if (trans->rx_buffer && (trans->rx_buffer != priv_trans->rx_buffer)) { + if (priv_trans->rx_buffer && (trans->rx_buffer != priv_trans->rx_buffer)) { size_t compatible_len = trans->rx_length ? trans->rx_length : trans->length; memcpy(trans->rx_buffer, priv_trans->rx_buffer, (MIN(compatible_len, trans->trans_len) + 7) / 8); free(priv_trans->rx_buffer); diff --git a/components/esp_driver_spi/src/gpspi/spi_slave_hd.c b/components/esp_driver_spi/src/gpspi/spi_slave_hd.c index 0c32ba5da27..e09d263cc02 100644 --- a/components/esp_driver_spi/src/gpspi/spi_slave_hd.c +++ b/components/esp_driver_spi/src/gpspi/spi_slave_hd.c @@ -698,7 +698,7 @@ static SPI_SLAVE_ISR_ATTR void s_spi_slave_hd_append_legacy_isr(void *arg) static void s_spi_slave_hd_destroy_priv_trans(spi_host_device_t host, spi_slave_hd_trans_priv_t *priv_trans, spi_slave_chan_t chan) { spi_slave_hd_data_t *orig_trans = priv_trans->trans; - if (priv_trans->aligned_buffer != orig_trans->data) { + if (priv_trans->aligned_buffer && priv_trans->aligned_buffer != orig_trans->data) { if (chan == SPI_SLAVE_CHAN_RX) { memcpy(orig_trans->data, priv_trans->aligned_buffer, orig_trans->trans_len); } From 6431436b0368f40409b50bf23e21d3b9e1de43d0 Mon Sep 17 00:00:00 2001 From: wanckl Date: Thu, 30 Jul 2026 16:01:27 +0800 Subject: [PATCH 3/3] fix(driver_spi): slave hd append fix wrong dma param --- components/esp_driver_spi/src/gpspi/spi_slave_hd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/esp_driver_spi/src/gpspi/spi_slave_hd.c b/components/esp_driver_spi/src/gpspi/spi_slave_hd.c index e09d263cc02..67b3d57266c 100644 --- a/components/esp_driver_spi/src/gpspi/spi_slave_hd.c +++ b/components/esp_driver_spi/src/gpspi/spi_slave_hd.c @@ -792,7 +792,7 @@ esp_err_t s_spi_slave_hd_append_rxdma(spi_slave_hd_slot_t *host, uint8_t *data, return ESP_ERR_INVALID_STATE; } - spicommon_dma_desc_setup_link(hal->rx_cur_desc->desc, data, len, false); + spicommon_dma_desc_setup_link(hal->rx_cur_desc->desc, data, len, true); hal->rx_cur_desc->arg = arg; if (!hal->rx_used_desc_cnt) {