From a9c8895bb29077b47c444b7ebf0f0e1bdc096494 Mon Sep 17 00:00:00 2001 From: "Michael (XIAO Xufeng)" Date: Thu, 30 Apr 2020 10:37:35 +0800 Subject: [PATCH 1/3] esp_flash: refactor to be compatible with the latest ROM Including: 1. Change the write bytes/read bytes parameter in the host driver into slicers to meet the requirements of complicated cases. 2. Refactor the esp_flash_api code a bit so that we can use the code in the ROM laster 3. Provide get_temp_buffer and release_temp_buffer in the os_functions when the buffer passed by application cannot be used directly. 4. Make timeout of operations configurable in the chip_driver. 5. Make dummy number configurable. --- components/soc/include/hal/spi_flash_types.h | 32 ++- components/spi_flash/esp_flash_api.c | 221 ++++++++++-------- components/spi_flash/include/esp_flash.h | 24 +- .../spi_flash/include/memspi_host_driver.h | 41 +++- .../spi_flash/include/spi_flash_chip_driver.h | 11 + .../include/spi_flash_chip_generic.h | 3 + components/spi_flash/memspi_host_driver.c | 69 ++++-- components/spi_flash/spi_flash_chip_gd.c | 1 + components/spi_flash/spi_flash_chip_generic.c | 110 ++++++--- components/spi_flash/spi_flash_chip_issi.c | 1 + components/spi_flash/spi_flash_chip_mxic.c | 1 + components/spi_flash/spi_flash_os_func_app.c | 34 ++- components/spi_flash/spi_flash_os_func_noos.c | 10 +- 13 files changed, 390 insertions(+), 168 deletions(-) diff --git a/components/soc/include/hal/spi_flash_types.h b/components/soc/include/hal/spi_flash_types.h index 0a468c6075..586dd6ee89 100644 --- a/components/soc/include/hal/spi_flash_types.h +++ b/components/soc/include/hal/spi_flash_types.h @@ -115,18 +115,36 @@ struct spi_flash_host_driver_t { * Program a page of the flash. Check ``max_write_bytes`` for the maximum allowed writing length. */ void (*program_page)(spi_flash_host_driver_t *driver, const void *buffer, uint32_t address, uint32_t length); - /** Check whether need to allocate new buffer to write */ + /** Check whether given buffer can be directly used to write */ bool (*supports_direct_write)(spi_flash_host_driver_t *driver, const void *p); - /** Check whether need to allocate new buffer to read */ - bool (*supports_direct_read)(spi_flash_host_driver_t *driver, const void *p); - /** maximum length of program_page */ - int max_write_bytes; + /** + * Slicer for write data. The `program_page` should be called iteratively with the return value + * of this function. + * + * @param address Beginning flash address to write + * @param len Length request to write + * @param align_addr Output of the aligned address to write to + * @param page_size Physical page size of the flash chip + * @return Length that can be actually written in one `program_page` call + */ + int (*write_data_slicer)(uint32_t address, uint32_t len, uint32_t *align_addr, uint32_t page_size); /** * Read data from the flash. Check ``max_read_bytes`` for the maximum allowed reading length. */ esp_err_t (*read)(spi_flash_host_driver_t *driver, void *buffer, uint32_t address, uint32_t read_len); - /** maximum length of read */ - int max_read_bytes; + /** Check whether given buffer can be directly used to read */ + bool (*supports_direct_read)(spi_flash_host_driver_t *driver, const void *p); + /** + * Slicer for read data. The `read` should be called iteratively with the return value + * of this function. + * + * @param address Beginning flash address to read + * @param len Length request to read + * @param align_addr Output of the aligned address to read + * @param page_size Physical page size of the flash chip + * @return Length that can be actually read in one `read` call + */ + int (*read_data_slicer)(uint32_t address, uint32_t len, uint32_t *align_addr, uint32_t page_size); /** * Check whether the host is idle to perform new operations. */ diff --git a/components/spi_flash/esp_flash_api.c b/components/spi_flash/esp_flash_api.c index 8ea142a7ca..802d69684a 100644 --- a/components/spi_flash/esp_flash_api.c +++ b/components/spi_flash/esp_flash_api.c @@ -71,12 +71,31 @@ _Static_assert(sizeof(io_mode_str)/IO_STR_LEN == SPI_FLASH_READ_MODE_MAX, "the i esp_err_t esp_flash_read_chip_id(esp_flash_t* chip, uint32_t* flash_id); +static esp_err_t spiflash_start_default(esp_flash_t *chip); +static esp_err_t spiflash_end_default(esp_flash_t *chip, esp_err_t err); +static esp_err_t check_chip_pointer_default(esp_flash_t **inout_chip); + +typedef struct { + esp_err_t (*start)(esp_flash_t *chip); + esp_err_t (*end)(esp_flash_t *chip, esp_err_t err); + esp_err_t (*chip_check)(esp_flash_t **inout_chip); +} rom_spiflash_api_func_t; + +// These functions can be placed in the ROM. For now we use the code in IDF. +DRAM_ATTR static rom_spiflash_api_func_t default_spiflash_rom_api = { + .start = spiflash_start_default, + .end = spiflash_end_default, + .chip_check = check_chip_pointer_default, +}; + +DRAM_ATTR rom_spiflash_api_func_t *rom_spiflash_api_funcs = &default_spiflash_rom_api; + /* Static function to notify OS of a new SPI flash operation. If returns an error result, caller must abort. If returns ESP_OK, caller must - call spiflash_end() before returning. + call rom_spiflash_api_funcs->end() before returning. */ -static esp_err_t IRAM_ATTR spiflash_start(esp_flash_t *chip) +static esp_err_t IRAM_ATTR spiflash_start_default(esp_flash_t *chip) { if (chip->os_func != NULL && chip->os_func->start != NULL) { esp_err_t err = chip->os_func->start(chip->os_func_data); @@ -90,7 +109,7 @@ static esp_err_t IRAM_ATTR spiflash_start(esp_flash_t *chip) /* Static function to notify OS that SPI flash operation is complete. */ -static esp_err_t IRAM_ATTR spiflash_end(const esp_flash_t *chip, esp_err_t err) +static esp_err_t IRAM_ATTR spiflash_end_default(esp_flash_t *chip, esp_err_t err) { if (chip->os_func != NULL && chip->os_func->end != NULL) { @@ -102,6 +121,20 @@ static esp_err_t IRAM_ATTR spiflash_end(const esp_flash_t *chip, esp_err_t err) return err; } +// check that the 'chip' parameter is properly initialised +static esp_err_t check_chip_pointer_default(esp_flash_t **inout_chip) +{ + esp_flash_t *chip = *inout_chip; + if (chip == NULL) { + chip = esp_flash_default_chip; + } + *inout_chip = chip; + if (chip == NULL || !esp_flash_chip_driver_initialized(chip)) { + return ESP_ERR_FLASH_NOT_INITIALISED; + } + return ESP_OK; +} + /* Return true if regions 'a' and 'b' overlap at all, based on their start offsets and lengths. */ inline static bool regions_overlap(uint32_t a_start, uint32_t a_len,uint32_t b_start, uint32_t b_len); @@ -152,7 +185,7 @@ esp_err_t IRAM_ATTR esp_flash_init(esp_flash_t *chip) } ESP_LOGI(TAG, "flash io: %s", io_mode_str[chip->read_mode]); - err = spiflash_start(chip); + err = rom_spiflash_api_funcs->start(chip); if (err != ESP_OK) { return err; } @@ -166,13 +199,13 @@ esp_err_t IRAM_ATTR esp_flash_init(esp_flash_t *chip) } } // Done: all fields on 'chip' are initialised - return spiflash_end(chip, err); + return rom_spiflash_api_funcs->end(chip, err); } //this is not public, but useful in unit tests esp_err_t IRAM_ATTR esp_flash_read_chip_id(esp_flash_t* chip, uint32_t* flash_id) { - esp_err_t err = spiflash_start(chip); + esp_err_t err = rom_spiflash_api_funcs->start(chip); if (err != ESP_OK) { return err; } @@ -189,7 +222,7 @@ esp_err_t IRAM_ATTR esp_flash_read_chip_id(esp_flash_t* chip, uint32_t* flash_id } } - return spiflash_end(chip, err); + return rom_spiflash_api_funcs->end(chip, err); } static esp_err_t IRAM_ATTR detect_spi_flash_chip(esp_flash_t *chip) @@ -205,7 +238,7 @@ static esp_err_t IRAM_ATTR detect_spi_flash_chip(esp_flash_t *chip) // and also so esp_flash_registered_flash_drivers can live in flash ESP_LOGD(TAG, "trying chip: %s", chip->chip_drv->name); - err = spiflash_start(chip); + err = rom_spiflash_api_funcs->start(chip); if (err != ESP_OK) { return err; } @@ -216,7 +249,7 @@ static esp_err_t IRAM_ATTR detect_spi_flash_chip(esp_flash_t *chip) // if probe succeeded, chip->drv stays set drivers++; - err = spiflash_end(chip, err); + err = rom_spiflash_api_funcs->end(chip, err); if (err != ESP_OK) { return err; } @@ -228,16 +261,12 @@ static esp_err_t IRAM_ATTR detect_spi_flash_chip(esp_flash_t *chip) return ESP_OK; } -// Convenience macro for beginning of all API functions, -// check that the 'chip' parameter is properly initialised -// and supports the operation in question -#define VERIFY_OP(OP) do { \ - if (chip == NULL) { \ - chip = esp_flash_default_chip; \ - } \ - if (chip == NULL || !esp_flash_chip_driver_initialized(chip)) { \ - return ESP_ERR_FLASH_NOT_INITIALISED; \ - } \ +/* Convenience macro for beginning of all API functions. + * Check the return value of `rom_spiflash_api_funcs->chip_check` is correct, + * and the chip supports the operation in question. + */ +#define VERIFY_CHIP_OP(OP) do { \ + if (err != ESP_OK) return err; \ if (chip->chip_drv->OP == NULL) { \ return ESP_ERR_FLASH_UNSUPPORTED_CHIP; \ } \ @@ -245,28 +274,25 @@ static esp_err_t IRAM_ATTR detect_spi_flash_chip(esp_flash_t *chip) esp_err_t IRAM_ATTR esp_flash_read_id(esp_flash_t *chip, uint32_t *out_id) { - if (chip == NULL) { - chip = esp_flash_default_chip; - } - if (chip == NULL || !esp_flash_chip_driver_initialized(chip)) { - return ESP_ERR_FLASH_NOT_INITIALISED; - } - if (out_id == NULL) { - return ESP_ERR_INVALID_ARG; - } - esp_err_t err = spiflash_start(chip); + esp_err_t err = rom_spiflash_api_funcs->chip_check(&chip); + //Accept uninitialized chip when reading chip id + if (err != ESP_OK && !(err == ESP_ERR_FLASH_NOT_INITIALISED && chip != NULL)) return err; + if (out_id == NULL) return ESP_ERR_INVALID_ARG; + + err = rom_spiflash_api_funcs->start(chip); if (err != ESP_OK) { return err; } err = chip->host->read_id(chip->host, out_id); - return spiflash_end(chip, err); + return rom_spiflash_api_funcs->end(chip, err); } esp_err_t IRAM_ATTR esp_flash_get_size(esp_flash_t *chip, uint32_t *out_size) { - VERIFY_OP(detect_size); + esp_err_t err = rom_spiflash_api_funcs->chip_check(&chip); + VERIFY_CHIP_OP(detect_size); if (out_size == NULL) { return ESP_ERR_INVALID_ARG; } @@ -275,7 +301,7 @@ esp_err_t IRAM_ATTR esp_flash_get_size(esp_flash_t *chip, uint32_t *out_size) return ESP_OK; } - esp_err_t err = spiflash_start(chip); + err = rom_spiflash_api_funcs->start(chip); if (err != ESP_OK) { return err; } @@ -284,28 +310,31 @@ esp_err_t IRAM_ATTR esp_flash_get_size(esp_flash_t *chip, uint32_t *out_size) if (err == ESP_OK) { chip->size = detect_size; } - return spiflash_end(chip, err); + return rom_spiflash_api_funcs->end(chip, err); } esp_err_t IRAM_ATTR esp_flash_erase_chip(esp_flash_t *chip) { - VERIFY_OP(erase_chip); + esp_err_t err = rom_spiflash_api_funcs->chip_check(&chip); + VERIFY_CHIP_OP(erase_chip); CHECK_WRITE_ADDRESS(chip, 0, chip->size); - esp_err_t err = spiflash_start(chip); + err = rom_spiflash_api_funcs->start(chip); if (err != ESP_OK) { return err; } err = chip->chip_drv->erase_chip(chip); - return spiflash_end(chip, err); + return rom_spiflash_api_funcs->end(chip, err); } esp_err_t IRAM_ATTR esp_flash_erase_region(esp_flash_t *chip, uint32_t start, uint32_t len) { - VERIFY_OP(erase_sector); - VERIFY_OP(erase_block); + esp_err_t err = rom_spiflash_api_funcs->chip_check(&chip); + VERIFY_CHIP_OP(erase_sector); + VERIFY_CHIP_OP(erase_block); CHECK_WRITE_ADDRESS(chip, start, len); + uint32_t block_erase_size = chip->chip_drv->erase_block == NULL ? 0 : chip->chip_drv->block_erase_size; uint32_t sector_size = chip->chip_drv->sector_size; @@ -320,12 +349,12 @@ esp_err_t IRAM_ATTR esp_flash_erase_region(esp_flash_t *chip, uint32_t start, ui return ESP_ERR_INVALID_ARG; } - esp_err_t err = ESP_OK; + err = ESP_OK; // Check for write protected regions overlapping the erase region if (chip->chip_drv->get_protected_regions != NULL && chip->chip_drv->num_protectable_regions > 0) { - err = spiflash_start(chip); + err = rom_spiflash_api_funcs->start(chip); if (err != ESP_OK) { return err; } @@ -341,7 +370,7 @@ esp_err_t IRAM_ATTR esp_flash_erase_region(esp_flash_t *chip, uint32_t start, ui } } // Don't lock the SPI flash for the entire erase, as this may be very long - err = spiflash_end(chip, err); + err = rom_spiflash_api_funcs->end(chip, err); } #ifdef CONFIG_SPI_FLASH_YIELD_DURING_ERASE @@ -351,7 +380,7 @@ esp_err_t IRAM_ATTR esp_flash_erase_region(esp_flash_t *chip, uint32_t start, ui #ifdef CONFIG_SPI_FLASH_YIELD_DURING_ERASE int64_t start_time_us = esp_timer_get_time(); #endif - err = spiflash_start(chip); + err = rom_spiflash_api_funcs->start(chip); if (err != ESP_OK) { return err; } @@ -371,7 +400,7 @@ esp_err_t IRAM_ATTR esp_flash_erase_region(esp_flash_t *chip, uint32_t start, ui len -= sector_size; } - err = spiflash_end(chip, err); + err = rom_spiflash_api_funcs->end(chip, err); #ifdef CONFIG_SPI_FLASH_YIELD_DURING_ERASE no_yield_time_us += (esp_timer_get_time() - start_time_us); @@ -388,34 +417,36 @@ esp_err_t IRAM_ATTR esp_flash_erase_region(esp_flash_t *chip, uint32_t start, ui esp_err_t IRAM_ATTR esp_flash_get_chip_write_protect(esp_flash_t *chip, bool *out_write_protected) { - VERIFY_OP(get_chip_write_protect); + esp_err_t err = rom_spiflash_api_funcs->chip_check(&chip); + VERIFY_CHIP_OP(get_chip_write_protect); if (out_write_protected == NULL) { return ESP_ERR_INVALID_ARG; } - esp_err_t err = spiflash_start(chip); + err = rom_spiflash_api_funcs->start(chip); if (err != ESP_OK) { return err; } err = chip->chip_drv->get_chip_write_protect(chip, out_write_protected); - return spiflash_end(chip, err); + return rom_spiflash_api_funcs->end(chip, err); } esp_err_t IRAM_ATTR esp_flash_set_chip_write_protect(esp_flash_t *chip, bool write_protect) { - VERIFY_OP(set_chip_write_protect); + esp_err_t err = rom_spiflash_api_funcs->chip_check(&chip); + VERIFY_CHIP_OP(set_chip_write_protect); //TODO: skip writing if already locked or unlocked - esp_err_t err = spiflash_start(chip); + err = rom_spiflash_api_funcs->start(chip); if (err != ESP_OK) { return err; } err = chip->chip_drv->set_chip_write_protect(chip, write_protect); - return spiflash_end(chip, err); + return rom_spiflash_api_funcs->end(chip, err); } esp_err_t esp_flash_get_protectable_regions(const esp_flash_t *chip, const esp_flash_region_t **out_regions, uint32_t *out_num_regions) @@ -423,7 +454,8 @@ esp_err_t esp_flash_get_protectable_regions(const esp_flash_t *chip, const esp_f if(out_num_regions != NULL) { *out_num_regions = 0; // In case caller doesn't check result } - VERIFY_OP(get_protected_regions); + esp_err_t err = rom_spiflash_api_funcs->chip_check((esp_flash_t **)&chip); + VERIFY_CHIP_OP(get_protected_regions); if(out_regions == NULL || out_num_regions == NULL) { return ESP_ERR_INVALID_ARG; @@ -452,20 +484,21 @@ static esp_err_t find_region(const esp_flash_t *chip, const esp_flash_region_t * esp_err_t IRAM_ATTR esp_flash_get_protected_region(esp_flash_t *chip, const esp_flash_region_t *region, bool *out_protected) { - VERIFY_OP(get_protected_regions); + esp_err_t err = rom_spiflash_api_funcs->chip_check(&chip); + VERIFY_CHIP_OP(get_protected_regions); if (out_protected == NULL) { return ESP_ERR_INVALID_ARG; } uint8_t index; - esp_err_t err = find_region(chip, region, &index); + err = find_region(chip, region, &index); if (err != ESP_OK) { return err; } uint64_t protection_mask = 0; - err = spiflash_start(chip); + err = rom_spiflash_api_funcs->start(chip); if (err != ESP_OK) { return err; } @@ -475,21 +508,22 @@ esp_err_t IRAM_ATTR esp_flash_get_protected_region(esp_flash_t *chip, const esp_ *out_protected = protection_mask & (1LL << index); } - return spiflash_end(chip, err); + return rom_spiflash_api_funcs->end(chip, err); } esp_err_t IRAM_ATTR esp_flash_set_protected_region(esp_flash_t *chip, const esp_flash_region_t *region, bool protect) { - VERIFY_OP(set_protected_regions); + esp_err_t err = rom_spiflash_api_funcs->chip_check(&chip); + VERIFY_CHIP_OP(set_protected_regions); uint8_t index; - esp_err_t err = find_region(chip, region, &index); + err = find_region(chip, region, &index); if (err != ESP_OK) { return err; } uint64_t protection_mask = 0; - err = spiflash_start(chip); + err = rom_spiflash_api_funcs->start(chip); if (err != ESP_OK) { return err; } @@ -504,7 +538,7 @@ esp_err_t IRAM_ATTR esp_flash_set_protected_region(esp_flash_t *chip, const esp_ err = chip->chip_drv->set_protected_regions(chip, protection_mask); } - return spiflash_end(chip, err); + return rom_spiflash_api_funcs->end(chip, err); } esp_err_t IRAM_ATTR esp_flash_read(esp_flash_t *chip, void *buffer, uint32_t address, uint32_t length) @@ -512,7 +546,8 @@ esp_err_t IRAM_ATTR esp_flash_read(esp_flash_t *chip, void *buffer, uint32_t add if (length == 0) { return ESP_OK; } - VERIFY_OP(read); + esp_err_t err = rom_spiflash_api_funcs->chip_check(&chip); + VERIFY_CHIP_OP(read); if (buffer == NULL || address > chip->size || address+length > chip->size) { return ESP_ERR_INVALID_ARG; } @@ -526,29 +561,17 @@ esp_err_t IRAM_ATTR esp_flash_read(esp_flash_t *chip, void *buffer, uint32_t add size_t read_chunk_size = MIN(MAX_READ_CHUNK, length); if (!direct_read) { - /* Allocate temporary internal buffer to use for the actual read. If the preferred size - doesn't fit in free internal memory, allocate the largest available free block. - - (May need to shrink read_chunk_size and retry due to race conditions with other tasks - also allocating from the heap.) - */ - unsigned retries = 5; - while(temp_buffer == NULL && retries--) { - read_chunk_size = MIN(read_chunk_size, heap_caps_get_largest_free_block(MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT)); - read_chunk_size = (read_chunk_size + 3) & ~3; - temp_buffer = heap_caps_malloc(read_chunk_size, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); - } - ESP_LOGV(TAG, "allocate temp buffer: %p (%d)", temp_buffer, read_chunk_size); - + size_t actual_len = 0; + temp_buffer = chip->os_func->get_temp_buffer(chip->os_func_data, read_chunk_size, &actual_len); + read_chunk_size = actual_len; if (temp_buffer == NULL) { return ESP_ERR_NO_MEM; } } - esp_err_t err = ESP_OK; - + err = ESP_OK; do { - err = spiflash_start(chip); + err = rom_spiflash_api_funcs->start(chip); if (err != ESP_OK) { break; } @@ -562,11 +585,11 @@ esp_err_t IRAM_ATTR esp_flash_read(esp_flash_t *chip, void *buffer, uint32_t add err = chip->chip_drv->read(chip, buffer_to_read, address, length_to_read); } if (err != ESP_OK) { - spiflash_end(chip, err); + rom_spiflash_api_funcs->end(chip, err); break; } //even if this is failed, the data is still valid, copy before quit - err = spiflash_end(chip, err); + err = rom_spiflash_api_funcs->end(chip, err); //copy back to the original buffer if (temp_buffer) { @@ -574,10 +597,10 @@ esp_err_t IRAM_ATTR esp_flash_read(esp_flash_t *chip, void *buffer, uint32_t add } address += length_to_read; length -= length_to_read; - buffer += length_to_read; + buffer = (void*)((intptr_t)buffer + length_to_read); } while (err == ESP_OK && length > 0); - free(temp_buffer); + chip->os_func->release_temp_buffer(chip->os_func_data, temp_buffer); return err; } @@ -586,7 +609,8 @@ esp_err_t IRAM_ATTR esp_flash_write(esp_flash_t *chip, const void *buffer, uint3 if (length == 0) { return ESP_OK; } - VERIFY_OP(write); + esp_err_t err = rom_spiflash_api_funcs->chip_check(&chip); + VERIFY_CHIP_OP(write); CHECK_WRITE_ADDRESS(chip, address, length); if (buffer == NULL || address > chip->size || address+length > chip->size) { return ESP_ERR_INVALID_ARG; @@ -595,7 +619,7 @@ esp_err_t IRAM_ATTR esp_flash_write(esp_flash_t *chip, const void *buffer, uint3 //when the cache is disabled, only the DRAM can be read, check whether we need to copy the data first bool direct_write = chip->host->supports_direct_write(chip->host, buffer); - esp_err_t err = ESP_OK; + err = ESP_OK; /* Write output in chunks, either by buffering on stack or by artificially cutting into MAX_WRITE_CHUNK parts (in an OS environment, this prevents writing from causing interrupt or higher priority task @@ -613,7 +637,7 @@ esp_err_t IRAM_ATTR esp_flash_write(esp_flash_t *chip, const void *buffer, uint3 write_buf = buf; } - err = spiflash_start(chip); + err = rom_spiflash_api_funcs->start(chip); if (err != ESP_OK) { return err; } @@ -624,7 +648,7 @@ esp_err_t IRAM_ATTR esp_flash_write(esp_flash_t *chip, const void *buffer, uint3 buffer = (void *)((intptr_t)buffer + write_len); length -= write_len; - err = spiflash_end(chip, err); + err = rom_spiflash_api_funcs->end(chip, err); } while (err == ESP_OK && length > 0); return err; } @@ -639,11 +663,8 @@ esp_err_t IRAM_ATTR esp_flash_write_encrypted(esp_flash_t *chip, uint32_t addres * is no way to support non-standard chips. We use the legacy * implementation and skip the chip and driver layers. */ - if (chip == NULL) { - chip = esp_flash_default_chip; - } else if (chip != esp_flash_default_chip) { - return ESP_ERR_NOT_SUPPORTED; - } + esp_err_t err = rom_spiflash_api_funcs->chip_check(&chip); + if (err != ESP_OK) return err; if (buffer == NULL || address > chip->size || address+length > chip->size) { return ESP_ERR_INVALID_ARG; } @@ -667,26 +688,24 @@ esp_err_t IRAM_ATTR esp_flash_read_encrypted(esp_flash_t *chip, uint32_t address * is no way to support non-standard chips. We use the legacy * implementation and skip the chip and driver layers. */ - if (chip == NULL) { - chip = esp_flash_default_chip; - } else if (chip != esp_flash_default_chip) { - return ESP_ERR_NOT_SUPPORTED; - } + esp_err_t err = rom_spiflash_api_funcs->chip_check(&chip); + if (err != ESP_OK) return err; return spi_flash_read_encrypted(address, out_buffer, length); } // test only, non-public IRAM_ATTR esp_err_t esp_flash_get_io_mode(esp_flash_t* chip, bool* qe) { - VERIFY_OP(get_io_mode); + esp_err_t err = rom_spiflash_api_funcs->chip_check(&chip); + VERIFY_CHIP_OP(get_io_mode); esp_flash_io_mode_t io_mode; - esp_err_t err = spiflash_start(chip); + err = rom_spiflash_api_funcs->start(chip); if (err != ESP_OK) { return err; } err = chip->chip_drv->get_io_mode(chip, &io_mode); - err = spiflash_end(chip, err); + err = rom_spiflash_api_funcs->end(chip, err); if (err == ESP_OK) { *qe = (io_mode == SPI_FLASH_QOUT); } @@ -695,14 +714,16 @@ IRAM_ATTR esp_err_t esp_flash_get_io_mode(esp_flash_t* chip, bool* qe) IRAM_ATTR esp_err_t esp_flash_set_io_mode(esp_flash_t* chip, bool qe) { - VERIFY_OP(set_io_mode); + esp_err_t err = rom_spiflash_api_funcs->chip_check(&chip); + VERIFY_CHIP_OP(set_io_mode); + chip->read_mode = (qe? SPI_FLASH_QOUT: SPI_FLASH_SLOWRD); - esp_err_t err = spiflash_start(chip); + err = rom_spiflash_api_funcs->start(chip); if (err != ESP_OK) { return err; } err = chip->chip_drv->set_io_mode(chip); - return spiflash_end(chip, err); + return rom_spiflash_api_funcs->end(chip, err); } #ifndef CONFIG_SPI_FLASH_USE_LEGACY_IMPL diff --git a/components/spi_flash/include/esp_flash.h b/components/spi_flash/include/esp_flash.h index ccea0d0722..c4951fe91e 100644 --- a/components/spi_flash/include/esp_flash.h +++ b/components/spi_flash/include/esp_flash.h @@ -34,7 +34,15 @@ typedef struct { uint32_t size; ///< Size of the region } esp_flash_region_t; -/** OS-level integration hooks for accessing flash chips inside a running OS */ +/** @brief OS-level integration hooks for accessing flash chips inside a running OS + * + * It's in the public header because some instances should be allocated statically in the startup + * code. May be updated according to hardware version and new flash chip feature requirements, + * shouldn't be treated as public API. + * + * For advanced developers, you may replace some of them with your implementations at your own + * risk. +*/ typedef struct { /** * Called before commencing any flash operation. Does not need to be @@ -51,13 +59,25 @@ typedef struct { /** Delay for at least 'us' microseconds. Called in between 'start' and 'end'. */ esp_err_t (*delay_us)(void *arg, unsigned us); + /** Called for get temp buffer when buffer from application cannot be directly read into/write from. */ + void *(*get_temp_buffer)(void* arg, size_t reqest_size, size_t* out_size); + + /** Called for release temp buffer. */ + void (*release_temp_buffer)(void* arg, void *temp_buf); + /** Yield to other tasks. Called during erase operations. */ esp_err_t (*yield)(void *arg); } esp_flash_os_functions_t; /** @brief Structure to describe a SPI flash chip connected to the system. - Structure must be initialized before use (passed to esp_flash_init()). + Structure must be initialized before use (passed to esp_flash_init()). It's in the public + header because some instances should be allocated statically in the startup code. May be + updated according to hardware version and new flash chip feature requirements, shouldn't be + treated as public API. + + For advanced developers, you may replace some of them with your implementations at your own + risk. */ struct esp_flash_t { spi_flash_host_driver_t *host; ///< Pointer to hardware-specific "host_driver" structure. Must be initialized before used. diff --git a/components/spi_flash/include/memspi_host_driver.h b/components/spi_flash/include/memspi_host_driver.h index 8832adfcc2..8c476ad4c7 100644 --- a/components/spi_flash/include/memspi_host_driver.h +++ b/components/spi_flash/include/memspi_host_driver.h @@ -28,9 +28,9 @@ .supports_direct_write = spi_flash_hal_supports_direct_write, \ .supports_direct_read = spi_flash_hal_supports_direct_read, \ .program_page = spi_flash_hal_program_page, \ - .max_write_bytes = SPI_FLASH_HAL_MAX_WRITE_BYTES, \ + .write_data_slicer = memspi_host_write_data_slicer, \ .read = spi_flash_hal_read, \ - .max_read_bytes = SPI_FLASH_HAL_MAX_READ_BYTES, \ + .read_data_slicer = memspi_host_read_data_slicer, \ .host_idle = spi_flash_hal_host_idle, \ .configure_host_io_mode = spi_flash_hal_configure_host_io_mode, \ .poll_cmd_done = spi_flash_hal_poll_cmd_done, \ @@ -140,3 +140,40 @@ void memspi_host_program_page(spi_flash_host_driver_t *driver, const void *buffe * @param wp Enable or disable write protect (true - enable, false - disable). */ esp_err_t memspi_host_set_write_protect(spi_flash_host_driver_t *driver, bool wp); + +/** + * Read data to buffer. + * + * @param driver The driver context. + * @param buffer Buffer which contains the data to be read. + * @param address Starting address of where to read the data. + * @param length The number of bytes to read. + */ +esp_err_t memspi_host_read(spi_flash_host_driver_t *driver, void *buffer, uint32_t address, uint32_t read_len); + +/** + * @brief Slicer for read data used in non-encrypted regions. This slicer does nothing but + * limit the length to the maximum size the host supports. + * + * @param address Flash address to read + * @param len Length to read + * @param align_address Output of the address to read, should be equal to the input `address` + * @param page_size Physical SPI flash page size + * + * @return Length that can actually be read in one `read` call in `spi_flash_host_driver_t`. + */ +int memspi_host_read_data_slicer(uint32_t address, uint32_t len, uint32_t *align_address, uint32_t page_size); + +/** + * @brief Slicer for write data used in non-encrypted regions. This slicer limit the length to the + * maximum size the host supports, and truncate if the write data lie accross the page boundary + * (256 bytes) + * + * @param address Flash address to write + * @param len Length to write + * @param align_address Output of the address to write, should be equal to the input `address` + * @param page_size Physical SPI flash page size + * + * @return Length that can actually be written in one `program_page` call in `spi_flash_host_driver_t`. + */ +int memspi_host_write_data_slicer(uint32_t address, uint32_t len, uint32_t *align_address, uint32_t page_size); \ No newline at end of file diff --git a/components/spi_flash/include/spi_flash_chip_driver.h b/components/spi_flash/include/spi_flash_chip_driver.h index 46667350de..c0b19badf4 100644 --- a/components/spi_flash/include/spi_flash_chip_driver.h +++ b/components/spi_flash/include/spi_flash_chip_driver.h @@ -19,6 +19,16 @@ struct esp_flash_t; typedef struct esp_flash_t esp_flash_t; typedef struct spi_flash_chip_t spi_flash_chip_t; + +/** Timeout configurations for flash operations, all in us */ +typedef struct { + uint32_t chip_erase_timeout; ///< Timeout for chip erase operation + uint32_t block_erase_timeout; ///< Timeout for block erase operation + uint32_t sector_erase_timeout; ///< Timeout for sector erase operation + uint32_t idle_timeout; ///< Default timeout for other commands to be sent by host and get done by flash + uint32_t page_program_timeout; ///< Timeout for page program operation +} flash_chip_op_timeout_t; + /** @brief SPI flash chip driver definition structure. * * The chip driver structure contains chip-specific pointers to functions to perform SPI flash operations, and some @@ -38,6 +48,7 @@ typedef struct spi_flash_chip_t spi_flash_chip_t; */ struct spi_flash_chip_t { const char *name; ///< Name of the chip driver + const flash_chip_op_timeout_t *timeout; ///< Timeout configuration for this chip /* Probe to detect if a supported SPI flash chip is found. * * Attempts to configure 'chip' with these operations and probes for a matching SPI flash chip. diff --git a/components/spi_flash/include/spi_flash_chip_generic.h b/components/spi_flash/include/spi_flash_chip_generic.h index 15ff8f7b11..814502d26e 100644 --- a/components/spi_flash/include/spi_flash_chip_generic.h +++ b/components/spi_flash/include/spi_flash_chip_generic.h @@ -368,3 +368,6 @@ esp_err_t spi_flash_common_set_io_mode(esp_flash_t *chip, esp_flash_wrsr_func_t * - or other error passed from the ``configure_host_mode`` function of host driver */ esp_err_t spi_flash_chip_generic_config_host_io_mode(esp_flash_t *chip); + +/// Default timeout configuration used by most chips +const flash_chip_op_timeout_t spi_flash_chip_generic_timeout; \ No newline at end of file diff --git a/components/spi_flash/memspi_host_driver.c b/components/spi_flash/memspi_host_driver.c index 3d87f8ae7a..645916bda0 100644 --- a/components/spi_flash/memspi_host_driver.c +++ b/components/spi_flash/memspi_host_driver.c @@ -19,6 +19,9 @@ #include "cache_utils.h" #include "esp_flash_partitions.h" +#define SPI_FLASH_HAL_MAX_WRITE_BYTES 64 +#define SPI_FLASH_HAL_MAX_READ_BYTES 64 + static const char TAG[] = "memspi"; static const spi_flash_host_driver_t esp_flash_default_host = ESP_FLASH_DEFAULT_HOST_DRIVER(); @@ -38,25 +41,25 @@ extern bool spi_flash_hal_gpspi_supports_direct_write(spi_flash_host_driver_t *d extern bool spi_flash_hal_gpspi_supports_direct_read(spi_flash_host_driver_t *driver, const void *p); /** Default configuration for GPSPI */ -static const spi_flash_host_driver_t esp_flash_gpspi_host = { - .dev_config = spi_flash_hal_gpspi_device_config, - .common_command = spi_flash_hal_gpspi_common_command, - .read_id = memspi_host_read_id_hs, - .erase_chip = memspi_host_erase_chip, - .erase_sector = memspi_host_erase_sector, - .erase_block = memspi_host_erase_block, - .read_status = memspi_host_read_status_hs, - .set_write_protect = memspi_host_set_write_protect, - .supports_direct_write = spi_flash_hal_gpspi_supports_direct_write, - .supports_direct_read = spi_flash_hal_gpspi_supports_direct_read, - .program_page = memspi_host_program_page, - .max_write_bytes = SPI_FLASH_HAL_MAX_WRITE_BYTES, - .read = spi_flash_hal_gpspi_read, - .max_read_bytes = SPI_FLASH_HAL_MAX_READ_BYTES, - .host_idle = spi_flash_hal_gpspi_host_idle, - .configure_host_io_mode = spi_flash_hal_gpspi_configure_host_io_mode, - .poll_cmd_done = spi_flash_hal_gpspi_poll_cmd_done, - .flush_cache = NULL, +static const spi_flash_host_driver_t esp_flash_gpspi_host = { + .dev_config = spi_flash_hal_gpspi_device_config, + .common_command = spi_flash_hal_gpspi_common_command, + .read_id = memspi_host_read_id_hs, + .erase_chip = memspi_host_erase_chip, + .erase_sector = memspi_host_erase_sector, + .erase_block = memspi_host_erase_block, + .read_status = memspi_host_read_status_hs, + .set_write_protect = memspi_host_set_write_protect, + .supports_direct_write = spi_flash_hal_gpspi_supports_direct_write, + .supports_direct_read = spi_flash_hal_gpspi_supports_direct_read, + .program_page = memspi_host_program_page, + .write_data_slicer = memspi_host_write_data_slicer, + .read = spi_flash_hal_gpspi_read, + .read_data_slicer = memspi_host_read_data_slicer, + .host_idle = spi_flash_hal_gpspi_host_idle, + .configure_host_io_mode = spi_flash_hal_gpspi_configure_host_io_mode, + .poll_cmd_done = spi_flash_hal_gpspi_poll_cmd_done, + .flush_cache = NULL, }; #endif @@ -143,7 +146,7 @@ void memspi_host_erase_chip(spi_flash_host_driver_t *chip_drv) void memspi_host_erase_sector(spi_flash_host_driver_t *chip_drv, uint32_t start_address) { - spi_flash_trans_t t = { + spi_flash_trans_t t = { .command = CMD_SECTOR_ERASE, .address_bitlen = 24, .address = start_address @@ -153,7 +156,7 @@ void memspi_host_erase_sector(spi_flash_host_driver_t *chip_drv, uint32_t start_ void memspi_host_erase_block(spi_flash_host_driver_t *chip_drv, uint32_t start_address) { - spi_flash_trans_t t = { + spi_flash_trans_t t = { .command = CMD_LARGE_BLOCK_ERASE, .address_bitlen = 24, .address = start_address, @@ -163,7 +166,7 @@ void memspi_host_erase_block(spi_flash_host_driver_t *chip_drv, uint32_t start_a void memspi_host_program_page(spi_flash_host_driver_t *chip_drv, const void *buffer, uint32_t address, uint32_t length) { - spi_flash_trans_t t = { + spi_flash_trans_t t = { .command = CMD_PROGRAM_PAGE, .address_bitlen = 24, .address = address, @@ -176,6 +179,7 @@ void memspi_host_program_page(spi_flash_host_driver_t *chip_drv, const void *buf esp_err_t memspi_host_read(spi_flash_host_driver_t *chip_drv, void *buffer, uint32_t address, uint32_t read_len) { spi_flash_trans_t t = { + .command = CMD_READ, .address_bitlen = 24, .address = address, .miso_len = read_len, @@ -193,3 +197,24 @@ esp_err_t memspi_host_set_write_protect(spi_flash_host_driver_t *chip_drv, bool chip_drv->common_command(chip_drv, &t); return ESP_OK; } + +// When encryption is enabled, etc. the data slicer may be complicated +// This is the simple case where the hardware has no other requirements than the size and page boundary +int memspi_host_write_data_slicer(uint32_t address, uint32_t len, uint32_t *align_address, uint32_t page_size) +{ + uint32_t align_addr = address; + uint32_t end_bound = (align_addr/page_size + 1) * page_size; + // Shouldn't program cross the page, or longer than SPI_FLASH_HAL_MAX_WRITE_BYTES + uint32_t max_len = MIN(end_bound - align_addr, SPI_FLASH_HAL_MAX_WRITE_BYTES); + *align_address = address; + return MIN(max_len, len); +} + +int memspi_host_read_data_slicer(uint32_t address, uint32_t len, uint32_t *align_address, uint32_t page_size) +{ + // Shouldn't read longer than SPI_FLASH_HAL_MAX_READ_BYTES + uint32_t max_len = SPI_FLASH_HAL_MAX_READ_BYTES; + *align_address = address; + return MIN(max_len, len); +} + diff --git a/components/spi_flash/spi_flash_chip_gd.c b/components/spi_flash/spi_flash_chip_gd.c index bc877d2cb1..e6c4539c1b 100644 --- a/components/spi_flash/spi_flash_chip_gd.c +++ b/components/spi_flash/spi_flash_chip_gd.c @@ -78,6 +78,7 @@ static const char chip_name[] = "gd"; // So we only replace these two functions. const spi_flash_chip_t esp_flash_chip_gd = { .name = chip_name, + .timeout = &spi_flash_chip_generic_timeout, .probe = spi_flash_chip_gd_probe, .reset = spi_flash_chip_generic_reset, .detect_size = spi_flash_chip_generic_detect_size, diff --git a/components/spi_flash/spi_flash_chip_generic.c b/components/spi_flash/spi_flash_chip_generic.c index e0c3badd50..cf9a306b64 100644 --- a/components/spi_flash/spi_flash_chip_generic.c +++ b/components/spi_flash/spi_flash_chip_generic.c @@ -13,13 +13,38 @@ // limitations under the License. #include +#include #include // For MIN/MAX #include "spi_flash_chip_generic.h" #include "spi_flash_defs.h" #include "esp_log.h" +#include "esp_attr.h" + static const char TAG[] = "chip_generic"; + +typedef struct flash_chip_dummy { + uint8_t dio_dummy_bitlen; + uint8_t qio_dummy_bitlen; + uint8_t qout_dummy_bitlen; + uint8_t dout_dummy_bitlen; + uint8_t fastrd_dummy_bitlen; + uint8_t slowrd_dummy_bitlen; +} flash_chip_dummy_t; + +// These parameters can be placed in the ROM. For now we use the code in IDF. +DRAM_ATTR const static flash_chip_dummy_t default_flash_chip_dummy = { + .dio_dummy_bitlen = SPI_FLASH_DIO_DUMMY_BITLEN, + .qio_dummy_bitlen = SPI_FLASH_QIO_DUMMY_BITLEN, + .qout_dummy_bitlen = SPI_FLASH_QOUT_DUMMY_BITLEN, + .dout_dummy_bitlen = SPI_FLASH_DOUT_DUMMY_BITLEN, + .fastrd_dummy_bitlen = SPI_FLASH_FASTRD_DUMMY_BITLEN, + .slowrd_dummy_bitlen = SPI_FLASH_SLOWRD_DUMMY_BITLEN, +}; + +DRAM_ATTR flash_chip_dummy_t *rom_flash_chip_dummy = (flash_chip_dummy_t *)&default_flash_chip_dummy; + #define SPI_FLASH_DEFAULT_IDLE_TIMEOUT_MS 200 #define SPI_FLASH_GENERIC_CHIP_ERASE_TIMEOUT_MS 4000 #define SPI_FLASH_GENERIC_SECTOR_ERASE_TIMEOUT_MS 500 //according to GD25Q127 + 100ms @@ -29,6 +54,13 @@ static const char TAG[] = "chip_generic"; #define HOST_DELAY_INTERVAL_US 1 #define CHIP_WAIT_IDLE_INTERVAL_US 20 +const DRAM_ATTR flash_chip_op_timeout_t spi_flash_chip_generic_timeout = { + .chip_erase_timeout = SPI_FLASH_GENERIC_CHIP_ERASE_TIMEOUT_MS * 1000, + .block_erase_timeout = SPI_FLASH_GENERIC_BLOCK_ERASE_TIMEOUT_MS * 1000, + .sector_erase_timeout = SPI_FLASH_GENERIC_SECTOR_ERASE_TIMEOUT_MS * 1000, + .idle_timeout = SPI_FLASH_DEFAULT_IDLE_TIMEOUT_MS * 1000, + .page_program_timeout = SPI_FLASH_GENERIC_PAGE_PROGRAM_TIMEOUT_MS * 1000, +}; esp_err_t spi_flash_chip_generic_probe(esp_flash_t *chip, uint32_t flash_id) { @@ -57,7 +89,7 @@ esp_err_t spi_flash_chip_generic_reset(esp_flash_t *chip) return err; } - err = chip->chip_drv->wait_idle(chip, SPI_FLASH_DEFAULT_IDLE_TIMEOUT_MS * 1000); + err = chip->chip_drv->wait_idle(chip, chip->chip_drv->timeout->idle_timeout); return err; } @@ -68,7 +100,7 @@ esp_err_t spi_flash_chip_generic_detect_size(esp_flash_t *chip, uint32_t *size) /* Can't detect size unless the high byte of the product ID matches the same convention, which is usually 0x40 or * 0xC0 or similar. */ - if ((id & 0x0F00) != 0) { + if (((id & 0xFFFF) == 0x0000) || ((id & 0xFFFF) == 0xFFFF)) { return ESP_ERR_FLASH_UNSUPPORTED_CHIP; } @@ -83,7 +115,7 @@ esp_err_t spi_flash_chip_generic_erase_chip(esp_flash_t *chip) err = chip->chip_drv->set_chip_write_protect(chip, false); if (err == ESP_OK) { - err = chip->chip_drv->wait_idle(chip, SPI_FLASH_DEFAULT_IDLE_TIMEOUT_MS * 1000); + err = chip->chip_drv->wait_idle(chip, chip->chip_drv->timeout->idle_timeout); } if (err == ESP_OK) { chip->host->erase_chip(chip->host); @@ -94,7 +126,7 @@ esp_err_t spi_flash_chip_generic_erase_chip(esp_flash_t *chip) return err; } } - err = chip->chip_drv->wait_idle(chip, SPI_FLASH_GENERIC_CHIP_ERASE_TIMEOUT_MS * 1000); + err = chip->chip_drv->wait_idle(chip, chip->chip_drv->timeout->chip_erase_timeout); } return err; } @@ -103,7 +135,7 @@ esp_err_t spi_flash_chip_generic_erase_sector(esp_flash_t *chip, uint32_t start_ { esp_err_t err = chip->chip_drv->set_chip_write_protect(chip, false); if (err == ESP_OK) { - err = chip->chip_drv->wait_idle(chip, SPI_FLASH_DEFAULT_IDLE_TIMEOUT_MS * 1000); + err = chip->chip_drv->wait_idle(chip, chip->chip_drv->timeout->idle_timeout); } if (err == ESP_OK) { chip->host->erase_sector(chip->host, start_address); @@ -114,7 +146,7 @@ esp_err_t spi_flash_chip_generic_erase_sector(esp_flash_t *chip, uint32_t start_ return err; } } - err = chip->chip_drv->wait_idle(chip, SPI_FLASH_GENERIC_SECTOR_ERASE_TIMEOUT_MS * 1000); + err = chip->chip_drv->wait_idle(chip, chip->chip_drv->timeout->sector_erase_timeout); } return err; } @@ -123,7 +155,7 @@ esp_err_t spi_flash_chip_generic_erase_block(esp_flash_t *chip, uint32_t start_a { esp_err_t err = chip->chip_drv->set_chip_write_protect(chip, false); if (err == ESP_OK) { - err = chip->chip_drv->wait_idle(chip, SPI_FLASH_DEFAULT_IDLE_TIMEOUT_MS * 1000); + err = chip->chip_drv->wait_idle(chip, chip->chip_drv->timeout->idle_timeout); } if (err == ESP_OK) { chip->host->erase_block(chip->host, start_address); @@ -134,7 +166,7 @@ esp_err_t spi_flash_chip_generic_erase_block(esp_flash_t *chip, uint32_t start_a return err; } } - err = chip->chip_drv->wait_idle(chip, SPI_FLASH_GENERIC_BLOCK_ERASE_TIMEOUT_MS * 1000); + err = chip->chip_drv->wait_idle(chip, chip->chip_drv->timeout->block_erase_timeout); } return err; } @@ -142,6 +174,10 @@ esp_err_t spi_flash_chip_generic_erase_block(esp_flash_t *chip, uint32_t start_a esp_err_t spi_flash_chip_generic_read(esp_flash_t *chip, void *buffer, uint32_t address, uint32_t length) { esp_err_t err = ESP_OK; + const uint32_t page_size = chip->chip_drv->page_size; + uint32_t align_address; + uint8_t temp_buffer[64]; //spiflash hal max length of read no longer than 64byte + // Configure the host, and return err = spi_flash_chip_generic_config_host_io_mode(chip); @@ -151,12 +187,17 @@ esp_err_t spi_flash_chip_generic_read(esp_flash_t *chip, void *buffer, uint32_t } while (err == ESP_OK && length > 0) { - uint32_t read_len = MIN(length, chip->host->max_read_bytes); - err = chip->host->read(chip->host, buffer, address, read_len); + memset(temp_buffer, 0xFF, sizeof(temp_buffer)); + uint32_t read_len = chip->host->read_data_slicer(address, length, &align_address, page_size); + uint32_t left_off = address - align_address; + uint32_t data_len = MIN(align_address + read_len, address + length) - address; + err = chip->host->read(chip->host, temp_buffer, align_address, read_len); - buffer += read_len; - length -= read_len; - address += read_len; + memcpy(buffer, temp_buffer + left_off, data_len); + + address += data_len; + buffer = (void *)((intptr_t)buffer + data_len); + length = length - data_len; } return err; @@ -166,13 +207,13 @@ esp_err_t spi_flash_chip_generic_page_program(esp_flash_t *chip, const void *buf { esp_err_t err; - err = chip->chip_drv->wait_idle(chip, SPI_FLASH_DEFAULT_IDLE_TIMEOUT_MS * 1000); + err = chip->chip_drv->wait_idle(chip, chip->chip_drv->timeout->idle_timeout); if (err == ESP_OK) { // Perform the actual Page Program command chip->host->program_page(chip->host, buffer, address, length); - err = chip->chip_drv->wait_idle(chip, SPI_FLASH_GENERIC_PAGE_PROGRAM_TIMEOUT_MS * 1000); + err = chip->chip_drv->wait_idle(chip, chip->chip_drv->timeout->page_program_timeout); } return err; } @@ -181,21 +222,23 @@ esp_err_t spi_flash_chip_generic_write(esp_flash_t *chip, const void *buffer, ui { esp_err_t err = ESP_OK; const uint32_t page_size = chip->chip_drv->page_size; + uint32_t align_address; + uint8_t temp_buffer[64]; //spiflash hal max length of write no longer than 64byte while (err == ESP_OK && length > 0) { - uint32_t page_len = MIN(chip->host->max_write_bytes, MIN(page_size, length)); - if ((address + page_len) / page_size != address / page_size) { - // Most flash chips can't page write across a page boundary - page_len = page_size - (address % page_size); - } + memset(temp_buffer, 0xFF, sizeof(temp_buffer)); + uint32_t page_len = chip->host->write_data_slicer(address, length, &align_address, page_size); + uint32_t left_off = address - align_address; + uint32_t write_len = MIN(align_address + page_len, address + length) - address; + memcpy(temp_buffer + left_off, buffer, write_len); err = chip->chip_drv->set_chip_write_protect(chip, false); + if (err == ESP_OK && length > 0) { + err = chip->chip_drv->program_page(chip, temp_buffer, align_address, page_len); - if (err == ESP_OK) { - err = chip->chip_drv->program_page(chip, buffer, address, page_len); - address += page_len; - buffer = (void *)((intptr_t)buffer + page_len); - length -= page_len; + address += write_len; + buffer = (void *)((intptr_t)buffer + write_len); + length -= write_len; } } if (err == ESP_OK && chip->host->flush_cache) { @@ -213,7 +256,7 @@ esp_err_t spi_flash_chip_generic_set_write_protect(esp_flash_t *chip, bool write { esp_err_t err = ESP_OK; - err = chip->chip_drv->wait_idle(chip, SPI_FLASH_DEFAULT_IDLE_TIMEOUT_MS * 1000); + err = chip->chip_drv->wait_idle(chip, chip->chip_drv->timeout->idle_timeout); if (err == ESP_OK) { chip->host->set_write_protect(chip->host, write_protect); @@ -298,33 +341,33 @@ esp_err_t spi_flash_chip_generic_config_host_io_mode(esp_flash_t *chip) case SPI_FLASH_QIO: //for QIO mode, the 4 bit right after the address are used for continuous mode, should be set to 0 to avoid that. addr_bitlen = SPI_FLASH_QIO_ADDR_BITLEN; - dummy_cyclelen_base = SPI_FLASH_QIO_DUMMY_BITLEN; + dummy_cyclelen_base = rom_flash_chip_dummy->qio_dummy_bitlen; read_command = CMD_FASTRD_QIO; break; case SPI_FLASH_QOUT: addr_bitlen = SPI_FLASH_QOUT_ADDR_BITLEN; - dummy_cyclelen_base = SPI_FLASH_QOUT_DUMMY_BITLEN; + dummy_cyclelen_base = rom_flash_chip_dummy->qout_dummy_bitlen; read_command = CMD_FASTRD_QUAD; break; case SPI_FLASH_DIO: //for DIO mode, the 4 bit right after the address are used for continuous mode, should be set to 0 to avoid that. addr_bitlen = SPI_FLASH_DIO_ADDR_BITLEN; - dummy_cyclelen_base = SPI_FLASH_DIO_DUMMY_BITLEN; + dummy_cyclelen_base = rom_flash_chip_dummy->dio_dummy_bitlen; read_command = CMD_FASTRD_DIO; break; case SPI_FLASH_DOUT: addr_bitlen = SPI_FLASH_DOUT_ADDR_BITLEN; - dummy_cyclelen_base = SPI_FLASH_DOUT_DUMMY_BITLEN; + dummy_cyclelen_base = rom_flash_chip_dummy->dout_dummy_bitlen; read_command = CMD_FASTRD_DUAL; break; case SPI_FLASH_FASTRD: addr_bitlen = SPI_FLASH_FASTRD_ADDR_BITLEN; - dummy_cyclelen_base = SPI_FLASH_FASTRD_DUMMY_BITLEN; + dummy_cyclelen_base = rom_flash_chip_dummy->fastrd_dummy_bitlen; read_command = CMD_FASTRD; break; case SPI_FLASH_SLOWRD: addr_bitlen = SPI_FLASH_SLOWRD_ADDR_BITLEN; - dummy_cyclelen_base = SPI_FLASH_SLOWRD_DUMMY_BITLEN; + dummy_cyclelen_base = rom_flash_chip_dummy->slowrd_dummy_bitlen; read_command = CMD_READ; break; default: @@ -364,6 +407,7 @@ static const char chip_name[] = "generic"; const spi_flash_chip_t esp_flash_chip_generic = { .name = chip_name, + .timeout = &spi_flash_chip_generic_timeout, .probe = spi_flash_chip_generic_probe, .reset = spi_flash_chip_generic_reset, .detect_size = spi_flash_chip_generic_detect_size, @@ -505,7 +549,7 @@ esp_err_t spi_flash_common_set_io_mode(esp_flash_t *chip, esp_flash_wrsr_func_t return ret; } - ret = chip->chip_drv->wait_idle(chip, SPI_FLASH_DEFAULT_IDLE_TIMEOUT_MS * 1000); + ret = chip->chip_drv->wait_idle(chip, chip->chip_drv->timeout->idle_timeout); if (ret != ESP_OK) { return ret; } diff --git a/components/spi_flash/spi_flash_chip_issi.c b/components/spi_flash/spi_flash_chip_issi.c index d5ecd4c040..e57d227686 100644 --- a/components/spi_flash/spi_flash_chip_issi.c +++ b/components/spi_flash/spi_flash_chip_issi.c @@ -64,6 +64,7 @@ static const char chip_name[] = "issi"; // So we only replace these two functions. const spi_flash_chip_t esp_flash_chip_issi = { .name = chip_name, + .timeout = &spi_flash_chip_generic_timeout, .probe = spi_flash_chip_issi_probe, .reset = spi_flash_chip_generic_reset, .detect_size = spi_flash_chip_generic_detect_size, diff --git a/components/spi_flash/spi_flash_chip_mxic.c b/components/spi_flash/spi_flash_chip_mxic.c index 4df6a4f723..36c27b9162 100644 --- a/components/spi_flash/spi_flash_chip_mxic.c +++ b/components/spi_flash/spi_flash_chip_mxic.c @@ -42,6 +42,7 @@ static const char chip_name[] = "mxic"; // So we only replace these two functions. const spi_flash_chip_t esp_flash_chip_mxic = { .name = chip_name, + .timeout = &spi_flash_chip_generic_timeout, .probe = spi_flash_chip_mxic_probe, .reset = spi_flash_chip_generic_reset, .detect_size = spi_flash_chip_generic_detect_size, diff --git a/components/spi_flash/spi_flash_os_func_app.c b/components/spi_flash/spi_flash_os_func_app.c index ceb046ec6d..8fd4d72e25 100644 --- a/components/spi_flash/spi_flash_os_func_app.c +++ b/components/spi_flash/spi_flash_os_func_app.c @@ -13,6 +13,7 @@ // limitations under the License. #include +#include //For max/min #include "esp_attr.h" #include "esp_spi_flash.h" //for ``g_flash_guard_default_ops`` #include "esp_flash.h" @@ -21,6 +22,7 @@ #include "freertos/task.h" #include "hal/spi_types.h" #include "sdkconfig.h" +#include "esp_log.h" #if CONFIG_IDF_TARGET_ESP32 #include "esp32/rom/ets_sys.h" @@ -30,6 +32,7 @@ #include "driver/spi_common_internal.h" +static const char TAG[] = "spi_flash"; /* * OS functions providing delay service and arbitration among chips, and with the cache. @@ -102,7 +105,6 @@ static IRAM_ATTR esp_err_t delay_us(void *arg, unsigned us) ets_delay_us(us); return ESP_OK; } - static IRAM_ATTR esp_err_t spi_flash_os_yield(void *arg) { #ifdef CONFIG_SPI_FLASH_YIELD_DURING_ERASE @@ -111,6 +113,32 @@ static IRAM_ATTR esp_err_t spi_flash_os_yield(void *arg) return ESP_OK; } +static IRAM_ATTR void* get_buffer_malloc(void* arg, size_t reqest_size, size_t* out_size) +{ + /* Allocate temporary internal buffer to use for the actual read. If the preferred size + doesn't fit in free internal memory, allocate the largest available free block. + + (May need to shrink read_chunk_size and retry due to race conditions with other tasks + also allocating from the heap.) + */ + void* ret = NULL; + unsigned retries = 5; + size_t read_chunk_size = reqest_size; + while(ret == NULL && retries--) { + read_chunk_size = MIN(read_chunk_size, heap_caps_get_largest_free_block(MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT)); + read_chunk_size = (read_chunk_size + 3) & ~3; + ret = heap_caps_malloc(read_chunk_size, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); + } + ESP_LOGV(TAG, "allocate temp buffer: %p (%d)", ret, read_chunk_size); + *out_size = (ret != NULL? read_chunk_size: 0); + return ret; +} + +static IRAM_ATTR void release_buffer_malloc(void* arg, void *temp_buf) +{ + free(temp_buf); +} + static IRAM_ATTR esp_err_t main_flash_region_protected(void* arg, size_t start_addr, size_t size) { if (((spi1_app_func_arg_t*)arg)->no_protect || esp_partition_main_flash_region_safe(start_addr, size)) { @@ -129,6 +157,8 @@ static const DRAM_ATTR esp_flash_os_functions_t esp_flash_spi1_default_os_functi .end = spi1_end, .region_protected = main_flash_region_protected, .delay_us = delay_us, + .get_temp_buffer = get_buffer_malloc, + .release_temp_buffer = release_buffer_malloc, .yield = spi_flash_os_yield, }; @@ -136,6 +166,8 @@ static const esp_flash_os_functions_t esp_flash_spi23_default_os_functions = { .start = spi_start, .end = spi_end, .delay_us = delay_us, + .get_temp_buffer = get_buffer_malloc, + .release_temp_buffer = release_buffer_malloc, .yield = spi_flash_os_yield }; diff --git a/components/spi_flash/spi_flash_os_func_noos.c b/components/spi_flash/spi_flash_os_func_noos.c index d565395e0b..27e87f3c42 100644 --- a/components/spi_flash/spi_flash_os_func_noos.c +++ b/components/spi_flash/spi_flash_os_func_noos.c @@ -31,7 +31,7 @@ typedef struct { uint32_t icache_autoload; uint32_t dcache_autoload; -} spi_noos_arg_t; +} spi_noos_arg_t; static DRAM_ATTR spi_noos_arg_t spi_arg = { 0 }; #endif @@ -71,11 +71,19 @@ static IRAM_ATTR esp_err_t delay_us(void *arg, unsigned us) return ESP_OK; } +// Currently when the os is not up yet, the caller is supposed to call esp_flash APIs with proper +// buffers. +IRAM_ATTR void* get_temp_buffer_not_supported(void* arg, size_t reqest_size, size_t* out_size) +{ + return NULL; +} + const DRAM_ATTR esp_flash_os_functions_t esp_flash_noos_functions = { .start = start, .end = end, .delay_us = delay_us, .region_protected = NULL, + .get_temp_buffer = get_temp_buffer_not_supported, .yield = NULL, }; From f99ba3392003d1e350d1a4de5818782de8698d4e Mon Sep 17 00:00:00 2001 From: "Michael (XIAO Xufeng)" Date: Sun, 3 May 2020 23:03:29 +0800 Subject: [PATCH 2/3] esp_flash: improve unit test to detect over boundary issue --- components/spi_flash/test/test_esp_flash.c | 25 ++++++++++++++++------ 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/components/spi_flash/test/test_esp_flash.c b/components/spi_flash/test/test_esp_flash.c index 9fbeee9d86..73ae94554a 100644 --- a/components/spi_flash/test/test_esp_flash.c +++ b/components/spi_flash/test/test_esp_flash.c @@ -382,7 +382,8 @@ void test_simple_read_write(esp_flash_t *chip) srand(test_seed); for (int i = 0; i < sizeof(sector_buf); i++) { - TEST_ASSERT_EQUAL_HEX8(rand() & 0xFF, sector_buf[i]); + uint8_t data = rand(); + TEST_ASSERT_EQUAL_HEX8(data, sector_buf[i]); } } @@ -412,17 +413,22 @@ FLASH_TEST_CASE_3("SPI flash unaligned read/write", test_unaligned_read_write); void test_single_read_write(esp_flash_t* chip) { + const int seed = 699; ESP_LOGI(TAG, "Testing chip %p...", chip); uint32_t offs = erase_test_region(chip, 2); + srand(seed); for (unsigned v = 0; v < 512; v++) { - TEST_ASSERT_EQUAL_HEX(ESP_OK, esp_flash_write(chip, &v, offs + v, 1) ); + uint32_t data = rand(); + TEST_ASSERT_EQUAL_HEX(ESP_OK, esp_flash_write(chip, &data, offs + v, 1) ); } + srand(seed); for (unsigned v = 0; v < 512; v++) { uint8_t readback; + uint32_t data = rand(); TEST_ASSERT_EQUAL_HEX(ESP_OK, esp_flash_read(chip, &readback, offs + v, 1) ); - TEST_ASSERT_EQUAL_HEX8(v, readback); + TEST_ASSERT_EQUAL_HEX8(data, readback); } } @@ -435,18 +441,23 @@ FLASH_TEST_CASE_3("SPI flash single byte reads/writes", test_single_read_write); */ void test_three_byte_read_write(esp_flash_t *chip) { + const int seed = 700; ESP_LOGI(TAG, "Testing chip %p...", chip); uint32_t offs = erase_test_region(chip, 2); ets_printf("offs:%X\n", offs); - for (uint32_t v = 0; v < 2000; v++) { - TEST_ASSERT_EQUAL(ESP_OK, esp_flash_write(chip, &v, offs + 3 * v, 3) ); + srand(seed); + for (uint32_t v = 0; v < 86; v++) { + uint32_t data = rand(); + TEST_ASSERT_EQUAL(ESP_OK, esp_flash_write(chip, &data, offs + 3 * v, 3) ); } - for (uint32_t v = 0; v < 2000; v++) { + srand(seed); + for (uint32_t v = 0; v < 1; v++) { uint32_t readback; + uint32_t data = rand(); TEST_ASSERT_EQUAL(ESP_OK, esp_flash_read(chip, &readback, offs + 3 * v, 3) ); - TEST_ASSERT_EQUAL_HEX32(v & 0xFFFFFF, readback & 0xFFFFFF); + TEST_ASSERT_EQUAL_HEX32(data & 0xFFFFFF, readback & 0xFFFFFF); } } From c796bd5e6370662436a06645ce2b38f048087255 Mon Sep 17 00:00:00 2001 From: "Michael (XIAO Xufeng)" Date: Thu, 7 May 2020 14:46:41 +0800 Subject: [PATCH 3/3] esp_flash: refactor to make host driver function a const table This is also part of ESP32-S3 ROM changes --- components/soc/include/hal/spi_flash_hal.h | 62 ++++++++------- components/soc/include/hal/spi_flash_types.h | 55 +++++++------ components/soc/src/hal/spi_flash_hal.c | 13 +-- .../soc/src/hal/spi_flash_hal_common.inc | 27 +++---- components/soc/src/hal/spi_flash_hal_gpspi.c | 8 +- components/soc/src/hal/spi_flash_hal_iram.c | 24 +++--- components/spi_flash/esp_flash_api.c | 16 ++-- components/spi_flash/esp_flash_spi_init.c | 35 +++----- components/spi_flash/include/esp_flash.h | 2 +- .../spi_flash/include/memspi_host_driver.h | 47 ++++++----- components/spi_flash/memspi_host_driver.c | 79 ++++++++----------- components/spi_flash/spi_flash_chip_generic.c | 48 +++++------ components/spi_flash/test/test_esp_flash.c | 8 +- 13 files changed, 204 insertions(+), 220 deletions(-) diff --git a/components/soc/include/hal/spi_flash_hal.h b/components/soc/include/hal/spi_flash_hal.h index 6992daf6e1..8ea7a454da 100644 --- a/components/soc/include/hal/spi_flash_hal.h +++ b/components/soc/include/hal/spi_flash_hal.h @@ -37,11 +37,13 @@ * implementations that also use the SPI peripheral. */ typedef struct { + spi_flash_host_inst_t inst; ///< Host instance, containing host data and function pointer table. May update with the host (hardware version). spi_dev_t *spi; ///< Pointer to SPI peripheral registers (SP1, SPI2 or SPI3). Set before initialisation. int cs_num; ///< Which cs pin is used, 0-2. - int extra_dummy; - spi_flash_ll_clock_reg_t clock_conf; -} spi_flash_memspi_data_t; + int extra_dummy; ///< Pre-calculated extra dummy used for compensation + spi_flash_ll_clock_reg_t clock_conf; ///< Pre-calculated clock configuration value + uint32_t reserved_config[2]; ///< The ROM has reserved some memory for configurations with one set of driver code. (e.g. QPI mode, 64-bit address mode, etc.) +} spi_flash_hal_context_t; /// Configuration structure for the SPI driver. typedef struct { @@ -50,7 +52,7 @@ typedef struct { bool iomux; ///< Whether the IOMUX is used, used for timing compensation. int input_delay_ns; ///< Input delay on the MISO pin after the launch clock, used for timing compensation. esp_flash_speed_t speed;///< SPI flash clock speed to work at. -} spi_flash_memspi_config_t; +} spi_flash_hal_config_t; /** * Configure SPI flash hal settings. @@ -62,16 +64,16 @@ typedef struct { * - ESP_OK: success * - ESP_ERR_INVALID_ARG: the data buffer is not in the DRAM. */ -esp_err_t spi_flash_hal_init(spi_flash_memspi_data_t *data_out, const spi_flash_memspi_config_t *cfg); +esp_err_t spi_flash_hal_init(spi_flash_hal_context_t *data_out, const spi_flash_hal_config_t *cfg); /** * Configure the device-related register before transactions. * - * @param driver The driver context. + * @param host The driver context. * * @return always return ESP_OK. */ -esp_err_t spi_flash_hal_device_config(spi_flash_host_driver_t *driver); +esp_err_t spi_flash_hal_device_config(spi_flash_host_inst_t *host); /** * Send an user-defined spi transaction to the device. @@ -80,60 +82,60 @@ esp_err_t spi_flash_hal_device_config(spi_flash_host_driver_t *driver); * particular commands. Since this function supports timing compensation, it is * also used to receive some data when the frequency is high. * - * @param driver The driver context. + * @param host The driver context. * @param trans The transaction to send, also holds the received data. * * @return always return ESP_OK. */ -esp_err_t spi_flash_hal_common_command(spi_flash_host_driver_t *driver, spi_flash_trans_t *trans); +esp_err_t spi_flash_hal_common_command(spi_flash_host_inst_t *host, spi_flash_trans_t *trans); /** * Erase whole flash chip by using the erase chip (C7h) command. * - * @param driver The driver context. + * @param host The driver context. */ -void spi_flash_hal_erase_chip(spi_flash_host_driver_t *driver); +void spi_flash_hal_erase_chip(spi_flash_host_inst_t *host); /** * Erase a specific sector by its start address through the sector erase (20h) * command. * - * @param driver The driver context. + * @param host The driver context. * @param start_address Start address of the sector to erase. */ -void spi_flash_hal_erase_sector(spi_flash_host_driver_t *driver, uint32_t start_address); +void spi_flash_hal_erase_sector(spi_flash_host_inst_t *host, uint32_t start_address); /** * Erase a specific 64KB block by its start address through the 64KB block * erase (D8h) command. * - * @param driver The driver context. + * @param host The driver context. * @param start_address Start address of the block to erase. */ -void spi_flash_hal_erase_block(spi_flash_host_driver_t *driver, uint32_t start_address); +void spi_flash_hal_erase_block(spi_flash_host_inst_t *host, uint32_t start_address); /** * Program a page of the flash using the page program (02h) command. * - * @param driver The driver context. + * @param host The driver context. * @param address Address of the page to program * @param buffer Data to program * @param length Size of the buffer in bytes, no larger than ``SPI_FLASH_HAL_MAX_WRITE_BYTES`` (64) bytes. */ -void spi_flash_hal_program_page(spi_flash_host_driver_t *driver, const void *buffer, uint32_t address, uint32_t length); +void spi_flash_hal_program_page(spi_flash_host_inst_t *host, const void *buffer, uint32_t address, uint32_t length); /** * Read from the flash. Call ``spi_flash_hal_configure_host_read_mode`` to * configure the read command before calling this function. * - * @param driver The driver context. + * @param host The driver context. * @param buffer Buffer to store the read data * @param address Address to read * @param length Length to read, no larger than ``SPI_FLASH_HAL_MAX_READ_BYTES`` (64) bytes. * * @return always return ESP_OK. */ -esp_err_t spi_flash_hal_read(spi_flash_host_driver_t *driver, void *buffer, uint32_t address, uint32_t read_len); +esp_err_t spi_flash_hal_read(spi_flash_host_inst_t *host, void *buffer, uint32_t address, uint32_t read_len); /** * @brief Send the write enable (06h) or write disable (04h) command to the flash chip. @@ -143,16 +145,16 @@ esp_err_t spi_flash_hal_read(spi_flash_host_driver_t *driver, void *buffer, uint * * @return always return ESP_OK. */ -esp_err_t spi_flash_hal_set_write_protect(spi_flash_host_driver_t *chip_drv, bool wp); +esp_err_t spi_flash_hal_set_write_protect(spi_flash_host_inst_t *host, bool wp); /** * Check whether the SPI host is idle and can perform other operations. * - * @param driver The driver context. + * @param host The driver context. * * @return ture if idle, otherwise false. */ -bool spi_flash_hal_host_idle(spi_flash_host_driver_t *driver); +bool spi_flash_hal_host_idle(spi_flash_host_inst_t *host); /** * @brief Configure the SPI host hardware registers for the specified io mode. @@ -177,7 +179,7 @@ bool spi_flash_hal_host_idle(spi_flash_host_driver_t *driver); * - Common write: set command value, address value (or length to 0 if not * used), disable dummy phase, and set output data. * - * @param driver The driver context + * @param host The driver context * @param io_mode The HW read mode to use * @param addr_bitlen Length of the address phase, in bits * @param dummy_cyclelen_base Base cycles of the dummy phase, some extra dummy cycles may be appended to compensate the timing. @@ -185,34 +187,34 @@ bool spi_flash_hal_host_idle(spi_flash_host_driver_t *driver); * * @return always return ESP_OK. */ -esp_err_t spi_flash_hal_configure_host_io_mode(spi_flash_host_driver_t *driver, uint32_t command, uint32_t addr_bitlen, +esp_err_t spi_flash_hal_configure_host_io_mode(spi_flash_host_inst_t *host, uint32_t command, uint32_t addr_bitlen, int dummy_cyclelen_base, esp_flash_io_mode_t io_mode); /** * Poll until the last operation is done. * - * @param driver The driver context. + * @param host The driver context. */ -void spi_flash_hal_poll_cmd_done(spi_flash_host_driver_t *driver); +void spi_flash_hal_poll_cmd_done(spi_flash_host_inst_t *host); /** * Check whether the given buffer can be used as the write buffer directly. If 'chip' is connected to the main SPI bus, we can only write directly from * regions that are accessible ith cache disabled. * * - * @param driver The driver context + * @param host The driver context * @param p The buffer holding data to send. * * @return True if the buffer can be used to send data, otherwise false. */ -bool spi_flash_hal_supports_direct_write(spi_flash_host_driver_t *driver, const void *p); +bool spi_flash_hal_supports_direct_write(spi_flash_host_inst_t *host, const void *p); /** * Check whether the given buffer can be used as the read buffer directly. If 'chip' is connected to the main SPI bus, we can only read directly from * regions that are accessible ith cache disabled. * * - * @param driver The driver context + * @param host The driver context * @param p The buffer to hold the received data. * * @return True if the buffer can be used to receive data, otherwise false. */ -bool spi_flash_hal_supports_direct_read(spi_flash_host_driver_t *driver, const void *p); +bool spi_flash_hal_supports_direct_read(spi_flash_host_inst_t *host, const void *p); diff --git a/components/soc/include/hal/spi_flash_types.h b/components/soc/include/hal/spi_flash_types.h index 586dd6ee89..d2efe3e8bb 100644 --- a/components/soc/include/hal/spi_flash_types.h +++ b/components/soc/include/hal/spi_flash_types.h @@ -68,55 +68,57 @@ typedef enum { ///Slowest io mode supported by ESP32, currently SlowRd #define SPI_FLASH_READ_MODE_MIN SPI_FLASH_SLOWRD -struct spi_flash_host_driver_t; -typedef struct spi_flash_host_driver_t spi_flash_host_driver_t; +struct spi_flash_host_driver_s; +typedef struct spi_flash_host_driver_s spi_flash_host_driver_t; + +/** SPI Flash Host driver instance */ +typedef struct { + const struct spi_flash_host_driver_s* driver; ///< Pointer to the implementation function table + // Implementations can wrap this structure into their own ones, and append other data here +} spi_flash_host_inst_t ; + /** Host driver configuration and context structure. */ -struct spi_flash_host_driver_t { - /** - * Configuration and static data used by the specific host driver. The type - * is determined by the host driver. - */ - void *driver_data; +struct spi_flash_host_driver_s { /** * Configure the device-related register before transactions. This saves * some time to re-configure those registers when we send continuously */ - esp_err_t (*dev_config)(spi_flash_host_driver_t *driver); + esp_err_t (*dev_config)(spi_flash_host_inst_t *host); /** * Send an user-defined spi transaction to the device. */ - esp_err_t (*common_command)(spi_flash_host_driver_t *driver, spi_flash_trans_t *t); + esp_err_t (*common_command)(spi_flash_host_inst_t *host, spi_flash_trans_t *t); /** * Read flash ID. */ - esp_err_t (*read_id)(spi_flash_host_driver_t *driver, uint32_t *id); + esp_err_t (*read_id)(spi_flash_host_inst_t *host, uint32_t *id); /** * Erase whole flash chip. */ - void (*erase_chip)(spi_flash_host_driver_t *driver); + void (*erase_chip)(spi_flash_host_inst_t *host); /** * Erase a specific sector by its start address. */ - void (*erase_sector)(spi_flash_host_driver_t *driver, uint32_t start_address); + void (*erase_sector)(spi_flash_host_inst_t *host, uint32_t start_address); /** * Erase a specific block by its start address. */ - void (*erase_block)(spi_flash_host_driver_t *driver, uint32_t start_address); + void (*erase_block)(spi_flash_host_inst_t *host, uint32_t start_address); /** * Read the status of the flash chip. */ - esp_err_t (*read_status)(spi_flash_host_driver_t *driver, uint8_t *out_sr); + esp_err_t (*read_status)(spi_flash_host_inst_t *host, uint8_t *out_sr); /** * Disable write protection. */ - esp_err_t (*set_write_protect)(spi_flash_host_driver_t *driver, bool wp); + esp_err_t (*set_write_protect)(spi_flash_host_inst_t *host, bool wp); /** * Program a page of the flash. Check ``max_write_bytes`` for the maximum allowed writing length. */ - void (*program_page)(spi_flash_host_driver_t *driver, const void *buffer, uint32_t address, uint32_t length); + void (*program_page)(spi_flash_host_inst_t *host, const void *buffer, uint32_t address, uint32_t length); /** Check whether given buffer can be directly used to write */ - bool (*supports_direct_write)(spi_flash_host_driver_t *driver, const void *p); + bool (*supports_direct_write)(spi_flash_host_inst_t *host, const void *p); /** * Slicer for write data. The `program_page` should be called iteratively with the return value * of this function. @@ -127,13 +129,14 @@ struct spi_flash_host_driver_t { * @param page_size Physical page size of the flash chip * @return Length that can be actually written in one `program_page` call */ - int (*write_data_slicer)(uint32_t address, uint32_t len, uint32_t *align_addr, uint32_t page_size); + int (*write_data_slicer)(spi_flash_host_inst_t *host, uint32_t address, uint32_t len, uint32_t *align_addr, + uint32_t page_size); /** * Read data from the flash. Check ``max_read_bytes`` for the maximum allowed reading length. */ - esp_err_t (*read)(spi_flash_host_driver_t *driver, void *buffer, uint32_t address, uint32_t read_len); + esp_err_t (*read)(spi_flash_host_inst_t *host, void *buffer, uint32_t address, uint32_t read_len); /** Check whether given buffer can be directly used to read */ - bool (*supports_direct_read)(spi_flash_host_driver_t *driver, const void *p); + bool (*supports_direct_read)(spi_flash_host_inst_t *host, const void *p); /** * Slicer for read data. The `read` should be called iteratively with the return value * of this function. @@ -144,26 +147,26 @@ struct spi_flash_host_driver_t { * @param page_size Physical page size of the flash chip * @return Length that can be actually read in one `read` call */ - int (*read_data_slicer)(uint32_t address, uint32_t len, uint32_t *align_addr, uint32_t page_size); + int (*read_data_slicer)(spi_flash_host_inst_t *host, uint32_t address, uint32_t len, uint32_t *align_addr, uint32_t page_size); /** * Check whether the host is idle to perform new operations. */ - bool (*host_idle)(spi_flash_host_driver_t *driver); + bool (*host_idle)(spi_flash_host_inst_t *host); /** * Configure the host to work at different read mode. Responsible to compensate the timing and set IO mode. */ - esp_err_t (*configure_host_io_mode)(spi_flash_host_driver_t *driver, uint32_t command, + esp_err_t (*configure_host_io_mode)(spi_flash_host_inst_t *host, uint32_t command, uint32_t addr_bitlen, int dummy_bitlen_base, esp_flash_io_mode_t io_mode); /** * Internal use, poll the HW until the last operation is done. */ - void (*poll_cmd_done)(spi_flash_host_driver_t *driver); + void (*poll_cmd_done)(spi_flash_host_inst_t *host); /** * For some host (SPI1), they are shared with a cache. When the data is * modified, the cache needs to be flushed. Left NULL if not supported. */ - esp_err_t (*flush_cache)(spi_flash_host_driver_t* driver, uint32_t addr, uint32_t size); + esp_err_t (*flush_cache)(spi_flash_host_inst_t* host, uint32_t addr, uint32_t size); }; #ifdef __cplusplus diff --git a/components/soc/src/hal/spi_flash_hal.c b/components/soc/src/hal/spi_flash_hal.c index e3954c720d..f8c2f3c611 100644 --- a/components/soc/src/hal/spi_flash_hal.c +++ b/components/soc/src/hal/spi_flash_hal.c @@ -63,7 +63,7 @@ static inline int get_dummy_n(bool gpio_is_used, int input_delay_ns, int eff_clk return apb_period_n / apbclk_n; } -esp_err_t spi_flash_hal_init(spi_flash_memspi_data_t *data_out, const spi_flash_memspi_config_t *cfg) +esp_err_t spi_flash_hal_init(spi_flash_hal_context_t *data_out, const spi_flash_hal_config_t *cfg) { if (!esp_ptr_internal(data_out)) { return ESP_ERR_INVALID_ARG; @@ -77,7 +77,8 @@ esp_err_t spi_flash_hal_init(spi_flash_memspi_data_t *data_out, const spi_flash_ } #endif - *data_out = (spi_flash_memspi_data_t) { + *data_out = (spi_flash_hal_context_t) { + .inst = data_out->inst, // Keeps the function pointer table .spi = spi_flash_ll_get_hw(cfg->host_id), .cs_num = cfg->cs_num, .extra_dummy = get_dummy_n(!cfg->iomux, cfg->input_delay_ns, clock_cfg.freq), @@ -88,18 +89,18 @@ esp_err_t spi_flash_hal_init(spi_flash_memspi_data_t *data_out, const spi_flash_ return ESP_OK; } -bool spi_flash_hal_supports_direct_write(spi_flash_host_driver_t *host, const void *p) +bool spi_flash_hal_supports_direct_write(spi_flash_host_inst_t *host, const void *p) { - bool direct_write = ( ((spi_flash_memspi_data_t *)host->driver_data)->spi != spi_flash_ll_get_hw(SPI_HOST) + bool direct_write = ( ((spi_flash_hal_context_t *)host)->spi != spi_flash_ll_get_hw(SPI_HOST) || esp_ptr_in_dram(p) ); return direct_write; } -bool spi_flash_hal_supports_direct_read(spi_flash_host_driver_t *host, const void *p) +bool spi_flash_hal_supports_direct_read(spi_flash_host_inst_t *host, const void *p) { //currently the host doesn't support to read through dma, no word-aligned requirements - bool direct_read = ( ((spi_flash_memspi_data_t *)host->driver_data)->spi != spi_flash_ll_get_hw(SPI_HOST) + bool direct_read = ( ((spi_flash_hal_context_t *)host)->spi != spi_flash_ll_get_hw(SPI_HOST) || esp_ptr_in_dram(p) ); return direct_read; } diff --git a/components/soc/src/hal/spi_flash_hal_common.inc b/components/soc/src/hal/spi_flash_hal_common.inc index b84c6181d7..83fe798de2 100644 --- a/components/soc/src/hal/spi_flash_hal_common.inc +++ b/components/soc/src/hal/spi_flash_hal_common.inc @@ -19,32 +19,31 @@ #include "sdkconfig.h" #define ADDRESS_MASK_24BIT 0xFFFFFF -#define COMPUTE_DUMMY_CYCLELEN(host, base) ((base) + ((spi_flash_memspi_data_t *)(host)->driver_data)->extra_dummy) +#define COMPUTE_DUMMY_CYCLELEN(host, base) ((base) + ((spi_flash_hal_context_t*)host)->extra_dummy) -static inline spi_dev_t *get_spi_dev(spi_flash_host_driver_t *host) +static inline spi_dev_t *get_spi_dev(spi_flash_host_inst_t *host) { - return ((spi_flash_memspi_data_t *)host->driver_data)->spi; + return ((spi_flash_hal_context_t*)host)->spi; } -void spi_flash_hal_poll_cmd_done(spi_flash_host_driver_t *host) +void spi_flash_hal_poll_cmd_done(spi_flash_host_inst_t *host) { while (!spi_flash_ll_cmd_is_done(get_spi_dev(host))) { //nop } } -esp_err_t spi_flash_hal_device_config(spi_flash_host_driver_t *host) +esp_err_t spi_flash_hal_device_config(spi_flash_host_inst_t *host) { - spi_flash_memspi_data_t *drv_data = (spi_flash_memspi_data_t *)host->driver_data; spi_dev_t *dev = get_spi_dev(host); spi_flash_ll_reset(dev); - spi_flash_ll_set_cs_pin(dev, drv_data->cs_num); - spi_flash_ll_set_clock(dev, &drv_data->clock_conf); + spi_flash_ll_set_cs_pin(dev, ((spi_flash_hal_context_t*)host)->cs_num); + spi_flash_ll_set_clock(dev, &((spi_flash_hal_context_t*)host)->clock_conf); return ESP_OK; } esp_err_t spi_flash_hal_configure_host_io_mode( - spi_flash_host_driver_t *host, + spi_flash_host_inst_t *host, uint32_t command, uint32_t addr_bitlen, int dummy_cyclelen_base, @@ -89,9 +88,9 @@ esp_err_t spi_flash_hal_configure_host_io_mode( return ESP_OK; } -esp_err_t spi_flash_hal_common_command(spi_flash_host_driver_t *host, spi_flash_trans_t *trans) +esp_err_t spi_flash_hal_common_command(spi_flash_host_inst_t *host, spi_flash_trans_t *trans) { - host->configure_host_io_mode(host, trans->command, trans->address_bitlen, 0, SPI_FLASH_FASTRD); + host->driver->configure_host_io_mode(host, trans->command, trans->address_bitlen, 0, SPI_FLASH_FASTRD); spi_dev_t *dev = get_spi_dev(host); @@ -106,19 +105,19 @@ esp_err_t spi_flash_hal_common_command(spi_flash_host_driver_t *host, spi_flash_ spi_flash_ll_set_miso_bitlen(dev, trans->miso_len * 8); spi_flash_ll_user_start(dev); - host->poll_cmd_done(host); + host->driver->poll_cmd_done(host); spi_flash_ll_get_buffer_data(dev, trans->miso_data, trans->miso_len); return ESP_OK; } -esp_err_t spi_flash_hal_read(spi_flash_host_driver_t *host, void *buffer, uint32_t address, uint32_t read_len) +esp_err_t spi_flash_hal_read(spi_flash_host_inst_t *host, void *buffer, uint32_t address, uint32_t read_len) { spi_dev_t *dev = get_spi_dev(host); int bitlen = spi_flash_ll_get_addr_bitlen(dev); spi_flash_ll_set_usr_address(dev, address << (bitlen - 24), bitlen); spi_flash_ll_set_miso_bitlen(dev, read_len * 8); spi_flash_ll_user_start(dev); - host->poll_cmd_done(host); + host->driver->poll_cmd_done(host); spi_flash_ll_get_buffer_data(dev, buffer, read_len); return ESP_OK; } diff --git a/components/soc/src/hal/spi_flash_hal_gpspi.c b/components/soc/src/hal/spi_flash_hal_gpspi.c index 9ec34120cd..c26321b437 100644 --- a/components/soc/src/hal/spi_flash_hal_gpspi.c +++ b/components/soc/src/hal/spi_flash_hal_gpspi.c @@ -22,18 +22,18 @@ #include "spi_flash_hal_common.inc" -bool spi_flash_hal_gpspi_supports_direct_write(spi_flash_host_driver_t *host, const void *p) +bool spi_flash_hal_gpspi_supports_direct_write(spi_flash_host_inst_t *host, const void *p) { return true; } -bool spi_flash_hal_gpspi_supports_direct_read(spi_flash_host_driver_t *host, const void *p) +bool spi_flash_hal_gpspi_supports_direct_read(spi_flash_host_inst_t *host, const void *p) { return true; } -bool spi_flash_hal_gpspi_host_idle(spi_flash_host_driver_t *chip_drv) +bool spi_flash_hal_gpspi_host_idle(spi_flash_host_inst_t *host) { - spi_dev_t *dev = get_spi_dev(chip_drv); + spi_dev_t *dev = get_spi_dev(host); return spi_flash_ll_host_idle(dev); } \ No newline at end of file diff --git a/components/soc/src/hal/spi_flash_hal_iram.c b/components/soc/src/hal/spi_flash_hal_iram.c index e88e1f4848..cf074ca006 100644 --- a/components/soc/src/hal/spi_flash_hal_iram.c +++ b/components/soc/src/hal/spi_flash_hal_iram.c @@ -14,51 +14,51 @@ #include "spi_flash_hal_common.inc" -void spi_flash_hal_erase_chip(spi_flash_host_driver_t *host) +void spi_flash_hal_erase_chip(spi_flash_host_inst_t *host) { spi_dev_t *dev = get_spi_dev(host); spi_flash_ll_erase_chip(dev); - host->poll_cmd_done(host); + host->driver->poll_cmd_done(host); } -void spi_flash_hal_erase_sector(spi_flash_host_driver_t *host, uint32_t start_address) +void spi_flash_hal_erase_sector(spi_flash_host_inst_t *host, uint32_t start_address) { spi_dev_t *dev = get_spi_dev(host); spi_flash_ll_set_addr_bitlen(dev, 24); spi_flash_ll_set_address(dev, start_address & ADDRESS_MASK_24BIT); spi_flash_ll_erase_sector(dev); - host->poll_cmd_done(host); + host->driver->poll_cmd_done(host); } -void spi_flash_hal_erase_block(spi_flash_host_driver_t *host, uint32_t start_address) +void spi_flash_hal_erase_block(spi_flash_host_inst_t *host, uint32_t start_address) { spi_dev_t *dev = get_spi_dev(host); spi_flash_ll_set_addr_bitlen(dev, 24); spi_flash_ll_set_address(dev, start_address & ADDRESS_MASK_24BIT); spi_flash_ll_erase_block(dev); - host->poll_cmd_done(host); + host->driver->poll_cmd_done(host); } -void spi_flash_hal_program_page(spi_flash_host_driver_t *host, const void *buffer, uint32_t address, uint32_t length) +void spi_flash_hal_program_page(spi_flash_host_inst_t *host, const void *buffer, uint32_t address, uint32_t length) { spi_dev_t *dev = get_spi_dev(host); spi_flash_ll_set_addr_bitlen(dev, 24); spi_flash_ll_set_address(dev, (address & ADDRESS_MASK_24BIT) | (length << 24)); spi_flash_ll_program_page(dev, buffer, length); - host->poll_cmd_done(host); + host->driver->poll_cmd_done(host); } -esp_err_t spi_flash_hal_set_write_protect(spi_flash_host_driver_t *host, bool wp) +esp_err_t spi_flash_hal_set_write_protect(spi_flash_host_inst_t *host, bool wp) { spi_dev_t *dev = get_spi_dev(host); spi_flash_ll_set_write_protect(dev, wp); - host->poll_cmd_done(host); + host->driver->poll_cmd_done(host); return ESP_OK; } -bool spi_flash_hal_host_idle(spi_flash_host_driver_t *chip_drv) +bool spi_flash_hal_host_idle(spi_flash_host_inst_t *host) { - spi_dev_t *dev = get_spi_dev(chip_drv); + spi_dev_t *dev = get_spi_dev(host); bool idle = spi_flash_ll_host_idle(dev); // Not clear if this is necessary, or only necessary if diff --git a/components/spi_flash/esp_flash_api.c b/components/spi_flash/esp_flash_api.c index 802d69684a..872a89fdde 100644 --- a/components/spi_flash/esp_flash_api.c +++ b/components/spi_flash/esp_flash_api.c @@ -103,7 +103,7 @@ static esp_err_t IRAM_ATTR spiflash_start_default(esp_flash_t *chip) return err; } } - chip->host->dev_config(chip->host); + chip->host->driver->dev_config(chip->host); return ESP_OK; } @@ -151,8 +151,8 @@ bool esp_flash_chip_driver_initialized(const esp_flash_t *chip) esp_err_t IRAM_ATTR esp_flash_init(esp_flash_t *chip) { esp_err_t err = ESP_OK; - if (chip == NULL || chip->host == NULL || chip->host->driver_data == NULL || - ((memspi_host_data_t*)chip->host->driver_data)->spi == NULL) { + if (chip == NULL || chip->host == NULL || chip->host->driver == NULL || + ((memspi_host_inst_t*)chip->host)->spi == NULL) { return ESP_ERR_INVALID_ARG; } @@ -212,11 +212,11 @@ esp_err_t IRAM_ATTR esp_flash_read_chip_id(esp_flash_t* chip, uint32_t* flash_id // Send generic RDID command twice, check for a matching result and retry in case we just powered on (inner // function fails if it sees all-ones or all-zeroes.) - err = chip->host->read_id(chip->host, flash_id); + err = chip->host->driver->read_id(chip->host, flash_id); if (err == ESP_OK) { // check we see the same ID twice, in case of transient power-on errors uint32_t new_id; - err = chip->host->read_id(chip->host, &new_id); + err = chip->host->driver->read_id(chip->host, &new_id); if (err == ESP_OK && (new_id != *flash_id)) { err = ESP_ERR_FLASH_NOT_INITIALISED; } @@ -284,7 +284,7 @@ esp_err_t IRAM_ATTR esp_flash_read_id(esp_flash_t *chip, uint32_t *out_id) return err; } - err = chip->host->read_id(chip->host, out_id); + err = chip->host->driver->read_id(chip->host, out_id); return rom_spiflash_api_funcs->end(chip, err); } @@ -553,7 +553,7 @@ esp_err_t IRAM_ATTR esp_flash_read(esp_flash_t *chip, void *buffer, uint32_t add } //when the cache is disabled, only the DRAM can be read, check whether we need to receive in another buffer in DRAM. - bool direct_read = chip->host->supports_direct_read(chip->host, buffer); + bool direct_read = chip->host->driver->supports_direct_read(chip->host, buffer); uint8_t* temp_buffer = NULL; //each time, we at most read this length @@ -617,7 +617,7 @@ esp_err_t IRAM_ATTR esp_flash_write(esp_flash_t *chip, const void *buffer, uint3 } //when the cache is disabled, only the DRAM can be read, check whether we need to copy the data first - bool direct_write = chip->host->supports_direct_write(chip->host, buffer); + bool direct_write = chip->host->driver->supports_direct_write(chip->host, buffer); err = ESP_OK; /* Write output in chunks, either by buffering on stack or diff --git a/components/spi_flash/esp_flash_spi_init.c b/components/spi_flash/esp_flash_spi_init.c index 261331723c..803fcd7f1c 100644 --- a/components/spi_flash/esp_flash_spi_init.c +++ b/components/spi_flash/esp_flash_spi_init.c @@ -116,8 +116,7 @@ esp_err_t spi_bus_add_flash_device(esp_flash_t **out_chip, const esp_flash_spi_d return ESP_ERR_INVALID_ARG; } esp_flash_t *chip = NULL; - spi_flash_host_driver_t *host = NULL; - memspi_host_data_t *host_data = NULL; + memspi_host_inst_t *host = NULL; esp_err_t ret = ESP_OK; uint32_t caps = MALLOC_CAP_DEFAULT; @@ -129,23 +128,16 @@ esp_err_t spi_bus_add_flash_device(esp_flash_t **out_chip, const esp_flash_spi_d goto fail; } - host = (spi_flash_host_driver_t*)heap_caps_malloc(sizeof(spi_flash_host_driver_t), caps); + host = (memspi_host_inst_t*)heap_caps_malloc(sizeof(memspi_host_inst_t), caps); *chip = (esp_flash_t) { .read_mode = config->io_mode, - .host = host, + .host = (spi_flash_host_inst_t*)host, }; if (!host) { ret = ESP_ERR_NO_MEM; goto fail; } - host_data = (memspi_host_data_t*)heap_caps_malloc(sizeof(memspi_host_data_t), caps); - host->driver_data = host_data; - if (!host_data) { - ret = ESP_ERR_NO_MEM; - goto fail; - } - int dev_id = -1; esp_err_t err = esp_flash_init_os_functions(chip, config->host_id, &dev_id); if (err == ESP_ERR_NOT_SUPPORTED) { @@ -173,7 +165,7 @@ esp_err_t spi_bus_add_flash_device(esp_flash_t **out_chip, const esp_flash_spi_d .input_delay_ns = config->input_delay_ns, .speed = config->speed, }; - err = memspi_host_init_pointers(host, host_data, &host_cfg); + err = memspi_host_init_pointers(host, &host_cfg); if (err != ESP_OK) { ret = err; goto fail; @@ -195,10 +187,7 @@ esp_err_t spi_bus_remove_flash_device(esp_flash_t *chip) return ESP_ERR_INVALID_ARG; } esp_flash_deinit_os_functions(chip); - if (chip->host) { - free(chip->host->driver_data); - free(chip->host); - } + free(chip->host); free(chip); return ESP_OK; } @@ -209,13 +198,11 @@ extern const esp_flash_os_functions_t esp_flash_noos_functions; #ifndef CONFIG_SPI_FLASH_USE_LEGACY_IMPL -static DRAM_ATTR memspi_host_data_t default_driver_data; -static DRAM_ATTR spi_flash_host_driver_t esp_flash_default_host_drv = ESP_FLASH_DEFAULT_HOST_DRIVER(); - +static DRAM_ATTR memspi_host_inst_t esp_flash_default_host; static DRAM_ATTR esp_flash_t default_chip = { .read_mode = DEFAULT_FLASH_MODE, - .host = &esp_flash_default_host_drv, + .host = (spi_flash_host_inst_t*)&esp_flash_default_host, .os_func = &esp_flash_noos_functions, }; @@ -229,12 +216,14 @@ esp_err_t esp_flash_init_default_chip(void) #endif //the host is already initialized, only do init for the data and load it to the host - spi_flash_hal_init(&default_driver_data, &cfg); - default_chip.host->driver_data = &default_driver_data; + esp_err_t err = memspi_host_init_pointers(&esp_flash_default_host, &cfg); + if (err != ESP_OK) { + return err; + } // ROM TODO: account for non-standard default pins in efuse // ROM TODO: to account for chips which are slow to power on, maybe keep probing in a loop here - esp_err_t err = esp_flash_init(&default_chip); + err = esp_flash_init(&default_chip); if (err != ESP_OK) { return err; } diff --git a/components/spi_flash/include/esp_flash.h b/components/spi_flash/include/esp_flash.h index c4951fe91e..d100c57ffe 100644 --- a/components/spi_flash/include/esp_flash.h +++ b/components/spi_flash/include/esp_flash.h @@ -80,7 +80,7 @@ typedef struct { risk. */ struct esp_flash_t { - spi_flash_host_driver_t *host; ///< Pointer to hardware-specific "host_driver" structure. Must be initialized before used. + spi_flash_host_inst_t* host; ///< Pointer to hardware-specific "host_driver" structure. Must be initialized before used. const spi_flash_chip_t *chip_drv; ///< Pointer to chip-model-specific "adapter" structure. If NULL, will be detected during initialisation. const esp_flash_os_functions_t *os_func; ///< Pointer to os-specific hook structure. Call ``esp_flash_init_os_functions()`` to setup this field, after the host is properly initialized. diff --git a/components/spi_flash/include/memspi_host_driver.h b/components/spi_flash/include/memspi_host_driver.h index 8c476ad4c7..a94260b26e 100644 --- a/components/spi_flash/include/memspi_host_driver.h +++ b/components/spi_flash/include/memspi_host_driver.h @@ -38,20 +38,19 @@ } /// configuration for the memspi host -typedef spi_flash_memspi_config_t memspi_host_config_t; +typedef spi_flash_hal_config_t memspi_host_config_t; /// context for the memspi host -typedef spi_flash_memspi_data_t memspi_host_data_t; +typedef spi_flash_hal_context_t memspi_host_inst_t; /** * Initialize the memory SPI host. * * @param host Pointer to the host structure. - * @param data Pointer to allocated space to hold the context of host driver. * @param cfg Pointer to configuration structure * * @return always return ESP_OK */ -esp_err_t memspi_host_init_pointers(spi_flash_host_driver_t *host, memspi_host_data_t *data, const memspi_host_config_t *cfg); +esp_err_t memspi_host_init_pointers(memspi_host_inst_t *host, const memspi_host_config_t *cfg); /******************************************************************************* * NOTICE @@ -66,7 +65,7 @@ esp_err_t memspi_host_init_pointers(spi_flash_host_driver_t *host, memspi_host_d * High speed implementation of RDID through memspi interface relying on the * ``common_command``. * - * @param driver The driver context. + * @param host The driver context. * @param id Output of the read ID from the slave. * * @return @@ -74,82 +73,82 @@ esp_err_t memspi_host_init_pointers(spi_flash_host_driver_t *host, memspi_host_d * - ESP_ERR_FLASH_NO_RESPONSE: if no response from chip * - or other cases from ``spi_hal_common_command`` */ -esp_err_t memspi_host_read_id_hs(spi_flash_host_driver_t *driver, uint32_t *id); +esp_err_t memspi_host_read_id_hs(spi_flash_host_inst_t *host, uint32_t *id); /** * High speed implementation of RDSR through memspi interface relying on the * ``common_command``. * - * @param driver The driver context. + * @param host The driver context. * @param id Output of the read ID from the slave. * * @return * - ESP_OK: if success * - or other cases from ``spi_hal_common_command`` */ -esp_err_t memspi_host_read_status_hs(spi_flash_host_driver_t *driver, uint8_t *out_sr); +esp_err_t memspi_host_read_status_hs(spi_flash_host_inst_t *host, uint8_t *out_sr); /** * Flush the cache (if needed) after the contents are modified. * - * @param driver The driver context. + * @param host The driver context. * @param addr Start address of the modified region * @param size Size of the region modified. * * @return always ESP_OK. */ -esp_err_t memspi_host_flush_cache(spi_flash_host_driver_t* driver, uint32_t addr, uint32_t size); +esp_err_t memspi_host_flush_cache(spi_flash_host_inst_t *host, uint32_t addr, uint32_t size); /** * Erase contents of entire chip. * - * @param driver The driver context. + * @param host The driver context. */ -void memspi_host_erase_chip(spi_flash_host_driver_t *driver); +void memspi_host_erase_chip(spi_flash_host_inst_t *host); /** * Erase a sector starting from a given address. * - * @param driver The driver context. + * @param host The driver context. * @param start_address Starting address of the sector. */ -void memspi_host_erase_sector(spi_flash_host_driver_t *driver, uint32_t start_address); +void memspi_host_erase_sector(spi_flash_host_inst_t *host, uint32_t start_address); /** * Erase a block starting from a given address. * - * @param driver The driver context. + * @param host The driver context. * @param start_address Starting address of the block. */ -void memspi_host_erase_block(spi_flash_host_driver_t *driver, uint32_t start_address); +void memspi_host_erase_block(spi_flash_host_inst_t *host, uint32_t start_address); /** * Program a page with contents of a buffer. * - * @param driver The driver context. + * @param host The driver context. * @param buffer Buffer which contains the data to be flashed. * @param address Starting address of where to flash the data. * @param length The number of bytes to flash. */ -void memspi_host_program_page(spi_flash_host_driver_t *driver, const void *buffer, uint32_t address, uint32_t length); +void memspi_host_program_page(spi_flash_host_inst_t *host, const void *buffer, uint32_t address, uint32_t length); /** * Set ability to write to chip. * - * @param driver The driver context. + * @param host The driver context. * @param wp Enable or disable write protect (true - enable, false - disable). */ -esp_err_t memspi_host_set_write_protect(spi_flash_host_driver_t *driver, bool wp); +esp_err_t memspi_host_set_write_protect(spi_flash_host_inst_t *host, bool wp); /** * Read data to buffer. * - * @param driver The driver context. + * @param host The driver context. * @param buffer Buffer which contains the data to be read. * @param address Starting address of where to read the data. * @param length The number of bytes to read. */ -esp_err_t memspi_host_read(spi_flash_host_driver_t *driver, void *buffer, uint32_t address, uint32_t read_len); +esp_err_t memspi_host_read(spi_flash_host_inst_t *host, void *buffer, uint32_t address, uint32_t read_len); /** * @brief Slicer for read data used in non-encrypted regions. This slicer does nothing but @@ -162,7 +161,7 @@ esp_err_t memspi_host_read(spi_flash_host_driver_t *driver, void *buffer, uint32 * * @return Length that can actually be read in one `read` call in `spi_flash_host_driver_t`. */ -int memspi_host_read_data_slicer(uint32_t address, uint32_t len, uint32_t *align_address, uint32_t page_size); +int memspi_host_read_data_slicer(spi_flash_host_inst_t *host, uint32_t address, uint32_t len, uint32_t *align_address, uint32_t page_size); /** * @brief Slicer for write data used in non-encrypted regions. This slicer limit the length to the @@ -176,4 +175,4 @@ int memspi_host_read_data_slicer(uint32_t address, uint32_t len, uint32_t *align * * @return Length that can actually be written in one `program_page` call in `spi_flash_host_driver_t`. */ -int memspi_host_write_data_slicer(uint32_t address, uint32_t len, uint32_t *align_address, uint32_t page_size); \ No newline at end of file +int memspi_host_write_data_slicer(spi_flash_host_inst_t *host, uint32_t address, uint32_t len, uint32_t *align_address, uint32_t page_size); \ No newline at end of file diff --git a/components/spi_flash/memspi_host_driver.c b/components/spi_flash/memspi_host_driver.c index 645916bda0..5f2002d638 100644 --- a/components/spi_flash/memspi_host_driver.c +++ b/components/spi_flash/memspi_host_driver.c @@ -23,22 +23,22 @@ #define SPI_FLASH_HAL_MAX_READ_BYTES 64 static const char TAG[] = "memspi"; -static const spi_flash_host_driver_t esp_flash_default_host = ESP_FLASH_DEFAULT_HOST_DRIVER(); +DRAM_ATTR static const spi_flash_host_driver_t esp_flash_default_host = ESP_FLASH_DEFAULT_HOST_DRIVER(); #ifdef CONFIG_IDF_TARGET_ESP32S2 -extern void spi_flash_hal_gpspi_poll_cmd_done(spi_flash_host_driver_t *driver); -extern esp_err_t spi_flash_hal_gpspi_device_config(spi_flash_host_driver_t *driver); +extern void spi_flash_hal_gpspi_poll_cmd_done(spi_flash_host_inst_t *host); +extern esp_err_t spi_flash_hal_gpspi_device_config(spi_flash_host_inst_t *host); esp_err_t spi_flash_hal_gpspi_configure_host_io_mode( - spi_flash_host_driver_t *host, + spi_flash_host_inst_t *host, uint32_t command, uint32_t addr_bitlen, int dummy_cyclelen_base, esp_flash_io_mode_t io_mode); -extern esp_err_t spi_flash_hal_gpspi_common_command(spi_flash_host_driver_t *chip_drv, spi_flash_trans_t *trans); -extern esp_err_t spi_flash_hal_gpspi_read(spi_flash_host_driver_t *chip_drv, void *buffer, uint32_t address, uint32_t read_len); -extern bool spi_flash_hal_gpspi_host_idle(spi_flash_host_driver_t *chip_drv); -extern bool spi_flash_hal_gpspi_supports_direct_write(spi_flash_host_driver_t *driver, const void *p); -extern bool spi_flash_hal_gpspi_supports_direct_read(spi_flash_host_driver_t *driver, const void *p); +extern esp_err_t spi_flash_hal_gpspi_common_command(spi_flash_host_inst_t *host, spi_flash_trans_t *trans); +extern esp_err_t spi_flash_hal_gpspi_read(spi_flash_host_inst_t *host, void *buffer, uint32_t address, uint32_t read_len); +extern bool spi_flash_hal_gpspi_host_idle(spi_flash_host_inst_t *host); +extern bool spi_flash_hal_gpspi_supports_direct_write(spi_flash_host_inst_t *host, const void *p); +extern bool spi_flash_hal_gpspi_supports_direct_read(spi_flash_host_inst_t *host, const void *p); /** Default configuration for GPSPI */ static const spi_flash_host_driver_t esp_flash_gpspi_host = { @@ -63,32 +63,23 @@ static const spi_flash_host_driver_t esp_flash_gpspi_host = { }; #endif -esp_err_t memspi_host_init_pointers(spi_flash_host_driver_t *host, memspi_host_data_t *data, const memspi_host_config_t *cfg) +esp_err_t memspi_host_init_pointers(memspi_host_inst_t *host, const memspi_host_config_t *cfg) { #ifdef CONFIG_IDF_TARGET_ESP32 - memcpy(host, &esp_flash_default_host, sizeof(spi_flash_host_driver_t)); + host->inst.driver = &esp_flash_default_host; #elif CONFIG_IDF_TARGET_ESP32S2 if (cfg->host_id == SPI_HOST) - memcpy(host, &esp_flash_default_host, sizeof(spi_flash_host_driver_t)); + host->inst.driver = &esp_flash_default_host; else { - memcpy(host, &esp_flash_gpspi_host, sizeof(spi_flash_host_driver_t)); + host->inst.driver = &esp_flash_gpspi_host; } #endif - esp_err_t err = spi_flash_hal_init(data, cfg); - if (err != ESP_OK) { - return err; - } - - host->driver_data = data; - //some functions are not required if not SPI1 - if ((void*)data->spi != (void*)spi_flash_ll_get_hw(SPI_HOST)) { - host->flush_cache = NULL; - } - return ESP_OK; + esp_err_t err = spi_flash_hal_init(host, cfg); + return err; } -esp_err_t memspi_host_read_id_hs(spi_flash_host_driver_t *host, uint32_t *id) +esp_err_t memspi_host_read_id_hs(spi_flash_host_inst_t *host, uint32_t *id) { uint32_t id_buf = 0; spi_flash_trans_t t = { @@ -96,7 +87,7 @@ esp_err_t memspi_host_read_id_hs(spi_flash_host_driver_t *host, uint32_t *id) .miso_len = 3, .miso_data = ((uint8_t*) &id_buf), }; - host->common_command(host, &t); + host->driver->common_command(host, &t); uint32_t raw_flash_id = id_buf; ESP_EARLY_LOGV(TAG, "raw_chip_id: %X\n", raw_flash_id); @@ -112,7 +103,7 @@ esp_err_t memspi_host_read_id_hs(spi_flash_host_driver_t *host, uint32_t *id) return ESP_OK; } -esp_err_t memspi_host_read_status_hs(spi_flash_host_driver_t *driver, uint8_t *out_sr) +esp_err_t memspi_host_read_status_hs(spi_flash_host_inst_t *host, uint8_t *out_sr) { //NOTE: we do have a read id function, however it doesn't work in high freq uint32_t stat_buf = 0; @@ -121,7 +112,7 @@ esp_err_t memspi_host_read_status_hs(spi_flash_host_driver_t *driver, uint8_t *o .miso_data = ((uint8_t*) &stat_buf), .miso_len = 1 }; - esp_err_t err = driver->common_command(driver, &t); + esp_err_t err = host->driver->common_command(host, &t); if (err != ESP_OK) { return err; } @@ -129,42 +120,42 @@ esp_err_t memspi_host_read_status_hs(spi_flash_host_driver_t *driver, uint8_t *o return ESP_OK; } -esp_err_t memspi_host_flush_cache(spi_flash_host_driver_t* driver, uint32_t addr, uint32_t size) +esp_err_t memspi_host_flush_cache(spi_flash_host_inst_t *host, uint32_t addr, uint32_t size) { - if ((void*)((memspi_host_data_t*)(driver->driver_data))->spi == (void*) spi_flash_ll_get_hw(SPI_HOST)) { + if ((void*)((memspi_host_inst_t*)host)->spi == (void*) spi_flash_ll_get_hw(SPI_HOST)) { spi_flash_check_and_flush_cache(addr, size); } return ESP_OK; } -void memspi_host_erase_chip(spi_flash_host_driver_t *chip_drv) +void memspi_host_erase_chip(spi_flash_host_inst_t *host) { spi_flash_trans_t t = { 0 }; t.command = CMD_CHIP_ERASE; - chip_drv->common_command(chip_drv, &t); + host->driver->common_command(host, &t); } -void memspi_host_erase_sector(spi_flash_host_driver_t *chip_drv, uint32_t start_address) +void memspi_host_erase_sector(spi_flash_host_inst_t *host, uint32_t start_address) { spi_flash_trans_t t = { .command = CMD_SECTOR_ERASE, .address_bitlen = 24, .address = start_address }; - chip_drv->common_command(chip_drv, &t); + host->driver->common_command(host, &t); } -void memspi_host_erase_block(spi_flash_host_driver_t *chip_drv, uint32_t start_address) +void memspi_host_erase_block(spi_flash_host_inst_t *host, uint32_t start_address) { spi_flash_trans_t t = { .command = CMD_LARGE_BLOCK_ERASE, .address_bitlen = 24, .address = start_address, }; - chip_drv->common_command(chip_drv, &t); + host->driver->common_command(host, &t); } -void memspi_host_program_page(spi_flash_host_driver_t *chip_drv, const void *buffer, uint32_t address, uint32_t length) +void memspi_host_program_page(spi_flash_host_inst_t *host, const void *buffer, uint32_t address, uint32_t length) { spi_flash_trans_t t = { .command = CMD_PROGRAM_PAGE, @@ -173,10 +164,10 @@ void memspi_host_program_page(spi_flash_host_driver_t *chip_drv, const void *buf .mosi_len = length, .mosi_data = buffer }; - chip_drv->common_command(chip_drv, &t); + host->driver->common_command(host, &t); } -esp_err_t memspi_host_read(spi_flash_host_driver_t *chip_drv, void *buffer, uint32_t address, uint32_t read_len) +esp_err_t memspi_host_read(spi_flash_host_inst_t *host, void *buffer, uint32_t address, uint32_t read_len) { spi_flash_trans_t t = { .command = CMD_READ, @@ -185,22 +176,22 @@ esp_err_t memspi_host_read(spi_flash_host_driver_t *chip_drv, void *buffer, uint .miso_len = read_len, .miso_data = buffer }; - chip_drv->common_command(chip_drv, &t); + host->driver->common_command(host, &t); return ESP_OK; } -esp_err_t memspi_host_set_write_protect(spi_flash_host_driver_t *chip_drv, bool wp) +esp_err_t memspi_host_set_write_protect(spi_flash_host_inst_t *host, bool wp) { spi_flash_trans_t t = { .command = wp ? CMD_WRDI : CMD_WREN }; - chip_drv->common_command(chip_drv, &t); + host->driver->common_command(host, &t); return ESP_OK; } // When encryption is enabled, etc. the data slicer may be complicated // This is the simple case where the hardware has no other requirements than the size and page boundary -int memspi_host_write_data_slicer(uint32_t address, uint32_t len, uint32_t *align_address, uint32_t page_size) +int memspi_host_write_data_slicer(spi_flash_host_inst_t *host, uint32_t address, uint32_t len, uint32_t *align_address, uint32_t page_size) { uint32_t align_addr = address; uint32_t end_bound = (align_addr/page_size + 1) * page_size; @@ -210,7 +201,7 @@ int memspi_host_write_data_slicer(uint32_t address, uint32_t len, uint32_t *alig return MIN(max_len, len); } -int memspi_host_read_data_slicer(uint32_t address, uint32_t len, uint32_t *align_address, uint32_t page_size) +int memspi_host_read_data_slicer(spi_flash_host_inst_t *host, uint32_t address, uint32_t len, uint32_t *align_address, uint32_t page_size) { // Shouldn't read longer than SPI_FLASH_HAL_MAX_READ_BYTES uint32_t max_len = SPI_FLASH_HAL_MAX_READ_BYTES; diff --git a/components/spi_flash/spi_flash_chip_generic.c b/components/spi_flash/spi_flash_chip_generic.c index cf9a306b64..6db7144773 100644 --- a/components/spi_flash/spi_flash_chip_generic.c +++ b/components/spi_flash/spi_flash_chip_generic.c @@ -76,7 +76,7 @@ esp_err_t spi_flash_chip_generic_reset(esp_flash_t *chip) t = (spi_flash_trans_t) { .command = CMD_RST_EN, }; - esp_err_t err = chip->host->common_command(chip->host, &t); + esp_err_t err = chip->host->driver->common_command(chip->host, &t); if (err != ESP_OK) { return err; } @@ -84,7 +84,7 @@ esp_err_t spi_flash_chip_generic_reset(esp_flash_t *chip) t = (spi_flash_trans_t) { .command = CMD_RST_DEV, }; - err = chip->host->common_command(chip->host, &t); + err = chip->host->driver->common_command(chip->host, &t); if (err != ESP_OK) { return err; } @@ -118,10 +118,10 @@ esp_err_t spi_flash_chip_generic_erase_chip(esp_flash_t *chip) err = chip->chip_drv->wait_idle(chip, chip->chip_drv->timeout->idle_timeout); } if (err == ESP_OK) { - chip->host->erase_chip(chip->host); + chip->host->driver->erase_chip(chip->host); //to save time, flush cache here - if (chip->host->flush_cache) { - err = chip->host->flush_cache(chip->host, 0, chip->size); + if (chip->host->driver->flush_cache) { + err = chip->host->driver->flush_cache(chip->host, 0, chip->size); if (err != ESP_OK) { return err; } @@ -138,10 +138,10 @@ esp_err_t spi_flash_chip_generic_erase_sector(esp_flash_t *chip, uint32_t start_ err = chip->chip_drv->wait_idle(chip, chip->chip_drv->timeout->idle_timeout); } if (err == ESP_OK) { - chip->host->erase_sector(chip->host, start_address); + chip->host->driver->erase_sector(chip->host, start_address); //to save time, flush cache here - if (chip->host->flush_cache) { - err = chip->host->flush_cache(chip->host, start_address, chip->chip_drv->sector_size); + if (chip->host->driver->flush_cache) { + err = chip->host->driver->flush_cache(chip->host, start_address, chip->chip_drv->sector_size); if (err != ESP_OK) { return err; } @@ -158,10 +158,10 @@ esp_err_t spi_flash_chip_generic_erase_block(esp_flash_t *chip, uint32_t start_a err = chip->chip_drv->wait_idle(chip, chip->chip_drv->timeout->idle_timeout); } if (err == ESP_OK) { - chip->host->erase_block(chip->host, start_address); + chip->host->driver->erase_block(chip->host, start_address); //to save time, flush cache here - if (chip->host->flush_cache) { - err = chip->host->flush_cache(chip->host, start_address, chip->chip_drv->block_erase_size); + if (chip->host->driver->flush_cache) { + err = chip->host->driver->flush_cache(chip->host, start_address, chip->chip_drv->block_erase_size); if (err != ESP_OK) { return err; } @@ -188,10 +188,10 @@ esp_err_t spi_flash_chip_generic_read(esp_flash_t *chip, void *buffer, uint32_t while (err == ESP_OK && length > 0) { memset(temp_buffer, 0xFF, sizeof(temp_buffer)); - uint32_t read_len = chip->host->read_data_slicer(address, length, &align_address, page_size); + uint32_t read_len = chip->host->driver->read_data_slicer(chip->host, address, length, &align_address, page_size); uint32_t left_off = address - align_address; uint32_t data_len = MIN(align_address + read_len, address + length) - address; - err = chip->host->read(chip->host, temp_buffer, align_address, read_len); + err = chip->host->driver->read(chip->host, temp_buffer, align_address, read_len); memcpy(buffer, temp_buffer + left_off, data_len); @@ -211,7 +211,7 @@ esp_err_t spi_flash_chip_generic_page_program(esp_flash_t *chip, const void *buf if (err == ESP_OK) { // Perform the actual Page Program command - chip->host->program_page(chip->host, buffer, address, length); + chip->host->driver->program_page(chip->host, buffer, address, length); err = chip->chip_drv->wait_idle(chip, chip->chip_drv->timeout->page_program_timeout); } @@ -227,7 +227,7 @@ esp_err_t spi_flash_chip_generic_write(esp_flash_t *chip, const void *buffer, ui while (err == ESP_OK && length > 0) { memset(temp_buffer, 0xFF, sizeof(temp_buffer)); - uint32_t page_len = chip->host->write_data_slicer(address, length, &align_address, page_size); + uint32_t page_len = chip->host->driver->write_data_slicer(chip->host, address, length, &align_address, page_size); uint32_t left_off = address - align_address; uint32_t write_len = MIN(align_address + page_len, address + length) - address; memcpy(temp_buffer + left_off, buffer, write_len); @@ -241,8 +241,8 @@ esp_err_t spi_flash_chip_generic_write(esp_flash_t *chip, const void *buffer, ui length -= write_len; } } - if (err == ESP_OK && chip->host->flush_cache) { - err = chip->host->flush_cache(chip->host, address, length); + if (err == ESP_OK && chip->host->driver->flush_cache) { + err = chip->host->driver->flush_cache(chip->host, address, length); } return err; } @@ -259,7 +259,7 @@ esp_err_t spi_flash_chip_generic_set_write_protect(esp_flash_t *chip, bool write err = chip->chip_drv->wait_idle(chip, chip->chip_drv->timeout->idle_timeout); if (err == ESP_OK) { - chip->host->set_write_protect(chip->host, write_protect); + chip->host->driver->set_write_protect(chip->host, write_protect); } bool wp_read; @@ -276,7 +276,7 @@ esp_err_t spi_flash_chip_generic_get_write_protect(esp_flash_t *chip, bool *out_ esp_err_t err = ESP_OK; uint8_t status; assert(out_write_protect!=NULL); - err = chip->host->read_status(chip->host, &status); + err = chip->host->driver->read_status(chip->host, &status); if (err != ESP_OK) { return err; } @@ -287,7 +287,7 @@ esp_err_t spi_flash_chip_generic_get_write_protect(esp_flash_t *chip, bool *out_ esp_err_t spi_flash_generic_wait_host_idle(esp_flash_t *chip, uint32_t *timeout_us) { - while (chip->host->host_idle(chip->host) && *timeout_us > 0) { + while (chip->host->driver->host_idle(chip->host) && *timeout_us > 0) { #if HOST_DELAY_INTERVAL_US > 0 if (*timeout_us > 1) { int delay = MIN(HOST_DELAY_INTERVAL_US, *timeout_us); @@ -314,7 +314,7 @@ esp_err_t spi_flash_chip_generic_wait_idle(esp_flash_t *chip, uint32_t timeout_u return err; } - err = chip->host->read_status(chip->host, &status); + err = chip->host->driver->read_status(chip->host, &status); if (err != ESP_OK) { return err; } @@ -374,7 +374,7 @@ esp_err_t spi_flash_chip_generic_config_host_io_mode(esp_flash_t *chip) return ESP_ERR_FLASH_NOT_INITIALISED; } - return chip->host->configure_host_io_mode(chip->host, read_command, addr_bitlen, dummy_cyclelen_base, + return chip->host->driver->configure_host_io_mode(chip->host, read_command, addr_bitlen, dummy_cyclelen_base, chip->read_mode); } @@ -451,7 +451,7 @@ static esp_err_t spi_flash_common_read_qe_sr(esp_flash_t *chip, uint8_t qe_rdsr_ .miso_data = (uint8_t*) &sr_buf, .miso_len = qe_sr_bitwidth / 8, }; - esp_err_t ret = chip->host->common_command(chip->host, &t); + esp_err_t ret = chip->host->driver->common_command(chip->host, &t); *sr = sr_buf; return ret; } @@ -464,7 +464,7 @@ static esp_err_t spi_flash_common_write_qe_sr(esp_flash_t *chip, uint8_t qe_wrsr .mosi_len = qe_sr_bitwidth / 8, .miso_len = 0, }; - return chip->host->common_command(chip->host, &t); + return chip->host->driver->common_command(chip->host, &t); } esp_err_t spi_flash_common_read_status_16b_rdsr_rdsr2(esp_flash_t* chip, uint32_t* out_sr) diff --git a/components/spi_flash/test/test_esp_flash.c b/components/spi_flash/test/test_esp_flash.c index 73ae94554a..0c7e2d44fb 100644 --- a/components/spi_flash/test/test_esp_flash.c +++ b/components/spi_flash/test/test_esp_flash.c @@ -8,6 +8,7 @@ #include "esp_flash.h" #include "driver/spi_common_internal.h" #include "esp_flash_spi_init.h" +#include "memspi_host_driver.h" #include #include "esp_log.h" @@ -18,7 +19,6 @@ #include "soc/io_mux_reg.h" #include "sdkconfig.h" -#include "hal/spi_flash_hal.h" #include "ccomp_timer.h" #include "esp_rom_gpio.h" @@ -175,9 +175,9 @@ static void get_chip_host(esp_flash_t* chip, spi_host_device_t* out_host_id, int host_id = SPI_HOST; cs_id = 0; } else { - spi_flash_memspi_data_t* driver_data = (spi_flash_memspi_data_t*)chip->host->driver_data; - host_id = spi_flash_ll_hw_get_id(driver_data->spi); - cs_id = driver_data->cs_num; + spi_flash_hal_context_t* host_data = (spi_flash_hal_context_t*)chip->host; + host_id = spi_flash_ll_hw_get_id(host_data->spi); + cs_id = host_data->cs_num; } if (out_host_id) { *out_host_id = host_id;