mirror of
				https://github.com/espressif/esp-idf.git
				synced 2025-10-31 13:09:38 +00:00 
			
		
		
		
	esp_flash: fix the write performance regression
Also changed internal delay unit into microsecond.
This commit is contained in:
		| @@ -48,8 +48,8 @@ typedef struct { | |||||||
|     /** Called before any erase/write operations to check whether the region is limited by the OS */ |     /** Called before any erase/write operations to check whether the region is limited by the OS */ | ||||||
|     esp_err_t (*region_protected)(void* arg, size_t start_addr, size_t size); |     esp_err_t (*region_protected)(void* arg, size_t start_addr, size_t size); | ||||||
|  |  | ||||||
|     /** Delay for at least 'ms' milliseconds. Called in between 'start' and 'end'. */ |     /** Delay for at least 'us' microseconds. Called in between 'start' and 'end'. */ | ||||||
|     esp_err_t (*delay_ms)(void *arg, unsigned ms); |     esp_err_t (*delay_us)(void *arg, unsigned us); | ||||||
| } esp_flash_os_functions_t; | } esp_flash_os_functions_t; | ||||||
|  |  | ||||||
| /** @brief Structure to describe a SPI flash chip connected to the system. | /** @brief Structure to describe a SPI flash chip connected to the system. | ||||||
|   | |||||||
| @@ -193,14 +193,14 @@ esp_err_t spi_flash_chip_generic_get_write_protect(esp_flash_t *chip, bool *out_ | |||||||
|  * progress bit) to be cleared. |  * progress bit) to be cleared. | ||||||
|  * |  * | ||||||
|  * @param chip Pointer to SPI flash chip to use. If NULL, esp_flash_default_chip is substituted. |  * @param chip Pointer to SPI flash chip to use. If NULL, esp_flash_default_chip is substituted. | ||||||
|  * @param timeout_ms Time to wait before timeout, in ms. |  * @param timeout_us Time to wait before timeout, in us. | ||||||
|  * |  * | ||||||
|  * @return |  * @return | ||||||
|  *      - ESP_OK if success |  *      - ESP_OK if success | ||||||
|  *      - ESP_ERR_TIMEOUT if not idle before timeout |  *      - ESP_ERR_TIMEOUT if not idle before timeout | ||||||
|  *      - or other error passed from the ``wait_idle`` or ``read_status`` function of host driver |  *      - or other error passed from the ``wait_idle`` or ``read_status`` function of host driver | ||||||
|  */ |  */ | ||||||
| esp_err_t spi_flash_chip_generic_wait_idle(esp_flash_t *chip, uint32_t timeout_ms); | esp_err_t spi_flash_chip_generic_wait_idle(esp_flash_t *chip, uint32_t timeout_us); | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * @brief Set the specified SPI read mode according to the data in the chip |  * @brief Set the specified SPI read mode according to the data in the chip | ||||||
| @@ -247,7 +247,7 @@ extern const spi_flash_chip_t esp_flash_chip_generic; | |||||||
|  * spi_flash_chip_generic_wait_idle() and may be useful when implementing |  * spi_flash_chip_generic_wait_idle() and may be useful when implementing | ||||||
|  * alternative drivers. |  * alternative drivers. | ||||||
|  * |  * | ||||||
|  * timeout_ms will be decremented if the function needs to wait until the host hardware is idle. |  * timeout_us will be decremented if the function needs to wait until the host hardware is idle. | ||||||
|  * |  * | ||||||
|  * @param chip Pointer to SPI flash chip to use. If NULL, esp_flash_default_chip is substituted. |  * @param chip Pointer to SPI flash chip to use. If NULL, esp_flash_default_chip is substituted. | ||||||
|  * |  * | ||||||
| @@ -256,7 +256,7 @@ extern const spi_flash_chip_t esp_flash_chip_generic; | |||||||
|  *      - ESP_ERR_TIMEOUT if not idle before timeout |  *      - ESP_ERR_TIMEOUT if not idle before timeout | ||||||
|  *      - or other error passed from the ``set_write_protect`` or ``common_command`` function of host driver |  *      - or other error passed from the ``set_write_protect`` or ``common_command`` function of host driver | ||||||
|  */ |  */ | ||||||
| esp_err_t spi_flash_generic_wait_host_idle(esp_flash_t *chip, uint32_t *timeout_ms); | esp_err_t spi_flash_generic_wait_host_idle(esp_flash_t *chip, uint32_t *timeout_us); | ||||||
|  |  | ||||||
| /// Function pointer type for reading status register with QE bit. | /// Function pointer type for reading status register with QE bit. | ||||||
| typedef esp_err_t (*esp_flash_rdsr_func_t)(esp_flash_t* chip, uint32_t* out_sr); | typedef esp_err_t (*esp_flash_rdsr_func_t)(esp_flash_t* chip, uint32_t* out_sr); | ||||||
|   | |||||||
| @@ -20,12 +20,15 @@ | |||||||
|  |  | ||||||
| static const char TAG[] = "chip_generic"; | static const char TAG[] = "chip_generic"; | ||||||
|  |  | ||||||
| #define SPI_FLASH_GENERIC_CHIP_ERASE_TIMEOUT 4000 | #define SPI_FLASH_DEFAULT_IDLE_TIMEOUT_MS           200 | ||||||
| #define SPI_FLASH_GENERIC_SECTOR_ERASE_TIMEOUT 500 | #define SPI_FLASH_GENERIC_CHIP_ERASE_TIMEOUT_MS     4000 | ||||||
| #define SPI_FLASH_GENERIC_BLOCK_ERASE_TIMEOUT 1000 | #define SPI_FLASH_GENERIC_SECTOR_ERASE_TIMEOUT_MS   500  //according to GD25Q127 + 100ms | ||||||
|  | #define SPI_FLASH_GENERIC_BLOCK_ERASE_TIMEOUT_MS    1300  //according to GD25Q127 + 100ms | ||||||
|  | #define SPI_FLASH_GENERIC_PAGE_PROGRAM_TIMEOUT_MS   500 | ||||||
|  |  | ||||||
|  | #define HOST_DELAY_INTERVAL_US                      1 | ||||||
|  | #define CHIP_WAIT_IDLE_INTERVAL_US                  20 | ||||||
|  |  | ||||||
| #define DEFAULT_IDLE_TIMEOUT 200 |  | ||||||
| #define DEFAULT_PAGE_PROGRAM_TIMEOUT 500 |  | ||||||
|  |  | ||||||
| esp_err_t spi_flash_chip_generic_probe(esp_flash_t *chip, uint32_t flash_id) | esp_err_t spi_flash_chip_generic_probe(esp_flash_t *chip, uint32_t flash_id) | ||||||
| { | { | ||||||
| @@ -54,7 +57,7 @@ esp_err_t spi_flash_chip_generic_reset(esp_flash_t *chip) | |||||||
|         return err; |         return err; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     err = chip->chip_drv->wait_idle(chip, DEFAULT_IDLE_TIMEOUT); |     err = chip->chip_drv->wait_idle(chip, SPI_FLASH_DEFAULT_IDLE_TIMEOUT_MS * 1000); | ||||||
|     return err; |     return err; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -80,7 +83,7 @@ esp_err_t spi_flash_chip_generic_erase_chip(esp_flash_t *chip) | |||||||
|  |  | ||||||
|     err = chip->chip_drv->set_chip_write_protect(chip, false); |     err = chip->chip_drv->set_chip_write_protect(chip, false); | ||||||
|     if (err == ESP_OK) { |     if (err == ESP_OK) { | ||||||
|         err = chip->chip_drv->wait_idle(chip, DEFAULT_IDLE_TIMEOUT); |         err = chip->chip_drv->wait_idle(chip, SPI_FLASH_DEFAULT_IDLE_TIMEOUT_MS * 1000); | ||||||
|     } |     } | ||||||
|     if (err == ESP_OK) { |     if (err == ESP_OK) { | ||||||
|         chip->host->erase_chip(chip->host); |         chip->host->erase_chip(chip->host); | ||||||
| @@ -91,7 +94,7 @@ esp_err_t spi_flash_chip_generic_erase_chip(esp_flash_t *chip) | |||||||
|                 return err; |                 return err; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         err = chip->chip_drv->wait_idle(chip, SPI_FLASH_GENERIC_CHIP_ERASE_TIMEOUT); |         err = chip->chip_drv->wait_idle(chip, SPI_FLASH_GENERIC_CHIP_ERASE_TIMEOUT_MS * 1000); | ||||||
|     } |     } | ||||||
|     return err; |     return err; | ||||||
| } | } | ||||||
| @@ -100,7 +103,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); |     esp_err_t err = chip->chip_drv->set_chip_write_protect(chip, false); | ||||||
|     if (err == ESP_OK) { |     if (err == ESP_OK) { | ||||||
|         err = chip->chip_drv->wait_idle(chip, DEFAULT_IDLE_TIMEOUT); |         err = chip->chip_drv->wait_idle(chip, SPI_FLASH_DEFAULT_IDLE_TIMEOUT_MS * 1000); | ||||||
|     } |     } | ||||||
|     if (err == ESP_OK) { |     if (err == ESP_OK) { | ||||||
|         chip->host->erase_sector(chip->host, start_address); |         chip->host->erase_sector(chip->host, start_address); | ||||||
| @@ -111,7 +114,7 @@ esp_err_t spi_flash_chip_generic_erase_sector(esp_flash_t *chip, uint32_t start_ | |||||||
|                 return err; |                 return err; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         err = chip->chip_drv->wait_idle(chip, SPI_FLASH_GENERIC_SECTOR_ERASE_TIMEOUT); |         err = chip->chip_drv->wait_idle(chip, SPI_FLASH_GENERIC_SECTOR_ERASE_TIMEOUT_MS * 1000); | ||||||
|     } |     } | ||||||
|     return err; |     return err; | ||||||
| } | } | ||||||
| @@ -120,7 +123,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); |     esp_err_t err = chip->chip_drv->set_chip_write_protect(chip, false); | ||||||
|     if (err == ESP_OK) { |     if (err == ESP_OK) { | ||||||
|         err = chip->chip_drv->wait_idle(chip, DEFAULT_IDLE_TIMEOUT); |         err = chip->chip_drv->wait_idle(chip, SPI_FLASH_DEFAULT_IDLE_TIMEOUT_MS * 1000); | ||||||
|     } |     } | ||||||
|     if (err == ESP_OK) { |     if (err == ESP_OK) { | ||||||
|         chip->host->erase_block(chip->host, start_address); |         chip->host->erase_block(chip->host, start_address); | ||||||
| @@ -131,7 +134,7 @@ esp_err_t spi_flash_chip_generic_erase_block(esp_flash_t *chip, uint32_t start_a | |||||||
|                 return err; |                 return err; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         err = chip->chip_drv->wait_idle(chip, SPI_FLASH_GENERIC_BLOCK_ERASE_TIMEOUT); |         err = chip->chip_drv->wait_idle(chip, SPI_FLASH_GENERIC_BLOCK_ERASE_TIMEOUT_MS * 1000); | ||||||
|     } |     } | ||||||
|     return err; |     return err; | ||||||
| } | } | ||||||
| @@ -158,13 +161,13 @@ esp_err_t spi_flash_chip_generic_page_program(esp_flash_t *chip, const void *buf | |||||||
| { | { | ||||||
|     esp_err_t err; |     esp_err_t err; | ||||||
|  |  | ||||||
|     err = chip->chip_drv->wait_idle(chip, DEFAULT_IDLE_TIMEOUT); |     err = chip->chip_drv->wait_idle(chip, SPI_FLASH_DEFAULT_IDLE_TIMEOUT_MS * 1000); | ||||||
|  |  | ||||||
|     if (err == ESP_OK) { |     if (err == ESP_OK) { | ||||||
|         // Perform the actual Page Program command |         // Perform the actual Page Program command | ||||||
|         chip->host->program_page(chip->host, buffer, address, length); |         chip->host->program_page(chip->host, buffer, address, length); | ||||||
|  |  | ||||||
|         err = chip->chip_drv->wait_idle(chip, DEFAULT_PAGE_PROGRAM_TIMEOUT); |         err = chip->chip_drv->wait_idle(chip, SPI_FLASH_GENERIC_PAGE_PROGRAM_TIMEOUT_MS * 1000); | ||||||
|     } |     } | ||||||
|     return err; |     return err; | ||||||
| } | } | ||||||
| @@ -205,7 +208,7 @@ esp_err_t spi_flash_chip_generic_set_write_protect(esp_flash_t *chip, bool write | |||||||
| { | { | ||||||
|     esp_err_t err = ESP_OK; |     esp_err_t err = ESP_OK; | ||||||
|  |  | ||||||
|     err = chip->chip_drv->wait_idle(chip, DEFAULT_IDLE_TIMEOUT); |     err = chip->chip_drv->wait_idle(chip, SPI_FLASH_DEFAULT_IDLE_TIMEOUT_MS * 1000); | ||||||
|  |  | ||||||
|     if (err == ESP_OK) { |     if (err == ESP_OK) { | ||||||
|         chip->host->set_write_protect(chip->host, write_protect); |         chip->host->set_write_protect(chip->host, write_protect); | ||||||
| @@ -234,25 +237,31 @@ esp_err_t spi_flash_chip_generic_get_write_protect(esp_flash_t *chip, bool *out_ | |||||||
|     return err; |     return err; | ||||||
| } | } | ||||||
|  |  | ||||||
| esp_err_t spi_flash_generic_wait_host_idle(esp_flash_t *chip, uint32_t *timeout_ms) | 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_ms > 0) { |     while (chip->host->host_idle(chip->host) && *timeout_us > 0) { | ||||||
|         if (*timeout_ms > 1) { | #if HOST_DELAY_INTERVAL_US > 0 | ||||||
|             chip->os_func->delay_ms(chip->os_func_data, 1); |         if (*timeout_us > 1) { | ||||||
|  |             int delay = MIN(HOST_DELAY_INTERVAL_US, *timeout_us); | ||||||
|  |             chip->os_func->delay_us(chip->os_func_data, delay); | ||||||
|  |             *timeout_us -= delay; | ||||||
|  |         } else { | ||||||
|  |             return ESP_ERR_TIMEOUT; | ||||||
|         } |         } | ||||||
|         (*timeout_ms)--; | #endif | ||||||
|     } |     } | ||||||
|     return (*timeout_ms > 0) ? ESP_OK : ESP_ERR_TIMEOUT; |     return ESP_OK; | ||||||
| } | } | ||||||
|  |  | ||||||
| esp_err_t spi_flash_chip_generic_wait_idle(esp_flash_t *chip, uint32_t timeout_ms) | esp_err_t spi_flash_chip_generic_wait_idle(esp_flash_t *chip, uint32_t timeout_us) | ||||||
| { | { | ||||||
|     timeout_ms++; // allow at least one pass before timeout, last one has no sleep cycle |     timeout_us++; // allow at least one pass before timeout, last one has no sleep cycle | ||||||
|  |  | ||||||
|     uint8_t status = 0; |     uint8_t status = 0; | ||||||
|     while (timeout_ms > 0) { |     const int interval = CHIP_WAIT_IDLE_INTERVAL_US; | ||||||
|  |     while (timeout_us > 0) { | ||||||
|  |  | ||||||
|         esp_err_t err = spi_flash_generic_wait_host_idle(chip, &timeout_ms); |         esp_err_t err = spi_flash_generic_wait_host_idle(chip, & timeout_us); | ||||||
|         if (err != ESP_OK) { |         if (err != ESP_OK) { | ||||||
|             return err; |             return err; | ||||||
|         } |         } | ||||||
| @@ -264,13 +273,14 @@ esp_err_t spi_flash_chip_generic_wait_idle(esp_flash_t *chip, uint32_t timeout_m | |||||||
|         if ((status & SR_WIP) == 0) { |         if ((status & SR_WIP) == 0) { | ||||||
|             break; // Write in progress is complete |             break; // Write in progress is complete | ||||||
|         } |         } | ||||||
|         if (timeout_ms > 1) { |         if (timeout_us > 0 && interval > 0) { | ||||||
|             chip->os_func->delay_ms(chip->os_func_data, 1); |             int delay = MIN(interval, timeout_us); | ||||||
|  |             chip->os_func->delay_us(chip->os_func_data, delay); | ||||||
|  |             timeout_us -= delay; | ||||||
|         } |         } | ||||||
|         timeout_ms--; |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     return (timeout_ms > 0) ?  ESP_OK : ESP_ERR_TIMEOUT; |     return (timeout_us > 0) ?  ESP_OK : ESP_ERR_TIMEOUT; | ||||||
| } | } | ||||||
|  |  | ||||||
| esp_err_t spi_flash_chip_generic_config_host_io_mode(esp_flash_t *chip) | esp_err_t spi_flash_chip_generic_config_host_io_mode(esp_flash_t *chip) | ||||||
| @@ -490,7 +500,7 @@ esp_err_t spi_flash_common_set_io_mode(esp_flash_t *chip, esp_flash_wrsr_func_t | |||||||
|             return ret; |             return ret; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         ret = chip->chip_drv->wait_idle(chip, DEFAULT_IDLE_TIMEOUT); |         ret = chip->chip_drv->wait_idle(chip, SPI_FLASH_DEFAULT_IDLE_TIMEOUT_MS * 1000); | ||||||
|         if (ret != ESP_OK) { |         if (ret != ESP_OK) { | ||||||
|             return ret; |             return ret; | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -77,9 +77,9 @@ static esp_err_t spi23_end(void *arg) | |||||||
|     return ESP_OK; |     return ESP_OK; | ||||||
| } | } | ||||||
|  |  | ||||||
| static IRAM_ATTR esp_err_t delay_ms(void *arg, unsigned ms) | static IRAM_ATTR esp_err_t delay_us(void *arg, unsigned us) | ||||||
| { | { | ||||||
|     ets_delay_us(1000 * ms); |     ets_delay_us(us); | ||||||
|     return ESP_OK; |     return ESP_OK; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -115,14 +115,14 @@ static app_func_arg_t spi3_arg = { | |||||||
| const DRAM_ATTR esp_flash_os_functions_t esp_flash_spi1_default_os_functions = { | const DRAM_ATTR esp_flash_os_functions_t esp_flash_spi1_default_os_functions = { | ||||||
|     .start = spi1_start, |     .start = spi1_start, | ||||||
|     .end = spi1_end, |     .end = spi1_end, | ||||||
|     .delay_ms = delay_ms, |     .delay_us = delay_us, | ||||||
|     .region_protected = main_flash_region_protected, |     .region_protected = main_flash_region_protected, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| const esp_flash_os_functions_t esp_flash_spi23_default_os_functions = { | const esp_flash_os_functions_t esp_flash_spi23_default_os_functions = { | ||||||
|     .start = spi23_start, |     .start = spi23_start, | ||||||
|     .end = spi23_end, |     .end = spi23_end, | ||||||
|     .delay_ms = delay_ms, |     .delay_us = delay_us, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| esp_err_t esp_flash_init_os_functions(esp_flash_t *chip, int host_id) | esp_err_t esp_flash_init_os_functions(esp_flash_t *chip, int host_id) | ||||||
|   | |||||||
| @@ -37,16 +37,16 @@ static IRAM_ATTR esp_err_t end(void *arg) | |||||||
|     return ESP_OK; |     return ESP_OK; | ||||||
| } | } | ||||||
|  |  | ||||||
| static IRAM_ATTR esp_err_t delay_ms(void *arg, unsigned ms) | static IRAM_ATTR esp_err_t delay_us(void *arg, unsigned us) | ||||||
| { | { | ||||||
|     ets_delay_us(1000 * ms); |     ets_delay_us(us); | ||||||
|     return ESP_OK; |     return ESP_OK; | ||||||
| } | } | ||||||
|  |  | ||||||
| const DRAM_ATTR esp_flash_os_functions_t esp_flash_noos_functions = { | const DRAM_ATTR esp_flash_os_functions_t esp_flash_noos_functions = { | ||||||
|     .start = start, |     .start = start, | ||||||
|     .end = end, |     .end = end, | ||||||
|     .delay_ms = delay_ms, |     .delay_us = delay_us, | ||||||
|     .region_protected = NULL, |     .region_protected = NULL, | ||||||
| }; | }; | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Michael (XIAO Xufeng)
					Michael (XIAO Xufeng)