Merge branch 'bugfix/dual_core_app_on_single_core_esp32' into 'master'

esp_system: fix dual core app issue on single core esp32

Closes IDF-2154

See merge request espressif/esp-idf!10728
This commit is contained in:
Angus Gratton 2021-03-31 01:06:52 +00:00
commit d44034c54d
7 changed files with 84 additions and 44 deletions

View File

@ -202,51 +202,55 @@ void IRAM_ATTR call_start_cpu1(void)
static void start_other_core(void)
{
// If not the single core variant of ESP32 - check this since there is
esp_chip_info_t chip_info;
esp_chip_info(&chip_info);
// If not the single core variant of a target - check this since there is
// no separate soc_caps.h for the single core variant.
bool is_single_core = false;
#if CONFIG_IDF_TARGET_ESP32
is_single_core = REG_GET_BIT(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_VER_DIS_APP_CPU);
#endif
if (!is_single_core) {
ESP_EARLY_LOGI(TAG, "Starting app cpu, entry point is %p", call_start_cpu1);
if (!(chip_info.cores > 1)) {
ESP_EARLY_LOGE(TAG, "Running on single core variant of a chip, but app is built with multi-core support.");
ESP_EARLY_LOGE(TAG, "Check that CONFIG_FREERTOS_UNICORE is enabled in menuconfig");
abort();
}
ESP_EARLY_LOGI(TAG, "Starting app cpu, entry point is %p", call_start_cpu1);
#if CONFIG_IDF_TARGET_ESP32
Cache_Flush(1);
Cache_Read_Enable(1);
Cache_Flush(1);
Cache_Read_Enable(1);
#endif
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.
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 CONFIG_IDF_TARGET_ESP32
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);
}
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);
}
#elif CONFIG_IDF_TARGET_ESP32S3
if (!REG_GET_BIT(SYSTEM_CORE_1_CONTROL_0_REG, SYSTEM_CONTROL_CORE_1_CLKGATE_EN)) {
REG_SET_BIT(SYSTEM_CORE_1_CONTROL_0_REG, SYSTEM_CONTROL_CORE_1_CLKGATE_EN);
REG_CLR_BIT(SYSTEM_CORE_1_CONTROL_0_REG, SYSTEM_CONTROL_CORE_1_RUNSTALL);
REG_SET_BIT(SYSTEM_CORE_1_CONTROL_0_REG, SYSTEM_CONTROL_CORE_1_RESETING);
REG_CLR_BIT(SYSTEM_CORE_1_CONTROL_0_REG, SYSTEM_CONTROL_CORE_1_RESETING);
}
if (!REG_GET_BIT(SYSTEM_CORE_1_CONTROL_0_REG, SYSTEM_CONTROL_CORE_1_CLKGATE_EN)) {
REG_SET_BIT(SYSTEM_CORE_1_CONTROL_0_REG, SYSTEM_CONTROL_CORE_1_CLKGATE_EN);
REG_CLR_BIT(SYSTEM_CORE_1_CONTROL_0_REG, SYSTEM_CONTROL_CORE_1_RUNSTALL);
REG_SET_BIT(SYSTEM_CORE_1_CONTROL_0_REG, SYSTEM_CONTROL_CORE_1_RESETING);
REG_CLR_BIT(SYSTEM_CORE_1_CONTROL_0_REG, SYSTEM_CONTROL_CORE_1_RESETING);
}
#endif
ets_set_appcpu_boot_addr((uint32_t)call_start_cpu1);
ets_set_appcpu_boot_addr((uint32_t)call_start_cpu1);
volatile bool cpus_up = false;
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];
}
esp_rom_delay_us(100);
while (!cpus_up) {
cpus_up = true;
for (int i = 0; i < SOC_CPU_CORES_NUM; i++) {
cpus_up &= s_cpu_up[i];
}
esp_rom_delay_us(100);
}
}
#endif // !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE

View File

@ -534,15 +534,6 @@ void esp_startup_start_app(void)
#endif
#endif
// 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_startup_start_app_common();
ESP_LOGI(TAG, "Starting scheduler on PRO CPU.");

View File

@ -2,9 +2,11 @@
import glob
import os
import re
import ttfw_idf
from tiny_test_fw import Utility
from ttfw_idf.IDFDUT import ESP32DUT
@ttfw_idf.idf_custom_test(env_tag='Example_GENERIC', group='test-apps')
@ -15,7 +17,14 @@ def test_startup(env, extra_data):
Utility.console_log("Checking config \"{}\"... ".format(name), end='')
dut = env.get_dut('startup', 'tools/test_apps/system/startup', app_config_name=name)
dut.start_app()
dut.expect('app_main running')
if (name == 'single_core_variant' and isinstance(dut, ESP32DUT)):
dut.allow_dut_exception = True
dut.expect('Running on single core variant of a chip, but app is built with multi-core support.')
dut.expect(re.compile(r'abort\(\) was called at PC [0-9xa-f]+ on core 0'))
else:
dut.expect('app_main running')
env.close_dut(dut.name)
Utility.console_log('done')

View File

@ -1,2 +1,7 @@
idf_component_register(SRCS "test_startup_main.c"
INCLUDE_DIRS ".")
if(CONFIG_SINGLE_CORE_VARIANT)
target_sources(${COMPONENT_LIB} PRIVATE "${CMAKE_CURRENT_LIST_DIR}/chip_info_patch.c")
target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=esp_chip_info")
endif()

View File

@ -0,0 +1,6 @@
menu "Test app config"
config SINGLE_CORE_VARIANT
bool "Patch esp_chip_info to return single core in a multicore chip"
default "n"
depends on IDF_TARGET_ESP32 || IDF_TARGET_ESP32S3
endmenu

View File

@ -0,0 +1,24 @@
// Copyright 2013-2016 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 "esp_system.h"
extern void __real_esp_chip_info(esp_chip_info_t* out_info);
// Fake a single core chip for testing purposes only, see CONFIG_SINGLE_CORE_VARIANT
void __wrap_esp_chip_info(esp_chip_info_t* out_info)
{
__real_esp_chip_info(out_info);
out_info->cores = 1;
}

View File

@ -0,0 +1 @@
CONFIG_SINGLE_CORE_VARIANT=y