mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-08 04:02:27 +00:00
esp_system: add a script to check the startup priorities
This commit is contained in:
@@ -148,6 +148,15 @@ check_esp_err_to_name:
|
|||||||
- ./gen_esp_err_to_name.py
|
- ./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; }
|
- 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:
|
scan_tests:
|
||||||
extends:
|
extends:
|
||||||
- .pre_check_base_template
|
- .pre_check_base_template
|
||||||
|
105
components/esp_system/check_system_init_priorities.py
Normal file
105
components/esp_system/check_system_init_priorities.py
Normal file
@@ -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()
|
18
components/esp_system/system_init_fn.txt
Normal file
18
components/esp_system/system_init_fn.txt
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# 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
|
||||||
|
|
||||||
|
|
||||||
|
# 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)
|
@@ -142,7 +142,7 @@ The primary system initialization stage includes:
|
|||||||
- Initialize SPI flash API support.
|
- Initialize SPI flash API support.
|
||||||
- Call global C++ constructors and any C functions marked with ``__attribute__((constructor))``.
|
- 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:
|
.. _app-main-task:
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user