esp_system: introduce single core mode proxy config

This commit is contained in:
Renz Christian Bagaporo 2020-02-13 17:43:23 +05:00 committed by Angus Gratton
parent c53ad56515
commit ef2a44d251
7 changed files with 142 additions and 81 deletions

View file

@ -10,4 +10,7 @@ add_subdirectory(port)
# Rely on user code to define app_main # Rely on user code to define app_main
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u app_main") target_link_libraries(${COMPONENT_LIB} INTERFACE "-u app_main")
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u app_mainX")
if (NOT CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE)
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u app_mainX")
endif()

View file

@ -32,4 +32,10 @@ menu "ESP System Settings"
of the crash. of the crash.
endchoice endchoice
config ESP_SYSTEM_SINGLE_CORE_MODE
bool
default n
help
Only initialize and use the main core.
endmenu # ESP System Settings endmenu # ESP System Settings

View file

@ -67,6 +67,8 @@
#endif // CONFIG_APP_BUILD_TYPE_ELF_RAM #endif // CONFIG_APP_BUILD_TYPE_ELF_RAM
#endif #endif
#include "startup_internal.h"
extern int _bss_start; extern int _bss_start;
extern int _bss_end; extern int _bss_end;
extern int _rtc_bss_start; extern int _rtc_bss_start;
@ -87,34 +89,23 @@ extern int _iram_bss_end;
#endif #endif
#endif // CONFIG_IDF_TARGET_ESP32 #endif // CONFIG_IDF_TARGET_ESP32
#include "startup_internal.h" #if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
static volatile bool s_cpu_up[SOC_CPU_CORES_NUM] = { false }; 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_cpu_inited[SOC_CPU_CORES_NUM] = { false };
static volatile bool s_resume_cores; 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. // 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; bool g_spiram_ok = true;
#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
void startup_resume_other_cores(void) void startup_resume_other_cores(void)
{ {
s_resume_cores = true; s_resume_cores = 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);
intr_matrix_set(1, i, ETS_INVALID_INUM);
}
}
#if SOC_CPU_CORES_NUM > 1
void IRAM_ATTR call_start_cpu1(void) void IRAM_ATTR call_start_cpu1(void)
{ {
cpu_hal_set_vecbase(&_init_start); cpu_hal_set_vecbase(&_init_start);
@ -156,7 +147,62 @@ void IRAM_ATTR call_start_cpu1(void)
SYS_STARTUP_FN(); 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];
}
cpu_hal_delay_us(100);
}
}
else {
s_cpu_inited[1] = true;
ESP_EARLY_LOGI(TAG, "Single core mode");
DPORT_CLEAR_PERI_REG_MASK(DPORT_APPCPU_CTRL_B_REG, DPORT_APPCPU_CLKGATE_EN);
}
}
#endif // !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
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 #endif
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, * We arrive here after the bootloader finished loading the program from flash. The hardware is mostly uninitialized,
@ -164,7 +210,11 @@ void IRAM_ATTR call_start_cpu1(void)
*/ */
void IRAM_ATTR call_start_cpu0(void) void IRAM_ATTR call_start_cpu0(void)
{ {
#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
RESET_REASON rst_reas[SOC_CPU_CORES_NUM]; RESET_REASON rst_reas[SOC_CPU_CORES_NUM];
#else
RESET_REASON rst_reas[1];
#endif
bootloader_init_mem(); bootloader_init_mem();
@ -172,14 +222,14 @@ void IRAM_ATTR call_start_cpu0(void)
cpu_hal_set_vecbase(&_init_start); cpu_hal_set_vecbase(&_init_start);
rst_reas[0] = rtc_get_reset_reason(0); rst_reas[0] = rtc_get_reset_reason(0);
#if SOC_CPU_CORES_NUM > 1 #if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
rst_reas[1] = rtc_get_reset_reason(1); rst_reas[1] = rtc_get_reset_reason(1);
#endif #endif
#ifndef CONFIG_BOOTLOADER_WDT_ENABLE #ifndef CONFIG_BOOTLOADER_WDT_ENABLE
// from panic handler we can be reset by RWDT or TG0WDT // 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 (rst_reas[0] == RTCWDT_SYS_RESET || rst_reas[0] == TG0WDT_SYS_RESET
#if SOC_CPU_CORES_NUM > 1 #if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
|| rst_reas[1] == RTCWDT_SYS_RESET || rst_reas[1] == TG0WDT_SYS_RESET || rst_reas[1] == RTCWDT_SYS_RESET || rst_reas[1] == TG0WDT_SYS_RESET
#endif #endif
) { ) {
@ -240,45 +290,13 @@ void IRAM_ATTR call_start_cpu0(void)
} }
#endif #endif
#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
s_cpu_up[0] = true; s_cpu_up[0] = true;
#endif
ESP_EARLY_LOGI(TAG, "Pro cpu up."); ESP_EARLY_LOGI(TAG, "Pro cpu up.");
#if CONFIG_IDF_TARGET_ESP32 #if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
// If not the single core variant of ESP32 - check this since there is start_other_core();
// 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];
}
cpu_hal_delay_us(100);
}
}
else {
s_cpu_inited[1] = true;
DPORT_CLEAR_PERI_REG_MASK(DPORT_APPCPU_CTRL_B_REG, DPORT_APPCPU_CLKGATE_EN);
}
#endif #endif
#if CONFIG_SPIRAM_MEMTEST #if CONFIG_SPIRAM_MEMTEST
@ -390,6 +408,7 @@ void IRAM_ATTR call_start_cpu0(void)
#endif //!CONFIG_SPIRAM_BOOT_INIT #endif //!CONFIG_SPIRAM_BOOT_INIT
#endif #endif
#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
s_cpu_inited[0] = true; s_cpu_inited[0] = true;
volatile bool cpus_inited = false; volatile bool cpus_inited = false;
@ -401,6 +420,7 @@ void IRAM_ATTR call_start_cpu0(void)
} }
cpu_hal_delay_us(100); cpu_hal_delay_us(100);
} }
#endif
SYS_STARTUP_FN(); SYS_STARTUP_FN();
} }

