fix(driver_spi): fixes psram dma rx buffer memory barrier issue

This commit is contained in:
wanckl
2026-03-16 14:01:48 +08:00
parent 88e4c52b19
commit 21b37a672a
5 changed files with 29 additions and 4 deletions
@@ -154,6 +154,14 @@ void spicommon_dma_desc_setup_link(spi_dma_desc_t *dmadesc, const void *data, in
*/
esp_err_t spicommon_dma_setup_priv_buffer(spi_host_device_t host_id, uint32_t *buffer, uint32_t len, bool is_tx, bool psram_prefer, bool auto_malloc, uint32_t **ret_buffer);
/**
* @brief Memory barrier for DMA RX buffer
*
* @param host_id SPI host ID
* @param rx_buffer RX buffer
*/
void spicommon_dma_rx_mb(spi_host_device_t host_id, void *rx_buffer);
/**
* @brief Free DMA for SPI
*
@@ -30,6 +30,9 @@
#if CONFIG_IDF_TARGET_ESP32
#include "soc/dport_reg.h"
#endif
#if CONFIG_SPIRAM
#include "esp_private/esp_psram_mspi.h"
#endif
#if SOC_PERIPH_CLK_CTRL_SHARED
#define SPI_COMMON_PERI_CLOCK_ATOMIC() PERIPH_RCC_ATOMIC()
@@ -438,6 +441,17 @@ esp_err_t SPI_COMMON_ISR_ATTR spicommon_dma_setup_priv_buffer(spi_host_device_t
return ESP_OK;
}
void SPI_COMMON_ISR_ATTR spicommon_dma_rx_mb(spi_host_device_t host_id, void *rx_buffer)
{
(void)host_id;
#if SOC_PSRAM_DMA_CAPABLE && CONFIG_SPIRAM
if (esp_ptr_external_ram(rx_buffer)) {
// dma rx data to psram need memory barrier fix
esp_psram_mspi_mb();
}
#endif
}
//----------------------------------------------------------free dma periph-------------------------------------------------------//
esp_err_t spicommon_dma_chan_free(spi_host_device_t host_id)
{
@@ -1002,6 +1002,7 @@ static void SPI_MASTER_ISR_ATTR spi_intr(void *arg)
//This workaround is only for esp32, where tx_dma_chan and rx_dma_chan are always same
spicommon_dmaworkaround_idle(dma_ctx->tx_dma_chan.chan_id);
#endif //#if CONFIG_IDF_TARGET_ESP32
spicommon_dma_rx_mb(host->id, host->cur_trans_buf.buffer_to_rcv);
spi_trans_dma_error_check(host);
}
@@ -1429,6 +1430,7 @@ esp_err_t SPI_MASTER_ISR_ATTR spi_device_polling_end(spi_device_handle_t handle,
return ESP_ERR_TIMEOUT;
}
}
spicommon_dma_rx_mb(host->id, host->cur_trans_buf.buffer_to_rcv);
spi_trans_dma_error_check(host);
uint32_t trans_flags = host->cur_trans_buf.trans->flags; // save the flags before bus_lock release
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -654,6 +654,7 @@ static void SPI_SLAVE_ISR_ATTR spi_intr(void *arg)
// When DMA is enabled, the slave rx dma suffers from unexpected transactions. Forbid reading until transaction ready.
if (use_dma) {
freeze_cs(host);
spicommon_dma_rx_mb(host->id, host->cur_trans.rx_buffer);
spi_slave_trans_dma_error_check(host);
}
@@ -8,6 +8,7 @@
#include "esp_compiler.h"
#include "esp_log.h"
#include "esp_check.h"
#include "esp_cache.h"
#include "esp_memory_utils.h"
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
@@ -19,9 +20,6 @@
#include "esp_private/esp_cache_private.h"
#include "driver/spi_slave_hd.h"
#include "hal/spi_slave_hd_hal.h"
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
#include "esp_cache.h"
#endif
#ifdef CONFIG_SPI_SLAVE_ISR_IN_IRAM
#define SPI_SLAVE_ISR_ATTR IRAM_ATTR
@@ -476,6 +474,7 @@ static SPI_SLAVE_ISR_ATTR void s_spi_slave_hd_segment_isr(void *arg)
host->tx_curr_trans.trans = NULL;
}
if (rx_done) {
spicommon_dma_rx_mb(host->host_id, host->rx_curr_trans.aligned_buffer);
spi_slave_hd_rx_dma_error_check(host, host->rx_curr_trans);
bool ret_queue = true;
host->rx_curr_trans.trans->trans_len = spi_slave_hd_hal_rxdma_seg_get_len(hal);
@@ -617,6 +616,7 @@ static SPI_SLAVE_ISR_ATTR void spi_slave_hd_append_rx_isr(void *arg)
ret_priv_trans.trans->trans_len = trans_len;
bool ret_queue = true;
spicommon_dma_rx_mb(host->host_id, ret_priv_trans.aligned_buffer);
spi_slave_hd_rx_dma_error_check(host, ret_priv_trans);
if (callback->cb_recv) {
spi_slave_hd_event_t ev = {