feat(bootloader): Initialize SPI flash clock and I/O mode at bootloader

This commit is contained in:
Dong Heng
2018-11-05 19:34:32 +08:00
parent 14d8307dc2
commit d5b14d7427
8 changed files with 108 additions and 108 deletions

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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 */

View File

@ -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++)

View File

@ -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

View File

@ -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\"

View File

@ -15,6 +15,8 @@
#include <string.h>
#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();
}