From 75c92c3a66d058f71fd5c1b75c3cc56809f7e43b Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Fri, 24 Nov 2023 18:32:37 +0100 Subject: [PATCH 1/2] refactor(startup): implement registration of core init functions Similar to how the secondary init functions were already registered via ESP_SYSTEM_INIT_FN, do the same for the core init functions. This MR doesn't actually move the init functions into respective components yet. This has to be carefully done in follow-up MRs. --- components/app_trace/app_trace.c | 2 +- .../app_trace/sys_view/esp/SEGGER_RTT_esp.c | 2 +- .../usb_serial_jtag_connection_monitor.c | 2 +- components/esp_hw_support/sleep_clock.c | 2 +- components/esp_hw_support/sleep_gpio.c | 2 +- .../esp_hw_support/sleep_system_peripheral.c | 2 +- components/esp_system/CMakeLists.txt | 2 + .../check_system_init_priorities.py | 22 +- components/esp_system/hw_stack_guard.c | 2 +- .../include/esp_private/startup_internal.h | 17 +- components/esp_system/port/usb_console.c | 2 +- components/esp_system/startup.c | 315 +------------- components/esp_system/startup_funcs.c | 386 ++++++++++++++++++ components/esp_system/system_init_fn.txt | 81 +++- components/esp_timer/src/esp_timer.c | 2 +- 15 files changed, 499 insertions(+), 342 deletions(-) create mode 100644 components/esp_system/startup_funcs.c diff --git a/components/app_trace/app_trace.c b/components/app_trace/app_trace.c index 6a18087690..16b3ae3336 100644 --- a/components/app_trace/app_trace.c +++ b/components/app_trace/app_trace.c @@ -77,7 +77,7 @@ esp_err_t esp_apptrace_init(void) return ESP_OK; } -ESP_SYSTEM_INIT_FN(esp_apptrace_init, ESP_SYSTEM_INIT_ALL_CORES, 115) +ESP_SYSTEM_INIT_FN(esp_apptrace_init, SECONDARY, ESP_SYSTEM_INIT_ALL_CORES, 115) { return esp_apptrace_init(); } diff --git a/components/app_trace/sys_view/esp/SEGGER_RTT_esp.c b/components/app_trace/sys_view/esp/SEGGER_RTT_esp.c index 9963aced9d..191d5e4e3b 100644 --- a/components/app_trace/sys_view/esp/SEGGER_RTT_esp.c +++ b/components/app_trace/sys_view/esp/SEGGER_RTT_esp.c @@ -296,7 +296,7 @@ int SEGGER_RTT_ConfigDownBuffer(unsigned BufferIndex, const char* sName, void* p * linked whenever SystemView is used. */ -ESP_SYSTEM_INIT_FN(sysview_init, BIT(0), 120) +ESP_SYSTEM_INIT_FN(sysview_init, SECONDARY, BIT(0), 120) { SEGGER_SYSVIEW_Conf(); return ESP_OK; diff --git a/components/driver/usb_serial_jtag/usb_serial_jtag_connection_monitor.c b/components/driver/usb_serial_jtag/usb_serial_jtag_connection_monitor.c index 238069e20a..44a9f37eda 100644 --- a/components/driver/usb_serial_jtag/usb_serial_jtag_connection_monitor.c +++ b/components/driver/usb_serial_jtag/usb_serial_jtag_connection_monitor.c @@ -68,7 +68,7 @@ static void IRAM_ATTR usb_serial_jtag_sof_tick_hook(void) } } -ESP_SYSTEM_INIT_FN(usb_serial_jtag_conn_status_init, BIT(0), 230) +ESP_SYSTEM_INIT_FN(usb_serial_jtag_conn_status_init, SECONDARY, BIT(0), 230) { #if CONFIG_USJ_NO_AUTO_LS_ON_CONNECTION ESP_RETURN_ON_ERROR(esp_pm_lock_create(ESP_PM_NO_LIGHT_SLEEP, 0, "usb_serial_jtag", &s_usb_serial_jtag_pm_lock), diff --git a/components/esp_hw_support/sleep_clock.c b/components/esp_hw_support/sleep_clock.c index b18f0cb23f..c8f5474a3a 100644 --- a/components/esp_hw_support/sleep_clock.c +++ b/components/esp_hw_support/sleep_clock.c @@ -89,7 +89,7 @@ bool clock_domain_pd_allowed(void) } #if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP || CONFIG_MAC_BB_PD || CONFIG_BT_LE_SLEEP_ENABLE || CONFIG_IEEE802154_SLEEP_ENABLE -ESP_SYSTEM_INIT_FN(sleep_clock_startup_init, BIT(0), 106) +ESP_SYSTEM_INIT_FN(sleep_clock_startup_init, SECONDARY, BIT(0), 106) { #if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP sleep_clock_system_retention_init(); diff --git a/components/esp_hw_support/sleep_gpio.c b/components/esp_hw_support/sleep_gpio.c index 759659d1a9..d29541f634 100644 --- a/components/esp_hw_support/sleep_gpio.c +++ b/components/esp_hw_support/sleep_gpio.c @@ -185,7 +185,7 @@ void esp_deep_sleep_wakeup_io_reset(void) } #if CONFIG_ESP_SLEEP_GPIO_RESET_WORKAROUND || CONFIG_PM_SLP_DISABLE_GPIO -ESP_SYSTEM_INIT_FN(esp_sleep_startup_init, BIT(0), 105) +ESP_SYSTEM_INIT_FN(esp_sleep_startup_init, SECONDARY, BIT(0), 105) { /* If the TOP domain is powered off, the GPIO will also be powered off during sleep, and all configurations in the sleep state of GPIO will not take effect.*/ diff --git a/components/esp_hw_support/sleep_system_peripheral.c b/components/esp_hw_support/sleep_system_peripheral.c index 22d236dcd6..4bf9be2e7c 100644 --- a/components/esp_hw_support/sleep_system_peripheral.c +++ b/components/esp_hw_support/sleep_system_peripheral.c @@ -259,7 +259,7 @@ bool peripheral_domain_pd_allowed(void) } #if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP -ESP_SYSTEM_INIT_FN(sleep_sys_periph_startup_init, BIT(0), 107) +ESP_SYSTEM_INIT_FN(sleep_sys_periph_startup_init, SECONDARY, BIT(0), 107) { sleep_sys_periph_retention_init(); return ESP_OK; diff --git a/components/esp_system/CMakeLists.txt b/components/esp_system/CMakeLists.txt index ef194aa29c..04ad996b4e 100644 --- a/components/esp_system/CMakeLists.txt +++ b/components/esp_system/CMakeLists.txt @@ -29,6 +29,7 @@ else() "panic.c" "esp_system.c" "startup.c" + "startup_funcs.c" "system_time.c" "stack_check.c" "ubsan.c" @@ -97,6 +98,7 @@ endif() # due to -ffunction-sections -Wl,--gc-sections options. target_link_libraries(${COMPONENT_LIB} INTERFACE "-u __ubsan_include") +target_link_libraries(${COMPONENT_LIB} INTERFACE "-u esp_system_include_startup_funcs") # [refactor-todo] requirements due to init code, should be removable # once link-time registration of component init functions is used. diff --git a/components/esp_system/check_system_init_priorities.py b/components/esp_system/check_system_init_priorities.py index 4bb1741c08..91afafc36d 100644 --- a/components/esp_system/check_system_init_priorities.py +++ b/components/esp_system/check_system_init_priorities.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 # # This file is used to check the order of execution of ESP_SYSTEM_INIT_FN functions. @@ -18,19 +18,20 @@ import typing ESP_SYSTEM_INIT_FN_STR = r'ESP_SYSTEM_INIT_FN' ESP_SYSTEM_INIT_FN_REGEX_SIMPLE = re.compile(r'ESP_SYSTEM_INIT_FN') -ESP_SYSTEM_INIT_FN_REGEX = re.compile(r'ESP_SYSTEM_INIT_FN\(([a-zA-Z0-9_]+)\s*,\s*([a-zA-Z\ _0-9\(\)|]+)\s*,\s*([0-9]+)\)') +ESP_SYSTEM_INIT_FN_REGEX = re.compile(r'ESP_SYSTEM_INIT_FN\(([a-zA-Z0-9_]+)\s*,\s*([a-zA-Z\ _0-9\(\)|]+)\s*,\s*([a-zA-Z\ _0-9\(\)|]+)\s*,\s*([0-9]+)\)') STARTUP_ENTRIES_FILE = 'components/esp_system/system_init_fn.txt' class StartupEntry: - def __init__(self, filename: str, func: str, affinity: str, priority: int) -> None: + def __init__(self, filename: str, func: str, stage: str, affinity: str, priority: int) -> None: self.filename = filename self.func = func + self.stage = stage self.affinity = affinity self.priority = priority def __str__(self) -> str: - return f'{self.priority:3d}: {self.func} in {self.filename} on {self.affinity}' + return f'{self.stage}: {self.priority:3d}: {self.func} in {self.filename} on {self.affinity}' def main() -> None: @@ -65,15 +66,20 @@ def main() -> None: entry = StartupEntry( filename=os.path.relpath(filename, idf_path), func=match[0], - affinity=match[1], - priority=int(match[2]) + stage=match[1], + affinity=match[2], + priority=int(match[3]) ) startup_entries.append(entry) # - # 2. Sort the ESP_SYSTEM_INIT_FN functions in C source files by priority + # 2. Sort the ESP_SYSTEM_INIT_FN functions in C source files by stage and then priority # - startup_entries = list(sorted(startup_entries, key=lambda e: e.priority)) + def sort_key(entry: StartupEntry) -> typing.Tuple[str, int]: + # luckily 'core' and 'secondary' are in alphabetical order, so we can return the string + return (entry.stage, entry.priority) + + startup_entries = list(sorted(startup_entries, key=sort_key)) startup_entries_lines = [str(entry) for entry in startup_entries] # diff --git a/components/esp_system/hw_stack_guard.c b/components/esp_system/hw_stack_guard.c index 1f5eee429c..6789093f1a 100644 --- a/components/esp_system/hw_stack_guard.c +++ b/components/esp_system/hw_stack_guard.c @@ -11,7 +11,7 @@ #include "esp_rom_sys.h" #include "esp_cpu.h" -ESP_SYSTEM_INIT_FN(esp_hw_stack_guard_init, ESP_SYSTEM_INIT_ALL_CORES, 101) +ESP_SYSTEM_INIT_FN(esp_hw_stack_guard_init, SECONDARY, ESP_SYSTEM_INIT_ALL_CORES, 101) { uint32_t core_id = esp_cpu_get_core_id(); diff --git a/components/esp_system/include/esp_private/startup_internal.h b/components/esp_system/include/esp_private/startup_internal.h index 9886da8ca1..a1ca5c927c 100644 --- a/components/esp_system/include/esp_private/startup_internal.h +++ b/components/esp_system/include/esp_private/startup_internal.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -43,13 +43,18 @@ void startup_resume_other_cores(void); */ typedef struct { esp_err_t (*fn)(void); /*!< Pointer to the startup function */ - uint32_t cores; /*!< Bit map of cores where the function has to be called */ + uint16_t cores; /*!< Bit mask of cores where the function has to be called */ + uint16_t stage; /*!< Init stage number (0 or 1) */ } esp_system_init_fn_t; +#define ESP_SYSTEM_INIT_STAGE_CORE 0 +#define ESP_SYSTEM_INIT_STAGE_SECONDARY 1 + /** * @brief Define a system initialization function which will be executed on the specified cores * * @param f function name (identifier) + * @param stage_ init stage name (CORE or SECONDARY) * @param c bit mask of cores to execute the function on (ex. if BIT0 is set, the function * will be executed on CPU 0, if BIT1 is set - on CPU 1, and so on) * @param priority integer, priority of the initialization function. Higher values mean that @@ -65,10 +70,14 @@ typedef struct { * It is, on the other hand, a good practice to make sure the initialization function does get * discarded if the related feature is not used. */ -#define ESP_SYSTEM_INIT_FN(f, c, priority, ...) \ +#define ESP_SYSTEM_INIT_FN(f, stage_, c, priority, ...) \ static esp_err_t __VA_ARGS__ __esp_system_init_fn_##f(void); \ static __attribute__((used)) _SECTION_ATTR_IMPL(".esp_system_init_fn", priority) \ - esp_system_init_fn_t esp_system_init_fn_##f = { .fn = ( __esp_system_init_fn_##f), .cores = (c) }; \ + esp_system_init_fn_t esp_system_init_fn_##f = { \ + .fn = ( __esp_system_init_fn_##f), \ + .cores = (c), \ + .stage = ESP_SYSTEM_INIT_STAGE_##stage_ \ + }; \ static esp_err_t __esp_system_init_fn_##f(void) #ifdef CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE diff --git a/components/esp_system/port/usb_console.c b/components/esp_system/port/usb_console.c index 7e5dc5b7a7..fe8bf81587 100644 --- a/components/esp_system/port/usb_console.c +++ b/components/esp_system/port/usb_console.c @@ -310,7 +310,7 @@ esp_err_t esp_usb_console_init(void) * too early, before esp_timer is fully initialized. * This gets called a bit later in the process when we can already register a timer. */ -ESP_SYSTEM_INIT_FN(esp_usb_console_init_restart_timer, BIT(0), 220) +ESP_SYSTEM_INIT_FN(esp_usb_console_init_restart_timer, SECONDARY, BIT(0), 220) { esp_timer_create_args_t timer_create_args = { .callback = &esp_usb_console_on_restart_timeout, diff --git a/components/esp_system/startup.c b/components/esp_system/startup.c index 51c4561d7e..5fd5772bf4 100644 --- a/components/esp_system/startup.c +++ b/components/esp_system/startup.c @@ -16,66 +16,8 @@ #include "sdkconfig.h" #include "soc/soc_caps.h" -#include "hal/wdt_hal.h" -#include "hal/uart_types.h" -#include "hal/uart_ll.h" -#include "hal/efuse_hal.h" - -#include "esp_heap_caps_init.h" -#include "spi_flash_mmap.h" -#include "esp_flash_internal.h" -#include "esp_newlib.h" -#include "esp_timer.h" -#include "esp_efuse.h" -#include "esp_efuse_table.h" -#include "esp_flash_encrypt.h" -#include "esp_secure_boot.h" -#include "esp_xt_wdt.h" #include "esp_cpu.h" -#include "esp_partition.h" - -/***********************************************/ -// Headers for other components init functions -#if CONFIG_SW_COEXIST_ENABLE || CONFIG_EXTERNAL_COEX_ENABLE -#include "private/esp_coexist_internal.h" -#endif - -#if __has_include("esp_app_desc.h") -#define WITH_APP_IMAGE_INFO -#include "esp_app_desc.h" -#endif - -#if CONFIG_ESP_COREDUMP_ENABLE -#include "esp_core_dump.h" -#endif - -#include "esp_private/dbg_stubs.h" - -#if CONFIG_PM_ENABLE -#include "esp_pm.h" -#include "esp_private/pm_impl.h" -#endif - -#if CONFIG_VFS_SUPPORT_IO -#include "esp_vfs_dev.h" -#include "esp_vfs_console.h" -#endif - -#include "esp_pthread.h" -#include "esp_private/esp_clk.h" -#include "esp_private/spi_flash_os.h" -#include "esp_private/brownout.h" - -#include "esp_rom_caps.h" -#include "esp_rom_sys.h" - -#if CONFIG_SPIRAM -#include "esp_psram.h" -#include "esp_private/esp_psram_extram.h" -#endif -/***********************************************/ - #include "esp_private/startup_internal.h" // Ensure that system configuration matches the underlying number of cores. @@ -84,26 +26,8 @@ #error "System has been configured to run on multiple cores, but target SoC only has a single core." #endif -// Set efuse ROM_LOG_MODE on first boot -// -// For CONFIG_BOOT_ROM_LOG_ALWAYS_ON (default) or undefined (ESP32), leave -// ROM_LOG_MODE undefined (no need to call this function during startup) -#if CONFIG_BOOT_ROM_LOG_ALWAYS_OFF -#define ROM_LOG_MODE ESP_EFUSE_ROM_LOG_ALWAYS_OFF -#elif CONFIG_BOOT_ROM_LOG_ON_GPIO_LOW -#define ROM_LOG_MODE ESP_EFUSE_ROM_LOG_ON_GPIO_LOW -#elif CONFIG_BOOT_ROM_LOG_ON_GPIO_HIGH -#define ROM_LOG_MODE ESP_EFUSE_ROM_LOG_ON_GPIO_HIGH -#endif - - uint64_t g_startup_time = 0; -#if SOC_APB_BACKUP_DMA -// APB DMA lock initialising API -extern void esp_apb_backup_dma_lock_init(void); -#endif - // App entry point for core 0 extern void esp_startup_start_app(void); @@ -130,34 +54,8 @@ static volatile bool s_system_full_inited = false; const sys_startup_fn_t g_startup_fn[1] = { start_cpu0 }; #endif -#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS -// workaround for C++ exception crashes -void _Unwind_SetNoFunctionContextInstall(unsigned char enable) __attribute__((weak, alias("_Unwind_SetNoFunctionContextInstall_Default"))); -// workaround for C++ exception large memory allocation -void _Unwind_SetEnableExceptionFdeSorting(unsigned char enable); - -static IRAM_ATTR void _Unwind_SetNoFunctionContextInstall_Default(unsigned char enable __attribute__((unused))) -{ - (void)0; -} -#endif // CONFIG_COMPILER_CXX_EXCEPTIONS - static const char* TAG = "cpu_start"; -/** - * This function overwrites a the same function of libsupc++ (part of libstdc++). - * Consequently, libsupc++ will then follow our configured exception emergency pool size. - * - * It will be called even with -fno-exception for user code since the stdlib still uses exceptions. - */ -size_t __cxx_eh_arena_size_get(void) -{ -#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS - return CONFIG_COMPILER_CXX_EXCEPTIONS_EMG_POOL_SIZE; -#else - return 0; -#endif -} /** * Xtensa gcc is configured to emit a .ctors section, RISC-V gcc is configured with --enable-initfini-array @@ -210,9 +108,10 @@ static void do_global_ctors(void) * linker. The functions are sorted by their priority value. * The sequence of the init function calls (sorted by priority) is documented in * system_init_fn.txt file. + * @param stage_num Stage number of the init function call (0, 1). */ __attribute__((no_sanitize_undefined)) /* TODO: IDF-8133 */ -static void do_system_init_fn(void) +static void do_system_init_fn(uint32_t stage_num) { extern esp_system_init_fn_t _esp_system_init_fn_array_start; extern esp_system_init_fn_t _esp_system_init_fn_array_end; @@ -221,11 +120,12 @@ static void do_system_init_fn(void) int core_id = esp_cpu_get_core_id(); for (p = &_esp_system_init_fn_array_start; p < &_esp_system_init_fn_array_end; ++p) { - if (p->cores & BIT(core_id)) { - ESP_LOGD(TAG, "calling init function: %p on core: %d", p->fn, core_id); + if (p->stage == stage_num && (p->cores & BIT(core_id)) != 0) { + // During core init, stdout is not initialized yet, so use early logging. + ESP_EARLY_LOGD(TAG, "calling init function: %p on core: %d", p->fn, core_id); esp_err_t err = (*(p->fn))(); if (err != ESP_OK) { - ESP_LOGE(TAG, "init function %p has failed (0x%x), aborting", p->fn, err); + ESP_EARLY_LOGE(TAG, "init function %p has failed (0x%x), aborting", p->fn, err); abort(); } } @@ -249,7 +149,7 @@ static void esp_startup_start_app_other_cores_default(void) */ static void IRAM_ATTR start_cpu_other_cores_default(void) { - do_system_init_fn(); + do_system_init_fn(ESP_SYSTEM_INIT_STAGE_SECONDARY); while (!s_system_full_inited) { esp_rom_delay_us(100); @@ -261,129 +161,7 @@ static void IRAM_ATTR start_cpu_other_cores_default(void) static void 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(); - - // When apptrace module is enabled, there will be SEGGER_SYSVIEW calls in the newlib init. - // SEGGER_SYSVIEW relies on apptrace module - // apptrace module uses esp_timer_get_time to determine timeout conditions. - // esp_timer early initialization is required for esp_timer_get_time to work. - esp_timer_early_init(); - esp_newlib_init(); - -#if CONFIG_SPIRAM_BOOT_INIT && (CONFIG_SPIRAM_USE_CAPS_ALLOC || CONFIG_SPIRAM_USE_MALLOC) - if (esp_psram_is_initialized()) { - esp_err_t r=esp_psram_extram_add_to_heap_allocator(); - 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_ESP_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 - - esp_newlib_time_init(); - -#if CONFIG_VFS_SUPPORT_IO - // VFS console register. - esp_err_t vfs_err = esp_vfs_console_register(); - assert(vfs_err == ESP_OK && "Failed to register vfs console"); -#endif - -#if defined(CONFIG_VFS_SUPPORT_IO) && !defined(CONFIG_ESP_CONSOLE_NONE) - esp_newlib_init_global_stdio(ESP_VFS_DEV_CONSOLE); -#else - esp_newlib_init_global_stdio(NULL); -#endif - - esp_err_t err __attribute__((unused)); - - err = esp_pthread_init(); - assert(err == ESP_OK && "Failed to init pthread module!"); - -#if !CONFIG_APP_BUILD_TYPE_PURE_RAM_APP -#if CONFIG_SPI_FLASH_ROM_IMPL - spi_flash_rom_impl_init(); -#endif - - esp_flash_app_init(); - esp_err_t flash_ret = esp_flash_init_default_chip(); - assert(flash_ret == ESP_OK); - (void)flash_ret; -#if CONFIG_SPI_FLASH_BROWNOUT_RESET - spi_flash_needs_reset_check(); -#endif // CONFIG_SPI_FLASH_BROWNOUT_RESET -#endif // !CONFIG_APP_BUILD_TYPE_PURE_RAM_APP - -#ifdef CONFIG_EFUSE_VIRTUAL - ESP_LOGW(TAG, "eFuse virtual mode is enabled. If Secure boot or Flash encryption is enabled then it does not provide any security. FOR TESTING ONLY!"); -#ifdef CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH - 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_virtual_mode_in_flash(efuse_partition->address, efuse_partition->size); - } -#endif -#endif - -#ifdef CONFIG_SECURE_FLASH_ENC_ENABLED - esp_flash_encryption_init_checks(); -#endif - -#if defined(CONFIG_SECURE_BOOT) || defined(CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT) - // Note: in some configs this may read flash, so placed after flash init - esp_secure_boot_init_checks(); -#endif - -#if SOC_EFUSE_ECDSA_USE_HARDWARE_K - if (esp_efuse_find_purpose(ESP_EFUSE_KEY_PURPOSE_ECDSA_KEY, NULL)) { - // ECDSA key purpose block is present and hence permanently enable - // the hardware TRNG supplied k mode (most secure mode) - err = esp_efuse_write_field_bit(ESP_EFUSE_ECDSA_FORCE_USE_HARDWARE_K); - assert(err == ESP_OK && "Failed to enable ECDSA hardware k mode"); - } -#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 - -#ifdef ROM_LOG_MODE - esp_efuse_set_rom_log_scheme(ROM_LOG_MODE); -#endif - -#if CONFIG_ESP_XT_WDT - esp_xt_wdt_config_t cfg = { - .timeout = CONFIG_ESP_XT_WDT_TIMEOUT, - .auto_backup_clk_enable = CONFIG_ESP_XT_WDT_BACKUP_CLK_ENABLE, - }; - err = esp_xt_wdt_init(&cfg); - assert(err == ESP_OK && "Failed to init xtwdt"); -#endif + do_system_init_fn(ESP_SYSTEM_INIT_STAGE_CORE); } static void do_secondary_init(void) @@ -397,7 +175,7 @@ static void do_secondary_init(void) // 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(); + do_system_init_fn(ESP_SYSTEM_INIT_STAGE_SECONDARY); #if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE // Wait for all cores to finish secondary init. @@ -415,41 +193,6 @@ static void do_secondary_init(void) static void start_cpu0_default(void) { - - ESP_EARLY_LOGI(TAG, "Pro cpu start user code"); - int cpu_freq = esp_clk_cpu_freq(); - ESP_EARLY_LOGI(TAG, "cpu freq: %d Hz", cpu_freq); - -#ifdef WITH_APP_IMAGE_INFO - // Display information about the current running image. - if (LOG_LOCAL_LEVEL >= ESP_LOG_INFO) { - const esp_app_desc_t *app_desc = esp_app_get_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_app_get_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, "Min chip rev: v%d.%d", CONFIG_ESP_REV_MIN_FULL / 100, CONFIG_ESP_REV_MIN_FULL % 100); - ESP_EARLY_LOGI(TAG, "Max chip rev: v%d.%d %s",CONFIG_ESP_REV_MAX_FULL / 100, CONFIG_ESP_REV_MAX_FULL % 100, - efuse_hal_get_disable_wafer_version_major() ? "(constraint ignored)" : ""); - unsigned revision = efuse_hal_chip_revision(); - ESP_EARLY_LOGI(TAG, "Chip rev: v%d.%d", revision / 100, revision % 100); - } -#endif - // Initialize core components and services. do_core_init(); @@ -460,14 +203,6 @@ static void start_cpu0_default(void) // 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 = RWDT_HAL_CONTEXT_DEFAULT(); - 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 @@ -475,35 +210,3 @@ static void start_cpu0_default(void) esp_startup_start_app(); while (1); } - -ESP_SYSTEM_INIT_FN(init_components0, BIT(0), 200) -{ -#if CONFIG_ESP_DEBUG_STUBS_ENABLE - esp_dbg_stubs_init(); -#endif - -#if defined(CONFIG_PM_ENABLE) - esp_pm_impl_init(); -#endif - -#if CONFIG_ESP_COREDUMP_ENABLE - esp_core_dump_init(); -#endif - -#if SOC_APB_BACKUP_DMA - esp_apb_backup_dma_lock_init(); -#endif - -#if CONFIG_SW_COEXIST_ENABLE || CONFIG_EXTERNAL_COEX_ENABLE - esp_coex_adapter_register(&g_coex_adapter_funcs); - coex_pre_init(); -#endif - -#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS - ESP_EARLY_LOGD(TAG, "Setting C++ exception workarounds."); - _Unwind_SetNoFunctionContextInstall(1); - _Unwind_SetEnableExceptionFdeSorting(0); -#endif // CONFIG_COMPILER_CXX_EXCEPTIONS - - return ESP_OK; -} diff --git a/components/esp_system/startup_funcs.c b/components/esp_system/startup_funcs.c new file mode 100644 index 0000000000..8997ab6634 --- /dev/null +++ b/components/esp_system/startup_funcs.c @@ -0,0 +1,386 @@ +/* + * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include "sdkconfig.h" +#include "esp_attr.h" +#include "esp_err.h" +#include "esp_check.h" +#include "esp_system.h" +#include "esp_log.h" +#include "esp_heap_caps_init.h" +#include "spi_flash_mmap.h" +#include "esp_flash_internal.h" +#include "esp_newlib.h" +#include "esp_timer.h" +#include "esp_efuse.h" +#include "esp_efuse_table.h" +#include "esp_flash_encrypt.h" +#include "esp_partition.h" +#include "esp_secure_boot.h" +#include "esp_xt_wdt.h" +#include "esp_cpu.h" +#include "esp_private/startup_internal.h" +#include "soc/soc_caps.h" +#include "hal/wdt_hal.h" +#include "hal/uart_types.h" +#include "hal/uart_ll.h" +#include "hal/efuse_hal.h" + +#if CONFIG_SW_COEXIST_ENABLE || CONFIG_EXTERNAL_COEX_ENABLE +#include "private/esp_coexist_internal.h" +#endif + +#if __has_include("esp_app_desc.h") +#define WITH_APP_IMAGE_INFO +#include "esp_app_desc.h" +#endif + +#if CONFIG_ESP_COREDUMP_ENABLE +#include "esp_core_dump.h" +#endif + +#include "esp_private/dbg_stubs.h" + +#if CONFIG_PM_ENABLE +#include "esp_pm.h" +#include "esp_private/pm_impl.h" +#endif + +#if CONFIG_VFS_SUPPORT_IO +#include "esp_vfs_dev.h" +#include "esp_vfs_console.h" +#endif + +#include "esp_pthread.h" +#include "esp_private/esp_clk.h" +#include "esp_private/spi_flash_os.h" +#include "esp_private/brownout.h" + +#include "esp_rom_caps.h" +#include "esp_rom_sys.h" + +#if CONFIG_SPIRAM +#include "esp_psram.h" +#include "esp_private/esp_psram_extram.h" +#endif + +// Using the same tag as in startup.c to keep the logs unchanged +static const char* TAG = "cpu_start"; + +// Hook to force the linker to include this file +void esp_system_include_startup_funcs(void) +{ +} + +// [refactor-todo] Most of these init functions should be moved to the respective components. + +ESP_SYSTEM_INIT_FN(init_show_cpu_freq, CORE, BIT(0), 10) +{ + ESP_EARLY_LOGI(TAG, "Pro cpu start user code"); + int cpu_freq = esp_clk_cpu_freq(); + ESP_EARLY_LOGI(TAG, "cpu freq: %d Hz", cpu_freq); + + return ESP_OK; +} + +#ifdef WITH_APP_IMAGE_INFO +ESP_SYSTEM_INIT_FN(init_show_app_info, CORE, BIT(0), 20) +{ + // Display information about the current running image. + if (LOG_LOCAL_LEVEL >= ESP_LOG_INFO) { + const esp_app_desc_t *app_desc = esp_app_get_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_app_get_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, "Min chip rev: v%d.%d", CONFIG_ESP_REV_MIN_FULL / 100, CONFIG_ESP_REV_MIN_FULL % 100); + ESP_EARLY_LOGI(TAG, "Max chip rev: v%d.%d %s", CONFIG_ESP_REV_MAX_FULL / 100, CONFIG_ESP_REV_MAX_FULL % 100, + efuse_hal_get_disable_wafer_version_major() ? "(constraint ignored)" : ""); + unsigned revision = efuse_hal_chip_revision(); + ESP_EARLY_LOGI(TAG, "Chip rev: v%d.%d", revision / 100, revision % 100); + } + return ESP_OK; +} +#endif // WITH_APP_IMAGE_INFO + +ESP_SYSTEM_INIT_FN(init_heap, CORE, BIT(0), 100) +{ + heap_caps_init(); + return ESP_OK; +} + +ESP_SYSTEM_INIT_FN(init_timer, CORE, BIT(0), 101) +{ + esp_timer_early_init(); + return ESP_OK; +} + +ESP_SYSTEM_INIT_FN(init_newlib, CORE, BIT(0), 102) +{ + esp_newlib_init(); + return ESP_OK; +} + +ESP_SYSTEM_INIT_FN(init_psram_heap, CORE, BIT(0), 103) +{ +#if CONFIG_SPIRAM_BOOT_INIT && (CONFIG_SPIRAM_USE_CAPS_ALLOC || CONFIG_SPIRAM_USE_MALLOC) + if (esp_psram_is_initialized()) { + esp_err_t r = esp_psram_extram_add_to_heap_allocator(); + 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 + return ESP_OK; +} + +#if CONFIG_ESP_BROWNOUT_DET +ESP_SYSTEM_INIT_FN(init_brownout, CORE, BIT(0), 104) +{ + // [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(); + return ESP_OK; +} +#endif + +ESP_SYSTEM_INIT_FN(init_newlib_time, CORE, BIT(0), 105) +{ + esp_newlib_time_init(); + return ESP_OK; +} + +#if CONFIG_VFS_SUPPORT_IO +ESP_SYSTEM_INIT_FN(init_vfs_console, CORE, BIT(0), 110) +{ + // VFS console register. + return esp_vfs_console_register(); +} +#endif // CONFIG_VFS_SUPPORT_IO + +ESP_SYSTEM_INIT_FN(init_newlib_stdio, CORE, BIT(0), 115) +{ +#if defined(CONFIG_VFS_SUPPORT_IO) && !defined(CONFIG_ESP_CONSOLE_NONE) + esp_newlib_init_global_stdio(ESP_VFS_DEV_CONSOLE); +#else + esp_newlib_init_global_stdio(NULL); +#endif + return ESP_OK; +} + +ESP_SYSTEM_INIT_FN(init_pthread, CORE, BIT(0), 120) +{ + return esp_pthread_init(); +} + +#if !CONFIG_APP_BUILD_TYPE_PURE_RAM_APP +ESP_SYSTEM_INIT_FN(init_flash, CORE, BIT(0), 130) +{ +#if CONFIG_SPI_FLASH_ROM_IMPL + spi_flash_rom_impl_init(); +#endif + + esp_flash_app_init(); + esp_err_t flash_ret = esp_flash_init_default_chip(); + assert(flash_ret == ESP_OK); + (void)flash_ret; +#if CONFIG_SPI_FLASH_BROWNOUT_RESET + spi_flash_needs_reset_check(); +#endif // CONFIG_SPI_FLASH_BROWNOUT_RESET + return ESP_OK; +} +#endif // !CONFIG_APP_BUILD_TYPE_PURE_RAM_APP + +#ifdef CONFIG_EFUSE_VIRTUAL +ESP_SYSTEM_INIT_FN(init_virtual_efuse, CORE, BIT(0), 140) +{ + ESP_LOGW(TAG, "eFuse virtual mode is enabled. If Secure boot or Flash encryption is enabled then it does not provide any security. FOR TESTING ONLY!"); +#ifdef CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH + 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_virtual_mode_in_flash(efuse_partition->address, efuse_partition->size); + } +#endif + return ESP_OK; +} +#endif // CONFIG_EFUSE_VIRTUAL + +ESP_SYSTEM_INIT_FN(init_secure, CORE, BIT(0), 150) +{ +#ifdef CONFIG_SECURE_FLASH_ENC_ENABLED + esp_flash_encryption_init_checks(); +#endif + +#if defined(CONFIG_SECURE_BOOT) || defined(CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT) + // Note: in some configs this may read flash, so placed after flash init + esp_secure_boot_init_checks(); +#endif + +#if SOC_EFUSE_ECDSA_USE_HARDWARE_K + if (esp_efuse_find_purpose(ESP_EFUSE_KEY_PURPOSE_ECDSA_KEY, NULL)) { + // ECDSA key purpose block is present and hence permanently enable + // the hardware TRNG supplied k mode (most secure mode) + ESP_RETURN_ON_ERROR(esp_efuse_write_field_bit(ESP_EFUSE_ECDSA_FORCE_USE_HARDWARE_K), TAG, "Failed to enable hardware k mode"); + } +#endif + +#if CONFIG_SECURE_DISABLE_ROM_DL_MODE + ESP_RETURN_ON_ERROR(esp_efuse_disable_rom_download_mode(), TAG, "Failed to disable ROM download mode"); +#endif + +#if CONFIG_SECURE_ENABLE_SECURE_ROM_DL_MODE + ESP_RETURN_ON_ERROR(esp_efuse_enable_rom_secure_download_mode(), TAG, "Failed to enable Secure Download mode"); +#endif + +#if CONFIG_ESP32_DISABLE_BASIC_ROM_CONSOLE + esp_efuse_disable_basic_rom_console(); +#endif + return ESP_OK; +} + +// Set efuse ROM_LOG_MODE on first boot +// +// For CONFIG_BOOT_ROM_LOG_ALWAYS_ON (default) or undefined (ESP32), leave +// ROM_LOG_MODE undefined (no need to call this function during startup) +#if CONFIG_BOOT_ROM_LOG_ALWAYS_OFF +#define ROM_LOG_MODE ESP_EFUSE_ROM_LOG_ALWAYS_OFF +#elif CONFIG_BOOT_ROM_LOG_ON_GPIO_LOW +#define ROM_LOG_MODE ESP_EFUSE_ROM_LOG_ON_GPIO_LOW +#elif CONFIG_BOOT_ROM_LOG_ON_GPIO_HIGH +#define ROM_LOG_MODE ESP_EFUSE_ROM_LOG_ON_GPIO_HIGH +#endif + +#ifdef ROM_LOG_MODE +ESP_SYSTEM_INIT_FN(init_rom_log, CORE, BIT(0), 160) +{ + esp_err_t err = esp_efuse_set_rom_log_scheme(ROM_LOG_MODE); + if (err == ESP_ERR_NOT_SUPPORTED) { + err = ESP_OK; + } + ESP_RETURN_ON_ERROR(err, TAG, "Failed to set ROM log scheme"); + return ESP_OK; +} +#endif // ROM_LOG_MODE + +#if CONFIG_ESP_XT_WDT +ESP_SYSTEM_INIT_FN(init_xt_wdt, CORE, BIT(0), 170) +{ + esp_xt_wdt_config_t cfg = { + .timeout = CONFIG_ESP_XT_WDT_TIMEOUT, + .auto_backup_clk_enable = CONFIG_ESP_XT_WDT_BACKUP_CLK_ENABLE, + }; + return esp_xt_wdt_init(&cfg); +} +#endif // CONFIG_ESP_XT_WDT + +#if CONFIG_ESP_DEBUG_STUBS_ENABLE +ESP_SYSTEM_INIT_FN(init_dbg_stubs, SECONDARY, BIT(0), 200) +{ + esp_dbg_stubs_init(); + return ESP_OK; +} +#endif // CONFIG_ESP_DEBUG_STUBS_ENABLE + +#if CONFIG_PM_ENABLE +ESP_SYSTEM_INIT_FN(init_pm, SECONDARY, BIT(0), 201) +{ + esp_pm_impl_init(); + return ESP_OK; +} +#endif // CONFIG_PM_ENABLE + +#if CONFIG_ESP_COREDUMP_ENABLE +ESP_SYSTEM_INIT_FN(init_coredump, SECONDARY, BIT(0), 202) +{ + esp_core_dump_init(); + return ESP_OK; +} +#endif // CONFIG_ESP_COREDUMP_ENABLE + +#if SOC_APB_BACKUP_DMA +ESP_SYSTEM_INIT_FN(init_apb_dma, SECONDARY, BIT(0), 203) +{ + extern void esp_apb_backup_dma_lock_init(void); + esp_apb_backup_dma_lock_init(); + return ESP_OK; +} +#endif + +#if CONFIG_SW_COEXIST_ENABLE || CONFIG_EXTERNAL_COEX_ENABLE +ESP_SYSTEM_INIT_FN(init_coexist, SECONDARY, BIT(0), 204) +{ + esp_coex_adapter_register(&g_coex_adapter_funcs); + coex_pre_init(); + return ESP_OK; +} +#endif // CONFIG_SW_COEXIST_ENABLE || CONFIG_EXTERNAL_COEX_ENABLE + +#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS +/** + * This function overwrites a the same function of libsupc++ (part of libstdc++). + * Consequently, libsupc++ will then follow our configured exception emergency pool size. + * + * It will be called even with -fno-exception for user code since the stdlib still uses exceptions. + */ +size_t __cxx_eh_arena_size_get(void) +{ +#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS + return CONFIG_COMPILER_CXX_EXCEPTIONS_EMG_POOL_SIZE; +#else + return 0; +#endif +} + +// workaround for C++ exception crashes +void _Unwind_SetNoFunctionContextInstall(unsigned char enable) __attribute__((weak, alias("_Unwind_SetNoFunctionContextInstall_Default"))); +// workaround for C++ exception large memory allocation +void _Unwind_SetEnableExceptionFdeSorting(unsigned char enable); + +static IRAM_ATTR void _Unwind_SetNoFunctionContextInstall_Default(unsigned char enable __attribute__((unused))) +{ + (void)0; +} + +ESP_SYSTEM_INIT_FN(init_cxx_exceptions, SECONDARY, BIT(0), 205) +{ + ESP_EARLY_LOGD(TAG, "Setting C++ exception workarounds."); + _Unwind_SetNoFunctionContextInstall(1); + _Unwind_SetEnableExceptionFdeSorting(0); + return ESP_OK; +} +#endif // CONFIG_COMPILER_CXX_EXCEPTIONS + +#ifndef CONFIG_BOOTLOADER_WDT_DISABLE_IN_USER_CODE +ESP_SYSTEM_INIT_FN(init_disable_rtc_wdt, SECONDARY, BIT(0), 999) +{ + wdt_hal_context_t rtc_wdt_ctx = RWDT_HAL_CONTEXT_DEFAULT(); + wdt_hal_write_protect_disable(&rtc_wdt_ctx); + wdt_hal_disable(&rtc_wdt_ctx); + wdt_hal_write_protect_enable(&rtc_wdt_ctx); + return ESP_OK; +} +#endif // CONFIG_BOOTLOADER_WDT_DISABLE_IN_USER_CODE diff --git a/components/esp_system/system_init_fn.txt b/components/esp_system/system_init_fn.txt index b336c1c599..260d447ed2 100644 --- a/components/esp_system/system_init_fn.txt +++ b/components/esp_system/system_init_fn.txt @@ -7,35 +7,86 @@ # # Entries are ordered by the order of execution (i.e. from low priority values to high ones). # Each line has the following format: -# prio: function_name in path/to/source_file on affinity_expression +# stage: prio: function_name in path/to/source_file on affinity_expression # Where: +# stage: which startup stage the function is executed in (CORE or SECONDARY) # prio: priority value (higher value means function is executed later) # affinity_expression: bit map of cores the function is executed on +########### CORE startup stage ########### +# [refactor-todo]: move init calls into respective components + +# Log some information about the system +CORE: 10: init_show_cpu_freq in components/esp_system/startup_funcs.c on BIT(0) +CORE: 20: init_show_app_info in components/esp_system/startup_funcs.c on BIT(0) + +# 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. +CORE: 100: init_heap in components/esp_system/startup_funcs.c on BIT(0) + +# When apptrace module is enabled, there will be SEGGER_SYSVIEW calls in the newlib init. +# SEGGER_SYSVIEW relies on apptrace module +# apptrace module uses esp_timer_get_time to determine timeout conditions. +# esp_timer early initialization is required for esp_timer_get_time to work. +CORE: 101: init_timer in components/esp_system/startup_funcs.c on BIT(0) + +CORE: 102: init_newlib in components/esp_system/startup_funcs.c on BIT(0) +CORE: 103: init_psram_heap in components/esp_system/startup_funcs.c on BIT(0) +CORE: 104: init_brownout in components/esp_system/startup_funcs.c on BIT(0) +CORE: 105: init_newlib_time in components/esp_system/startup_funcs.c on BIT(0) +CORE: 110: init_vfs_console in components/esp_system/startup_funcs.c on BIT(0) +CORE: 115: init_newlib_stdio in components/esp_system/startup_funcs.c on BIT(0) +CORE: 120: init_pthread in components/esp_system/startup_funcs.c on BIT(0) +CORE: 130: init_flash in components/esp_system/startup_funcs.c on BIT(0) +CORE: 140: init_virtual_efuse in components/esp_system/startup_funcs.c on BIT(0) +CORE: 150: init_secure in components/esp_system/startup_funcs.c on BIT(0) +CORE: 160: init_rom_log in components/esp_system/startup_funcs.c on BIT(0) +CORE: 170: init_xt_wdt in components/esp_system/startup_funcs.c on BIT(0) + + +########### SECONDARY startup stage ########### + # esp_timer has to be initialized early, since it is used by several other components -100: esp_timer_startup_init in components/esp_timer/src/esp_timer.c on CONFIG_ESP_TIMER_ISR_AFFINITY +SECONDARY: 100: esp_timer_startup_init in components/esp_timer/src/esp_timer.c on CONFIG_ESP_TIMER_ISR_AFFINITY # HW stack guard via assist-debug module. -101: esp_hw_stack_guard_init in components/esp_system/hw_stack_guard.c on ESP_SYSTEM_INIT_ALL_CORES +SECONDARY: 101: esp_hw_stack_guard_init in components/esp_system/hw_stack_guard.c on ESP_SYSTEM_INIT_ALL_CORES # esp_sleep doesn't have init dependencies -105: esp_sleep_startup_init in components/esp_hw_support/sleep_gpio.c on BIT(0) -106: sleep_clock_startup_init in components/esp_hw_support/sleep_clock.c on BIT(0) -107: sleep_sys_periph_startup_init in components/esp_hw_support/sleep_system_peripheral.c on BIT(0) +SECONDARY: 105: esp_sleep_startup_init in components/esp_hw_support/sleep_gpio.c on BIT(0) +SECONDARY: 106: sleep_clock_startup_init in components/esp_hw_support/sleep_clock.c on BIT(0) +SECONDARY: 107: sleep_sys_periph_startup_init in components/esp_hw_support/sleep_system_peripheral.c on BIT(0) # app_trace has to be initialized before systemview -115: esp_apptrace_init in components/app_trace/app_trace.c on ESP_SYSTEM_INIT_ALL_CORES -120: sysview_init in components/app_trace/sys_view/esp/SEGGER_RTT_esp.c on BIT(0) +SECONDARY: 115: esp_apptrace_init in components/app_trace/app_trace.c on ESP_SYSTEM_INIT_ALL_CORES +SECONDARY: 120: sysview_init in components/app_trace/sys_view/esp/SEGGER_RTT_esp.c on BIT(0) -# the rest of the components which are initialized from startup.c +# the rest of the components which are initialized from startup_funcs.c # [refactor-todo]: move init calls into respective components -200: init_components0 in components/esp_system/startup.c on BIT(0) +SECONDARY: 200: init_dbg_stubs in components/esp_system/startup_funcs.c on BIT(0) +SECONDARY: 201: init_pm in components/esp_system/startup_funcs.c on BIT(0) +SECONDARY: 202: init_coredump in components/esp_system/startup_funcs.c on BIT(0) +SECONDARY: 203: init_apb_dma in components/esp_system/startup_funcs.c on BIT(0) +SECONDARY: 204: init_coexist in components/esp_system/startup_funcs.c on BIT(0) +SECONDARY: 205: init_cxx_exceptions in components/esp_system/startup_funcs.c on BIT(0) # usb_console needs to create an esp_timer at startup. -# This can be done only after esp_timer initialization, which is now in init_components0. -220: esp_usb_console_init_restart_timer in components/esp_system/port/usb_console.c on BIT(0) +# This can be done only after esp_timer initialization (esp_timer_startup_init). +SECONDARY: 220: esp_usb_console_init_restart_timer in components/esp_system/port/usb_console.c on BIT(0) -# usb_serial_jtag needs to create and acquire a PM clock at startup. -# This makes more sense to be done after esp_pm_impl_init, which is initialized in init_components0. -230: usb_serial_jtag_conn_status_init in components/driver/usb_serial_jtag/usb_serial_jtag_connection_monitor.c on BIT(0) +# usb_serial_jtag needs to create and acquire a PM lock at startup. +# This makes more sense to be done after esp_pm_impl_init (called from init_pm). +SECONDARY: 230: usb_serial_jtag_conn_status_init in components/driver/usb_serial_jtag/usb_serial_jtag_connection_monitor.c on BIT(0) + +# Has to be the last step! +# Now that the application is about to start, disable boot watchdog +SECONDARY: 999: init_disable_rtc_wdt in components/esp_system/startup_funcs.c on BIT(0) + +# DO NOT add new init functions here. Add them to the correct stage above. diff --git a/components/esp_timer/src/esp_timer.c b/components/esp_timer/src/esp_timer.c index 5fffae5770..bc3ab3fca2 100644 --- a/components/esp_timer/src/esp_timer.c +++ b/components/esp_timer/src/esp_timer.c @@ -574,7 +574,7 @@ esp_err_t esp_timer_init(void) return err; } -ESP_SYSTEM_INIT_FN(esp_timer_startup_init, CONFIG_ESP_TIMER_ISR_AFFINITY, 100) +ESP_SYSTEM_INIT_FN(esp_timer_startup_init, SECONDARY, CONFIG_ESP_TIMER_ISR_AFFINITY, 100) { return esp_timer_init(); } From 6046b396acaf6e891f5389fb012d05acb69a7938 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Sat, 25 Nov 2023 02:25:20 +0100 Subject: [PATCH 2/2] fix(esp_timer): avoid signed integer overflow in ESP_SYSTEM_INIT_FN CONFIG_ESP_TIMER_ISR_AFFINITY can be equal to -1, whereas ESP_SYSTEM_INIT_FN takes an uint16_t argument. To avoid overflow, move the choice of init mask into source code and set the value explicitly. --- components/esp_system/system_init_fn.txt | 2 +- components/esp_timer/Kconfig | 6 ------ components/esp_timer/src/esp_timer.c | 13 +++++++++++-- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/components/esp_system/system_init_fn.txt b/components/esp_system/system_init_fn.txt index 260d447ed2..3970de39f0 100644 --- a/components/esp_system/system_init_fn.txt +++ b/components/esp_system/system_init_fn.txt @@ -54,7 +54,7 @@ CORE: 170: init_xt_wdt in components/esp_system/startup_funcs.c on BIT(0) ########### SECONDARY startup stage ########### # esp_timer has to be initialized early, since it is used by several other components -SECONDARY: 100: esp_timer_startup_init in components/esp_timer/src/esp_timer.c on CONFIG_ESP_TIMER_ISR_AFFINITY +SECONDARY: 100: esp_timer_startup_init in components/esp_timer/src/esp_timer.c on ESP_TIMER_INIT_MASK # HW stack guard via assist-debug module. SECONDARY: 101: esp_hw_stack_guard_init in components/esp_system/hw_stack_guard.c on ESP_SYSTEM_INIT_ALL_CORES diff --git a/components/esp_timer/Kconfig b/components/esp_timer/Kconfig index cbce3ae3a8..6cd748fa33 100644 --- a/components/esp_timer/Kconfig +++ b/components/esp_timer/Kconfig @@ -74,12 +74,6 @@ menu "High resolution timer (esp_timer)" depends on !FREERTOS_UNICORE && ESP_TIMER_SHOW_EXPERIMENTAL endchoice - config ESP_TIMER_ISR_AFFINITY - hex - default 0x1 if ESP_TIMER_ISR_AFFINITY_CPU0 - default 0x2 if ESP_TIMER_ISR_AFFINITY_CPU1 - default FREERTOS_NO_AFFINITY if ESP_TIMER_ISR_AFFINITY_NO_AFFINITY - choice ESP_TIMER_ISR_AFFINITY prompt "timer interrupt core affinity" default ESP_TIMER_ISR_AFFINITY_CPU0 diff --git a/components/esp_timer/src/esp_timer.c b/components/esp_timer/src/esp_timer.c index bc3ab3fca2..7440a2c935 100644 --- a/components/esp_timer/src/esp_timer.c +++ b/components/esp_timer/src/esp_timer.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2017-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2017-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -574,7 +574,16 @@ esp_err_t esp_timer_init(void) return err; } -ESP_SYSTEM_INIT_FN(esp_timer_startup_init, SECONDARY, CONFIG_ESP_TIMER_ISR_AFFINITY, 100) +#if CONFIG_ESP_TIMER_ISR_AFFINITY_CPU0 +#define ESP_TIMER_INIT_MASK BIT(0) +#elif CONFIG_ESP_TIMER_ISR_AFFINITY_CPU1 +#define ESP_TIMER_INIT_MASK BIT(1) +#elif CONFIG_ESP_TIMER_ISR_AFFINITY_NO_AFFINITY +#define ESP_TIMER_INIT_MASK ESP_SYSTEM_INIT_ALL_CORES +#endif // CONFIG_ESP_TIMER_ISR_AFFINITY_* + + +ESP_SYSTEM_INIT_FN(esp_timer_startup_init, SECONDARY, ESP_TIMER_INIT_MASK, 100) { return esp_timer_init(); }