diff --git a/.gitlab/ci/pre_check.yml b/.gitlab/ci/pre_check.yml index 4a3dfe3649..7718af3ec3 100644 --- a/.gitlab/ci/pre_check.yml +++ b/.gitlab/ci/pre_check.yml @@ -148,6 +148,15 @@ check_esp_err_to_name: - ./gen_esp_err_to_name.py - git diff --exit-code -- ../components/esp_common/src/esp_err_to_name.c || { echo 'Differences found. Please run gen_esp_err_to_name.py and commit the changes.'; exit 1; } +check_esp_system: + extends: + - .pre_check_base_template + - .rules:build + tags: + - build + script: + - python components/esp_system/check_system_init_priorities.py + scan_tests: extends: - .pre_check_base_template diff --git a/components/app_trace/app_trace.c b/components/app_trace/app_trace.c index 141a62b670..9f5ec743fb 100644 --- a/components/app_trace/app_trace.c +++ b/components/app_trace/app_trace.c @@ -8,6 +8,7 @@ #include "esp_log.h" #include "esp_app_trace.h" #include "esp_app_trace_port.h" +#include "esp_private/startup_internal.h" #ifdef CONFIG_APPTRACE_DEST_UART0 #define ESP_APPTRACE_DEST_UART_NUM 0 @@ -75,6 +76,11 @@ esp_err_t esp_apptrace_init(void) return ESP_OK; } +ESP_SYSTEM_INIT_FN(esp_apptrace_init, ESP_SYSTEM_INIT_ALL_CORES, 115) +{ + return esp_apptrace_init(); +} + void esp_apptrace_down_buffer_config(uint8_t *buf, uint32_t size) { esp_apptrace_channel_t *ch; 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 b4d186f2a9..beb6128970 100644 --- a/components/app_trace/sys_view/esp/SEGGER_RTT_esp.c +++ b/components/app_trace/sys_view/esp/SEGGER_RTT_esp.c @@ -12,6 +12,7 @@ #include "esp_app_trace.h" #include "esp_log.h" +#include "esp_private/startup_internal.h" const static char *TAG = "segger_rtt"; @@ -288,4 +289,17 @@ int SEGGER_RTT_ConfigDownBuffer(unsigned BufferIndex, const char* sName, void* p return 0; } +/*************************** Init hook **************************** + * + * This init function is placed here because this port file will be + * linked whenever SystemView is used. + */ + +ESP_SYSTEM_INIT_FN(sysview_init, BIT(0), 120) +{ + SEGGER_SYSVIEW_Conf(); + return ESP_OK; +} + + /*************************** End of file ****************************/ diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index d40572a170..14e606f3db 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -45,6 +45,7 @@ #include "esp_private/brownout.h" #include "esp_private/sleep_retention.h" #include "esp_private/esp_clk.h" +#include "esp_private/startup_internal.h" #ifdef CONFIG_IDF_TARGET_ESP32 #include "esp32/rom/cache.h" @@ -1395,3 +1396,15 @@ void rtc_sleep_enable_ultra_low(bool enable) { s_ultra_low_enabled = enable; } + +#if CONFIG_ESP_SLEEP_GPIO_RESET_WORKAROUND && !CONFIG_PM_SLP_DISABLE_GPIO +ESP_SYSTEM_INIT_FN(esp_sleep_startup_init, BIT(0), 105) +{ + // Configure to isolate (disable the Input/Output/Pullup/Pulldown + // function of the pin) all GPIO pins in sleep state + esp_sleep_config_gpio_isolate(); + // Enable automatic switching of GPIO configuration + esp_sleep_enable_gpio_switch(true); + return ESP_OK; +} +#endif diff --git a/components/esp_system/check_system_init_priorities.py b/components/esp_system/check_system_init_priorities.py new file mode 100644 index 0000000000..4bb1741c08 --- /dev/null +++ b/components/esp_system/check_system_init_priorities.py @@ -0,0 +1,105 @@ +#!/usr/bin/env python +# +# SPDX-FileCopyrightText: 2022 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. +# It compares the priorities found in .c source files to the contents of system_init_fn.txt +# In case of an inconsistency, the script prints the differences found and returns with a +# non-zero exit code. + +import difflib +import glob +import itertools +import os +import re +import sys +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]+)\)') +STARTUP_ENTRIES_FILE = 'components/esp_system/system_init_fn.txt' + + +class StartupEntry: + def __init__(self, filename: str, func: str, affinity: str, priority: int) -> None: + self.filename = filename + self.func = func + self.affinity = affinity + self.priority = priority + + def __str__(self) -> str: + return f'{self.priority:3d}: {self.func} in {self.filename} on {self.affinity}' + + +def main() -> None: + try: + idf_path = os.environ['IDF_PATH'] + except KeyError: + raise SystemExit('IDF_PATH must be set before running this script') + + has_errors = False + startup_entries = [] # type: typing.List[StartupEntry] + + # + # 1. Iterate over all .c and .cpp source files and find ESP_SYSTEM_INIT_FN definitions + # + source_files_iters = [] + for extension in ('c', 'cpp'): + glob_iter = glob.glob(os.path.join(idf_path, 'components', '**', f'*.{extension}'), recursive=True) + source_files_iters.append(glob_iter) + for filename in itertools.chain(*source_files_iters): + with open(filename, 'r') as f_obj: + file_contents = f_obj.read() + if ESP_SYSTEM_INIT_FN_STR not in file_contents: + continue + count_expected = len(ESP_SYSTEM_INIT_FN_REGEX_SIMPLE.findall(file_contents)) + found = ESP_SYSTEM_INIT_FN_REGEX.findall(file_contents) + if len(found) != count_expected: + print((f'error: In {filename}, found ESP_SYSTEM_INIT_FN {count_expected} time(s), ' + f'but regular expression matched {len(found)} time(s)'), file=sys.stderr) + has_errors = True + + for match in found: + entry = StartupEntry( + filename=os.path.relpath(filename, idf_path), + func=match[0], + affinity=match[1], + priority=int(match[2]) + ) + startup_entries.append(entry) + + # + # 2. Sort the ESP_SYSTEM_INIT_FN functions in C source files by priority + # + startup_entries = list(sorted(startup_entries, key=lambda e: e.priority)) + startup_entries_lines = [str(entry) for entry in startup_entries] + + # + # 3. Load startup entries list from STARTUP_ENTRIES_FILE, removing comments and empty lines + # + startup_entries_expected_lines = [] + with open(os.path.join(idf_path, STARTUP_ENTRIES_FILE), 'r') as startup_entries_expected_file: + for line in startup_entries_expected_file: + if line.startswith('#') or len(line.strip()) == 0: + continue + startup_entries_expected_lines.append(line.rstrip()) + + # + # 4. Print the list of differences, if any + # + diff_lines = list(difflib.unified_diff(startup_entries_expected_lines, startup_entries_lines, lineterm='')) + if len(diff_lines) > 0: + print(('error: startup order doesn\'t match the reference file. ' + f'please update {STARTUP_ENTRIES_FILE} to match the actual startup order:'), file=sys.stderr) + for line in diff_lines: + print(f'{line}', file=sys.stderr) + has_errors = True + + if has_errors: + raise SystemExit(1) + + +if __name__ == '__main__': + main() diff --git a/components/esp_system/include/esp_private/startup_internal.h b/components/esp_system/include/esp_private/startup_internal.h index 3e59429c2a..da39b4b1fa 100644 --- a/components/esp_system/include/esp_private/startup_internal.h +++ b/components/esp_system/include/esp_private/startup_internal.h @@ -7,6 +7,8 @@ #pragma once #include "esp_attr.h" +#include "esp_err.h" +#include "esp_bit_defs.h" #include "soc/soc_caps.h" #include "hal/cpu_hal.h" @@ -36,25 +38,44 @@ extern sys_startup_fn_t const g_startup_fn[1]; void startup_resume_other_cores(void); #endif +/** + * Internal structure describing ESP_SYSTEM_INIT_FN startup functions + */ typedef struct { - void (*fn)(void); - uint32_t cores; + esp_err_t (*fn)(void); /*!< Pointer to the startup function */ + uint32_t cores; /*!< Bit map of cores where the function has to be called */ } esp_system_init_fn_t; -/* - * Declare an component initialization function that will execute on the specified cores (ex. if BIT0 == 1, will execute - * on CORE0, CORE1 if BIT1 and so on). +/** + * @brief Define a system initialization function which will be executed on the specified cores * - * @note Initialization functions should be placed in a compilation unit where at least one other - * symbol is referenced 'meaningfully' in another compilation unit, otherwise this gets discarded during linking. (By - * 'meaningfully' we mean the reference should not itself get optimized out by the compiler/discarded by the linker). + * @param f function name (identifier) + * @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 + * the function will be executed later in the process. + * @param (varargs) optional, additional attributes for the function declaration (such as IRAM_ATTR) + * + * The function defined using this macro must return ESP_OK on success. Any other value will be + * logged and the startup process will abort. + * + * Initialization functions should be placed in a compilation unit where at least one other + * symbol is referenced in another compilation unit. This means that the reference should not itself + * get optimized out by the compiler or discarded by the linker if the related feature is used. + * 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, ...) \ -static void __attribute__((used)) __VA_ARGS__ __esp_system_init_fn_##f(void); \ -static __attribute__((used)) esp_system_init_fn_t _SECTION_ATTR_IMPL(".esp_system_init_fn", f) \ - esp_system_init_fn_##f = { .fn = ( __esp_system_init_fn_##f), .cores = (c) }; \ -static __attribute__((used)) __VA_ARGS__ void __esp_system_init_fn_##f(void) // [refactor-todo] this can be made public API if we allow components to declare init functions, - // instead of calling them explicitly +#define ESP_SYSTEM_INIT_FN(f, 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) }; \ + static esp_err_t __esp_system_init_fn_##f(void) + +#ifdef CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE +#define ESP_SYSTEM_INIT_ALL_CORES BIT(0) +#else +#define ESP_SYSTEM_INIT_ALL_CORES (BIT(SOC_CPU_CORES_NUM) - 1) +#endif extern uint64_t g_startup_time; // Startup time that serves as the point of origin for system time. Should be set by the entry // function in the port layer. May be 0 as well if this is not backed by a persistent counter, in which case diff --git a/components/esp_system/ld/esp32/sections.ld.in b/components/esp_system/ld/esp32/sections.ld.in index 1de48ab1e5..29f581ef8e 100644 --- a/components/esp_system/ld/esp32/sections.ld.in +++ b/components/esp_system/ld/esp32/sections.ld.in @@ -185,10 +185,6 @@ SECTIONS *(.gnu.linkonce.s2.*) *(.jcr) - _esp_system_init_fn_array_start = ABSOLUTE(.); - KEEP (*(SORT(.esp_system_init_fn) SORT(.esp_system_init_fn.*))) - _esp_system_init_fn_array_end = ABSOLUTE(.); - mapping[dram0_data] _data_end = ABSOLUTE(.); @@ -304,6 +300,10 @@ SECTIONS soc_reserved_memory_region_start = ABSOLUTE(.); KEEP (*(.reserved_memory_address)) soc_reserved_memory_region_end = ABSOLUTE(.); + /* System init functions registered via ESP_SYSTEM_INIT_FN */ + _esp_system_init_fn_array_start = ABSOLUTE(.); + KEEP (*(SORT_BY_INIT_PRIORITY(.esp_system_init_fn.*))) + _esp_system_init_fn_array_end = ABSOLUTE(.); _rodata_end = ABSOLUTE(.); /* Literals are also RO data. */ _lit4_start = ABSOLUTE(.); diff --git a/components/esp_system/ld/esp32c2/sections.ld.in b/components/esp_system/ld/esp32c2/sections.ld.in index 6b7b6a7417..66431103de 100644 --- a/components/esp_system/ld/esp32c2/sections.ld.in +++ b/components/esp_system/ld/esp32c2/sections.ld.in @@ -47,10 +47,6 @@ SECTIONS *(.gnu.linkonce.s2.*) *(.jcr) - _esp_system_init_fn_array_start = ABSOLUTE(.); - KEEP (*(SORT(.esp_system_init_fn) SORT(.esp_system_init_fn.*))) - _esp_system_init_fn_array_end = ABSOLUTE(.); - mapping[dram0_data] _data_end = ABSOLUTE(.); @@ -208,6 +204,10 @@ SECTIONS soc_reserved_memory_region_start = ABSOLUTE(.); KEEP (*(.reserved_memory_address)) soc_reserved_memory_region_end = ABSOLUTE(.); + /* System init functions registered via ESP_SYSTEM_INIT_FN */ + _esp_system_init_fn_array_start = ABSOLUTE(.); + KEEP (*(SORT_BY_INIT_PRIORITY(.esp_system_init_fn.*))) + _esp_system_init_fn_array_end = ABSOLUTE(.); _rodata_end = ABSOLUTE(.); /* Literals are also RO data. */ _lit4_start = ABSOLUTE(.); diff --git a/components/esp_system/ld/esp32c3/sections.ld.in b/components/esp_system/ld/esp32c3/sections.ld.in index 8803f0254d..d6670bf759 100644 --- a/components/esp_system/ld/esp32c3/sections.ld.in +++ b/components/esp_system/ld/esp32c3/sections.ld.in @@ -157,10 +157,6 @@ SECTIONS *(.gnu.linkonce.s2.*) *(.jcr) - _esp_system_init_fn_array_start = ABSOLUTE(.); - KEEP (*(SORT(.esp_system_init_fn) SORT(.esp_system_init_fn.*))) - _esp_system_init_fn_array_end = ABSOLUTE(.); - mapping[dram0_data] _data_end = ABSOLUTE(.); @@ -318,6 +314,10 @@ SECTIONS soc_reserved_memory_region_start = ABSOLUTE(.); KEEP (*(.reserved_memory_address)) soc_reserved_memory_region_end = ABSOLUTE(.); + /* System init functions registered via ESP_SYSTEM_INIT_FN */ + _esp_system_init_fn_array_start = ABSOLUTE(.); + KEEP (*(SORT_BY_INIT_PRIORITY(.esp_system_init_fn.*))) + _esp_system_init_fn_array_end = ABSOLUTE(.); _rodata_end = ABSOLUTE(.); /* Literals are also RO data. */ _lit4_start = ABSOLUTE(.); diff --git a/components/esp_system/ld/esp32h2/sections.ld.in b/components/esp_system/ld/esp32h2/sections.ld.in index a49f22e70e..93239b0dec 100644 --- a/components/esp_system/ld/esp32h2/sections.ld.in +++ b/components/esp_system/ld/esp32h2/sections.ld.in @@ -160,10 +160,6 @@ SECTIONS *(.gnu.linkonce.s2.*) *(.jcr) - _esp_system_init_fn_array_start = ABSOLUTE(.); - KEEP (*(SORT(.esp_system_init_fn) SORT(.esp_system_init_fn.*))) - _esp_system_init_fn_array_end = ABSOLUTE(.); - mapping[dram0_data] _data_end = ABSOLUTE(.); @@ -321,6 +317,10 @@ SECTIONS soc_reserved_memory_region_start = ABSOLUTE(.); KEEP (*(.reserved_memory_address)) soc_reserved_memory_region_end = ABSOLUTE(.); + /* System init functions registered via ESP_SYSTEM_INIT_FN */ + _esp_system_init_fn_array_start = ABSOLUTE(.); + KEEP (*(SORT_BY_INIT_PRIORITY(.esp_system_init_fn.*))) + _esp_system_init_fn_array_end = ABSOLUTE(.); _rodata_end = ABSOLUTE(.); /* Literals are also RO data. */ _lit4_start = ABSOLUTE(.); diff --git a/components/esp_system/ld/esp32s2/sections.ld.in b/components/esp_system/ld/esp32s2/sections.ld.in index 4e1ccc83b2..16b9104edd 100644 --- a/components/esp_system/ld/esp32s2/sections.ld.in +++ b/components/esp_system/ld/esp32s2/sections.ld.in @@ -207,10 +207,6 @@ SECTIONS *(.gnu.linkonce.s2.*) *(.jcr) - _esp_system_init_fn_array_start = ABSOLUTE(.); - KEEP (*(SORT(.esp_system_init_fn) SORT(.esp_system_init_fn.*))) - _esp_system_init_fn_array_end = ABSOLUTE(.); - mapping[dram0_data] _data_end = ABSOLUTE(.); @@ -322,6 +318,10 @@ SECTIONS soc_reserved_memory_region_start = ABSOLUTE(.); KEEP (*(.reserved_memory_address)) soc_reserved_memory_region_end = ABSOLUTE(.); + /* System init functions registered via ESP_SYSTEM_INIT_FN */ + _esp_system_init_fn_array_start = ABSOLUTE(.); + KEEP (*(SORT_BY_INIT_PRIORITY(.esp_system_init_fn.*))) + _esp_system_init_fn_array_end = ABSOLUTE(.); _rodata_end = ABSOLUTE(.); /* Literals are also RO data. */ _lit4_start = ABSOLUTE(.); diff --git a/components/esp_system/ld/esp32s3/sections.ld.in b/components/esp_system/ld/esp32s3/sections.ld.in index 5c0d41b1ca..13741b45ef 100644 --- a/components/esp_system/ld/esp32s3/sections.ld.in +++ b/components/esp_system/ld/esp32s3/sections.ld.in @@ -194,10 +194,6 @@ SECTIONS *(.gnu.linkonce.s2.*) *(.jcr) - _esp_system_init_fn_array_start = ABSOLUTE(.); - KEEP (*(SORT(.esp_system_init_fn) SORT(.esp_system_init_fn.*))) - _esp_system_init_fn_array_end = ABSOLUTE(.); - mapping[dram0_data] _data_end = ABSOLUTE(.); @@ -347,6 +343,10 @@ SECTIONS soc_reserved_memory_region_start = ABSOLUTE(.); KEEP (*(.reserved_memory_address)) soc_reserved_memory_region_end = ABSOLUTE(.); + /* System init functions registered via ESP_SYSTEM_INIT_FN */ + _esp_system_init_fn_array_start = ABSOLUTE(.); + KEEP (*(SORT_BY_INIT_PRIORITY(.esp_system_init_fn.*))) + _esp_system_init_fn_array_end = ABSOLUTE(.); _rodata_end = ABSOLUTE(.); /* Literals are also RO data. */ _lit4_start = ABSOLUTE(.); diff --git a/components/esp_system/startup.c b/components/esp_system/startup.c index e1c00d8fcd..98156a3d52 100644 --- a/components/esp_system/startup.c +++ b/components/esp_system/startup.c @@ -30,7 +30,6 @@ #include "esp_efuse.h" #include "esp_flash_encrypt.h" #include "esp_secure_boot.h" -#include "esp_sleep.h" #include "esp_xt_wdt.h" #if __has_include("esp_ota_ops.h") @@ -48,10 +47,6 @@ #include "esp_core_dump.h" #endif -#if CONFIG_APPTRACE_ENABLE -#include "esp_app_trace.h" -#endif - #include "esp_private/dbg_stubs.h" #if CONFIG_PM_ENABLE @@ -179,17 +174,25 @@ static void do_global_ctors(void) #if __riscv for (p = &__init_priority_array_start; p < &__init_priority_array_end; ++p) { - ESP_EARLY_LOGD(TAG, "calling init function: %p", *p); + ESP_LOGD(TAG, "calling init function: %p", *p); (*p)(); } #endif for (p = &__init_array_end - 1; p >= &__init_array_start; --p) { - ESP_EARLY_LOGD(TAG, "calling init function: %p", *p); + ESP_LOGD(TAG, "calling init function: %p", *p); (*p)(); } } +/** + * @brief Call component init functions defined using ESP_SYSTEM_INIT_Fn 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 + * 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. + */ static void do_system_init_fn(void) { extern esp_system_init_fn_t _esp_system_init_fn_array_start; @@ -197,14 +200,20 @@ static void do_system_init_fn(void) esp_system_init_fn_t *p; - for (p = &_esp_system_init_fn_array_end - 1; p >= &_esp_system_init_fn_array_start; --p) { - if (p->cores & BIT(cpu_hal_get_core_id())) { - (*(p->fn))(); + int core_id = cpu_hal_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); + esp_err_t err = (*(p->fn))(); + if (err != ESP_OK) { + ESP_LOGE(TAG, "init function %p has failed (0x%x), aborting", p->fn, err); + abort(); + } } } #if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE - s_system_inited[cpu_hal_get_core_id()] = true; + s_system_inited[core_id] = true; #endif } @@ -216,6 +225,9 @@ static void esp_startup_start_app_other_cores_default(void) } } +/* This function has to be in IRAM, as while it is running on CPU1, CPU0 may do some flash operations + * (e.g. initialize the core dump), which means that cache will be disabled. + */ static void IRAM_ATTR start_cpu_other_cores_default(void) { do_system_init_fn(); @@ -428,26 +440,8 @@ static void start_cpu0_default(void) while (1); } -IRAM_ATTR ESP_SYSTEM_INIT_FN(init_components0, BIT(0)) +ESP_SYSTEM_INIT_FN(init_components0, BIT(0), 200) { - esp_timer_init(); - -#if CONFIG_ESP_SLEEP_GPIO_RESET_WORKAROUND && !CONFIG_PM_SLP_DISABLE_GPIO - // Configure to isolate (disable the Input/Output/Pullup/Pulldown - // function of the pin) all GPIO pins in sleep state - esp_sleep_config_gpio_isolate(); - // Enable automatic switching of GPIO configuration - esp_sleep_enable_gpio_switch(true); -#endif - -#if CONFIG_APPTRACE_ENABLE - esp_err_t err = esp_apptrace_init(); - assert(err == ESP_OK && "Failed to init apptrace module on PRO CPU!"); -#endif -#if CONFIG_APPTRACE_SV_ENABLE - SEGGER_SYSVIEW_Conf(); -#endif - #if CONFIG_ESP_DEBUG_STUBS_ENABLE esp_dbg_stubs_init(); #endif @@ -474,4 +468,6 @@ IRAM_ATTR ESP_SYSTEM_INIT_FN(init_components0, BIT(0)) _Unwind_SetNoFunctionContextInstall(1); _Unwind_SetEnableExceptionFdeSorting(0); #endif // CONFIG_COMPILER_CXX_EXCEPTIONS + + return ESP_OK; } diff --git a/components/esp_system/system_init_fn.txt b/components/esp_system/system_init_fn.txt new file mode 100644 index 0000000000..7f67937c60 --- /dev/null +++ b/components/esp_system/system_init_fn.txt @@ -0,0 +1,28 @@ +# This file documents the expected order of execution of ESP_SYSTEM_INIT_FN functions. +# +# When adding new ESP_SYSTEM_INIT_FN functions or changing init priorities of existing functions, +# keep this file up to date. This is checked in CI. +# When adding new functions or changing the priorities, please read the comments and see if +# they need to be updated to be consistent with the changes you are making. +# +# 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 +# Where: +# prio: priority value (higher value means function is executed later) +# affinity_expression: bit map of cores the function is executed on + + +# 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 BIT(0) + +# esp_sleep doesn't have init dependencies +105: esp_sleep_startup_init in components/esp_hw_support/sleep_modes.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) + +# the rest of the components which are initialized from startup.c +# [refactor-todo]: move init calls into respective components +200: init_components0 in components/esp_system/startup.c on BIT(0) diff --git a/components/esp_timer/src/esp_timer.c b/components/esp_timer/src/esp_timer.c index ff2e6bd322..3ca19f642f 100644 --- a/components/esp_timer/src/esp_timer.c +++ b/components/esp_timer/src/esp_timer.c @@ -460,6 +460,11 @@ out: return ESP_ERR_NO_MEM; } +ESP_SYSTEM_INIT_FN(esp_timer_startup_init, BIT(0), 100) +{ + return esp_timer_init(); +} + esp_err_t esp_timer_deinit(void) { if (!is_initialized()) { diff --git a/docs/en/api-guides/startup.rst b/docs/en/api-guides/startup.rst index af8013e319..26c1340b2e 100644 --- a/docs/en/api-guides/startup.rst +++ b/docs/en/api-guides/startup.rst @@ -142,7 +142,7 @@ The primary system initialization stage includes: - Initialize SPI flash API support. - Call global C++ constructors and any C functions marked with ``__attribute__((constructor))``. -Secondary system initialization allows individual components to be initialized. If a component has an initialization function annotated with the ``ESP_SYSTEM_INIT_FN`` macro, it will be called as part of secondary initialization. +Secondary system initialization allows individual components to be initialized. If a component has an initialization function annotated with the ``ESP_SYSTEM_INIT_FN`` macro, it will be called as part of secondary initialization. Component initialization functions have priorities assigned to them to ensure the desired initialization order. The priorities are documented in :component_file:`esp_system/system_init_fn.txt` and ``ESP_SYSTEM_INIT_FN`` definition in source code are checked against this file. .. _app-main-task: