From a9a36512a8201e15d7979ed0e110beba34ba4055 Mon Sep 17 00:00:00 2001 From: Armando Date: Tue, 2 Jan 2024 13:09:56 +0800 Subject: [PATCH] bugfix(dma): fixed wrong esp_dma_is_buffer_aligned result for psram on s3 --- components/esp_hw_support/dma/esp_dma_utils.c | 57 ++++++++++++------- .../esp_hw_support/include/esp_dma_utils.h | 1 + 2 files changed, 36 insertions(+), 22 deletions(-) diff --git a/components/esp_hw_support/dma/esp_dma_utils.c b/components/esp_hw_support/dma/esp_dma_utils.c index 5db42309c2..6dd01cf863 100644 --- a/components/esp_hw_support/dma/esp_dma_utils.c +++ b/components/esp_hw_support/dma/esp_dma_utils.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -69,41 +69,54 @@ esp_err_t esp_dma_calloc(size_t n, size_t size, uint32_t flags, void **out_ptr, return ret; } +static bool s_buf_in_region(const void *ptr, size_t size, esp_dma_buf_location_t location, uint32_t *in_out_flags) +{ + bool found = false; + if (location == ESP_DMA_BUF_LOCATION_INTERNAL) { + if (esp_ptr_dma_capable(ptr) && esp_ptr_dma_capable(ptr + size - 1)) { + found = true; + } + } else if (location == ESP_DMA_BUF_LOCATION_PSRAM) { +#if SOC_PSRAM_DMA_CAPABLE + if (esp_ptr_external_ram(ptr) && esp_ptr_external_ram(ptr + size - 1)) { + *in_out_flags |= ESP_DMA_MALLOC_FLAG_PSRAM; + found = true; + } +#endif + } + return found; +} + bool esp_dma_is_buffer_aligned(const void *ptr, size_t size, esp_dma_buf_location_t location) { assert(ptr); uint32_t flags = ESP_CACHE_MALLOC_FLAG_DMA; - if (location == ESP_DMA_BUF_LOCATION_INTERNAL) { - if (!esp_ptr_dma_capable(ptr) || !esp_ptr_dma_capable(ptr + size - 1)) { - return false; + bool found = false; + if (location == ESP_DMA_BUF_LOCATION_AUTO) { + for (int i = ESP_DMA_BUF_LOCATION_INTERNAL; i < ESP_DMA_BUF_LOCATION_AUTO; i++) { + if (s_buf_in_region(ptr, size, i, &flags)) { + found = true; + break; + } } + } else if (location == ESP_DMA_BUF_LOCATION_INTERNAL) { + found = s_buf_in_region(ptr, size, ESP_DMA_BUF_LOCATION_INTERNAL, &flags); } else { -#if !SOC_PSRAM_DMA_CAPABLE + found = s_buf_in_region(ptr, size, ESP_DMA_BUF_LOCATION_PSRAM, &flags); + } + if (!found) { return false; -#endif - if (!esp_ptr_external_ram(ptr) || !esp_ptr_external_ram(ptr + size - 1)) { - return false; - } - - flags |= ESP_DMA_MALLOC_FLAG_PSRAM; } bool is_aligned = false; - -#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE + size_t dma_alignment = 0; size_t cache_alignment = 0; + size_t alignment = 0; esp_err_t ret = esp_cache_get_alignment(flags, &cache_alignment); assert(ret == ESP_OK); - if (((intptr_t)ptr % cache_alignment == 0) && (size % cache_alignment == 0)) { - is_aligned = true; - } -#else - (void)size; - if ((intptr_t)ptr % 4 == 0) { - is_aligned = true; - } -#endif + alignment = MAX(dma_alignment, cache_alignment); + is_aligned = ((intptr_t)ptr % alignment == 0) && (size % alignment == 0); return is_aligned; } diff --git a/components/esp_hw_support/include/esp_dma_utils.h b/components/esp_hw_support/include/esp_dma_utils.h index 3c59db9008..747cd1b31b 100644 --- a/components/esp_hw_support/include/esp_dma_utils.h +++ b/components/esp_hw_support/include/esp_dma_utils.h @@ -59,6 +59,7 @@ esp_err_t esp_dma_calloc(size_t n, size_t size, uint32_t flags, void **out_ptr, typedef enum { ESP_DMA_BUF_LOCATION_INTERNAL, ///< DMA buffer is in internal memory ESP_DMA_BUF_LOCATION_PSRAM, ///< DMA buffer is in PSRAM + ESP_DMA_BUF_LOCATION_AUTO, ///< Auto detect buffer location, under this condition API will loop to search the buffer location } esp_dma_buf_location_t; /**