From 643b0abca288934631df6de5368dfab9d34aa8d9 Mon Sep 17 00:00:00 2001 From: Cao Sen Miao Date: Thu, 12 Oct 2023 11:57:04 +0800 Subject: [PATCH] fix(ota): Fixed OTA fail on octal flash with 32MB memory, Closes https://github.com/espressif/esp-idf/issues/11903 --- .../include/bootloader_flash_override.h | 12 ++++++++ .../bootloader_flash_priv.h | 2 ++ .../bootloader_support/src/bootloader_flash.c | 28 ++++++++++++++++++ .../src/esp32s3/bootloader_esp32s3.c | 4 ++- components/spi_flash/Kconfig | 11 +++++++ .../spi_flash/esp32s3/spi_flash_rom_patch.c | 29 +++++++++++++++++++ 6 files changed, 85 insertions(+), 1 deletion(-) diff --git a/components/bootloader_support/include/bootloader_flash_override.h b/components/bootloader_support/include/bootloader_flash_override.h index ae29f00434..3650e28e0a 100644 --- a/components/bootloader_support/include/bootloader_flash_override.h +++ b/components/bootloader_support/include/bootloader_flash_override.h @@ -96,6 +96,18 @@ extern const bootloader_qio_info_t __attribute__((weak)) bootloader_flash_qe_sup */ esp_err_t IRAM_ATTR __attribute__((weak)) bootloader_flash_unlock(void); +#if CONFIG_SPI_FLASH_OCTAL_32BIT_ADDR_ENABLE +/** + * @brief Enable 32bits address flash(larger than 16MB) can map to cache. + * + * @param flash_mode SPI flash working mode. + * + * @note This can be overridden because it's attribute weak. + */ +void __attribute__((weak)) bootloader_flash_32bits_address_map_enable(esp_rom_spiflash_read_mode_t flash_mode); +#endif + + #ifdef __cplusplus } #endif diff --git a/components/bootloader_support/include_bootloader/bootloader_flash_priv.h b/components/bootloader_support/include_bootloader/bootloader_flash_priv.h index 98d0b26808..413e1ccf84 100644 --- a/components/bootloader_support/include_bootloader/bootloader_flash_priv.h +++ b/components/bootloader_support/include_bootloader/bootloader_flash_priv.h @@ -35,6 +35,8 @@ #define CMD_RDSFDP 0x5A /* Read the SFDP of the flash */ #define CMD_WRAP 0x77 /* Set burst with wrap command */ #define CMD_RESUME 0x7A /* Resume command to clear flash suspend bit */ +#define CMD_FASTRD_4B 0x0C +#define CMD_SLOWRD_4B 0x13 /* Provide a Flash API for bootloader_support code, diff --git a/components/bootloader_support/src/bootloader_flash.c b/components/bootloader_support/src/bootloader_flash.c index 3c971d3b7e..98cd822165 100644 --- a/components/bootloader_support/src/bootloader_flash.c +++ b/components/bootloader_support/src/bootloader_flash.c @@ -482,6 +482,34 @@ esp_err_t bootloader_flash_erase_range(uint32_t start_addr, uint32_t size) return spi_to_esp_err(rc); } +#if CONFIG_SPI_FLASH_OCTAL_32BIT_ADDR_ENABLE +void bootloader_flash_32bits_address_map_enable(esp_rom_spiflash_read_mode_t flash_mode) +{ + esp_rom_opiflash_spi0rd_t cache_rd = {}; + switch (flash_mode) { + case ESP_ROM_SPIFLASH_FASTRD_MODE: + cache_rd.addr_bit_len = 32; + cache_rd.dummy_bit_len = 8; + cache_rd.cmd = CMD_FASTRD_4B; + cache_rd.cmd_bit_len = 8; + break; + case ESP_ROM_SPIFLASH_SLOWRD_MODE: + cache_rd.addr_bit_len = 32; + cache_rd.dummy_bit_len = 0; + cache_rd.cmd = CMD_SLOWRD_4B; + cache_rd.cmd_bit_len = 8; + break; + default: + assert(false); + break; + } + cache_hal_disable(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL); + esp_rom_opiflash_cache_mode_config(flash_mode, &cache_rd); + cache_hal_enable(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_ALL); +} +#endif + + #endif // BOOTLOADER_BUILD diff --git a/components/bootloader_support/src/esp32s3/bootloader_esp32s3.c b/components/bootloader_support/src/esp32s3/bootloader_esp32s3.c index 732ff3a943..f61080f508 100644 --- a/components/bootloader_support/src/esp32s3/bootloader_esp32s3.c +++ b/components/bootloader_support/src/esp32s3/bootloader_esp32s3.c @@ -228,7 +228,9 @@ static esp_err_t bootloader_init_spi_flash(void) #if CONFIG_ESPTOOLPY_FLASHMODE_QIO || CONFIG_ESPTOOLPY_FLASHMODE_QOUT bootloader_enable_qio_mode(); #endif - +#if CONFIG_SPI_FLASH_OCTAL_32BIT_ADDR_ENABLE + bootloader_flash_32bits_address_map_enable(bootloader_flash_get_spi_mode()); +#endif print_flash_info(&bootloader_image_hdr); update_flash_config(&bootloader_image_hdr); //ensure the flash is write-protected diff --git a/components/spi_flash/Kconfig b/components/spi_flash/Kconfig index 89410b4acb..68096cbfb5 100644 --- a/components/spi_flash/Kconfig +++ b/components/spi_flash/Kconfig @@ -286,4 +286,15 @@ menu "SPI Flash driver" This option is invisible, and will be selected automatically when ``ESPTOOLPY_FLASHFREQ_120M`` is selected. + config SPI_FLASH_32BIT_ADDRESS + bool + default y if ESPTOOLPY_FLASHSIZE_32MB || ESPTOOLPY_FLASHSIZE_64MB || ESPTOOLPY_FLASHSIZE_128MB + default n + help + This is a helper config for 32bits address flash. Invisible for users. + + config SPI_FLASH_OCTAL_32BIT_ADDR_ENABLE + bool + default y if ESPTOOLPY_OCT_FLASH && SPI_FLASH_32BIT_ADDRESS + default n endmenu diff --git a/components/spi_flash/esp32s3/spi_flash_rom_patch.c b/components/spi_flash/esp32s3/spi_flash_rom_patch.c index a3a6079529..336499504d 100644 --- a/components/spi_flash/esp32s3/spi_flash_rom_patch.c +++ b/components/spi_flash/esp32s3/spi_flash_rom_patch.c @@ -4,3 +4,32 @@ * SPDX-License-Identifier: Apache-2.0 */ // We keep this file here only for future use + +#include "sdkconfig.h" +#include "soc/spi_periph.h" +#include "esp32s3/rom/spi_flash.h" +#include "esp32s3/rom/opi_flash.h" + +extern void esp_rom_spi_set_address_bit_len(int spi, int addr_bits); +void esp_rom_opiflash_cache_mode_config(esp_rom_spiflash_read_mode_t mode, const esp_rom_opiflash_spi0rd_t *cache) +{ + esp_rom_spi_set_op_mode(0, mode); + REG_CLR_BIT(SPI_MEM_USER_REG(0), SPI_MEM_USR_MOSI); + REG_SET_BIT(SPI_MEM_USER_REG(0), SPI_MEM_USR_MISO | SPI_MEM_USR_ADDR); + + if (cache) { + esp_rom_spi_set_address_bit_len(0, cache->addr_bit_len); + // Patch for ROM function `esp_rom_opiflash_cache_mode_config`, because when dummy is 0, + // `SPI_MEM_USR_DUMMY` should be 0. `esp_rom_opiflash_cache_mode_config` doesn't handle this + // properly. + if (cache->dummy_bit_len == 0) { + REG_CLR_BIT(SPI_MEM_USER_REG(0), SPI_MEM_USR_DUMMY); + } else { + REG_SET_BIT(SPI_MEM_USER_REG(0), SPI_MEM_USR_DUMMY); + REG_SET_FIELD(SPI_MEM_USER1_REG(0), SPI_MEM_USR_DUMMY_CYCLELEN, cache->dummy_bit_len - 1 + rom_spiflash_legacy_data->dummy_len_plus[0]); + } + REG_SET_FIELD(SPI_MEM_USER2_REG(0), SPI_MEM_USR_COMMAND_VALUE, cache->cmd); + REG_SET_FIELD(SPI_MEM_USER2_REG(0), SPI_MEM_USR_COMMAND_BITLEN, cache->cmd_bit_len - 1); + REG_SET_FIELD(SPI_MEM_DDR_REG(0), SPI_MEM_SPI_FMEM_VAR_DUMMY, cache->var_dummy_en); + } +}