Skip to content

SPI NAND program load may fail with non-DMA-capable buffer (IEC-488) #684

@EeeeBin

Description

@EeeeBin

Answers checklist.

  • I have read the component documentation ESP-IDF Components and the issue is not addressed there.
  • I am using target and esp-idf version as defined in component's idf_component.yml
  • I have searched the issue tracker for a similar issue and not found any related issue.

Which component are you using? If you choose Other, provide details in More Information.

spi_nand_flash

ESP-IDF version.

v5.5.1

Development Kit.

ESP32P4

Used Component version.

v0.17.0

More Information.

Run the nand_flash + FatFs example. spi_nand_program_load() may fail because the provided data buffer can reside in non-DMA-capable memory (and/or be not 64-byte aligned). The current implementation conditionally sets SPI_TRANS_DMA_BUFFER_ALIGN_MANUAL based only on length alignment, without validating whether the buffer address and memory capabilities satisfy SPI DMA requirements.

When the data buffer is not DMA-capable or properly aligned, the SPI driver rejects the transaction, causing the NAND program operation to fail.

esp_err_t spi_nand_program_load(spi_nand_flash_device_t *handle, const uint8_t *data, uint16_t column, uint16_t length)
{
    ESP_LOGI("nand", "spi_nand_program_load: column=%"PRIu16", length=%"PRIu16, column, length);
    ESP_LOGI("nand", "data: %p, align 64 ? %d, dma capable ? %d", data, (uintptr_t)data % 64 == 0, esp_ptr_dma_capable(data));
    uint8_t cmd = CMD_PROGRAM_LOAD;
    uint32_t spi_flags = 0;
    if (handle->config.io_mode == SPI_NAND_IO_MODE_QOUT || handle->config.io_mode == SPI_NAND_IO_MODE_QIO) {
        cmd = CMD_PROGRAM_LOAD_X4;
        spi_flags = SPI_TRANS_MODE_QIO;
    }

    const uint8_t *data_write = data;
    uint16_t data_write_len = length;
    // memcpy(handle->temp_buffer, data_write, length);
    spi_nand_transaction_t t = {
        .command = cmd,
        .address_bytes = 2,
        .address = column,
        .mosi_len = data_write_len,
        .mosi_data = data_write,
        .flags = spi_flags,
    };

#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 2, 0)
    // Check if length needs alignment for DMA
    uint16_t aligned_len = check_length_alignment(handle, length);

    if (aligned_len == length) {
        t.flags |= SPI_TRANS_DMA_BUFFER_ALIGN_MANUAL;
    }
#endif

    esp_err_t ret = spi_nand_execute_transaction(handle, &t);

    return ret;
}

log:

I (1335) nand: spi_nand_program_load: column=0, length=2048
I (1335) nand: data: 0x480c1494, align 64? 0, dma capable? 0
E (1339) spi_master: setup_priv_desc(1193): Set flag SPI_TRANS_DMA_BUFFER_ALIGN_MANUAL but TX buffer addr&len not align to 64 byte, or not dma_capable
E (1352) spi_nand: nand_prog(223): 
E (1356) spi_nand: Error in nand_prog 258
E (1359) diskio_nand: ff_nand_write(65): spi_nand_flash_write failed
E (1365) diskio_nand: ff_nand_write failed with error 0x4FF151F4

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions