2021-05-10 04:56:51 +02:00
|
|
|
/*
|
|
|
|
|
* SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD
|
|
|
|
|
*
|
|
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
|
|
|
*/
|
2019-12-12 19:03:25 +08:00
|
|
|
#include <stdint.h>
|
|
|
|
|
#include "sdkconfig.h"
|
|
|
|
|
#include "esp_attr.h"
|
|
|
|
|
#include "esp_log.h"
|
|
|
|
|
#include "esp_image_format.h"
|
|
|
|
|
#include "flash_qio_mode.h"
|
2019-10-02 19:19:26 +02:00
|
|
|
|
2019-12-12 19:03:25 +08:00
|
|
|
#include "bootloader_init.h"
|
|
|
|
|
#include "bootloader_clock.h"
|
2019-05-27 14:29:43 +08:00
|
|
|
#include "bootloader_common.h"
|
2019-12-12 19:03:25 +08:00
|
|
|
#include "bootloader_flash_config.h"
|
2020-02-03 18:12:32 +08:00
|
|
|
#include "bootloader_mem.h"
|
2020-04-30 15:29:23 +02:00
|
|
|
#include "bootloader_console.h"
|
2020-07-13 03:23:12 +08:00
|
|
|
#include "bootloader_flash_priv.h"
|
2019-12-12 19:03:25 +08:00
|
|
|
|
2021-12-14 10:08:15 +05:30
|
|
|
#include "esp_cpu.h"
|
2019-12-12 19:03:25 +08:00
|
|
|
#include "soc/dport_reg.h"
|
2019-05-27 14:29:43 +08:00
|
|
|
#include "soc/efuse_reg.h"
|
2020-02-18 13:10:37 +00:00
|
|
|
#include "soc/gpio_periph.h"
|
2019-05-27 14:29:43 +08:00
|
|
|
#include "soc/gpio_sig_map.h"
|
|
|
|
|
#include "soc/io_mux_reg.h"
|
2019-12-12 19:03:25 +08:00
|
|
|
#include "soc/rtc.h"
|
|
|
|
|
#include "soc/spi_periph.h"
|
2021-03-16 10:55:05 +08:00
|
|
|
#include "hal/gpio_hal.h"
|
2019-12-12 19:03:25 +08:00
|
|
|
|
|
|
|
|
#include "esp32/rom/cache.h"
|
2020-06-19 12:00:58 +08:00
|
|
|
#include "esp_rom_gpio.h"
|
2020-07-13 21:57:24 +08:00
|
|
|
#include "esp_rom_efuse.h"
|
2020-07-21 13:07:34 +08:00
|
|
|
#include "esp_rom_sys.h"
|
2021-09-28 14:12:56 +08:00
|
|
|
#include "esp_rom_spiflash.h"
|
2021-06-17 07:21:36 +08:00
|
|
|
#include "esp_efuse.h"
|
2019-12-12 19:03:25 +08:00
|
|
|
|
|
|
|
|
static const char *TAG = "boot.esp32";
|
2019-05-27 14:29:43 +08:00
|
|
|
|
|
|
|
|
#define FLASH_CLK_IO SPI_CLK_GPIO_NUM
|
|
|
|
|
#define FLASH_CS_IO SPI_CS0_GPIO_NUM
|
|
|
|
|
#define FLASH_SPIQ_IO SPI_Q_GPIO_NUM
|
|
|
|
|
#define FLASH_SPID_IO SPI_D_GPIO_NUM
|
|
|
|
|
#define FLASH_SPIWP_IO SPI_WP_GPIO_NUM
|
|
|
|
|
#define FLASH_SPIHD_IO SPI_HD_GPIO_NUM
|
|
|
|
|
|
|
|
|
|
void bootloader_configure_spi_pins(int drv)
|
|
|
|
|
{
|
2020-08-05 14:56:01 +08:00
|
|
|
uint32_t pkg_ver = bootloader_common_get_chip_ver_pkg();
|
2019-05-27 14:29:43 +08:00
|
|
|
|
2020-07-03 22:26:50 +08:00
|
|
|
if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32D2WDQ5 ||
|
|
|
|
|
pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD2 ||
|
|
|
|
|
pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD4 ||
|
|
|
|
|
pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOV302) {
|
|
|
|
|
// For ESP32D2WD or ESP32-PICO series,the SPI pins are already configured
|
2019-05-27 14:29:43 +08:00
|
|
|
// flash clock signal should come from IO MUX.
|
2021-03-16 10:55:05 +08:00
|
|
|
gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK);
|
2019-05-27 14:29:43 +08:00
|
|
|
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S);
|
|
|
|
|
} else {
|
2020-07-13 21:57:24 +08:00
|
|
|
const uint32_t spiconfig = esp_rom_efuse_get_flash_gpio_info();
|
|
|
|
|
if (spiconfig == ESP_ROM_EFUSE_FLASH_DEFAULT_SPI) {
|
2020-06-19 12:00:58 +08:00
|
|
|
esp_rom_gpio_connect_out_signal(FLASH_CS_IO, SPICS0_OUT_IDX, 0, 0);
|
|
|
|
|
esp_rom_gpio_connect_out_signal(FLASH_SPIQ_IO, SPIQ_OUT_IDX, 0, 0);
|
|
|
|
|
esp_rom_gpio_connect_in_signal(FLASH_SPIQ_IO, SPIQ_IN_IDX, 0);
|
|
|
|
|
esp_rom_gpio_connect_out_signal(FLASH_SPID_IO, SPID_OUT_IDX, 0, 0);
|
|
|
|
|
esp_rom_gpio_connect_in_signal(FLASH_SPID_IO, SPID_IN_IDX, 0);
|
|
|
|
|
esp_rom_gpio_connect_out_signal(FLASH_SPIWP_IO, SPIWP_OUT_IDX, 0, 0);
|
|
|
|
|
esp_rom_gpio_connect_in_signal(FLASH_SPIWP_IO, SPIWP_IN_IDX, 0);
|
|
|
|
|
esp_rom_gpio_connect_out_signal(FLASH_SPIHD_IO, SPIHD_OUT_IDX, 0, 0);
|
|
|
|
|
esp_rom_gpio_connect_in_signal(FLASH_SPIHD_IO, SPIHD_IN_IDX, 0);
|
2019-05-27 14:29:43 +08:00
|
|
|
//select pin function gpio
|
2021-03-16 10:55:05 +08:00
|
|
|
gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_SD_DATA0_U, PIN_FUNC_GPIO);
|
|
|
|
|
gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_SD_DATA1_U, PIN_FUNC_GPIO);
|
|
|
|
|
gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_SD_DATA2_U, PIN_FUNC_GPIO);
|
|
|
|
|
gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_SD_DATA3_U, PIN_FUNC_GPIO);
|
|
|
|
|
gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_SD_CMD_U, PIN_FUNC_GPIO);
|
2019-05-27 14:29:43 +08:00
|
|
|
// flash clock signal should come from IO MUX.
|
|
|
|
|
// set drive ability for clock
|
2021-03-16 10:55:05 +08:00
|
|
|
gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK);
|
2019-05-27 14:29:43 +08:00
|
|
|
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S);
|
|
|
|
|
|
2019-12-12 19:03:25 +08:00
|
|
|
#if CONFIG_SPIRAM_TYPE_ESPPSRAM32 || CONFIG_SPIRAM_TYPE_ESPPSRAM64
|
2019-05-27 14:29:43 +08:00
|
|
|
uint32_t flash_id = g_rom_flashchip.device_id;
|
|
|
|
|
if (flash_id == FLASH_ID_GD25LQ32C) {
|
|
|
|
|
// Set drive ability for 1.8v flash in 80Mhz.
|
|
|
|
|
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_DATA0_U, FUN_DRV, 3, FUN_DRV_S);
|
|
|
|
|
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_DATA1_U, FUN_DRV, 3, FUN_DRV_S);
|
|
|
|
|
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_DATA2_U, FUN_DRV, 3, FUN_DRV_S);
|
|
|
|
|
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_DATA3_U, FUN_DRV, 3, FUN_DRV_S);
|
|
|
|
|
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CMD_U, FUN_DRV, 3, FUN_DRV_S);
|
|
|
|
|
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, 3, FUN_DRV_S);
|
|
|
|
|
}
|
2019-12-12 19:03:25 +08:00
|
|
|
#endif
|
2019-05-27 14:29:43 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-12-12 19:03:25 +08:00
|
|
|
|
|
|
|
|
static void bootloader_reset_mmu(void)
|
|
|
|
|
{
|
|
|
|
|
/* completely reset MMU in case serial bootloader was running */
|
|
|
|
|
Cache_Read_Disable(0);
|
|
|
|
|
#if !CONFIG_FREERTOS_UNICORE
|
|
|
|
|
Cache_Read_Disable(1);
|
|
|
|
|
#endif
|
|
|
|
|
Cache_Flush(0);
|
|
|
|
|
#if !CONFIG_FREERTOS_UNICORE
|
|
|
|
|
Cache_Flush(1);
|
|
|
|
|
#endif
|
|
|
|
|
mmu_init(0);
|
|
|
|
|
#if !CONFIG_FREERTOS_UNICORE
|
|
|
|
|
/* The lines which manipulate DPORT_APP_CACHE_MMU_IA_CLR bit are
|
|
|
|
|
necessary to work around a hardware bug. */
|
|
|
|
|
DPORT_REG_SET_BIT(DPORT_APP_CACHE_CTRL1_REG, DPORT_APP_CACHE_MMU_IA_CLR);
|
|
|
|
|
mmu_init(1);
|
|
|
|
|
DPORT_REG_CLR_BIT(DPORT_APP_CACHE_CTRL1_REG, DPORT_APP_CACHE_MMU_IA_CLR);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/* normal ROM boot exits with DROM0 cache unmasked,
|
|
|
|
|
but serial bootloader exits with it masked. */
|
|
|
|
|
DPORT_REG_CLR_BIT(DPORT_PRO_CACHE_CTRL1_REG, DPORT_PRO_CACHE_MASK_DROM0);
|
|
|
|
|
#if !CONFIG_FREERTOS_UNICORE
|
|
|
|
|
DPORT_REG_CLR_BIT(DPORT_APP_CACHE_CTRL1_REG, DPORT_APP_CACHE_MASK_DROM0);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static esp_err_t bootloader_check_rated_cpu_clock(void)
|
|
|
|
|
{
|
|
|
|
|
int rated_freq = bootloader_clock_get_rated_freq_mhz();
|
|
|
|
|
if (rated_freq < CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ) {
|
|
|
|
|
ESP_LOGE(TAG, "Chip CPU frequency rated for %dMHz, configured for %dMHz. Modify CPU frequency in menuconfig",
|
|
|
|
|
rated_freq, CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ);
|
|
|
|
|
return ESP_FAIL;
|
|
|
|
|
}
|
|
|
|
|
return ESP_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void update_flash_config(const esp_image_header_t *bootloader_hdr)
|
|
|
|
|
{
|
|
|
|
|
uint32_t size;
|
|
|
|
|
switch (bootloader_hdr->spi_size) {
|
|
|
|
|
case ESP_IMAGE_FLASH_SIZE_1MB:
|
|
|
|
|
size = 1;
|
|
|
|
|
break;
|
|
|
|
|
case ESP_IMAGE_FLASH_SIZE_2MB:
|
|
|
|
|
size = 2;
|
|
|
|
|
break;
|
|
|
|
|
case ESP_IMAGE_FLASH_SIZE_4MB:
|
|
|
|
|
size = 4;
|
|
|
|
|
break;
|
|
|
|
|
case ESP_IMAGE_FLASH_SIZE_8MB:
|
|
|
|
|
size = 8;
|
|
|
|
|
break;
|
|
|
|
|
case ESP_IMAGE_FLASH_SIZE_16MB:
|
|
|
|
|
size = 16;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
size = 2;
|
|
|
|
|
}
|
|
|
|
|
Cache_Read_Disable(0);
|
|
|
|
|
// 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
|
|
|
|
|
Cache_Flush(0);
|
|
|
|
|
Cache_Read_Enable(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void print_flash_info(const esp_image_header_t *bootloader_hdr)
|
|
|
|
|
{
|
|
|
|
|
ESP_LOGD(TAG, "magic %02x", bootloader_hdr->magic);
|
|
|
|
|
ESP_LOGD(TAG, "segments %02x", bootloader_hdr->segment_count);
|
|
|
|
|
ESP_LOGD(TAG, "spi_mode %02x", bootloader_hdr->spi_mode);
|
|
|
|
|
ESP_LOGD(TAG, "spi_speed %02x", bootloader_hdr->spi_speed);
|
|
|
|
|
ESP_LOGD(TAG, "spi_size %02x", bootloader_hdr->spi_size);
|
|
|
|
|
|
|
|
|
|
const char *str;
|
|
|
|
|
switch (bootloader_hdr->spi_speed) {
|
|
|
|
|
case ESP_IMAGE_SPI_SPEED_40M:
|
|
|
|
|
str = "40MHz";
|
|
|
|
|
break;
|
|
|
|
|
case ESP_IMAGE_SPI_SPEED_26M:
|
|
|
|
|
str = "26.7MHz";
|
|
|
|
|
break;
|
|
|
|
|
case ESP_IMAGE_SPI_SPEED_20M:
|
|
|
|
|
str = "20MHz";
|
|
|
|
|
break;
|
|
|
|
|
case ESP_IMAGE_SPI_SPEED_80M:
|
|
|
|
|
str = "80MHz";
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
str = "20MHz";
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
ESP_LOGI(TAG, "SPI Speed : %s", str);
|
|
|
|
|
|
|
|
|
|
/* SPI mode could have been set to QIO during boot already,
|
|
|
|
|
so test the SPI registers not the flash header */
|
|
|
|
|
uint32_t spi_ctrl = REG_READ(SPI_CTRL_REG(0));
|
|
|
|
|
if (spi_ctrl & SPI_FREAD_QIO) {
|
|
|
|
|
str = "QIO";
|
|
|
|
|
} else if (spi_ctrl & SPI_FREAD_QUAD) {
|
|
|
|
|
str = "QOUT";
|
|
|
|
|
} else if (spi_ctrl & SPI_FREAD_DIO) {
|
|
|
|
|
str = "DIO";
|
|
|
|
|
} else if (spi_ctrl & SPI_FREAD_DUAL) {
|
|
|
|
|
str = "DOUT";
|
|
|
|
|
} else if (spi_ctrl & SPI_FASTRD_MODE) {
|
|
|
|
|
str = "FAST READ";
|
|
|
|
|
} else {
|
|
|
|
|
str = "SLOW READ";
|
|
|
|
|
}
|
|
|
|
|
ESP_LOGI(TAG, "SPI Mode : %s", str);
|
|
|
|
|
|
|
|
|
|
switch (bootloader_hdr->spi_size) {
|
|
|
|
|
case ESP_IMAGE_FLASH_SIZE_1MB:
|
|
|
|
|
str = "1MB";
|
|
|
|
|
break;
|
|
|
|
|
case ESP_IMAGE_FLASH_SIZE_2MB:
|
|
|
|
|
str = "2MB";
|
|
|
|
|
break;
|
|
|
|
|
case ESP_IMAGE_FLASH_SIZE_4MB:
|
|
|
|
|
str = "4MB";
|
|
|
|
|
break;
|
|
|
|
|
case ESP_IMAGE_FLASH_SIZE_8MB:
|
|
|
|
|
str = "8MB";
|
|
|
|
|
break;
|
|
|
|
|
case ESP_IMAGE_FLASH_SIZE_16MB:
|
|
|
|
|
str = "16MB";
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
str = "2MB";
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
ESP_LOGI(TAG, "SPI Flash Size : %s", str);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void IRAM_ATTR bootloader_init_flash_configure(void)
|
|
|
|
|
{
|
|
|
|
|
bootloader_flash_gpio_config(&bootloader_image_hdr);
|
|
|
|
|
bootloader_flash_dummy_config(&bootloader_image_hdr);
|
|
|
|
|
bootloader_flash_cs_timing_config();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static esp_err_t bootloader_init_spi_flash(void)
|
|
|
|
|
{
|
|
|
|
|
bootloader_init_flash_configure();
|
|
|
|
|
#ifndef CONFIG_SPI_FLASH_ROM_DRIVER_PATCH
|
2020-07-13 21:57:24 +08:00
|
|
|
const uint32_t spiconfig = esp_rom_efuse_get_flash_gpio_info();
|
|
|
|
|
if (spiconfig != ESP_ROM_EFUSE_FLASH_DEFAULT_SPI && spiconfig != ESP_ROM_EFUSE_FLASH_DEFAULT_HSPI) {
|
2019-12-12 19:03:25 +08:00
|
|
|
ESP_LOGE(TAG, "SPI flash pins are overridden. Enable CONFIG_SPI_FLASH_ROM_DRIVER_PATCH in menuconfig");
|
|
|
|
|
return ESP_FAIL;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2021-05-07 15:25:06 +08:00
|
|
|
bootloader_flash_unlock();
|
2019-12-12 19:03:25 +08:00
|
|
|
|
|
|
|
|
#if CONFIG_ESPTOOLPY_FLASHMODE_QIO || CONFIG_ESPTOOLPY_FLASHMODE_QOUT
|
|
|
|
|
bootloader_enable_qio_mode();
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
print_flash_info(&bootloader_image_hdr);
|
|
|
|
|
update_flash_config(&bootloader_image_hdr);
|
bootloader: fix the WRSR format for ISSI flash chips
1. The 2nd bootloader always call `rom_spiflash_unlock()`, but never help to clear the WEL bit when exit. This may cause system unstability.
This commit helps to clear WEL when flash configuration is done.
**RISK:** When the app starts, it didn't have to clear the WEL before it actually write/erase. But now the very first write/erase operation should be done after a WEL clear. Though the risk is little (all the following write/erase also need to clear the WEL), we still have to test this carefully, especially for those functions used by the OTA.
2. The `rom_spiflash_unlock()` function in the patch of ESP32 may (1) trigger the QPI, (2) clear the QE or (3) fail to unlock the ISSI chips.
Status register bitmap of ISSI chip and GD chip:
| SR | ISSI | GD25LQ32C |
| -- | ---- | --------- |
| 0 | WIP | WIP |
| 1 | WEL | WEL |
| 2 | BP0 | BP0 |
| 3 | BP1 | BP1 |
| 4 | BP2 | BP2 |
| 5 | BP3 | BP3 |
| 6 | QE | BP4 |
| 7 | SRWD | SRP0 |
| 8 | | SRP1 |
| 9 | | QE |
| 10 | | SUS2 |
| 11 | | LB1 |
| 12 | | LB2 |
| 13 | | LB3 |
| 14 | | CMP |
| 15 | | SUS1 |
QE bit of other chips are at the bit 9 of the status register (i.e. bit 1 of SR2), which should be read by RDSR2 command.
However, the RDSR2 (35H, Read Status 2) command for chip of other vendors happens to be the QIOEN (Enter QPI mode) command of ISSI chips. When the `rom_spiflash_unlock()` function trys to read SR2, it may trigger the QPI of ISSI chips.
Moreover, when `rom_spiflash_unlock()` try to clear the BP4 bit in the status register, QE (bit 6) of ISSI chip may be cleared by accident. Or if the ISSI chip doesn't accept WRSR command with argument of two bytes (since it only have status register of one byte), it may fail to clear the other protect bits (BP0~BP3) as expected.
This commit makes the `rom_spiflash_unlock()` check whether the vendor is issi. if so, `rom_spiflash_unlock()` only send RDSR to read the status register, send WRSR with only 1 byte argument, and also avoid clearing the QE bit (bit 6).
3. `rom_spiflash_unlock()` always send WRSR command to clear protection bits even when there is no protection bit active. And the execution of clearing status registers, which takes about 700us, will also happen even when there's no bits cleared.
This commit skips the clearing of status register if there is no protection bits active.
Also move the execute_flash_command to be a bootloader API; move
implementation of spi_flash_wrap_set to the bootloader
2020-03-12 18:20:31 +08:00
|
|
|
//ensure the flash is write-protected
|
|
|
|
|
bootloader_enable_wp();
|
2019-12-12 19:03:25 +08:00
|
|
|
return ESP_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void wdt_reset_cpu0_info_enable(void)
|
|
|
|
|
{
|
|
|
|
|
//We do not reset core1 info here because it didn't work before cpu1 was up. So we put it into call_start_cpu1.
|
|
|
|
|
DPORT_REG_SET_BIT(DPORT_PRO_CPU_RECORD_CTRL_REG, DPORT_PRO_CPU_PDEBUG_ENABLE | DPORT_PRO_CPU_RECORD_ENABLE);
|
|
|
|
|
DPORT_REG_CLR_BIT(DPORT_PRO_CPU_RECORD_CTRL_REG, DPORT_PRO_CPU_RECORD_ENABLE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void wdt_reset_info_dump(int cpu)
|
|
|
|
|
{
|
|
|
|
|
uint32_t inst = 0, pid = 0, stat = 0, data = 0, pc = 0,
|
|
|
|
|
lsstat = 0, lsaddr = 0, lsdata = 0, dstat = 0;
|
|
|
|
|
const char *cpu_name = cpu ? "APP" : "PRO";
|
|
|
|
|
|
|
|
|
|
if (cpu == 0) {
|
|
|
|
|
stat = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_STATUS_REG);
|
|
|
|
|
pid = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PID_REG);
|
|
|
|
|
inst = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGINST_REG);
|
|
|
|
|
dstat = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGSTATUS_REG);
|
|
|
|
|
data = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGDATA_REG);
|
|
|
|
|
pc = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGPC_REG);
|
|
|
|
|
lsstat = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGLS0STAT_REG);
|
|
|
|
|
lsaddr = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGLS0ADDR_REG);
|
|
|
|
|
lsdata = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGLS0DATA_REG);
|
|
|
|
|
} else {
|
|
|
|
|
#if !CONFIG_FREERTOS_UNICORE
|
|
|
|
|
stat = DPORT_REG_READ(DPORT_APP_CPU_RECORD_STATUS_REG);
|
|
|
|
|
pid = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PID_REG);
|
|
|
|
|
inst = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGINST_REG);
|
|
|
|
|
dstat = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGSTATUS_REG);
|
|
|
|
|
data = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGDATA_REG);
|
|
|
|
|
pc = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGPC_REG);
|
|
|
|
|
lsstat = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGLS0STAT_REG);
|
|
|
|
|
lsaddr = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGLS0ADDR_REG);
|
|
|
|
|
lsdata = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGLS0DATA_REG);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (DPORT_RECORD_PDEBUGINST_SZ(inst) == 0 &&
|
|
|
|
|
DPORT_RECORD_PDEBUGSTATUS_BBCAUSE(dstat) == DPORT_RECORD_PDEBUGSTATUS_BBCAUSE_WAITI) {
|
|
|
|
|
ESP_LOGW(TAG, "WDT reset info: %s CPU PC=0x%x (waiti mode)", cpu_name, pc);
|
|
|
|
|
} else {
|
|
|
|
|
ESP_LOGW(TAG, "WDT reset info: %s CPU PC=0x%x", cpu_name, pc);
|
|
|
|
|
}
|
|
|
|
|
ESP_LOGD(TAG, "WDT reset info: %s CPU STATUS 0x%08x", cpu_name, stat);
|
|
|
|
|
ESP_LOGD(TAG, "WDT reset info: %s CPU PID 0x%08x", cpu_name, pid);
|
|
|
|
|
ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGINST 0x%08x", cpu_name, inst);
|
|
|
|
|
ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGSTATUS 0x%08x", cpu_name, dstat);
|
|
|
|
|
ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGDATA 0x%08x", cpu_name, data);
|
|
|
|
|
ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGPC 0x%08x", cpu_name, pc);
|
|
|
|
|
ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGLS0STAT 0x%08x", cpu_name, lsstat);
|
|
|
|
|
ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGLS0ADDR 0x%08x", cpu_name, lsaddr);
|
|
|
|
|
ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGLS0DATA 0x%08x", cpu_name, lsdata);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void bootloader_check_wdt_reset(void)
|
|
|
|
|
{
|
|
|
|
|
int wdt_rst = 0;
|
2021-07-13 10:45:06 +08:00
|
|
|
soc_reset_reason_t rst_reas[2];
|
2019-12-12 19:03:25 +08:00
|
|
|
|
2021-07-13 10:45:06 +08:00
|
|
|
rst_reas[0] = esp_rom_get_reset_reason(0);
|
|
|
|
|
rst_reas[1] = esp_rom_get_reset_reason(1);
|
|
|
|
|
if (rst_reas[0] == RESET_REASON_CORE_RTC_WDT || rst_reas[0] == RESET_REASON_CORE_MWDT0 || rst_reas[0] == RESET_REASON_CORE_MWDT1 ||
|
|
|
|
|
rst_reas[0] == RESET_REASON_CPU0_MWDT0 || rst_reas[0] == RESET_REASON_CPU0_RTC_WDT) {
|
2019-12-12 19:03:25 +08:00
|
|
|
ESP_LOGW(TAG, "PRO CPU has been reset by WDT.");
|
|
|
|
|
wdt_rst = 1;
|
|
|
|
|
}
|
2021-07-13 10:45:06 +08:00
|
|
|
if (rst_reas[1] == RESET_REASON_CORE_RTC_WDT || rst_reas[1] == RESET_REASON_CORE_MWDT0 || rst_reas[1] == RESET_REASON_CORE_MWDT1 ||
|
|
|
|
|
rst_reas[1] == RESET_REASON_CPU1_MWDT1 || rst_reas[1] == RESET_REASON_CPU1_RTC_WDT) {
|
2019-12-12 19:03:25 +08:00
|
|
|
ESP_LOGW(TAG, "APP CPU has been reset by WDT.");
|
|
|
|
|
wdt_rst = 1;
|
|
|
|
|
}
|
|
|
|
|
if (wdt_rst) {
|
|
|
|
|
// if reset by WDT dump info from trace port
|
|
|
|
|
wdt_reset_info_dump(0);
|
2020-04-30 17:27:28 +10:00
|
|
|
#if !CONFIG_FREERTOS_UNICORE
|
2019-12-12 19:03:25 +08:00
|
|
|
wdt_reset_info_dump(1);
|
2020-04-30 17:27:28 +10:00
|
|
|
#endif
|
2019-12-12 19:03:25 +08:00
|
|
|
}
|
|
|
|
|
wdt_reset_cpu0_info_enable();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
esp_err_t bootloader_init(void)
|
|
|
|
|
{
|
|
|
|
|
esp_err_t ret = ESP_OK;
|
2020-02-03 18:12:32 +08:00
|
|
|
|
|
|
|
|
bootloader_init_mem();
|
|
|
|
|
|
2019-12-12 19:03:25 +08:00
|
|
|
// check that static RAM is after the stack
|
|
|
|
|
#ifndef NDEBUG
|
|
|
|
|
{
|
|
|
|
|
assert(&_bss_start <= &_bss_end);
|
|
|
|
|
assert(&_data_start <= &_data_end);
|
2021-02-19 20:23:32 +08:00
|
|
|
int *sp = esp_cpu_get_sp();
|
2019-12-12 19:03:25 +08:00
|
|
|
assert(sp < &_bss_start);
|
|
|
|
|
assert(sp < &_data_start);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
// clear bss section
|
|
|
|
|
bootloader_clear_bss_section();
|
2021-06-17 07:21:36 +08:00
|
|
|
// init eFuse virtual mode (read eFuses to RAM)
|
|
|
|
|
#ifdef CONFIG_EFUSE_VIRTUAL
|
|
|
|
|
ESP_LOGW(TAG, "eFuse virtual mode is enabled. If Secure boot or Flash encryption is enabled then it does not provide any security. FOR TESTING ONLY!");
|
|
|
|
|
#ifndef CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH
|
|
|
|
|
esp_efuse_init_virtual_mode_in_ram();
|
|
|
|
|
#endif
|
|
|
|
|
#endif
|
2019-12-12 19:03:25 +08:00
|
|
|
// bootst up vddsdio
|
|
|
|
|
bootloader_common_vddsdio_configure();
|
|
|
|
|
// reset MMU
|
|
|
|
|
bootloader_reset_mmu();
|
|
|
|
|
// check rated CPU clock
|
|
|
|
|
if ((ret = bootloader_check_rated_cpu_clock()) != ESP_OK) {
|
|
|
|
|
goto err;
|
|
|
|
|
}
|
|
|
|
|
// config clock
|
|
|
|
|
bootloader_clock_configure();
|
|
|
|
|
// initialize uart console, from now on, we can use esp_log
|
2020-04-30 15:29:23 +02:00
|
|
|
bootloader_console_init();
|
2019-12-12 19:03:25 +08:00
|
|
|
/* print 2nd bootloader banner */
|
|
|
|
|
bootloader_print_banner();
|
|
|
|
|
// update flash ID
|
|
|
|
|
bootloader_flash_update_id();
|
2021-08-01 14:23:36 +08:00
|
|
|
// Check and run XMC startup flow
|
|
|
|
|
if ((ret = bootloader_flash_xmc_startup()) != ESP_OK) {
|
|
|
|
|
ESP_LOGE(TAG, "failed when running XMC startup flow, reboot!");
|
|
|
|
|
goto err;
|
|
|
|
|
}
|
2019-12-12 19:03:25 +08:00
|
|
|
// read bootloader header
|
|
|
|
|
if ((ret = bootloader_read_bootloader_header()) != ESP_OK) {
|
|
|
|
|
goto err;
|
|
|
|
|
}
|
|
|
|
|
// read chip revision and check if it's compatible to bootloader
|
|
|
|
|
if ((ret = bootloader_check_bootloader_validity()) != ESP_OK) {
|
|
|
|
|
goto err;
|
|
|
|
|
}
|
|
|
|
|
// initialize spi flash
|
|
|
|
|
if ((ret = bootloader_init_spi_flash()) != ESP_OK) {
|
|
|
|
|
goto err;
|
|
|
|
|
}
|
|
|
|
|
// check whether a WDT reset happend
|
|
|
|
|
bootloader_check_wdt_reset();
|
|
|
|
|
// config WDT
|
|
|
|
|
bootloader_config_wdt();
|
|
|
|
|
// enable RNG early entropy source
|
|
|
|
|
bootloader_enable_random();
|
|
|
|
|
err:
|
|
|
|
|
return ret;
|
|
|
|
|
}
|