diff --git a/components/esp_system/CMakeLists.txt b/components/esp_system/CMakeLists.txt index fc4f1397f3a..b5bbfa96635 100644 --- a/components/esp_system/CMakeLists.txt +++ b/components/esp_system/CMakeLists.txt @@ -8,8 +8,18 @@ if(${target} STREQUAL "linux") "port/soc/linux/reset_reason.c" "port/soc/linux/system_internal.c" "port/esp_system_linux.c" + "freertos_hooks.c" + "startup.c" INCLUDE_DIRS "include" PRIV_REQUIRES spi_flash) + + # Add custom ld file (used to place system init functions). + # Mach-O (Apple) does not support linker scripts; section bounds are resolved + # at runtime via getsectiondata() so no -T flag is needed there. + if(NOT CMAKE_SYSTEM_NAME STREQUAL "Darwin") + target_link_options(${COMPONENT_TARGET} INTERFACE "-Wl,-T,${CMAKE_CURRENT_SOURCE_DIR}/ld/linux/sections.ld") + endif() + return() endif() diff --git a/components/esp_system/Kconfig b/components/esp_system/Kconfig index 56165299cd5..6ae836f62c7 100644 --- a/components/esp_system/Kconfig +++ b/components/esp_system/Kconfig @@ -74,6 +74,7 @@ menu "ESP System Settings" config ESP_SYSTEM_SINGLE_CORE_MODE bool + default y if IDF_TARGET_LINUX default n help Only initialize and use the main core. diff --git a/components/esp_system/freertos_hooks.c b/components/esp_system/freertos_hooks.c index f29f5ba6271..49f0a49271d 100644 --- a/components/esp_system/freertos_hooks.c +++ b/components/esp_system/freertos_hooks.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -10,14 +10,14 @@ #include "freertos/FreeRTOS.h" #include "esp_attr.h" #include "esp_freertos_hooks.h" -#include "esp_cpu.h" #include "sdkconfig.h" +#include "esp_cpu.h" #if CONFIG_PM_ENABLE #include "esp_pm.h" #include "esp_private/pm_impl.h" -#endif +#endif // CONFIG_PM_ENABLE //We use just a static array here because it's not expected many components will need //an idle or tick hook. @@ -57,7 +57,6 @@ void esp_vApplicationIdleHook(void) #else esp_cpu_wait_for_intr(); #endif - } esp_err_t esp_register_freertos_idle_hook_for_cpu(esp_freertos_idle_cb_t new_idle_cb, UBaseType_t cpuid) diff --git a/components/esp_system/include/esp_private/startup_internal.h b/components/esp_system/include/esp_private/startup_internal.h index ed1b03e6028..c86a1701860 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-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -69,14 +69,14 @@ typedef struct { * discarded if the related feature is not used. */ #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), \ + static esp_err_t __VA_ARGS__ __esp_sys_init_fn_##f(void); \ + static _SECTION_ATTR_IMPL_GENERIC("esp_sys_init_fn", priority) \ + esp_system_init_fn_t esp_sys_init_fn_##f = { \ + .fn = ( __esp_sys_init_fn_##f), \ .cores = (c), \ .stage = ESP_SYSTEM_INIT_STAGE_##stage_ \ }; \ - static esp_err_t __esp_system_init_fn_##f(void) + static esp_err_t __esp_sys_init_fn_##f(void) #ifdef CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE #define ESP_SYSTEM_INIT_ALL_CORES BIT(0) diff --git a/components/esp_system/ld/esp32/sections.ld.in b/components/esp_system/ld/esp32/sections.ld.in index 62793100e81..f420b9ed9c4 100644 --- a/components/esp_system/ld/esp32/sections.ld.in +++ b/components/esp_system/ld/esp32/sections.ld.in @@ -368,9 +368,9 @@ SECTIONS soc_reserved_memory_region_end = ABSOLUTE(.); /* System init functions registered via ESP_SYSTEM_INIT_FN */ - ALIGNED_SYMBOL(4, _esp_system_init_fn_array_start) - KEEP (*(SORT_BY_INIT_PRIORITY(.esp_system_init_fn.*))) - _esp_system_init_fn_array_end = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _esp_sys_init_fn_start) + KEEP (*(SORT_BY_INIT_PRIORITY(.esp_sys_init_fn.*))) + _esp_sys_init_fn_end = ABSOLUTE(.); _rodata_end = ABSOLUTE(.); diff --git a/components/esp_system/ld/esp32s2/sections.ld.in b/components/esp_system/ld/esp32s2/sections.ld.in index 158df7fb8a2..0f67740208b 100644 --- a/components/esp_system/ld/esp32s2/sections.ld.in +++ b/components/esp_system/ld/esp32s2/sections.ld.in @@ -372,9 +372,9 @@ SECTIONS soc_reserved_memory_region_end = ABSOLUTE(.); /* System init functions registered via ESP_SYSTEM_INIT_FN */ - ALIGNED_SYMBOL(4, _esp_system_init_fn_array_start) - KEEP (*(SORT_BY_INIT_PRIORITY(.esp_system_init_fn.*))) - _esp_system_init_fn_array_end = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _esp_sys_init_fn_start) + KEEP (*(SORT_BY_INIT_PRIORITY(.esp_sys_init_fn.*))) + _esp_sys_init_fn_end = ABSOLUTE(.); _rodata_end = ABSOLUTE(.); diff --git a/components/esp_system/ld/esp32s3/sections.ld.in b/components/esp_system/ld/esp32s3/sections.ld.in index b7facdb8c5e..ab323eee536 100644 --- a/components/esp_system/ld/esp32s3/sections.ld.in +++ b/components/esp_system/ld/esp32s3/sections.ld.in @@ -381,9 +381,9 @@ SECTIONS soc_reserved_memory_region_end = ABSOLUTE(.); /* System init functions registered via ESP_SYSTEM_INIT_FN */ - ALIGNED_SYMBOL(4, _esp_system_init_fn_array_start) - KEEP (*(SORT_BY_INIT_PRIORITY(.esp_system_init_fn.*))) - _esp_system_init_fn_array_end = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _esp_sys_init_fn_start) + KEEP (*(SORT_BY_INIT_PRIORITY(.esp_sys_init_fn.*))) + _esp_sys_init_fn_end = ABSOLUTE(.); _rodata_end = ABSOLUTE(.); diff --git a/components/esp_system/ld/ld.flash.sections b/components/esp_system/ld/ld.flash.sections index 16ef50b63c3..8d06bde52ab 100644 --- a/components/esp_system/ld/ld.flash.sections +++ b/components/esp_system/ld/ld.flash.sections @@ -135,9 +135,9 @@ soc_reserved_memory_region_end = ABSOLUTE(.); /* System init functions registered via ESP_SYSTEM_INIT_FN */ - ALIGNED_SYMBOL(4, _esp_system_init_fn_array_start) - KEEP (*(SORT_BY_INIT_PRIORITY(.esp_system_init_fn.*))) - _esp_system_init_fn_array_end = ABSOLUTE(.); + ALIGNED_SYMBOL(4, _esp_sys_init_fn_start) + KEEP (*(SORT_BY_INIT_PRIORITY(.esp_sys_init_fn.*))) + _esp_sys_init_fn_end = ABSOLUTE(.); _rodata_end = ABSOLUTE(.); . = ALIGN(ALIGNOF(SECTION_AFTER_FLASH_RODATA)); diff --git a/components/esp_system/ld/linux/sections.ld b/components/esp_system/ld/linux/sections.ld new file mode 100644 index 00000000000..512d72e9f67 --- /dev/null +++ b/components/esp_system/ld/linux/sections.ld @@ -0,0 +1,15 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +SECTIONS +{ + .esp_sys_init_fn : + { + PROVIDE(_esp_sys_init_fn_start = .); + KEEP(*(SORT(.esp_sys_init_fn*))) + PROVIDE(_esp_sys_init_fn_end = .); + } +} +INSERT AFTER .data; diff --git a/components/esp_system/startup.c b/components/esp_system/startup.c index d0887f02e7b..91ba435c431 100644 --- a/components/esp_system/startup.c +++ b/components/esp_system/startup.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -34,14 +34,41 @@ uint64_t g_startup_time = 0; extern void esp_startup_start_app(void); // Entry point for core 0 from hardware init (port layer) +#if defined(__APPLE__) && defined(__MACH__) +static void start_cpu0_default(void); +__attribute__((weak, noreturn)) void start_cpu0(void) +{ + start_cpu0_default(); + __builtin_unreachable(); +} +#else void start_cpu0(void) __attribute__((weak, alias("start_cpu0_default"))) __attribute__((noreturn)); +#endif #if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE // Entry point for core [1..X] from hardware init (port layer) +#if defined(__APPLE__) && defined(__MACH__) +static void start_cpu_other_cores_default(void); +__attribute__((weak, noreturn)) void start_cpu_other_cores(void) +{ + start_cpu_other_cores_default(); + __builtin_unreachable(); +} +#else void start_cpu_other_cores(void) __attribute__((weak, alias("start_cpu_other_cores_default"))) __attribute__((noreturn)); +#endif // App entry point for core [1..X] +#if defined(__APPLE__) && defined(__MACH__) +static void esp_startup_start_app_other_cores_default(void); +__attribute__((weak, noreturn)) void esp_startup_start_app_other_cores(void) +{ + esp_startup_start_app_other_cores_default(); + __builtin_unreachable(); +} +#else void esp_startup_start_app_other_cores(void) __attribute__((weak, alias("esp_startup_start_app_other_cores_default"))) __attribute__((noreturn)); +#endif static volatile bool s_system_inited[SOC_CPU_CORES_NUM] = { false }; @@ -79,10 +106,14 @@ static void __do_global_ctors_1(void) } #endif // CONFIG_COMPILER_CXX_EXCEPTIONS +/* declare the start and stop symbols surrounding the array of init functions + * registered by calling the system init function macros */ +_SECTION_ATTR_SYMBOL_DECL_GENERIC(esp_system_init_fn_t, esp_sys_init_fn) + /** - * @brief Call component init functions defined using ESP_SYSTEM_INIT_Fn macros. + * @brief Call component init functions defined using the system init function macros. * The esp_system_init_fn_t structures describing these functions are collected into - * an array [_esp_system_init_fn_array_start, _esp_system_init_fn_array_end) by the + * an array [_esp_sys_init_fn_start, _esp_sys_init_fn_end) by the * 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. @@ -91,13 +122,10 @@ static void __do_global_ctors_1(void) __attribute__((no_sanitize_undefined)) /* TODO: IDF-8133 */ 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; - - esp_system_init_fn_t *p; + const esp_system_init_fn_t *p; int core_id = esp_cpu_get_core_id(); - for (p = &_esp_system_init_fn_array_start; p < &_esp_system_init_fn_array_end; ++p) { + for (p = _SECTION_START(esp_sys_init_fn); p < _SECTION_END(esp_sys_init_fn); ++p) { 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); @@ -171,7 +199,6 @@ static void do_secondary_init(void) static void start_cpu0_default(void) { - extern void __libc_init_array(void); // Initialize core components and services. // Operations that needs the cache to be disabled have to be done here. do_core_init(); @@ -180,7 +207,10 @@ static void start_cpu0_default(void) #ifdef CONFIG_COMPILER_CXX_EXCEPTIONS __do_global_ctors_1(); #endif +#if !CONFIG_IDF_TARGET_LINUX + extern void __libc_init_array(void); __libc_init_array(); +#endif // !CONFIG_IDF_TARGET_LINUX /* ----------------------------------Separator----------------------------- * After this stage, other CPU start running with the cache, however the scheduler (and ipc service) is not available.