esp32, esp32s2: move startup code into esp_system

This commit is contained in:
Renz Bagaporo 2020-03-03 12:22:41 +08:00 committed by Angus Gratton
parent 62ef63e835
commit bb5535ca5d
12 changed files with 610 additions and 847 deletions

View file

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

View file

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

View file

@ -50,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")

View file

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

View file

@ -1,7 +1,12 @@
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)
# Rely on user code to define app_main
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u app_main")

View file

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

View file

@ -0,0 +1,407 @@
// 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/brownout.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
#if !CONFIG_FREERTOS_UNICORE
static bool app_cpu_started = false;
#endif //!CONFIG_FREERTOS_UNICORE
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
extern void start_cpu0(void);
#if !CONFIG_FREERTOS_UNICORE
extern void start_cpu1(void);
#endif //!CONFIG_FREERTOS_UNICORE
extern int _init_start;
static const char* TAG = "cpu_start";
//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;
static void intr_matrix_clear(void)
{
#if CONFIG_IDF_TARGET_ESP32
//Clear all the interrupt matrix register
for (int i = ETS_WIFI_MAC_INTR_SOURCE; i <= ETS_CACHE_IA_INTR_SOURCE; i++) {
#elif CONFIG_IDF_TARGET_ESP32S2
for (int i = ETS_WIFI_MAC_INTR_SOURCE; i < ETS_MAX_INTR_SOURCE; i++) {
#endif
intr_matrix_set(0, i, ETS_INVALID_INUM);
#if !CONFIG_FREERTOS_UNICORE
intr_matrix_set(1, i, ETS_INVALID_INUM);
#endif
}
}
#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)
{
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;
//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
start_cpu1();
}
#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_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));
#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
ESP_EARLY_LOGI(TAG, "Pro cpu up.");
#ifdef CONFIG_SECURE_FLASH_ENC_ENABLED
esp_flash_encryption_init_checks();
#endif
#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
#if CONFIG_IDF_TARGET_ESP32 // Single core chips have no 'single core mode'
ESP_EARLY_LOGI(TAG, "Single core mode");
DPORT_CLEAR_PERI_REG_MASK(DPORT_APPCPU_CTRL_B_REG, DPORT_APPCPU_CLKGATE_EN);
#endif
#endif
#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();
#if CONFIG_ESP32_BROWNOUT_DET || CONFIG_ESP32S2_BROWNOUT_DET
esp_brownout_init();
#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 || CONFIG_ESP32S2_DISABLE_BASIC_ROM_CONSOLE
esp_efuse_disable_basic_rom_console();
#endif
rtc_gpio_force_hold_dis_all();
esp_cache_err_int_init();
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
start_cpu0();
}

View 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.

View file

@ -0,0 +1,21 @@
// Copyright 2020 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 "sdkconfig.h"
extern bool g_spiram_ok;
void sys_startup(void);

View file

@ -14,29 +14,11 @@
#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 "soc/rtc_wdt.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
@ -45,10 +27,8 @@
#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"
@ -59,114 +39,153 @@
#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_flash_encrypt.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"
#include "sdkconfig.h"
#if CONFIG_IDF_TARGET_ESP32
#include "esp32/rom/uart.h"
#include "esp32/dport_access.h"
#elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/rom/uart.h"
#include "esp32s2/dport_access.h"
#endif
#include "sys_funcs.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));
#if !CONFIG_FREERTOS_UNICORE
void start_cpu1(void) __attribute__((weak, alias("start_cpu1_default"))) __attribute__((noreturn));
void start_cpu1_default(void) IRAM_ATTR __attribute__((noreturn));
#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;
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 ];
};
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;
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
// 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));
}
esp_spiram_init_cache();
#endif
// Now that the application is about to start, disable boot watchdog
#ifndef CONFIG_BOOTLOADER_WDT_DISABLE_IN_USER_CODE
rtc_wdt_disable();
#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);
}
#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_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
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
/*
* 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)
void IRAM_ATTR start_cpu0_default(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:");
@ -187,97 +206,28 @@ void IRAM_ATTR call_start_cpu0(void)
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 (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_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;
@ -289,11 +239,6 @@ void start_cpu0_default(void)
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();
@ -310,10 +255,15 @@ void start_cpu0_default(void)
#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_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");
@ -321,16 +271,19 @@ void start_cpu0_default(void)
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
#if CONFIG_ESP_DEBUG_STUBS_ENABLE
esp_dbg_stubs_init();
#endif
err = esp_pthread_init();
assert(err == ESP_OK && "Failed to init pthread module!");
@ -345,11 +298,20 @@ void start_cpu0_default(void)
do_global_ctors();
#if CONFIG_ESP_INT_WDT
esp_int_wdt_init();
//Initialize the interrupt watch dog
//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
esp_cache_err_int_init();
#endif
esp_crosscore_int_init();
#ifndef CONFIG_FREERTOS_UNICORE
esp_dport_access_int_init();
#endif
spi_flash_init();
/* init default OS-aware flash access critical section */
spi_flash_guard_set(&g_flash_guard_default_ops);
@ -358,20 +320,29 @@ void start_cpu0_default(void)
esp_err_t flash_ret = esp_flash_init_default_chip();
assert(flash_ret == ESP_OK);
#if CONFIG_IDF_TARGET_ESP32
#if CONFIG_ESP32_ENABLE_COREDUMP
esp_core_dump_init();
#endif
#endif
#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,
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();
#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
portBASE_TYPE res = xTaskCreatePinnedToCore(&main_task, "main",
@ -383,63 +354,3 @@ void start_cpu0_default(void)
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);
}

View file

@ -1,8 +1,10 @@
menu "FreeRTOS"
config FREERTOS_UNICORE
# This config variable is also checked in the ESP32 startup code, not only in FreeRTOS.
# This config variable is also checked in the target startup code, not only in FreeRTOS
# hence the dependency on what target the app is being built for.
bool "Run FreeRTOS only on first core"
default y if IDF_TARGET_ESP32S2
default n
help
This version of FreeRTOS normally takes control of all cores of