From 3a550d820d4ea0e5b0d48a6b63f9eecc5415986c Mon Sep 17 00:00:00 2001 From: "sonika.rathi" Date: Wed, 16 Oct 2024 11:23:04 +0200 Subject: [PATCH] update(spi_nand_flash): handle alignment and DMA requirements for work buffers --- spi_nand_flash/idf_component.yml | 2 +- spi_nand_flash/src/nand.c | 37 ++++++++++++++++++++++-------- spi_nand_flash/src/nand.h | 1 + spi_nand_flash/src/spi_nand_oper.c | 30 ++++++++++++++++++++---- spi_nand_flash/src/spi_nand_oper.h | 1 + 5 files changed, 55 insertions(+), 16 deletions(-) diff --git a/spi_nand_flash/idf_component.yml b/spi_nand_flash/idf_component.yml index 9bb154687d..068f188442 100644 --- a/spi_nand_flash/idf_component.yml +++ b/spi_nand_flash/idf_component.yml @@ -1,4 +1,4 @@ -version: "0.4.0" +version: "0.4.1" description: Driver for accessing SPI NAND Flash url: https://github.com/espressif/idf-extra-components/tree/master/spi_nand_flash issues: https://github.com/espressif/idf-extra-components/issues diff --git a/spi_nand_flash/src/nand.c b/spi_nand_flash/src/nand.c index 7415551eee..b0a0979f98 100644 --- a/spi_nand_flash/src/nand.c +++ b/spi_nand_flash/src/nand.c @@ -17,7 +17,7 @@ #include "nand_flash_devices.h" #include "esp_vfs_fat_nand.h" -static const char *TAG = "nand"; +static const char *TAG = "nand_flash"; static esp_err_t spi_nand_winbond_init(spi_nand_flash_device_t *dev) { @@ -26,13 +26,15 @@ static esp_err_t spi_nand_winbond_init(spi_nand_flash_device_t *dev) .command = CMD_READ_ID, .dummy_bits = 16, .miso_len = 2, - .miso_data = device_id_buf + .miso_data = device_id_buf, + .flags = SPI_TRANS_USE_RXDATA, }; spi_nand_execute_transaction(dev->config.device_handle, &t); uint16_t device_id = (device_id_buf[0] << 8) + device_id_buf[1]; dev->read_page_delay_us = 10; dev->erase_block_delay_us = 2500; dev->program_page_delay_us = 320; + ESP_LOGD(TAG, "%s: device_id: %x\n", __func__, device_id); switch (device_id) { case WINBOND_DI_AA20: case WINBOND_DI_BA20: @@ -58,11 +60,13 @@ static esp_err_t spi_nand_alliance_init(spi_nand_flash_device_t *dev) .address_bytes = 1, .dummy_bits = 8, .miso_len = 1, - .miso_data = &device_id + .miso_data = &device_id, + .flags = SPI_TRANS_USE_RXDATA, }; spi_nand_execute_transaction(dev->config.device_handle, &t); dev->erase_block_delay_us = 3000; dev->program_page_delay_us = 630; + ESP_LOGD(TAG, "%s: device_id: %x\n", __func__, device_id); switch (device_id) { case ALLIANCE_DI_25: //AS5F31G04SND-08LIN dev->dhara_nand.num_blocks = 1024; @@ -97,13 +101,14 @@ static esp_err_t spi_nand_gigadevice_init(spi_nand_flash_device_t *dev) .command = CMD_READ_ID, .dummy_bits = 16, .miso_len = 1, - .miso_data = &device_id + .miso_data = &device_id, + .flags = SPI_TRANS_USE_RXDATA, }; spi_nand_execute_transaction(dev->config.device_handle, &t); dev->read_page_delay_us = 25; dev->erase_block_delay_us = 3200; dev->program_page_delay_us = 380; - printf("device_id: %x\n", device_id); + ESP_LOGD(TAG, "%s: device_id: %x\n", __func__, device_id); switch (device_id) { case GIGADEVICE_DI_51: case GIGADEVICE_DI_41: @@ -136,12 +141,14 @@ static esp_err_t spi_nand_micron_init(spi_nand_flash_device_t *dev) .command = CMD_READ_ID, .dummy_bits = 16, .miso_len = 1, - .miso_data = &device_id + .miso_data = &device_id, + .flags = SPI_TRANS_USE_RXDATA, }; spi_nand_execute_transaction(dev->config.device_handle, &t); dev->read_page_delay_us = 115; dev->erase_block_delay_us = 2000; dev->program_page_delay_us = 240; + ESP_LOGD(TAG, "%s: device_id: %x\n", __func__, device_id); switch (device_id) { case MICRON_DI_34: dev->dhara_nand.num_blocks = 2048; @@ -162,9 +169,11 @@ static esp_err_t detect_chip(spi_nand_flash_device_t *dev) .address = 0, // This normally selects the manufacturer id. Some chips ignores it, but still expects 8 dummy bits here .address_bytes = 1, .miso_len = 1, - .miso_data = &manufacturer_id + .miso_data = &manufacturer_id, + .flags = SPI_TRANS_USE_RXDATA, }; spi_nand_execute_transaction(dev->config.device_handle, &t); + ESP_LOGD(TAG, "%s: manufacturer_id: %x\n", __func__, manufacturer_id); switch (manufacturer_id) { case SPI_NAND_FLASH_ALLIANCE_MI: // Alliance @@ -221,10 +230,13 @@ esp_err_t spi_nand_flash_init_device(spi_nand_flash_config_t *config, spi_nand_f (*handle)->page_size = 1 << (*handle)->dhara_nand.log2_page_size; (*handle)->block_size = (1 << (*handle)->dhara_nand.log2_ppb) * (*handle)->page_size; (*handle)->num_blocks = (*handle)->dhara_nand.num_blocks; - (*handle)->work_buffer = malloc((*handle)->page_size); + (*handle)->work_buffer = heap_caps_malloc((*handle)->page_size, MALLOC_CAP_DMA | MALLOC_CAP_8BIT); ESP_GOTO_ON_FALSE((*handle)->work_buffer != NULL, ESP_ERR_NO_MEM, fail, TAG, "nomem"); + (*handle)->read_buffer = heap_caps_malloc((*handle)->page_size, MALLOC_CAP_DMA | MALLOC_CAP_8BIT); + ESP_GOTO_ON_FALSE((*handle)->read_buffer != NULL, ESP_ERR_NO_MEM, fail, TAG, "nomem"); + (*handle)->mutex = xSemaphoreCreateMutex(); if (!(*handle)->mutex) { ret = ESP_ERR_NO_MEM; @@ -242,6 +254,9 @@ esp_err_t spi_nand_flash_init_device(spi_nand_flash_config_t *config, spi_nand_f if ((*handle)->work_buffer != NULL) { free((*handle)->work_buffer); } + if ((*handle)->read_buffer != NULL) { + free((*handle)->read_buffer); + } if ((*handle)->mutex != NULL) { vSemaphoreDelete((*handle)->mutex); } @@ -281,16 +296,17 @@ esp_err_t spi_nand_flash_read_sector(spi_nand_flash_device_t *handle, uint8_t *b xSemaphoreTake(handle->mutex, portMAX_DELAY); - if (dhara_map_read(&handle->dhara_map, sector_id, buffer, &err)) { + if (dhara_map_read(&handle->dhara_map, sector_id, handle->read_buffer, &err)) { ret = ESP_ERR_FLASH_BASE + err; } else if (err) { // This indicates a soft ECC error, we rewrite the sector to recover - if (dhara_map_write(&handle->dhara_map, sector_id, buffer, &err)) { + if (dhara_map_write(&handle->dhara_map, sector_id, handle->read_buffer, &err)) { ret = ESP_ERR_FLASH_BASE + err; } } xSemaphoreGive(handle->mutex); + memcpy(buffer, handle->read_buffer, handle->page_size); return ret; } @@ -339,6 +355,7 @@ esp_err_t spi_nand_flash_get_sector_size(spi_nand_flash_device_t *handle, uint32 esp_err_t spi_nand_flash_deinit_device(spi_nand_flash_device_t *handle) { free(handle->work_buffer); + free(handle->read_buffer); vSemaphoreDelete(handle->mutex); free(handle); return ESP_OK; diff --git a/spi_nand_flash/src/nand.h b/spi_nand_flash/src/nand.h index 4b046c9a34..d5db7c9c08 100644 --- a/spi_nand_flash/src/nand.h +++ b/spi_nand_flash/src/nand.h @@ -27,6 +27,7 @@ struct spi_nand_flash_device_t { struct dhara_map dhara_map; struct dhara_nand dhara_nand; uint8_t *work_buffer; + uint8_t *read_buffer; uint32_t read_page_delay_us; uint32_t erase_block_delay_us; uint32_t program_page_delay_us; diff --git a/spi_nand_flash/src/spi_nand_oper.c b/spi_nand_flash/src/spi_nand_oper.c index 3b7f1be160..88496a844c 100644 --- a/spi_nand_flash/src/spi_nand_oper.c +++ b/spi_nand_flash/src/spi_nand_oper.c @@ -6,6 +6,7 @@ * SPDX-FileContributor: 2015-2023 Espressif Systems (Shanghai) CO LTD */ +#include #include "spi_nand_oper.h" #include "driver/spi_master.h" @@ -13,7 +14,7 @@ esp_err_t spi_nand_execute_transaction(spi_device_handle_t device, spi_nand_tran { spi_transaction_ext_t e = { .base = { - .flags = SPI_TRANS_VARIABLE_ADDR | SPI_TRANS_VARIABLE_CMD | SPI_TRANS_VARIABLE_DUMMY, + .flags = SPI_TRANS_VARIABLE_ADDR | SPI_TRANS_VARIABLE_CMD | SPI_TRANS_VARIABLE_DUMMY | transaction->flags, .rxlength = transaction->miso_len * 8, .rx_buffer = transaction->miso_data, .length = transaction->mosi_len * 8, @@ -26,7 +27,21 @@ esp_err_t spi_nand_execute_transaction(spi_device_handle_t device, spi_nand_tran .dummy_bits = transaction->dummy_bits }; - return spi_device_transmit(device, (spi_transaction_t *) &e); + if (transaction->flags == SPI_TRANS_USE_TXDATA) { + assert(transaction->mosi_len <= 4 && "SPI_TRANS_USE_TXDATA used for a long transaction"); + memcpy(e.base.tx_data, transaction->mosi_data, transaction->mosi_len); + } + if (transaction->flags == SPI_TRANS_USE_RXDATA) { + assert(transaction->miso_len <= 4 && "SPI_TRANS_USE_RXDATA used for a long transaction"); + } + + esp_err_t ret = spi_device_transmit(device, (spi_transaction_t *) &e); + if (ret == ESP_OK) { + if (transaction->flags == SPI_TRANS_USE_RXDATA) { + memcpy(transaction->miso_data, e.base.rx_data, transaction->miso_len); + } + } + return ret; } esp_err_t spi_nand_read_register(spi_device_handle_t device, uint8_t reg, uint8_t *val) @@ -36,7 +51,8 @@ esp_err_t spi_nand_read_register(spi_device_handle_t device, uint8_t reg, uint8_ .address_bytes = 1, .address = reg, .miso_len = 1, - .miso_data = val + .miso_data = val, + .flags = SPI_TRANS_USE_RXDATA, }; return spi_nand_execute_transaction(device, &t); @@ -49,7 +65,8 @@ esp_err_t spi_nand_write_register(spi_device_handle_t device, uint8_t reg, uint8 .address_bytes = 1, .address = reg, .mosi_len = 1, - .mosi_data = &val + .mosi_data = &val, + .flags = SPI_TRANS_USE_TXDATA, }; return spi_nand_execute_transaction(device, &t); @@ -83,7 +100,10 @@ esp_err_t spi_nand_read(spi_device_handle_t device, uint8_t *data, uint16_t colu .address = column, .miso_len = length, .miso_data = data, - .dummy_bits = 8 + .dummy_bits = 8, +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 2, 0) + .flags = SPI_TRANS_DMA_BUFFER_ALIGN_MANUAL, +#endif }; return spi_nand_execute_transaction(device, &t); diff --git a/spi_nand_flash/src/spi_nand_oper.h b/spi_nand_flash/src/spi_nand_oper.h index 3e83120836..7bf0e9de36 100644 --- a/spi_nand_flash/src/spi_nand_oper.h +++ b/spi_nand_flash/src/spi_nand_oper.h @@ -25,6 +25,7 @@ struct spi_nand_transaction_t { uint32_t miso_len; uint8_t *miso_data; uint32_t dummy_bits; + uint32_t flags; }; typedef struct spi_nand_transaction_t spi_nand_transaction_t;