View file

@ -19,18 +19,26 @@
#include "soc/soc_caps.h" #include "soc/soc_caps.h"
#include "hal/cpu_hal.h" #include "hal/cpu_hal.h"
#include "sdkconfig.h"
extern bool g_spiram_ok; // [refactor-todo] better way to communicate this from port layer to common startup code 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 // Port layer defines the entry point. It then transfer control to a `sys_startup_fn_t`, stored in this
// array, one per core. // array, one per core.
typedef void (*sys_startup_fn_t)(void); 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]; 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. // Utility to execute `sys_startup_fn_t` for the current core.
#define SYS_STARTUP_FN() ((*g_startup_fn[(cpu_hal_get_core_id())])()) #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); void startup_resume_other_cores(void);
void startup_core_init(); #endif
typedef struct { typedef struct {
void (*fn)(void); void (*fn)(void);

View file

@ -38,7 +38,8 @@
#include "esp_efuse.h" #include "esp_efuse.h"
#include "esp_flash_encrypt.h" #include "esp_flash_encrypt.h"
/* Headers for other components init functions */ /***********************************************/
// Headers for other components init functions
#include "nvs_flash.h" #include "nvs_flash.h"
#include "esp_phy_init.h" #include "esp_phy_init.h"
#include "esp_coexist_internal.h" #include "esp_coexist_internal.h"
@ -61,12 +62,26 @@
#include "startup_internal.h" #include "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
// App entry point for core 0
extern void app_main(void);
// Entry point for core 0 from hardware init (port layer)
void start_cpu0(void) __attribute__((weak, alias("start_cpu0_default"))) __attribute__((noreturn)); 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_cpuX(void) __attribute__((weak, alias("start_cpuX_default"))) __attribute__((noreturn)); void start_cpuX(void) __attribute__((weak, alias("start_cpuX_default"))) __attribute__((noreturn));
// App entry point for core [1..X]
void app_mainX(void) __attribute__((weak, alias("app_mainX_default"))) __attribute__((noreturn)); void app_mainX(void) __attribute__((weak, alias("app_mainX_default"))) __attribute__((noreturn));
extern void app_main(void); 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, sys_startup_fn_t g_startup_fn[SOC_CPU_CORES_NUM] = { [0] = start_cpu0,
#if SOC_CPU_CORES_NUM > 1 #if SOC_CPU_CORES_NUM > 1
@ -74,8 +89,10 @@ sys_startup_fn_t g_startup_fn[SOC_CPU_CORES_NUM] = { [0] = start_cpu0,
#endif #endif
}; };
static volatile bool s_system_inited[SOC_CPU_CORES_NUM] = { false };
static volatile bool s_system_full_inited = false; 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 const char* TAG = "cpu_start";
@ -112,9 +129,12 @@ static void IRAM_ATTR do_system_init_fn(void)
} }
} }
#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
s_system_inited[cpu_hal_get_core_id()] = true; s_system_inited[cpu_hal_get_core_id()] = true;
#endif
} }
#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
static void IRAM_ATTR app_mainX_default(void) static void IRAM_ATTR app_mainX_default(void)
{ {
while(1) { while(1) {
@ -132,6 +152,7 @@ static void IRAM_ATTR start_cpuX_default(void)
app_mainX(); app_mainX();
} }
#endif
static void IRAM_ATTR do_core_init(void) static void IRAM_ATTR do_core_init(void)
{ {
@ -221,15 +242,18 @@ static void IRAM_ATTR do_core_init(void)
static void IRAM_ATTR do_secondary_init(void) 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', // The port layer transferred control to this function with other cores 'paused',
// resume execution so that cores might execute component initialization functions. // resume execution so that cores might execute component initialization functions.
startup_resume_other_cores(); startup_resume_other_cores();
#endif
// Execute initialization functions esp_system_init_fn_t assigned to the main core. While // 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 // this is happening, all other cores are executing the initialization functions
// assigned to them since they have been resumed already. // assigned to them since they have been resumed already.
do_system_init_fn(); do_system_init_fn();
#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
// Wait for all cores to finish secondary init. // Wait for all cores to finish secondary init.
volatile bool system_inited = false; volatile bool system_inited = false;
@ -240,6 +264,7 @@ static void IRAM_ATTR do_secondary_init(void)
} }
cpu_hal_delay_us(100); cpu_hal_delay_us(100);
} }
#endif
} }
void IRAM_ATTR start_cpu0_default(void) void IRAM_ATTR start_cpu0_default(void)
@ -273,7 +298,7 @@ void IRAM_ATTR start_cpu0_default(void)
do_global_ctors(); do_global_ctors();
// Execute init functions of other components; blocks // Execute init functions of other components; blocks
// until all cores finish. // until all cores finish (when !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE).
do_secondary_init(); do_secondary_init();
// Now that the application is about to start, disable boot watchdog // Now that the application is about to start, disable boot watchdog
@ -284,7 +309,9 @@ void IRAM_ATTR start_cpu0_default(void)
// Finally, we jump to user code. // Finally, we jump to user code.
ESP_EARLY_LOGI(TAG, "Pro cpu start user code"); ESP_EARLY_LOGI(TAG, "Pro cpu start user code");
#if SOC_CPU_CORES_NUM > 1 && !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
s_system_full_inited = true; s_system_full_inited = true;
#endif
app_main(); app_main();
while(1); while(1);
@ -339,10 +366,12 @@ IRAM_ATTR ESP_SYSTEM_INIT_FN(init_components0, BIT(0))
#endif #endif
} }
#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
IRAM_ATTR ESP_SYSTEM_INIT_FN(init_components1, BIT(1)) IRAM_ATTR ESP_SYSTEM_INIT_FN(init_components1, BIT(1))
{ {
#if CONFIG_APPTRACE_ENABLE #if CONFIG_APPTRACE_ENABLE
esp_err_t err = esp_apptrace_init(); esp_err_t err = esp_apptrace_init();
assert(err == ESP_OK && "Failed to init apptrace module on APP CPU!"); assert(err == ESP_OK && "Failed to init apptrace module on APP CPU!");
#endif #endif
} }
#endif

