Merge branch 'refactor/startup' into 'master'
Startup flow refactor See merge request espressif/esp-idf!7533
This commit is contained in:
commit
ca50718501
40 changed files with 1799 additions and 1751 deletions
|
@ -24,15 +24,15 @@ const static char *TAG = "efuse";
|
|||
#if defined(BOOTLOADER_BUILD)
|
||||
#define EFUSE_LOCK_ACQUIRE()
|
||||
#define EFUSE_LOCK_RELEASE()
|
||||
#define EFUSE_LOCK_ACQUIRE_RUCURSIVE()
|
||||
#define EFUSE_LOCK_RELEASE_RUCURSIVE()
|
||||
#define EFUSE_LOCK_ACQUIRE_RECURSIVE()
|
||||
#define EFUSE_LOCK_RELEASE_RECURSIVE()
|
||||
#else
|
||||
#include <sys/lock.h>
|
||||
static _lock_t s_efuse_lock;
|
||||
#define EFUSE_LOCK_ACQUIRE() _lock_acquire(&s_efuse_lock)
|
||||
#define EFUSE_LOCK_RELEASE() _lock_release(&s_efuse_lock)
|
||||
#define EFUSE_LOCK_ACQUIRE_RUCURSIVE() _lock_acquire_recursive(&s_efuse_lock)
|
||||
#define EFUSE_LOCK_RELEASE_RUCURSIVE() _lock_release_recursive(&s_efuse_lock)
|
||||
#define EFUSE_LOCK_ACQUIRE_RECURSIVE() _lock_acquire_recursive(&s_efuse_lock)
|
||||
#define EFUSE_LOCK_RELEASE_RECURSIVE() _lock_release_recursive(&s_efuse_lock)
|
||||
#endif
|
||||
|
||||
static bool s_batch_writing_mode = false;
|
||||
|
@ -80,7 +80,7 @@ esp_err_t esp_efuse_read_field_cnt(const esp_efuse_desc_t* field[], size_t* out_
|
|||
// write array to EFUSE
|
||||
esp_err_t esp_efuse_write_field_blob(const esp_efuse_desc_t* field[], const void* src, size_t src_size_bits)
|
||||
{
|
||||
EFUSE_LOCK_ACQUIRE_RUCURSIVE();
|
||||
EFUSE_LOCK_ACQUIRE_RECURSIVE();
|
||||
esp_err_t err = ESP_OK;
|
||||
if (field == NULL || src == NULL || src_size_bits == 0) {
|
||||
err = ESP_ERR_INVALID_ARG;
|
||||
|
@ -100,14 +100,14 @@ esp_err_t esp_efuse_write_field_blob(const esp_efuse_desc_t* field[], const void
|
|||
esp_efuse_utility_reset();
|
||||
}
|
||||
}
|
||||
EFUSE_LOCK_RELEASE_RUCURSIVE();
|
||||
EFUSE_LOCK_RELEASE_RECURSIVE();
|
||||
return err;
|
||||
}
|
||||
|
||||
// program cnt bits to "1"
|
||||
esp_err_t esp_efuse_write_field_cnt(const esp_efuse_desc_t* field[], size_t cnt)
|
||||
{
|
||||
EFUSE_LOCK_ACQUIRE_RUCURSIVE();
|
||||
EFUSE_LOCK_ACQUIRE_RECURSIVE();
|
||||
esp_err_t err = ESP_OK;
|
||||
if (field == NULL || cnt == 0) {
|
||||
err = ESP_ERR_INVALID_ARG;
|
||||
|
@ -135,7 +135,7 @@ esp_err_t esp_efuse_write_field_cnt(const esp_efuse_desc_t* field[], size_t cnt)
|
|||
esp_efuse_utility_reset();
|
||||
}
|
||||
}
|
||||
EFUSE_LOCK_RELEASE_RUCURSIVE();
|
||||
EFUSE_LOCK_RELEASE_RECURSIVE();
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -184,7 +184,7 @@ uint32_t esp_efuse_read_reg(esp_efuse_block_t blk, unsigned int num_reg)
|
|||
// writing efuse register.
|
||||
esp_err_t esp_efuse_write_reg(esp_efuse_block_t blk, unsigned int num_reg, uint32_t val)
|
||||
{
|
||||
EFUSE_LOCK_ACQUIRE_RUCURSIVE();
|
||||
EFUSE_LOCK_ACQUIRE_RECURSIVE();
|
||||
if (s_batch_writing_mode == false) {
|
||||
esp_efuse_utility_reset();
|
||||
}
|
||||
|
@ -198,7 +198,7 @@ esp_err_t esp_efuse_write_reg(esp_efuse_block_t blk, unsigned int num_reg, uint3
|
|||
}
|
||||
esp_efuse_utility_reset();
|
||||
}
|
||||
EFUSE_LOCK_RELEASE_RUCURSIVE();
|
||||
EFUSE_LOCK_RELEASE_RECURSIVE();
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,6 @@ else()
|
|||
"cache_err_int.c"
|
||||
"cache_sram_mmu.c"
|
||||
"clk.c"
|
||||
"cpu_start.c"
|
||||
"crosscore_int.c"
|
||||
"dport_access.c"
|
||||
"esp_himem.c"
|
||||
|
@ -48,8 +47,6 @@ else()
|
|||
|
||||
target_linker_script(${COMPONENT_LIB} INTERFACE "${CMAKE_CURRENT_BINARY_DIR}/esp32_out.ld")
|
||||
|
||||
# Rely on user code to define app_main
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u app_main")
|
||||
|
||||
if(CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY)
|
||||
# This has to be linked before esp32.project.ld
|
||||
|
|
|
@ -23,16 +23,22 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
|
||||
#include "esp_err.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
#include "esp_attr.h"
|
||||
|
||||
#include "esp_intr_alloc.h"
|
||||
#include "soc/dport_reg.h"
|
||||
#include "hal/cpu_hal.h"
|
||||
|
||||
#include "esp32/dport_access.h"
|
||||
#include "esp32/rom/ets_sys.h"
|
||||
|
||||
#include "sdkconfig.h"
|
||||
|
||||
void esp_cache_err_int_init(void)
|
||||
{
|
||||
uint32_t core_id = xPortGetCoreID();
|
||||
uint32_t core_id = cpu_hal_get_core_id();
|
||||
ESP_INTR_DISABLE(ETS_MEMACCESS_ERR_INUM);
|
||||
|
||||
// We do not register a handler for the interrupt because it is interrupt
|
||||
|
|
|
@ -13,148 +13,20 @@
|
|||
// limitations under the License.
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/param.h>
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#include "esp_attr.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp32/clk.h"
|
||||
#include "esp_clk_internal.h"
|
||||
#include "esp32/rom/ets_sys.h"
|
||||
#include "esp32/rom/uart.h"
|
||||
#include "esp32/rom/rtc.h"
|
||||
#include "soc/soc.h"
|
||||
#include "soc/dport_reg.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "soc/rtc_periph.h"
|
||||
#include "soc/i2s_periph.h"
|
||||
#include "hal/wdt_hal.h"
|
||||
#include "driver/periph_ctrl.h"
|
||||
#include "xtensa/core-macros.h"
|
||||
#include "bootloader_clock.h"
|
||||
#include "driver/spi_common_internal.h"
|
||||
|
||||
/* Number of cycles to wait from the 32k XTAL oscillator to consider it running.
|
||||
* Larger values increase startup delay. Smaller values may cause false positive
|
||||
* detection (i.e. oscillator runs for a few cycles and then stops).
|
||||
*/
|
||||
#define SLOW_CLK_CAL_CYCLES CONFIG_ESP32_RTC_CLK_CAL_CYCLES
|
||||
|
||||
#ifdef CONFIG_ESP32_RTC_XTAL_CAL_RETRY
|
||||
#define RTC_XTAL_CAL_RETRY CONFIG_ESP32_RTC_XTAL_CAL_RETRY
|
||||
#else
|
||||
#define RTC_XTAL_CAL_RETRY 1
|
||||
#endif
|
||||
#include "esp32/clk.h"
|
||||
|
||||
#define MHZ (1000000)
|
||||
|
||||
/* Lower threshold for a reasonably-looking calibration value for a 32k XTAL.
|
||||
* The ideal value (assuming 32768 Hz frequency) is 1000000/32768*(2**19) = 16*10^6.
|
||||
*/
|
||||
#define MIN_32K_XTAL_CAL_VAL 15000000L
|
||||
|
||||
/* Indicates that this 32k oscillator gets input from external oscillator, rather
|
||||
* than a crystal.
|
||||
*/
|
||||
#define EXT_OSC_FLAG BIT(3)
|
||||
|
||||
/* This is almost the same as rtc_slow_freq_t, except that we define
|
||||
* an extra enum member for the external 32k oscillator.
|
||||
* For convenience, lower 2 bits should correspond to rtc_slow_freq_t values.
|
||||
*/
|
||||
typedef enum {
|
||||
SLOW_CLK_150K = RTC_SLOW_FREQ_RTC, //!< Internal 150 kHz RC oscillator
|
||||
SLOW_CLK_32K_XTAL = RTC_SLOW_FREQ_32K_XTAL, //!< External 32 kHz XTAL
|
||||
SLOW_CLK_8MD256 = RTC_SLOW_FREQ_8MD256, //!< Internal 8 MHz RC oscillator, divided by 256
|
||||
SLOW_CLK_32K_EXT_OSC = RTC_SLOW_FREQ_32K_XTAL | EXT_OSC_FLAG //!< External 32k oscillator connected to 32K_XP pin
|
||||
} slow_clk_sel_t;
|
||||
|
||||
static void select_rtc_slow_clk(slow_clk_sel_t slow_clk);
|
||||
|
||||
// g_ticks_us defined in ROMs for PRO and APP CPU
|
||||
extern uint32_t g_ticks_per_us_pro;
|
||||
#ifndef CONFIG_FREERTOS_UNICORE
|
||||
extern uint32_t g_ticks_per_us_app;
|
||||
#endif
|
||||
|
||||
static const char* TAG = "clk";
|
||||
|
||||
|
||||
void esp_clk_init(void)
|
||||
{
|
||||
rtc_config_t cfg = RTC_CONFIG_DEFAULT();
|
||||
rtc_init(cfg);
|
||||
|
||||
#if (CONFIG_ESP32_COMPATIBLE_PRE_V2_1_BOOTLOADERS || CONFIG_ESP32_APP_INIT_CLK)
|
||||
/* Check the bootloader set the XTAL frequency.
|
||||
|
||||
Bootloaders pre-v2.1 don't do this.
|
||||
*/
|
||||
rtc_xtal_freq_t xtal_freq = rtc_clk_xtal_freq_get();
|
||||
if (xtal_freq == RTC_XTAL_FREQ_AUTO) {
|
||||
ESP_EARLY_LOGW(TAG, "RTC domain not initialised by bootloader");
|
||||
bootloader_clock_configure();
|
||||
}
|
||||
#else
|
||||
/* If this assertion fails, either upgrade the bootloader or enable CONFIG_ESP32_COMPATIBLE_PRE_V2_1_BOOTLOADERS */
|
||||
assert(rtc_clk_xtal_freq_get() != RTC_XTAL_FREQ_AUTO);
|
||||
#endif
|
||||
|
||||
rtc_clk_fast_freq_set(RTC_FAST_FREQ_8M);
|
||||
|
||||
#ifdef CONFIG_BOOTLOADER_WDT_ENABLE
|
||||
// WDT uses a SLOW_CLK clock source. After a function select_rtc_slow_clk a frequency of this source can changed.
|
||||
// If the frequency changes from 150kHz to 32kHz, then the timeout set for the WDT will increase 4.6 times.
|
||||
// Therefore, for the time of frequency change, set a new lower timeout value (1.6 sec).
|
||||
// This prevents excessive delay before resetting in case the supply voltage is drawdown.
|
||||
// (If frequency is changed from 150kHz to 32kHz then WDT timeout will increased to 1.6sec * 150/32 = 7.5 sec).
|
||||
wdt_hal_context_t rtc_wdt_ctx = {.inst = WDT_RWDT, .rwdt_dev = &RTCCNTL};
|
||||
uint32_t stage_timeout_ticks = (uint32_t)(1600ULL * rtc_clk_slow_freq_get_hz() / 1000ULL);
|
||||
wdt_hal_write_protect_disable(&rtc_wdt_ctx);
|
||||
wdt_hal_feed(&rtc_wdt_ctx);
|
||||
//Bootloader has enabled RTC WDT until now. We're only modifying timeout, so keep the stage and timeout action the same
|
||||
wdt_hal_config_stage(&rtc_wdt_ctx, WDT_STAGE0, stage_timeout_ticks, WDT_STAGE_ACTION_RESET_RTC);
|
||||
wdt_hal_write_protect_enable(&rtc_wdt_ctx);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_ESP32_RTC_CLK_SRC_EXT_CRYS)
|
||||
select_rtc_slow_clk(SLOW_CLK_32K_XTAL);
|
||||
#elif defined(CONFIG_ESP32_RTC_CLK_SRC_EXT_OSC)
|
||||
select_rtc_slow_clk(SLOW_CLK_32K_EXT_OSC);
|
||||
#elif defined(CONFIG_ESP32_RTC_CLK_SRC_INT_8MD256)
|
||||
select_rtc_slow_clk(SLOW_CLK_8MD256);
|
||||
#else
|
||||
select_rtc_slow_clk(RTC_SLOW_FREQ_RTC);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BOOTLOADER_WDT_ENABLE
|
||||
// After changing a frequency WDT timeout needs to be set for new frequency.
|
||||
stage_timeout_ticks = (uint32_t)((uint64_t)CONFIG_BOOTLOADER_WDT_TIME_MS * rtc_clk_slow_freq_get_hz() / 1000);
|
||||
wdt_hal_write_protect_disable(&rtc_wdt_ctx);
|
||||
wdt_hal_feed(&rtc_wdt_ctx);
|
||||
wdt_hal_config_stage(&rtc_wdt_ctx, WDT_STAGE0, stage_timeout_ticks, WDT_STAGE_ACTION_RESET_RTC);
|
||||
wdt_hal_write_protect_enable(&rtc_wdt_ctx);
|
||||
#endif
|
||||
|
||||
rtc_cpu_freq_config_t old_config, new_config;
|
||||
rtc_clk_cpu_freq_get_config(&old_config);
|
||||
const uint32_t old_freq_mhz = old_config.freq_mhz;
|
||||
const uint32_t new_freq_mhz = CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ;
|
||||
|
||||
bool res = rtc_clk_cpu_freq_mhz_to_config(new_freq_mhz, &new_config);
|
||||
assert(res);
|
||||
|
||||
// Wait for UART TX to finish, otherwise some UART output will be lost
|
||||
// when switching APB frequency
|
||||
uart_tx_wait_idle(CONFIG_ESP_CONSOLE_UART_NUM);
|
||||
|
||||
rtc_clk_cpu_freq_set_config(&new_config);
|
||||
|
||||
// Re calculate the ccount to make time calculation correct.
|
||||
XTHAL_SET_CCOUNT( (uint64_t)XTHAL_GET_CCOUNT() * new_freq_mhz / old_freq_mhz );
|
||||
}
|
||||
|
||||
int IRAM_ATTR esp_clk_cpu_freq(void)
|
||||
{
|
||||
return g_ticks_per_us_pro * MHZ;
|
||||
|
@ -178,176 +50,3 @@ void IRAM_ATTR ets_update_cpu_frequency(uint32_t ticks_per_us)
|
|||
g_ticks_per_us_app = ticks_per_us;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void select_rtc_slow_clk(slow_clk_sel_t slow_clk)
|
||||
{
|
||||
rtc_slow_freq_t rtc_slow_freq = slow_clk & RTC_CNTL_ANA_CLK_RTC_SEL_V;
|
||||
uint32_t cal_val = 0;
|
||||
/* number of times to repeat 32k XTAL calibration
|
||||
* before giving up and switching to the internal RC
|
||||
*/
|
||||
int retry_32k_xtal = RTC_XTAL_CAL_RETRY;
|
||||
|
||||
do {
|
||||
if (rtc_slow_freq == RTC_SLOW_FREQ_32K_XTAL) {
|
||||
/* 32k XTAL oscillator needs to be enabled and running before it can
|
||||
* be used. Hardware doesn't have a direct way of checking if the
|
||||
* oscillator is running. Here we use rtc_clk_cal function to count
|
||||
* the number of main XTAL cycles in the given number of 32k XTAL
|
||||
* oscillator cycles. If the 32k XTAL has not started up, calibration
|
||||
* will time out, returning 0.
|
||||
*/
|
||||
ESP_EARLY_LOGD(TAG, "waiting for 32k oscillator to start up");
|
||||
if (slow_clk == SLOW_CLK_32K_XTAL) {
|
||||
rtc_clk_32k_enable(true);
|
||||
} else if (slow_clk == SLOW_CLK_32K_EXT_OSC) {
|
||||
rtc_clk_32k_enable_external();
|
||||
}
|
||||
// When SLOW_CLK_CAL_CYCLES is set to 0, clock calibration will not be performed at startup.
|
||||
if (SLOW_CLK_CAL_CYCLES > 0) {
|
||||
cal_val = rtc_clk_cal(RTC_CAL_32K_XTAL, SLOW_CLK_CAL_CYCLES);
|
||||
if (cal_val == 0 || cal_val < MIN_32K_XTAL_CAL_VAL) {
|
||||
if (retry_32k_xtal-- > 0) {
|
||||
continue;
|
||||
}
|
||||
ESP_EARLY_LOGW(TAG, "32 kHz XTAL not found, switching to internal 150 kHz oscillator");
|
||||
rtc_slow_freq = RTC_SLOW_FREQ_RTC;
|
||||
}
|
||||
}
|
||||
} else if (rtc_slow_freq == RTC_SLOW_FREQ_8MD256) {
|
||||
rtc_clk_8m_enable(true, true);
|
||||
}
|
||||
rtc_clk_slow_freq_set(rtc_slow_freq);
|
||||
|
||||
if (SLOW_CLK_CAL_CYCLES > 0) {
|
||||
/* TODO: 32k XTAL oscillator has some frequency drift at startup.
|
||||
* Improve calibration routine to wait until the frequency is stable.
|
||||
*/
|
||||
cal_val = rtc_clk_cal(RTC_CAL_RTC_MUX, SLOW_CLK_CAL_CYCLES);
|
||||
} else {
|
||||
const uint64_t cal_dividend = (1ULL << RTC_CLK_CAL_FRACT) * 1000000ULL;
|
||||
cal_val = (uint32_t) (cal_dividend / rtc_clk_slow_freq_get_hz());
|
||||
}
|
||||
} while (cal_val == 0);
|
||||
ESP_EARLY_LOGD(TAG, "RTC_SLOW_CLK calibration value: %d", cal_val);
|
||||
esp_clk_slowclk_cal_set(cal_val);
|
||||
}
|
||||
|
||||
void rtc_clk_select_rtc_slow_clk(void)
|
||||
{
|
||||
select_rtc_slow_clk(RTC_SLOW_FREQ_32K_XTAL);
|
||||
}
|
||||
|
||||
/* This function is not exposed as an API at this point.
|
||||
* All peripheral clocks are default enabled after chip is powered on.
|
||||
* This function disables some peripheral clocks when cpu starts.
|
||||
* These peripheral clocks are enabled when the peripherals are initialized
|
||||
* and disabled when they are de-initialized.
|
||||
*/
|
||||
void esp_perip_clk_init(void)
|
||||
{
|
||||
uint32_t common_perip_clk, hwcrypto_perip_clk, wifi_bt_sdio_clk = 0;
|
||||
|
||||
#if CONFIG_FREERTOS_UNICORE
|
||||
RESET_REASON rst_reas[1];
|
||||
#else
|
||||
RESET_REASON rst_reas[2];
|
||||
#endif
|
||||
|
||||
rst_reas[0] = rtc_get_reset_reason(0);
|
||||
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
rst_reas[1] = rtc_get_reset_reason(1);
|
||||
#endif
|
||||
|
||||
/* For reason that only reset CPU, do not disable the clocks
|
||||
* that have been enabled before reset.
|
||||
*/
|
||||
if ((rst_reas[0] >= TGWDT_CPU_RESET && rst_reas[0] <= RTCWDT_CPU_RESET)
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
|| (rst_reas[1] >= TGWDT_CPU_RESET && rst_reas[1] <= RTCWDT_CPU_RESET)
|
||||
#endif
|
||||
) {
|
||||
common_perip_clk = ~DPORT_READ_PERI_REG(DPORT_PERIP_CLK_EN_REG);
|
||||
hwcrypto_perip_clk = ~DPORT_READ_PERI_REG(DPORT_PERI_CLK_EN_REG);
|
||||
wifi_bt_sdio_clk = ~DPORT_READ_PERI_REG(DPORT_WIFI_CLK_EN_REG);
|
||||
}
|
||||
else {
|
||||
common_perip_clk = DPORT_WDG_CLK_EN |
|
||||
DPORT_PCNT_CLK_EN |
|
||||
DPORT_LEDC_CLK_EN |
|
||||
DPORT_TIMERGROUP1_CLK_EN |
|
||||
DPORT_PWM0_CLK_EN |
|
||||
DPORT_CAN_CLK_EN |
|
||||
DPORT_PWM1_CLK_EN |
|
||||
DPORT_PWM2_CLK_EN |
|
||||
DPORT_PWM3_CLK_EN;
|
||||
hwcrypto_perip_clk = DPORT_PERI_EN_AES |
|
||||
DPORT_PERI_EN_SHA |
|
||||
DPORT_PERI_EN_RSA |
|
||||
DPORT_PERI_EN_SECUREBOOT;
|
||||
wifi_bt_sdio_clk = DPORT_WIFI_CLK_WIFI_EN |
|
||||
DPORT_WIFI_CLK_BT_EN_M |
|
||||
DPORT_WIFI_CLK_UNUSED_BIT5 |
|
||||
DPORT_WIFI_CLK_UNUSED_BIT12 |
|
||||
DPORT_WIFI_CLK_SDIOSLAVE_EN |
|
||||
DPORT_WIFI_CLK_SDIO_HOST_EN |
|
||||
DPORT_WIFI_CLK_EMAC_EN;
|
||||
}
|
||||
|
||||
//Reset the communication peripherals like I2C, SPI, UART, I2S and bring them to known state.
|
||||
common_perip_clk |= DPORT_I2S0_CLK_EN |
|
||||
#if CONFIG_ESP_CONSOLE_UART_NUM != 0
|
||||
DPORT_UART_CLK_EN |
|
||||
#endif
|
||||
#if CONFIG_ESP_CONSOLE_UART_NUM != 1
|
||||
DPORT_UART1_CLK_EN |
|
||||
#endif
|
||||
#if CONFIG_ESP_CONSOLE_UART_NUM != 2
|
||||
DPORT_UART2_CLK_EN |
|
||||
#endif
|
||||
DPORT_SPI2_CLK_EN |
|
||||
DPORT_I2C_EXT0_CLK_EN |
|
||||
DPORT_UHCI0_CLK_EN |
|
||||
DPORT_RMT_CLK_EN |
|
||||
DPORT_UHCI1_CLK_EN |
|
||||
DPORT_SPI3_CLK_EN |
|
||||
DPORT_I2C_EXT1_CLK_EN |
|
||||
DPORT_I2S1_CLK_EN |
|
||||
DPORT_SPI_DMA_CLK_EN;
|
||||
|
||||
common_perip_clk &= ~DPORT_SPI01_CLK_EN;
|
||||
|
||||
#if CONFIG_SPIRAM_SPEED_80M
|
||||
//80MHz SPIRAM uses SPI2/SPI3 as well; it's initialized before this is called. Because it is used in
|
||||
//a weird mode where clock to the peripheral is disabled but reset is also disabled, it 'hangs'
|
||||
//in a state where it outputs a continuous 80MHz signal. Mask its bit here because we should
|
||||
//not modify that state, regardless of what we calculated earlier.
|
||||
if (spicommon_periph_in_use(HSPI_HOST)) {
|
||||
common_perip_clk &= ~DPORT_SPI2_CLK_EN;
|
||||
}
|
||||
if (spicommon_periph_in_use(VSPI_HOST)) {
|
||||
common_perip_clk &= ~DPORT_SPI3_CLK_EN;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Change I2S clock to audio PLL first. Because if I2S uses 160MHz clock,
|
||||
* the current is not reduced when disable I2S clock.
|
||||
*/
|
||||
DPORT_SET_PERI_REG_MASK(I2S_CLKM_CONF_REG(0), I2S_CLKA_ENA);
|
||||
DPORT_SET_PERI_REG_MASK(I2S_CLKM_CONF_REG(1), I2S_CLKA_ENA);
|
||||
|
||||
/* Disable some peripheral clocks. */
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, common_perip_clk);
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, common_perip_clk);
|
||||
|
||||
/* Disable hardware crypto clocks. */
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERI_CLK_EN_REG, hwcrypto_perip_clk);
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERI_RST_EN_REG, hwcrypto_perip_clk);
|
||||
|
||||
/* Disable WiFi/BT/SDIO clocks. */
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_WIFI_CLK_EN_REG, wifi_bt_sdio_clk);
|
||||
|
||||
/* Enable RNG clock. */
|
||||
periph_module_enable(PERIPH_RNG_MODULE);
|
||||
}
|
||||
|
|
|
@ -1,592 +0,0 @@
|
|||
// Copyright 2015-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 <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "esp_attr.h"
|
||||
#include "esp_err.h"
|
||||
|
||||
#include "esp32/rom/ets_sys.h"
|
||||
#include "esp32/rom/uart.h"
|
||||
#include "esp32/rom/rtc.h"
|
||||
#include "esp32/rom/cache.h"
|
||||
|
||||
#include "soc/cpu.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "soc/dport_reg.h"
|
||||
#include "soc/gpio_periph.h"
|
||||
#include "soc/timer_periph.h"
|
||||
#include "soc/efuse_periph.h"
|
||||
|
||||
#include "hal/wdt_hal.h"
|
||||
|
||||
#include "driver/rtc_io.h"
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "freertos/queue.h"
|
||||
|
||||
#include "esp_heap_caps_init.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_system.h"
|
||||
#include "esp_spi_flash.h"
|
||||
#include "esp_flash_internal.h"
|
||||
#include "nvs_flash.h"
|
||||
#include "esp_spi_flash.h"
|
||||
#include "esp_private/crosscore_int.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_vfs_dev.h"
|
||||
#include "esp_newlib.h"
|
||||
#include "esp32/brownout.h"
|
||||
#include "esp_int_wdt.h"
|
||||
#include "esp_task.h"
|
||||
#include "esp_task_wdt.h"
|
||||
#include "esp_phy_init.h"
|
||||
#include "esp32/cache_err_int.h"
|
||||
#include "esp_coexist_internal.h"
|
||||
#include "esp_core_dump.h"
|
||||
#include "esp_app_trace.h"
|
||||
#include "esp_private/dbg_stubs.h"
|
||||
#include "esp_flash_encrypt.h"
|
||||
#include "esp32/spiram.h"
|
||||
#include "esp_clk_internal.h"
|
||||
#include "esp_timer.h"
|
||||
#include "esp_pm.h"
|
||||
#include "esp_private/pm_impl.h"
|
||||
#include "trax.h"
|
||||
#include "esp_ota_ops.h"
|
||||
#include "esp_efuse.h"
|
||||
#include "bootloader_flash_config.h"
|
||||
#include "bootloader_mem.h"
|
||||
|
||||
#ifdef CONFIG_APP_BUILD_TYPE_ELF_RAM
|
||||
#include "esp32/rom/efuse.h"
|
||||
#include "esp32/rom/spi_flash.h"
|
||||
#endif // CONFIG_APP_BUILD_TYPE_ELF_RAM
|
||||
|
||||
#define STRINGIFY(s) STRINGIFY2(s)
|
||||
#define STRINGIFY2(s) #s
|
||||
|
||||
void start_cpu0(void) __attribute__((weak, alias("start_cpu0_default"))) __attribute__((noreturn));
|
||||
void start_cpu0_default(void) IRAM_ATTR __attribute__((noreturn));
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
static void IRAM_ATTR call_start_cpu1(void) __attribute__((noreturn));
|
||||
void start_cpu1(void) __attribute__((weak, alias("start_cpu1_default"))) __attribute__((noreturn));
|
||||
void start_cpu1_default(void) IRAM_ATTR __attribute__((noreturn));
|
||||
static bool app_cpu_started = false;
|
||||
#endif //!CONFIG_FREERTOS_UNICORE
|
||||
|
||||
static void do_global_ctors(void);
|
||||
static void main_task(void* args);
|
||||
extern void app_main(void);
|
||||
extern esp_err_t esp_pthread_init(void);
|
||||
|
||||
extern int _bss_start;
|
||||
extern int _bss_end;
|
||||
extern int _rtc_bss_start;
|
||||
extern int _rtc_bss_end;
|
||||
#ifdef CONFIG_ESP32_IRAM_AS_8BIT_ACCESSIBLE_MEMORY
|
||||
extern int _iram_bss_start;
|
||||
extern int _iram_bss_end;
|
||||
#endif
|
||||
#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY
|
||||
extern int _ext_ram_bss_start;
|
||||
extern int _ext_ram_bss_end;
|
||||
#endif
|
||||
extern int _init_start;
|
||||
extern void (*__init_array_start)(void);
|
||||
extern void (*__init_array_end)(void);
|
||||
extern volatile int port_xSchedulerRunning[2];
|
||||
|
||||
static const char* TAG = "cpu_start";
|
||||
|
||||
struct object { long placeholder[ 10 ]; };
|
||||
void __register_frame_info (const void *begin, struct object *ob);
|
||||
extern char __eh_frame[];
|
||||
|
||||
//If CONFIG_SPIRAM_IGNORE_NOTFOUND is set and external RAM is not found or errors out on testing, this is set to false.
|
||||
static bool s_spiram_okay=true;
|
||||
|
||||
/*
|
||||
* We arrive here after the bootloader finished loading the program from flash. The hardware is mostly uninitialized,
|
||||
* and the app CPU is in reset. We do have a stack, so we can do the initialization in C.
|
||||
*/
|
||||
|
||||
void IRAM_ATTR call_start_cpu0(void)
|
||||
{
|
||||
#if CONFIG_FREERTOS_UNICORE
|
||||
RESET_REASON rst_reas[1];
|
||||
#else
|
||||
RESET_REASON rst_reas[2];
|
||||
#endif
|
||||
|
||||
bootloader_init_mem();
|
||||
|
||||
// Move exception vectors to IRAM
|
||||
cpu_hal_set_vecbase(&_init_start);
|
||||
|
||||
rst_reas[0] = rtc_get_reset_reason(0);
|
||||
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
rst_reas[1] = rtc_get_reset_reason(1);
|
||||
#endif
|
||||
|
||||
// from panic handler we can be reset by RWDT or TG0WDT
|
||||
if (rst_reas[0] == RTCWDT_SYS_RESET || rst_reas[0] == TG0WDT_SYS_RESET
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
|| rst_reas[1] == RTCWDT_SYS_RESET || rst_reas[1] == TG0WDT_SYS_RESET
|
||||
#endif
|
||||
) {
|
||||
#ifndef CONFIG_BOOTLOADER_WDT_ENABLE
|
||||
wdt_hal_context_t rtc_wdt_ctx = {.inst = WDT_RWDT, .rwdt_dev = &RTCCNTL};
|
||||
wdt_hal_write_protect_disable(&rtc_wdt_ctx);
|
||||
wdt_hal_disable(&rtc_wdt_ctx);
|
||||
wdt_hal_write_protect_enable(&rtc_wdt_ctx);
|
||||
#endif
|
||||
}
|
||||
|
||||
//Clear BSS. Please do not attempt to do any complex stuff (like early logging) before this.
|
||||
memset(&_bss_start, 0, (&_bss_end - &_bss_start) * sizeof(_bss_start));
|
||||
|
||||
#ifdef CONFIG_ESP32_IRAM_AS_8BIT_ACCESSIBLE_MEMORY
|
||||
// Clear IRAM BSS
|
||||
memset(&_iram_bss_start, 0, (&_iram_bss_end - &_iram_bss_start) * sizeof(_iram_bss_start));
|
||||
#endif
|
||||
|
||||
/* Unless waking from deep sleep (implying RTC memory is intact), clear RTC bss */
|
||||
if (rst_reas[0] != DEEPSLEEP_RESET) {
|
||||
memset(&_rtc_bss_start, 0, (&_rtc_bss_end - &_rtc_bss_start) * sizeof(_rtc_bss_start));
|
||||
}
|
||||
|
||||
#if CONFIG_SPIRAM_BOOT_INIT
|
||||
esp_spiram_init_cache();
|
||||
if (esp_spiram_init() != ESP_OK) {
|
||||
#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY
|
||||
ESP_EARLY_LOGE(TAG, "Failed to init external RAM, needed for external .bss segment");
|
||||
abort();
|
||||
#endif
|
||||
|
||||
#if CONFIG_SPIRAM_IGNORE_NOTFOUND
|
||||
ESP_EARLY_LOGI(TAG, "Failed to init external RAM; continuing without it.");
|
||||
s_spiram_okay = false;
|
||||
#else
|
||||
ESP_EARLY_LOGE(TAG, "Failed to init external RAM!");
|
||||
abort();
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
ESP_EARLY_LOGI(TAG, "Pro cpu up.");
|
||||
if (LOG_LOCAL_LEVEL >= ESP_LOG_INFO) {
|
||||
const esp_app_desc_t *app_desc = esp_ota_get_app_description();
|
||||
ESP_EARLY_LOGI(TAG, "Application information:");
|
||||
#ifndef CONFIG_APP_EXCLUDE_PROJECT_NAME_VAR
|
||||
ESP_EARLY_LOGI(TAG, "Project name: %s", app_desc->project_name);
|
||||
#endif
|
||||
#ifndef CONFIG_APP_EXCLUDE_PROJECT_VER_VAR
|
||||
ESP_EARLY_LOGI(TAG, "App version: %s", app_desc->version);
|
||||
#endif
|
||||
#ifdef CONFIG_BOOTLOADER_APP_SECURE_VERSION
|
||||
ESP_EARLY_LOGI(TAG, "Secure version: %d", app_desc->secure_version);
|
||||
#endif
|
||||
#ifdef CONFIG_APP_COMPILE_TIME_DATE
|
||||
ESP_EARLY_LOGI(TAG, "Compile time: %s %s", app_desc->date, app_desc->time);
|
||||
#endif
|
||||
char buf[17];
|
||||
esp_ota_get_app_elf_sha256(buf, sizeof(buf));
|
||||
ESP_EARLY_LOGI(TAG, "ELF file SHA256: %s...", buf);
|
||||
ESP_EARLY_LOGI(TAG, "ESP-IDF: %s", app_desc->idf_ver);
|
||||
}
|
||||
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
if (REG_GET_BIT(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_VER_DIS_APP_CPU)) {
|
||||
ESP_EARLY_LOGE(TAG, "Running on single core chip, but application is built with dual core support.");
|
||||
ESP_EARLY_LOGE(TAG, "Please enable CONFIG_FREERTOS_UNICORE option in menuconfig.");
|
||||
abort();
|
||||
}
|
||||
ESP_EARLY_LOGI(TAG, "Starting app cpu, entry point is %p", call_start_cpu1);
|
||||
|
||||
//Flush and enable icache for APP CPU
|
||||
Cache_Flush(1);
|
||||
Cache_Read_Enable(1);
|
||||
esp_cpu_unstall(1);
|
||||
// Enable clock and reset APP CPU. Note that OpenOCD may have already
|
||||
// enabled clock and taken APP CPU out of reset. In this case don't reset
|
||||
// APP CPU again, as that will clear the breakpoints which may have already
|
||||
// been set.
|
||||
if (!DPORT_GET_PERI_REG_MASK(DPORT_APPCPU_CTRL_B_REG, DPORT_APPCPU_CLKGATE_EN)) {
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_APPCPU_CTRL_B_REG, DPORT_APPCPU_CLKGATE_EN);
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_APPCPU_CTRL_C_REG, DPORT_APPCPU_RUNSTALL);
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_APPCPU_CTRL_A_REG, DPORT_APPCPU_RESETTING);
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_APPCPU_CTRL_A_REG, DPORT_APPCPU_RESETTING);
|
||||
}
|
||||
ets_set_appcpu_boot_addr((uint32_t)call_start_cpu1);
|
||||
|
||||
while (!app_cpu_started) {
|
||||
ets_delay_us(100);
|
||||
}
|
||||
#else
|
||||
ESP_EARLY_LOGI(TAG, "Single core mode");
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_APPCPU_CTRL_B_REG, DPORT_APPCPU_CLKGATE_EN);
|
||||
#endif
|
||||
|
||||
|
||||
#if CONFIG_SPIRAM_MEMTEST
|
||||
if (s_spiram_okay) {
|
||||
bool ext_ram_ok=esp_spiram_test();
|
||||
if (!ext_ram_ok) {
|
||||
ESP_EARLY_LOGE(TAG, "External RAM failed memory test!");
|
||||
abort();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY
|
||||
memset(&_ext_ram_bss_start, 0, (&_ext_ram_bss_end - &_ext_ram_bss_start) * sizeof(_ext_ram_bss_start));
|
||||
#endif
|
||||
/* Initialize heap allocator. WARNING: This *needs* to happen *after* the app cpu has booted.
|
||||
If the heap allocator is initialized first, it will put free memory linked list items into
|
||||
memory also used by the ROM. Starting the app cpu will let its ROM initialize that memory,
|
||||
corrupting those linked lists. Initializing the allocator *after* the app cpu has booted
|
||||
works around this problem.
|
||||
With SPI RAM enabled, there's a second reason: half of the SPI RAM will be managed by the
|
||||
app CPU, and when that is not up yet, the memory will be inaccessible and heap_caps_init may
|
||||
fail initializing it properly. */
|
||||
heap_caps_init();
|
||||
|
||||
ESP_EARLY_LOGI(TAG, "Pro cpu start user code");
|
||||
start_cpu0();
|
||||
}
|
||||
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
|
||||
static void wdt_reset_cpu1_info_enable(void)
|
||||
{
|
||||
DPORT_REG_SET_BIT(DPORT_APP_CPU_RECORD_CTRL_REG, DPORT_APP_CPU_PDEBUG_ENABLE | DPORT_APP_CPU_RECORD_ENABLE);
|
||||
DPORT_REG_CLR_BIT(DPORT_APP_CPU_RECORD_CTRL_REG, DPORT_APP_CPU_RECORD_ENABLE);
|
||||
}
|
||||
|
||||
void IRAM_ATTR call_start_cpu1(void)
|
||||
{
|
||||
// Move exception vectors to IRAM
|
||||
cpu_hal_set_vecbase(&_init_start);
|
||||
|
||||
ets_set_appcpu_boot_addr(0);
|
||||
|
||||
bootloader_init_mem();
|
||||
|
||||
#if CONFIG_ESP_CONSOLE_UART_NONE
|
||||
ets_install_putc1(NULL);
|
||||
ets_install_putc2(NULL);
|
||||
#else // CONFIG_ESP_CONSOLE_UART_NONE
|
||||
uartAttach();
|
||||
ets_install_uart_printf();
|
||||
uart_tx_switch(CONFIG_ESP_CONSOLE_UART_NUM);
|
||||
#endif
|
||||
|
||||
wdt_reset_cpu1_info_enable();
|
||||
ESP_EARLY_LOGI(TAG, "App cpu up.");
|
||||
app_cpu_started = 1;
|
||||
start_cpu1();
|
||||
}
|
||||
#endif //!CONFIG_FREERTOS_UNICORE
|
||||
|
||||
static void intr_matrix_clear(void)
|
||||
{
|
||||
//Clear all the interrupt matrix register
|
||||
for (int i = ETS_WIFI_MAC_INTR_SOURCE; i <= ETS_CACHE_IA_INTR_SOURCE; i++) {
|
||||
intr_matrix_set(0, i, ETS_INVALID_INUM);
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
intr_matrix_set(1, i, ETS_INVALID_INUM);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void start_cpu0_default(void)
|
||||
{
|
||||
esp_err_t err;
|
||||
esp_setup_syscall_table();
|
||||
|
||||
if (s_spiram_okay) {
|
||||
#if CONFIG_SPIRAM_BOOT_INIT && (CONFIG_SPIRAM_USE_CAPS_ALLOC || CONFIG_SPIRAM_USE_MALLOC)
|
||||
esp_err_t r=esp_spiram_add_to_heapalloc();
|
||||
if (r != ESP_OK) {
|
||||
ESP_EARLY_LOGE(TAG, "External RAM could not be added to heap!");
|
||||
abort();
|
||||
}
|
||||
#if CONFIG_SPIRAM_USE_MALLOC
|
||||
heap_caps_malloc_extmem_enable(CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
//Enable trace memory and immediately start trace.
|
||||
#if CONFIG_ESP32_TRAX
|
||||
#if CONFIG_ESP32_TRAX_TWOBANKS
|
||||
trax_enable(TRAX_ENA_PRO_APP);
|
||||
#else
|
||||
trax_enable(TRAX_ENA_PRO);
|
||||
#endif
|
||||
trax_start_trace(TRAX_DOWNCOUNT_WORDS);
|
||||
#endif
|
||||
esp_clk_init();
|
||||
esp_perip_clk_init();
|
||||
intr_matrix_clear();
|
||||
|
||||
#ifndef CONFIG_ESP_CONSOLE_UART_NONE
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
const int uart_clk_freq = REF_CLK_FREQ;
|
||||
/* When DFS is enabled, use REFTICK as UART clock source */
|
||||
CLEAR_PERI_REG_MASK(UART_CONF0_REG(CONFIG_ESP_CONSOLE_UART_NUM), UART_TICK_REF_ALWAYS_ON);
|
||||
#else
|
||||
const int uart_clk_freq = APB_CLK_FREQ;
|
||||
#endif // CONFIG_PM_DFS_ENABLE
|
||||
uart_div_modify(CONFIG_ESP_CONSOLE_UART_NUM, (uart_clk_freq << 4) / CONFIG_ESP_CONSOLE_UART_BAUDRATE);
|
||||
#endif // CONFIG_ESP_CONSOLE_UART_NONE
|
||||
|
||||
#if CONFIG_ESP32_BROWNOUT_DET
|
||||
esp_brownout_init();
|
||||
#endif
|
||||
|
||||
rtc_gpio_force_hold_dis_all();
|
||||
|
||||
#ifdef CONFIG_VFS_SUPPORT_IO
|
||||
esp_vfs_dev_uart_register();
|
||||
#endif // CONFIG_VFS_SUPPORT_IO
|
||||
|
||||
#if defined(CONFIG_VFS_SUPPORT_IO) && !defined(CONFIG_ESP_CONSOLE_UART_NONE)
|
||||
esp_reent_init(_GLOBAL_REENT);
|
||||
const char* default_uart_dev = "/dev/uart/" STRINGIFY(CONFIG_ESP_CONSOLE_UART_NUM);
|
||||
_GLOBAL_REENT->_stdin = fopen(default_uart_dev, "r");
|
||||
_GLOBAL_REENT->_stdout = fopen(default_uart_dev, "w");
|
||||
_GLOBAL_REENT->_stderr = fopen(default_uart_dev, "w");
|
||||
#else // defined(CONFIG_VFS_SUPPORT_IO) && !defined(CONFIG_ESP_CONSOLE_UART_NONE)
|
||||
_REENT_SMALL_CHECK_INIT(_GLOBAL_REENT);
|
||||
#endif // defined(CONFIG_VFS_SUPPORT_IO) && !defined(CONFIG_ESP_CONSOLE_UART_NONE)
|
||||
// After setting _GLOBAL_REENT, ESP_LOGIx can be used instead of ESP_EARLY_LOGx.
|
||||
|
||||
#ifdef CONFIG_SECURE_FLASH_ENC_ENABLED
|
||||
esp_flash_encryption_init_checks();
|
||||
#endif
|
||||
#if CONFIG_ESP32_DISABLE_BASIC_ROM_CONSOLE
|
||||
esp_efuse_disable_basic_rom_console();
|
||||
#endif
|
||||
#if CONFIG_SECURE_DISABLE_ROM_DL_MODE
|
||||
esp_efuse_disable_rom_download_mode();
|
||||
#endif
|
||||
|
||||
esp_timer_init();
|
||||
esp_set_time_from_rtc();
|
||||
#if CONFIG_APPTRACE_ENABLE
|
||||
err = esp_apptrace_init();
|
||||
assert(err == ESP_OK && "Failed to init apptrace module on PRO CPU!");
|
||||
#endif
|
||||
#if CONFIG_SYSVIEW_ENABLE
|
||||
SEGGER_SYSVIEW_Conf();
|
||||
#endif
|
||||
#if CONFIG_ESP_DEBUG_STUBS_ENABLE
|
||||
esp_dbg_stubs_init();
|
||||
#endif
|
||||
err = esp_pthread_init();
|
||||
assert(err == ESP_OK && "Failed to init pthread module!");
|
||||
|
||||
do_global_ctors();
|
||||
#if CONFIG_ESP_INT_WDT
|
||||
esp_int_wdt_init();
|
||||
//Initialize the interrupt watch dog for CPU0.
|
||||
esp_int_wdt_cpu_init();
|
||||
#else
|
||||
#if CONFIG_ESP32_ECO3_CACHE_LOCK_FIX
|
||||
assert(!soc_has_cache_lock_bug() && "ESP32 Rev 3 + Dual Core + PSRAM requires INT WDT enabled in project config!");
|
||||
#endif
|
||||
#endif
|
||||
esp_cache_err_int_init();
|
||||
esp_crosscore_int_init();
|
||||
#ifndef CONFIG_FREERTOS_UNICORE
|
||||
esp_dport_access_int_init();
|
||||
#endif
|
||||
|
||||
bootloader_flash_update_id();
|
||||
#if !CONFIG_SPIRAM_BOOT_INIT
|
||||
// Read the application binary image header. This will also decrypt the header if the image is encrypted.
|
||||
esp_image_header_t fhdr = {0};
|
||||
#ifdef CONFIG_APP_BUILD_TYPE_ELF_RAM
|
||||
fhdr.spi_mode = ESP_IMAGE_SPI_MODE_DIO;
|
||||
fhdr.spi_speed = ESP_IMAGE_SPI_SPEED_40M;
|
||||
fhdr.spi_size = ESP_IMAGE_FLASH_SIZE_4MB;
|
||||
|
||||
extern void esp_rom_spiflash_attach(uint32_t, bool);
|
||||
esp_rom_spiflash_attach(ets_efuse_get_spiconfig(), false);
|
||||
esp_rom_spiflash_unlock();
|
||||
#else
|
||||
// This assumes that DROM is the first segment in the application binary, i.e. that we can read
|
||||
// the binary header through cache by accessing SOC_DROM_LOW address.
|
||||
memcpy(&fhdr, (void*) SOC_DROM_LOW, sizeof(fhdr));
|
||||
#endif // CONFIG_APP_BUILD_TYPE_ELF_RAM
|
||||
|
||||
// If psram is uninitialized, we need to improve some flash configuration.
|
||||
bootloader_flash_clock_config(&fhdr);
|
||||
bootloader_flash_gpio_config(&fhdr);
|
||||
bootloader_flash_dummy_config(&fhdr);
|
||||
bootloader_flash_cs_timing_config();
|
||||
#endif //!CONFIG_SPIRAM_BOOT_INIT
|
||||
|
||||
spi_flash_init();
|
||||
/* init default OS-aware flash access critical section */
|
||||
spi_flash_guard_set(&g_flash_guard_default_ops);
|
||||
|
||||
esp_flash_app_init();
|
||||
esp_err_t flash_ret = esp_flash_init_default_chip();
|
||||
assert(flash_ret == ESP_OK);
|
||||
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
esp_pm_impl_init();
|
||||
#ifdef CONFIG_PM_DFS_INIT_AUTO
|
||||
int xtal_freq = (int) rtc_clk_xtal_freq_get();
|
||||
esp_pm_config_esp32_t cfg = {
|
||||
.max_freq_mhz = CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ,
|
||||
.min_freq_mhz = xtal_freq,
|
||||
};
|
||||
esp_pm_configure(&cfg);
|
||||
#endif //CONFIG_PM_DFS_INIT_AUTO
|
||||
#endif //CONFIG_PM_ENABLE
|
||||
|
||||
#if CONFIG_ESP32_ENABLE_COREDUMP
|
||||
esp_core_dump_init();
|
||||
#endif
|
||||
|
||||
#if CONFIG_ESP32_WIFI_SW_COEXIST_ENABLE
|
||||
esp_coex_adapter_register(&g_coex_adapter_funcs);
|
||||
coex_pre_init();
|
||||
#endif
|
||||
|
||||
portBASE_TYPE res = xTaskCreatePinnedToCore(&main_task, "main",
|
||||
ESP_TASK_MAIN_STACK, NULL,
|
||||
ESP_TASK_MAIN_PRIO, NULL, 0);
|
||||
assert(res == pdTRUE);
|
||||
ESP_LOGI(TAG, "Starting scheduler on PRO CPU.");
|
||||
vTaskStartScheduler();
|
||||
abort(); /* Only get to here if not enough free heap to start scheduler */
|
||||
}
|
||||
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
void start_cpu1_default(void)
|
||||
{
|
||||
// Wait for FreeRTOS initialization to finish on PRO CPU
|
||||
while (port_xSchedulerRunning[0] == 0) {
|
||||
;
|
||||
}
|
||||
#if CONFIG_ESP32_TRAX_TWOBANKS
|
||||
trax_start_trace(TRAX_DOWNCOUNT_WORDS);
|
||||
#endif
|
||||
#if CONFIG_APPTRACE_ENABLE
|
||||
esp_err_t err = esp_apptrace_init();
|
||||
assert(err == ESP_OK && "Failed to init apptrace module on APP CPU!");
|
||||
#endif
|
||||
#if CONFIG_ESP_INT_WDT
|
||||
//Initialize the interrupt watch dog for CPU1.
|
||||
esp_int_wdt_cpu_init();
|
||||
#endif
|
||||
//Take care putting stuff here: if asked, FreeRTOS will happily tell you the scheduler
|
||||
//has started, but it isn't active *on this CPU* yet.
|
||||
esp_cache_err_int_init();
|
||||
esp_crosscore_int_init();
|
||||
esp_dport_access_int_init();
|
||||
|
||||
ESP_EARLY_LOGI(TAG, "Starting scheduler on APP CPU.");
|
||||
xPortStartScheduler();
|
||||
abort(); /* Only get to here if FreeRTOS somehow very broken */
|
||||
}
|
||||
#endif //!CONFIG_FREERTOS_UNICORE
|
||||
|
||||
#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
|
||||
size_t __cxx_eh_arena_size_get(void)
|
||||
{
|
||||
return CONFIG_COMPILER_CXX_EXCEPTIONS_EMG_POOL_SIZE;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void do_global_ctors(void)
|
||||
{
|
||||
#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
|
||||
static struct object ob;
|
||||
__register_frame_info( __eh_frame, &ob );
|
||||
#endif
|
||||
|
||||
void (**p)(void);
|
||||
for (p = &__init_array_end - 1; p >= &__init_array_start; --p) {
|
||||
(*p)();
|
||||
}
|
||||
}
|
||||
|
||||
static void main_task(void* args)
|
||||
{
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
// Wait for FreeRTOS initialization to finish on APP CPU, before replacing its startup stack
|
||||
while (port_xSchedulerRunning[1] == 0) {
|
||||
;
|
||||
}
|
||||
#endif
|
||||
//Enable allocation in region where the startup stacks were located.
|
||||
heap_caps_enable_nonos_stack_heaps();
|
||||
|
||||
// Now we have startup stack RAM available for heap, enable any DMA pool memory
|
||||
#if CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL
|
||||
esp_err_t r = esp_spiram_reserve_dma_pool(CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL);
|
||||
if (r != ESP_OK) {
|
||||
ESP_EARLY_LOGE(TAG, "Could not reserve internal/DMA pool (error 0x%x)", r);
|
||||
abort();
|
||||
}
|
||||
#endif
|
||||
|
||||
//Initialize task wdt if configured to do so
|
||||
#ifdef CONFIG_ESP_TASK_WDT_PANIC
|
||||
ESP_ERROR_CHECK(esp_task_wdt_init(CONFIG_ESP_TASK_WDT_TIMEOUT_S, true));
|
||||
#elif CONFIG_ESP_TASK_WDT
|
||||
ESP_ERROR_CHECK(esp_task_wdt_init(CONFIG_ESP_TASK_WDT_TIMEOUT_S, false));
|
||||
#endif
|
||||
|
||||
//Add IDLE 0 to task wdt
|
||||
#ifdef CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0
|
||||
TaskHandle_t idle_0 = xTaskGetIdleTaskHandleForCPU(0);
|
||||
if(idle_0 != NULL){
|
||||
ESP_ERROR_CHECK(esp_task_wdt_add(idle_0));
|
||||
}
|
||||
#endif
|
||||
//Add IDLE 1 to task wdt
|
||||
#ifdef CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1
|
||||
TaskHandle_t idle_1 = xTaskGetIdleTaskHandleForCPU(1);
|
||||
if(idle_1 != NULL){
|
||||
ESP_ERROR_CHECK(esp_task_wdt_add(idle_1));
|
||||
}
|
||||
#endif
|
||||
|
||||
// Now that the application is about to start, disable boot watchdog
|
||||
#ifndef CONFIG_BOOTLOADER_WDT_DISABLE_IN_USER_CODE
|
||||
wdt_hal_context_t rtc_wdt_ctx = {.inst = WDT_RWDT, .rwdt_dev = &RTCCNTL};
|
||||
wdt_hal_write_protect_disable(&rtc_wdt_ctx);
|
||||
wdt_hal_disable(&rtc_wdt_ctx);
|
||||
wdt_hal_write_protect_enable(&rtc_wdt_ctx);
|
||||
#endif
|
||||
#ifdef CONFIG_BOOTLOADER_EFUSE_SECURE_VERSION_EMULATE
|
||||
const esp_partition_t *efuse_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_EFUSE_EM, NULL);
|
||||
if (efuse_partition) {
|
||||
esp_efuse_init(efuse_partition->address, efuse_partition->size);
|
||||
}
|
||||
#endif
|
||||
app_main();
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
|
@ -208,6 +208,10 @@ SECTIONS
|
|||
_coredump_dram_end = ABSOLUTE(.);
|
||||
|
||||
/* should be placed after coredump mapping */
|
||||
_esp_system_init_fn_array_start = ABSOLUTE(.);
|
||||
KEEP (*(SORT(.esp_system_init_fn) SORT(.esp_system_init_fn.*)))
|
||||
_esp_system_init_fn_array_end = ABSOLUTE(.);
|
||||
|
||||
mapping[dram0_data]
|
||||
|
||||
_data_end = ABSOLUTE(.);
|
||||
|
@ -278,6 +282,7 @@ SECTIONS
|
|||
|
||||
mapping[flash_rodata]
|
||||
|
||||
|
||||
*(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */
|
||||
*(.gnu.linkonce.r.*)
|
||||
*(.rodata1)
|
||||
|
@ -297,6 +302,7 @@ SECTIONS
|
|||
__init_array_start = ABSOLUTE(.);
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.* *crtbegin.*) .ctors SORT(.ctors.*)))
|
||||
__init_array_end = ABSOLUTE(.);
|
||||
|
||||
KEEP (*crtbegin.*(.dtors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.*) .dtors))
|
||||
KEEP (*(SORT(.dtors.*)))
|
||||
|
|
|
@ -33,12 +33,7 @@
|
|||
#include "hal/wdt_hal.h"
|
||||
#include "freertos/xtensa_api.h"
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#include "esp32/cache_err_int.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
#include "esp32s2/cache_err_int.h"
|
||||
#endif
|
||||
|
||||
|
||||
/* "inner" restart function for after RTOS, interrupts & anything else on this
|
||||
* core are already stopped. Stalls other core, resets hardware,
|
||||
|
|
|
@ -14,7 +14,6 @@ else()
|
|||
set(srcs "cache_err_int.c"
|
||||
"memprot.c"
|
||||
"clk.c"
|
||||
"cpu_start.c"
|
||||
"crosscore_int.c"
|
||||
"dport_access.c"
|
||||
"hw_random.c"
|
||||
|
@ -51,9 +50,6 @@ else()
|
|||
|
||||
target_linker_script(${COMPONENT_LIB} INTERFACE "${CMAKE_CURRENT_BINARY_DIR}/esp32s2_out.ld")
|
||||
|
||||
# Rely on user code to define app_main
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u app_main")
|
||||
|
||||
# Process the template file through the linker script generation mechanism, and use the output for linking the
|
||||
# final binary
|
||||
target_linker_script(${COMPONENT_LIB} INTERFACE "${CMAKE_CURRENT_LIST_DIR}/ld/esp32s2.project.ld.in" PROCESS "${CMAKE_CURRENT_BINARY_DIR}/ld/esp32s2.project.ld")
|
||||
|
|
|
@ -23,19 +23,25 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
|
||||
#include "esp_err.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
#include "esp_attr.h"
|
||||
|
||||
#include "esp_intr_alloc.h"
|
||||
|
||||
#include "soc/extmem_reg.h"
|
||||
#include "soc/dport_reg.h"
|
||||
#include "soc/periph_defs.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "hal/cpu_hal.h"
|
||||
|
||||
#include "esp32s2/dport_access.h"
|
||||
#include "esp32s2/rom/ets_sys.h"
|
||||
|
||||
#include "sdkconfig.h"
|
||||
|
||||
void esp_cache_err_int_init(void)
|
||||
{
|
||||
uint32_t core_id = xPortGetCoreID();
|
||||
uint32_t core_id = cpu_hal_get_core_id();
|
||||
ESP_INTR_DISABLE(ETS_MEMACCESS_ERR_INUM);
|
||||
|
||||
// We do not register a handler for the interrupt because it is interrupt
|
||||
|
|
|
@ -13,318 +13,34 @@
|
|||
// limitations under the License.
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/param.h>
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#include "esp_attr.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp32s2/clk.h"
|
||||
#include "esp_clk_internal.h"
|
||||
#include "esp32s2/rom/ets_sys.h"
|
||||
#include "esp32s2/rom/uart.h"
|
||||
#include "esp32s2/rom/rtc.h"
|
||||
#include "soc/system_reg.h"
|
||||
#include "soc/dport_access.h"
|
||||
#include "soc/soc.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "soc/rtc_periph.h"
|
||||
#include "soc/i2s_reg.h"
|
||||
#include "hal/wdt_hal.h"
|
||||
#include "driver/periph_ctrl.h"
|
||||
#include "xtensa/core-macros.h"
|
||||
#include "bootloader_clock.h"
|
||||
#include "soc/syscon_reg.h"
|
||||
|
||||
/* Number of cycles to wait from the 32k XTAL oscillator to consider it running.
|
||||
* Larger values increase startup delay. Smaller values may cause false positive
|
||||
* detection (i.e. oscillator runs for a few cycles and then stops).
|
||||
*/
|
||||
#define SLOW_CLK_CAL_CYCLES CONFIG_ESP32S2_RTC_CLK_CAL_CYCLES
|
||||
|
||||
#ifdef CONFIG_ESP32S2_RTC_XTAL_CAL_RETRY
|
||||
#define RTC_XTAL_CAL_RETRY CONFIG_ESP32S2_RTC_XTAL_CAL_RETRY
|
||||
#else
|
||||
#define RTC_XTAL_CAL_RETRY 1
|
||||
#endif
|
||||
#include "esp32s2/clk.h"
|
||||
|
||||
#define MHZ (1000000)
|
||||
|
||||
/* Lower threshold for a reasonably-looking calibration value for a 32k XTAL.
|
||||
* The ideal value (assuming 32768 Hz frequency) is 1000000/32768*(2**19) = 16*10^6.
|
||||
*/
|
||||
#define MIN_32K_XTAL_CAL_VAL 15000000L
|
||||
|
||||
/* Indicates that this 32k oscillator gets input from external oscillator, rather
|
||||
* than a crystal.
|
||||
*/
|
||||
#define EXT_OSC_FLAG BIT(3)
|
||||
|
||||
/* This is almost the same as rtc_slow_freq_t, except that we define
|
||||
* an extra enum member for the external 32k oscillator.
|
||||
* For convenience, lower 2 bits should correspond to rtc_slow_freq_t values.
|
||||
*/
|
||||
typedef enum {
|
||||
SLOW_CLK_RTC = RTC_SLOW_FREQ_RTC, //!< Internal 90 kHz RC oscillator
|
||||
SLOW_CLK_32K_XTAL = RTC_SLOW_FREQ_32K_XTAL, //!< External 32 kHz XTAL
|
||||
SLOW_CLK_8MD256 = RTC_SLOW_FREQ_8MD256, //!< Internal 8 MHz RC oscillator, divided by 256
|
||||
SLOW_CLK_32K_EXT_OSC = RTC_SLOW_FREQ_32K_XTAL | EXT_OSC_FLAG //!< External 32k oscillator connected to 32K_XP pin
|
||||
} slow_clk_sel_t;
|
||||
|
||||
static void select_rtc_slow_clk(slow_clk_sel_t slow_clk);
|
||||
|
||||
static const char *TAG = "clk";
|
||||
|
||||
|
||||
void esp_clk_init(void)
|
||||
{
|
||||
rtc_config_t cfg = RTC_CONFIG_DEFAULT();
|
||||
RESET_REASON rst_reas;
|
||||
rst_reas = rtc_get_reset_reason(0);
|
||||
if (rst_reas == POWERON_RESET) {
|
||||
cfg.cali_ocode = 1;
|
||||
}
|
||||
rtc_init(cfg);
|
||||
|
||||
assert(rtc_clk_xtal_freq_get() == RTC_XTAL_FREQ_40M);
|
||||
|
||||
rtc_clk_fast_freq_set(RTC_FAST_FREQ_8M);
|
||||
|
||||
#ifdef CONFIG_BOOTLOADER_WDT_ENABLE
|
||||
// WDT uses a SLOW_CLK clock source. After a function select_rtc_slow_clk a frequency of this source can changed.
|
||||
// If the frequency changes from 90kHz to 32kHz, then the timeout set for the WDT will increase 2.8 times.
|
||||
// Therefore, for the time of frequency change, set a new lower timeout value (1.6 sec).
|
||||
// This prevents excessive delay before resetting in case the supply voltage is drawdown.
|
||||
// (If frequency is changed from 90kHz to 32kHz then WDT timeout will increased to 1.6sec * 90/32 = 4.5 sec).
|
||||
wdt_hal_context_t rtc_wdt_ctx = {.inst = WDT_RWDT, .rwdt_dev = &RTCCNTL};
|
||||
uint32_t stage_timeout_ticks = (uint32_t)(1600ULL * rtc_clk_slow_freq_get_hz() / 1000ULL);
|
||||
wdt_hal_write_protect_disable(&rtc_wdt_ctx);
|
||||
wdt_hal_feed(&rtc_wdt_ctx);
|
||||
//Bootloader has enabled RTC WDT until now. We're only modifying timeout, so keep the stage and timeout action the same
|
||||
wdt_hal_config_stage(&rtc_wdt_ctx, WDT_STAGE0, stage_timeout_ticks, WDT_STAGE_ACTION_RESET_RTC);
|
||||
wdt_hal_write_protect_enable(&rtc_wdt_ctx);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_ESP32S2_RTC_CLK_SRC_EXT_CRYS)
|
||||
select_rtc_slow_clk(SLOW_CLK_32K_XTAL);
|
||||
#elif defined(CONFIG_ESP32S2_RTC_CLK_SRC_EXT_OSC)
|
||||
select_rtc_slow_clk(SLOW_CLK_32K_EXT_OSC);
|
||||
#elif defined(CONFIG_ESP32S2_RTC_CLK_SRC_INT_8MD256)
|
||||
select_rtc_slow_clk(SLOW_CLK_8MD256);
|
||||
#else
|
||||
select_rtc_slow_clk(RTC_SLOW_FREQ_RTC);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BOOTLOADER_WDT_ENABLE
|
||||
// After changing a frequency WDT timeout needs to be set for new frequency.
|
||||
stage_timeout_ticks = (uint32_t)((uint64_t)CONFIG_BOOTLOADER_WDT_TIME_MS * rtc_clk_slow_freq_get_hz() / 1000ULL);
|
||||
wdt_hal_write_protect_disable(&rtc_wdt_ctx);
|
||||
wdt_hal_feed(&rtc_wdt_ctx);
|
||||
wdt_hal_config_stage(&rtc_wdt_ctx, WDT_STAGE0, stage_timeout_ticks, WDT_STAGE_ACTION_RESET_RTC);
|
||||
wdt_hal_write_protect_enable(&rtc_wdt_ctx);
|
||||
#endif
|
||||
|
||||
rtc_cpu_freq_config_t old_config, new_config;
|
||||
rtc_clk_cpu_freq_get_config(&old_config);
|
||||
const uint32_t old_freq_mhz = old_config.freq_mhz;
|
||||
const uint32_t new_freq_mhz = CONFIG_ESP32S2_DEFAULT_CPU_FREQ_MHZ;
|
||||
|
||||
bool res = rtc_clk_cpu_freq_mhz_to_config(new_freq_mhz, &new_config);
|
||||
assert(res);
|
||||
|
||||
// Wait for UART TX to finish, otherwise some UART output will be lost
|
||||
// when switching APB frequency
|
||||
uart_tx_wait_idle(CONFIG_ESP_CONSOLE_UART_NUM);
|
||||
|
||||
rtc_clk_cpu_freq_set_config(&new_config);
|
||||
|
||||
// Re calculate the ccount to make time calculation correct.
|
||||
XTHAL_SET_CCOUNT( (uint64_t)XTHAL_GET_CCOUNT() * new_freq_mhz / old_freq_mhz );
|
||||
}
|
||||
// g_ticks_us defined in ROMs
|
||||
extern uint32_t g_ticks_per_us_pro;
|
||||
|
||||
int IRAM_ATTR esp_clk_cpu_freq(void)
|
||||
{
|
||||
return ets_get_cpu_frequency() * 1000000;
|
||||
return g_ticks_per_us_pro * MHZ;
|
||||
}
|
||||
|
||||
int IRAM_ATTR esp_clk_apb_freq(void)
|
||||
{
|
||||
return MIN(ets_get_cpu_frequency(), 80) * 1000000;
|
||||
return MIN(g_ticks_per_us_pro, 80) * MHZ;
|
||||
}
|
||||
|
||||
static void select_rtc_slow_clk(slow_clk_sel_t slow_clk)
|
||||
int IRAM_ATTR esp_clk_xtal_freq(void)
|
||||
{
|
||||
rtc_slow_freq_t rtc_slow_freq = slow_clk & RTC_CNTL_ANA_CLK_RTC_SEL_V;
|
||||
uint32_t cal_val = 0;
|
||||
/* number of times to repeat 32k XTAL calibration
|
||||
* before giving up and switching to the internal RC
|
||||
*/
|
||||
int retry_32k_xtal = RTC_XTAL_CAL_RETRY;
|
||||
|
||||
do {
|
||||
if (rtc_slow_freq == RTC_SLOW_FREQ_32K_XTAL) {
|
||||
/* 32k XTAL oscillator needs to be enabled and running before it can
|
||||
* be used. Hardware doesn't have a direct way of checking if the
|
||||
* oscillator is running. Here we use rtc_clk_cal function to count
|
||||
* the number of main XTAL cycles in the given number of 32k XTAL
|
||||
* oscillator cycles. If the 32k XTAL has not started up, calibration
|
||||
* will time out, returning 0.
|
||||
*/
|
||||
ESP_EARLY_LOGD(TAG, "waiting for 32k oscillator to start up");
|
||||
if (slow_clk == SLOW_CLK_32K_XTAL) {
|
||||
rtc_clk_32k_enable(true);
|
||||
} else if (slow_clk == SLOW_CLK_32K_EXT_OSC) {
|
||||
rtc_clk_32k_enable_external();
|
||||
}
|
||||
// When SLOW_CLK_CAL_CYCLES is set to 0, clock calibration will not be performed at startup.
|
||||
if (SLOW_CLK_CAL_CYCLES > 0) {
|
||||
cal_val = rtc_clk_cal(RTC_CAL_32K_XTAL, SLOW_CLK_CAL_CYCLES);
|
||||
if (cal_val == 0 || cal_val < MIN_32K_XTAL_CAL_VAL) {
|
||||
if (retry_32k_xtal-- > 0) {
|
||||
continue;
|
||||
}
|
||||
ESP_EARLY_LOGW(TAG, "32 kHz XTAL not found, switching to internal 90 kHz oscillator");
|
||||
rtc_slow_freq = RTC_SLOW_FREQ_RTC;
|
||||
}
|
||||
}
|
||||
} else if (rtc_slow_freq == RTC_SLOW_FREQ_8MD256) {
|
||||
rtc_clk_8m_enable(true, true);
|
||||
}
|
||||
rtc_clk_slow_freq_set(rtc_slow_freq);
|
||||
|
||||
if (SLOW_CLK_CAL_CYCLES > 0) {
|
||||
/* TODO: 32k XTAL oscillator has some frequency drift at startup.
|
||||
* Improve calibration routine to wait until the frequency is stable.
|
||||
*/
|
||||
cal_val = rtc_clk_cal(RTC_CAL_RTC_MUX, SLOW_CLK_CAL_CYCLES);
|
||||
} else {
|
||||
const uint64_t cal_dividend = (1ULL << RTC_CLK_CAL_FRACT) * 1000000ULL;
|
||||
cal_val = (uint32_t) (cal_dividend / rtc_clk_slow_freq_get_hz());
|
||||
}
|
||||
} while (cal_val == 0);
|
||||
ESP_EARLY_LOGD(TAG, "RTC_SLOW_CLK calibration value: %d", cal_val);
|
||||
esp_clk_slowclk_cal_set(cal_val);
|
||||
return rtc_clk_xtal_freq_get() * MHZ;
|
||||
}
|
||||
|
||||
void rtc_clk_select_rtc_slow_clk(void)
|
||||
void IRAM_ATTR ets_update_cpu_frequency(uint32_t ticks_per_us)
|
||||
{
|
||||
select_rtc_slow_clk(RTC_SLOW_FREQ_32K_XTAL);
|
||||
}
|
||||
|
||||
/* This function is not exposed as an API at this point.
|
||||
* All peripheral clocks are default enabled after chip is powered on.
|
||||
* This function disables some peripheral clocks when cpu starts.
|
||||
* These peripheral clocks are enabled when the peripherals are initialized
|
||||
* and disabled when they are de-initialized.
|
||||
*/
|
||||
void esp_perip_clk_init(void)
|
||||
{
|
||||
uint32_t common_perip_clk, hwcrypto_perip_clk, wifi_bt_sdio_clk = 0;
|
||||
uint32_t common_perip_clk1 = 0;
|
||||
|
||||
RESET_REASON rst_reas[1];
|
||||
|
||||
rst_reas[0] = rtc_get_reset_reason(0);
|
||||
|
||||
/* For reason that only reset CPU, do not disable the clocks
|
||||
* that have been enabled before reset.
|
||||
*/
|
||||
if (rst_reas[0] >= TG0WDT_CPU_RESET &&
|
||||
rst_reas[0] <= TG0WDT_CPU_RESET &&
|
||||
rst_reas[0] != RTCWDT_BROWN_OUT_RESET) {
|
||||
common_perip_clk = ~DPORT_READ_PERI_REG(DPORT_PERIP_CLK_EN_REG);
|
||||
hwcrypto_perip_clk = ~DPORT_READ_PERI_REG(DPORT_PERIP_CLK_EN1_REG);
|
||||
wifi_bt_sdio_clk = ~DPORT_READ_PERI_REG(DPORT_WIFI_CLK_EN_REG);
|
||||
} else {
|
||||
common_perip_clk = DPORT_WDG_CLK_EN |
|
||||
DPORT_I2S0_CLK_EN |
|
||||
#if CONFIG_ESP_CONSOLE_UART_NUM != 0
|
||||
DPORT_UART_CLK_EN |
|
||||
#endif
|
||||
#if CONFIG_ESP_CONSOLE_UART_NUM != 1
|
||||
DPORT_UART1_CLK_EN |
|
||||
#endif
|
||||
DPORT_USB_CLK_EN |
|
||||
DPORT_SPI2_CLK_EN |
|
||||
DPORT_I2C_EXT0_CLK_EN |
|
||||
DPORT_UHCI0_CLK_EN |
|
||||
DPORT_RMT_CLK_EN |
|
||||
DPORT_PCNT_CLK_EN |
|
||||
DPORT_LEDC_CLK_EN |
|
||||
DPORT_TIMERGROUP1_CLK_EN |
|
||||
DPORT_SPI3_CLK_EN |
|
||||
DPORT_SPI4_CLK_EN |
|
||||
DPORT_PWM0_CLK_EN |
|
||||
DPORT_CAN_CLK_EN |
|
||||
DPORT_PWM1_CLK_EN |
|
||||
DPORT_I2S1_CLK_EN |
|
||||
DPORT_SPI2_DMA_CLK_EN |
|
||||
DPORT_SPI3_DMA_CLK_EN |
|
||||
DPORT_PWM2_CLK_EN |
|
||||
DPORT_PWM3_CLK_EN;
|
||||
common_perip_clk1 = 0;
|
||||
hwcrypto_perip_clk = DPORT_CRYPTO_AES_CLK_EN |
|
||||
DPORT_CRYPTO_SHA_CLK_EN |
|
||||
DPORT_CRYPTO_RSA_CLK_EN;
|
||||
wifi_bt_sdio_clk = DPORT_WIFI_CLK_WIFI_EN |
|
||||
DPORT_WIFI_CLK_BT_EN_M |
|
||||
DPORT_WIFI_CLK_UNUSED_BIT5 |
|
||||
DPORT_WIFI_CLK_UNUSED_BIT12 |
|
||||
DPORT_WIFI_CLK_SDIOSLAVE_EN |
|
||||
DPORT_WIFI_CLK_SDIO_HOST_EN |
|
||||
DPORT_WIFI_CLK_EMAC_EN;
|
||||
}
|
||||
|
||||
//Reset the communication peripherals like I2C, SPI, UART, I2S and bring them to known state.
|
||||
common_perip_clk |= DPORT_I2S0_CLK_EN |
|
||||
#if CONFIG_ESP_CONSOLE_UART_NUM != 0
|
||||
DPORT_UART_CLK_EN |
|
||||
#endif
|
||||
#if CONFIG_ESP_CONSOLE_UART_NUM != 1
|
||||
DPORT_UART1_CLK_EN |
|
||||
#endif
|
||||
DPORT_USB_CLK_EN |
|
||||
DPORT_SPI2_CLK_EN |
|
||||
DPORT_I2C_EXT0_CLK_EN |
|
||||
DPORT_UHCI0_CLK_EN |
|
||||
DPORT_RMT_CLK_EN |
|
||||
DPORT_UHCI1_CLK_EN |
|
||||
DPORT_SPI3_CLK_EN |
|
||||
DPORT_SPI4_CLK_EN |
|
||||
DPORT_I2C_EXT1_CLK_EN |
|
||||
DPORT_I2S1_CLK_EN |
|
||||
DPORT_SPI2_DMA_CLK_EN |
|
||||
DPORT_SPI3_DMA_CLK_EN;
|
||||
common_perip_clk1 = 0;
|
||||
|
||||
/* Change I2S clock to audio PLL first. Because if I2S uses 160MHz clock,
|
||||
* the current is not reduced when disable I2S clock.
|
||||
*/
|
||||
REG_SET_FIELD(I2S_CLKM_CONF_REG(0), I2S_CLK_SEL, I2S_CLK_AUDIO_PLL);
|
||||
REG_SET_FIELD(I2S_CLKM_CONF_REG(1), I2S_CLK_SEL, I2S_CLK_AUDIO_PLL);
|
||||
|
||||
/* Disable some peripheral clocks. */
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, common_perip_clk);
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, common_perip_clk);
|
||||
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN1_REG, common_perip_clk1);
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN1_REG, common_perip_clk1);
|
||||
|
||||
/* Disable hardware crypto clocks. */
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN1_REG, hwcrypto_perip_clk);
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN1_REG, hwcrypto_perip_clk);
|
||||
|
||||
/* Disable WiFi/BT/SDIO clocks. */
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_WIFI_CLK_EN_REG, wifi_bt_sdio_clk);
|
||||
|
||||
/* Enable WiFi MAC and POWER clocks */
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_WIFI_CLK_EN_REG, DPORT_WIFI_CLK_WIFI_EN);
|
||||
|
||||
/* Set WiFi light sleep clock source to RTC slow clock */
|
||||
DPORT_REG_SET_FIELD(DPORT_BT_LPCK_DIV_INT_REG, DPORT_BT_LPCK_DIV_NUM, 0);
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_BT_LPCK_DIV_FRAC_REG, DPORT_LPCLK_SEL_8M);
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_BT_LPCK_DIV_FRAC_REG, DPORT_LPCLK_SEL_RTC_SLOW);
|
||||
|
||||
/* Enable RNG clock. */
|
||||
periph_module_enable(PERIPH_RNG_MODULE);
|
||||
/* Update scale factors used by ets_delay_us */
|
||||
g_ticks_per_us_pro = ticks_per_us;
|
||||
}
|
||||
|
|
|
@ -1,445 +0,0 @@
|
|||
// Copyright 2015-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 <stdint.h>
|
||||
#include <string.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_attr.h"
|
||||
#include "esp_err.h"
|
||||
|
||||
#include "esp32s2/rom/ets_sys.h"
|
||||
#include "esp32s2/rom/uart.h"
|
||||
#include "esp32s2/rom/rtc.h"
|
||||
#include "esp32s2/rom/cache.h"
|
||||
#include "esp32s2/dport_access.h"
|
||||
#include "esp32s2/brownout.h"
|
||||
#include "esp32s2/cache_err_int.h"
|
||||
#include "esp32s2/spiram.h"
|
||||
#include "esp32s2/memprot.h"
|
||||
|
||||
#include "soc/cpu.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "soc/dport_reg.h"
|
||||
#include "soc/io_mux_reg.h"
|
||||
#include "soc/rtc_cntl_reg.h"
|
||||
#include "soc/timer_group_reg.h"
|
||||
#include "soc/periph_defs.h"
|
||||
#include "hal/wdt_hal.h"
|
||||
#include "driver/rtc_io.h"
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "freertos/queue.h"
|
||||
|
||||
#include "esp_heap_caps_init.h"
|
||||
#include "esp_system.h"
|
||||
#include "esp_spi_flash.h"
|
||||
#include "esp_flash_internal.h"
|
||||
#include "nvs_flash.h"
|
||||
#include "esp_event.h"
|
||||
#include "esp_spi_flash.h"
|
||||
#include "esp_private/crosscore_int.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_vfs_dev.h"
|
||||
#include "esp_newlib.h"
|
||||
#include "esp_int_wdt.h"
|
||||
#include "esp_task.h"
|
||||
#include "esp_task_wdt.h"
|
||||
#include "esp_phy_init.h"
|
||||
#include "esp_coexist_internal.h"
|
||||
#include "esp_debug_helpers.h"
|
||||
#include "esp_core_dump.h"
|
||||
#include "esp_app_trace.h"
|
||||
#include "esp_private/dbg_stubs.h"
|
||||
#include "esp_clk_internal.h"
|
||||
#include "esp_timer.h"
|
||||
#include "esp_pm.h"
|
||||
#include "esp_private/pm_impl.h"
|
||||
#include "trax.h"
|
||||
#include "esp_ota_ops.h"
|
||||
#include "esp_efuse.h"
|
||||
#include "bootloader_mem.h"
|
||||
|
||||
#define STRINGIFY(s) STRINGIFY2(s)
|
||||
#define STRINGIFY2(s) #s
|
||||
|
||||
void start_cpu0(void) __attribute__((weak, alias("start_cpu0_default"))) __attribute__((noreturn));
|
||||
void start_cpu0_default(void) IRAM_ATTR __attribute__((noreturn));
|
||||
|
||||
static void do_global_ctors(void);
|
||||
static void main_task(void *args);
|
||||
extern void app_main(void);
|
||||
extern esp_err_t esp_pthread_init(void);
|
||||
|
||||
extern int _bss_start;
|
||||
extern int _bss_end;
|
||||
extern int _rtc_bss_start;
|
||||
extern int _rtc_bss_end;
|
||||
extern int _init_start;
|
||||
extern void (*__init_array_start)(void);
|
||||
extern void (*__init_array_end)(void);
|
||||
extern volatile int port_xSchedulerRunning[2];
|
||||
|
||||
static const char *TAG = "cpu_start";
|
||||
|
||||
struct object {
|
||||
long placeholder[ 10 ];
|
||||
};
|
||||
void __register_frame_info (const void *begin, struct object *ob);
|
||||
extern char __eh_frame[];
|
||||
|
||||
//If CONFIG_SPIRAM_IGNORE_NOTFOUND is set and external RAM is not found or errors out on testing, this is set to false.
|
||||
static bool s_spiram_okay = true;
|
||||
|
||||
/*
|
||||
* We arrive here after the bootloader finished loading the program from flash. The hardware is mostly uninitialized,
|
||||
* and the app CPU is in reset. We do have a stack, so we can do the initialization in C.
|
||||
*/
|
||||
|
||||
void IRAM_ATTR call_start_cpu0(void)
|
||||
{
|
||||
RESET_REASON rst_reas;
|
||||
|
||||
bootloader_init_mem();
|
||||
|
||||
// Move exception vectors to IRAM
|
||||
cpu_hal_set_vecbase(&_init_start);
|
||||
|
||||
rst_reas = rtc_get_reset_reason(0);
|
||||
|
||||
// from panic handler we can be reset by RWDT or TG0WDT
|
||||
if (rst_reas == RTCWDT_SYS_RESET || rst_reas == TG0WDT_SYS_RESET) {
|
||||
#ifndef CONFIG_BOOTLOADER_WDT_ENABLE
|
||||
wdt_hal_context_t rtc_wdt_ctx = {.inst = WDT_RWDT, .rwdt_dev = &RTCCNTL};
|
||||
wdt_hal_write_protect_disable(&rtc_wdt_ctx);
|
||||
wdt_hal_disable(&rtc_wdt_ctx);
|
||||
wdt_hal_write_protect_enable(&rtc_wdt_ctx);
|
||||
#endif
|
||||
}
|
||||
|
||||
//Clear BSS. Please do not attempt to do any complex stuff (like early logging) before this.
|
||||
memset(&_bss_start, 0, (&_bss_end - &_bss_start) * sizeof(_bss_start));
|
||||
|
||||
/* Unless waking from deep sleep (implying RTC memory is intact), clear RTC bss */
|
||||
if (rst_reas != DEEPSLEEP_RESET) {
|
||||
memset(&_rtc_bss_start, 0, (&_rtc_bss_end - &_rtc_bss_start) * sizeof(_rtc_bss_start));
|
||||
}
|
||||
|
||||
/* Configure the mode of instruction cache : cache size, cache associated ways, cache line size. */
|
||||
extern void esp_config_instruction_cache_mode(void);
|
||||
esp_config_instruction_cache_mode();
|
||||
|
||||
/* If we need use SPIRAM, we should use data cache, or if we want to access rodata, we also should use data cache.
|
||||
Configure the mode of data : cache size, cache associated ways, cache line size.
|
||||
Enable data cache, so if we don't use SPIRAM, it just works. */
|
||||
#if CONFIG_SPIRAM_BOOT_INIT
|
||||
extern void esp_config_data_cache_mode(void);
|
||||
esp_config_data_cache_mode();
|
||||
Cache_Enable_DCache(0);
|
||||
#endif
|
||||
|
||||
/* In SPIRAM code, we will reconfigure data cache, as well as instruction cache, so that we can:
|
||||
1. make data buses works with SPIRAM
|
||||
2. make instruction and rodata work with SPIRAM, still through instruction cache */
|
||||
#if CONFIG_SPIRAM_BOOT_INIT
|
||||
if (esp_spiram_init() != ESP_OK) {
|
||||
#if CONFIG_SPIRAM_IGNORE_NOTFOUND
|
||||
ESP_EARLY_LOGI(TAG, "Failed to init external RAM; continuing without it.");
|
||||
s_spiram_okay = false;
|
||||
#else
|
||||
ESP_EARLY_LOGE(TAG, "Failed to init external RAM!");
|
||||
abort();
|
||||
#endif
|
||||
}
|
||||
esp_spiram_init_cache();
|
||||
#endif
|
||||
|
||||
ESP_EARLY_LOGI(TAG, "Pro cpu up.");
|
||||
if (LOG_LOCAL_LEVEL >= ESP_LOG_INFO) {
|
||||
const esp_app_desc_t *app_desc = esp_ota_get_app_description();
|
||||
ESP_EARLY_LOGI(TAG, "Application information:");
|
||||
#ifndef CONFIG_APP_EXCLUDE_PROJECT_NAME_VAR
|
||||
ESP_EARLY_LOGI(TAG, "Project name: %s", app_desc->project_name);
|
||||
#endif
|
||||
#ifndef CONFIG_APP_EXCLUDE_PROJECT_VER_VAR
|
||||
ESP_EARLY_LOGI(TAG, "App version: %s", app_desc->version);
|
||||
#endif
|
||||
#ifdef CONFIG_BOOTLOADER_APP_SECURE_VERSION
|
||||
ESP_EARLY_LOGI(TAG, "Secure version: %d", app_desc->secure_version);
|
||||
#endif
|
||||
#ifdef CONFIG_APP_COMPILE_TIME_DATE
|
||||
ESP_EARLY_LOGI(TAG, "Compile time: %s %s", app_desc->date, app_desc->time);
|
||||
#endif
|
||||
char buf[17];
|
||||
esp_ota_get_app_elf_sha256(buf, sizeof(buf));
|
||||
ESP_EARLY_LOGI(TAG, "ELF file SHA256: %s...", buf);
|
||||
ESP_EARLY_LOGI(TAG, "ESP-IDF: %s", app_desc->idf_ver);
|
||||
}
|
||||
ESP_EARLY_LOGI(TAG, "Single core mode");
|
||||
|
||||
#if CONFIG_SPIRAM_MEMTEST
|
||||
if (s_spiram_okay) {
|
||||
bool ext_ram_ok = esp_spiram_test();
|
||||
if (!ext_ram_ok) {
|
||||
ESP_EARLY_LOGE(TAG, "External RAM failed memory test!");
|
||||
abort();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
|
||||
extern void instruction_flash_page_info_init(void);
|
||||
instruction_flash_page_info_init();
|
||||
#endif
|
||||
#if CONFIG_SPIRAM_RODATA
|
||||
extern void rodata_flash_page_info_init(void);
|
||||
rodata_flash_page_info_init();
|
||||
#endif
|
||||
|
||||
#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
|
||||
extern void esp_spiram_enable_instruction_access(void);
|
||||
esp_spiram_enable_instruction_access();
|
||||
#endif
|
||||
#if CONFIG_SPIRAM_RODATA
|
||||
extern void esp_spiram_enable_rodata_access(void);
|
||||
esp_spiram_enable_rodata_access();
|
||||
#endif
|
||||
|
||||
#if CONFIG_ESP32S2_INSTRUCTION_CACHE_WRAP || CONFIG_ESP32S2_DATA_CACHE_WRAP
|
||||
uint32_t icache_wrap_enable = 0, dcache_wrap_enable = 0;
|
||||
#if CONFIG_ESP32S2_INSTRUCTION_CACHE_WRAP
|
||||
icache_wrap_enable = 1;
|
||||
#endif
|
||||
#if CONFIG_ESP32S2_DATA_CACHE_WRAP
|
||||
dcache_wrap_enable = 1;
|
||||
#endif
|
||||
extern void esp_enable_cache_wrap(uint32_t icache_wrap_enable, uint32_t dcache_wrap_enable);
|
||||
esp_enable_cache_wrap(icache_wrap_enable, dcache_wrap_enable);
|
||||
#endif
|
||||
|
||||
/* Initialize heap allocator */
|
||||
heap_caps_init();
|
||||
|
||||
ESP_EARLY_LOGI(TAG, "Pro cpu start user code");
|
||||
start_cpu0();
|
||||
}
|
||||
|
||||
static void intr_matrix_clear(void)
|
||||
{
|
||||
//Clear all the interrupt matrix register
|
||||
for (int i = ETS_WIFI_MAC_INTR_SOURCE; i < ETS_MAX_INTR_SOURCE; i++) {
|
||||
intr_matrix_set(0, i, ETS_INVALID_INUM);
|
||||
}
|
||||
}
|
||||
|
||||
void start_cpu0_default(void)
|
||||
{
|
||||
esp_err_t err;
|
||||
esp_setup_syscall_table();
|
||||
|
||||
if (s_spiram_okay) {
|
||||
#if CONFIG_SPIRAM_BOOT_INIT && (CONFIG_SPIRAM_USE_CAPS_ALLOC || CONFIG_SPIRAM_USE_MALLOC)
|
||||
esp_err_t r = esp_spiram_add_to_heapalloc();
|
||||
if (r != ESP_OK) {
|
||||
ESP_EARLY_LOGE(TAG, "External RAM could not be added to heap!");
|
||||
abort();
|
||||
}
|
||||
#if CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL
|
||||
r = esp_spiram_reserve_dma_pool(CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL);
|
||||
if (r != ESP_OK) {
|
||||
ESP_EARLY_LOGE(TAG, "Could not reserve internal/DMA pool!");
|
||||
abort();
|
||||
}
|
||||
#endif
|
||||
#if CONFIG_SPIRAM_USE_MALLOC
|
||||
heap_caps_malloc_extmem_enable(CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
//Enable trace memory and immediately start trace.
|
||||
#if CONFIG_ESP32S2_TRAX
|
||||
trax_enable(TRAX_ENA_PRO);
|
||||
trax_start_trace(TRAX_DOWNCOUNT_WORDS);
|
||||
#endif
|
||||
esp_clk_init();
|
||||
esp_perip_clk_init();
|
||||
intr_matrix_clear();
|
||||
|
||||
#ifndef CONFIG_ESP_CONSOLE_UART_NONE
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
const int uart_clk_freq = REF_CLK_FREQ;
|
||||
/* When DFS is enabled, use REFTICK as UART clock source */
|
||||
CLEAR_PERI_REG_MASK(UART_CONF0_REG(CONFIG_ESP_CONSOLE_UART_NUM), UART_TICK_REF_ALWAYS_ON);
|
||||
#else
|
||||
const int uart_clk_freq = APB_CLK_FREQ;
|
||||
#endif // CONFIG_PM_DFS_ENABLE
|
||||
uart_div_modify(CONFIG_ESP_CONSOLE_UART_NUM, (uart_clk_freq << 4) / CONFIG_ESP_CONSOLE_UART_BAUDRATE);
|
||||
#endif // CONFIG_ESP_CONSOLE_UART_NONE
|
||||
|
||||
#if CONFIG_ESP32S2_BROWNOUT_DET
|
||||
esp_brownout_init();
|
||||
#endif
|
||||
|
||||
rtc_gpio_force_hold_dis_all();
|
||||
|
||||
#ifdef CONFIG_VFS_SUPPORT_IO
|
||||
esp_vfs_dev_uart_register();
|
||||
#endif // CONFIG_VFS_SUPPORT_IO
|
||||
|
||||
#if defined(CONFIG_VFS_SUPPORT_IO) && !defined(CONFIG_ESP_CONSOLE_UART_NONE)
|
||||
esp_reent_init(_GLOBAL_REENT);
|
||||
const char *default_uart_dev = "/dev/uart/" STRINGIFY(CONFIG_ESP_CONSOLE_UART_NUM);
|
||||
_GLOBAL_REENT->_stdin = fopen(default_uart_dev, "r");
|
||||
_GLOBAL_REENT->_stdout = fopen(default_uart_dev, "w");
|
||||
_GLOBAL_REENT->_stderr = fopen(default_uart_dev, "w");
|
||||
#else // defined(CONFIG_VFS_SUPPORT_IO) && !defined(CONFIG_ESP_CONSOLE_UART_NONE)
|
||||
_REENT_SMALL_CHECK_INIT(_GLOBAL_REENT);
|
||||
#endif // defined(CONFIG_VFS_SUPPORT_IO) && !defined(CONFIG_ESP_CONSOLE_UART_NONE)
|
||||
// After setting _GLOBAL_REENT, ESP_LOGIx can be used instead of ESP_EARLY_LOGx.
|
||||
|
||||
#if CONFIG_SECURE_DISABLE_ROM_DL_MODE
|
||||
err = esp_efuse_disable_rom_download_mode();
|
||||
assert(err == ESP_OK && "Failed to disable ROM download mode");
|
||||
#endif
|
||||
#if CONFIG_SECURE_ENABLE_SECURE_ROM_DL_MODE
|
||||
err = esp_efuse_enable_rom_secure_download_mode();
|
||||
assert(err == ESP_OK && "Failed to enable Secure Download mode");
|
||||
#endif
|
||||
|
||||
esp_timer_init();
|
||||
esp_set_time_from_rtc();
|
||||
#if CONFIG_APPTRACE_ENABLE
|
||||
err = esp_apptrace_init();
|
||||
assert(err == ESP_OK && "Failed to init apptrace module on PRO CPU!");
|
||||
#endif
|
||||
#if CONFIG_SYSVIEW_ENABLE
|
||||
SEGGER_SYSVIEW_Conf();
|
||||
#endif
|
||||
#if CONFIG_ESP32S2_DEBUG_STUBS_ENABLE
|
||||
esp_dbg_stubs_init();
|
||||
#endif
|
||||
err = esp_pthread_init();
|
||||
assert(err == ESP_OK && "Failed to init pthread module!");
|
||||
|
||||
#if CONFIG_ESP32S2_MEMPROT_FEATURE
|
||||
#if CONFIG_ESP32S2_MEMPROT_FEATURE_LOCK
|
||||
esp_memprot_set_prot(true, true);
|
||||
#else
|
||||
esp_memprot_set_prot(true, false);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
do_global_ctors();
|
||||
#if CONFIG_ESP_INT_WDT
|
||||
esp_int_wdt_init();
|
||||
//Initialize the interrupt watch dog
|
||||
esp_int_wdt_cpu_init();
|
||||
#endif
|
||||
esp_cache_err_int_init();
|
||||
esp_crosscore_int_init();
|
||||
spi_flash_init();
|
||||
/* init default OS-aware flash access critical section */
|
||||
spi_flash_guard_set(&g_flash_guard_default_ops);
|
||||
|
||||
esp_flash_app_init();
|
||||
esp_err_t flash_ret = esp_flash_init_default_chip();
|
||||
assert(flash_ret == ESP_OK);
|
||||
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
esp_pm_impl_init();
|
||||
#ifdef CONFIG_PM_DFS_INIT_AUTO
|
||||
int xtal_freq = (int) rtc_clk_xtal_freq_get();
|
||||
esp_pm_config_esp32s2_t cfg = {
|
||||
.max_freq_mhz = CONFIG_ESP32S2_DEFAULT_CPU_FREQ_MHZ,
|
||||
.min_freq_mhz = xtal_freq,
|
||||
};
|
||||
esp_pm_configure(&cfg);
|
||||
#endif //CONFIG_PM_DFS_INIT_AUTO
|
||||
#endif //CONFIG_PM_ENABLE
|
||||
|
||||
#if CONFIG_ESP32_ENABLE_COREDUMP
|
||||
esp_core_dump_init();
|
||||
#endif
|
||||
|
||||
portBASE_TYPE res = xTaskCreatePinnedToCore(&main_task, "main",
|
||||
ESP_TASK_MAIN_STACK, NULL,
|
||||
ESP_TASK_MAIN_PRIO, NULL, 0);
|
||||
assert(res == pdTRUE);
|
||||
|
||||
ESP_LOGI(TAG, "Starting scheduler on PRO CPU.");
|
||||
vTaskStartScheduler();
|
||||
abort(); /* Only get to here if not enough free heap to start scheduler */
|
||||
}
|
||||
|
||||
#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
|
||||
size_t __cxx_eh_arena_size_get(void)
|
||||
{
|
||||
return CONFIG_COMPILER_CXX_EXCEPTIONS_EMG_POOL_SIZE;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void do_global_ctors(void)
|
||||
{
|
||||
#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
|
||||
static struct object ob;
|
||||
__register_frame_info( __eh_frame, &ob );
|
||||
#endif
|
||||
|
||||
void (**p)(void);
|
||||
for (p = &__init_array_end - 1; p >= &__init_array_start; --p) {
|
||||
(*p)();
|
||||
}
|
||||
}
|
||||
|
||||
static void main_task(void *args)
|
||||
{
|
||||
//Enable allocation in region where the startup stacks were located.
|
||||
heap_caps_enable_nonos_stack_heaps();
|
||||
|
||||
//Initialize task wdt if configured to do so
|
||||
#ifdef CONFIG_ESP_TASK_WDT_PANIC
|
||||
ESP_ERROR_CHECK(esp_task_wdt_init(CONFIG_ESP_TASK_WDT_TIMEOUT_S, true));
|
||||
#elif CONFIG_ESP_TASK_WDT
|
||||
ESP_ERROR_CHECK(esp_task_wdt_init(CONFIG_ESP_TASK_WDT_TIMEOUT_S, false));
|
||||
#endif
|
||||
|
||||
//Add IDLE 0 to task wdt
|
||||
#ifdef CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0
|
||||
TaskHandle_t idle_0 = xTaskGetIdleTaskHandleForCPU(0);
|
||||
if (idle_0 != NULL) {
|
||||
ESP_ERROR_CHECK(esp_task_wdt_add(idle_0));
|
||||
}
|
||||
#endif
|
||||
|
||||
// Now that the application is about to start, disable boot watchdog
|
||||
#ifndef CONFIG_BOOTLOADER_WDT_DISABLE_IN_USER_CODE
|
||||
wdt_hal_context_t rtc_wdt_ctx = {.inst = WDT_RWDT, .rwdt_dev = &RTCCNTL};
|
||||
wdt_hal_write_protect_disable(&rtc_wdt_ctx);
|
||||
wdt_hal_disable(&rtc_wdt_ctx);
|
||||
wdt_hal_write_protect_enable(&rtc_wdt_ctx);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BOOTLOADER_EFUSE_SECURE_VERSION_EMULATE
|
||||
const esp_partition_t *efuse_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_EFUSE_EM, NULL);
|
||||
if (efuse_partition) {
|
||||
esp_efuse_init(efuse_partition->address, efuse_partition->size);
|
||||
}
|
||||
#endif
|
||||
|
||||
app_main();
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
// Copyright 2015-2017 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.
|
||||
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* @file esp_clk_internal.h
|
||||
*
|
||||
* Private clock-related functions
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initialize clock-related settings
|
||||
*
|
||||
* Called from cpu_start.c, not intended to be called from other places.
|
||||
* This function configures the CPU clock, RTC slow and fast clocks, and
|
||||
* performs RTC slow clock calibration.
|
||||
*/
|
||||
void esp_clk_init(void);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Disables clock of some peripherals
|
||||
*
|
||||
* Called from cpu_start.c, not intended to be called from other places.
|
||||
* This function disables clock of useless peripherals when cpu starts.
|
||||
*/
|
||||
void esp_perip_clk_init(void);
|
||||
|
||||
/* Selects an external clock source (32 kHz) for RTC.
|
||||
* Only internal use in unit test.
|
||||
*/
|
||||
void rtc_clk_select_rtc_slow_clk(void);
|
|
@ -78,18 +78,6 @@ size_t esp_spiram_get_size(void);
|
|||
void esp_spiram_writeback_cache(void);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Reserve a pool of internal memory for specific DMA/internal allocations
|
||||
*
|
||||
* @param size Size of reserved pool in bytes
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
* - ESP_ERR_NO_MEM when no memory available for pool
|
||||
*/
|
||||
esp_err_t esp_spiram_reserve_dma_pool(size_t size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -214,6 +214,10 @@ SECTIONS
|
|||
_coredump_dram_end = ABSOLUTE(.);
|
||||
|
||||
/* should be placed after coredump mapping */
|
||||
_esp_system_init_fn_array_start = ABSOLUTE(.);
|
||||
KEEP (*(SORT(.esp_system_init_fn) SORT(.esp_system_init_fn.*)))
|
||||
_esp_system_init_fn_array_end = ABSOLUTE(.);
|
||||
|
||||
mapping[dram0_data]
|
||||
|
||||
_data_end = ABSOLUTE(.);
|
||||
|
|
|
@ -69,7 +69,7 @@ void esp_brownout_init(void)
|
|||
|
||||
brownout_hal_config(&cfg);
|
||||
|
||||
ESP_ERROR_CHECK( rtc_isr_register(rtc_brownout_isr_handler, NULL, RTC_CNTL_BROWN_OUT_INT_ENA_M) );
|
||||
rtc_isr_register(rtc_brownout_isr_handler, NULL, RTC_CNTL_BROWN_OUT_INT_ENA_M);
|
||||
|
||||
brownout_hal_intr_enable(true);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,19 @@
|
|||
idf_component_register(SRCS "panic.c" "system_api.c"
|
||||
idf_component_register(SRCS "panic.c" "system_api.c" "startup.c"
|
||||
INCLUDE_DIRS include
|
||||
PRIV_INCLUDE_DIRS private_include
|
||||
PRIV_REQUIRES spi_flash app_update
|
||||
# requirements due to startup code
|
||||
nvs_flash pthread app_trace
|
||||
LDFRAGMENTS "linker.lf")
|
||||
|
||||
add_subdirectory(port)
|
||||
|
||||
# After system initialization, `start_app` (and its other cores variant) is called.
|
||||
# This is provided by the user or from another component. Since we can't establish
|
||||
# dependency on what we don't know, force linker to not drop the symbol regardless
|
||||
# of link line order.
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u start_app")
|
||||
|
||||
if (NOT CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE)
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u start_app_other_cores")
|
||||
endif()
|
|
@ -32,4 +32,10 @@ menu "ESP System Settings"
|
|||
of the crash.
|
||||
endchoice
|
||||
|
||||
config ESP_SYSTEM_SINGLE_CORE_MODE
|
||||
bool
|
||||
default n
|
||||
help
|
||||
Only initialize and use the main core.
|
||||
|
||||
endmenu # ESP System Settings
|
||||
|
|
70
components/esp_system/include/esp_private/startup_internal.h
Normal file
70
components/esp_system/include/esp_private/startup_internal.h
Normal file
|
@ -0,0 +1,70 @@
|
|||
// Copyright 2015-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.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "esp_attr.h"
|
||||
|
||||
#include "soc/soc_caps.h"
|
||||
#include "hal/cpu_hal.h"
|
||||
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern bool g_spiram_ok; // [refactor-todo] better way to communicate this from port layer to common startup code
|
||||
|
||||
// Port layer defines the entry point. It then transfer control to a `sys_startup_fn_t`, stored in this
|
||||
// array, one per core.
|
||||
typedef void (*sys_startup_fn_t)(void);
|
||||
|
||||
#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
|
||||
extern sys_startup_fn_t g_startup_fn[SOC_CPU_CORES_NUM];
|
||||
#else
|
||||
extern sys_startup_fn_t g_startup_fn[1];
|
||||
#endif
|
||||
|
||||
// Utility to execute `sys_startup_fn_t` for the current core.
|
||||
#define SYS_STARTUP_FN() ((*g_startup_fn[(cpu_hal_get_core_id())])())
|
||||
|
||||
#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
|
||||
void startup_resume_other_cores(void);
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
void (*fn)(void);
|
||||
uint32_t cores;
|
||||
} esp_system_init_fn_t;
|
||||
|
||||
/*
|
||||
* Declare an component initialization function that will execute on the specified cores (ex. if BIT0 == 1, will execute
|
||||
* on CORE0, CORE1 if BIT1 and so on).
|
||||
*
|
||||
* @note Initialization functions should be placed in a compilation unit where at least one other
|
||||
* symbol is referenced 'meaningfully' in another compilation unit, otherwise this gets discarded during linking. (By
|
||||
* 'meaningfully' we mean the reference should not itself get optimized out by the compiler/discarded by the linker).
|
||||
*/
|
||||
#define ESP_SYSTEM_INIT_FN(f, c, ...) \
|
||||
static void __attribute__((used)) __VA_ARGS__ __esp_system_init_fn_##f(void); \
|
||||
static __attribute__((used)) esp_system_init_fn_t _SECTION_ATTR_IMPL(".esp_system_init_fn", f) \
|
||||
esp_system_init_fn_##f = { .fn = ( __esp_system_init_fn_##f), .cores = (c) }; \
|
||||
static __attribute__((used)) __VA_ARGS__ void __esp_system_init_fn_##f(void) // [refactor-todo] this can be made public API if we allow components to declare init functions,
|
||||
// instead of calling them explicitly
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
target_include_directories(${COMPONENT_LIB} PRIVATE include)
|
||||
|
||||
set(srcs "panic_handler.c" "panic_handler_asm.S")
|
||||
set(srcs "panic_handler.c" "panic_handler_asm.S" "cpu_start.c")
|
||||
add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" ${srcs})
|
||||
|
||||
target_sources(${COMPONENT_LIB} PRIVATE ${srcs})
|
||||
|
|
419
components/esp_system/port/cpu_start.c
Normal file
419
components/esp_system/port/cpu_start.c
Normal file
|
@ -0,0 +1,419 @@
|
|||
// Copyright 2015-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 <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "esp_attr.h"
|
||||
#include "esp_err.h"
|
||||
|
||||
#include "esp_log.h"
|
||||
#include "esp_system.h"
|
||||
|
||||
#include "esp_clk_internal.h"
|
||||
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#include "esp32/cache_err_int.h"
|
||||
#include "esp32/rom/cache.h"
|
||||
#include "esp32/rom/rtc.h"
|
||||
#include "esp32/rom/uart.h"
|
||||
#include "esp32/spiram.h"
|
||||
#include "esp32/rom/ets_sys.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
#include "esp32s2/brownout.h"
|
||||
#include "esp32s2/cache_err_int.h"
|
||||
#include "esp32s2/rom/cache.h"
|
||||
#include "esp32s2/rom/ets_sys.h"
|
||||
#include "esp32s2/rom/rtc.h"
|
||||
#include "esp32s2/spiram.h"
|
||||
#include "esp32s2/rom/uart.h"
|
||||
#include "soc/periph_defs.h"
|
||||
#include "esp32s2/dport_access.h"
|
||||
#include "esp32s2/memprot.h"
|
||||
#endif
|
||||
|
||||
#include "bootloader_flash_config.h"
|
||||
#include "esp_private/crosscore_int.h"
|
||||
#include "esp_flash_encrypt.h"
|
||||
|
||||
#include "hal/rtc_io_hal.h"
|
||||
#include "soc/dport_reg.h"
|
||||
#include "soc/efuse_reg.h"
|
||||
#include "soc/cpu.h"
|
||||
|
||||
#include "trax.h"
|
||||
|
||||
#include "bootloader_mem.h"
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#if CONFIG_APP_BUILD_TYPE_ELF_RAM
|
||||
#include "esp32/rom/efuse.h"
|
||||
#include "esp32/rom/spi_flash.h"
|
||||
#endif // CONFIG_APP_BUILD_TYPE_ELF_RAM
|
||||
#endif
|
||||
|
||||
#include "esp_private/startup_internal.h"
|
||||
|
||||
extern int _bss_start;
|
||||
extern int _bss_end;
|
||||
extern int _rtc_bss_start;
|
||||
extern int _rtc_bss_end;
|
||||
|
||||
extern int _init_start;
|
||||
|
||||
static const char *TAG = "cpu_start";
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY
|
||||
extern int _ext_ram_bss_start;
|
||||
extern int _ext_ram_bss_end;
|
||||
#endif
|
||||
#ifdef CONFIG_ESP32_IRAM_AS_8BIT_ACCESSIBLE_MEMORY
|
||||
extern int _iram_bss_start;
|
||||
extern int _iram_bss_end;
|
||||
#endif
|
||||
#endif // CONFIG_IDF_TARGET_ESP32
|
||||
|
||||
#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
|
||||
static volatile bool s_cpu_up[SOC_CPU_CORES_NUM] = { false };
|
||||
static volatile bool s_cpu_inited[SOC_CPU_CORES_NUM] = { false };
|
||||
|
||||
static volatile bool s_resume_cores;
|
||||
#endif
|
||||
|
||||
// If CONFIG_SPIRAM_IGNORE_NOTFOUND is set and external RAM is not found or errors out on testing, this is set to false.
|
||||
bool g_spiram_ok = true;
|
||||
|
||||
#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
|
||||
void startup_resume_other_cores(void)
|
||||
{
|
||||
s_resume_cores = true;
|
||||
}
|
||||
|
||||
|
||||
void IRAM_ATTR call_start_cpu1(void)
|
||||
{
|
||||
cpu_hal_set_vecbase(&_init_start);
|
||||
|
||||
ets_set_appcpu_boot_addr(0);
|
||||
|
||||
bootloader_init_mem();
|
||||
|
||||
#if CONFIG_ESP_CONSOLE_UART_NONE
|
||||
ets_install_putc1(NULL);
|
||||
ets_install_putc2(NULL);
|
||||
#else // CONFIG_ESP_CONSOLE_UART_NONE
|
||||
uartAttach();
|
||||
ets_install_uart_printf();
|
||||
uart_tx_switch(CONFIG_ESP_CONSOLE_UART_NUM);
|
||||
#endif
|
||||
|
||||
DPORT_REG_SET_BIT(DPORT_APP_CPU_RECORD_CTRL_REG, DPORT_APP_CPU_PDEBUG_ENABLE | DPORT_APP_CPU_RECORD_ENABLE);
|
||||
DPORT_REG_CLR_BIT(DPORT_APP_CPU_RECORD_CTRL_REG, DPORT_APP_CPU_RECORD_ENABLE);
|
||||
|
||||
s_cpu_up[1] = true;
|
||||
ESP_EARLY_LOGI(TAG, "App cpu up.");
|
||||
|
||||
//Take care putting stuff here: if asked, FreeRTOS will happily tell you the scheduler
|
||||
//has started, but it isn't active *on this CPU* yet.
|
||||
esp_cache_err_int_init();
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#if CONFIG_ESP32_TRAX_TWOBANKS
|
||||
trax_start_trace(TRAX_DOWNCOUNT_WORDS);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
s_cpu_inited[1] = true;
|
||||
|
||||
while (!s_resume_cores) {
|
||||
ets_delay_us(100);
|
||||
}
|
||||
|
||||
SYS_STARTUP_FN();
|
||||
}
|
||||
|
||||
static void start_other_core(void)
|
||||
{
|
||||
// If not the single core variant of ESP32 - check this since there is
|
||||
// no separate soc_caps.h for the single core variant.
|
||||
if (!REG_GET_BIT(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_VER_DIS_APP_CPU)) {
|
||||
ESP_EARLY_LOGI(TAG, "Starting app cpu, entry point is %p", call_start_cpu1);
|
||||
|
||||
Cache_Flush(1);
|
||||
Cache_Read_Enable(1);
|
||||
esp_cpu_unstall(1);
|
||||
|
||||
// Enable clock and reset APP CPU. Note that OpenOCD may have already
|
||||
// enabled clock and taken APP CPU out of reset. In this case don't reset
|
||||
// APP CPU again, as that will clear the breakpoints which may have already
|
||||
// been set.
|
||||
if (!DPORT_GET_PERI_REG_MASK(DPORT_APPCPU_CTRL_B_REG, DPORT_APPCPU_CLKGATE_EN)) {
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_APPCPU_CTRL_B_REG, DPORT_APPCPU_CLKGATE_EN);
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_APPCPU_CTRL_C_REG, DPORT_APPCPU_RUNSTALL);
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_APPCPU_CTRL_A_REG, DPORT_APPCPU_RESETTING);
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_APPCPU_CTRL_A_REG, DPORT_APPCPU_RESETTING);
|
||||
}
|
||||
ets_set_appcpu_boot_addr((uint32_t)call_start_cpu1);
|
||||
|
||||
volatile bool cpus_up = false;
|
||||
|
||||
while (!cpus_up){
|
||||
cpus_up = true;
|
||||
for (int i = 0; i < SOC_CPU_CORES_NUM; i++) {
|
||||
cpus_up &= s_cpu_up[i];
|
||||
}
|
||||
ets_delay_us(100);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
|
||||
|
||||
static void intr_matrix_clear(void)
|
||||
{
|
||||
for (int i = ETS_WIFI_MAC_INTR_SOURCE; i < ETS_MAX_INTR_SOURCE; i++) {
|
||||
intr_matrix_set(0, i, ETS_INVALID_INUM);
|
||||
#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
|
||||
intr_matrix_set(1, i, ETS_INVALID_INUM);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We arrive here after the bootloader finished loading the program from flash. The hardware is mostly uninitialized,
|
||||
* and the app CPU is in reset. We do have a stack, so we can do the initialization in C.
|
||||
*/
|
||||
void IRAM_ATTR call_start_cpu0(void)
|
||||
{
|
||||
#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
|
||||
RESET_REASON rst_reas[SOC_CPU_CORES_NUM];
|
||||
#else
|
||||
RESET_REASON rst_reas[1];
|
||||
#endif
|
||||
|
||||
bootloader_init_mem();
|
||||
|
||||
// Move exception vectors to IRAM
|
||||
cpu_hal_set_vecbase(&_init_start);
|
||||
|
||||
rst_reas[0] = rtc_get_reset_reason(0);
|
||||
#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
|
||||
rst_reas[1] = rtc_get_reset_reason(1);
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_BOOTLOADER_WDT_ENABLE
|
||||
// from panic handler we can be reset by RWDT or TG0WDT
|
||||
if (rst_reas[0] == RTCWDT_SYS_RESET || rst_reas[0] == TG0WDT_SYS_RESET
|
||||
#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
|
||||
|| rst_reas[1] == RTCWDT_SYS_RESET || rst_reas[1] == TG0WDT_SYS_RESET
|
||||
#endif
|
||||
) {
|
||||
wdt_hal_context_t rtc_wdt_ctx = {.inst = WDT_RWDT, .rwdt_dev = &RTCCNTL};
|
||||
wdt_hal_write_protect_disable(&rtc_wdt_ctx);
|
||||
wdt_hal_disable(&rtc_wdt_ctx);
|
||||
wdt_hal_write_protect_enable(&rtc_wdt_ctx);
|
||||
}
|
||||
#endif
|
||||
|
||||
//Clear BSS. Please do not attempt to do any complex stuff (like early logging) before this.
|
||||
memset(&_bss_start, 0, (&_bss_end - &_bss_start) * sizeof(_bss_start));
|
||||
|
||||
#if defined(CONFIG_IDF_TARGET_ESP32) && defined(CONFIG_ESP32_IRAM_AS_8BIT_ACCESSIBLE_MEMORY)
|
||||
// Clear IRAM BSS
|
||||
memset(&_iram_bss_start, 0, (&_iram_bss_end - &_iram_bss_start) * sizeof(_iram_bss_start));
|
||||
#endif
|
||||
|
||||
/* Unless waking from deep sleep (implying RTC memory is intact), clear RTC bss */
|
||||
if (rst_reas[0] != DEEPSLEEP_RESET) {
|
||||
memset(&_rtc_bss_start, 0, (&_rtc_bss_end - &_rtc_bss_start) * sizeof(_rtc_bss_start));
|
||||
}
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32S2
|
||||
/* Configure the mode of instruction cache : cache size, cache associated ways, cache line size. */
|
||||
extern void esp_config_instruction_cache_mode(void);
|
||||
esp_config_instruction_cache_mode();
|
||||
|
||||
/* If we need use SPIRAM, we should use data cache, or if we want to access rodata, we also should use data cache.
|
||||
Configure the mode of data : cache size, cache associated ways, cache line size.
|
||||
Enable data cache, so if we don't use SPIRAM, it just works. */
|
||||
#if CONFIG_SPIRAM_BOOT_INIT
|
||||
extern void esp_config_data_cache_mode(void);
|
||||
esp_config_data_cache_mode();
|
||||
Cache_Enable_DCache(0);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if CONFIG_SPIRAM_BOOT_INIT
|
||||
esp_spiram_init_cache();
|
||||
if (esp_spiram_init() != ESP_OK) {
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY
|
||||
ESP_EARLY_LOGE(TAG, "Failed to init external RAM, needed for external .bss segment");
|
||||
abort();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if CONFIG_SPIRAM_IGNORE_NOTFOUND
|
||||
ESP_EARLY_LOGI(TAG, "Failed to init external RAM; continuing without it.");
|
||||
g_spiram_ok = false;
|
||||
#else
|
||||
ESP_EARLY_LOGE(TAG, "Failed to init external RAM!");
|
||||
abort();
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
|
||||
s_cpu_up[0] = true;
|
||||
#endif
|
||||
ESP_EARLY_LOGI(TAG, "Pro cpu up.");
|
||||
|
||||
#if SOC_CPU_CORES_NUM > 1 // there is no 'single-core mode' for natively single-core processors
|
||||
#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
|
||||
start_other_core();
|
||||
#else
|
||||
ESP_EARLY_LOGI(TAG, "Single core mode");
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_APPCPU_CTRL_B_REG, DPORT_APPCPU_CLKGATE_EN); // stop the other core
|
||||
#endif // !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
|
||||
#endif // SOC_CPU_CORES_NUM > 1
|
||||
|
||||
#if CONFIG_SPIRAM_MEMTEST
|
||||
if (g_spiram_ok) {
|
||||
bool ext_ram_ok = esp_spiram_test();
|
||||
if (!ext_ram_ok) {
|
||||
ESP_EARLY_LOGE(TAG, "External RAM failed memory test!");
|
||||
abort();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32S2
|
||||
#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
|
||||
extern void instruction_flash_page_info_init(void);
|
||||
instruction_flash_page_info_init();
|
||||
#endif
|
||||
#if CONFIG_SPIRAM_RODATA
|
||||
extern void rodata_flash_page_info_init(void);
|
||||
rodata_flash_page_info_init();
|
||||
#endif
|
||||
|
||||
#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
|
||||
extern void esp_spiram_enable_instruction_access(void);
|
||||
esp_spiram_enable_instruction_access();
|
||||
#endif
|
||||
#if CONFIG_SPIRAM_RODATA
|
||||
extern void esp_spiram_enable_rodata_access(void);
|
||||
esp_spiram_enable_rodata_access();
|
||||
#endif
|
||||
|
||||
#if CONFIG_ESP32S2_INSTRUCTION_CACHE_WRAP || CONFIG_ESP32S2_DATA_CACHE_WRAP
|
||||
uint32_t icache_wrap_enable = 0, dcache_wrap_enable = 0;
|
||||
#if CONFIG_ESP32S2_INSTRUCTION_CACHE_WRAP
|
||||
icache_wrap_enable = 1;
|
||||
#endif
|
||||
#if CONFIG_ESP32S2_DATA_CACHE_WRAP
|
||||
dcache_wrap_enable = 1;
|
||||
#endif
|
||||
extern void esp_enable_cache_wrap(uint32_t icache_wrap_enable, uint32_t dcache_wrap_enable);
|
||||
esp_enable_cache_wrap(icache_wrap_enable, dcache_wrap_enable);
|
||||
#endif
|
||||
#endif // CONFIG_IDF_TARGET_ESP32S2
|
||||
|
||||
#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY
|
||||
memset(&_ext_ram_bss_start, 0, (&_ext_ram_bss_end - &_ext_ram_bss_start) * sizeof(_ext_ram_bss_start));
|
||||
#endif
|
||||
|
||||
//Enable trace memory and immediately start trace.
|
||||
#if CONFIG_ESP32_TRAX || CONFIG_ESP32S2_TRAX
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#if CONFIG_ESP32_TRAX_TWOBANKS
|
||||
trax_enable(TRAX_ENA_PRO_APP);
|
||||
#else
|
||||
trax_enable(TRAX_ENA_PRO);
|
||||
#endif
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
trax_enable(TRAX_ENA_PRO);
|
||||
#endif
|
||||
trax_start_trace(TRAX_DOWNCOUNT_WORDS);
|
||||
#endif // CONFIG_ESP32_TRAX || CONFIG_ESP32S2_TRAX
|
||||
|
||||
esp_clk_init();
|
||||
esp_perip_clk_init();
|
||||
intr_matrix_clear();
|
||||
|
||||
#ifndef CONFIG_ESP_CONSOLE_UART_NONE
|
||||
const int uart_clk_freq = APB_CLK_FREQ;
|
||||
uart_div_modify(CONFIG_ESP_CONSOLE_UART_NUM, (uart_clk_freq << 4) / CONFIG_ESP_CONSOLE_UART_BAUDRATE);
|
||||
#endif
|
||||
|
||||
rtcio_hal_unhold_all();
|
||||
|
||||
esp_cache_err_int_init();
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32S2
|
||||
#if CONFIG_ESP32S2_MEMPROT_FEATURE
|
||||
#if CONFIG_ESP32S2_MEMPROT_FEATURE_LOCK
|
||||
esp_memprot_set_prot(true, true);
|
||||
#else
|
||||
esp_memprot_set_prot(true, false);
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
bootloader_flash_update_id();
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#if !CONFIG_SPIRAM_BOOT_INIT
|
||||
// Read the application binary image header. This will also decrypt the header if the image is encrypted.
|
||||
esp_image_header_t fhdr = {0};
|
||||
#ifdef CONFIG_APP_BUILD_TYPE_ELF_RAM
|
||||
fhdr.spi_mode = ESP_IMAGE_SPI_MODE_DIO;
|
||||
fhdr.spi_speed = ESP_IMAGE_SPI_SPEED_40M;
|
||||
fhdr.spi_size = ESP_IMAGE_FLASH_SIZE_4MB;
|
||||
|
||||
extern void esp_rom_spiflash_attach(uint32_t, bool);
|
||||
esp_rom_spiflash_attach(ets_efuse_get_spiconfig(), false);
|
||||
esp_rom_spiflash_unlock();
|
||||
#else
|
||||
// This assumes that DROM is the first segment in the application binary, i.e. that we can read
|
||||
// the binary header through cache by accessing SOC_DROM_LOW address.
|
||||
memcpy(&fhdr, (void*) SOC_DROM_LOW, sizeof(fhdr));
|
||||
#endif // CONFIG_APP_BUILD_TYPE_ELF_RAM
|
||||
|
||||
// If psram is uninitialized, we need to improve some flash configuration.
|
||||
bootloader_flash_clock_config(&fhdr);
|
||||
bootloader_flash_gpio_config(&fhdr);
|
||||
bootloader_flash_dummy_config(&fhdr);
|
||||
bootloader_flash_cs_timing_config();
|
||||
#endif //!CONFIG_SPIRAM_BOOT_INIT
|
||||
#endif
|
||||
|
||||
#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
|
||||
s_cpu_inited[0] = true;
|
||||
|
||||
volatile bool cpus_inited = false;
|
||||
|
||||
while (!cpus_inited) {
|
||||
cpus_inited = true;
|
||||
for (int i = 0; i < SOC_CPU_CORES_NUM; i++) {
|
||||
cpus_inited &= s_cpu_inited[i];
|
||||
}
|
||||
ets_delay_us(100);
|
||||
}
|
||||
#endif
|
||||
|
||||
SYS_STARTUP_FN();
|
||||
}
|
|
@ -1,2 +1,4 @@
|
|||
target_sources(${COMPONENT_LIB} PRIVATE "${CMAKE_CURRENT_LIST_DIR}/dport_panic_highint_hdl.S"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/reset_reason.c")
|
||||
set(srcs "dport_panic_highint_hdl.S" "clk.c" "reset_reason.c")
|
||||
add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" ${srcs})
|
||||
|
||||
target_sources(${COMPONENT_LIB} PRIVATE ${srcs})
|
||||
|
|
315
components/esp_system/port/esp32/clk.c
Normal file
315
components/esp_system/port/esp32/clk.c
Normal file
|
@ -0,0 +1,315 @@
|
|||
|
||||
// Copyright 2015-2017 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 "soc/rtc.h"
|
||||
#include "soc/dport_reg.h"
|
||||
#include "soc/dport_access.h"
|
||||
#include "xtensa/core-macros.h"
|
||||
#include "soc/i2s_reg.h"
|
||||
#include "driver/periph_ctrl.h"
|
||||
#include "bootloader_clock.h"
|
||||
#include "hal/wdt_hal.h"
|
||||
|
||||
#include "driver/spi_common_internal.h" // [refactor-todo]: for spicommon_periph_in_use
|
||||
|
||||
#include "esp_log.h"
|
||||
|
||||
#include "esp32/clk.h"
|
||||
#include "esp32/rom/uart.h"
|
||||
#include "esp32/rom/rtc.h"
|
||||
|
||||
#include "sdkconfig.h"
|
||||
|
||||
static const char* TAG = "clk";
|
||||
|
||||
/* Number of cycles to wait from the 32k XTAL oscillator to consider it running.
|
||||
* Larger values increase startup delay. Smaller values may cause false positive
|
||||
* detection (i.e. oscillator runs for a few cycles and then stops).
|
||||
*/
|
||||
#define SLOW_CLK_CAL_CYCLES CONFIG_ESP32_RTC_CLK_CAL_CYCLES
|
||||
|
||||
#ifdef CONFIG_ESP32_RTC_XTAL_CAL_RETRY
|
||||
#define RTC_XTAL_CAL_RETRY CONFIG_ESP32_RTC_XTAL_CAL_RETRY
|
||||
#else
|
||||
#define RTC_XTAL_CAL_RETRY 1
|
||||
#endif
|
||||
|
||||
/* Lower threshold for a reasonably-looking calibration value for a 32k XTAL.
|
||||
* The ideal value (assuming 32768 Hz frequency) is 1000000/32768*(2**19) = 16*10^6.
|
||||
*/
|
||||
#define MIN_32K_XTAL_CAL_VAL 15000000L
|
||||
|
||||
/* Indicates that this 32k oscillator gets input from external oscillator, rather
|
||||
* than a crystal.
|
||||
*/
|
||||
#define EXT_OSC_FLAG BIT(3)
|
||||
|
||||
/* This is almost the same as rtc_slow_freq_t, except that we define
|
||||
* an extra enum member for the external 32k oscillator.
|
||||
* For convenience, lower 2 bits should correspond to rtc_slow_freq_t values.
|
||||
*/
|
||||
typedef enum {
|
||||
SLOW_CLK_150K = RTC_SLOW_FREQ_RTC, //!< Internal 150 kHz RC oscillator
|
||||
SLOW_CLK_32K_XTAL = RTC_SLOW_FREQ_32K_XTAL, //!< External 32 kHz XTAL
|
||||
SLOW_CLK_8MD256 = RTC_SLOW_FREQ_8MD256, //!< Internal 8 MHz RC oscillator, divided by 256
|
||||
SLOW_CLK_32K_EXT_OSC = RTC_SLOW_FREQ_32K_XTAL | EXT_OSC_FLAG //!< External 32k oscillator connected to 32K_XP pin
|
||||
} slow_clk_sel_t;
|
||||
|
||||
static void select_rtc_slow_clk(slow_clk_sel_t slow_clk)
|
||||
{
|
||||
rtc_slow_freq_t rtc_slow_freq = slow_clk & RTC_CNTL_ANA_CLK_RTC_SEL_V;
|
||||
uint32_t cal_val = 0;
|
||||
/* number of times to repeat 32k XTAL calibration
|
||||
* before giving up and switching to the internal RC
|
||||
*/
|
||||
int retry_32k_xtal = RTC_XTAL_CAL_RETRY;
|
||||
|
||||
do {
|
||||
if (rtc_slow_freq == RTC_SLOW_FREQ_32K_XTAL) {
|
||||
/* 32k XTAL oscillator needs to be enabled and running before it can
|
||||
* be used. Hardware doesn't have a direct way of checking if the
|
||||
* oscillator is running. Here we use rtc_clk_cal function to count
|
||||
* the number of main XTAL cycles in the given number of 32k XTAL
|
||||
* oscillator cycles. If the 32k XTAL has not started up, calibration
|
||||
* will time out, returning 0.
|
||||
*/
|
||||
ESP_EARLY_LOGD(TAG, "waiting for 32k oscillator to start up");
|
||||
if (slow_clk == SLOW_CLK_32K_XTAL) {
|
||||
rtc_clk_32k_enable(true);
|
||||
} else if (slow_clk == SLOW_CLK_32K_EXT_OSC) {
|
||||
rtc_clk_32k_enable_external();
|
||||
}
|
||||
// When SLOW_CLK_CAL_CYCLES is set to 0, clock calibration will not be performed at startup.
|
||||
if (SLOW_CLK_CAL_CYCLES > 0) {
|
||||
cal_val = rtc_clk_cal(RTC_CAL_32K_XTAL, SLOW_CLK_CAL_CYCLES);
|
||||
if (cal_val == 0 || cal_val < MIN_32K_XTAL_CAL_VAL) {
|
||||
if (retry_32k_xtal-- > 0) {
|
||||
continue;
|
||||
}
|
||||
ESP_EARLY_LOGW(TAG, "32 kHz XTAL not found, switching to internal 150 kHz oscillator");
|
||||
rtc_slow_freq = RTC_SLOW_FREQ_RTC;
|
||||
}
|
||||
}
|
||||
} else if (rtc_slow_freq == RTC_SLOW_FREQ_8MD256) {
|
||||
rtc_clk_8m_enable(true, true);
|
||||
}
|
||||
rtc_clk_slow_freq_set(rtc_slow_freq);
|
||||
|
||||
if (SLOW_CLK_CAL_CYCLES > 0) {
|
||||
/* TODO: 32k XTAL oscillator has some frequency drift at startup.
|
||||
* Improve calibration routine to wait until the frequency is stable.
|
||||
*/
|
||||
cal_val = rtc_clk_cal(RTC_CAL_RTC_MUX, SLOW_CLK_CAL_CYCLES);
|
||||
} else {
|
||||
const uint64_t cal_dividend = (1ULL << RTC_CLK_CAL_FRACT) * 1000000ULL;
|
||||
cal_val = (uint32_t) (cal_dividend / rtc_clk_slow_freq_get_hz());
|
||||
}
|
||||
} while (cal_val == 0);
|
||||
ESP_EARLY_LOGD(TAG, "RTC_SLOW_CLK calibration value: %d", cal_val);
|
||||
esp_clk_slowclk_cal_set(cal_val);
|
||||
}
|
||||
|
||||
void esp_clk_init(void)
|
||||
{
|
||||
rtc_config_t cfg = RTC_CONFIG_DEFAULT();
|
||||
rtc_init(cfg);
|
||||
|
||||
#if (CONFIG_ESP32_COMPATIBLE_PRE_V2_1_BOOTLOADERS || CONFIG_ESP32_APP_INIT_CLK)
|
||||
/* Check the bootloader set the XTAL frequency.
|
||||
|
||||
Bootloaders pre-v2.1 don't do this.
|
||||
*/
|
||||
rtc_xtal_freq_t xtal_freq = rtc_clk_xtal_freq_get();
|
||||
if (xtal_freq == RTC_XTAL_FREQ_AUTO) {
|
||||
ESP_EARLY_LOGW(TAG, "RTC domain not initialised by bootloader");
|
||||
bootloader_clock_configure();
|
||||
}
|
||||
#else
|
||||
/* If this assertion fails, either upgrade the bootloader or enable CONFIG_ESP32_COMPATIBLE_PRE_V2_1_BOOTLOADERS */
|
||||
assert(rtc_clk_xtal_freq_get() != RTC_XTAL_FREQ_AUTO);
|
||||
#endif
|
||||
|
||||
rtc_clk_fast_freq_set(RTC_FAST_FREQ_8M);
|
||||
|
||||
#ifdef CONFIG_BOOTLOADER_WDT_ENABLE
|
||||
// WDT uses a SLOW_CLK clock source. After a function select_rtc_slow_clk a frequency of this source can changed.
|
||||
// If the frequency changes from 150kHz to 32kHz, then the timeout set for the WDT will increase 4.6 times.
|
||||
// Therefore, for the time of frequency change, set a new lower timeout value (1.6 sec).
|
||||
// This prevents excessive delay before resetting in case the supply voltage is drawdown.
|
||||
// (If frequency is changed from 150kHz to 32kHz then WDT timeout will increased to 1.6sec * 150/32 = 7.5 sec).
|
||||
wdt_hal_context_t rtc_wdt_ctx = {.inst = WDT_RWDT, .rwdt_dev = &RTCCNTL};
|
||||
uint32_t stage_timeout_ticks = (uint32_t)(1600ULL * rtc_clk_slow_freq_get_hz() / 1000ULL);
|
||||
wdt_hal_write_protect_disable(&rtc_wdt_ctx);
|
||||
wdt_hal_feed(&rtc_wdt_ctx);
|
||||
//Bootloader has enabled RTC WDT until now. We're only modifying timeout, so keep the stage and timeout action the same
|
||||
wdt_hal_config_stage(&rtc_wdt_ctx, WDT_STAGE0, stage_timeout_ticks, WDT_STAGE_ACTION_RESET_RTC);
|
||||
wdt_hal_write_protect_enable(&rtc_wdt_ctx);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_ESP32_RTC_CLK_SRC_EXT_CRYS)
|
||||
select_rtc_slow_clk(SLOW_CLK_32K_XTAL);
|
||||
#elif defined(CONFIG_ESP32_RTC_CLK_SRC_EXT_OSC)
|
||||
select_rtc_slow_clk(SLOW_CLK_32K_EXT_OSC);
|
||||
#elif defined(CONFIG_ESP32_RTC_CLK_SRC_INT_8MD256)
|
||||
select_rtc_slow_clk(SLOW_CLK_8MD256);
|
||||
#else
|
||||
select_rtc_slow_clk(RTC_SLOW_FREQ_RTC);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BOOTLOADER_WDT_ENABLE
|
||||
// After changing a frequency WDT timeout needs to be set for new frequency.
|
||||
stage_timeout_ticks = (uint32_t)((uint64_t)CONFIG_BOOTLOADER_WDT_TIME_MS * rtc_clk_slow_freq_get_hz() / 1000);
|
||||
wdt_hal_write_protect_disable(&rtc_wdt_ctx);
|
||||
wdt_hal_feed(&rtc_wdt_ctx);
|
||||
wdt_hal_config_stage(&rtc_wdt_ctx, WDT_STAGE0, stage_timeout_ticks, WDT_STAGE_ACTION_RESET_RTC);
|
||||
wdt_hal_write_protect_enable(&rtc_wdt_ctx);
|
||||
#endif
|
||||
|
||||
rtc_cpu_freq_config_t old_config, new_config;
|
||||
rtc_clk_cpu_freq_get_config(&old_config);
|
||||
const uint32_t old_freq_mhz = old_config.freq_mhz;
|
||||
const uint32_t new_freq_mhz = CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ;
|
||||
|
||||
bool res = rtc_clk_cpu_freq_mhz_to_config(new_freq_mhz, &new_config);
|
||||
assert(res);
|
||||
|
||||
// Wait for UART TX to finish, otherwise some UART output will be lost
|
||||
// when switching APB frequency
|
||||
uart_tx_wait_idle(CONFIG_ESP_CONSOLE_UART_NUM);
|
||||
|
||||
rtc_clk_cpu_freq_set_config(&new_config);
|
||||
|
||||
// Re calculate the ccount to make time calculation correct.
|
||||
XTHAL_SET_CCOUNT( (uint64_t)XTHAL_GET_CCOUNT() * new_freq_mhz / old_freq_mhz );
|
||||
}
|
||||
|
||||
/* This function is not exposed as an API at this point.
|
||||
* All peripheral clocks are default enabled after chip is powered on.
|
||||
* This function disables some peripheral clocks when cpu starts.
|
||||
* These peripheral clocks are enabled when the peripherals are initialized
|
||||
* and disabled when they are de-initialized.
|
||||
*/
|
||||
void esp_perip_clk_init(void)
|
||||
{
|
||||
uint32_t common_perip_clk, hwcrypto_perip_clk, wifi_bt_sdio_clk = 0;
|
||||
|
||||
#if CONFIG_FREERTOS_UNICORE
|
||||
RESET_REASON rst_reas[1];
|
||||
#else
|
||||
RESET_REASON rst_reas[2];
|
||||
#endif
|
||||
|
||||
rst_reas[0] = rtc_get_reset_reason(0);
|
||||
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
rst_reas[1] = rtc_get_reset_reason(1);
|
||||
#endif
|
||||
|
||||
/* For reason that only reset CPU, do not disable the clocks
|
||||
* that have been enabled before reset.
|
||||
*/
|
||||
if ((rst_reas[0] >= TGWDT_CPU_RESET && rst_reas[0] <= RTCWDT_CPU_RESET)
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
|| (rst_reas[1] >= TGWDT_CPU_RESET && rst_reas[1] <= RTCWDT_CPU_RESET)
|
||||
#endif
|
||||
) {
|
||||
common_perip_clk = ~DPORT_READ_PERI_REG(DPORT_PERIP_CLK_EN_REG);
|
||||
hwcrypto_perip_clk = ~DPORT_READ_PERI_REG(DPORT_PERI_CLK_EN_REG);
|
||||
wifi_bt_sdio_clk = ~DPORT_READ_PERI_REG(DPORT_WIFI_CLK_EN_REG);
|
||||
}
|
||||
else {
|
||||
common_perip_clk = DPORT_WDG_CLK_EN |
|
||||
DPORT_PCNT_CLK_EN |
|
||||
DPORT_LEDC_CLK_EN |
|
||||
DPORT_TIMERGROUP1_CLK_EN |
|
||||
DPORT_PWM0_CLK_EN |
|
||||
DPORT_CAN_CLK_EN |
|
||||
DPORT_PWM1_CLK_EN |
|
||||
DPORT_PWM2_CLK_EN |
|
||||
DPORT_PWM3_CLK_EN;
|
||||
hwcrypto_perip_clk = DPORT_PERI_EN_AES |
|
||||
DPORT_PERI_EN_SHA |
|
||||
DPORT_PERI_EN_RSA |
|
||||
DPORT_PERI_EN_SECUREBOOT;
|
||||
wifi_bt_sdio_clk = DPORT_WIFI_CLK_WIFI_EN |
|
||||
DPORT_WIFI_CLK_BT_EN_M |
|
||||
DPORT_WIFI_CLK_UNUSED_BIT5 |
|
||||
DPORT_WIFI_CLK_UNUSED_BIT12 |
|
||||
DPORT_WIFI_CLK_SDIOSLAVE_EN |
|
||||
DPORT_WIFI_CLK_SDIO_HOST_EN |
|
||||
DPORT_WIFI_CLK_EMAC_EN;
|
||||
}
|
||||
|
||||
//Reset the communication peripherals like I2C, SPI, UART, I2S and bring them to known state.
|
||||
common_perip_clk |= DPORT_I2S0_CLK_EN |
|
||||
#if CONFIG_ESP_CONSOLE_UART_NUM != 0
|
||||
DPORT_UART_CLK_EN |
|
||||
#endif
|
||||
#if CONFIG_ESP_CONSOLE_UART_NUM != 1
|
||||
DPORT_UART1_CLK_EN |
|
||||
#endif
|
||||
#if CONFIG_ESP_CONSOLE_UART_NUM != 2
|
||||
DPORT_UART2_CLK_EN |
|
||||
#endif
|
||||
DPORT_SPI2_CLK_EN |
|
||||
DPORT_I2C_EXT0_CLK_EN |
|
||||
DPORT_UHCI0_CLK_EN |
|
||||
DPORT_RMT_CLK_EN |
|
||||
DPORT_UHCI1_CLK_EN |
|
||||
DPORT_SPI3_CLK_EN |
|
||||
DPORT_I2C_EXT1_CLK_EN |
|
||||
DPORT_I2S1_CLK_EN |
|
||||
DPORT_SPI_DMA_CLK_EN;
|
||||
|
||||
common_perip_clk &= ~DPORT_SPI01_CLK_EN;
|
||||
|
||||
#if CONFIG_SPIRAM_SPEED_80M
|
||||
//80MHz SPIRAM uses SPI2/SPI3 as well; it's initialized before this is called. Because it is used in
|
||||
//a weird mode where clock to the peripheral is disabled but reset is also disabled, it 'hangs'
|
||||
//in a state where it outputs a continuous 80MHz signal. Mask its bit here because we should
|
||||
//not modify that state, regardless of what we calculated earlier.
|
||||
if (spicommon_periph_in_use(HSPI_HOST)) {
|
||||
common_perip_clk &= ~DPORT_SPI2_CLK_EN;
|
||||
}
|
||||
if (spicommon_periph_in_use(VSPI_HOST)) {
|
||||
common_perip_clk &= ~DPORT_SPI3_CLK_EN;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Change I2S clock to audio PLL first. Because if I2S uses 160MHz clock,
|
||||
* the current is not reduced when disable I2S clock.
|
||||
*/
|
||||
DPORT_SET_PERI_REG_MASK(I2S_CLKM_CONF_REG(0), I2S_CLKA_ENA);
|
||||
DPORT_SET_PERI_REG_MASK(I2S_CLKM_CONF_REG(1), I2S_CLKA_ENA);
|
||||
|
||||
/* Disable some peripheral clocks. */
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, common_perip_clk);
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, common_perip_clk);
|
||||
|
||||
/* Disable hardware crypto clocks. */
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERI_CLK_EN_REG, hwcrypto_perip_clk);
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERI_RST_EN_REG, hwcrypto_perip_clk);
|
||||
|
||||
/* Disable WiFi/BT/SDIO clocks. */
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_WIFI_CLK_EN_REG, wifi_bt_sdio_clk);
|
||||
|
||||
/* Enable RNG clock. */
|
||||
periph_module_enable(PERIPH_RNG_MODULE);
|
||||
}
|
||||
|
||||
void rtc_clk_select_rtc_slow_clk(void)
|
||||
{
|
||||
select_rtc_slow_clk(RTC_SLOW_FREQ_32K_XTAL);
|
||||
}
|
15
components/esp_system/port/esp32/intr.c
Normal file
15
components/esp_system/port/esp32/intr.c
Normal file
|
@ -0,0 +1,15 @@
|
|||
// Copyright 2015-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.
|
||||
|
||||
|
|
@ -1,2 +1,4 @@
|
|||
target_sources(${COMPONENT_LIB} PRIVATE "${CMAKE_CURRENT_LIST_DIR}/dport_panic_highint_hdl.S"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/reset_reason.c")
|
||||
set(srcs "dport_panic_highint_hdl.S" "clk.c" "reset_reason.c")
|
||||
add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" ${srcs})
|
||||
|
||||
target_sources(${COMPONENT_LIB} PRIVATE ${srcs})
|
||||
|
|
318
components/esp_system/port/esp32s2/clk.c
Normal file
318
components/esp_system/port/esp32s2/clk.c
Normal file
|
@ -0,0 +1,318 @@
|
|||
|
||||
// Copyright 2015-2017 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 <stdint.h>
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/param.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_attr.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp32s2/clk.h"
|
||||
#include "esp_clk_internal.h"
|
||||
#include "esp32s2/rom/ets_sys.h"
|
||||
#include "esp32s2/rom/uart.h"
|
||||
#include "esp32s2/rom/rtc.h"
|
||||
#include "soc/system_reg.h"
|
||||
#include "soc/dport_access.h"
|
||||
#include "soc/soc.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "hal/wdt_hal.h"
|
||||
#include "soc/rtc_periph.h"
|
||||
#include "soc/i2s_reg.h"
|
||||
#include "driver/periph_ctrl.h"
|
||||
#include "xtensa/core-macros.h"
|
||||
#include "bootloader_clock.h"
|
||||
#include "soc/syscon_reg.h"
|
||||
|
||||
static const char *TAG = "clk";
|
||||
|
||||
/* Number of cycles to wait from the 32k XTAL oscillator to consider it running.
|
||||
* Larger values increase startup delay. Smaller values may cause false positive
|
||||
* detection (i.e. oscillator runs for a few cycles and then stops).
|
||||
*/
|
||||
#define SLOW_CLK_CAL_CYCLES CONFIG_ESP32S2_RTC_CLK_CAL_CYCLES
|
||||
|
||||
#ifdef CONFIG_ESP32S2_RTC_XTAL_CAL_RETRY
|
||||
#define RTC_XTAL_CAL_RETRY CONFIG_ESP32S2_RTC_XTAL_CAL_RETRY
|
||||
#else
|
||||
#define RTC_XTAL_CAL_RETRY 1
|
||||
#endif
|
||||
|
||||
/* Lower threshold for a reasonably-looking calibration value for a 32k XTAL.
|
||||
* The ideal value (assuming 32768 Hz frequency) is 1000000/32768*(2**19) = 16*10^6.
|
||||
*/
|
||||
#define MIN_32K_XTAL_CAL_VAL 15000000L
|
||||
|
||||
/* Indicates that this 32k oscillator gets input from external oscillator, rather
|
||||
* than a crystal.
|
||||
*/
|
||||
#define EXT_OSC_FLAG BIT(3)
|
||||
|
||||
/* This is almost the same as rtc_slow_freq_t, except that we define
|
||||
* an extra enum member for the external 32k oscillator.
|
||||
* For convenience, lower 2 bits should correspond to rtc_slow_freq_t values.
|
||||
*/
|
||||
typedef enum {
|
||||
SLOW_CLK_RTC = RTC_SLOW_FREQ_RTC, //!< Internal 90 kHz RC oscillator
|
||||
SLOW_CLK_32K_XTAL = RTC_SLOW_FREQ_32K_XTAL, //!< External 32 kHz XTAL
|
||||
SLOW_CLK_8MD256 = RTC_SLOW_FREQ_8MD256, //!< Internal 8 MHz RC oscillator, divided by 256
|
||||
SLOW_CLK_32K_EXT_OSC = RTC_SLOW_FREQ_32K_XTAL | EXT_OSC_FLAG //!< External 32k oscillator connected to 32K_XP pin
|
||||
} slow_clk_sel_t;
|
||||
|
||||
static void select_rtc_slow_clk(slow_clk_sel_t slow_clk);
|
||||
|
||||
void esp_clk_init(void)
|
||||
{
|
||||
rtc_config_t cfg = RTC_CONFIG_DEFAULT();
|
||||
RESET_REASON rst_reas;
|
||||
rst_reas = rtc_get_reset_reason(0);
|
||||
if (rst_reas == POWERON_RESET) {
|
||||
cfg.cali_ocode = 1;
|
||||
}
|
||||
rtc_init(cfg);
|
||||
|
||||
assert(rtc_clk_xtal_freq_get() == RTC_XTAL_FREQ_40M);
|
||||
|
||||
rtc_clk_fast_freq_set(RTC_FAST_FREQ_8M);
|
||||
|
||||
#ifdef CONFIG_BOOTLOADER_WDT_ENABLE
|
||||
// WDT uses a SLOW_CLK clock source. After a function select_rtc_slow_clk a frequency of this source can changed.
|
||||
// If the frequency changes from 90kHz to 32kHz, then the timeout set for the WDT will increase 2.8 times.
|
||||
// Therefore, for the time of frequency change, set a new lower timeout value (1.6 sec).
|
||||
// This prevents excessive delay before resetting in case the supply voltage is drawdown.
|
||||
// (If frequency is changed from 90kHz to 32kHz then WDT timeout will increased to 1.6sec * 90/32 = 4.5 sec).
|
||||
wdt_hal_context_t rtc_wdt_ctx = {.inst = WDT_RWDT, .rwdt_dev = &RTCCNTL};
|
||||
uint32_t stage_timeout_ticks = (uint32_t)(1600ULL * rtc_clk_slow_freq_get_hz() / 1000ULL);
|
||||
wdt_hal_write_protect_disable(&rtc_wdt_ctx);
|
||||
wdt_hal_feed(&rtc_wdt_ctx);
|
||||
//Bootloader has enabled RTC WDT until now. We're only modifying timeout, so keep the stage and timeout action the same
|
||||
wdt_hal_config_stage(&rtc_wdt_ctx, WDT_STAGE0, stage_timeout_ticks, WDT_STAGE_ACTION_RESET_RTC);
|
||||
wdt_hal_write_protect_enable(&rtc_wdt_ctx);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_ESP32S2_RTC_CLK_SRC_EXT_CRYS)
|
||||
select_rtc_slow_clk(SLOW_CLK_32K_XTAL);
|
||||
#elif defined(CONFIG_ESP32S2_RTC_CLK_SRC_EXT_OSC)
|
||||
select_rtc_slow_clk(SLOW_CLK_32K_EXT_OSC);
|
||||
#elif defined(CONFIG_ESP32S2_RTC_CLK_SRC_INT_8MD256)
|
||||
select_rtc_slow_clk(SLOW_CLK_8MD256);
|
||||
#else
|
||||
select_rtc_slow_clk(RTC_SLOW_FREQ_RTC);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BOOTLOADER_WDT_ENABLE
|
||||
// After changing a frequency WDT timeout needs to be set for new frequency.
|
||||
stage_timeout_ticks = (uint32_t)((uint64_t)CONFIG_BOOTLOADER_WDT_TIME_MS * rtc_clk_slow_freq_get_hz() / 1000ULL);
|
||||
wdt_hal_write_protect_disable(&rtc_wdt_ctx);
|
||||
wdt_hal_feed(&rtc_wdt_ctx);
|
||||
wdt_hal_config_stage(&rtc_wdt_ctx, WDT_STAGE0, stage_timeout_ticks, WDT_STAGE_ACTION_RESET_RTC);
|
||||
wdt_hal_write_protect_enable(&rtc_wdt_ctx);
|
||||
#endif
|
||||
|
||||
rtc_cpu_freq_config_t old_config, new_config;
|
||||
rtc_clk_cpu_freq_get_config(&old_config);
|
||||
const uint32_t old_freq_mhz = old_config.freq_mhz;
|
||||
const uint32_t new_freq_mhz = CONFIG_ESP32S2_DEFAULT_CPU_FREQ_MHZ;
|
||||
|
||||
bool res = rtc_clk_cpu_freq_mhz_to_config(new_freq_mhz, &new_config);
|
||||
assert(res);
|
||||
|
||||
// Wait for UART TX to finish, otherwise some UART output will be lost
|
||||
// when switching APB frequency
|
||||
uart_tx_wait_idle(CONFIG_ESP_CONSOLE_UART_NUM);
|
||||
|
||||
rtc_clk_cpu_freq_set_config(&new_config);
|
||||
|
||||
// Re calculate the ccount to make time calculation correct.
|
||||
XTHAL_SET_CCOUNT( (uint64_t)XTHAL_GET_CCOUNT() * new_freq_mhz / old_freq_mhz );
|
||||
}
|
||||
|
||||
static void select_rtc_slow_clk(slow_clk_sel_t slow_clk)
|
||||
{
|
||||
rtc_slow_freq_t rtc_slow_freq = slow_clk & RTC_CNTL_ANA_CLK_RTC_SEL_V;
|
||||
uint32_t cal_val = 0;
|
||||
/* number of times to repeat 32k XTAL calibration
|
||||
* before giving up and switching to the internal RC
|
||||
*/
|
||||
int retry_32k_xtal = RTC_XTAL_CAL_RETRY;
|
||||
|
||||
do {
|
||||
if (rtc_slow_freq == RTC_SLOW_FREQ_32K_XTAL) {
|
||||
/* 32k XTAL oscillator needs to be enabled and running before it can
|
||||
* be used. Hardware doesn't have a direct way of checking if the
|
||||
* oscillator is running. Here we use rtc_clk_cal function to count
|
||||
* the number of main XTAL cycles in the given number of 32k XTAL
|
||||
* oscillator cycles. If the 32k XTAL has not started up, calibration
|
||||
* will time out, returning 0.
|
||||
*/
|
||||
ESP_EARLY_LOGD(TAG, "waiting for 32k oscillator to start up");
|
||||
if (slow_clk == SLOW_CLK_32K_XTAL) {
|
||||
rtc_clk_32k_enable(true);
|
||||
} else if (slow_clk == SLOW_CLK_32K_EXT_OSC) {
|
||||
rtc_clk_32k_enable_external();
|
||||
}
|
||||
// When SLOW_CLK_CAL_CYCLES is set to 0, clock calibration will not be performed at startup.
|
||||
if (SLOW_CLK_CAL_CYCLES > 0) {
|
||||
cal_val = rtc_clk_cal(RTC_CAL_32K_XTAL, SLOW_CLK_CAL_CYCLES);
|
||||
if (cal_val == 0 || cal_val < MIN_32K_XTAL_CAL_VAL) {
|
||||
if (retry_32k_xtal-- > 0) {
|
||||
continue;
|
||||
}
|
||||
ESP_EARLY_LOGW(TAG, "32 kHz XTAL not found, switching to internal 90 kHz oscillator");
|
||||
rtc_slow_freq = RTC_SLOW_FREQ_RTC;
|
||||
}
|
||||
}
|
||||
} else if (rtc_slow_freq == RTC_SLOW_FREQ_8MD256) {
|
||||
rtc_clk_8m_enable(true, true);
|
||||
}
|
||||
rtc_clk_slow_freq_set(rtc_slow_freq);
|
||||
|
||||
if (SLOW_CLK_CAL_CYCLES > 0) {
|
||||
/* TODO: 32k XTAL oscillator has some frequency drift at startup.
|
||||
* Improve calibration routine to wait until the frequency is stable.
|
||||
*/
|
||||
cal_val = rtc_clk_cal(RTC_CAL_RTC_MUX, SLOW_CLK_CAL_CYCLES);
|
||||
} else {
|
||||
const uint64_t cal_dividend = (1ULL << RTC_CLK_CAL_FRACT) * 1000000ULL;
|
||||
cal_val = (uint32_t) (cal_dividend / rtc_clk_slow_freq_get_hz());
|
||||
}
|
||||
} while (cal_val == 0);
|
||||
ESP_EARLY_LOGD(TAG, "RTC_SLOW_CLK calibration value: %d", cal_val);
|
||||
esp_clk_slowclk_cal_set(cal_val);
|
||||
}
|
||||
|
||||
void rtc_clk_select_rtc_slow_clk(void)
|
||||
{
|
||||
select_rtc_slow_clk(RTC_SLOW_FREQ_32K_XTAL);
|
||||
}
|
||||
|
||||
/* This function is not exposed as an API at this point.
|
||||
* All peripheral clocks are default enabled after chip is powered on.
|
||||
* This function disables some peripheral clocks when cpu starts.
|
||||
* These peripheral clocks are enabled when the peripherals are initialized
|
||||
* and disabled when they are de-initialized.
|
||||
*/
|
||||
void esp_perip_clk_init(void)
|
||||
{
|
||||
uint32_t common_perip_clk, hwcrypto_perip_clk, wifi_bt_sdio_clk = 0;
|
||||
uint32_t common_perip_clk1 = 0;
|
||||
|
||||
RESET_REASON rst_reas[1];
|
||||
|
||||
rst_reas[0] = rtc_get_reset_reason(0);
|
||||
|
||||
/* For reason that only reset CPU, do not disable the clocks
|
||||
* that have been enabled before reset.
|
||||
*/
|
||||
if (rst_reas[0] >= TG0WDT_CPU_RESET &&
|
||||
rst_reas[0] <= TG0WDT_CPU_RESET &&
|
||||
rst_reas[0] != RTCWDT_BROWN_OUT_RESET) {
|
||||
common_perip_clk = ~DPORT_READ_PERI_REG(DPORT_PERIP_CLK_EN_REG);
|
||||
hwcrypto_perip_clk = ~DPORT_READ_PERI_REG(DPORT_PERIP_CLK_EN1_REG);
|
||||
wifi_bt_sdio_clk = ~DPORT_READ_PERI_REG(DPORT_WIFI_CLK_EN_REG);
|
||||
} else {
|
||||
common_perip_clk = DPORT_WDG_CLK_EN |
|
||||
DPORT_I2S0_CLK_EN |
|
||||
#if CONFIG_ESP_CONSOLE_UART_NUM != 0
|
||||
DPORT_UART_CLK_EN |
|
||||
#endif
|
||||
#if CONFIG_ESP_CONSOLE_UART_NUM != 1
|
||||
DPORT_UART1_CLK_EN |
|
||||
#endif
|
||||
DPORT_USB_CLK_EN |
|
||||
DPORT_SPI2_CLK_EN |
|
||||
DPORT_I2C_EXT0_CLK_EN |
|
||||
DPORT_UHCI0_CLK_EN |
|
||||
DPORT_RMT_CLK_EN |
|
||||
DPORT_PCNT_CLK_EN |
|
||||
DPORT_LEDC_CLK_EN |
|
||||
DPORT_TIMERGROUP1_CLK_EN |
|
||||
DPORT_SPI3_CLK_EN |
|
||||
DPORT_SPI4_CLK_EN |
|
||||
DPORT_PWM0_CLK_EN |
|
||||
DPORT_CAN_CLK_EN |
|
||||
DPORT_PWM1_CLK_EN |
|
||||
DPORT_I2S1_CLK_EN |
|
||||
DPORT_SPI2_DMA_CLK_EN |
|
||||
DPORT_SPI3_DMA_CLK_EN |
|
||||
DPORT_PWM2_CLK_EN |
|
||||
DPORT_PWM3_CLK_EN;
|
||||
common_perip_clk1 = 0;
|
||||
hwcrypto_perip_clk = DPORT_CRYPTO_AES_CLK_EN |
|
||||
DPORT_CRYPTO_SHA_CLK_EN |
|
||||
DPORT_CRYPTO_RSA_CLK_EN;
|
||||
wifi_bt_sdio_clk = DPORT_WIFI_CLK_WIFI_EN |
|
||||
DPORT_WIFI_CLK_BT_EN_M |
|
||||
DPORT_WIFI_CLK_UNUSED_BIT5 |
|
||||
DPORT_WIFI_CLK_UNUSED_BIT12 |
|
||||
DPORT_WIFI_CLK_SDIOSLAVE_EN |
|
||||
DPORT_WIFI_CLK_SDIO_HOST_EN |
|
||||
DPORT_WIFI_CLK_EMAC_EN;
|
||||
}
|
||||
|
||||
//Reset the communication peripherals like I2C, SPI, UART, I2S and bring them to known state.
|
||||
common_perip_clk |= DPORT_I2S0_CLK_EN |
|
||||
#if CONFIG_ESP_CONSOLE_UART_NUM != 0
|
||||
DPORT_UART_CLK_EN |
|
||||
#endif
|
||||
#if CONFIG_ESP_CONSOLE_UART_NUM != 1
|
||||
DPORT_UART1_CLK_EN |
|
||||
#endif
|
||||
DPORT_USB_CLK_EN |
|
||||
DPORT_SPI2_CLK_EN |
|
||||
DPORT_I2C_EXT0_CLK_EN |
|
||||
DPORT_UHCI0_CLK_EN |
|
||||
DPORT_RMT_CLK_EN |
|
||||
DPORT_UHCI1_CLK_EN |
|
||||
DPORT_SPI3_CLK_EN |
|
||||
DPORT_SPI4_CLK_EN |
|
||||
DPORT_I2C_EXT1_CLK_EN |
|
||||
DPORT_I2S1_CLK_EN |
|
||||
DPORT_SPI2_DMA_CLK_EN |
|
||||
DPORT_SPI3_DMA_CLK_EN;
|
||||
common_perip_clk1 = 0;
|
||||
|
||||
/* Change I2S clock to audio PLL first. Because if I2S uses 160MHz clock,
|
||||
* the current is not reduced when disable I2S clock.
|
||||
*/
|
||||
REG_SET_FIELD(I2S_CLKM_CONF_REG(0), I2S_CLK_SEL, I2S_CLK_AUDIO_PLL);
|
||||
REG_SET_FIELD(I2S_CLKM_CONF_REG(1), I2S_CLK_SEL, I2S_CLK_AUDIO_PLL);
|
||||
|
||||
/* Disable some peripheral clocks. */
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, common_perip_clk);
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, common_perip_clk);
|
||||
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN1_REG, common_perip_clk1);
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN1_REG, common_perip_clk1);
|
||||
|
||||
/* Disable hardware crypto clocks. */
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN1_REG, hwcrypto_perip_clk);
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN1_REG, hwcrypto_perip_clk);
|
||||
|
||||
/* Disable WiFi/BT/SDIO clocks. */
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_WIFI_CLK_EN_REG, wifi_bt_sdio_clk);
|
||||
|
||||
/* Enable WiFi MAC and POWER clocks */
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_WIFI_CLK_EN_REG, DPORT_WIFI_CLK_WIFI_EN);
|
||||
|
||||
/* Set WiFi light sleep clock source to RTC slow clock */
|
||||
DPORT_REG_SET_FIELD(DPORT_BT_LPCK_DIV_INT_REG, DPORT_BT_LPCK_DIV_NUM, 0);
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_BT_LPCK_DIV_FRAC_REG, DPORT_LPCLK_SEL_8M);
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_BT_LPCK_DIV_FRAC_REG, DPORT_LPCLK_SEL_RTC_SLOW);
|
||||
|
||||
/* Enable RNG clock. */
|
||||
periph_module_enable(PERIPH_RNG_MODULE);
|
||||
}
|
0
components/esp_system/port/include/intr.h
Normal file
0
components/esp_system/port/include/intr.h
Normal file
378
components/esp_system/startup.c
Normal file
378
components/esp_system/startup.c
Normal file
|
@ -0,0 +1,378 @@
|
|||
// Copyright 2015-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 <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "esp_attr.h"
|
||||
#include "esp_err.h"
|
||||
|
||||
#include "esp_system.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_ota_ops.h"
|
||||
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#include "soc/soc_caps.h"
|
||||
#include "hal/wdt_hal.h"
|
||||
|
||||
#include "esp_system.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_heap_caps_init.h"
|
||||
#include "esp_spi_flash.h"
|
||||
#include "esp_flash_internal.h"
|
||||
#include "esp_newlib.h"
|
||||
#include "esp_vfs_dev.h"
|
||||
#include "esp_timer.h"
|
||||
#include "esp_efuse.h"
|
||||
#include "esp_flash_encrypt.h"
|
||||
|
||||
/***********************************************/
|
||||
// Headers for other components init functions
|
||||
#include "nvs_flash.h"
|
||||
#include "esp_phy_init.h"
|
||||
#include "esp_coexist_internal.h"
|
||||
#include "esp_core_dump.h"
|
||||
#include "esp_app_trace.h"
|
||||
#include "esp_private/dbg_stubs.h"
|
||||
#include "esp_flash_encrypt.h"
|
||||
#include "esp_pm.h"
|
||||
#include "esp_private/pm_impl.h"
|
||||
#include "esp_pthread.h"
|
||||
|
||||
// [refactor-todo] make this file completely target-independent
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#include "esp32/rom/uart.h"
|
||||
#include "esp32/rom/ets_sys.h"
|
||||
#include "esp32/spiram.h"
|
||||
#include "esp32/brownout.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
#include "esp32s2/rom/uart.h"
|
||||
#include "esp32s2/rom/ets_sys.h"
|
||||
#include "esp32s2/spiram.h"
|
||||
#include "esp32s2/brownout.h"
|
||||
#endif
|
||||
/***********************************************/
|
||||
|
||||
#include "esp_private/startup_internal.h"
|
||||
|
||||
// Ensure that system configuration matches the underlying number of cores.
|
||||
// This should enable us to avoid checking for both everytime.
|
||||
#if !(SOC_CPU_CORES_NUM > 1) && !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
|
||||
#error "System has been configured to run on multiple cores, but target SoC only has a single core."
|
||||
#endif
|
||||
|
||||
#define STRINGIFY(s) STRINGIFY2(s)
|
||||
#define STRINGIFY2(s) #s
|
||||
|
||||
// App entry point for core 0
|
||||
extern void start_app(void);
|
||||
|
||||
// Entry point for core 0 from hardware init (port layer)
|
||||
void start_cpu0(void) __attribute__((weak, alias("start_cpu0_default"))) __attribute__((noreturn));
|
||||
|
||||
#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
|
||||
// Entry point for core [1..X] from hardware init (port layer)
|
||||
void start_cpu_other_cores(void) __attribute__((weak, alias("start_cpu_other_cores_default"))) __attribute__((noreturn));
|
||||
|
||||
// App entry point for core [1..X]
|
||||
void start_app_other_cores(void) __attribute__((weak, alias("start_app_other_cores_default"))) __attribute__((noreturn));
|
||||
|
||||
static volatile bool s_system_inited[SOC_CPU_CORES_NUM] = { false };
|
||||
|
||||
sys_startup_fn_t g_startup_fn[SOC_CPU_CORES_NUM] = { [0] = start_cpu0,
|
||||
#if SOC_CPU_CORES_NUM > 1
|
||||
[1 ... SOC_CPU_CORES_NUM - 1] = start_cpu_other_cores
|
||||
#endif
|
||||
};
|
||||
|
||||
static volatile bool s_system_full_inited = false;
|
||||
#else
|
||||
sys_startup_fn_t g_startup_fn[1] = { start_cpu0 };
|
||||
#endif
|
||||
|
||||
static const char* TAG = "cpu_start";
|
||||
|
||||
static void IRAM_ATTR do_global_ctors(void)
|
||||
{
|
||||
extern void (*__init_array_start)(void);
|
||||
extern void (*__init_array_end)(void);
|
||||
|
||||
#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
|
||||
struct object { long placeholder[ 10 ]; };
|
||||
void __register_frame_info (const void *begin, struct object *ob);
|
||||
extern char __eh_frame[];
|
||||
|
||||
static struct object ob;
|
||||
__register_frame_info( __eh_frame, &ob );
|
||||
#endif
|
||||
|
||||
void (**p)(void);
|
||||
for (p = &__init_array_end - 1; p >= &__init_array_start; --p) {
|
||||
(*p)();
|
||||
}
|
||||
}
|
||||
|
||||
static void IRAM_ATTR do_system_init_fn(void)
|
||||
{
|
||||
extern esp_system_init_fn_t _esp_system_init_fn_array_start;
|
||||
extern esp_system_init_fn_t _esp_system_init_fn_array_end;
|
||||
|
||||
esp_system_init_fn_t *p;
|
||||
|
||||
for (p = &_esp_system_init_fn_array_end - 1; p >= &_esp_system_init_fn_array_start; --p) {
|
||||
if (p->cores & BIT(cpu_hal_get_core_id())) {
|
||||
(*(p->fn))();
|
||||
}
|
||||
}
|
||||
|
||||
#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
|
||||
s_system_inited[cpu_hal_get_core_id()] = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
|
||||
static void IRAM_ATTR start_app_other_cores_default(void)
|
||||
{
|
||||
while (1) {
|
||||
ets_delay_us(UINT32_MAX);
|
||||
}
|
||||
}
|
||||
|
||||
static void IRAM_ATTR start_cpu_other_cores_default(void)
|
||||
{
|
||||
do_system_init_fn();
|
||||
|
||||
while (!s_system_full_inited) {
|
||||
ets_delay_us(100);
|
||||
}
|
||||
|
||||
start_app_other_cores();
|
||||
}
|
||||
#endif
|
||||
|
||||
static void IRAM_ATTR do_core_init(void)
|
||||
{
|
||||
/* Initialize heap allocator. WARNING: This *needs* to happen *after* the app cpu has booted.
|
||||
If the heap allocator is initialized first, it will put free memory linked list items into
|
||||
memory also used by the ROM. Starting the app cpu will let its ROM initialize that memory,
|
||||
corrupting those linked lists. Initializing the allocator *after* the app cpu has booted
|
||||
works around this problem.
|
||||
With SPI RAM enabled, there's a second reason: half of the SPI RAM will be managed by the
|
||||
app CPU, and when that is not up yet, the memory will be inaccessible and heap_caps_init may
|
||||
fail initializing it properly. */
|
||||
heap_caps_init();
|
||||
esp_setup_syscall_table();
|
||||
|
||||
if (g_spiram_ok) {
|
||||
#if CONFIG_SPIRAM_BOOT_INIT && (CONFIG_SPIRAM_USE_CAPS_ALLOC || CONFIG_SPIRAM_USE_MALLOC)
|
||||
esp_err_t r=esp_spiram_add_to_heapalloc();
|
||||
if (r != ESP_OK) {
|
||||
ESP_EARLY_LOGE(TAG, "External RAM could not be added to heap!");
|
||||
abort();
|
||||
}
|
||||
#if CONFIG_SPIRAM_USE_MALLOC
|
||||
heap_caps_malloc_extmem_enable(CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
#if CONFIG_ESP32_BROWNOUT_DET || CONFIG_ESP32S2_BROWNOUT_DET
|
||||
// [refactor-todo] leads to call chain rtc_is_register (driver) -> esp_intr_alloc (esp32/esp32s2) ->
|
||||
// malloc (newlib) -> heap_caps_malloc (heap), so heap must be at least initialized
|
||||
esp_brownout_init();
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_VFS_SUPPORT_IO
|
||||
esp_vfs_dev_uart_register();
|
||||
#endif // CONFIG_VFS_SUPPORT_IO
|
||||
|
||||
#if defined(CONFIG_VFS_SUPPORT_IO) && !defined(CONFIG_ESP_CONSOLE_UART_NONE)
|
||||
esp_reent_init(_GLOBAL_REENT);
|
||||
const char *default_uart_dev = "/dev/uart/" STRINGIFY(CONFIG_ESP_CONSOLE_UART_NUM);
|
||||
_GLOBAL_REENT->_stdin = fopen(default_uart_dev, "r");
|
||||
_GLOBAL_REENT->_stdout = fopen(default_uart_dev, "w");
|
||||
_GLOBAL_REENT->_stderr = fopen(default_uart_dev, "w");
|
||||
#else // defined(CONFIG_VFS_SUPPORT_IO) && !defined(CONFIG_ESP_CONSOLE_UART_NONE)
|
||||
_REENT_SMALL_CHECK_INIT(_GLOBAL_REENT);
|
||||
#endif // defined(CONFIG_VFS_SUPPORT_IO) && !defined(CONFIG_ESP_CONSOLE_UART_NONE)
|
||||
|
||||
#ifdef CONFIG_SECURE_FLASH_ENC_ENABLED
|
||||
esp_flash_encryption_init_checks();
|
||||
#endif
|
||||
|
||||
#if CONFIG_SECURE_DISABLE_ROM_DL_MODE
|
||||
err = esp_efuse_disable_rom_download_mode();
|
||||
assert(err == ESP_OK && "Failed to disable ROM download mode");
|
||||
#endif
|
||||
|
||||
#if CONFIG_SECURE_ENABLE_SECURE_ROM_DL_MODE
|
||||
err = esp_efuse_enable_rom_secure_download_mode();
|
||||
assert(err == ESP_OK && "Failed to enable Secure Download mode");
|
||||
#endif
|
||||
|
||||
#if CONFIG_ESP32_DISABLE_BASIC_ROM_CONSOLE
|
||||
esp_efuse_disable_basic_rom_console();
|
||||
#endif
|
||||
|
||||
esp_err_t err;
|
||||
|
||||
esp_timer_init();
|
||||
esp_set_time_from_rtc();
|
||||
|
||||
// [refactor-todo] move this to secondary init
|
||||
#if CONFIG_APPTRACE_ENABLE
|
||||
err = esp_apptrace_init();
|
||||
assert(err == ESP_OK && "Failed to init apptrace module on PRO CPU!");
|
||||
#endif
|
||||
#if CONFIG_SYSVIEW_ENABLE
|
||||
SEGGER_SYSVIEW_Conf();
|
||||
#endif
|
||||
|
||||
#if CONFIG_ESP_DEBUG_STUBS_ENABLE
|
||||
esp_dbg_stubs_init();
|
||||
#endif
|
||||
|
||||
err = esp_pthread_init();
|
||||
assert(err == ESP_OK && "Failed to init pthread module!");
|
||||
|
||||
spi_flash_init();
|
||||
/* init default OS-aware flash access critical section */
|
||||
spi_flash_guard_set(&g_flash_guard_default_ops);
|
||||
|
||||
esp_flash_app_init();
|
||||
esp_err_t flash_ret = esp_flash_init_default_chip();
|
||||
assert(flash_ret == ESP_OK);
|
||||
}
|
||||
|
||||
static void IRAM_ATTR do_secondary_init(void)
|
||||
{
|
||||
#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
|
||||
// The port layer transferred control to this function with other cores 'paused',
|
||||
// resume execution so that cores might execute component initialization functions.
|
||||
startup_resume_other_cores();
|
||||
#endif
|
||||
|
||||
// Execute initialization functions esp_system_init_fn_t assigned to the main core. While
|
||||
// this is happening, all other cores are executing the initialization functions
|
||||
// assigned to them since they have been resumed already.
|
||||
do_system_init_fn();
|
||||
|
||||
#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
|
||||
// Wait for all cores to finish secondary init.
|
||||
volatile bool system_inited = false;
|
||||
|
||||
while (!system_inited) {
|
||||
system_inited = true;
|
||||
for (int i = 0; i < SOC_CPU_CORES_NUM; i++) {
|
||||
system_inited &= s_system_inited[i];
|
||||
}
|
||||
ets_delay_us(100);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void IRAM_ATTR start_cpu0_default(void)
|
||||
{
|
||||
ESP_EARLY_LOGI(TAG, "Pro cpu start user code");
|
||||
|
||||
// Display information about the current running image.
|
||||
if (LOG_LOCAL_LEVEL >= ESP_LOG_INFO) {
|
||||
const esp_app_desc_t *app_desc = esp_ota_get_app_description();
|
||||
ESP_EARLY_LOGI(TAG, "Application information:");
|
||||
#ifndef CONFIG_APP_EXCLUDE_PROJECT_NAME_VAR
|
||||
ESP_EARLY_LOGI(TAG, "Project name: %s", app_desc->project_name);
|
||||
#endif
|
||||
#ifndef CONFIG_APP_EXCLUDE_PROJECT_VER_VAR
|
||||
ESP_EARLY_LOGI(TAG, "App version: %s", app_desc->version);
|
||||
#endif
|
||||
#ifdef CONFIG_BOOTLOADER_APP_SECURE_VERSION
|
||||
ESP_EARLY_LOGI(TAG, "Secure version: %d", app_desc->secure_version);
|
||||
#endif
|
||||
#ifdef CONFIG_APP_COMPILE_TIME_DATE
|
||||
ESP_EARLY_LOGI(TAG, "Compile time: %s %s", app_desc->date, app_desc->time);
|
||||
#endif
|
||||
char buf[17];
|
||||
esp_ota_get_app_elf_sha256(buf, sizeof(buf));
|
||||
ESP_EARLY_LOGI(TAG, "ELF file SHA256: %s...", buf);
|
||||
ESP_EARLY_LOGI(TAG, "ESP-IDF: %s", app_desc->idf_ver);
|
||||
}
|
||||
|
||||
// Initialize core components and services.
|
||||
do_core_init();
|
||||
|
||||
// Execute constructors.
|
||||
do_global_ctors();
|
||||
|
||||
// Execute init functions of other components; blocks
|
||||
// until all cores finish (when !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE).
|
||||
do_secondary_init();
|
||||
|
||||
// Now that the application is about to start, disable boot watchdog
|
||||
#ifndef CONFIG_BOOTLOADER_WDT_DISABLE_IN_USER_CODE
|
||||
wdt_hal_context_t rtc_wdt_ctx = {.inst = WDT_RWDT, .rwdt_dev = &RTCCNTL};
|
||||
wdt_hal_write_protect_disable(&rtc_wdt_ctx);
|
||||
wdt_hal_disable(&rtc_wdt_ctx);
|
||||
wdt_hal_write_protect_enable(&rtc_wdt_ctx);
|
||||
#endif
|
||||
|
||||
#if SOC_CPU_CORES_NUM > 1 && !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
|
||||
s_system_full_inited = true;
|
||||
#endif
|
||||
|
||||
start_app();
|
||||
while (1);
|
||||
}
|
||||
|
||||
IRAM_ATTR ESP_SYSTEM_INIT_FN(init_components0, BIT(0))
|
||||
{
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
const int uart_clk_freq = REF_CLK_FREQ;
|
||||
/* When DFS is enabled, use REFTICK as UART clock source */
|
||||
CLEAR_PERI_REG_MASK(UART_CONF0_REG(CONFIG_ESP_CONSOLE_UART_NUM), UART_TICK_REF_ALWAYS_ON);
|
||||
uart_div_modify(CONFIG_ESP_CONSOLE_UART_NUM, (uart_clk_freq << 4) / CONFIG_ESP_CONSOLE_UART_BAUDRATE);
|
||||
#endif // CONFIG_ESP_CONSOLE_UART_NONE
|
||||
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
esp_pm_impl_init();
|
||||
#ifdef CONFIG_PM_DFS_INIT_AUTO
|
||||
int xtal_freq = (int) rtc_clk_xtal_freq_get();
|
||||
esp_pm_config_esp32_t cfg = {
|
||||
.max_freq_mhz = CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ,
|
||||
.min_freq_mhz = xtal_freq,
|
||||
};
|
||||
esp_pm_configure(&cfg);
|
||||
#endif //CONFIG_PM_DFS_INIT_AUTO
|
||||
#endif //CONFIG_PM_ENABLE
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#if CONFIG_ESP32_ENABLE_COREDUMP
|
||||
esp_core_dump_init();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#if CONFIG_ESP32_WIFI_SW_COEXIST_ENABLE
|
||||
esp_coex_adapter_register(&g_coex_adapter_funcs);
|
||||
coex_pre_init();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BOOTLOADER_EFUSE_SECURE_VERSION_EMULATE
|
||||
const esp_partition_t *efuse_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_EFUSE_EM, NULL);
|
||||
if (efuse_partition) {
|
||||
esp_efuse_init(efuse_partition->address, efuse_partition->size);
|
||||
}
|
||||
#endif
|
||||
}
|
|
@ -62,3 +62,11 @@ set_source_files_properties(
|
|||
PROPERTIES COMPILE_DEFINITIONS
|
||||
_ESP_FREERTOS_INTERNAL
|
||||
)
|
||||
|
||||
# The freertos component provides the `start_app` and `start_app_other_cores`
|
||||
# if it is included in the build. It then calls `app_main`
|
||||
# from the main task created, which must be provided by the user.
|
||||
# Like for `start_app` and `start_app_other_cores`,
|
||||
# we can't establish dependency on what we don't yet know, so we force the
|
||||
# linker to not drop this symbol.
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u app_main")
|
|
@ -1,9 +1,9 @@
|
|||
menu "FreeRTOS"
|
||||
|
||||
config FREERTOS_UNICORE
|
||||
# This config variable is also checked in the ESP32 startup code, not only in FreeRTOS.
|
||||
bool "Run FreeRTOS only on first core"
|
||||
default n
|
||||
default "y" if IDF_TARGET_ESP32S2
|
||||
select ESP_SYSTEM_SINGLE_CORE_MODE
|
||||
help
|
||||
This version of FreeRTOS normally takes control of all cores of
|
||||
the CPU. Select this if you only want to start it on the first core.
|
||||
|
|
|
@ -103,6 +103,7 @@
|
|||
|
||||
#include "esp_debug_helpers.h"
|
||||
#include "esp_heap_caps.h"
|
||||
#include "esp_heap_caps_init.h"
|
||||
#include "esp_private/crosscore_int.h"
|
||||
|
||||
#include "esp_intr_alloc.h"
|
||||
|
@ -110,12 +111,37 @@
|
|||
#include "sdkconfig.h"
|
||||
#include "esp_compiler.h"
|
||||
|
||||
#include "esp_task_wdt.h"
|
||||
#include "esp_task.h"
|
||||
|
||||
#include "soc/soc_caps.h"
|
||||
#include "soc/efuse_reg.h"
|
||||
#include "soc/dport_access.h"
|
||||
#include "soc/dport_reg.h"
|
||||
#include "esp_int_wdt.h"
|
||||
|
||||
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#include "esp32/spiram.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
#include "esp32s2/spiram.h"
|
||||
#endif
|
||||
|
||||
#include "esp_private/startup_internal.h" // [refactor-todo] for g_spiram_ok
|
||||
#include "esp_app_trace.h" // [refactor-todo] for esp_app_trace_init
|
||||
|
||||
/* Defined in portasm.h */
|
||||
extern void _frxt_tick_timer_init(void);
|
||||
|
||||
/* Defined in xtensa_context.S */
|
||||
extern void _xt_coproc_init(void);
|
||||
|
||||
extern void app_main(void);
|
||||
|
||||
static const char* TAG = "cpu_start"; // [refactor-todo]: might be appropriate to change in the future, but
|
||||
// for now maintain the same log output
|
||||
|
||||
#if CONFIG_FREERTOS_CORETIMER_0
|
||||
#define SYSTICK_INTR_ID (ETS_INTERNAL_TIMER0_INTR_SOURCE+ETS_INTERNAL_INTR_SOURCE_OFF)
|
||||
|
@ -127,7 +153,7 @@ extern void _xt_coproc_init(void);
|
|||
_Static_assert(tskNO_AFFINITY == CONFIG_FREERTOS_NO_AFFINITY, "incorrect tskNO_AFFINITY value");
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
unsigned port_xSchedulerRunning[portNUM_PROCESSORS] = {0}; // Duplicate of inaccessible xSchedulerRunning; needed at startup to avoid counting nesting
|
||||
volatile unsigned port_xSchedulerRunning[portNUM_PROCESSORS] = {0}; // Duplicate of inaccessible xSchedulerRunning; needed at startup to avoid counting nesting
|
||||
unsigned port_interruptNesting[portNUM_PROCESSORS] = {0}; // Interrupt nesting level. Increased/decreased in portasm.c, _frxt_int_enter/_frxt_int_exit
|
||||
BaseType_t port_uxCriticalNesting[portNUM_PROCESSORS] = {0};
|
||||
BaseType_t port_uxOldInterruptState[portNUM_PROCESSORS] = {0};
|
||||
|
@ -435,3 +461,132 @@ void __attribute__((weak)) vApplicationStackOverflowHook( TaskHandle_t xTask, c
|
|||
}
|
||||
esp_system_abort(buf);
|
||||
}
|
||||
|
||||
|
||||
static void main_task(void* args)
|
||||
{
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
// Wait for FreeRTOS initialization to finish on APP CPU, before replacing its startup stack
|
||||
while (port_xSchedulerRunning[1] == 0) {
|
||||
;
|
||||
}
|
||||
#endif
|
||||
|
||||
// [refactor-todo] check if there is a way to move the following block to esp_system startup
|
||||
heap_caps_enable_nonos_stack_heaps();
|
||||
|
||||
// Now we have startup stack RAM available for heap, enable any DMA pool memory
|
||||
#if CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL
|
||||
if (g_spiram_ok) {
|
||||
esp_err_t r = esp_spiram_reserve_dma_pool(CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL);
|
||||
if (r != ESP_OK) {
|
||||
ESP_EARLY_LOGE(TAG, "Could not reserve internal/DMA pool (error 0x%x)", r);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
//Initialize task wdt if configured to do so
|
||||
#ifdef CONFIG_ESP_TASK_WDT_PANIC
|
||||
ESP_ERROR_CHECK(esp_task_wdt_init(CONFIG_ESP_TASK_WDT_TIMEOUT_S, true));
|
||||
#elif CONFIG_ESP_TASK_WDT
|
||||
ESP_ERROR_CHECK(esp_task_wdt_init(CONFIG_ESP_TASK_WDT_TIMEOUT_S, false));
|
||||
#endif
|
||||
|
||||
//Add IDLE 0 to task wdt
|
||||
#ifdef CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0
|
||||
TaskHandle_t idle_0 = xTaskGetIdleTaskHandleForCPU(0);
|
||||
if(idle_0 != NULL){
|
||||
ESP_ERROR_CHECK(esp_task_wdt_add(idle_0));
|
||||
}
|
||||
#endif
|
||||
//Add IDLE 1 to task wdt
|
||||
#ifdef CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1
|
||||
TaskHandle_t idle_1 = xTaskGetIdleTaskHandleForCPU(1);
|
||||
if(idle_1 != NULL){
|
||||
ESP_ERROR_CHECK(esp_task_wdt_add(idle_1));
|
||||
}
|
||||
#endif
|
||||
|
||||
app_main();
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
// For now, running FreeRTOS on one core and a bare metal on the other (or other OSes)
|
||||
// is not supported. For now CONFIG_FREERTOS_UNICORE and CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
|
||||
// should mirror each other's values.
|
||||
//
|
||||
// And since this should be true, we can just check for CONFIG_FREERTOS_UNICORE.
|
||||
#if CONFIG_FREERTOS_UNICORE != CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
|
||||
#error "FreeRTOS and system configuration mismatch regarding the use of multiple cores."
|
||||
#endif
|
||||
|
||||
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
void start_app_other_cores(void)
|
||||
{
|
||||
// For now, we only support up to two core: 0 and 1.
|
||||
if (xPortGetCoreID() >= 2) {
|
||||
abort();
|
||||
}
|
||||
|
||||
// Wait for FreeRTOS initialization to finish on PRO CPU
|
||||
while (port_xSchedulerRunning[0] == 0) {
|
||||
;
|
||||
}
|
||||
|
||||
#if CONFIG_APPTRACE_ENABLE
|
||||
// [refactor-todo] move to esp_system initialization
|
||||
esp_err_t err = esp_apptrace_init();
|
||||
assert(err == ESP_OK && "Failed to init apptrace module on APP CPU!");
|
||||
#endif
|
||||
|
||||
#if CONFIG_ESP_INT_WDT
|
||||
//Initialize the interrupt watch dog for CPU1.
|
||||
esp_int_wdt_cpu_init();
|
||||
#endif
|
||||
|
||||
esp_crosscore_int_init();
|
||||
esp_dport_access_int_init();
|
||||
|
||||
ESP_EARLY_LOGI(TAG, "Starting scheduler on APP CPU.");
|
||||
xPortStartScheduler();
|
||||
abort(); /* Only get to here if FreeRTOS somehow very broken */
|
||||
}
|
||||
#endif
|
||||
|
||||
void start_app(void)
|
||||
{
|
||||
#if CONFIG_ESP_INT_WDT
|
||||
esp_int_wdt_init();
|
||||
//Initialize the interrupt watch dog for CPU0.
|
||||
esp_int_wdt_cpu_init();
|
||||
#else
|
||||
#if CONFIG_ESP32_ECO3_CACHE_LOCK_FIX
|
||||
assert(!soc_has_cache_lock_bug() && "ESP32 Rev 3 + Dual Core + PSRAM requires INT WDT enabled in project config!");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
esp_crosscore_int_init();
|
||||
|
||||
#ifndef CONFIG_FREERTOS_UNICORE
|
||||
esp_dport_access_int_init();
|
||||
#endif
|
||||
|
||||
portBASE_TYPE res = xTaskCreatePinnedToCore(&main_task, "main",
|
||||
ESP_TASK_MAIN_STACK, NULL,
|
||||
ESP_TASK_MAIN_PRIO, NULL, 0);
|
||||
assert(res == pdTRUE);
|
||||
|
||||
// ESP32 has single core variants. Check that FreeRTOS has been configured properly.
|
||||
#if CONFIG_IDF_TARGET_ESP32 && !CONFIG_FREERTOS_UNICORE
|
||||
if (REG_GET_BIT(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_VER_DIS_APP_CPU)) {
|
||||
ESP_EARLY_LOGE(TAG, "Running on single core chip, but FreeRTOS is built with dual core support.");
|
||||
ESP_EARLY_LOGE(TAG, "Please enable CONFIG_FREERTOS_UNICORE option in menuconfig.");
|
||||
abort();
|
||||
}
|
||||
#endif // CONFIG_IDF_TARGET_ESP32 && !CONFIG_FREERTOS_UNICORE
|
||||
|
||||
ESP_LOGI(TAG, "Starting scheduler on PRO CPU.");
|
||||
vTaskStartScheduler();
|
||||
}
|
|
@ -82,6 +82,11 @@ esp_err_t esp_pthread_set_cfg(const esp_pthread_cfg_t *cfg);
|
|||
*/
|
||||
esp_err_t esp_pthread_get_cfg(esp_pthread_cfg_t *p);
|
||||
|
||||
/**
|
||||
* @brief Initialize pthread library
|
||||
*/
|
||||
esp_err_t esp_pthread_init(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -22,6 +22,14 @@
|
|||
|
||||
#include "soc/cpu_caps.h"
|
||||
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#include "esp32/rom/ets_sys.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
#include "esp32s2/rom/ets_sys.h"
|
||||
#endif
|
||||
|
||||
#if SOC_CPU_BREAKPOINTS_NUM > 0
|
||||
void cpu_hal_set_breakpoint(int id, const void* addr)
|
||||
{
|
||||
|
|
|
@ -10,7 +10,8 @@
|
|||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "../esp_clk_internal.h"
|
||||
|
||||
extern void rtc_clk_select_rtc_slow_clk(void);
|
||||
|
||||
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2)
|
||||
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
#include "soc/soc_memory_layout.h"
|
||||
#include "soc/cpu.h"
|
||||
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#include "esp32/rom/ets_sys.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
|
|
|
@ -30,12 +30,12 @@ static const char* TAG = "trax";
|
|||
int trax_start_trace(trax_downcount_unit_t units_until_stop)
|
||||
{
|
||||
#if !WITH_TRAX
|
||||
ESP_LOGE(TAG, "Trax_start_trace called, but trax is disabled in menuconfig!");
|
||||
ESP_EARLY_LOGE(TAG, "Trax_start_trace called, but trax is disabled in menuconfig!");
|
||||
return ESP_ERR_NO_MEM;
|
||||
#endif
|
||||
uint32_t v;
|
||||
if (eri_read(ERI_TRAX_TRAXSTAT)&TRAXSTAT_TRACT) {
|
||||
ESP_LOGI(TAG, "Stopping active trace first.");
|
||||
ESP_EARLY_LOGI(TAG, "Stopping active trace first.");
|
||||
//Trace is active. Stop trace.
|
||||
eri_write(ERI_TRAX_DELAYCNT, 0);
|
||||
eri_write(ERI_TRAX_TRAXCTRL, eri_read(ERI_TRAX_TRAXCTRL)|TRAXCTRL_TRSTP);
|
||||
|
@ -54,7 +54,7 @@ int trax_start_trace(trax_downcount_unit_t units_until_stop)
|
|||
int trax_trigger_traceend_after_delay(int delay)
|
||||
{
|
||||
#if !WITH_TRAX
|
||||
ESP_LOGE(TAG, "Trax_trigger_traceend_after_delay called, but trax is disabled in menuconfig!");
|
||||
ESP_EARLY_LOGE(TAG, "Trax_trigger_traceend_after_delay called, but trax is disabled in menuconfig!");
|
||||
return ESP_ERR_NO_MEM;
|
||||
#endif
|
||||
eri_write(ERI_TRAX_DELAYCNT, delay);
|
||||
|
|
|
@ -499,8 +499,8 @@ ESP-IDF FreeRTOS configurations, see :doc:`FreeRTOS <../api-reference/kconfig>`
|
|||
|
||||
:ref:`CONFIG_FREERTOS_UNICORE` will run ESP-IDF FreeRTOS only
|
||||
on **PRO_CPU**. Note that this is **not equivalent to running vanilla
|
||||
FreeRTOS**. Behaviors of multiple components in ESP-IDF will be modified such
|
||||
as :component_file:`esp32/cpu_start.c`. For more details regarding the
|
||||
FreeRTOS**. Note that this option may affect behavior of components other than
|
||||
:component:`freertos`. For more details regarding the
|
||||
effects of running ESP-IDF FreeRTOS on a single core, search for
|
||||
occurences of ``CONFIG_FREERTOS_UNICORE`` in the ESP-IDF components.
|
||||
|
||||
|
|
|
@ -69,9 +69,9 @@ function run_tests()
|
|||
print_status "Updating component source file rebuilds component"
|
||||
# touch a file & do a build
|
||||
take_build_snapshot
|
||||
touch ${IDF_PATH}/components/esp32/cpu_start.c
|
||||
touch ${IDF_PATH}/components/esp_system/port/cpu_start.c
|
||||
make || failure "Failed to partial build"
|
||||
assert_rebuilt ${APP_BINS} esp32/libesp32.a esp32/cpu_start.o
|
||||
assert_rebuilt ${APP_BINS} esp_system/libesp_system.a esp_system/port/cpu_start.o
|
||||
assert_not_rebuilt lwip/liblwip.a freertos/libfreertos.a ${BOOTLOADER_BINS} partitions_singleapp.bin
|
||||
|
||||
print_status "Bootloader source file rebuilds bootloader"
|
||||
|
@ -251,12 +251,12 @@ function run_tests()
|
|||
echo "project-version-2.0(012345678901234567890123456789)" > ${TESTDIR}/template/version.txt
|
||||
make
|
||||
assert_rebuilt ${APP_BINS}
|
||||
assert_not_rebuilt ${BOOTLOADER_BINS} esp32/libesp32.a
|
||||
assert_not_rebuilt ${BOOTLOADER_BINS} esp_system/libesp_system.a
|
||||
|
||||
print_status "Re-building does not change app.bin"
|
||||
take_build_snapshot
|
||||
make
|
||||
assert_not_rebuilt ${APP_BINS} ${BOOTLOADER_BINS} esp32/libesp32.a
|
||||
assert_not_rebuilt ${APP_BINS} ${BOOTLOADER_BINS} esp_system/libesp_system.a
|
||||
rm -f ${TESTDIR}/template/version.txt
|
||||
|
||||
print_status "Get the version of app from git describe. Project is not inside IDF and do not have a tag only a hash commit."
|
||||
|
|
|
@ -72,9 +72,9 @@ function run_tests()
|
|||
print_status "Updating component source file rebuilds component"
|
||||
# touch a file & do a build
|
||||
take_build_snapshot
|
||||
touch ${IDF_PATH}/components/esp32/cpu_start.c
|
||||
touch ${IDF_PATH}/components/esp_system/port/cpu_start.c
|
||||
idf.py build || failure "Failed to partial build"
|
||||
assert_rebuilt ${APP_BINS} esp-idf/esp32/libesp32.a esp-idf/esp32/CMakeFiles/${IDF_COMPONENT_PREFIX}_esp32.dir/cpu_start.c.obj
|
||||
assert_rebuilt ${APP_BINS} esp-idf/esp_system/libesp_system.a esp-idf/esp_system/CMakeFiles/${IDF_COMPONENT_PREFIX}_esp_system.dir/port/cpu_start.c.obj
|
||||
assert_not_rebuilt esp-idf/lwip/liblwip.a esp-idf/freertos/libfreertos.a ${BOOTLOADER_BINS} ${PARTITION_BIN}
|
||||
|
||||
print_status "Bootloader source file rebuilds bootloader"
|
||||
|
@ -109,12 +109,12 @@ function run_tests()
|
|||
echo "project-version-2.0(012345678901234567890123456789)" > ${TESTDIR}/template/version.txt
|
||||
idf.py build || failure "Failed to rebuild with changed app version"
|
||||
assert_rebuilt ${APP_BINS}
|
||||
assert_not_rebuilt ${BOOTLOADER_BINS} esp-idf/esp32/libesp32.a
|
||||
assert_not_rebuilt ${BOOTLOADER_BINS} esp-idf/esp_system/libesp_system.a
|
||||
|
||||
print_status "Re-building does not change app.bin"
|
||||
take_build_snapshot
|
||||
idf.py build
|
||||
assert_not_rebuilt ${APP_BINS} ${BOOTLOADER_BINS} esp-idf/esp32/libesp32.a
|
||||
assert_not_rebuilt ${APP_BINS} ${BOOTLOADER_BINS} esp-idf/esp_system/libesp_system.a
|
||||
rm -f ${IDF_PATH}/version.txt
|
||||
rm -f ${TESTDIR}/template/version.txt
|
||||
|
||||
|
|
Loading…
Reference in a new issue