From 6b6065de509b5de39e4655fd425bf96f43b365f7 Mon Sep 17 00:00:00 2001 From: wanckl Date: Tue, 27 Aug 2024 20:01:56 +0800 Subject: [PATCH] fix(driver_spi): fix p4 cache auto writeback during spi(dma) rx --- .../esp_driver_spi/src/gpspi/spi_master.c | 23 ++++++++++++------- .../esp_driver_spi/src/gpspi/spi_slave.c | 22 ++++++++++-------- .../esp_driver_spi/src/gpspi/spi_slave_hd.c | 3 +++ 3 files changed, 31 insertions(+), 17 deletions(-) diff --git a/components/esp_driver_spi/src/gpspi/spi_master.c b/components/esp_driver_spi/src/gpspi/spi_master.c index d359f8f1b28..e565e42d160 100644 --- a/components/esp_driver_spi/src/gpspi/spi_master.c +++ b/components/esp_driver_spi/src/gpspi/spi_master.c @@ -1161,15 +1161,22 @@ static SPI_MASTER_ISR_ATTR esp_err_t setup_priv_desc(spi_host_t *host, spi_trans #endif } - if (rcv_ptr && bus_attr->dma_enabled && (!esp_ptr_dma_capable(rcv_ptr) || rx_unaligned)) { - ESP_RETURN_ON_FALSE(!(trans_desc->flags & SPI_TRANS_DMA_BUFFER_ALIGN_MANUAL), ESP_ERR_INVALID_ARG, SPI_TAG, "Set flag SPI_TRANS_DMA_BUFFER_ALIGN_MANUAL but RX buffer addr&len not align to %d, or not dma_capable", alignment); - //if rxbuf in the desc not DMA-capable, or not aligned to alignment, malloc a new one - ESP_EARLY_LOGD(SPI_TAG, "Allocate RX buffer for DMA"); - rx_byte_len = (rx_byte_len + alignment - 1) & (~(alignment - 1)); // up align alignment - rcv_ptr = heap_caps_aligned_alloc(alignment, rx_byte_len, MALLOC_CAP_DMA); - if (rcv_ptr == NULL) { - goto clean_up; + if (rcv_ptr && bus_attr->dma_enabled) { + if ((!esp_ptr_dma_capable(rcv_ptr) || rx_unaligned)) { + ESP_RETURN_ON_FALSE(!(trans_desc->flags & SPI_TRANS_DMA_BUFFER_ALIGN_MANUAL), ESP_ERR_INVALID_ARG, SPI_TAG, "Set flag SPI_TRANS_DMA_BUFFER_ALIGN_MANUAL but RX buffer addr&len not align to %d, or not dma_capable", alignment); + //if rxbuf in the desc not DMA-capable, or not aligned to alignment, malloc a new one + ESP_EARLY_LOGD(SPI_TAG, "Allocate RX buffer for DMA"); + rx_byte_len = (rx_byte_len + alignment - 1) & (~(alignment - 1)); // up align alignment + rcv_ptr = heap_caps_aligned_alloc(alignment, rx_byte_len, MALLOC_CAP_DMA); + if (rcv_ptr == NULL) { + goto clean_up; + } } +#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE + // do invalid here to hold on cache status to avoid hardware auto write back during dma transaction + esp_err_t ret = esp_cache_msync((void *)rcv_ptr, rx_byte_len, ESP_CACHE_MSYNC_FLAG_DIR_M2C); + assert(ret == ESP_OK); +#endif } priv_desc->buffer_to_send = send_ptr; priv_desc->buffer_to_rcv = rcv_ptr; diff --git a/components/esp_driver_spi/src/gpspi/spi_slave.c b/components/esp_driver_spi/src/gpspi/spi_slave.c index 9ebdc6e8f0f..65b011675d0 100644 --- a/components/esp_driver_spi/src/gpspi/spi_slave.c +++ b/components/esp_driver_spi/src/gpspi/spi_slave.c @@ -347,16 +347,20 @@ static esp_err_t SPI_SLAVE_ISR_ATTR spi_slave_setup_priv_trans(spi_host_device_t esp_err_t ret = esp_cache_msync((void *)priv_trans->tx_buffer, buffer_byte_len, ESP_CACHE_MSYNC_FLAG_DIR_C2M); ESP_RETURN_ON_FALSE_ISR(ESP_OK == ret, ESP_ERR_INVALID_STATE, SPI_TAG, "mem sync c2m(writeback) fail"); } - if (spihost[host]->dma_enabled && trans->rx_buffer && (!esp_ptr_dma_capable(trans->rx_buffer) || ((((uint32_t)trans->rx_buffer) | (trans->length + 7) / 8) & (alignment - 1)))) { - ESP_RETURN_ON_FALSE_ISR(trans->flags & SPI_SLAVE_TRANS_DMA_BUFFER_ALIGN_AUTO, ESP_ERR_INVALID_ARG, SPI_TAG, "RX buffer addr&len not align to %d, or not dma_capable", alignment); - //if rxbuf in the desc not DMA-capable, or not align to "alignment", malloc a new one - ESP_EARLY_LOGD(SPI_TAG, "Allocate RX buffer for DMA"); - buffer_byte_len = (buffer_byte_len + alignment - 1) & (~(alignment - 1)); // up align to "alignment" - priv_trans->rx_buffer = heap_caps_aligned_alloc(alignment, buffer_byte_len, MALLOC_CAP_DMA); - if (priv_trans->rx_buffer == NULL) { - free(priv_trans->tx_buffer); - return ESP_ERR_NO_MEM; + if (spihost[host]->dma_enabled && trans->rx_buffer) { + if ((!esp_ptr_dma_capable(trans->rx_buffer) || ((((uint32_t)trans->rx_buffer) | (trans->length + 7) / 8) & (alignment - 1)))) { + ESP_RETURN_ON_FALSE_ISR(trans->flags & SPI_SLAVE_TRANS_DMA_BUFFER_ALIGN_AUTO, ESP_ERR_INVALID_ARG, SPI_TAG, "RX buffer addr&len not align to %d, or not dma_capable", alignment); + //if rxbuf in the desc not DMA-capable, or not align to "alignment", malloc a new one + ESP_EARLY_LOGD(SPI_TAG, "Allocate RX buffer for DMA"); + buffer_byte_len = (buffer_byte_len + alignment - 1) & (~(alignment - 1)); // up align to "alignment" + priv_trans->rx_buffer = heap_caps_aligned_alloc(alignment, buffer_byte_len, MALLOC_CAP_DMA); + if (priv_trans->rx_buffer == NULL) { + free(priv_trans->tx_buffer); + return ESP_ERR_NO_MEM; + } } + esp_err_t ret = esp_cache_msync((void *)priv_trans->rx_buffer, buffer_byte_len, ESP_CACHE_MSYNC_FLAG_DIR_M2C); + ESP_RETURN_ON_FALSE_ISR(ESP_OK == ret, ESP_ERR_INVALID_STATE, SPI_TAG, "mem sync m2c(invalid) fail"); } #endif //SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE return ESP_OK; 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 4c145445c1a..ba79b9eb23c 100644 --- a/components/esp_driver_spi/src/gpspi/spi_slave_hd.c +++ b/components/esp_driver_spi/src/gpspi/spi_slave_hd.c @@ -609,6 +609,9 @@ static esp_err_t s_spi_slave_hd_setup_priv_trans(spi_host_device_t host, spi_sla memcpy(priv_trans->aligned_buffer, orig_trans->data, orig_trans->len); esp_err_t ret = esp_cache_msync((void *)priv_trans->aligned_buffer, byte_len, ESP_CACHE_MSYNC_FLAG_DIR_C2M); ESP_RETURN_ON_FALSE(ESP_OK == ret, ESP_ERR_INVALID_STATE, TAG, "mem sync c2m(writeback) fail"); + } else { + esp_err_t ret = esp_cache_msync((void *)priv_trans->aligned_buffer, byte_len, ESP_CACHE_MSYNC_FLAG_DIR_M2C); + ESP_RETURN_ON_FALSE(ESP_OK == ret, ESP_ERR_INVALID_STATE, TAG, "mem sync m2c(invalid) fail"); } #endif //SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE return ESP_OK;