mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 11:10:54 +03:00
fix(sdmmc): Add a better handling of devices accessing PSRAM through DMA
Closes https://github.com/espressif/esp-idf/issues/18412
This commit is contained in:
@@ -23,6 +23,20 @@ static inline size_t get_chunk_size(const sdmmc_card_t *card)
|
||||
return (chunk_size != 0) ? chunk_size : 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Whether the host can transfer the user buffer directly, without an
|
||||
* intermediate DMA-capable buffer.
|
||||
*
|
||||
* The protocol layer does not need to reason about DMA or PSRAM: it simply asks
|
||||
* the host driver whether the buffer is usable as-is. The driver accounts for
|
||||
* alignment and any hardware-specific reachability constraints (e.g. whether the
|
||||
* peripheral's DMA can reach PSRAM).
|
||||
*/
|
||||
static inline bool sdmmc_buffer_directly_usable(const sdmmc_card_t *card, const void *buf, size_t size)
|
||||
{
|
||||
return card->host.check_buffer_alignment(card->host.slot, buf, size);
|
||||
}
|
||||
|
||||
static esp_err_t allocate_dma_buf(size_t* actual_size, size_t block_size, void **buf)
|
||||
{
|
||||
if (actual_size == NULL || buf == NULL) {
|
||||
@@ -486,16 +500,10 @@ 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;
|
||||
bool is_aligned = card->host.check_buffer_alignment(card->host.slot, src, block_size * block_count);
|
||||
|
||||
if (is_aligned
|
||||
#if !SOC_SDMMC_PSRAM_DMA_CAPABLE
|
||||
&& !esp_ptr_external_ram(src)
|
||||
#endif
|
||||
) {
|
||||
if (sdmmc_buffer_directly_usable(card, src, block_size * block_count)) {
|
||||
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
|
||||
// The host cannot transfer this buffer directly. Split the write into
|
||||
// separate (multi) block writes, if needed, and allocate a temporary
|
||||
// DMA-capable buffer.
|
||||
size_t chunk_size = get_chunk_size(card);
|
||||
@@ -649,16 +657,10 @@ 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;
|
||||
bool is_aligned = card->host.check_buffer_alignment(card->host.slot, dst, block_size * block_count);
|
||||
|
||||
if (is_aligned
|
||||
#if !SOC_SDMMC_PSRAM_DMA_CAPABLE
|
||||
&& !esp_ptr_external_ram(dst)
|
||||
#endif
|
||||
) {
|
||||
if (sdmmc_buffer_directly_usable(card, dst, block_size * block_count)) {
|
||||
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
|
||||
// The host cannot transfer this buffer directly. Split the read into
|
||||
// separate (multi) block reads, if needed, and allocate a temporary
|
||||
// DMA-capable buffer.
|
||||
size_t chunk_size = get_chunk_size(card);
|
||||
|
||||
Reference in New Issue
Block a user