mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
feat(dma): refactor dma calloc function
This commit is contained in:
parent
78f96c4466
commit
40f38bea6f
@ -1,4 +1,4 @@
|
||||
[codespell]
|
||||
skip = build,*.yuv,components/fatfs/src/*,alice.txt,*.rgb
|
||||
ignore-words-list = ser,dout,rsource,fram,inout
|
||||
ignore-words-list = ser,dout,rsource,fram,inout,shs
|
||||
write-changes = true
|
||||
|
@ -576,9 +576,10 @@ static esp_err_t i2s_alloc_dma_buffer(i2s_port_t i2s_num, i2s_dma_t *dma_obj)
|
||||
for (int cnt = 0; cnt < buf_cnt; cnt++) {
|
||||
/* Allocate DMA buffer */
|
||||
esp_dma_mem_info_t dma_mem_info = {
|
||||
.heap_caps = MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA,
|
||||
.dma_alignment = 4,
|
||||
.extra_heap_caps = MALLOC_CAP_INTERNAL,
|
||||
.dma_alignment_bytes = 4,
|
||||
};
|
||||
//TODO: IDF-9636
|
||||
esp_dma_capable_calloc(1, sizeof(char) * dma_obj->buf_size, &dma_mem_info, (void **)&dma_obj->buf[cnt], NULL);
|
||||
ESP_GOTO_ON_FALSE(dma_obj->buf[cnt], ESP_ERR_NO_MEM, err, TAG, "Error malloc dma buffer");
|
||||
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
|
||||
@ -587,7 +588,6 @@ static esp_err_t i2s_alloc_dma_buffer(i2s_port_t i2s_num, i2s_dma_t *dma_obj)
|
||||
|
||||
/* Allocate DMA descriptor */
|
||||
esp_dma_capable_calloc(1, sizeof(lldesc_t), &dma_mem_info, (void **)&dma_obj->desc[cnt], &desc_size);
|
||||
// esp_dma_calloc(1, sizeof(lldesc_t), MALLOC_CAP_DEFAULT, (void **)&dma_obj->desc[cnt], &desc_size);
|
||||
ESP_GOTO_ON_FALSE(dma_obj->desc[cnt], ESP_ERR_NO_MEM, err, TAG, "Error malloc dma description entry");
|
||||
}
|
||||
/* DMA descriptor must be initialize after all descriptor has been created, otherwise they can't be linked together as a chain */
|
||||
|
@ -69,32 +69,15 @@
|
||||
static const char *TAG = "i2s_common";
|
||||
|
||||
__attribute__((always_inline))
|
||||
inline void *i2s_dma_calloc(i2s_chan_handle_t handle, size_t num, size_t size, bool is_desc, size_t *actual_size)
|
||||
inline void *i2s_dma_calloc(i2s_chan_handle_t handle, size_t num, size_t size, size_t *actual_size)
|
||||
{
|
||||
esp_err_t ret = ESP_FAIL;
|
||||
void *ptr = NULL;
|
||||
|
||||
size_t dma_alignment = 0;
|
||||
void *gdma_chan_handle = NULL;
|
||||
#if SOC_GDMA_SUPPORTED
|
||||
gdma_chan_handle = handle->dma.dma_chan;
|
||||
#endif
|
||||
dma_alignment_info_t info = {
|
||||
.is_desc = is_desc,
|
||||
};
|
||||
ret = esp_dma_get_alignment(gdma_chan_handle, &info, &dma_alignment);
|
||||
assert(ret == ESP_OK);
|
||||
|
||||
esp_dma_mem_info_t dma_mem_info = {
|
||||
.heap_caps = MALLOC_CAP_DMA,
|
||||
.dma_alignment = 4,
|
||||
.extra_heap_caps = I2S_DMA_ALLOC_CAPS,
|
||||
.dma_alignment_bytes = 4,
|
||||
};
|
||||
//TODO: IDF-9636
|
||||
esp_dma_capable_calloc(num, size, &dma_mem_info, &ptr, actual_size);
|
||||
#if CONFIG_IDF_TARGET_ESP32P4
|
||||
assert((int)ptr % 64 == 0);
|
||||
#else
|
||||
assert((int)ptr % 4 == 0);
|
||||
#endif
|
||||
return ptr;
|
||||
}
|
||||
|
||||
@ -444,7 +427,7 @@ esp_err_t i2s_alloc_dma_desc(i2s_chan_handle_t handle, uint32_t num, uint32_t bu
|
||||
size_t desc_size = 0;
|
||||
for (int i = 0; i < num; i++) {
|
||||
/* Allocate DMA descriptor */
|
||||
handle->dma.desc[i] = (lldesc_t *) i2s_dma_calloc(handle, 1, sizeof(lldesc_t), true, &desc_size);
|
||||
handle->dma.desc[i] = (lldesc_t *) i2s_dma_calloc(handle, 1, sizeof(lldesc_t), &desc_size);
|
||||
ESP_GOTO_ON_FALSE(handle->dma.desc[i], ESP_ERR_NO_MEM, err, TAG, "allocate DMA description failed");
|
||||
handle->dma.desc[i]->owner = 1;
|
||||
handle->dma.desc[i]->eof = 1;
|
||||
@ -452,7 +435,7 @@ esp_err_t i2s_alloc_dma_desc(i2s_chan_handle_t handle, uint32_t num, uint32_t bu
|
||||
handle->dma.desc[i]->length = bufsize;
|
||||
handle->dma.desc[i]->size = bufsize;
|
||||
handle->dma.desc[i]->offset = 0;
|
||||
handle->dma.bufs[i] = (uint8_t *) i2s_dma_calloc(handle, 1, bufsize * sizeof(uint8_t), false, NULL);
|
||||
handle->dma.bufs[i] = (uint8_t *) i2s_dma_calloc(handle, 1, bufsize * sizeof(uint8_t), NULL);
|
||||
ESP_GOTO_ON_FALSE(handle->dma.bufs[i], ESP_ERR_NO_MEM, err, TAG, "allocate DMA buffer failed");
|
||||
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
|
||||
esp_cache_msync(handle->dma.bufs[i], bufsize * sizeof(uint8_t), ESP_CACHE_MSYNC_FLAG_DIR_C2M);
|
||||
|
@ -176,7 +176,11 @@ esp_err_t jpeg_decoder_process(jpeg_decoder_handle_t decoder_engine, const jpeg_
|
||||
ESP_RETURN_ON_FALSE(decoder_engine, ESP_ERR_INVALID_ARG, TAG, "jpeg decode handle is null");
|
||||
ESP_RETURN_ON_FALSE(decode_cfg, ESP_ERR_INVALID_ARG, TAG, "jpeg decode config is null");
|
||||
ESP_RETURN_ON_FALSE(decode_outbuf, ESP_ERR_INVALID_ARG, TAG, "jpeg decode picture buffer is null");
|
||||
ESP_RETURN_ON_FALSE(esp_dma_is_buffer_aligned(decode_outbuf, outbuf_size, ESP_DMA_BUF_LOCATION_PSRAM), ESP_ERR_INVALID_ARG, TAG, "jpeg decode decode_outbuf or out_buffer size is not aligned, please use jpeg_alloc_decoder_mem to malloc your buffer");
|
||||
esp_dma_mem_info_t dma_mem_info = {
|
||||
.dma_alignment_bytes = 4,
|
||||
};
|
||||
//TODO: IDF-9637
|
||||
ESP_RETURN_ON_FALSE(esp_dma_is_buffer_alignment_satisfied(decode_outbuf, outbuf_size, dma_mem_info), ESP_ERR_INVALID_ARG, TAG, "jpeg decode decode_outbuf or out_buffer size is not aligned, please use jpeg_alloc_decoder_mem to malloc your buffer");
|
||||
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
||||
|
@ -46,6 +46,7 @@ extern "C" {
|
||||
.set_input_delay = &sdmmc_host_set_input_delay, \
|
||||
.dma_aligned_buffer = NULL, \
|
||||
.pwr_ctrl_handle = NULL, \
|
||||
.get_dma_info = &sdmmc_host_get_dma_info, \
|
||||
}
|
||||
|
||||
#define SDMMC_SLOT_NO_CD GPIO_NUM_NC ///< indicates that card detect line is not used
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -247,6 +247,17 @@ esp_err_t sdmmc_host_get_real_freq(int slot, int* real_freq_khz);
|
||||
*/
|
||||
esp_err_t sdmmc_host_set_input_delay(int slot, sdmmc_delay_phase_t delay_phase);
|
||||
|
||||
/**
|
||||
* @brief Get the DMA memory information for the host driver
|
||||
*
|
||||
* @param[in] slot slot number (SDMMC_HOST_SLOT_0 or SDMMC_HOST_SLOT_1)
|
||||
* @param[out] dma_mem_info DMA memory information structure
|
||||
* @return
|
||||
* - ESP_OK: ON success.
|
||||
* - ESP_ERR_INVALID_ARG: Invalid argument.
|
||||
*/
|
||||
esp_err_t sdmmc_host_get_dma_info(int slot, esp_dma_mem_info_t *dma_mem_info);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -921,3 +921,13 @@ static esp_err_t sdmmc_host_pullup_en_internal(int slot, int width)
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t sdmmc_host_get_dma_info(int slot, esp_dma_mem_info_t *dma_mem_info)
|
||||
{
|
||||
if (!(slot == 0 || slot == 1)) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
dma_mem_info->extra_heap_caps = MALLOC_CAP_DMA;
|
||||
dma_mem_info->dma_alignment_bytes = 4;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -53,7 +53,8 @@ typedef int sdspi_dev_handle_t;
|
||||
.command_timeout_ms = 0, \
|
||||
.get_real_freq = &sdspi_host_get_real_freq, \
|
||||
.input_delay_phase = SDMMC_DELAY_PHASE_0, \
|
||||
.set_input_delay = NULL \
|
||||
.set_input_delay = NULL, \
|
||||
.get_dma_info = &sdspi_host_get_dma_info, \
|
||||
}
|
||||
|
||||
/**
|
||||
@ -209,6 +210,17 @@ esp_err_t sdspi_host_io_int_enable(sdspi_dev_handle_t handle);
|
||||
*/
|
||||
esp_err_t sdspi_host_io_int_wait(sdspi_dev_handle_t handle, TickType_t timeout_ticks);
|
||||
|
||||
/**
|
||||
* @brief Get the DMA memory information for the host driver
|
||||
*
|
||||
* @param[in] slot Not used
|
||||
* @param[out] dma_mem_info DMA memory information structure
|
||||
* @return
|
||||
* - ESP_OK: ON success.
|
||||
* - ESP_ERR_INVALID_ARG: Invalid argument.
|
||||
*/
|
||||
esp_err_t sdspi_host_get_dma_info(int slot, esp_dma_mem_info_t *dma_mem_info);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -998,3 +998,11 @@ esp_err_t sdspi_host_io_int_wait(sdspi_dev_handle_t handle, TickType_t timeout_t
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t sdspi_host_get_dma_info(int slot, esp_dma_mem_info_t *dma_mem_info)
|
||||
{
|
||||
(void)slot;
|
||||
dma_mem_info->extra_heap_caps = MALLOC_CAP_DMA;
|
||||
dma_mem_info->dma_alignment_bytes = 4;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
@ -385,7 +385,7 @@ uint8_t *emac_esp_dma_alloc_recv_buf(emac_esp_dma_handle_t emac_esp_dma, uint32_
|
||||
buf = malloc(copy_len);
|
||||
if (buf != NULL) {
|
||||
emac_esp_dma_auto_buf_info_t *buff_info = (emac_esp_dma_auto_buf_info_t *)buf;
|
||||
/* no need to check allocated buffer min lenght prior writing since we know that EMAC DMA is configured to
|
||||
/* no need to check allocated buffer min length prior writing since we know that EMAC DMA is configured to
|
||||
not forward erroneous or undersized frames (less than 64B) on ESP32, see emac_hal_init_dma_default */
|
||||
#ifndef NDEBUG
|
||||
buff_info->magic_id = EMAC_HAL_BUF_MAGIC_ID;
|
||||
@ -532,8 +532,8 @@ esp_err_t emac_esp_new_dma(const emac_esp_dma_config_t* config, emac_esp_dma_han
|
||||
uint32_t desc_size = CONFIG_ETH_DMA_RX_BUFFER_NUM * sizeof(eth_dma_rx_descriptor_t) +
|
||||
CONFIG_ETH_DMA_TX_BUFFER_NUM * sizeof(eth_dma_tx_descriptor_t);
|
||||
esp_dma_mem_info_t dma_mem_info = {
|
||||
.heap_caps = MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA,
|
||||
.dma_alignment = 4,
|
||||
.extra_heap_caps = MALLOC_CAP_INTERNAL,
|
||||
.dma_alignment_bytes = 4,
|
||||
};
|
||||
esp_dma_capable_calloc(1, desc_size, &dma_mem_info, (void*)&emac_esp_dma->descriptors, NULL);
|
||||
|
||||
|
@ -14,7 +14,6 @@
|
||||
#include "esp_memory_utils.h"
|
||||
#include "esp_dma_utils.h"
|
||||
#include "esp_private/esp_cache_private.h"
|
||||
#include "esp_private/gdma.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include "hal/hal_utils.h"
|
||||
|
||||
@ -28,33 +27,31 @@ esp_err_t esp_dma_capable_malloc(size_t size, const esp_dma_mem_info_t *dma_mem_
|
||||
{
|
||||
ESP_RETURN_ON_FALSE_ISR(dma_mem_info && out_ptr, ESP_ERR_INVALID_ARG, TAG, "null pointer");
|
||||
|
||||
size_t alignment = 1;
|
||||
size_t alignment_bytes = 0;
|
||||
|
||||
//dma align
|
||||
size_t dma_alignment = dma_mem_info->dma_alignment;
|
||||
|
||||
//custom align
|
||||
size_t custom_alignment = dma_mem_info->custom_alignment;
|
||||
size_t dma_alignment_bytes = dma_mem_info->dma_alignment_bytes;
|
||||
|
||||
//cache align
|
||||
int cache_flags = 0;
|
||||
size_t cache_alignment = 1;
|
||||
if (dma_mem_info->heap_caps & MALLOC_CAP_SPIRAM) {
|
||||
size_t cache_alignment_bytes = 0;
|
||||
|
||||
int heap_caps = dma_mem_info->extra_heap_caps | MALLOC_CAP_DMA;
|
||||
if (dma_mem_info->extra_heap_caps & MALLOC_CAP_SPIRAM) {
|
||||
cache_flags |= ESP_DMA_MALLOC_FLAG_PSRAM;
|
||||
heap_caps = dma_mem_info->extra_heap_caps | MALLOC_CAP_SPIRAM;
|
||||
}
|
||||
esp_err_t ret = esp_cache_get_alignment(cache_flags, &cache_alignment);
|
||||
|
||||
esp_err_t ret = esp_cache_get_alignment(cache_flags, &cache_alignment_bytes);
|
||||
assert(ret == ESP_OK);
|
||||
|
||||
//lcm3
|
||||
alignment = _lcm_3(dma_alignment, cache_alignment, custom_alignment);
|
||||
ESP_LOGD(TAG, "alignment: 0x%x", alignment);
|
||||
//Get the least common multiple of two alignment
|
||||
alignment_bytes = hal_utils_calc_lcm(dma_alignment_bytes, cache_alignment_bytes);
|
||||
|
||||
//malloc
|
||||
size = ALIGN_UP_BY(size, alignment);
|
||||
int heap_caps = dma_mem_info->heap_caps;
|
||||
|
||||
void *ptr = heap_caps_aligned_alloc(alignment, size, heap_caps);
|
||||
ESP_RETURN_ON_FALSE_ISR(ptr, ESP_ERR_NO_MEM, TAG, "no enough heap memory");
|
||||
size = ALIGN_UP_BY(size, alignment_bytes);
|
||||
void *ptr = heap_caps_aligned_alloc(alignment_bytes, size, heap_caps);
|
||||
ESP_RETURN_ON_FALSE_ISR(ptr, ESP_ERR_NO_MEM, TAG, "Not enough heap memory");
|
||||
|
||||
*out_ptr = ptr;
|
||||
if (actual_size) {
|
||||
@ -64,13 +61,13 @@ esp_err_t esp_dma_capable_malloc(size_t size, const esp_dma_mem_info_t *dma_mem_
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_dma_capable_calloc(size_t n, size_t size, const esp_dma_mem_info_t *dma_mem_info, void **out_ptr, size_t *actual_size)
|
||||
esp_err_t esp_dma_capable_calloc(size_t calloc_num, size_t size, const esp_dma_mem_info_t *dma_mem_info, void **out_ptr, size_t *actual_size)
|
||||
{
|
||||
esp_err_t ret = ESP_FAIL;
|
||||
size_t size_bytes = 0;
|
||||
bool ovf = false;
|
||||
|
||||
ovf = __builtin_mul_overflow(n, size, &size_bytes);
|
||||
ovf = __builtin_mul_overflow(calloc_num, size, &size_bytes);
|
||||
ESP_RETURN_ON_FALSE_ISR(!ovf, ESP_ERR_INVALID_ARG, TAG, "wrong size, total size overflow");
|
||||
|
||||
void *ptr = NULL;
|
||||
@ -105,7 +102,7 @@ static inline bool s_is_buf_aligned(intptr_t ptr, size_t alignment)
|
||||
return (ptr % alignment == 0);
|
||||
}
|
||||
|
||||
bool esp_dma_is_buffer_alignment_satisfied(const void *ptr, size_t size, esp_dma_mem_info_t *dma_mem_info)
|
||||
bool esp_dma_is_buffer_alignment_satisfied(const void *ptr, size_t size, esp_dma_mem_info_t dma_mem_info)
|
||||
{
|
||||
assert(ptr);
|
||||
|
||||
@ -120,27 +117,24 @@ bool esp_dma_is_buffer_alignment_satisfied(const void *ptr, size_t size, esp_dma
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t alignment = 1;
|
||||
size_t alignment_bytes = 0;
|
||||
|
||||
//dma align
|
||||
size_t dma_alignment = dma_mem_info->dma_alignment;
|
||||
|
||||
//custom align
|
||||
size_t custom_alignment = dma_mem_info->custom_alignment;
|
||||
size_t dma_alignment_bytes = dma_mem_info.dma_alignment_bytes;
|
||||
|
||||
//cache align
|
||||
int cache_flags = 0;
|
||||
size_t cache_alignment = 1;
|
||||
if (dma_mem_info->heap_caps & MALLOC_CAP_SPIRAM) {
|
||||
size_t cache_alignment_bytes = 0;
|
||||
if (esp_ptr_external_ram(ptr)) {
|
||||
cache_flags |= ESP_DMA_MALLOC_FLAG_PSRAM;
|
||||
}
|
||||
esp_err_t ret = esp_cache_get_alignment(cache_flags, &cache_alignment);
|
||||
esp_err_t ret = esp_cache_get_alignment(cache_flags, &cache_alignment_bytes);
|
||||
assert(ret == ESP_OK);
|
||||
|
||||
//lcm3
|
||||
alignment = _lcm_3(dma_alignment, cache_alignment, custom_alignment);
|
||||
//Get the least common multiple of two alignment
|
||||
alignment_bytes = hal_utils_calc_lcm(dma_alignment_bytes, cache_alignment_bytes);
|
||||
|
||||
bool is_aligned = s_is_buf_aligned((intptr_t)ptr, alignment) && s_is_buf_aligned((intptr_t)size, alignment);
|
||||
bool is_aligned = s_is_buf_aligned((intptr_t)ptr, alignment_bytes) && s_is_buf_aligned((intptr_t)size, alignment_bytes);
|
||||
return is_aligned;
|
||||
}
|
||||
|
||||
@ -158,8 +152,8 @@ esp_err_t s_legacy_malloc(size_t size, uint32_t flags, void **out_ptr, size_t *a
|
||||
}
|
||||
|
||||
esp_dma_mem_info_t dma_mem_info = {
|
||||
.heap_caps = heap_caps,
|
||||
.dma_alignment = 4, //legacy API behaviour is only check max dma buffer alignment
|
||||
.extra_heap_caps = heap_caps,
|
||||
.dma_alignment_bytes = 4, //legacy API behaviour is only check max dma buffer alignment
|
||||
};
|
||||
|
||||
ESP_RETURN_ON_ERROR_ISR(esp_dma_capable_malloc(size, &dma_mem_info, out_ptr, actual_size), TAG, "failed to do malloc");
|
||||
@ -235,28 +229,8 @@ bool esp_dma_is_buffer_aligned(const void *ptr, size_t size, esp_dma_buf_locatio
|
||||
}
|
||||
|
||||
esp_dma_mem_info_t dma_mem_info = {
|
||||
.heap_caps = heap_caps,
|
||||
.dma_alignment = 4, //legacy API behaviour is only check max dma buffer alignment
|
||||
.extra_heap_caps = heap_caps,
|
||||
.dma_alignment_bytes = 4, //legacy API behaviour is only check max dma buffer alignment
|
||||
};
|
||||
return esp_dma_is_buffer_alignment_satisfied(ptr, size, &dma_mem_info);
|
||||
}
|
||||
|
||||
esp_err_t esp_dma_get_alignment(void *gdma_chan_handle, const dma_alignment_info_t *info, size_t *alignment)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(info && alignment, ESP_ERR_INVALID_ARG, TAG, "null pointer");
|
||||
|
||||
#if SOC_GDMA_SUPPORTED
|
||||
if (gdma_chan_handle) {
|
||||
gdma_channel_handle_t dma_chan = (gdma_channel_handle_t)gdma_chan_handle;
|
||||
gdma_alignment_info_t gdma_info = {};
|
||||
memcpy(&gdma_info, info, sizeof(gdma_alignment_info_t));
|
||||
ESP_RETURN_ON_ERROR(gdma_get_alignment(dma_chan, &gdma_info, alignment), TAG, "failed to get gdma alignment");
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
//for esp32 and esp32s2
|
||||
*alignment = 4;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
return esp_dma_is_buffer_alignment_satisfied(ptr, size, dma_mem_info);
|
||||
}
|
||||
|
@ -944,34 +944,3 @@ static esp_err_t gdma_install_tx_interrupt(gdma_tx_channel_t *tx_chan)
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t gdma_get_alignment(gdma_channel_handle_t dma_chan, const gdma_alignment_info_t *info, size_t *alignment)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(dma_chan && info && alignment, ESP_ERR_INVALID_ARG, TAG, "null pointer");
|
||||
bool desc_on_psram = info->is_desc && info->on_psram;
|
||||
ESP_RETURN_ON_FALSE(!desc_on_psram, ESP_ERR_INVALID_ARG, TAG, "should not place descriptor on psram");
|
||||
|
||||
if (info->is_desc) {
|
||||
if (dma_chan->pair->group->bus_id == SOC_GDMA_BUS_AHB) {
|
||||
*alignment = GDMA_LL_AHB_DESC_ALIGNMENT;
|
||||
}
|
||||
#if SOC_AXI_GDMA_SUPPORTED
|
||||
else if (dma_chan->pair->group->bus_id == SOC_GDMA_BUS_AXI) {
|
||||
*alignment = GDMA_LL_AXI_DESC_ALIGNMENT;
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
if (dma_chan->psram_alignment == 0 && dma_chan->sram_alignment == 0) {
|
||||
ESP_LOGI(TAG, "gdma_set_transfer_ability isn't called before, use fallback alignment");
|
||||
*alignment = 4;
|
||||
} else {
|
||||
if (info->on_psram) {
|
||||
*alignment = dma_chan->psram_alignment;
|
||||
} else {
|
||||
*alignment = dma_chan->sram_alignment;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
@ -16,17 +16,20 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @breif DMA Mem info
|
||||
* @brief DMA Mem info
|
||||
*/
|
||||
typedef struct {
|
||||
int heap_caps; ///< See heap caps
|
||||
size_t dma_alignment; ///< DMA alignment
|
||||
size_t custom_alignment; ///< Set this if you have custom alignment. E.g. if `psram_trans_align` is set when using GDMA driver, or you're using IP self DMA (e.g. SDMMC)
|
||||
int extra_heap_caps; ///< extra heap caps based on MALLOC_CAP_DMA
|
||||
size_t dma_alignment_bytes; ///< DMA alignment
|
||||
} esp_dma_mem_info_t;
|
||||
|
||||
/**
|
||||
* @brief Helper function for malloc a DMA capable memory buffer
|
||||
*
|
||||
* @note This API will take care of the cache alignment internally,
|
||||
* you will need to set `esp_dma_mem_info_t: dma_alignment_bytes`
|
||||
* with either the custom alignment or DMA alignment of used peripheral driver.
|
||||
*
|
||||
* @param[in] size Size in bytes, the amount of memory to allocate
|
||||
* @param[in] dma_mem_info DMA and memory info, see `esp_dma_mem_info_t`
|
||||
* @param[out] out_ptr A pointer to the memory allocated successfully
|
||||
@ -42,6 +45,7 @@ esp_err_t esp_dma_capable_malloc(size_t size, const esp_dma_mem_info_t *dma_mem_
|
||||
/**
|
||||
* @brief Helper function for calloc a DMA capable memory buffer
|
||||
*
|
||||
* @param[in] calloc_num Number of elements to allocate
|
||||
* @param[in] size Size in bytes, the amount of memory to allocate
|
||||
* @param[in] dma_mem_info DMA and memory info, see `esp_dma_mem_info_t`
|
||||
* @param[out] out_ptr A pointer to the memory allocated successfully
|
||||
@ -52,10 +56,10 @@ esp_err_t esp_dma_capable_malloc(size_t size, const esp_dma_mem_info_t *dma_mem_
|
||||
* - ESP_ERR_INVALID_ARG: Invalid argument
|
||||
* - ESP_ERR_NO_MEM: No enough memory for allocation
|
||||
*/
|
||||
esp_err_t esp_dma_capable_calloc(size_t n, size_t size, const esp_dma_mem_info_t *dma_mem_info, void **out_ptr, size_t *actual_size);
|
||||
esp_err_t esp_dma_capable_calloc(size_t calloc_num, size_t size, const esp_dma_mem_info_t *dma_mem_info, void **out_ptr, size_t *actual_size);
|
||||
|
||||
/**
|
||||
* @brief Helper function to check if a DMA buffer meets alignment requirements
|
||||
* @brief Helper function to check if a DMA buffer pointer and size meet both hardware alignment requirements and custom alignment requirements
|
||||
*
|
||||
* @param[in] ptr Pointer to the buffer
|
||||
* @param[in] size Size of the buffer
|
||||
@ -65,29 +69,16 @@ esp_err_t esp_dma_capable_calloc(size_t n, size_t size, const esp_dma_mem_info_t
|
||||
* - True: Buffer is aligned
|
||||
* - False: Buffer is not aligned, or buffer is not DMA capable
|
||||
*/
|
||||
bool esp_dma_is_buffer_alignment_satisfied(const void *ptr, size_t size, esp_dma_mem_info_t *dma_mem_info);
|
||||
bool esp_dma_is_buffer_alignment_satisfied(const void *ptr, size_t size, esp_dma_mem_info_t dma_mem_info);
|
||||
|
||||
/**
|
||||
* @brief Needed info to get GDMA alignment
|
||||
*/
|
||||
typedef struct {
|
||||
bool is_desc;
|
||||
bool on_psram;
|
||||
bool is_desc; ///< allocate DMA descriptor
|
||||
bool on_psram; ///< allocate DMA from the PSRAM
|
||||
} dma_alignment_info_t;
|
||||
|
||||
/**
|
||||
* @brief Helper to get DMA alignment
|
||||
*
|
||||
* @param[in] gdma_chan_handle GDMA channel handle, if no GDMA supported, set it to NULL
|
||||
* @param[in] info DMA alignment info
|
||||
* @param[out] alignment Alignment
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK
|
||||
* - ESP_ERR_INVALID_ARG Invalid argument
|
||||
*/
|
||||
esp_err_t esp_dma_get_alignment(void *gdma_chan_handle, const dma_alignment_info_t *info, size_t *alignment);
|
||||
|
||||
//-----------------------Deprecated APIs-----------------------//
|
||||
/**
|
||||
* DMA malloc flags
|
||||
|
@ -457,26 +457,6 @@ esp_err_t gdma_config_crc_calculator(gdma_channel_handle_t dma_chan, const gdma_
|
||||
esp_err_t gdma_crc_get_result(gdma_channel_handle_t dma_chan, uint32_t *result);
|
||||
#endif // SOC_GDMA_SUPPORT_CRC
|
||||
|
||||
/**
|
||||
* @brief Needed info to get GDMA alignment
|
||||
*/
|
||||
typedef struct {
|
||||
bool is_desc;
|
||||
bool on_psram;
|
||||
} gdma_alignment_info_t;
|
||||
|
||||
/**
|
||||
* @brief Get GDMA alignment from the channel handle
|
||||
*
|
||||
* @param[in] dma_chan GDMA channel handle
|
||||
* @param[in] info GDMA alignment info
|
||||
* @param[out] alignment Alignment
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK
|
||||
* - ESP_ERR_INVALID_ARG Invalid argument
|
||||
*/
|
||||
esp_err_t gdma_get_alignment(gdma_channel_handle_t dma_chan, const gdma_alignment_info_t *info, size_t *alignment);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -39,9 +39,8 @@ TEST_CASE("test esp_dma_capable_malloc for PSRAM", "[dma_utils]")
|
||||
size_t actual_size = 0;
|
||||
|
||||
esp_dma_mem_info_t dma_mem_info = {
|
||||
.heap_caps = MALLOC_CAP_SPIRAM,
|
||||
.dma_alignment = 4,
|
||||
.custom_alignment = 4,
|
||||
.extra_heap_caps = MALLOC_CAP_SPIRAM,
|
||||
.dma_alignment_bytes = 4,
|
||||
};
|
||||
|
||||
//------ psram ------//
|
||||
@ -65,91 +64,18 @@ TEST_CASE("test esp_dma_capable_malloc for PSRAM", "[dma_utils]")
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST_CASE("test custom alignment", "[dma_utils]")
|
||||
{
|
||||
size_t test_size = 0;
|
||||
void *test_ptr = NULL;
|
||||
size_t actual_size = 0;
|
||||
size_t custom_alignment = 512;
|
||||
|
||||
esp_dma_mem_info_t dma_mem_info = {
|
||||
.heap_caps = MALLOC_CAP_SPIRAM,
|
||||
.dma_alignment = 4,
|
||||
.custom_alignment = custom_alignment,
|
||||
};
|
||||
test_size = custom_alignment + 3;
|
||||
ESP_LOGI(TAG, "to alloc 0x%zx", test_size);
|
||||
TEST_ESP_OK(esp_dma_capable_malloc(test_size, &dma_mem_info, &test_ptr, &actual_size));
|
||||
ESP_LOGI(TAG, "get test_ptr: %p, actual_size: 0x%zx", test_ptr, actual_size);
|
||||
TEST_ASSERT((uint32_t)test_ptr % custom_alignment == 0);
|
||||
TEST_ASSERT(ALIGN_UP_BY(test_size, custom_alignment) == actual_size);
|
||||
free(test_ptr);
|
||||
}
|
||||
|
||||
TEST_CASE("test esp_dma_is_buffer_alignment_satisfied", "[dma_utils]")
|
||||
{
|
||||
size_t test_size = 64;
|
||||
void *test_ptr = NULL;
|
||||
|
||||
esp_dma_mem_info_t dma_mem_info = {
|
||||
.heap_caps = MALLOC_CAP_DMA,
|
||||
.dma_alignment = 4,
|
||||
.dma_alignment_bytes = 4,
|
||||
};
|
||||
TEST_ESP_OK(esp_dma_capable_malloc(test_size, &dma_mem_info, &test_ptr, NULL));
|
||||
ESP_LOGI(TAG, "test_ptr %p", test_ptr);
|
||||
bool is_aligned = esp_dma_is_buffer_alignment_satisfied(test_ptr, test_size, &dma_mem_info);
|
||||
bool is_aligned = esp_dma_is_buffer_alignment_satisfied(test_ptr, test_size, dma_mem_info);
|
||||
TEST_ASSERT(is_aligned);
|
||||
is_aligned = esp_dma_is_buffer_alignment_satisfied(test_ptr + 3, test_size, &dma_mem_info);
|
||||
is_aligned = esp_dma_is_buffer_alignment_satisfied(test_ptr + 3, test_size, dma_mem_info);
|
||||
TEST_ASSERT(!is_aligned);
|
||||
}
|
||||
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32P4
|
||||
#define TEST_DMA_ALIGNMENT_INT 8
|
||||
#else
|
||||
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2
|
||||
#define TEST_DMA_ALIGNMENT_INT 4
|
||||
#else
|
||||
#define TEST_DMA_ALIGNMENT_INT 8
|
||||
#endif
|
||||
#endif
|
||||
|
||||
TEST_CASE("test esp_dma_get_alignment", "[dma_utils]")
|
||||
{
|
||||
size_t dma_alignment = 0;
|
||||
gdma_channel_handle_t tx_channel = NULL;
|
||||
#if SOC_GDMA_SUPPORTED
|
||||
gdma_channel_alloc_config_t channel_config = {};
|
||||
channel_config.direction = GDMA_CHANNEL_DIRECTION_TX;
|
||||
|
||||
TEST_ESP_OK(gdma_new_ahb_channel(&channel_config, &tx_channel));
|
||||
|
||||
gdma_transfer_ability_t ability = {
|
||||
.psram_trans_align = 0,
|
||||
.sram_trans_align = 8,
|
||||
};
|
||||
TEST_ESP_OK(gdma_set_transfer_ability(tx_channel, &ability));
|
||||
#endif
|
||||
|
||||
dma_alignment_info_t internal_info = {};
|
||||
|
||||
TEST_ESP_OK(esp_dma_get_alignment(tx_channel, &internal_info, &dma_alignment));
|
||||
ESP_LOGI(TAG, "dma_alignment: 0x%x", dma_alignment);
|
||||
TEST_ASSERT(dma_alignment == TEST_DMA_ALIGNMENT_INT);
|
||||
}
|
||||
|
||||
#if SOC_GDMA_SUPPORTED
|
||||
TEST_CASE("test esp_dma_get_alignment with no transfer ability set", "[dma_utils]")
|
||||
{
|
||||
size_t dma_alignment = 0;
|
||||
gdma_channel_handle_t tx_channel = NULL;
|
||||
gdma_channel_alloc_config_t channel_config = {};
|
||||
channel_config.direction = GDMA_CHANNEL_DIRECTION_TX;
|
||||
TEST_ESP_OK(gdma_new_ahb_channel(&channel_config, &tx_channel));
|
||||
|
||||
dma_alignment_info_t internal_info = {};
|
||||
TEST_ESP_OK(esp_dma_get_alignment(tx_channel, &internal_info, &dma_alignment));
|
||||
ESP_LOGI(TAG, "dma_alignment: 0x%x", dma_alignment);
|
||||
TEST_ASSERT(dma_alignment == 4);
|
||||
}
|
||||
#endif
|
||||
|
@ -99,6 +99,8 @@ extern "C" {
|
||||
// TODO: Workaround for C5-beta3 only. C5-mp can still vectorized channels into an array in gdma_struct.h
|
||||
#define GDMA_LL_CHANNEL_GET_REG_ADDR(dev, ch) ((volatile gdma_chn_reg_t*[]){&dev->channel0, &dev->channel1, &dev->channel2}[(ch)])
|
||||
|
||||
#define GDMA_LL_AHB_DESC_ALIGNMENT 4
|
||||
|
||||
///////////////////////////////////// Common /////////////////////////////////////////
|
||||
|
||||
/**
|
||||
|
@ -26,7 +26,7 @@ uint32_t hal_utils_calc_clk_div_frac_fast(const hal_utils_clk_info_t *clk_info,
|
||||
// Carry bit if the decimal is greater than 1.0 - 1.0 / ((max_fract - 1) * 2)
|
||||
if (freq_error < clk_info->exp_freq_hz - clk_info->exp_freq_hz / (clk_info->max_fract - 1) * 2) {
|
||||
// Calculate the Greatest Common Divisor, time complexity O(log n)
|
||||
uint32_t gcd = _gcd(clk_info->exp_freq_hz, freq_error);
|
||||
uint32_t gcd = hal_utils_gcd(clk_info->exp_freq_hz, freq_error);
|
||||
// divide by the Greatest Common Divisor to get the accurate fraction before normalization
|
||||
div_denom = clk_info->exp_freq_hz / gcd;
|
||||
div_numer = freq_error / gcd;
|
||||
|
@ -23,7 +23,7 @@ typedef enum {
|
||||
} hal_utils_div_round_opt_t;
|
||||
|
||||
/**
|
||||
* @brief Clock infomation
|
||||
* @brief Clock information
|
||||
*
|
||||
*/
|
||||
typedef struct {
|
||||
@ -53,7 +53,7 @@ typedef struct {
|
||||
* @note Speed first algorithm, Time complexity O(log n).
|
||||
* About 8~10 times faster than the accurate algorithm
|
||||
*
|
||||
* @param[in] clk_info The clock infomation
|
||||
* @param[in] clk_info The clock information
|
||||
* @param[out] clk_div The clock division with integral and fractal part
|
||||
* @return
|
||||
* - 0: Failed to get the result because the division is out of range
|
||||
@ -66,7 +66,7 @@ uint32_t hal_utils_calc_clk_div_frac_fast(const hal_utils_clk_info_t *clk_info,
|
||||
* @note Accuracy first algorithm, Time complexity O(n).
|
||||
* About 1~hundreds times more accurate than the fast algorithm
|
||||
*
|
||||
* @param[in] clk_info The clock infomation
|
||||
* @param[in] clk_info The clock information
|
||||
* @param[out] clk_div The clock division with integral and fractal part
|
||||
* @return
|
||||
* - 0: Failed to get the result because the division is out of range
|
||||
@ -77,12 +77,12 @@ uint32_t hal_utils_calc_clk_div_frac_accurate(const hal_utils_clk_info_t *clk_in
|
||||
/**
|
||||
* @brief Calculate the clock division without fractal part
|
||||
*
|
||||
* @param[in] clk_info The clock infomation
|
||||
* @param[in] clk_info The clock information
|
||||
* @param[out] int_div The clock integral division
|
||||
* @return
|
||||
* - 0: Failed to get the result because the division is out of range,
|
||||
* but parameter `int_div` will still be assigned to min/max division that given in `clk_info`,
|
||||
* incase the caller still want to use the min/max division in this case.
|
||||
* in case the caller still want to use the min/max division in this case.
|
||||
* - others: The real output clock frequency
|
||||
*/
|
||||
uint32_t hal_utils_calc_clk_div_integer(const hal_utils_clk_info_t *clk_info, uint32_t *int_div);
|
||||
@ -103,20 +103,31 @@ static inline uint8_t hal_utils_bitwise_reverse8(uint8_t n)
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief helper function, calculate the Greatest Common Divisor
|
||||
* @note gcd(a, b) = gcd(b, a % b)
|
||||
* @param a bigger value
|
||||
* @param b smaller value
|
||||
* @return result of gcd(a, b)
|
||||
* @brief Helper function to calculate the GCD between two numbers using the Euclidean algorithm.
|
||||
* Calculate the Greatest Common Divisor (GDC) of two unsigned numbers
|
||||
*
|
||||
* @param num_1 First number
|
||||
* @param num_2 Second number
|
||||
* @return GCD of 'a' and 'b'
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline uint32_t _gcd(uint32_t a, uint32_t b)
|
||||
static inline uint32_t hal_utils_gcd(uint32_t num_1, uint32_t num_2)
|
||||
{
|
||||
uint32_t c = a % b;
|
||||
while (c != 0) {
|
||||
uint32_t a, b, rem;
|
||||
// Always mod larger number by smaller number
|
||||
if (num_1 > num_2) {
|
||||
a = num_1;
|
||||
b = num_2;
|
||||
} else {
|
||||
b = num_2;
|
||||
a = num_1;
|
||||
}
|
||||
|
||||
rem = a % b;
|
||||
while (rem != 0) {
|
||||
a = b;
|
||||
b = c;
|
||||
c = a % b;
|
||||
b = rem;
|
||||
rem = a % b;
|
||||
}
|
||||
return b;
|
||||
}
|
||||
@ -130,29 +141,11 @@ static inline uint32_t _gcd(uint32_t a, uint32_t b)
|
||||
* @return LCM of A and B
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline uint32_t _lcm(uint32_t a, uint32_t b)
|
||||
static inline uint32_t hal_utils_calc_lcm(uint32_t a, uint32_t b)
|
||||
{
|
||||
a = a == 0 ? 1 : a;
|
||||
b = b == 0 ? 1 : b;
|
||||
return (a * b / _gcd(a, b));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the least common multiple of three integer
|
||||
*
|
||||
* @param[in] Integer A
|
||||
* @param[in] Integer B
|
||||
* @param[in] Integer C
|
||||
*
|
||||
* @return LCM of A, B and C
|
||||
*/
|
||||
__attribute__((always_inline))
|
||||
static inline uint32_t _lcm_3(uint32_t a, uint32_t b, uint32_t c)
|
||||
{
|
||||
a = a == 0 ? 1 : a;
|
||||
b = b == 0 ? 1 : b;
|
||||
c = c == 0 ? 1 : c;
|
||||
return _lcm(a, _lcm(b, c));
|
||||
return (a * b / hal_utils_gcd(a, b));
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -46,7 +46,7 @@
|
||||
#define AES_DMA_INTR_TRIG_LEN 2000
|
||||
|
||||
/* With buffers in PSRAM (worst condition) we still achieve a speed of 4 MB/s
|
||||
thus a 2 second timeout value should be suffient for even very large buffers.
|
||||
thus a 2 second timeout value should be sufficient for even very large buffers.
|
||||
*/
|
||||
#define AES_WAIT_INTR_TIMEOUT_MS 2000
|
||||
|
||||
@ -98,7 +98,7 @@ void esp_aes_intr_alloc(void)
|
||||
|
||||
static StaticSemaphore_t op_sem_buf;
|
||||
op_complete_sem = xSemaphoreCreateBinaryStatic(&op_sem_buf);
|
||||
// Static semaphore creation is unlikley to fail but still basic sanity
|
||||
// Static semaphore creation is unlikely to fail but still basic sanity
|
||||
assert(op_complete_sem != NULL);
|
||||
}
|
||||
}
|
||||
@ -164,7 +164,7 @@ static int esp_aes_dma_wait_complete(bool use_intr, crypto_dma_desc_t *output_de
|
||||
}
|
||||
|
||||
|
||||
/* Output buffers in external ram needs to be 16-byte aligned and DMA cant access input in the iCache mem range,
|
||||
/* Output buffers in external ram needs to be 16-byte aligned and DMA can't access input in the iCache mem range,
|
||||
reallocate them into internal memory and encrypt in chunks to avoid
|
||||
having to malloc too big of a buffer
|
||||
|
||||
@ -276,7 +276,12 @@ static inline void dma_desc_append(crypto_dma_desc_t **head, crypto_dma_desc_t *
|
||||
static inline void *aes_dma_calloc(size_t num, size_t size, uint32_t caps, size_t *actual_size)
|
||||
{
|
||||
void *ptr = NULL;
|
||||
esp_dma_calloc(num, size, caps, &ptr, actual_size);
|
||||
esp_dma_mem_info_t dma_mem_info = {
|
||||
.extra_heap_caps = caps,
|
||||
.dma_alignment_bytes = 4,
|
||||
};
|
||||
//TODO: IDF-9638
|
||||
esp_dma_capable_calloc(num, size, &dma_mem_info, &ptr, actual_size);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "esp_err.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "sd_pwr_ctrl.h"
|
||||
#include "esp_dma_utils.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -79,7 +80,7 @@ typedef struct {
|
||||
uint32_t erase_size_au: 16; /*!< Erase size for the purpose of timeout calculation, in multiples of allocation unit */
|
||||
uint32_t cur_bus_width: 2; /*!< SD current bus width */
|
||||
uint32_t discard_support: 1; /*!< SD discard feature support */
|
||||
uint32_t fule_support: 1; /*!< SD FULE (Full User Area Logical Erase) feature support */
|
||||
uint32_t fule_support: 1; /*!< SD FILE (Full User Area Logical Erase) feature support */
|
||||
uint32_t erase_timeout: 6; /*!< Timeout (in seconds) for erase of a single allocation unit */
|
||||
uint32_t erase_offset: 2; /*!< Constant timeout offset (in seconds) for any erase operation */
|
||||
uint32_t reserved: 20; /*!< reserved for future expansion */
|
||||
@ -209,6 +210,7 @@ typedef struct {
|
||||
esp_err_t (*set_input_delay)(int slot, sdmmc_delay_phase_t delay_phase); /*!< set input delay phase */
|
||||
void* dma_aligned_buffer; /*!< Leave it NULL. Reserved for cache aligned buffers for SDIO mode */
|
||||
sd_pwr_ctrl_handle_t pwr_ctrl_handle; /*!< Power control handle */
|
||||
esp_err_t (*get_dma_info)(int slot, esp_dma_mem_info_t *dma_mem_info); /*!< host function to dma memory information*/
|
||||
} sdmmc_host_t;
|
||||
|
||||
/**
|
||||
|
@ -326,13 +326,11 @@ esp_err_t sdmmc_send_cmd_send_scr(sdmmc_card_t* card, sdmmc_scr_t *out_scr)
|
||||
{
|
||||
size_t datalen = 8;
|
||||
esp_err_t err = ESP_FAIL;
|
||||
uint32_t *buf = NULL;
|
||||
void *buf = NULL;
|
||||
size_t actual_size = 0;
|
||||
esp_dma_mem_info_t dma_mem_info = {
|
||||
.heap_caps = MALLOC_CAP_DMA,
|
||||
.custom_alignment = 4,
|
||||
};
|
||||
err = esp_dma_capable_malloc(datalen, &dma_mem_info, (void *)&buf, &actual_size);
|
||||
esp_dma_mem_info_t dma_mem_info;
|
||||
card->host.get_dma_info(card->host.slot, &dma_mem_info);
|
||||
err = esp_dma_capable_malloc(datalen, &dma_mem_info, &buf, &actual_size);
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
@ -405,11 +403,9 @@ esp_err_t sdmmc_write_sectors(sdmmc_card_t* card, const void* src,
|
||||
|
||||
esp_err_t err = ESP_OK;
|
||||
size_t block_size = card->csd.sector_size;
|
||||
esp_dma_mem_info_t dma_mem_info = {
|
||||
.heap_caps = MALLOC_CAP_DMA,
|
||||
.custom_alignment = 4,
|
||||
};
|
||||
if (esp_dma_is_buffer_alignment_satisfied(src, block_size * block_count, &dma_mem_info)) {
|
||||
esp_dma_mem_info_t dma_mem_info;
|
||||
card->host.get_dma_info(card->host.slot, &dma_mem_info);
|
||||
if (esp_dma_is_buffer_alignment_satisfied(src, block_size * block_count, dma_mem_info)) {
|
||||
err = sdmmc_write_sectors_dma(card, src, start_block, block_count, block_size * block_count);
|
||||
} else {
|
||||
// SDMMC peripheral needs DMA-capable buffers. Split the write into
|
||||
@ -527,11 +523,9 @@ esp_err_t sdmmc_read_sectors(sdmmc_card_t* card, void* dst,
|
||||
|
||||
esp_err_t err = ESP_OK;
|
||||
size_t block_size = card->csd.sector_size;
|
||||
esp_dma_mem_info_t dma_mem_info = {
|
||||
.heap_caps = MALLOC_CAP_DMA,
|
||||
.custom_alignment = 4,
|
||||
};
|
||||
if (esp_dma_is_buffer_alignment_satisfied(dst, block_size * block_count, &dma_mem_info)) {
|
||||
esp_dma_mem_info_t dma_mem_info;
|
||||
card->host.get_dma_info(card->host.slot, &dma_mem_info);
|
||||
if (esp_dma_is_buffer_alignment_satisfied(dst, block_size * block_count, dma_mem_info)) {
|
||||
err = sdmmc_read_sectors_dma(card, dst, start_block, block_count, block_size * block_count);
|
||||
} else {
|
||||
// SDMMC peripheral needs DMA-capable buffers. Split the read into
|
||||
|
@ -340,11 +340,8 @@ esp_err_t sdmmc_allocate_aligned_buf(sdmmc_card_t* card)
|
||||
if (card->host.flags & SDMMC_HOST_FLAG_ALLOC_ALIGNED_BUF) {
|
||||
void* buf = NULL;
|
||||
size_t actual_size = 0;
|
||||
// esp_err_t ret = esp_dma_malloc(SDMMC_IO_BLOCK_SIZE, 0, &buf, &actual_size);
|
||||
esp_dma_mem_info_t dma_mem_info = {
|
||||
.heap_caps = MALLOC_CAP_DMA,
|
||||
.custom_alignment = 4,
|
||||
};
|
||||
esp_dma_mem_info_t dma_mem_info;
|
||||
card->host.get_dma_info(card->host.slot, &dma_mem_info);
|
||||
esp_err_t ret = esp_dma_capable_malloc(SDMMC_IO_BLOCK_SIZE, &dma_mem_info, &buf, &actual_size);
|
||||
|
||||
if (ret != ESP_OK) {
|
||||
|
@ -277,11 +277,9 @@ esp_err_t sdmmc_io_rw_extended(sdmmc_card_t* card, int func,
|
||||
.blklen = SDMMC_IO_BLOCK_SIZE /* TODO: read max block size from CIS */
|
||||
};
|
||||
|
||||
esp_dma_mem_info_t dma_mem_info = {
|
||||
.heap_caps = MALLOC_CAP_DMA,
|
||||
.custom_alignment = 4,
|
||||
};
|
||||
if (unlikely(datalen > 0 && !esp_dma_is_buffer_alignment_satisfied(datap, buflen, &dma_mem_info))) {
|
||||
esp_dma_mem_info_t dma_mem_info;
|
||||
card->host.get_dma_info(card->host.slot, &dma_mem_info);
|
||||
if (unlikely(datalen > 0 && !esp_dma_is_buffer_alignment_satisfied(datap, buflen, dma_mem_info))) {
|
||||
if (datalen > SDMMC_IO_BLOCK_SIZE || card->host.dma_aligned_buffer == NULL) {
|
||||
// User gives unaligned buffer while `SDMMC_HOST_FLAG_ALLOC_ALIGNED_BUF` not set.
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
@ -304,7 +302,7 @@ esp_err_t sdmmc_io_rw_extended(sdmmc_card_t* card, int func,
|
||||
return ESP_ERR_INVALID_SIZE;
|
||||
}
|
||||
if (datalen == SDMMC_IO_BLOCK_SIZE) {
|
||||
count = 0; // See 5.3.1 SDIO simplifed spec
|
||||
count = 0; // See 5.3.1 SDIO simplified spec
|
||||
} else {
|
||||
count = datalen;
|
||||
}
|
||||
@ -390,11 +388,9 @@ esp_err_t sdmmc_io_write_bytes(sdmmc_card_t* card, uint32_t function,
|
||||
esp_err_t sdmmc_io_read_blocks(sdmmc_card_t* card, uint32_t function,
|
||||
uint32_t addr, void* dst, size_t size)
|
||||
{
|
||||
esp_dma_mem_info_t dma_mem_info = {
|
||||
.heap_caps = MALLOC_CAP_DMA,
|
||||
.custom_alignment = 4,
|
||||
};
|
||||
if (unlikely(!esp_dma_is_buffer_alignment_satisfied(dst, size, &dma_mem_info))) {
|
||||
esp_dma_mem_info_t dma_mem_info;
|
||||
card->host.get_dma_info(card->host.slot, &dma_mem_info);
|
||||
if (unlikely(!esp_dma_is_buffer_alignment_satisfied(dst, size, dma_mem_info))) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
return sdmmc_io_rw_extended(card, function, addr,
|
||||
@ -405,11 +401,9 @@ esp_err_t sdmmc_io_read_blocks(sdmmc_card_t* card, uint32_t function,
|
||||
esp_err_t sdmmc_io_write_blocks(sdmmc_card_t* card, uint32_t function,
|
||||
uint32_t addr, const void* src, size_t size)
|
||||
{
|
||||
esp_dma_mem_info_t dma_mem_info = {
|
||||
.heap_caps = MALLOC_CAP_DMA,
|
||||
.custom_alignment = 4,
|
||||
};
|
||||
if (unlikely(!esp_dma_is_buffer_alignment_satisfied(src, size, &dma_mem_info))) {
|
||||
esp_dma_mem_info_t dma_mem_info;
|
||||
card->host.get_dma_info(card->host.slot, &dma_mem_info);
|
||||
if (unlikely(!esp_dma_is_buffer_alignment_satisfied(src, size, dma_mem_info))) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
return sdmmc_io_rw_extended(card, function, addr,
|
||||
|
@ -28,10 +28,8 @@ esp_err_t sdmmc_init_mmc_read_ext_csd(sdmmc_card_t* card)
|
||||
esp_err_t err = ESP_OK;
|
||||
uint8_t* ext_csd = NULL;
|
||||
size_t actual_size = 0;
|
||||
esp_dma_mem_info_t dma_mem_info = {
|
||||
.heap_caps = MALLOC_CAP_DMA,
|
||||
.custom_alignment = 4,
|
||||
};
|
||||
esp_dma_mem_info_t dma_mem_info;
|
||||
card->host.get_dma_info(card->host.slot, &dma_mem_info);
|
||||
err = esp_dma_capable_malloc(EXT_CSD_MMC_SIZE, &dma_mem_info, (void *)&ext_csd, &actual_size);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "%s: could not allocate ext_csd", __func__);
|
||||
@ -259,10 +257,8 @@ esp_err_t sdmmc_init_mmc_check_ext_csd(sdmmc_card_t* card)
|
||||
/* ensure EXT_CSD buffer is available before starting any SD-card operation */
|
||||
uint8_t* ext_csd = NULL;
|
||||
size_t actual_size = 0;
|
||||
esp_dma_mem_info_t dma_mem_info = {
|
||||
.heap_caps = MALLOC_CAP_DMA,
|
||||
.custom_alignment = 4,
|
||||
};
|
||||
esp_dma_mem_info_t dma_mem_info;
|
||||
card->host.get_dma_info(card->host.slot, &dma_mem_info);
|
||||
esp_err_t err = esp_dma_capable_malloc(EXT_CSD_MMC_SIZE, &dma_mem_info, (void *)&ext_csd, &actual_size);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "%s: could not allocate ext_csd", __func__);
|
||||
|
@ -91,10 +91,8 @@ esp_err_t sdmmc_init_sd_ssr(sdmmc_card_t* card)
|
||||
*/
|
||||
uint32_t* sd_ssr = NULL;
|
||||
size_t actual_size = 0;
|
||||
esp_dma_mem_info_t dma_mem_info = {
|
||||
.heap_caps = MALLOC_CAP_DMA,
|
||||
.custom_alignment = 4,
|
||||
};
|
||||
esp_dma_mem_info_t dma_mem_info;
|
||||
card->host.get_dma_info(card->host.slot, &dma_mem_info);
|
||||
err = esp_dma_capable_calloc(1, SD_SSR_SIZE, &dma_mem_info, (void *)&sd_ssr, &actual_size);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "%s: could not allocate sd_ssr", __func__);
|
||||
@ -243,10 +241,8 @@ esp_err_t sdmmc_enable_hs_mode(sdmmc_card_t* card)
|
||||
|
||||
size_t actual_size = 0;
|
||||
sdmmc_switch_func_rsp_t *response = NULL;
|
||||
esp_dma_mem_info_t dma_mem_info = {
|
||||
.heap_caps = MALLOC_CAP_DMA,
|
||||
.custom_alignment = 4,
|
||||
};
|
||||
esp_dma_mem_info_t dma_mem_info;
|
||||
card->host.get_dma_info(card->host.slot, &dma_mem_info);
|
||||
esp_err_t err = esp_dma_capable_malloc(sizeof(*response), &dma_mem_info, (void *)&response, &actual_size);
|
||||
assert(actual_size == sizeof(*response));
|
||||
if (err != ESP_OK) {
|
||||
|
@ -1040,18 +1040,18 @@ static void port_obj_free(port_t *port)
|
||||
|
||||
void *frame_list_alloc(size_t frame_list_len)
|
||||
{
|
||||
esp_err_t ret = ESP_FAIL;
|
||||
esp_err_t ret;
|
||||
void *frame_list = NULL;
|
||||
size_t actual_size = 0;
|
||||
esp_dma_mem_info_t dma_mem_info = {
|
||||
.heap_caps = MALLOC_CAP_DMA,
|
||||
.custom_alignment = USB_DWC_FRAME_LIST_MEM_ALIGN,
|
||||
.dma_alignment_bytes = USB_DWC_FRAME_LIST_MEM_ALIGN,
|
||||
};
|
||||
ret = esp_dma_capable_calloc(frame_list_len, sizeof(uint32_t), &dma_mem_info, &frame_list, NULL);
|
||||
assert(ret != ESP_ERR_INVALID_ARG);
|
||||
ret = esp_dma_capable_calloc(frame_list_len, sizeof(uint32_t), &dma_mem_info, &frame_list, &actual_size);
|
||||
assert(ret == ESP_OK);
|
||||
|
||||
// Both Frame List start address and size should be already cache aligned so this is only a sanity check
|
||||
if (frame_list) {
|
||||
if (!esp_dma_is_buffer_alignment_satisfied(frame_list, frame_list_len * sizeof(uint32_t), &dma_mem_info)) {
|
||||
if (!esp_dma_is_buffer_alignment_satisfied(frame_list, actual_size, dma_mem_info)) {
|
||||
// This should never happen
|
||||
heap_caps_free(frame_list);
|
||||
frame_list = NULL;
|
||||
@ -1072,17 +1072,17 @@ void *transfer_descriptor_list_alloc(size_t list_len, size_t *list_len_bytes_out
|
||||
*list_len_bytes_out = list_len * sizeof(usb_dwc_ll_dma_qtd_t);
|
||||
#endif // SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
|
||||
|
||||
esp_err_t ret = ESP_FAIL;
|
||||
esp_err_t ret;
|
||||
void *qtd_list = NULL;
|
||||
size_t actual_size = 0;
|
||||
esp_dma_mem_info_t dma_mem_info = {
|
||||
.heap_caps = MALLOC_CAP_DMA,
|
||||
.custom_alignment = USB_DWC_QTD_LIST_MEM_ALIGN,
|
||||
.dma_alignment_bytes = USB_DWC_QTD_LIST_MEM_ALIGN,
|
||||
};
|
||||
ret = esp_dma_capable_calloc(*list_len_bytes_out, 1, &dma_mem_info, &qtd_list, NULL);
|
||||
assert(ret != ESP_ERR_INVALID_ARG);
|
||||
ret = esp_dma_capable_calloc(*list_len_bytes_out, 1, &dma_mem_info, &qtd_list, &actual_size);
|
||||
assert(ret == ESP_OK);
|
||||
|
||||
if (qtd_list) {
|
||||
if (!esp_dma_is_buffer_alignment_satisfied(qtd_list, *list_len_bytes_out * sizeof(usb_dwc_ll_dma_qtd_t), &dma_mem_info)) {
|
||||
if (!esp_dma_is_buffer_alignment_satisfied(qtd_list, actual_size, dma_mem_info)) {
|
||||
// This should never happen
|
||||
heap_caps_free(qtd_list);
|
||||
qtd_list = NULL;
|
||||
|
@ -267,11 +267,7 @@ urb_t *test_hcd_alloc_urb(int num_isoc_packets, size_t data_buffer_size)
|
||||
void *data_buffer;
|
||||
size_t real_size;
|
||||
esp_dma_mem_info_t dma_mem_info = {
|
||||
.dma_type = ESP_DMA_OTHERS,
|
||||
.mem_flags = {
|
||||
.dir = ESP_DMA_MEM_DIR_DONT_CARE,
|
||||
},
|
||||
.custom_alignment = 4,
|
||||
.dma_alignment_bytes = 4,
|
||||
};
|
||||
esp_dma_capable_malloc(data_buffer_size, &dma_mem_info, &data_buffer, &real_size);
|
||||
TEST_ASSERT_NOT_NULL_MESSAGE(urb, "Failed to allocate URB");
|
||||
|
@ -15,12 +15,9 @@ urb_t *urb_alloc(size_t data_buffer_size, int num_isoc_packets)
|
||||
void *data_buffer;
|
||||
size_t real_size;
|
||||
esp_dma_mem_info_t dma_mem_info = {
|
||||
.dma_type = ESP_DMA_OTHERS,
|
||||
.mem_flags = {
|
||||
.dir = ESP_DMA_MEM_DIR_DONT_CARE,
|
||||
},
|
||||
.custom_alignment = 4,
|
||||
.dma_alignment_bytes = 4,
|
||||
};
|
||||
//TODO: IDF-9639
|
||||
esp_dma_capable_malloc(data_buffer_size, &dma_mem_info, &data_buffer, &real_size);
|
||||
if (urb == NULL || data_buffer == NULL) {
|
||||
goto err;
|
||||
|
@ -109,7 +109,7 @@ cache memory synchronization is usually considered when DMA is involved. ESP-IDF
|
||||
- :cpp:func:`esp_dma_capable_malloc`, this API allocates a chunk of memory that meets the alignment requirement from both the cache and the DMA.
|
||||
- :cpp:func:`esp_dma_capable_calloc`, this API allocates a chunk of memory that meets the alignment requirement from both the cache and the DMA. The initialized value in the memory is set to zero.
|
||||
|
||||
You can also use :cpp:member:`esp_dma_mem_info_t::on_psram` to allocate from the PSRAM.
|
||||
You can also use :c:macro:`ESP_DMA_MALLOC_FLAG_PSRAM` to allocate from the PSRAM.
|
||||
|
||||
|
||||
Warning for Address Alignment Requirement
|
||||
|
@ -448,11 +448,11 @@ void app_main(void)
|
||||
lv_color_t *buf1 = NULL;
|
||||
lv_color_t *buf2 = NULL;
|
||||
esp_dma_mem_info_t dma_mem_info = {
|
||||
.dma_alignment = 4,
|
||||
.dma_alignment_bytes = 4,
|
||||
#if CONFIG_EXAMPLE_LCD_I80_COLOR_IN_PSRAM
|
||||
.heap_caps = MALLOC_CAP_SPIRAM,
|
||||
.extra_heap_caps = MALLOC_CAP_SPIRAM,
|
||||
#else
|
||||
.heap_caps = MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL,
|
||||
.extra_heap_caps = MALLOC_CAP_INTERNAL,
|
||||
#endif // CONFIG_EXAMPLE_LCD_I80_COLOR_IN_PSRAM
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_dma_capable_malloc(EXAMPLE_LCD_H_RES * 100 * sizeof(lv_color_t), &dma_mem_info, (void *)&buf1, NULL));
|
||||
|
Loading…
Reference in New Issue
Block a user