mirror of
https://github.com/espressif/esp-idf.git
synced 2026-04-27 19:13:21 +00:00
feat(sdmmc): Try to reallocate smaller DMA buffer if larger one failed
This commit is contained in:
@@ -48,7 +48,7 @@ extern "C" {
|
|||||||
.input_delay_phase = SDMMC_DELAY_PHASE_0, \
|
.input_delay_phase = SDMMC_DELAY_PHASE_0, \
|
||||||
.set_input_delay = &sdmmc_host_set_input_delay, \
|
.set_input_delay = &sdmmc_host_set_input_delay, \
|
||||||
.set_input_delayline = &sdmmc_host_set_input_delayline, \
|
.set_input_delayline = &sdmmc_host_set_input_delayline, \
|
||||||
.unaligned_multi_block_rw_max_chunk_size = 0, \
|
.unaligned_multi_block_rw_max_chunk_size = 16, \
|
||||||
.dma_aligned_buffer = NULL, \
|
.dma_aligned_buffer = NULL, \
|
||||||
.pwr_ctrl_handle = NULL, \
|
.pwr_ctrl_handle = NULL, \
|
||||||
.check_buffer_alignment = &sdmmc_host_check_buffer_alignment, \
|
.check_buffer_alignment = &sdmmc_host_check_buffer_alignment, \
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ typedef int sdspi_dev_handle_t;
|
|||||||
.input_delay_phase = SDMMC_DELAY_PHASE_0, \
|
.input_delay_phase = SDMMC_DELAY_PHASE_0, \
|
||||||
.set_input_delay = NULL, \
|
.set_input_delay = NULL, \
|
||||||
.set_input_delayline = NULL, \
|
.set_input_delayline = NULL, \
|
||||||
.unaligned_multi_block_rw_max_chunk_size = 0, \
|
.unaligned_multi_block_rw_max_chunk_size = 16, \
|
||||||
.dma_aligned_buffer = NULL, \
|
.dma_aligned_buffer = NULL, \
|
||||||
.pwr_ctrl_handle = NULL, \
|
.pwr_ctrl_handle = NULL, \
|
||||||
.check_buffer_alignment = sdspi_host_check_buffer_alignment, \
|
.check_buffer_alignment = sdspi_host_check_buffer_alignment, \
|
||||||
|
|||||||
@@ -23,6 +23,27 @@ static inline size_t get_chunk_size(const sdmmc_card_t *card)
|
|||||||
return (chunk_size != 0) ? chunk_size : 1;
|
return (chunk_size != 0) ? chunk_size : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static esp_err_t allocate_dma_buf(size_t* actual_size, size_t block_size, void **buf)
|
||||||
|
{
|
||||||
|
if (actual_size == NULL || buf == NULL) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t size = *actual_size;
|
||||||
|
do {
|
||||||
|
if (*actual_size < block_size) {
|
||||||
|
ESP_LOGE(TAG, "%s: not enough mem, err=0x%x", __func__, ESP_ERR_NO_MEM);
|
||||||
|
return ESP_ERR_NO_MEM;
|
||||||
|
}
|
||||||
|
*buf = heap_caps_malloc(*actual_size, MALLOC_CAP_DMA);
|
||||||
|
if (!*buf) {
|
||||||
|
*actual_size /= 2;
|
||||||
|
ESP_LOGD(TAG, "%s: required space for buffer of size %d not available, trying again with size %zu", __func__, size, *actual_size);
|
||||||
|
}
|
||||||
|
} while (!*buf);
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
esp_err_t sdmmc_send_cmd(sdmmc_card_t* card, sdmmc_command_t* cmd)
|
esp_err_t sdmmc_send_cmd(sdmmc_card_t* card, sdmmc_command_t* cmd)
|
||||||
{
|
{
|
||||||
if (card->host.command_timeout_ms != 0) {
|
if (card->host.command_timeout_ms != 0) {
|
||||||
@@ -489,11 +510,12 @@ esp_err_t sdmmc_write_sectors(sdmmc_card_t* card, const void* src,
|
|||||||
// Allocate a temporary DMA-capable buffer.
|
// Allocate a temporary DMA-capable buffer.
|
||||||
// We don't want to force the allocation into SPIRAM, the allocator
|
// We don't want to force the allocation into SPIRAM, the allocator
|
||||||
// will decide based on the buffer size and memory availability.
|
// will decide based on the buffer size and memory availability.
|
||||||
buf = heap_caps_malloc(actual_size, MALLOC_CAP_DMA);
|
// We start with the largest buffer possible to minimize the number of read iterations, but if that fails, we try smaller sizes down to a single block.
|
||||||
if (!buf) {
|
err = allocate_dma_buf(&actual_size, block_size, &buf);
|
||||||
ESP_LOGE(TAG, "%s: not enough mem, err=0x%x", __func__, ESP_ERR_NO_MEM);
|
if (err != ESP_OK) {
|
||||||
return ESP_ERR_NO_MEM;
|
return err;
|
||||||
}
|
}
|
||||||
|
blocks_per_write = actual_size / block_size;
|
||||||
} else {
|
} else {
|
||||||
// Check that the provided dma_aligned_buffer is large enough
|
// Check that the provided dma_aligned_buffer is large enough
|
||||||
actual_size = heap_caps_get_allocated_size(buf);
|
actual_size = heap_caps_get_allocated_size(buf);
|
||||||
@@ -649,11 +671,12 @@ esp_err_t sdmmc_read_sectors(sdmmc_card_t* card, void* dst,
|
|||||||
// Allocate a temporary DMA-capable buffer.
|
// Allocate a temporary DMA-capable buffer.
|
||||||
// We don't want to force the allocation into SPIRAM, the allocator
|
// We don't want to force the allocation into SPIRAM, the allocator
|
||||||
// will decide based on the buffer size and memory availability.
|
// will decide based on the buffer size and memory availability.
|
||||||
buf = heap_caps_malloc(actual_size, MALLOC_CAP_DMA);
|
// We start with the largest buffer possible to minimize the number of read iterations, but if that fails, we try smaller sizes down to a single block.
|
||||||
if (!buf) {
|
err = allocate_dma_buf(&actual_size, block_size, &buf);
|
||||||
ESP_LOGE(TAG, "%s: not enough mem, err=0x%x", __func__, ESP_ERR_NO_MEM);
|
if (err != ESP_OK) {
|
||||||
return ESP_ERR_NO_MEM;
|
return err;
|
||||||
}
|
}
|
||||||
|
blocks_per_read = actual_size / block_size;
|
||||||
} else {
|
} else {
|
||||||
// Check that the provided dma_aligned_buffer is large enough
|
// Check that the provided dma_aligned_buffer is large enough
|
||||||
actual_size = heap_caps_get_allocated_size(buf);
|
actual_size = heap_caps_get_allocated_size(buf);
|
||||||
|
|||||||
Reference in New Issue
Block a user