Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update(spi_nand_flash): handle alignment and DMA requirements for work buffers #426

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion spi_nand_flash/idf_component.yml
Original file line number Diff line number Diff line change
@@ -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
Expand Down
37 changes: 27 additions & 10 deletions spi_nand_flash/src/nand.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand All @@ -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:
Expand All @@ -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;
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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;
Expand All @@ -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
Expand Down Expand Up @@ -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;
Expand All @@ -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) {
RathiSonika marked this conversation as resolved.
Show resolved Hide resolved
free((*handle)->read_buffer);
}
if ((*handle)->mutex != NULL) {
vSemaphoreDelete((*handle)->mutex);
}
Expand Down Expand Up @@ -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);
Dismissed Show dismissed Hide dismissed
RathiSonika marked this conversation as resolved.
Show resolved Hide resolved
return ret;
}

Expand Down Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions spi_nand_flash/src/nand.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
30 changes: 25 additions & 5 deletions spi_nand_flash/src/spi_nand_oper.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@
* SPDX-FileContributor: 2015-2023 Espressif Systems (Shanghai) CO LTD
*/

#include <string.h>
#include "spi_nand_oper.h"
#include "driver/spi_master.h"

esp_err_t spi_nand_execute_transaction(spi_device_handle_t device, spi_nand_transaction_t *transaction)
{
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,
Expand All @@ -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) {
RathiSonika marked this conversation as resolved.
Show resolved Hide resolved
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);
Fixed Show fixed Hide fixed
Dismissed Show dismissed Hide dismissed
}
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);
github-advanced-security[bot] marked this conversation as resolved.
Dismissed
Show resolved Hide resolved
}
}
return ret;
}

esp_err_t spi_nand_read_register(spi_device_handle_t device, uint8_t reg, uint8_t *val)
Expand All @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -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,
RathiSonika marked this conversation as resolved.
Show resolved Hide resolved
#endif
};

return spi_nand_execute_transaction(device, &t);
Expand Down
1 change: 1 addition & 0 deletions spi_nand_flash/src/spi_nand_oper.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Loading