diff --git a/components/bootloader/Kconfig.projbuild b/components/bootloader/Kconfig.projbuild index 5efa1dc3..3e03ba91 100644 --- a/components/bootloader/Kconfig.projbuild +++ b/components/bootloader/Kconfig.projbuild @@ -1,4 +1,15 @@ menu "Bootloader config" + +config BOOTLOADER_INIT_SPI_FLASH + bool "Bootloader init SPI flash" + default y + help + Enable this option, software will initialize SPI flash clock and I/O mode at bootloader instead of at APP. + So it will speed up system starting and reduce the time cost at loading firmware. + + If your system bootloader is based on v3.0, the option must not be enable, because the v3.0 bootloader don't support + this function. + choice LOG_BOOTLOADER_LEVEL bool "Bootloader log verbosity" default LOG_BOOTLOADER_LEVEL_INFO diff --git a/components/bootloader_support/src/bootloader_init.c b/components/bootloader_support/src/bootloader_init.c index a7e518bb..52eea185 100644 --- a/components/bootloader_support/src/bootloader_init.c +++ b/components/bootloader_support/src/bootloader_init.c @@ -619,46 +619,26 @@ static esp_err_t bootloader_main() return ESP_FAIL; } + update_flash_config(&fhdr); + ESP_LOGI(TAG, "ESP-IDF %s 2nd stage bootloader", IDF_VER); ESP_LOGI(TAG, "compile time " __TIME__ ); print_flash_info(&fhdr); - update_flash_config(&fhdr); - return ESP_OK; } static void update_flash_config(const esp_image_header_t* pfhdr) { - // uint32_t size; - // switch(pfhdr->spi_size) { - // case ESP_IMAGE_FLASH_SIZE_1MB: - // size = 1; - // break; - // case ESP_IMAGE_FLASH_SIZE_2MB: - // case ESP_IMAGE_FLASH_SIZE_2MB_C1: - // size = 2; - // break; - // case ESP_IMAGE_FLASH_SIZE_4MB: - // case ESP_IMAGE_FLASH_SIZE_4MB_C1: - // size = 4; - // break; - // case ESP_IMAGE_FLASH_SIZE_8MB: - // size = 8; - // break; - // case ESP_IMAGE_FLASH_SIZE_16MB: - // size = 16; - // break; - // default: - // size = 2; - // } +#ifdef CONFIG_BOOTLOADER_INIT_SPI_FLASH + extern void esp_spi_flash_init(uint32_t spi_speed, uint32_t spi_mode); - // Set flash chip size -// esp_rom_spiflash_config_param(g_rom_flashchip.device_id, size * 0x100000, 0x10000, 0x1000, 0x100, 0xffff); - // TODO: set mode - // TODO: set frequency + esp_spi_flash_init(pfhdr->spi_speed, pfhdr->spi_mode); + + ESP_LOGD(TAG, "bootloader initialize SPI flash clock and I/O"); +#endif /* CONFIG_BOOTLOADER_INIT_SPI_FLASH */ } static void print_flash_info(const esp_image_header_t* phdr) diff --git a/components/esp8266/include/driver/spi_register.h b/components/esp8266/include/driver/spi_register.h index 9591c382..48051aa7 100644 --- a/components/esp8266/include/driver/spi_register.h +++ b/components/esp8266/include/driver/spi_register.h @@ -256,4 +256,8 @@ #define PERIPHS_SPI_FLASH_CTRL SPI_CTRL(SPI) #define PERIPHS_SPI_FLASH_CMD SPI_CMD(SPI) +#define SPI0_CLK_EQU_SYSCLK BIT8 + +#define PERIPHS_SPI_FLASH_USRREG (0x60000200 + 0x1c) + #endif // SPI_REGISTER_H_INCLUDED diff --git a/components/esp8266/source/chip_boot.c b/components/esp8266/source/chip_boot.c index 0ca7ff5b..9ced7620 100644 --- a/components/esp8266/source/chip_boot.c +++ b/components/esp8266/source/chip_boot.c @@ -13,86 +13,17 @@ // limitations under the License. #include "sdkconfig.h" -#include "esp_attr.h" + +#ifndef CONFIG_BOOTLOADER_INIT_SPI_FLASH #include "spi_flash.h" -#include "esp_log.h" -#include "esp_system.h" -#include "esp8266/eagle_soc.h" -#include "esp8266/rom_functions.h" -#include "esp_image_format.h" - -#define PERIPHS_SPI_FLASH_USRREG (0x60000200 + 0x1c) -#define PERIPHS_SPI_FLASH_CTRL (0x60000200 + 0x08) -#define PERIPHS_IO_MUX_CONF_U (0x60000800) - -#define SPI0_CLK_EQU_SYSCLK BIT8 -#define SPI_FLASH_CLK_EQU_SYSCLK BIT12 - -static const char *TAG = "chip_boot"; /* - * @brief initialize the chip including flash I/O and chip cache according to - * boot parameters which are stored at the flash + * @brief initialize the chip */ -void chip_boot(size_t start_addr) +void chip_boot(void) { - int ret; - uint32_t freqdiv, flash_size; - uint32_t freqbits; - esp_image_header_t fhdr; + extern void esp_spi_flash_init(uint32_t spi_speed, uint32_t spi_mode); - uint32_t flash_map_table[FALSH_SIZE_MAP_MAX] = { - 1 * 1024 * 1024, - 2 * 1024 * 1024, - 4 * 1024 * 1024, - 8 * 1024 * 1024, - 16 * 1024 * 1024 - }; - uint32_t flash_map_table_size = sizeof(flash_map_table) / sizeof(flash_map_table[0]); - - extern esp_spi_flash_chip_t flashchip; - extern void phy_get_bb_evm(void); - extern void cache_init(uint8_t); - extern void user_spi_flash_dio_to_qio_pre_init(void); - - phy_get_bb_evm(); - - SET_PERI_REG_MASK(PERIPHS_SPI_FLASH_USRREG, BIT5); - - ret = spi_flash_read(start_addr, &fhdr, sizeof(esp_image_header_t)); - if (ret) { - ESP_EARLY_LOGE(TAG, "SPI flash read result %d\n", ret); - } - - if (3 > fhdr.spi_speed) - freqdiv = fhdr.spi_speed + 2; - else if (0x0F == fhdr.spi_speed) - freqdiv = 1; - else - freqdiv = 2; - - if (fhdr.spi_size < flash_map_table_size) { - flash_size = flash_map_table[fhdr.spi_size]; - ESP_EARLY_LOGD(TAG, "SPI flash size is %d\n", flash_size); - } else { - flash_size = 0; - ESP_EARLY_LOGE(TAG, "SPI size error is %d\n", fhdr.spi_size); - } - flashchip.chip_size = flash_size; - - if (1 >= freqdiv) { - freqbits = SPI_FLASH_CLK_EQU_SYSCLK; - SET_PERI_REG_MASK(PERIPHS_SPI_FLASH_CTRL, SPI_FLASH_CLK_EQU_SYSCLK); - SET_PERI_REG_MASK(PERIPHS_IO_MUX_CONF_U, SPI0_CLK_EQU_SYSCLK); - } else { - freqbits = ((freqdiv - 1) << 8) + ((freqdiv / 2 - 1) << 4) + (freqdiv - 1); - CLEAR_PERI_REG_MASK(PERIPHS_SPI_FLASH_CTRL, SPI_FLASH_CLK_EQU_SYSCLK); - CLEAR_PERI_REG_MASK(PERIPHS_IO_MUX_CONF_U, SPI0_CLK_EQU_SYSCLK); - } - SET_PERI_REG_BITS(PERIPHS_SPI_FLASH_CTRL, 0xfff, freqbits, 0); - - if (fhdr.spi_mode == ESP_IMAGE_SPI_MODE_QIO) { - ESP_EARLY_LOGD(TAG, "SPI flash enable QIO mode\n"); - user_spi_flash_dio_to_qio_pre_init(); - } + esp_spi_flash_init(CONFIG_SPI_FLASH_FREQ, CONFIG_SPI_FLASH_MODE); } +#endif /* CONFIG_BOOTLOADER_INIT_SPI_FLASH */ diff --git a/components/esp8266/source/startup.c b/components/esp8266/source/startup.c index a9be9235..994393cb 100644 --- a/components/esp8266/source/startup.c +++ b/components/esp8266/source/startup.c @@ -33,7 +33,7 @@ #define FLASH_MAP_ADDR 0x40200000 #define FLASH_MAP_SIZE 0x00100000 -extern void chip_boot(size_t start_addr); +extern void chip_boot(void); extern int rtc_init(void); extern int mac_init(void); extern int base_gpio_init(void); @@ -41,6 +41,7 @@ extern int watchdog_init(void); extern int wifi_timer_init(void); extern int wifi_nvs_init(void); extern esp_err_t esp_pthread_init(void); +extern void phy_get_bb_evm(void); static void user_init_entry(void *param) { @@ -55,6 +56,8 @@ static void user_init_entry(void *param) for (func = &__init_array_start; func < &__init_array_end; func++) func[0](); + phy_get_bb_evm(); + assert(nvs_flash_init() == 0); assert(wifi_nvs_init() == 0); assert(rtc_init() == 0); @@ -108,7 +111,9 @@ void call_user_start(size_t start_addr) "wsr a0, vecbase\n" : : :"memory"); - chip_boot(start_addr); +#ifndef CONFIG_BOOTLOADER_INIT_SPI_FLASH + chip_boot(); +#endif /* clear bss data */ for (p = &_bss_start; p < &_bss_end; p++) diff --git a/components/esptool_py/Kconfig.projbuild b/components/esptool_py/Kconfig.projbuild index 7b29f4e3..63ff90c3 100644 --- a/components/esptool_py/Kconfig.projbuild +++ b/components/esptool_py/Kconfig.projbuild @@ -63,6 +63,14 @@ config FLASHMODE_DOUT bool "DOUT" endchoice +config FLASHMODE_SWITCH_TO_QIO + bool "Try to switch to QIO mode at startup" + default y + depends on FLASHMODE_DIO + help + If users use SPI flash DIO mode to download firmware, bootloader or application + can switch to QIO mode by enable this option. + # Note: we use esptool.py to flash bootloader in # dio mode for QIO/QOUT, bootloader then upgrades # itself to quad mode during initialisation @@ -73,6 +81,13 @@ config ESPTOOLPY_FLASHMODE default "dio" if FLASHMODE_DIO default "dout" if FLASHMODE_DOUT +config SPI_FLASH_MODE + hex + default 0x0 if FLASHMODE_QIO + default 0x1 if FLASHMODE_QOUT + default 0x2 if FLASHMODE_DIO + default 0x3 if FLASHMODE_DOUT + choice ESPTOOLPY_FLASHFREQ prompt "Flash SPI speed" default ESPTOOLPY_FLASHFREQ_40M @@ -96,6 +111,12 @@ config ESPTOOLPY_FLASHFREQ default "26m" if ESPTOOLPY_FLASHFREQ_26M default "20m" if ESPTOOLPY_FLASHFREQ_20M +config SPI_FLASH_FREQ + hex + default 0xf if ESPTOOLPY_FLASHFREQ_80M + default 0x0 if ESPTOOLPY_FLASHFREQ_40M + default 0x1 if ESPTOOLPY_FLASHFREQ_26M + default 0x2 if ESPTOOLPY_FLASHFREQ_20M choice ESPTOOLPY_FLASHSIZE prompt "Flash size" @@ -122,6 +143,14 @@ config ESPTOOLPY_FLASHSIZE default "8MB" if ESPTOOLPY_FLASHSIZE_8MB default "16MB" if ESPTOOLPY_FLASHSIZE_16MB +config SPI_FLASH_SIZE + hex + default 0x100000 if ESPTOOLPY_FLASHSIZE_1MB + default 0x200000 if ESPTOOLPY_FLASHSIZE_2MB + default 0x400000 if ESPTOOLPY_FLASHSIZE_4MB + default 0x800000 if ESPTOOLPY_FLASHSIZE_8MB + default 0x1000000 if ESPTOOLPY_FLASHSIZE_16MB + choice ESPTOOLPY_BEFORE prompt "Before flashing" default ESPTOOLPY_BEFORE_RESET diff --git a/components/spi_flash/component.mk b/components/spi_flash/component.mk index 6ec0f676..3172f3eb 100644 --- a/components/spi_flash/component.mk +++ b/components/spi_flash/component.mk @@ -2,8 +2,10 @@ # Component Makefile # -ifndef IS_BOOTLOADER_BUILD COMPONENT_SRCDIRS := src + +ifdef IS_BOOTLOADER_BUILD +COMPONENT_OBJS := src/spi_flash.o src/spi_flash_raw.o endif CFLAGS += -DPARTITION_QUEUE_HEADER=\"sys/queue.h\" diff --git a/components/spi_flash/src/spi_flash.c b/components/spi_flash/src/spi_flash.c index c82be03d..22aeec04 100644 --- a/components/spi_flash/src/spi_flash.c +++ b/components/spi_flash/src/spi_flash.c @@ -15,6 +15,8 @@ #include #include "spi_flash.h" +#include "driver/spi_register.h" +#include "esp8266/pin_mux_register.h" #include "priv/esp_spi_flash_raw.h" #include "esp_attr.h" @@ -43,9 +45,15 @@ #define SPI_FLASH_RDSR2 0x35 #define SPI_FLASH_PROTECT_STATUS (BIT(2)|BIT(3)|BIT(4)|BIT(5)|BIT(6)|BIT(14)) +#ifndef BOOTLOADER_BUILD #define FLASH_INTR_DECLARE(t) #define FLASH_INTR_LOCK(t) vPortEnterCritical() #define FLASH_INTR_UNLOCK(t) vPortExitCritical() +#else +#define FLASH_INTR_DECLARE(t) +#define FLASH_INTR_LOCK(t) +#define FLASH_INTR_UNLOCK(t) +#endif #define FLASH_ALIGN_BYTES 4 #define FLASH_ALIGN(addr) ((((size_t)addr) + (FLASH_ALIGN_BYTES - 1)) & (~(FLASH_ALIGN_BYTES - 1))) @@ -61,7 +69,7 @@ extern void vPortExitCritical(void); esp_spi_flash_chip_t flashchip = { 0x1640ef, - (32 / 8) * 1024 * 1024, + CONFIG_SPI_FLASH_SIZE, 64 * 1024, 4 * 1024, 256, @@ -720,3 +728,33 @@ esp_err_t spi_flash_erase_range(size_t start_address, size_t size) return ret; } + +void esp_spi_flash_init(uint32_t spi_speed, uint32_t spi_mode) +{ + uint32_t freqdiv, freqbits; + + SET_PERI_REG_MASK(PERIPHS_SPI_FLASH_USRREG, BIT5); + + if (spi_speed < 3) + freqdiv = spi_speed + 2; + else if (0x0F == spi_speed) + freqdiv = 1; + else + freqdiv = 2; + + if (1 >= freqdiv) { + freqbits = SPI_FLASH_CLK_EQU_SYSCLK; + SET_PERI_REG_MASK(PERIPHS_SPI_FLASH_CTRL, SPI_FLASH_CLK_EQU_SYSCLK); + SET_PERI_REG_MASK(PERIPHS_IO_MUX_CONF_U, SPI0_CLK_EQU_SYSCLK); + } else { + freqbits = ((freqdiv - 1) << 8) + ((freqdiv / 2 - 1) << 4) + (freqdiv - 1); + CLEAR_PERI_REG_MASK(PERIPHS_SPI_FLASH_CTRL, SPI_FLASH_CLK_EQU_SYSCLK); + CLEAR_PERI_REG_MASK(PERIPHS_IO_MUX_CONF_U, SPI0_CLK_EQU_SYSCLK); + } + SET_PERI_REG_BITS(PERIPHS_SPI_FLASH_CTRL, 0xfff, freqbits, 0); + +#ifndef CONFIG_FLASHMODE_SWITCH_TO_QIO + if (spi_mode == 0) +#endif + user_spi_flash_dio_to_qio_pre_init(); +}