mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 03:00:34 +03:00
feat(sdmmc): Use zero-copy TX for SDSPI
This commit is contained in:
+32
@@ -352,6 +352,38 @@ void sdmmc_test_rw_psram_buffer(sdmmc_card_t *card)
|
||||
TEST_ESP_OK(sdmmc_read_sectors(card, psram_buf, 0, block_count));
|
||||
check_buffer(seed_c, psram_buf, buffer_size / sizeof(uint32_t));
|
||||
|
||||
/* Test D: Write from a PSRAM buffer that is NOT cache/DMA aligned.
|
||||
*
|
||||
* The host (or the underlying SPI master) must transparently handle the
|
||||
* unaligned PSRAM source - either by an internal aligned copy or by direct
|
||||
* DMA when the hardware supports it. This exercises the fallback path of the
|
||||
* SDSPI write transfer, which no longer copies the buffer itself but relies
|
||||
* on the SPI master to accept PSRAM buffers (SPI_TRANS_DMA_USE_PSRAM). The
|
||||
* data read back must still match.
|
||||
*
|
||||
* NOTE: this sub-test requires real SD-card + PSRAM hardware to be meaningful.
|
||||
*/
|
||||
{
|
||||
const size_t misalign = 1; /* 1-byte offset breaks 4-byte/cache alignment */
|
||||
uint8_t *unaligned_psram = heap_caps_malloc(buffer_size + misalign,
|
||||
MALLOC_CAP_SPIRAM | MALLOC_CAP_DMA);
|
||||
TEST_ASSERT_NOT_NULL_MESSAGE(unaligned_psram, "Failed to allocate PSRAM buffer");
|
||||
uint8_t *src = unaligned_psram + misalign;
|
||||
TEST_ASSERT_MESSAGE(esp_ptr_external_ram(src), "Buffer not in PSRAM");
|
||||
|
||||
const uint32_t seed_d = 0x13572468;
|
||||
for (size_t i = 0; i < buffer_size; i++) {
|
||||
src[i] = (uint8_t)(seed_d + i);
|
||||
}
|
||||
TEST_ESP_OK(sdmmc_write_sectors(card, src, 0, block_count));
|
||||
memset(internal_buf, 0xcc, buffer_size);
|
||||
TEST_ESP_OK(sdmmc_read_sectors(card, internal_buf, 0, block_count));
|
||||
for (size_t i = 0; i < buffer_size; i++) {
|
||||
TEST_ASSERT_EQUAL_HEX8((uint8_t)(seed_d + i), internal_buf[i]);
|
||||
}
|
||||
free(unaligned_psram);
|
||||
}
|
||||
|
||||
free(psram_buf);
|
||||
free(internal_buf);
|
||||
printf("PSRAM buffer R/W test passed\n");
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -20,7 +20,6 @@
|
||||
#include "esp_timer.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "soc/soc_memory_layout.h"
|
||||
#include "esp_private/esp_cache_private.h"
|
||||
|
||||
/// Max number of transactions in flight (used in start_command_write_blocks)
|
||||
@@ -931,22 +930,17 @@ static esp_err_t start_command_write_blocks(slot_info_t *slot, sdspi_hw_cmd_t *c
|
||||
|
||||
// Prepare data to be sent
|
||||
size_t will_send = MIN(tx_length, SDSPI_MAX_DATA_LEN);
|
||||
const uint8_t* tx_data = data;
|
||||
if (!esp_ptr_in_dram(tx_data)) {
|
||||
// If the pointer can't be used with DMA, copy data into a new buffer
|
||||
uint8_t* tmp;
|
||||
ret = get_block_buf(slot, &tmp);
|
||||
if (ret != ESP_OK) {
|
||||
return ret;
|
||||
}
|
||||
memcpy(tmp, tx_data, will_send);
|
||||
tx_data = tmp;
|
||||
}
|
||||
|
||||
// Write data
|
||||
// Write data. The SPI master driver handles buffers that are not
|
||||
// directly DMA-usable (e.g. PSRAM, or unaligned): with
|
||||
// SPI_TRANS_DMA_USE_PSRAM it transfers a suitable PSRAM buffer directly
|
||||
// (no copy), and otherwise falls back to an internal aligned buffer
|
||||
// itself. This avoids the redundant copy the SDSPI driver used to do.
|
||||
// The flag is ignored for buffers that are not in PSRAM.
|
||||
spi_transaction_t t_data = {
|
||||
.length = will_send * 8,
|
||||
.tx_buffer = tx_data,
|
||||
.tx_buffer = data,
|
||||
.flags = SPI_TRANS_DMA_USE_PSRAM,
|
||||
};
|
||||
ret = spi_device_transmit(slot->spi_handle, &t_data);
|
||||
if (ret != ESP_OK) {
|
||||
|
||||
Reference in New Issue
Block a user