View file

@ -1,11 +1,9 @@
menu "FreeRTOS" menu "FreeRTOS"
config FREERTOS_UNICORE config FREERTOS_UNICORE
# 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" bool "Run FreeRTOS only on first core"
default y if IDF_TARGET_ESP32S2 default "y" if IDF_TARGET_ESP32S2
default n select ESP_SYSTEM_SINGLE_CORE_MODE
help help
This version of FreeRTOS normally takes control of all cores of 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. the CPU. Select this if you only want to start it on the first core.

View file

@ -135,8 +135,6 @@ static const char* TAG = "cpu_start"; // [refactor-todo]: might be appropriate t
#define SYSTICK_INTR_ID (ETS_INTERNAL_TIMER1_INTR_SOURCE+ETS_INTERNAL_INTR_SOURCE_OFF) #define SYSTICK_INTR_ID (ETS_INTERNAL_TIMER1_INTR_SOURCE+ETS_INTERNAL_INTR_SOURCE_OFF)
#endif #endif
_Static_assert(tskNO_AFFINITY == CONFIG_FREERTOS_NO_AFFINITY, "incorrect tskNO_AFFINITY value"); _Static_assert(tskNO_AFFINITY == CONFIG_FREERTOS_NO_AFFINITY, "incorrect tskNO_AFFINITY value");
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -494,11 +492,20 @@ static void main_task(void* args)
vTaskDelete(NULL); 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 #if !CONFIG_FREERTOS_UNICORE
void app_mainX(void) void app_mainX(void)
{ {
// For now, we only support up to two core: 0 and 1.
if (xPortGetCoreID() >= 2) { if (xPortGetCoreID() >= 2) {
// Explicitly support only up to two cores for now.
abort(); abort();
} }
@ -544,24 +551,14 @@ void __wrap_app_main(void)
ESP_TASK_MAIN_PRIO, NULL, 0); ESP_TASK_MAIN_PRIO, NULL, 0);
assert(res == pdTRUE); assert(res == pdTRUE);
#if !CONFIG_FREERTOS_UNICORE // ESP32 has single core variants. Check that FreeRTOS has been configured properly.
// Check that FreeRTOS is configured properly for the number of cores the target #if CONFIG_IDF_TARGET_ESP32 && !CONFIG_FREERTOS_UNICORE
// has at compile and build time.
#if SOC_CPU_CORES_NUM < 2
#error FreeRTOS configured to run on dual core, but target only has a single core.
#endif
if (REG_GET_BIT(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_VER_DIS_APP_CPU)) { 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, "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."); ESP_EARLY_LOGE(TAG, "Please enable CONFIG_FREERTOS_UNICORE option in menuconfig.");
abort(); abort();
} }
#endif // CONFIG_IDF_TARGET_ESP32 && !CONFIG_FREERTOS_UNICORE
#else
#if SOC_CPU_CORES_NUM > 1 // 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 // !CONFIG_FREERTOS_UNICORE
ESP_LOGI(TAG, "Starting scheduler on PRO CPU."); ESP_LOGI(TAG, "Starting scheduler on PRO CPU.");
vTaskStartScheduler(); vTaskStartScheduler();