From d4244f3d52f276337b44b0bab8c85094c985682f Mon Sep 17 00:00:00 2001 From: Vegard Storheil Eriksen Date: Thu, 7 Jan 2021 02:12:00 +0100 Subject: build: Add platform spec framework. --- build/env.py | 2 + build/rules.py | 127 -------------------------------- build/scons_tools/tool_platform_spec.py | 112 ++++++++++++++++++++++++++++ build/scons_tools/tool_selectmcu.py | 126 ++++++------------------------- platforms/cortex-m.yaml | 13 ++++ platforms/index.yaml | 9 +++ platforms/stm32/f4.yaml | 30 ++++++++ platforms/stm32/index.yaml | 8 ++ 8 files changed, 196 insertions(+), 231 deletions(-) delete mode 100644 build/rules.py create mode 100644 build/scons_tools/tool_platform_spec.py create mode 100644 platforms/cortex-m.yaml create mode 100644 platforms/index.yaml create mode 100644 platforms/stm32/f4.yaml create mode 100644 platforms/stm32/index.yaml diff --git a/build/env.py b/build/env.py index 6bc23e8..082195d 100644 --- a/build/env.py +++ b/build/env.py @@ -2,6 +2,7 @@ import os env = Environment( ENV = os.environ, + LAKS_PATH = Dir('..'), toolpath = ['scons_tools'], tools = [ @@ -9,6 +10,7 @@ env = Environment( 'tool_selectmcu', 'tool_firmware', 'tool_jinja2', + 'tool_platform_spec', ], ) diff --git a/build/rules.py b/build/rules.py deleted file mode 100644 index 80a4d10..0000000 --- a/build/rules.py +++ /dev/null @@ -1,127 +0,0 @@ -laks_dir = Dir('..') -ld_dir = Dir('../ld_scripts') -main_sconscript = File('../SConscript') - -def select_arm(env, family): - env.SetDefault( - TOOLCHAIN = 'arm-none-eabi-', - ) - - if family == 'cortex-m4f': - family = 'cortex-m4' - has_mcu = True - else: - has_mcu = False - - env.Replace( - CC = '${TOOLCHAIN}gcc', - CXX = '${TOOLCHAIN}g++', - AS = '${TOOLCHAIN}gcc', - LINK = '${TOOLCHAIN}gcc', - AR = '${TOOLCHAIN}ar', - RANLIB = '${TOOLCHAIN}ranlib', - - CCFLAGS = Split('-O2 -Wall -ggdb -mcpu=${CPU_FAMILY} -mthumb -ffunction-sections'), - CXXFLAGS = Split('-std=c++20 -fno-exceptions -fno-rtti -Wno-pmf-conversions'), - ASFLAGS = Split('-c -x assembler-with-cpp -mcpu=${CPU_FAMILY} -mthumb'), - LINKFLAGS = Split('-Wall -mcpu=${CPU_FAMILY} -mthumb -nostartfiles -Wl,-T${LINK_SCRIPT} -Wl,--gc-sections'), - - CPPPATH = [laks_dir], - LIBPATH = [ld_dir], - - LIB_SOURCES = [], - - CPU_FAMILY = family, - ) - - if has_mcu: - env.Append(CCFLAGS = Split('-mfloat-abi=hard -mfpu=fpv4-sp-d16')) - env.Append(LINKFLAGS = Split('-mfloat-abi=hard -mfpu=fpv4-sp-d16')) - env.Append(CPPDEFINES = ['HAS_FPU']) - -def select_stm32(env, variant): - family = variant[5:9] - pin_count = variant[9] - flash = variant[10] - - if family.startswith('f0'): - select_arm(env, 'cortex-m0') - env.Append(CPPDEFINES = ['STM32F0']) - - sram = family[2] - - env['LINK_SCRIPT'] = { - ('4', '6'): 'stm32_f04_6.ld', - ('5', '8'): 'stm32_f05_8.ld', - }[sram, flash] - - elif family == 'f103': - select_arm(env, 'cortex-m3') - env.Append(CPPDEFINES = ['STM32F1']) - - env['LINK_SCRIPT'] = { - '8': 'stm32_f1_8.ld', - 'b': 'stm32_f1_b.ld', - }[flash] - - elif family == 'f303': - select_arm(env, 'cortex-m4f') - env.Append(CPPDEFINES = ['STM32F3']) - - env['LINK_SCRIPT'] = { - 'b': 'stm32_f303_b.ld', - 'c': 'stm32_f303_c.ld', - }[flash] - - elif family == 'f373': - select_arm(env, 'cortex-m4f') - env.Append(CPPDEFINES = ['STM32F3']) - - env['LINK_SCRIPT'] = { - '8': 'stm32_f373_8.ld', - 'b': 'stm32_f373_b.ld', - 'c': 'stm32_f373_c.ld', - }[flash] - - elif family in ('f401'): - select_arm(env, 'cortex-m4f') - env.Append(CPPDEFINES = ['STM32F4']) - - env['LINK_SCRIPT'] = { - 'e': 'stm32_f401_e.ld', - }[flash] - - elif family in ('f405', 'f407'): - select_arm(env, 'cortex-m4f') - env.Append(CPPDEFINES = ['STM32F4']) - - env['LINK_SCRIPT'] = { - 'e': 'stm32_f4_e.ld', - 'g': 'stm32_f4_g.ld', - }[flash] - - elif family in ('l051', 'l052', 'l053'): - select_arm(env, 'cortex-m0plus') - env.Append(CPPDEFINES = ['STM32L0']) - - env['LINK_SCRIPT'] = { - '8': 'stm32_l0_8.ld', - }[flash] - - else: - print('Unknown stm32 family: %s' % family) - Exit(1) - -def SelectMCU(env, mcu, variant_dir = None): - mcu = mcu.lower() - - if mcu.startswith('stm32'): - select_stm32(env, mcu) - - else: - print('Unknown MCU: %s' % mcu) - Exit(1) - - SConscript(main_sconscript, variant_dir = variant_dir, exports = 'env') - -AddMethod(Environment, SelectMCU) diff --git a/build/scons_tools/tool_platform_spec.py b/build/scons_tools/tool_platform_spec.py new file mode 100644 index 0000000..a532036 --- /dev/null +++ b/build/scons_tools/tool_platform_spec.py @@ -0,0 +1,112 @@ +from SCons.Script import * + +import yaml +import re +import os.path + +def load(fn): + return yaml.load(open(fn), Loader = yaml.FullLoader) + +class Matcher: + pass + +class ReMatcher(Matcher): + def __init__(self, pattern): + self.pattern = pattern + + def match(self, meta, key): + m = re.match(self.pattern, meta.get(key, '')) + + if m: + meta.update(m.groupdict()) + return True + + return False + +class Import: + def __init__(self, fn): + self.fn = fn + self.data = None + + def _load(self): + if self.data is None: + self.data = load(self.fn) + + def __iter__(self): + self._load() + return iter(self.data or []) + +yaml.add_constructor('!re', (lambda loader, node: ReMatcher(loader.construct_scalar(node)))) + +def construct_import(loader, node): + fn = loader.construct_scalar(node) + path = os.path.split(loader.stream.name)[0] + + return Import(os.path.join(path, fn)) + +yaml.add_constructor('!import', construct_import) + +def unprefix(s): + return int(s[:-1]) * 1024**(' kMG'.index(s[-1])) + +yaml.add_constructor('!prefixed', (lambda loader, node: unprefix(loader.construct_scalar(node)))) +yaml.add_implicit_resolver('!prefixed', re.compile(r'^\d+[kMG]$')) + +def match(meta, name, value): + if isinstance(value, Matcher): + return value.match(meta, name) + + return meta.get(name) == value + +def merge(parent, key, value): + if key in parent: + target = parent[key] + if isinstance(target, dict): + for k, v in value.items(): + merge(target, k, v) + return + + elif isinstance(target, list): + target.extend(value) + return + + parent[key] = value + +def parse(state, data): + for obj in data: + if not obj: + continue + + m = obj.get('match') + if m: + if not all(match(state['meta'], name, value) for name, value in m.items()): + continue + + for key, value in obj.items(): + if key in ('match', '-'): + continue + + #state[key] = obj[key] + merge(state, key, obj[key]) + + if '-' in obj: + parse(state, obj['-']) + + return state + +def PlatformSpec(env, **kwargs): + state = { + 'meta': kwargs + } + + fn = str(env.File('${LAKS_PATH}/platforms/index.yaml')) + + data = yaml.load(open(fn), Loader = yaml.FullLoader) + + return parse(state, data) + +def exists(): + return True + +def generate(env): + env.AddMethod(PlatformSpec) \ No newline at end of file diff --git a/build/scons_tools/tool_selectmcu.py b/build/scons_tools/tool_selectmcu.py index 1e2b0ee..da4b38d 100644 --- a/build/scons_tools/tool_selectmcu.py +++ b/build/scons_tools/tool_selectmcu.py @@ -1,20 +1,17 @@ from SCons.Script import * -laks_dir = Dir('..') -ld_dir = Dir('../ld_scripts') -main_sconscript = File('../SConscript') +def SelectMCU(env, mcu, variant_dir = None): + + spec = env.PlatformSpec(mcu = mcu) + + if len(spec) <= 1: + print('Unknown MCU: %s' % mcu) + Exit(1) -def select_arm(env, family): env.SetDefault( - TOOLCHAIN = 'arm-none-eabi-', + TOOLCHAIN = '%s-' % spec['toolchains'][0], ) - if family == 'cortex-m4f': - family = 'cortex-m4' - has_mcu = True - else: - has_mcu = False - env.Replace( CC = '${TOOLCHAIN}gcc', CXX = '${TOOLCHAIN}g++', @@ -23,108 +20,29 @@ def select_arm(env, family): AR = '${TOOLCHAIN}ar', RANLIB = '${TOOLCHAIN}ranlib', - CCFLAGS = Split('-O2 -Wall -ggdb -mcpu=${CPU_FAMILY} -mthumb -ffunction-sections'), + CCFLAGS = Split('-O2 -Wall -ggdb -ffunction-sections'), CXXFLAGS = Split('-std=c++20 -fno-exceptions -fno-rtti -Wno-pmf-conversions'), - ASFLAGS = Split('-c -x assembler-with-cpp -mcpu=${CPU_FAMILY} -mthumb'), - LINKFLAGS = Split('-Wall -mcpu=${CPU_FAMILY} -mthumb -nostartfiles -Wl,-T${LINK_SCRIPT} -Wl,--gc-sections'), + ASFLAGS = Split('-c -x assembler-with-cpp'), + LINKFLAGS = Split('-Wall -nostartfiles -Wl,-T${LINK_SCRIPT} -Wl,--gc-sections'), - CPPPATH = [laks_dir], - LIBPATH = [ld_dir], + CPPPATH = ['${LAKS_PATH}'], + LIBPATH = ['${LAKS_PATH}/ld_scripts'], LIB_SOURCES = [], - - CPU_FAMILY = family, ) - - if has_mcu: - env.Append(CCFLAGS = Split('-mfloat-abi=hard -mfpu=fpv4-sp-d16')) - env.Append(LINKFLAGS = Split('-mfloat-abi=hard -mfpu=fpv4-sp-d16')) - env.Append(CPPDEFINES = ['HAS_FPU']) -def select_stm32(env, variant): - family = variant[5:9] - pin_count = variant[9] - flash = variant[10] - - if family.startswith('f0'): - select_arm(env, 'cortex-m0') - env.Append(CPPDEFINES = ['STM32F0']) + env.Replace( + LINK_SCRIPT = spec.get('ld_script'), + ) - sram = family[2] - - env['LINK_SCRIPT'] = { - ('4', '6'): 'stm32_f04_6.ld', - ('5', '8'): 'stm32_f05_8.ld', - }[sram, flash] - - elif family == 'f103': - select_arm(env, 'cortex-m3') - env.Append(CPPDEFINES = ['STM32F1']) - - env['LINK_SCRIPT'] = { - '8': 'stm32_f1_8.ld', - 'b': 'stm32_f1_b.ld', - }[flash] - - elif family == 'f303': - select_arm(env, 'cortex-m4f') - env.Append(CPPDEFINES = ['STM32F3']) - - env['LINK_SCRIPT'] = { - 'b': 'stm32_f303_b.ld', - 'c': 'stm32_f303_c.ld', - }[flash] - - elif family == 'f373': - select_arm(env, 'cortex-m4f') - env.Append(CPPDEFINES = ['STM32F3']) - - env['LINK_SCRIPT'] = { - '8': 'stm32_f373_8.ld', - 'b': 'stm32_f373_b.ld', - 'c': 'stm32_f373_c.ld', - }[flash] - - elif family in ('f401'): - select_arm(env, 'cortex-m4f') - env.Append(CPPDEFINES = ['STM32F4']) - - env['LINK_SCRIPT'] = { - 'e': 'stm32_f401_e.ld', - }[flash] - - elif family in ('f405', 'f407'): - select_arm(env, 'cortex-m4f') - env.Append(CPPDEFINES = ['STM32F4']) - - env['LINK_SCRIPT'] = { - 'e': 'stm32_f4_e.ld', - 'g': 'stm32_f4_g.ld', - }[flash] - - elif family in ('l051', 'l052', 'l053'): - select_arm(env, 'cortex-m0plus') - env.Append(CPPDEFINES = ['STM32L0']) - - env['LINK_SCRIPT'] = { - '8': 'stm32_l0_8.ld', - }[flash] + env.Append( + CCFLAGS = spec.get('cflags', []), + LINKFLAGS = spec.get('cflags', []), + CPPDEFINES = spec.get('define', []), + ) - else: - print('Unknown stm32 family: %s' % family) - Exit(1) + env.SConscript('${LAKS_PATH}/SConscript', variant_dir = variant_dir, exports = 'env') -def SelectMCU(env, mcu, variant_dir = None): - mcu = mcu.lower() - - if mcu.startswith('stm32'): - select_stm32(env, mcu) - - else: - print('Unknown MCU: %s' % mcu) - Exit(1) - - SConscript(main_sconscript, variant_dir = variant_dir, exports = 'env') def exists(): return True diff --git a/platforms/cortex-m.yaml b/platforms/cortex-m.yaml new file mode 100644 index 0000000..d1612b2 --- /dev/null +++ b/platforms/cortex-m.yaml @@ -0,0 +1,13 @@ +- match: + cpu: cortex-m4f + + cflags: + - -mcpu=cortex-m4 + - -mfloat-abi=hard + - -mfpu=fpv4-sp-d16 + + define: + - HAS_FPU + + toolchains: + - arm-none-eabi diff --git a/platforms/index.yaml b/platforms/index.yaml new file mode 100644 index 0000000..558b535 --- /dev/null +++ b/platforms/index.yaml @@ -0,0 +1,9 @@ +- match: + mcu: !re stm32 + + -: !import stm32/index.yaml + +- match: + cpu: !re cortex-m + + -: !import cortex-m.yaml diff --git a/platforms/stm32/f4.yaml b/platforms/stm32/f4.yaml new file mode 100644 index 0000000..0d336ce --- /dev/null +++ b/platforms/stm32/f4.yaml @@ -0,0 +1,30 @@ +- match: + mem: e + mem: + flash: + origin: 0x08000000 + size: 512k + ld_script: stm32_f4_e.ld + +- match: + mem: g + mem: + flash: + origin: 0x08000000 + size: 1M + ld_script: stm32_f4_g.ld + +- mem: + ram: + origin: 0x20000000 + size: 128k + + ccm: + origin: 0x10000000 + size: 64k + + define: + - STM32F4 + + meta: + cpu: cortex-m4f \ No newline at end of file diff --git a/platforms/stm32/index.yaml b/platforms/stm32/index.yaml new file mode 100644 index 0000000..a8cb56f --- /dev/null +++ b/platforms/stm32/index.yaml @@ -0,0 +1,8 @@ +- match: + mcu: !re stm32(?P..)(?P..).(?P.) + + -: + - match: + family: f4 + + -: !import f4.yaml -- cgit v1.2.3