From c402cc7c623ee86875e1c19640f2049803687fab Mon Sep 17 00:00:00 2001 From: Valeriy Koval Date: Tue, 3 Feb 2015 14:32:12 +0200 Subject: [PATCH] Add support for STM32 CMSIS, SPL and OpenCM3 frameworks --- .../builder/scripts/frameworks/cmsis.py | 42 +++++ .../builder/scripts/frameworks/opencm3.py | 172 ++++++++++++++++++ platformio/builder/scripts/frameworks/spl.py | 64 +++++++ platformio/platforms/stm32.py | 13 ++ 4 files changed, 291 insertions(+) create mode 100644 platformio/builder/scripts/frameworks/cmsis.py create mode 100644 platformio/builder/scripts/frameworks/opencm3.py create mode 100644 platformio/builder/scripts/frameworks/spl.py diff --git a/platformio/builder/scripts/frameworks/cmsis.py b/platformio/builder/scripts/frameworks/cmsis.py new file mode 100644 index 00000000..a1c0c9a6 --- /dev/null +++ b/platformio/builder/scripts/frameworks/cmsis.py @@ -0,0 +1,42 @@ +# Copyright (C) Ivan Kravets +# See LICENSE for details. + +""" + Build script for CMSIS Framework. +""" + +from os.path import join + +from SCons.Script import Import, Return + + +env = None +Import("env") + +env.VariantDir( + join("$BUILD_DIR", "FrameworkCMSIS"), + join("$PIOPACKAGES_DIR", "framework-cmsis", + "cores", "${BOARD_OPTIONS['build']['core']}") +) + +env.Append( + CPPPATH=[ + join("$BUILD_DIR", "FrameworkCMSIS"), + join("$BUILD_DIR", "FrameworkCMSISVariant") + ] +) + +envsafe = env.Clone() + +# +# Target: Build Core Library +# + +libs = [] +libs.append(envsafe.BuildLibrary( + join("$BUILD_DIR", "FrameworkCMSISVariant"), + join("$PIOPACKAGES_DIR", "framework-cmsis", "variants", + "${BOARD_OPTIONS['build']['variant']}") +)) + +Return("env libs") diff --git a/platformio/builder/scripts/frameworks/opencm3.py b/platformio/builder/scripts/frameworks/opencm3.py new file mode 100644 index 00000000..82c9a5bb --- /dev/null +++ b/platformio/builder/scripts/frameworks/opencm3.py @@ -0,0 +1,172 @@ +# Copyright (C) Ivan Kravets +# See LICENSE for details. + +""" + Build script for OpenCM3 Framework. +""" + +import re +from os import listdir, sep, walk +from os.path import isfile, join, normpath + +from SCons.Script import Import, Return + +from platformio.util import exec_command + + +env = None +Import("env") +BOARD_BUILDOPTS = env.get("BOARD_OPTIONS", {}).get("build", {}) + + +def find_ldscript(src_dir): + ldscript = None + matches = [] + for item in listdir(src_dir): + _path = join(src_dir, item) + if not isfile(_path) or not item.endswith(".ld"): + continue + matches.append(_path) + + if len(matches) == 1: + ldscript = matches[0] + elif isfile(join(src_dir, BOARD_BUILDOPTS['ldscript'])): + ldscript = join(src_dir, BOARD_BUILDOPTS['ldscript']) + + assert isfile(ldscript) + return ldscript + + +def generate_nvic_files(): + fw_dir = join(env.get("PIOHOME_DIR"), "packages", "framework-opencm3") + + for root, _, files in walk(join(fw_dir, "include", "libopencm3")): + if "irq.json" not in files or isfile(join(root, "nvic.h")): + continue + + exec_command( + ["python", join("scripts", "irq2nvic_h"), + join("." + root.replace(fw_dir, ""), + "irq.json").replace("\\", "/")], + cwd=fw_dir + ) + + +def parse_makefile_data(makefile): + data = {"includes": [], "objs": [], "vpath": ["./"]} + + with open(makefile) as f: + content = f.read() + + # fetch "includes" + re_include = re.compile(r"^include\s+([^\r\n]+)", re.M) + for match in re_include.finditer(content): + data['includes'].append(match.group(1)) + + # fetch "vpath"s + re_vpath = re.compile(r"^VPATH\s+\+?=\s+([^\r\n]+)", re.M) + for match in re_vpath.finditer(content): + data['vpath'] += match.group(1).split(":") + + # fetch obj files + objs_match = re.search( + r"^OBJS\s+\+?=\s+([^\.]+\.o\s*(?:\s+\\s+)?)+", content, re.M) + assert objs_match + data['objs'] = re.sub( + r"(OBJS|[\+=\\\s]+)", "\n", objs_match.group(0)).split() + return data + + +def get_source_files(src_dir): + mkdata = parse_makefile_data(join(src_dir, "Makefile")) + + for include in mkdata['includes']: + _mkdata = parse_makefile_data(normpath(join(src_dir, include))) + for key, value in _mkdata.iteritems(): + for v in value: + if v not in mkdata[key]: + mkdata[key].append(v) + + sources = [] + lib_root = env.subst( + join(env.get("PIOHOME_DIR"), "packages", "framework-opencm3")) + for obj_file in mkdata['objs']: + src_file = obj_file[:-1] + "c" + for search_path in mkdata['vpath']: + src_path = normpath(join(src_dir, search_path, src_file)) + if isfile(src_path): + sources.append(join("$BUILD_DIR", "FrameworkOpenCM3", + src_path.replace(lib_root + sep, ""))) + break + return sources + + +def merge_ld_scripts(main_ld_file): + + def _include_callback(match): + included_ld_file = match.group(1) + # search included ld file in lib directories + for root, _, files in walk(join( + env.get("PIOHOME_DIR"), "packages", + "framework-opencm3", "lib")): + + if included_ld_file not in files: + continue + with open(join(root, included_ld_file)) as fp: + return fp.read() + + return match.group(0) + + content = "" + with open(main_ld_file) as f: + content = f.read() + + incre = re.compile(r"^INCLUDE\s+\"?([^\.]+\.ld)\"?", re.M) + with open(main_ld_file, "w") as f: + f.write(incre.sub(_include_callback, content)) + +# +# Processing ... +# + +if BOARD_BUILDOPTS.get("core") == "lm4f": + env.Append( + CPPDEFINES=["LM4F"] + ) + +env.VariantDir( + join("$BUILD_DIR", "FrameworkOpenCM3Variant"), + join("$PIOPACKAGES_DIR", "framework-opencm3", "include") +) + +env.Append( + CPPPATH=[ + join("$BUILD_DIR", "FrameworkOpenCM3"), + join("$BUILD_DIR", "FrameworkOpenCM3Variant") + ] +) + +root_dir = join(env.get("PIOHOME_DIR"), "packages", "framework-opencm3", "lib", + BOARD_BUILDOPTS.get("core")) +if BOARD_BUILDOPTS.get("core") == "stm32": + root_dir = join(root_dir, BOARD_BUILDOPTS.get("variant")[-2:]) + +ldscript_path = find_ldscript(root_dir) +merge_ld_scripts(ldscript_path) +generate_nvic_files() + +# override ldscript by opencm3 +assert env['LINKFLAGS'][0] == "-T" +env['LINKFLAGS'][1] = ldscript_path + +libs = [] +env.VariantDir( + join("$BUILD_DIR", "FrameworkOpenCM3"), + join(env.get("PIOHOME_DIR"), "packages", "framework-opencm3") +) +libs.append(env.Library( + join("$BUILD_DIR", "FrameworkOpenCM3"), + get_source_files(root_dir) +)) + +Return("env libs") diff --git a/platformio/builder/scripts/frameworks/spl.py b/platformio/builder/scripts/frameworks/spl.py new file mode 100644 index 00000000..239a6ba2 --- /dev/null +++ b/platformio/builder/scripts/frameworks/spl.py @@ -0,0 +1,64 @@ +# Copyright (C) Ivan Kravets +# See LICENSE for details. + +""" + Build script for SPL Framework +""" + +from os.path import join + +from SCons.Script import Import, Return + + +env = None +Import("env") + +env.VariantDir( + join("$BUILD_DIR", "FrameworkSPLInc"), + join("$PIOPACKAGES_DIR", "framework-spl", + "${BOARD_OPTIONS['build']['core']}", + "variants", "${BOARD_OPTIONS['build']['variant']}", "inc") +) + +env.Append( + CPPPATH=[ + join("$BUILD_DIR", "FrameworkSPLInc"), + join("$BUILD_DIR", "FrameworkSPL") + ] +) + +envsafe = env.Clone() + +envsafe.Append( + CPPPATH=[ + join("$BUILD_DIR", "src") + ], + + CPPDEFINES=[ + "USE_STDPERIPH_DRIVER" + ] +) + +# +# Target: Build SPL Library +# + +extra_flags = env.get("BOARD_OPTIONS", {}).get("build", {}).get("extra_flags") +ignore_files = [] +if "STM32F40_41xxx" in extra_flags: + ignore_files += ["stm32f4xx_fmc.c"] +elif "STM32F303xC" in extra_flags: + ignore_files += ["stm32f30x_hrtim.c"] +elif "STM32L1XX_MD" in extra_flags: + ignore_files += ["stm32l1xx_flash_ramfunc.c"] # removed warning + +libs = [] +libs.append(envsafe.BuildLibrary( + join("$BUILD_DIR", "FrameworkSPL"), + join("$PIOPACKAGES_DIR", "framework-spl", + "${BOARD_OPTIONS['build']['core']}", "variants", + "${BOARD_OPTIONS['build']['variant']}", "src"), + ignore_files +)) + +Return("env libs") diff --git a/platformio/platforms/stm32.py b/platformio/platforms/stm32.py index 807b1a2e..63607d95 100644 --- a/platformio/platforms/stm32.py +++ b/platformio/platforms/stm32.py @@ -5,6 +5,7 @@ from platformio.platforms.base import BasePlatform class Stm32Platform(BasePlatform): + """ An embedded platform for STMicroelectronics ARM microcontrollers """ @@ -23,5 +24,17 @@ class Stm32Platform(BasePlatform): "tool-stlink": { "alias": "uploader", "default": True + }, + + "framework-cmsis": { + "default": True + }, + + "framework-spl": { + "default": True + }, + + "framework-opencm3": { + "default": True } }