mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'bugfix/erase_with_vtaskdelay_v4.1' into 'release/v4.1'
spi_flash: Add vTaskDelay while a long erasing (v4.1) See merge request espressif/esp-idf!8598
This commit is contained in:
commit
e9d4659175
@ -84,6 +84,36 @@ menu "SPI Flash driver"
|
|||||||
The implementation of SPI flash has been greatly changed in IDF v4.0.
|
The implementation of SPI flash has been greatly changed in IDF v4.0.
|
||||||
Enable this option to use the legacy implementation.
|
Enable this option to use the legacy implementation.
|
||||||
|
|
||||||
|
config SPI_FLASH_BYPASS_BLOCK_ERASE
|
||||||
|
bool "Bypass a block erase and always do sector erase"
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
Some flash chips can have very high "max" erase times, especially for block erase (32KB or 64KB).
|
||||||
|
This option allows to bypass "block erase" and always do sector erase commands.
|
||||||
|
This will be much slower overall in most cases, but improves latency for other code to run.
|
||||||
|
|
||||||
|
config SPI_FLASH_YIELD_DURING_ERASE
|
||||||
|
bool "Enables yield operation during flash erase"
|
||||||
|
default y
|
||||||
|
help
|
||||||
|
This allows to yield the CPUs between erase commands.
|
||||||
|
Prevents starvation of other tasks.
|
||||||
|
|
||||||
|
config SPI_FLASH_ERASE_YIELD_DURATION_MS
|
||||||
|
int "Duration of erasing to yield CPUs (ms)"
|
||||||
|
depends on SPI_FLASH_YIELD_DURING_ERASE
|
||||||
|
default 20
|
||||||
|
help
|
||||||
|
If a duration of one erase command is large
|
||||||
|
then it will yield CPUs after finishing a current command.
|
||||||
|
|
||||||
|
config SPI_FLASH_ERASE_YIELD_TICKS
|
||||||
|
int "CPU release time (tick)"
|
||||||
|
depends on SPI_FLASH_YIELD_DURING_ERASE
|
||||||
|
default 1
|
||||||
|
help
|
||||||
|
Defines how many ticks will be before returning to continue a erasing.
|
||||||
|
|
||||||
menu "Auto-detect flash chips"
|
menu "Auto-detect flash chips"
|
||||||
|
|
||||||
config SPI_FLASH_SUPPORT_ISSI_CHIP
|
config SPI_FLASH_SUPPORT_ISSI_CHIP
|
||||||
|
@ -23,6 +23,9 @@
|
|||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#include "esp_heap_caps.h"
|
#include "esp_heap_caps.h"
|
||||||
#include "esp_flash_internal.h"
|
#include "esp_flash_internal.h"
|
||||||
|
#include <freertos/FreeRTOS.h>
|
||||||
|
#include <freertos/task.h>
|
||||||
|
#include "esp_timer.h"
|
||||||
|
|
||||||
static const char TAG[] = "spi_flash";
|
static const char TAG[] = "spi_flash";
|
||||||
|
|
||||||
@ -337,20 +340,27 @@ esp_err_t IRAM_ATTR esp_flash_erase_region(esp_flash_t *chip, uint32_t start, ui
|
|||||||
err = spiflash_end(chip, err);
|
err = spiflash_end(chip, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_SPI_FLASH_YIELD_DURING_ERASE
|
||||||
|
int64_t no_yield_time_us = 0;
|
||||||
|
#endif
|
||||||
while (err == ESP_OK && len >= sector_size) {
|
while (err == ESP_OK && len >= sector_size) {
|
||||||
|
#ifdef CONFIG_SPI_FLASH_YIELD_DURING_ERASE
|
||||||
|
int64_t start_time_us = esp_timer_get_time();
|
||||||
|
#endif
|
||||||
err = spiflash_start(chip);
|
err = spiflash_start(chip);
|
||||||
if (err != ESP_OK) {
|
if (err != ESP_OK) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef CONFIG_SPI_FLASH_BYPASS_BLOCK_ERASE
|
||||||
// If possible erase an entire multi-sector block
|
// If possible erase an entire multi-sector block
|
||||||
if (block_erase_size > 0 && len >= block_erase_size && (start % block_erase_size) == 0) {
|
if (block_erase_size > 0 && len >= block_erase_size && (start % block_erase_size) == 0) {
|
||||||
err = chip->chip_drv->erase_block(chip, start);
|
err = chip->chip_drv->erase_block(chip, start);
|
||||||
start += block_erase_size;
|
start += block_erase_size;
|
||||||
len -= block_erase_size;
|
len -= block_erase_size;
|
||||||
}
|
} else
|
||||||
else {
|
#endif
|
||||||
|
{
|
||||||
// Otherwise erase individual sector only
|
// Otherwise erase individual sector only
|
||||||
err = chip->chip_drv->erase_sector(chip, start);
|
err = chip->chip_drv->erase_sector(chip, start);
|
||||||
start += sector_size;
|
start += sector_size;
|
||||||
@ -358,6 +368,14 @@ esp_err_t IRAM_ATTR esp_flash_erase_region(esp_flash_t *chip, uint32_t start, ui
|
|||||||
}
|
}
|
||||||
|
|
||||||
err = spiflash_end(chip, err);
|
err = spiflash_end(chip, err);
|
||||||
|
|
||||||
|
#ifdef CONFIG_SPI_FLASH_YIELD_DURING_ERASE
|
||||||
|
no_yield_time_us += (esp_timer_get_time() - start_time_us);
|
||||||
|
if (no_yield_time_us / 1000 >= CONFIG_SPI_FLASH_ERASE_YIELD_DURATION_MS) {
|
||||||
|
no_yield_time_us = 0;
|
||||||
|
vTaskDelay(CONFIG_SPI_FLASH_ERASE_YIELD_TICKS);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -42,6 +42,7 @@
|
|||||||
#include "cache_utils.h"
|
#include "cache_utils.h"
|
||||||
#include "esp_flash.h"
|
#include "esp_flash.h"
|
||||||
#include "esp_attr.h"
|
#include "esp_attr.h"
|
||||||
|
#include "esp_timer.h"
|
||||||
|
|
||||||
|
|
||||||
/* bytes erased by SPIEraseBlock() ROM function */
|
/* bytes erased by SPIEraseBlock() ROM function */
|
||||||
@ -235,18 +236,34 @@ esp_err_t IRAM_ATTR spi_flash_erase_range(size_t start_addr, size_t size)
|
|||||||
esp_rom_spiflash_result_t rc;
|
esp_rom_spiflash_result_t rc;
|
||||||
rc = spi_flash_unlock();
|
rc = spi_flash_unlock();
|
||||||
if (rc == ESP_ROM_SPIFLASH_RESULT_OK) {
|
if (rc == ESP_ROM_SPIFLASH_RESULT_OK) {
|
||||||
|
#ifdef CONFIG_SPI_FLASH_YIELD_DURING_ERASE
|
||||||
|
int64_t no_yield_time_us = 0;
|
||||||
|
#endif
|
||||||
for (size_t sector = start; sector != end && rc == ESP_ROM_SPIFLASH_RESULT_OK; ) {
|
for (size_t sector = start; sector != end && rc == ESP_ROM_SPIFLASH_RESULT_OK; ) {
|
||||||
|
#ifdef CONFIG_SPI_FLASH_YIELD_DURING_ERASE
|
||||||
|
int64_t start_time_us = esp_timer_get_time();
|
||||||
|
#endif
|
||||||
spi_flash_guard_start();
|
spi_flash_guard_start();
|
||||||
|
#ifndef CONFIG_SPI_FLASH_BYPASS_BLOCK_ERASE
|
||||||
if (sector % sectors_per_block == 0 && end - sector >= sectors_per_block) {
|
if (sector % sectors_per_block == 0 && end - sector >= sectors_per_block) {
|
||||||
rc = esp_rom_spiflash_erase_block(sector / sectors_per_block);
|
rc = esp_rom_spiflash_erase_block(sector / sectors_per_block);
|
||||||
sector += sectors_per_block;
|
sector += sectors_per_block;
|
||||||
COUNTER_ADD_BYTES(erase, sectors_per_block * SPI_FLASH_SEC_SIZE);
|
COUNTER_ADD_BYTES(erase, sectors_per_block * SPI_FLASH_SEC_SIZE);
|
||||||
} else {
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
rc = esp_rom_spiflash_erase_sector(sector);
|
rc = esp_rom_spiflash_erase_sector(sector);
|
||||||
++sector;
|
++sector;
|
||||||
COUNTER_ADD_BYTES(erase, SPI_FLASH_SEC_SIZE);
|
COUNTER_ADD_BYTES(erase, SPI_FLASH_SEC_SIZE);
|
||||||
}
|
}
|
||||||
spi_flash_guard_end();
|
spi_flash_guard_end();
|
||||||
|
#ifdef CONFIG_SPI_FLASH_YIELD_DURING_ERASE
|
||||||
|
no_yield_time_us += (esp_timer_get_time() - start_time_us);
|
||||||
|
if (no_yield_time_us / 1000 >= CONFIG_SPI_FLASH_ERASE_YIELD_DURATION_MS) {
|
||||||
|
no_yield_time_us = 0;
|
||||||
|
vTaskDelay(CONFIG_SPI_FLASH_ERASE_YIELD_TICKS);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
COUNTER_STOP(erase);
|
COUNTER_STOP(erase);
|
||||||
|
@ -17,6 +17,7 @@ INCLUDE_DIRS := \
|
|||||||
app_update/include \
|
app_update/include \
|
||||||
driver/include \
|
driver/include \
|
||||||
esp32/include \
|
esp32/include \
|
||||||
|
esp_timer/include \
|
||||||
freertos/include \
|
freertos/include \
|
||||||
log/include \
|
log/include \
|
||||||
newlib/include \
|
newlib/include \
|
||||||
@ -31,6 +32,7 @@ INCLUDE_DIRS := \
|
|||||||
soc/esp32/include \
|
soc/esp32/include \
|
||||||
soc/include \
|
soc/include \
|
||||||
esp32/include \
|
esp32/include \
|
||||||
|
esp_timer/include \
|
||||||
bootloader_support/include \
|
bootloader_support/include \
|
||||||
app_update/include \
|
app_update/include \
|
||||||
spi_flash/include \
|
spi_flash/include \
|
||||||
|
@ -4,6 +4,7 @@ SOURCE_FILES := \
|
|||||||
newlib/lock.c \
|
newlib/lock.c \
|
||||||
esp32/crc.cpp \
|
esp32/crc.cpp \
|
||||||
esp32/esp_random.c \
|
esp32/esp_random.c \
|
||||||
|
esp_timer/src/esp_timer.c \
|
||||||
bootloader_support/src/bootloader_common.c
|
bootloader_support/src/bootloader_common.c
|
||||||
|
|
||||||
INCLUDE_DIRS := \
|
INCLUDE_DIRS := \
|
||||||
@ -12,6 +13,7 @@ INCLUDE_DIRS := \
|
|||||||
app_update/include \
|
app_update/include \
|
||||||
driver/include \
|
driver/include \
|
||||||
esp32/include \
|
esp32/include \
|
||||||
|
esp_timer/include \
|
||||||
freertos/include \
|
freertos/include \
|
||||||
log/include \
|
log/include \
|
||||||
newlib/include \
|
newlib/include \
|
||||||
@ -24,6 +26,7 @@ INCLUDE_DIRS := \
|
|||||||
xtensa/include \
|
xtensa/include \
|
||||||
xtensa/esp32/include \
|
xtensa/esp32/include \
|
||||||
esp32/include \
|
esp32/include \
|
||||||
|
esp_timer/include \
|
||||||
bootloader_support/include \
|
bootloader_support/include \
|
||||||
app_update/include \
|
app_update/include \
|
||||||
spi_flash/include \
|
spi_flash/include \
|
||||||
|
15
components/spi_flash/sim/stubs/esp_timer/include/esp_timer.h
Normal file
15
components/spi_flash/sim/stubs/esp_timer/include/esp_timer.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int64_t esp_timer_get_time(void);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
20
components/spi_flash/sim/stubs/esp_timer/src/esp_timer.c
Normal file
20
components/spi_flash/sim/stubs/esp_timer/src/esp_timer.c
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include "esp_timer.h"
|
||||||
|
|
||||||
|
int64_t esp_timer_get_time(void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user