2018-04-16 11:35:41 -04:00
|
|
|
// Copyright 2018 Espressif Systems (Shanghai) PTE LTD
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <limits.h>
|
|
|
|
#include <sys/param.h>
|
|
|
|
|
|
|
|
#include "esp_attr.h"
|
|
|
|
#include "esp_log.h"
|
|
|
|
|
2019-03-14 05:29:32 -04:00
|
|
|
#include "esp32/rom/cache.h"
|
|
|
|
#include "esp32/rom/efuse.h"
|
|
|
|
#include "esp32/rom/ets_sys.h"
|
|
|
|
#include "esp32/rom/spi_flash.h"
|
|
|
|
#include "esp32/rom/crc.h"
|
|
|
|
#include "esp32/rom/rtc.h"
|
|
|
|
#include "esp32/rom/uart.h"
|
|
|
|
#include "esp32/rom/gpio.h"
|
|
|
|
#include "esp32/rom/secure_boot.h"
|
2018-04-16 11:35:41 -04:00
|
|
|
|
|
|
|
#include "soc/soc.h"
|
|
|
|
#include "soc/cpu.h"
|
|
|
|
#include "soc/rtc.h"
|
|
|
|
#include "soc/dport_reg.h"
|
|
|
|
#include "soc/efuse_reg.h"
|
|
|
|
#include "soc/rtc_cntl_reg.h"
|
|
|
|
#include "soc/timer_group_reg.h"
|
2019-05-16 06:46:00 -04:00
|
|
|
#include "soc/gpio_periph.h"
|
2018-07-23 06:59:37 -04:00
|
|
|
#include "soc/rtc_wdt.h"
|
global: move the soc component out of the common list
This MR removes the common dependency from every IDF components to the SOC component.
Currently, in the ``idf_functions.cmake`` script, we include the header path of SOC component by default for all components.
But for better code organization (or maybe also benifits to the compiling speed), we may remove the dependency to SOC components for most components except the driver and kernel related components.
In CMAKE, we have two kinds of header visibilities (set by include path visibility):
(Assume component A --(depends on)--> B, B is the current component)
1. public (``COMPONENT_ADD_INCLUDEDIRS``): means this path is visible to other depending components (A) (visible to A and B)
2. private (``COMPONENT_PRIV_INCLUDEDIRS``): means this path is only visible to source files inside the component (visible to B only)
and we have two kinds of depending ways:
(Assume component A --(depends on)--> B --(depends on)--> C, B is the current component)
1. public (```COMPONENT_REQUIRES```): means B can access to public include path of C. All other components rely on you (A) will also be available for the public headers. (visible to A, B)
2. private (``COMPONENT_PRIV_REQUIRES``): means B can access to public include path of C, but don't propagate this relation to other components (A). (visible to B)
1. remove the common requirement in ``idf_functions.cmake``, this makes the SOC components invisible to all other components by default.
2. if a component (for example, DRIVER) really needs the dependency to SOC, add a private dependency to SOC for it.
3. some other components that don't really depends on the SOC may still meet some errors saying "can't find header soc/...", this is because it's depended component (DRIVER) incorrectly include the header of SOC in its public headers. Moving all this kind of #include into source files, or private headers
4. Fix the include requirements for some file which miss sufficient #include directives. (Previously they include some headers by the long long long header include link)
This is a breaking change. Previous code may depends on the long include chain.
You may need to include the following headers for some files after this commit:
- soc/soc.h
- soc/soc_memory_layout.h
- driver/gpio.h
- esp_sleep.h
The major broken include chain includes:
1. esp_system.h no longer includes esp_sleep.h. The latter includes driver/gpio.h and driver/touch_pad.h.
2. ets_sys.h no longer includes soc/soc.h
3. freertos/portmacro.h no longer includes soc/soc_memory_layout.h
some peripheral headers no longer includes their hw related headers, e.g. rom/gpio.h no longer includes soc/gpio_pins.h and soc/gpio_reg.h
BREAKING CHANGE
2019-04-03 01:17:38 -04:00
|
|
|
#include "soc/spi_reg.h"
|
2018-04-16 11:35:41 -04:00
|
|
|
|
|
|
|
#include "sdkconfig.h"
|
|
|
|
#include "esp_image_format.h"
|
|
|
|
#include "esp_secure_boot.h"
|
|
|
|
#include "esp_flash_encrypt.h"
|
|
|
|
#include "esp_flash_partitions.h"
|
|
|
|
#include "bootloader_flash.h"
|
|
|
|
#include "bootloader_random.h"
|
|
|
|
#include "bootloader_config.h"
|
|
|
|
#include "bootloader_clock.h"
|
|
|
|
|
|
|
|
#include "flash_qio_mode.h"
|
|
|
|
|
|
|
|
extern int _bss_start;
|
|
|
|
extern int _bss_end;
|
|
|
|
extern int _data_start;
|
|
|
|
extern int _data_end;
|
|
|
|
|
|
|
|
static const char* TAG = "boot";
|
|
|
|
|
|
|
|
static esp_err_t bootloader_main();
|
|
|
|
static void print_flash_info(const esp_image_header_t* pfhdr);
|
|
|
|
static void update_flash_config(const esp_image_header_t* pfhdr);
|
|
|
|
static void vddsdio_configure();
|
2018-04-20 04:59:25 -04:00
|
|
|
static void flash_gpio_configure(const esp_image_header_t* pfhdr);
|
2018-04-16 11:35:41 -04:00
|
|
|
static void uart_console_configure(void);
|
|
|
|
static void wdt_reset_check(void);
|
|
|
|
|
|
|
|
|
|
|
|
esp_err_t bootloader_init()
|
|
|
|
{
|
|
|
|
cpu_configure_region_protection();
|
2018-10-31 23:30:48 -04:00
|
|
|
cpu_init_memctl();
|
2018-04-16 11:35:41 -04:00
|
|
|
|
|
|
|
/* Sanity check that static RAM is after the stack */
|
|
|
|
#ifndef NDEBUG
|
|
|
|
{
|
|
|
|
int *sp = get_sp();
|
|
|
|
assert(&_bss_start <= &_bss_end);
|
|
|
|
assert(&_data_start <= &_data_end);
|
|
|
|
assert(sp < &_bss_start);
|
|
|
|
assert(sp < &_data_start);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
//Clear bss
|
|
|
|
memset(&_bss_start, 0, (&_bss_end - &_bss_start) * sizeof(_bss_start));
|
|
|
|
|
|
|
|
/* completely reset MMU for both CPUs
|
|
|
|
(in case serial bootloader was running) */
|
|
|
|
Cache_Read_Disable(0);
|
|
|
|
Cache_Read_Disable(1);
|
|
|
|
Cache_Flush(0);
|
|
|
|
Cache_Flush(1);
|
|
|
|
mmu_init(0);
|
|
|
|
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);
|
|
|
|
/* (above steps probably unnecessary for most serial bootloader
|
|
|
|
usage, all that's absolutely needed is that we unmask DROM0
|
|
|
|
cache on the following two lines - normal ROM boot exits with
|
|
|
|
DROM0 cache unmasked, but serial bootloader exits with it
|
|
|
|
masked. However can't hurt to be thorough and reset
|
|
|
|
everything.)
|
|
|
|
|
|
|
|
The lines which manipulate DPORT_APP_CACHE_MMU_IA_CLR bit are
|
|
|
|
necessary to work around a hardware bug.
|
|
|
|
*/
|
|
|
|
DPORT_REG_CLR_BIT(DPORT_PRO_CACHE_CTRL1_REG, DPORT_PRO_CACHE_MASK_DROM0);
|
|
|
|
DPORT_REG_CLR_BIT(DPORT_APP_CACHE_CTRL1_REG, DPORT_APP_CACHE_MASK_DROM0);
|
|
|
|
|
|
|
|
if(bootloader_main() != ESP_OK){
|
|
|
|
return ESP_FAIL;
|
|
|
|
}
|
|
|
|
return ESP_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static esp_err_t bootloader_main()
|
|
|
|
{
|
|
|
|
vddsdio_configure();
|
2018-04-20 04:59:25 -04:00
|
|
|
/* Read and keep flash ID, for further use. */
|
|
|
|
g_rom_flashchip.device_id = bootloader_read_flash_id();
|
|
|
|
esp_image_header_t fhdr;
|
|
|
|
if (bootloader_flash_read(ESP_BOOTLOADER_OFFSET, &fhdr, sizeof(esp_image_header_t), true) != ESP_OK) {
|
|
|
|
ESP_LOGE(TAG, "failed to load bootloader header!");
|
|
|
|
return ESP_FAIL;
|
|
|
|
}
|
|
|
|
flash_gpio_configure(&fhdr);
|
2018-04-16 11:35:41 -04:00
|
|
|
#if (CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ == 240)
|
|
|
|
//Check if ESP32 is rated for a CPU frequency of 160MHz only
|
|
|
|
if (REG_GET_BIT(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_CPU_FREQ_RATED) &&
|
|
|
|
REG_GET_BIT(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_CPU_FREQ_LOW)) {
|
|
|
|
ESP_LOGE(TAG, "Chip CPU frequency rated for 160MHz. Modify CPU frequency in menuconfig");
|
|
|
|
return ESP_FAIL;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
bootloader_clock_configure();
|
|
|
|
uart_console_configure();
|
|
|
|
wdt_reset_check();
|
|
|
|
ESP_LOGI(TAG, "ESP-IDF %s 2nd stage bootloader", IDF_VER);
|
|
|
|
|
|
|
|
ESP_LOGI(TAG, "compile time " __TIME__ );
|
|
|
|
ets_set_appcpu_boot_addr(0);
|
|
|
|
|
2018-07-26 05:07:36 -04:00
|
|
|
#ifdef CONFIG_BOOTLOADER_WDT_ENABLE
|
|
|
|
ESP_LOGD(TAG, "Enabling RTCWDT(%d ms)", CONFIG_BOOTLOADER_WDT_TIME_MS);
|
|
|
|
rtc_wdt_protect_off();
|
|
|
|
rtc_wdt_disable();
|
|
|
|
rtc_wdt_set_length_of_reset_signal(RTC_WDT_SYS_RESET_SIG, RTC_WDT_LENGTH_3_2us);
|
|
|
|
rtc_wdt_set_length_of_reset_signal(RTC_WDT_CPU_RESET_SIG, RTC_WDT_LENGTH_3_2us);
|
|
|
|
rtc_wdt_set_stage(RTC_WDT_STAGE0, RTC_WDT_STAGE_ACTION_RESET_RTC);
|
|
|
|
rtc_wdt_set_time(RTC_WDT_STAGE0, CONFIG_BOOTLOADER_WDT_TIME_MS);
|
|
|
|
rtc_wdt_enable();
|
|
|
|
rtc_wdt_protect_on();
|
|
|
|
#else
|
2018-04-16 11:35:41 -04:00
|
|
|
/* disable watch dog here */
|
2018-07-23 06:59:37 -04:00
|
|
|
rtc_wdt_disable();
|
2018-07-26 05:07:36 -04:00
|
|
|
#endif
|
|
|
|
REG_SET_FIELD(TIMG_WDTWPROTECT_REG(0), TIMG_WDT_WKEY, TIMG_WDT_WKEY_VALUE);
|
2018-04-16 11:35:41 -04:00
|
|
|
REG_CLR_BIT( TIMG_WDTCONFIG0_REG(0), TIMG_WDT_FLASHBOOT_MOD_EN );
|
|
|
|
|
|
|
|
#ifndef CONFIG_SPI_FLASH_ROM_DRIVER_PATCH
|
|
|
|
const uint32_t spiconfig = ets_efuse_get_spiconfig();
|
|
|
|
if(spiconfig != EFUSE_SPICONFIG_SPI_DEFAULTS && spiconfig != EFUSE_SPICONFIG_HSPI_DEFAULTS) {
|
|
|
|
ESP_LOGE(TAG, "SPI flash pins are overridden. \"Enable SPI flash ROM driver patched functions\" must be enabled in menuconfig");
|
|
|
|
return ESP_FAIL;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
esp_rom_spiflash_unlock();
|
|
|
|
|
|
|
|
ESP_LOGI(TAG, "Enabling RNG early entropy source...");
|
|
|
|
bootloader_random_enable();
|
|
|
|
|
2019-05-09 07:39:30 -04:00
|
|
|
#if CONFIG_ESPTOOLPY_FLASHMODE_QIO || CONFIG_ESPTOOLPY_FLASHMODE_QOUT
|
2018-04-16 11:35:41 -04:00
|
|
|
bootloader_enable_qio_mode();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
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:
|
|
|
|
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* phdr)
|
|
|
|
{
|
|
|
|
#if (BOOT_LOG_LEVEL >= BOOT_LOG_LEVEL_NOTICE)
|
|
|
|
|
|
|
|
ESP_LOGD(TAG, "magic %02x", phdr->magic );
|
|
|
|
ESP_LOGD(TAG, "segments %02x", phdr->segment_count );
|
|
|
|
ESP_LOGD(TAG, "spi_mode %02x", phdr->spi_mode );
|
|
|
|
ESP_LOGD(TAG, "spi_speed %02x", phdr->spi_speed );
|
|
|
|
ESP_LOGD(TAG, "spi_size %02x", phdr->spi_size );
|
|
|
|
|
|
|
|
const char* str;
|
|
|
|
switch ( phdr->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 ( phdr->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 );
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
static void vddsdio_configure()
|
|
|
|
{
|
|
|
|
#if CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V
|
|
|
|
rtc_vddsdio_config_t cfg = rtc_vddsdio_get_config();
|
2018-05-25 00:52:41 -04:00
|
|
|
if (cfg.enable == 1 && cfg.tieh == RTC_VDDSDIO_TIEH_1_8V) { // VDDSDIO regulator is enabled @ 1.8V
|
2018-04-16 11:35:41 -04:00
|
|
|
cfg.drefh = 3;
|
|
|
|
cfg.drefm = 3;
|
|
|
|
cfg.drefl = 3;
|
|
|
|
cfg.force = 1;
|
|
|
|
rtc_vddsdio_set_config(cfg);
|
|
|
|
ets_delay_us(10); // wait for regulator to become stable
|
|
|
|
}
|
|
|
|
#endif // CONFIG_BOOTLOADER_VDDSDIO_BOOST
|
|
|
|
}
|
|
|
|
|
|
|
|
#define FLASH_CLK_IO 6
|
|
|
|
#define FLASH_CS_IO 11
|
|
|
|
#define FLASH_SPIQ_IO 7
|
|
|
|
#define FLASH_SPID_IO 8
|
|
|
|
#define FLASH_SPIWP_IO 10
|
|
|
|
#define FLASH_SPIHD_IO 9
|
|
|
|
#define FLASH_IO_MATRIX_DUMMY_40M 1
|
|
|
|
#define FLASH_IO_MATRIX_DUMMY_80M 2
|
2018-04-20 04:59:25 -04:00
|
|
|
#define FLASH_IO_DRIVE_GD_WITH_1V8PSRAM 3
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Bootloader reads SPI configuration from bin header, so that
|
|
|
|
* the burning configuration can be different with compiling configuration.
|
|
|
|
*/
|
|
|
|
static void IRAM_ATTR flash_gpio_configure(const esp_image_header_t* pfhdr)
|
2018-04-16 11:35:41 -04:00
|
|
|
{
|
|
|
|
int spi_cache_dummy = 0;
|
|
|
|
int drv = 2;
|
2018-04-20 04:59:25 -04:00
|
|
|
switch (pfhdr->spi_mode) {
|
|
|
|
case ESP_IMAGE_SPI_MODE_QIO:
|
|
|
|
spi_cache_dummy = SPI0_R_DIO_DUMMY_CYCLELEN;
|
|
|
|
break;
|
|
|
|
case ESP_IMAGE_SPI_MODE_DIO:
|
|
|
|
spi_cache_dummy = SPI0_R_DIO_DUMMY_CYCLELEN; //qio 3
|
|
|
|
break;
|
|
|
|
case ESP_IMAGE_SPI_MODE_QOUT:
|
|
|
|
case ESP_IMAGE_SPI_MODE_DOUT:
|
|
|
|
default:
|
|
|
|
spi_cache_dummy = SPI0_R_FAST_DUMMY_CYCLELEN;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2018-04-16 11:35:41 -04:00
|
|
|
/* dummy_len_plus values defined in ROM for SPI flash configuration */
|
|
|
|
extern uint8_t g_rom_spiflash_dummy_len_plus[];
|
2018-04-20 04:59:25 -04:00
|
|
|
switch (pfhdr->spi_speed) {
|
|
|
|
case ESP_IMAGE_SPI_SPEED_80M:
|
|
|
|
g_rom_spiflash_dummy_len_plus[0] = FLASH_IO_MATRIX_DUMMY_80M;
|
|
|
|
g_rom_spiflash_dummy_len_plus[1] = FLASH_IO_MATRIX_DUMMY_80M;
|
|
|
|
SET_PERI_REG_BITS(SPI_USER1_REG(0), SPI_USR_DUMMY_CYCLELEN_V, spi_cache_dummy + FLASH_IO_MATRIX_DUMMY_80M,
|
|
|
|
SPI_USR_DUMMY_CYCLELEN_S); //DUMMY
|
|
|
|
drv = 3;
|
|
|
|
break;
|
|
|
|
case ESP_IMAGE_SPI_SPEED_40M:
|
|
|
|
g_rom_spiflash_dummy_len_plus[0] = FLASH_IO_MATRIX_DUMMY_40M;
|
|
|
|
g_rom_spiflash_dummy_len_plus[1] = FLASH_IO_MATRIX_DUMMY_40M;
|
|
|
|
SET_PERI_REG_BITS(SPI_USER1_REG(0), SPI_USR_DUMMY_CYCLELEN_V, spi_cache_dummy + FLASH_IO_MATRIX_DUMMY_40M,
|
|
|
|
SPI_USR_DUMMY_CYCLELEN_S); //DUMMY
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2018-04-16 11:35:41 -04:00
|
|
|
|
|
|
|
uint32_t chip_ver = REG_GET_FIELD(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_VER_PKG);
|
|
|
|
uint32_t pkg_ver = chip_ver & 0x7;
|
|
|
|
|
|
|
|
if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32D2WDQ5) {
|
|
|
|
// For ESP32D2WD the SPI pins are already configured
|
|
|
|
// flash clock signal should come from IO MUX.
|
|
|
|
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK);
|
|
|
|
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S);
|
|
|
|
} else if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD2) {
|
|
|
|
// For ESP32PICOD2 the SPI pins are already configured
|
|
|
|
// flash clock signal should come from IO MUX.
|
|
|
|
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK);
|
|
|
|
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S);
|
|
|
|
} else if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD4) {
|
|
|
|
// For ESP32PICOD4 the SPI pins are already configured
|
|
|
|
// flash clock signal should come from IO MUX.
|
|
|
|
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK);
|
|
|
|
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S);
|
|
|
|
} else {
|
|
|
|
const uint32_t spiconfig = ets_efuse_get_spiconfig();
|
|
|
|
if (spiconfig == EFUSE_SPICONFIG_SPI_DEFAULTS) {
|
|
|
|
gpio_matrix_out(FLASH_CS_IO, SPICS0_OUT_IDX, 0, 0);
|
|
|
|
gpio_matrix_out(FLASH_SPIQ_IO, SPIQ_OUT_IDX, 0, 0);
|
|
|
|
gpio_matrix_in(FLASH_SPIQ_IO, SPIQ_IN_IDX, 0);
|
|
|
|
gpio_matrix_out(FLASH_SPID_IO, SPID_OUT_IDX, 0, 0);
|
|
|
|
gpio_matrix_in(FLASH_SPID_IO, SPID_IN_IDX, 0);
|
|
|
|
gpio_matrix_out(FLASH_SPIWP_IO, SPIWP_OUT_IDX, 0, 0);
|
|
|
|
gpio_matrix_in(FLASH_SPIWP_IO, SPIWP_IN_IDX, 0);
|
|
|
|
gpio_matrix_out(FLASH_SPIHD_IO, SPIHD_OUT_IDX, 0, 0);
|
|
|
|
gpio_matrix_in(FLASH_SPIHD_IO, SPIHD_IN_IDX, 0);
|
|
|
|
//select pin function gpio
|
|
|
|
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA0_U, PIN_FUNC_GPIO);
|
|
|
|
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA1_U, PIN_FUNC_GPIO);
|
|
|
|
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA2_U, PIN_FUNC_GPIO);
|
|
|
|
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA3_U, PIN_FUNC_GPIO);
|
|
|
|
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CMD_U, PIN_FUNC_GPIO);
|
|
|
|
// flash clock signal should come from IO MUX.
|
|
|
|
// set drive ability for clock
|
|
|
|
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK);
|
|
|
|
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S);
|
2018-04-20 04:59:25 -04:00
|
|
|
|
|
|
|
#if CONFIG_SPIRAM_TYPE_ESPPSRAM32
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
#endif
|
2018-04-16 11:35:41 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void uart_console_configure(void)
|
|
|
|
{
|
2019-04-30 06:51:55 -04:00
|
|
|
#if CONFIG_ESP_CONSOLE_UART_NONE
|
2018-04-16 11:35:41 -04:00
|
|
|
ets_install_putc1(NULL);
|
|
|
|
ets_install_putc2(NULL);
|
2019-04-30 06:51:55 -04:00
|
|
|
#else // CONFIG_ESP_CONSOLE_UART_NONE
|
|
|
|
const int uart_num = CONFIG_ESP_CONSOLE_UART_NUM;
|
2018-04-16 11:35:41 -04:00
|
|
|
|
|
|
|
uartAttach();
|
|
|
|
ets_install_uart_printf();
|
|
|
|
|
|
|
|
// Wait for UART FIFO to be empty.
|
|
|
|
uart_tx_wait_idle(0);
|
|
|
|
|
2019-04-30 06:51:55 -04:00
|
|
|
#if CONFIG_ESP_CONSOLE_UART_CUSTOM
|
2018-04-16 11:35:41 -04:00
|
|
|
// Some constants to make the following code less upper-case
|
2019-04-30 06:51:55 -04:00
|
|
|
const int uart_tx_gpio = CONFIG_ESP_CONSOLE_UART_TX_GPIO;
|
|
|
|
const int uart_rx_gpio = CONFIG_ESP_CONSOLE_UART_RX_GPIO;
|
2018-04-16 11:35:41 -04:00
|
|
|
// Switch to the new UART (this just changes UART number used for
|
|
|
|
// ets_printf in ROM code).
|
|
|
|
uart_tx_switch(uart_num);
|
|
|
|
// If console is attached to UART1 or if non-default pins are used,
|
|
|
|
// need to reconfigure pins using GPIO matrix
|
|
|
|
if (uart_num != 0 || uart_tx_gpio != 1 || uart_rx_gpio != 3) {
|
|
|
|
// Change pin mode for GPIO1/3 from UART to GPIO
|
|
|
|
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_U0RXD_GPIO3);
|
|
|
|
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD_GPIO1);
|
|
|
|
// Route GPIO signals to/from pins
|
|
|
|
// (arrays should be optimized away by the compiler)
|
|
|
|
const uint32_t tx_idx_list[3] = { U0TXD_OUT_IDX, U1TXD_OUT_IDX, U2TXD_OUT_IDX };
|
|
|
|
const uint32_t rx_idx_list[3] = { U0RXD_IN_IDX, U1RXD_IN_IDX, U2RXD_IN_IDX };
|
|
|
|
const uint32_t tx_idx = tx_idx_list[uart_num];
|
|
|
|
const uint32_t rx_idx = rx_idx_list[uart_num];
|
2019-05-16 06:46:00 -04:00
|
|
|
|
|
|
|
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[uart_rx_gpio]);
|
|
|
|
gpio_pad_pullup(uart_rx_gpio);
|
|
|
|
|
2018-04-16 11:35:41 -04:00
|
|
|
gpio_matrix_out(uart_tx_gpio, tx_idx, 0, 0);
|
|
|
|
gpio_matrix_in(uart_rx_gpio, rx_idx, 0);
|
|
|
|
}
|
2019-04-30 06:51:55 -04:00
|
|
|
#endif // CONFIG_ESP_CONSOLE_UART_CUSTOM
|
2018-04-16 11:35:41 -04:00
|
|
|
|
|
|
|
// Set configured UART console baud rate
|
2019-04-30 06:51:55 -04:00
|
|
|
const int uart_baud = CONFIG_ESP_CONSOLE_UART_BAUDRATE;
|
2018-04-16 11:35:41 -04:00
|
|
|
uart_div_modify(uart_num, (rtc_clk_apb_freq_get() << 4) / uart_baud);
|
|
|
|
|
2019-04-30 06:51:55 -04:00
|
|
|
#endif // CONFIG_ESP_CONSOLE_UART_NONE
|
2018-04-16 11:35:41 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
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 {
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
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 wdt_reset_check(void)
|
|
|
|
{
|
|
|
|
int wdt_rst = 0;
|
|
|
|
RESET_REASON rst_reas[2];
|
|
|
|
|
|
|
|
rst_reas[0] = rtc_get_reset_reason(0);
|
|
|
|
rst_reas[1] = rtc_get_reset_reason(1);
|
|
|
|
if (rst_reas[0] == RTCWDT_SYS_RESET || rst_reas[0] == TG0WDT_SYS_RESET || rst_reas[0] == TG1WDT_SYS_RESET ||
|
|
|
|
rst_reas[0] == TGWDT_CPU_RESET || rst_reas[0] == RTCWDT_CPU_RESET) {
|
|
|
|
ESP_LOGW(TAG, "PRO CPU has been reset by WDT.");
|
|
|
|
wdt_rst = 1;
|
|
|
|
}
|
|
|
|
if (rst_reas[1] == RTCWDT_SYS_RESET || rst_reas[1] == TG0WDT_SYS_RESET || rst_reas[1] == TG1WDT_SYS_RESET ||
|
|
|
|
rst_reas[1] == TGWDT_CPU_RESET || rst_reas[1] == RTCWDT_CPU_RESET) {
|
|
|
|
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);
|
|
|
|
wdt_reset_info_dump(1);
|
|
|
|
}
|
|
|
|
wdt_reset_cpu0_info_enable();
|
|
|
|
}
|
|
|
|
|
|
|
|
void __assert_func(const char *file, int line, const char *func, const char *expr)
|
|
|
|
{
|
|
|
|
ESP_LOGE(TAG, "Assert failed in %s, %s:%d (%s)", func, file, line, expr);
|
|
|
|
while(1) {}
|
|
|
|
}
|
2018-10-15 03:02:56 -04:00
|
|
|
|
|
|
|
void abort()
|
|
|
|
{
|
|
|
|
#if !CONFIG_ESP32_PANIC_SILENT_REBOOT
|
|
|
|
ets_printf("abort() was called at PC 0x%08x\r\n", (intptr_t)__builtin_return_address(0) - 3);
|
|
|
|
#endif
|
|
|
|
if (esp_cpu_in_ocd_debug_mode()) {
|
|
|
|
__asm__ ("break 0,0");
|
|
|
|
}
|
|
|
|
while(1) {}
|
|
|
|
}
|