From 4906779d50911dc96702b00ef4237c3d7566be33 Mon Sep 17 00:00:00 2001 From: Cao Sen Miao Date: Fri, 19 Mar 2021 17:39:56 +0800 Subject: [PATCH] spi_flash: make suspend off by default and add more information for using suspend --- components/spi_flash/Kconfig | 9 ++++++--- components/spi_flash/esp_flash_api.c | 1 + components/spi_flash/spi_flash_chip_boya.c | 8 +------- components/spi_flash/spi_flash_chip_gd.c | 14 +------------- components/spi_flash/spi_flash_chip_generic.c | 9 +++++++-- components/spi_flash/spi_flash_chip_issi.c | 14 +------------- components/spi_flash/spi_flash_chip_mxic.c | 14 +------------- docs/en/api-reference/storage/auto_suspend.inc | 12 ++++++++++++ docs/zh_CN/api-reference/storage/auto_suspend.inc | 9 +++++++++ 9 files changed, 39 insertions(+), 51 deletions(-) diff --git a/components/spi_flash/Kconfig b/components/spi_flash/Kconfig index 1853d0cc6c..ed1d2ec3d7 100644 --- a/components/spi_flash/Kconfig +++ b/components/spi_flash/Kconfig @@ -148,9 +148,8 @@ menu "SPI Flash driver" Defines how many ticks will be before returning to continue a erasing. config SPI_FLASH_AUTO_SUSPEND - bool "Auto suspend long erase/write operations" - default n if !IDF_TARGET_ESP32C3 - default y if IDF_TARGET_ESP32C3 + bool "Auto suspend long erase/write operations (READ DOCS FIRST)" + default n depends on IDF_TARGET_ESP32C3 && !SPI_FLASH_USE_LEGACY_IMPL && !SPI_FLASH_ROM_IMPL help This option is default n before ESP32-C3, because it needs bootloader support. @@ -158,6 +157,10 @@ menu "SPI Flash driver" CAUTION: If you want to OTA to an app with this feature turned on, please make sure the bootloader has the support for it. (later than IDF v4.3) + Auto-suspend feature is only supported by XMC chip. + If you are using an official module, please contact Espressif Business support. + Also reading auto suspend part in `SPI Flash API` document before you enable this function. + config SPI_FLASH_WRITE_CHUNK_SIZE int "Flash write chunk size" default 8192 diff --git a/components/spi_flash/esp_flash_api.c b/components/spi_flash/esp_flash_api.c index b47b0afadd..68b1935daf 100644 --- a/components/spi_flash/esp_flash_api.c +++ b/components/spi_flash/esp_flash_api.c @@ -836,6 +836,7 @@ IRAM_ATTR esp_err_t esp_flash_set_io_mode(esp_flash_t* chip, bool qe) //init suspend mode cmd, uses internal. esp_err_t esp_flash_suspend_cmd_init(esp_flash_t* chip) { + ESP_EARLY_LOGW(TAG, "Flash suspend feature is enabled"); return chip->chip_drv->sus_setup(chip); } diff --git a/components/spi_flash/spi_flash_chip_boya.c b/components/spi_flash/spi_flash_chip_boya.c index 57e20e7b83..c51fef69f9 100644 --- a/components/spi_flash/spi_flash_chip_boya.c +++ b/components/spi_flash/spi_flash_chip_boya.c @@ -17,12 +17,6 @@ #include "spi_flash_chip_gd.h" #include "spi_flash_defs.h" -/* Driver for BOYA flash chip */ -esp_err_t spi_flash_chip_gd_suspend_cmd_conf(esp_flash_t *chip); - -// Use the same implementation as GD chips -#define spi_flash_chip_boya_suspend_cmd_conf spi_flash_chip_gd_suspend_cmd_conf - esp_err_t spi_flash_chip_boya_probe(esp_flash_t *chip, uint32_t flash_id) { /* Check manufacturer and product IDs match our desired masks */ @@ -76,5 +70,5 @@ const spi_flash_chip_t esp_flash_chip_boya = { .read_reg = spi_flash_chip_generic_read_reg, .yield = spi_flash_chip_generic_yield, - .sus_setup = spi_flash_chip_boya_suspend_cmd_conf, + .sus_setup = spi_flash_chip_generic_suspend_cmd_conf, }; diff --git a/components/spi_flash/spi_flash_chip_gd.c b/components/spi_flash/spi_flash_chip_gd.c index 54a2255566..9e1e580b75 100644 --- a/components/spi_flash/spi_flash_chip_gd.c +++ b/components/spi_flash/spi_flash_chip_gd.c @@ -75,18 +75,6 @@ esp_err_t spi_flash_chip_gd_get_io_mode(esp_flash_t *chip, esp_flash_io_mode_t* } #endif //CONFIG_SPI_FLASH_ROM_IMPL -esp_err_t spi_flash_chip_gd_suspend_cmd_conf(esp_flash_t *chip) -{ - spi_flash_sus_cmd_conf sus_conf = { - .sus_mask = 0x84, - .cmd_rdsr = CMD_RDSR2, - .sus_cmd = CMD_SUSPEND, - .res_cmd = CMD_RESUME, - }; - - return chip->host->driver->sus_setup(chip->host, &sus_conf); -} - static const char chip_name[] = "gd"; // The issi chip can use the functions for generic chips except from set read mode and probe, @@ -123,5 +111,5 @@ const spi_flash_chip_t esp_flash_chip_gd = { .read_reg = spi_flash_chip_generic_read_reg, .yield = spi_flash_chip_generic_yield, - .sus_setup = spi_flash_chip_gd_suspend_cmd_conf, + .sus_setup = spi_flash_chip_generic_suspend_cmd_conf, }; diff --git a/components/spi_flash/spi_flash_chip_generic.c b/components/spi_flash/spi_flash_chip_generic.c index e4011ff67b..2426013e03 100644 --- a/components/spi_flash/spi_flash_chip_generic.c +++ b/components/spi_flash/spi_flash_chip_generic.c @@ -58,10 +58,10 @@ const DRAM_ATTR flash_chip_op_timeout_t spi_flash_chip_generic_timeout = { .page_program_timeout = SPI_FLASH_GENERIC_PAGE_PROGRAM_TIMEOUT_MS * 1000, }; -#ifndef CONFIG_SPI_FLASH_ROM_IMPL - static const char TAG[] = "chip_generic"; +#ifndef CONFIG_SPI_FLASH_ROM_IMPL + esp_err_t spi_flash_chip_generic_probe(esp_flash_t *chip, uint32_t flash_id) { // This is the catch-all probe function, claim the chip always if nothing @@ -645,6 +645,11 @@ esp_err_t spi_flash_common_set_io_mode(esp_flash_t *chip, esp_flash_wrsr_func_t esp_err_t spi_flash_chip_generic_suspend_cmd_conf(esp_flash_t *chip) { + // Only XMC support auto-suspend + if (chip->chip_id >> 16 != 0x20) { + ESP_EARLY_LOGE(TAG, "The flash you use doesn't support auto suspend, only \'XMC\' is supported"); + return ESP_ERR_NOT_SUPPORTED; + } spi_flash_sus_cmd_conf sus_conf = { .sus_mask = 0x80, .cmd_rdsr = CMD_RDSR2, diff --git a/components/spi_flash/spi_flash_chip_issi.c b/components/spi_flash/spi_flash_chip_issi.c index b5cdbcb326..f47d356a6f 100644 --- a/components/spi_flash/spi_flash_chip_issi.c +++ b/components/spi_flash/spi_flash_chip_issi.c @@ -58,18 +58,6 @@ esp_err_t spi_flash_chip_issi_get_io_mode(esp_flash_t *chip, esp_flash_io_mode_t return ret; } -esp_err_t spi_flash_chip_issi_suspend_cmd_conf(esp_flash_t *chip) -{ - spi_flash_sus_cmd_conf sus_conf = { - .sus_mask = 0x06, - .cmd_rdsr = CMD_RDFR, - .sus_cmd = CMD_SUSPEND, - .res_cmd = CMD_RESUME, - }; - - return chip->host->driver->sus_setup(chip->host, &sus_conf); -} - static const char chip_name[] = "issi"; // The issi chip can use the functions for generic chips except from set read mode and probe, @@ -106,5 +94,5 @@ const spi_flash_chip_t esp_flash_chip_issi = { .read_reg = spi_flash_chip_generic_read_reg, .yield = spi_flash_chip_generic_yield, - .sus_setup = spi_flash_chip_issi_suspend_cmd_conf, + .sus_setup = spi_flash_chip_generic_suspend_cmd_conf, }; diff --git a/components/spi_flash/spi_flash_chip_mxic.c b/components/spi_flash/spi_flash_chip_mxic.c index ed19db7611..8c0cd9a2dc 100644 --- a/components/spi_flash/spi_flash_chip_mxic.c +++ b/components/spi_flash/spi_flash_chip_mxic.c @@ -39,18 +39,6 @@ esp_err_t spi_flash_chip_issi_get_io_mode(esp_flash_t *chip, esp_flash_io_mode_t static const char chip_name[] = "mxic"; -esp_err_t spi_flash_chip_mxic_suspend_cmd_conf(esp_flash_t *chip) -{ - spi_flash_sus_cmd_conf sus_conf = { - .sus_mask = 0x06, - .cmd_rdsr = CMD_RDSCUR, - .sus_cmd = CMD_SUSPEND, - .res_cmd = CMD_RESUME, - }; - - return chip->host->driver->sus_setup(chip->host, &sus_conf); -} - // The mxic chip can use the functions for generic chips except from set read mode and probe, // So we only replace these two functions. const spi_flash_chip_t esp_flash_chip_mxic = { @@ -85,5 +73,5 @@ const spi_flash_chip_t esp_flash_chip_mxic = { .read_reg = spi_flash_chip_mxic_read_reg, .yield = spi_flash_chip_generic_yield, - .sus_setup = spi_flash_chip_mxic_suspend_cmd_conf, + .sus_setup = spi_flash_chip_generic_suspend_cmd_conf, }; diff --git a/docs/en/api-reference/storage/auto_suspend.inc b/docs/en/api-reference/storage/auto_suspend.inc index a46217418e..43bd20c0b1 100644 --- a/docs/en/api-reference/storage/auto_suspend.inc +++ b/docs/en/api-reference/storage/auto_suspend.inc @@ -3,6 +3,18 @@ When auto suspend is enabled ---------------------------- +.. important:: + + The flash chip you are using must have suspend/resume function, even then, and not all flash chips with suspend/resume support auto-suspend on {IDF_TARGET_NAME}. If you use suspend feature on a unsupported chip, it may cause a severe crash. Therefore, we strongly suggest you reading the flash chip datasheets first. Ensure the flash chip satisfies the following conditions at minimum. Even then, thorough testing is recommended. + + 1. SUS bit in status registers should in SR2 bit7 (or SR bit15)(This is caused by the restriction of out software implementation). + + 2. Suspend command is 75H, resume command is 7AH(This is caused by the restriction of out software implementation). + + 3. When the flash is successfully suspended, all address of the flash, except from the section/block being erased, can be read correctly. And resume can be sent immediately at this state. + + 4. When the flash is successfully resumed, another suspend can be sent immediately at this state. + When auto suspend is enabled, the cache will be kept enabled while accessing the SPI1 bus (e.g. erasing/writing/reading main flash). The hardware handles the arbitration between them. If SPI1 operation is short (like reading operation), the CPU and the cache will wait until the SPI1 operation is done. However if it's an erasing, auto suspend will happen, interrupting the erasing, making the CPU able to read from cache in limited time. diff --git a/docs/zh_CN/api-reference/storage/auto_suspend.inc b/docs/zh_CN/api-reference/storage/auto_suspend.inc index 425d67bdf2..efdc508795 100644 --- a/docs/zh_CN/api-reference/storage/auto_suspend.inc +++ b/docs/zh_CN/api-reference/storage/auto_suspend.inc @@ -4,6 +4,15 @@ 当使能 flash 擦除的自动暂停 -------------------------------------- +.. important: + + 您使用的 flash 需要有 suspend/resume 功能,而且不是所有具备 suspend/resume 的 flash 都可以在 {IDF_TARGET_NAME} 上使用自动暂停功能。如果您在不支持自动暂停的 flash 上使用该功能,可能会造成严重的程序崩溃。因此,我们强烈建议您在使用前阅读对应的 flash 的数据手册,确保您的 flash 可以满足如下条件, 即使这样,我们也建议您对 flash 做完整的测试: + + 1. flash 状态寄存器中的 SUS bit 应当位于 SR2 bit7 ( 或者是 SR bit15 )(这是当前软件的实现限制)。 + 2. 暂停的命令是 75H,恢复的命令是 7AH(这是当前软件的实现限制)。 + 3. 当 flash 芯片成功暂停之后,除了正在被擦除的段或块外的任何 flash 地址中的的内容,都可以被正确的读取。恢复命令也可以在这种状态下立即下达。 + 4. 当 flash 已经从暂停的模式恢复后,另一个暂停命令可以立即下达。 + 当使能 flash 擦除的自动暂停,访问 SPI1 时(如擦除、写入、读取主 flash ) cache 便无需被禁用。硬件会负责仲裁二者的访问。 当 SPI1 操作较短时(如读取操作), CPU 和 cache 会等待直到 SPI1 的操作结束。然而对于一个擦除操作,自动暂停会发生并打断擦除操作,允许 CPU 能够在有限时间内从 cache 读取数据。