diff --git a/components/esp32/include/rom/spi_flash.h b/components/esp32/include/rom/spi_flash.h index a6ed793d6c..fab768bab2 100644 --- a/components/esp32/include/rom/spi_flash.h +++ b/components/esp32/include/rom/spi_flash.h @@ -538,6 +538,13 @@ esp_rom_spiflash_result_t esp_rom_spiflash_wait_idle(esp_rom_spiflash_chip_t *sp */ void esp_rom_spiflash_select_qio_pins(uint8_t wp_gpio_num, uint32_t spiconfig); +/** + * @brief Clear WEL bit unconditionally. + * + * @return always ESP_ROM_SPIFLASH_RESULT_OK + */ +esp_rom_spiflash_result_t esp_rom_spiflash_write_disable(void); + /** @brief Global esp_rom_spiflash_chip_t structure used by ROM functions * */ diff --git a/components/spi_flash/flash_ops.c b/components/spi_flash/flash_ops.c index 420399269c..8593f444d7 100644 --- a/components/spi_flash/flash_ops.c +++ b/components/spi_flash/flash_ops.c @@ -267,6 +267,8 @@ esp_err_t IRAM_ATTR spi_flash_erase_range(uint32_t start_addr, uint32_t size) COUNTER_STOP(erase); spi_flash_guard_start(); + // Ensure WEL is 0 after the operation, even if the erase failed. + esp_rom_spiflash_write_disable(); spi_flash_check_and_flush_cache(start_addr, size); spi_flash_guard_end(); @@ -437,6 +439,8 @@ out: COUNTER_STOP(write); spi_flash_guard_start(); + // Ensure WEL is 0 after the operation, even if the write failed. + esp_rom_spiflash_write_disable(); spi_flash_check_and_flush_cache(dst, size); spi_flash_guard_end(); @@ -503,6 +507,7 @@ esp_err_t IRAM_ATTR spi_flash_write_encrypted(size_t dest_addr, const void *src, COUNTER_STOP(write); spi_flash_guard_start(); + esp_rom_spiflash_write_disable(); spi_flash_check_and_flush_cache(dest_addr, size); spi_flash_guard_end(); diff --git a/components/spi_flash/sim/flash_mock.cpp b/components/spi_flash/sim/flash_mock.cpp index 502f6df994..4fb96ab6cb 100644 --- a/components/spi_flash/sim/flash_mock.cpp +++ b/components/spi_flash/sim/flash_mock.cpp @@ -109,3 +109,8 @@ void *heap_caps_malloc( size_t size, uint32_t caps ) { return NULL; } + +esp_rom_spiflash_result_t esp_rom_spiflash_write_disable(void) +{ + return ESP_ROM_SPIFLASH_RESULT_OK; +} diff --git a/components/spi_flash/spi_flash_rom_patch.c b/components/spi_flash/spi_flash_rom_patch.c index 2d585ba440..2837fe18b4 100644 --- a/components/spi_flash/spi_flash_rom_patch.c +++ b/components/spi_flash/spi_flash_rom_patch.c @@ -65,19 +65,20 @@ esp_rom_spiflash_result_t esp_rom_spiflash_unlock() (This is different from ROM esp_rom_spiflash_unlock, which keeps all bits as-is.) */ status &= ESP_ROM_SPIFLASH_QE; + SET_PERI_REG_MASK(SPI_CTRL_REG(SPI_IDX), SPI_WRSR_2B); esp_rom_spiflash_wait_idle(&g_rom_spiflash_chip); REG_WRITE(SPI_CMD_REG(SPI_IDX), SPI_FLASH_WREN); while (REG_READ(SPI_CMD_REG(SPI_IDX)) != 0) { } esp_rom_spiflash_wait_idle(&g_rom_spiflash_chip); - - SET_PERI_REG_MASK(SPI_CTRL_REG(SPI_IDX), SPI_WRSR_2B); - if (esp_rom_spiflash_write_status(&g_rom_spiflash_chip, status) != ESP_ROM_SPIFLASH_RESULT_OK) { - return ESP_ROM_SPIFLASH_RESULT_ERR; + esp_rom_spiflash_result_t ret = esp_rom_spiflash_write_status(&g_rom_spiflash_chip, status); + // WEL bit should be cleared after operations regardless of writing succeed or not. + esp_rom_spiflash_wait_idle(&g_rom_spiflash_chip); + REG_WRITE(SPI_CMD_REG(SPI_IDX), SPI_FLASH_WRDI); + while (REG_READ(SPI_CMD_REG(SPI_IDX)) != 0) { } - - return ESP_ROM_SPIFLASH_RESULT_OK; + return ret; } @@ -660,4 +661,11 @@ esp_rom_spiflash_result_t esp_rom_spiflash_erase_area(uint32_t start_addr, uint3 return ESP_ROM_SPIFLASH_RESULT_OK; } +esp_rom_spiflash_result_t esp_rom_spiflash_write_disable(void) +{ + REG_WRITE(SPI_CMD_REG(SPI_IDX), SPI_FLASH_WRDI); + while (READ_PERI_REG(PERIPHS_SPI_FLASH_CMD) != 0); + return ESP_ROM_SPIFLASH_RESULT_OK; +} + #endif