diff --git a/components/soc/esp32/include/soc/Kconfig.soc_caps.in b/components/soc/esp32/include/soc/Kconfig.soc_caps.in index 8dcc2363e1..7517216c38 100644 --- a/components/soc/esp32/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32/include/soc/Kconfig.soc_caps.in @@ -3,18 +3,6 @@ # using gen_soc_caps_kconfig.py, do not edit manually ##################################################### -config SOC_BROWNOUT_RESET_SUPPORTED - string - default "Not determined" - -config SOC_TWAI_BRP_DIV_SUPPORTED - string - default "Not determined" - -config SOC_DPORT_WORKAROUND - string - default "Not determined" - config SOC_CAPS_ECO_VER_MAX int default 301 @@ -279,6 +267,10 @@ config SOC_ADC_SHARED_POWER bool default y +config SOC_BROWNOUT_RESET_SUPPORTED + bool + default y + config SOC_SHARED_IDCACHE_SUPPORTED bool default y @@ -312,8 +304,8 @@ config SOC_CPU_WATCHPOINTS_NUM default 2 config SOC_CPU_WATCHPOINT_MAX_REGION_SIZE - int - default 64 + hex + default 0x40 config SOC_DAC_CHAN_NUM int @@ -836,8 +828,8 @@ config SOC_MPI_MEM_BLOCKS_NUM default 4 config SOC_MPI_OPERATIONS_NUM - bool - default y + int + default 1 config SOC_RSA_MAX_BIT_LEN int @@ -860,8 +852,8 @@ config SOC_SECURE_BOOT_V1 default y config SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS - bool - default y + int + default 1 config SOC_FLASH_ENCRYPTED_XTS_AES_BLOCK_MAX int diff --git a/components/soc/esp32/include/soc/soc_caps.h b/components/soc/esp32/include/soc/soc_caps.h index 608223aefc..199b940414 100644 --- a/components/soc/esp32/include/soc/soc_caps.h +++ b/components/soc/esp32/include/soc/soc_caps.h @@ -1,6 +1,6 @@ /* - * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -54,9 +54,9 @@ // Define warning strings here for ECO-ed features to show error when they are used without being // defined correctly -#define SOC_BROWNOUT_RESET_SUPPORTED "Not determined" -#define SOC_TWAI_BRP_DIV_SUPPORTED "Not determined" -#define SOC_DPORT_WORKAROUND "Not determined" +#define SOC_BROWNOUT_RESET_SUPPORTED "Not determined" // [gen_soc_caps:ignore] +#define SOC_TWAI_BRP_DIV_SUPPORTED "Not determined" // [gen_soc_caps:ignore] +#define SOC_DPORT_WORKAROUND "Not determined" // [gen_soc_caps:ignore] #endif /*-------------------------- COMMON CAPS ---------------------------------------*/ @@ -107,7 +107,7 @@ #define SOC_PM_SUPPORTED 1 #if SOC_CAPS_ECO_VER < 200 -#define SOC_DPORT_WORKAROUND 1 +#define SOC_DPORT_WORKAROUND 1 // [gen_soc_caps:ignore] #endif // SOC_CAPS_ECO_VER < 200 #define SOC_DPORT_WORKAROUND_DIS_INTERRUPT_LVL (5U) @@ -162,7 +162,7 @@ #define SOC_CPU_BREAKPOINTS_NUM 2 #define SOC_CPU_WATCHPOINTS_NUM 2 -#define SOC_CPU_WATCHPOINT_MAX_REGION_SIZE 64 // bytes +#define SOC_CPU_WATCHPOINT_MAX_REGION_SIZE 0x40 // bytes /*-------------------------- DAC CAPS ----------------------------------------*/ #define SOC_DAC_CHAN_NUM 2 @@ -386,7 +386,7 @@ /*--------------------------- MPI CAPS ---------------------------------------*/ #define SOC_MPI_MEM_BLOCKS_NUM (4) -#define SOC_MPI_OPERATIONS_NUM (1) +#define SOC_MPI_OPERATIONS_NUM (1U) /*--------------------------- RSA CAPS ---------------------------------------*/ #define SOC_RSA_MAX_BIT_LEN (4096) @@ -403,7 +403,7 @@ * Hence, for now we are handling this special capability in bootloader "security" configuration itself. */ #define SOC_SECURE_BOOT_V1 1 -#define SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS 1 +#define SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS (1U) /*-------------------------- Flash Encryption CAPS----------------------------*/ #define SOC_FLASH_ENCRYPTED_XTS_AES_BLOCK_MAX (32) diff --git a/components/soc/esp32c61/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c61/include/soc/Kconfig.soc_caps.in index 7f4eb028f9..b231b665ed 100644 --- a/components/soc/esp32c61/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c61/include/soc/Kconfig.soc_caps.in @@ -204,8 +204,8 @@ config SOC_ADC_DMA_SUPPORTED default y config SOC_ADC_PERIPH_NUM - bool - default y + int + default 1 config SOC_ADC_MAX_CHANNEL_NUM int diff --git a/components/soc/esp32c61/include/soc/soc_caps.h b/components/soc/esp32c61/include/soc/soc_caps.h index d4df399419..ce5c8596cd 100644 --- a/components/soc/esp32c61/include/soc/soc_caps.h +++ b/components/soc/esp32c61/include/soc/soc_caps.h @@ -76,7 +76,7 @@ #define SOC_ADC_MONITOR_SUPPORTED 1 #define SOC_ADC_DIG_SUPPORTED_UNIT(UNIT) 1 //Digital controller supported ADC unit #define SOC_ADC_DMA_SUPPORTED 1 -#define SOC_ADC_PERIPH_NUM (1) +#define SOC_ADC_PERIPH_NUM (1U) #define SOC_ADC_MAX_CHANNEL_NUM (4) #define SOC_ADC_CHANNEL_NUM(PERIPH_NUM) (4) #define SOC_ADC_ATTEN_NUM (4) diff --git a/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in index 297aaaa266..58e4996e97 100644 --- a/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in @@ -348,8 +348,8 @@ config SOC_CPU_WATCHPOINTS_NUM default 2 config SOC_CPU_WATCHPOINT_MAX_REGION_SIZE - int - default 64 + hex + default 0x40 config SOC_DAC_CHAN_NUM int @@ -776,8 +776,8 @@ config SOC_MEMSPI_SRC_FREQ_20M_SUPPORTED default y config SOC_SYSTIMER_COUNTER_NUM - bool - default y + int + default 1 config SOC_SYSTIMER_ALARM_NUM int @@ -832,8 +832,8 @@ config SOC_TOUCH_SENSOR_NUM default 15 config SOC_TOUCH_MIN_CHAN_ID - bool - default y + int + default 1 config SOC_TOUCH_MAX_CHAN_ID int diff --git a/components/soc/esp32s2/include/soc/soc_caps.h b/components/soc/esp32s2/include/soc/soc_caps.h index 36c4920c19..edb1119c19 100644 --- a/components/soc/esp32s2/include/soc/soc_caps.h +++ b/components/soc/esp32s2/include/soc/soc_caps.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -22,8 +22,8 @@ * x 0`, it's still a risk.) * * ECO & exceptions: - * For ECO-ed booleans, `#define x "Not determined"` for them. This will cause error when used by - * `#if x` and `#if !x`, making these missing definitions more obvious. + * For ECO-ed booleans, `#define x "Not determined" // [gen_soc_caps:ignore]` for them. This will cause error when used by + * `#if x` and `#if !x`, making these missing definitions more obvious. Ignore pragma ensures those values are not converted into config options. * * These defines are parsed and imported as kconfig variables via the script * `tools/gen_soc_caps_kconfig/gen_soc_caps_kconfig.py` @@ -148,7 +148,7 @@ #define SOC_CPU_BREAKPOINTS_NUM 2 #define SOC_CPU_WATCHPOINTS_NUM 2 -#define SOC_CPU_WATCHPOINT_MAX_REGION_SIZE 64 // bytes +#define SOC_CPU_WATCHPOINT_MAX_REGION_SIZE 0x40 // bytes /*-------------------------- DAC CAPS ----------------------------------------*/ #define SOC_DAC_CHAN_NUM 2 @@ -329,7 +329,7 @@ #define SOC_MEMSPI_SRC_FREQ_20M_SUPPORTED 1 /*-------------------------- SYSTIMER CAPS ----------------------------------*/ -#define SOC_SYSTIMER_COUNTER_NUM 1 // Number of counter units +#define SOC_SYSTIMER_COUNTER_NUM (1U) // Number of counter units #define SOC_SYSTIMER_ALARM_NUM 3 // Number of alarm units #define SOC_SYSTIMER_BIT_WIDTH_LO 32 // Bit width of systimer low part #define SOC_SYSTIMER_BIT_WIDTH_HI 32 // Bit width of systimer high part @@ -349,7 +349,7 @@ /*-------------------------- TOUCH SENSOR CAPS -------------------------------*/ #define SOC_TOUCH_SENSOR_VERSION (2) /*!< Hardware version of touch sensor */ #define SOC_TOUCH_SENSOR_NUM (15) /*!< 15 Touch channels */ -#define SOC_TOUCH_MIN_CHAN_ID (1) /*!< Touch minimum channel number, (0 is internal denoise channel) */ +#define SOC_TOUCH_MIN_CHAN_ID (1U) /*!< Touch minimum channel number, (0 is internal denoise channel) */ #define SOC_TOUCH_MAX_CHAN_ID (14) /*!< Touch maximum channel number */ #define SOC_TOUCH_SUPPORT_BENCHMARK (1) /*!< Touch sensor supports benchmark configuration */ #define SOC_TOUCH_SUPPORT_SLEEP_WAKEUP (1) /*!< Touch sensor supports sleep awake */ diff --git a/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in b/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in index 48f5a40c29..45f2afeaf5 100644 --- a/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in @@ -400,8 +400,8 @@ config SOC_CPU_WATCHPOINTS_NUM default 2 config SOC_CPU_WATCHPOINT_MAX_REGION_SIZE - int - default 64 + hex + default 0x40 config SOC_SIMD_PREFERRED_DATA_ALIGNMENT int @@ -856,8 +856,8 @@ config SOC_LP_IO_CLOCK_IS_INDEPENDENT default y config SOC_SDM_GROUPS - bool - default y + int + default 1 config SOC_SDM_CHANNELS_PER_GROUP int @@ -1032,8 +1032,8 @@ config SOC_TOUCH_SENSOR_NUM default 15 config SOC_TOUCH_MIN_CHAN_ID - bool - default y + int + default 1 config SOC_TOUCH_MAX_CHAN_ID int diff --git a/components/soc/esp32s3/include/soc/soc_caps.h b/components/soc/esp32s3/include/soc/soc_caps.h index 0482ce297e..7f761a3a86 100644 --- a/components/soc/esp32s3/include/soc/soc_caps.h +++ b/components/soc/esp32s3/include/soc/soc_caps.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2019-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -148,7 +148,7 @@ #define SOC_CPU_BREAKPOINTS_NUM 2 #define SOC_CPU_WATCHPOINTS_NUM 2 -#define SOC_CPU_WATCHPOINT_MAX_REGION_SIZE 64 // bytes +#define SOC_CPU_WATCHPOINT_MAX_REGION_SIZE 0x40 // bytes #define SOC_SIMD_PREFERRED_DATA_ALIGNMENT 16 // The preferred data alignment accepted by the SIMD instructions, in bytes @@ -335,7 +335,7 @@ #define SOC_LP_IO_CLOCK_IS_INDEPENDENT 1 /*-------------------------- Sigma Delta Modulator CAPS -----------------*/ -#define SOC_SDM_GROUPS 1 +#define SOC_SDM_GROUPS (1U) #define SOC_SDM_CHANNELS_PER_GROUP 8 #define SOC_SDM_CLK_SUPPORT_APB 1 @@ -400,7 +400,7 @@ /*-------------------------- TOUCH SENSOR CAPS -------------------------------*/ #define SOC_TOUCH_SENSOR_VERSION (2) /*!< Hardware version of touch sensor */ #define SOC_TOUCH_SENSOR_NUM (15) /*!< 15 Touch channels */ -#define SOC_TOUCH_MIN_CHAN_ID (1) /*!< Touch minimum channel number, (0 is internal denoise channel) */ +#define SOC_TOUCH_MIN_CHAN_ID (1U) /*!< Touch minimum channel number, (0 is internal denoise channel) */ #define SOC_TOUCH_MAX_CHAN_ID (14) /*!< Touch maximum channel number */ #define SOC_TOUCH_SUPPORT_BENCHMARK (1) /*!< Touch sensor supports benchmark configuration */ #define SOC_TOUCH_SUPPORT_SLEEP_WAKEUP (1) /*!< Touch sensor supports sleep awake */ diff --git a/tools/gen_soc_caps_kconfig/README.md b/tools/gen_soc_caps_kconfig/README.md index 2238c47531..57d6d31433 100644 --- a/tools/gen_soc_caps_kconfig/README.md +++ b/tools/gen_soc_caps_kconfig/README.md @@ -19,3 +19,5 @@ Defines that are 0 or 1 will automatically be interpreted as Booleans. If it's n The script is not able to evaluate expressions, e.g X*Y. If you need a variable to be available in kconfig it needs to be a simple assignment expression. + +If some `#define` statement should be excluded from being converted into config option, use `// [gen_soc_caps:ignore]` pragma. \ No newline at end of file diff --git a/tools/gen_soc_caps_kconfig/gen_soc_caps_kconfig.py b/tools/gen_soc_caps_kconfig/gen_soc_caps_kconfig.py index af6cfefc02..485d5ee93e 100755 --- a/tools/gen_soc_caps_kconfig/gen_soc_caps_kconfig.py +++ b/tools/gen_soc_caps_kconfig/gen_soc_caps_kconfig.py @@ -1,14 +1,16 @@ #!/usr/bin/env python # -# SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 """ Generate Kconfig.soc_caps.in with defines from soc_caps.h """ + import argparse import inspect import io import logging +import os import sys from difflib import unified_diff from os import path @@ -16,21 +18,22 @@ from pathlib import Path from string import Template import pyparsing -from pyparsing import alphas from pyparsing import CaselessLiteral from pyparsing import Char from pyparsing import Combine from pyparsing import Group -from pyparsing import hexnums +from pyparsing import Keyword from pyparsing import Literal -from pyparsing import nums from pyparsing import OneOrMore from pyparsing import Optional -from pyparsing import ParserElement +from pyparsing import ParserElement # noqa: F401 # pylint: disable=unused-import from pyparsing import QuotedString -from pyparsing import restOfLine from pyparsing import Suppress from pyparsing import Word +from pyparsing import alphas +from pyparsing import hexnums +from pyparsing import nums +from pyparsing import restOfLine pyparsing.usePackrat = True @@ -40,50 +43,49 @@ except ImportError: pass -class KconfigWriter(): - PREAMBLE = inspect.cleandoc(''' +class KconfigWriter: + PREAMBLE = inspect.cleandoc(""" ##################################################### # This file is auto-generated from SoC caps # using gen_soc_caps_kconfig.py, do not edit manually ##################################################### - ''') + """) KCONFIG_ENTRY_TEMPLATE = Template( - inspect.cleandoc(''' + inspect.cleandoc(""" config $name $entry_type default $value - ''')) + """) + ) KCONFIG_CONDITION_SOURCE_TEMPLATE = Template( - inspect.cleandoc(''' + inspect.cleandoc(""" if $condition source "$source_path" endif - ''')) - - def __init__(self): # type: () -> None - self.entries = set('') + """) + ) + def __init__(self, path, always_write): # type: (str, bool) -> None self.kconfig_text = io.StringIO('') self.kconfig_text.write(self.PREAMBLE) - def add_entry(self, name, entry_type, value): # type: (str, str, typing.Any) -> None + # NAME: (type, val) + self.entries = dict() # type: typing.Dict[str, typing.Tuple[str, typing.Any]] # key: config name, value: tuple of (config_type, config_value) + self.kconfig_path = path + self.always_write = always_write + def add_entry(self, name, entry_type, value): # type: (str, str, typing.Any) -> None if name in self.entries: logging.info('Duplicate entry: {}'.format(name)) return - self.entries.add(name) - self.kconfig_text.write('\n\n') - # Format values for kconfig if entry_type == 'bool': value = 'y' if value else 'n' elif entry_type == 'string': value = '"' + value + '"' - - entry = self.KCONFIG_ENTRY_TEMPLATE.substitute(name=name, entry_type=entry_type, value=value) - self.kconfig_text.write(entry) + self.entries[name] = (entry_type, value) def add_source(self, source_path, condition): # type: (str, str) -> None self.kconfig_text.write('\n\n') @@ -93,10 +95,16 @@ class KconfigWriter(): else: self.kconfig_text.write('source "' + source_path + '"') - def update_file(self, kconfig_path, always_write): # type: (Path, bool) -> bool + def update_file(self): # type: () -> bool + for entry_name in self.entries: + self.kconfig_text.write('\n\n') + config_option = self.KCONFIG_ENTRY_TEMPLATE.substitute( + name=entry_name, entry_type=self.entries[entry_name][0], value=self.entries[entry_name][1] + ) + self.kconfig_text.write(config_option) try: - with open(kconfig_path, 'r', encoding='utf-8') as f: + with open(self.kconfig_path, 'r', encoding='utf-8') as f: old_content = f.readlines() except FileNotFoundError: old_content = [''] @@ -105,17 +113,17 @@ class KconfigWriter(): new_content = self.kconfig_text.readlines() new_content[-1] += '\n' # Add final newline to end of file - file_needs_update = always_write + file_needs_update = self.always_write # Check if file was updated and print diff for users - diff = unified_diff(old_content, new_content, fromfile=str(kconfig_path), n=2) + diff = unified_diff(old_content, new_content, fromfile=str(self.kconfig_path), n=2) for line in diff: print(line, end='') file_needs_update = True if file_needs_update: - print('\n' + 'Updating file: {}'.format(kconfig_path)) - with open(kconfig_path, 'w', encoding='utf-8') as f: + print('\n' + 'Updating file: {}'.format(self.kconfig_path)) + with open(self.kconfig_path, 'w', encoding='utf-8') as f: f.writelines(new_content) return file_needs_update @@ -138,7 +146,6 @@ def parse_include(inc_line): # type: (str) -> typing.Any[typing.Type[ParserElem def parse_define(define_line): # type: (str) -> typing.Any[typing.Type[ParserElement]] - # Group for parsing literal suffix of a numbers, e.g. 100UL literal_symbol = Group(CaselessLiteral('L') | CaselessLiteral('U')) literal_suffix = OneOrMore(literal_symbol) @@ -148,23 +155,29 @@ def parse_define(define_line): # type: (str) -> typing.Any[typing.Type[ParserEl # Define value, either a hex, int or a string hex_value = Combine(Literal('0x') + Word(hexnums) + Optional(literal_suffix).suppress())('hex_value') - int_value = Combine(Optional('-') + Word(nums))('int_value') + ~Char('.') + Optional(literal_suffix)('literal_suffix') + int_value = ( + Combine(Optional('-') + Word(nums))('int_value') + ~Char('.') + Optional(literal_suffix)('literal_suffix') + ) str_value = QuotedString('"')('str_value') # Remove optional parenthesis around values - value = Optional('(').suppress() + (hex_value ^ int_value ^ str_value)('value') + Optional(')').suppress() + value = Optional('(').suppress() + (hex_value ^ int_value ^ str_value)('value') + Optional(')').suppress() - expr = '#define' + Optional(name)('name') + Optional(value) + # Define ignore pragma (if present, define will be ignored) + ignore_pragma = Literal('//') + Keyword('[gen_soc_caps:ignore]') + + expr = ( + '#define' + Optional(name)('name') + Optional(value) + Optional(ignore_pragma).set_results_name('ignore_pragma') + ) res = expr.parseString(define_line) return res -def generate_defines(soc_caps_dir, filename, always_write): # type: (Path, str, bool) -> bool - +def generate_defines(soc_caps_dir, filename, always_write): # type: (Path, str, bool) -> typing.Union[KconfigWriter, None] soc_headers = list(soc_caps_dir.glob(filename)) if soc_headers == []: - return False + return None # Sort header files to make the generated files deterministic soc_headers.sort(key=lambda file: file.name) @@ -173,13 +186,15 @@ def generate_defines(soc_caps_dir, filename, always_write): # type: (Path, str, for soc_header in soc_headers: defines.extend(get_defines(soc_header)) - writer = KconfigWriter() + writer = KconfigWriter(os.path.join(soc_caps_dir, 'Kconfig.soc_caps.in'), always_write) for line in defines: try: inc = parse_include(line) if 'inc_path' in inc and 'recursive' in inc and inc['inc_path'][-6:] == 'caps.h': - source_path = path.join('$IDF_PATH', str(soc_caps_dir), path.dirname(inc['inc_path']), 'Kconfig.soc_caps.in') + source_path = path.join( + '$IDF_PATH', str(soc_caps_dir), path.dirname(inc['inc_path']), 'Kconfig.soc_caps.in' + ) condition = inc['condition'].strip(' ') if 'condition' in inc else '' writer.add_source(source_path, condition) sub_soc_cap_dir = soc_caps_dir.joinpath(str(inc['inc_path'])).parent @@ -194,6 +209,10 @@ def generate_defines(soc_caps_dir, filename, always_write): # type: (Path, str, logging.debug('Failed to parse: {}'.format(line)) continue + if res.ignore_pragma: + # Ignore this define + continue + # Add the kconfig entry corresponding to the type we parsed if 'str_value' in res: writer.add_entry(res.name, 'string', res.str_value) @@ -209,10 +228,7 @@ def generate_defines(soc_caps_dir, filename, always_write): # type: (Path, str, elif 'hex_value' in res: writer.add_entry(res.name, 'hex', res.hex_value) - # Updates output if necessary - updated = writer.update_file(Path(soc_caps_dir) / 'Kconfig.soc_caps.in', always_write) - - return updated + return writer def get_defines(header_path): # type: (Path) -> list[str] @@ -230,12 +246,15 @@ def get_defines(header_path): # type: (Path) -> list[str] if __name__ == '__main__': - parser = argparse.ArgumentParser(description=__doc__) parser.add_argument('-d', '--dir', help='SoC caps folder paths, support wildcards', nargs='+', default=[]) - parser.add_argument('-n', '--filename', nargs='?', default='*caps.h', - help='SoC caps filename, support wildcards') - parser.add_argument('-v', '--verbose', action='count', help='Increase the logging level of the script. Can be specified multiple times.') + parser.add_argument('-n', '--filename', nargs='?', default='*caps.h', help='SoC caps filename, support wildcards') + parser.add_argument( + '-v', + '--verbose', + action='count', + help='Increase the logging level of the script. Can be specified multiple times.', + ) parser.add_argument('--always-write', help='Always generate new output files', action='store_true') args = parser.parse_args() @@ -249,10 +268,47 @@ if __name__ == '__main__': logging.basicConfig(level=log_level) files_updated = [] + writers = [] # type: typing.List[typing.Optional[KconfigWriter]] for caps_dir in args.dir: soc_caps_dirs = Path().glob(caps_dir) - files_updated += [generate_defines(d, args.filename, args.always_write) for d in soc_caps_dirs if path.isdir(d)] + new_writers = [generate_defines(d, args.filename, args.always_write) for d in soc_caps_dirs if path.isdir(d)] + writers.extend(new_writers) + configs = dict() # type: typing.Dict[str, str] # key: config name, value: config_type + configs_with_differing_types = dict() # type: typing.Dict[str, typing.Set[str]] # key: config name, value: set of types + for writer in writers: + if writer is None: + continue + for config_name in writer.entries: + if config_name in configs: + type_in_writer = writer.entries[config_name][0] + type_in_configs = configs[config_name] + if type_in_writer != type_in_configs: + if config_name not in configs_with_differing_types: + configs_with_differing_types[config_name] = set() + configs_with_differing_types[config_name].add(type_in_writer) + configs_with_differing_types[config_name].add(type_in_configs) + + else: + configs[config_name] = writer.entries[config_name][0] + + if configs_with_differing_types: + print( + 'The following macro constants would be translated to config options with different types' + ' for different targets (which may lead to unexpected behavior).' + ) + + for config_name in configs_with_differing_types: + print( + f' {config_name} has types' + f'{", ".join(config_type for config_type in configs_with_differing_types[config_name])}' + ) + + print('Please ensure all the macro constants will translate to the same config type for all targets.') + + sys.exit(1) + + files_updated = [writer.update_file() for writer in writers if writer is not None] print('Updated {} files'.format(sum(files_updated))) sys.exit(all(files_updated)) diff --git a/tools/gen_soc_caps_kconfig/test/test_gen_soc_caps_kconfig.py b/tools/gen_soc_caps_kconfig/test/test_gen_soc_caps_kconfig.py index 4d0cd796ff..1a6cccdc5f 100755 --- a/tools/gen_soc_caps_kconfig/test/test_gen_soc_caps_kconfig.py +++ b/tools/gen_soc_caps_kconfig/test/test_gen_soc_caps_kconfig.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Apache-2.0 import sys @@ -13,7 +13,6 @@ except ImportError: class ParserTests(unittest.TestCase): - def test_parse_name(self): res = gen_soc_caps_kconfig.parse_define('#define TEST_NAME (2)') self.assertEqual(res.name, 'TEST_NAME') @@ -44,10 +43,17 @@ class ParserTests(unittest.TestCase): self.assertEqual(res.int_value, '329000') def test_parse_float(self): - # Kconfig doesnt support floats, should not be parsed as anything + # Kconfig doesn't support floats, should not be parsed as anything res = gen_soc_caps_kconfig.parse_define('#define TEST_FLOAT (3.14)') self.assertEqual(res.value, '') + def test_parse_ignore_pragma(self): + res = gen_soc_caps_kconfig.parse_define('#define TEST_IGNORE // [gen_soc_caps:ignore]') + self.assertEqual(' '.join(res.ignore_pragma), '// [gen_soc_caps:ignore]') + + res = gen_soc_caps_kconfig.parse_define('#define TEST_NO_IGNORE') + self.assertEqual(res.ignore_pragma, '') + if __name__ == '__main__': print('Running gen_soc_caps_config tests...')