From 8d322328999425e09977748f31469173b24e082e Mon Sep 17 00:00:00 2001 From: Renz Bagaporo Date: Mon, 5 Oct 2020 18:50:09 +0800 Subject: [PATCH 1/2] esp_system: check early for single core variant --- components/esp_system/port/cpu_start.c | 72 ++++++++++++++------------ components/freertos/port/xtensa/port.c | 9 ---- 2 files changed, 38 insertions(+), 43 deletions(-) diff --git a/components/esp_system/port/cpu_start.c b/components/esp_system/port/cpu_start.c index 124123ec2a..84ff745a4c 100644 --- a/components/esp_system/port/cpu_start.c +++ b/components/esp_system/port/cpu_start.c @@ -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 diff --git a/components/freertos/port/xtensa/port.c b/components/freertos/port/xtensa/port.c index 4061223364..033d6cc25a 100644 --- a/components/freertos/port/xtensa/port.c +++ b/components/freertos/port/xtensa/port.c @@ -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."); From 0a3ae58a61cca103242dcc10b3585f8085fadbc1 Mon Sep 17 00:00:00 2001 From: Renz Bagaporo Date: Wed, 10 Mar 2021 14:07:52 +0800 Subject: [PATCH 2/2] system: add test for simulating single core esp32 startup --- tools/test_apps/system/startup/app_test.py | 11 ++++++++- .../system/startup/main/CMakeLists.txt | 5 ++++ tools/test_apps/system/startup/main/Kconfig | 6 +++++ .../system/startup/main/chip_info_patch.c | 24 +++++++++++++++++++ .../startup/sdkconfig.ci.single_core_variant | 1 + 5 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 tools/test_apps/system/startup/main/Kconfig create mode 100644 tools/test_apps/system/startup/main/chip_info_patch.c create mode 100644 tools/test_apps/system/startup/sdkconfig.ci.single_core_variant diff --git a/tools/test_apps/system/startup/app_test.py b/tools/test_apps/system/startup/app_test.py index 9ce0a214f0..d7d1ee94bd 100644 --- a/tools/test_apps/system/startup/app_test.py +++ b/tools/test_apps/system/startup/app_test.py @@ -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') diff --git a/tools/test_apps/system/startup/main/CMakeLists.txt b/tools/test_apps/system/startup/main/CMakeLists.txt index 53aa18c094..2ba0fd3b3f 100644 --- a/tools/test_apps/system/startup/main/CMakeLists.txt +++ b/tools/test_apps/system/startup/main/CMakeLists.txt @@ -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() diff --git a/tools/test_apps/system/startup/main/Kconfig b/tools/test_apps/system/startup/main/Kconfig new file mode 100644 index 0000000000..220ac13799 --- /dev/null +++ b/tools/test_apps/system/startup/main/Kconfig @@ -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 diff --git a/tools/test_apps/system/startup/main/chip_info_patch.c b/tools/test_apps/system/startup/main/chip_info_patch.c new file mode 100644 index 0000000000..21b6ac78bc --- /dev/null +++ b/tools/test_apps/system/startup/main/chip_info_patch.c @@ -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; +} diff --git a/tools/test_apps/system/startup/sdkconfig.ci.single_core_variant b/tools/test_apps/system/startup/sdkconfig.ci.single_core_variant new file mode 100644 index 0000000000..61216b07fa --- /dev/null +++ b/tools/test_apps/system/startup/sdkconfig.ci.single_core_variant @@ -0,0 +1 @@ +CONFIG_SINGLE_CORE_VARIANT=y