diff --git a/lib/python/qmk/cli/__init__.py b/lib/python/qmk/cli/__init__.py
index 47e1b44351..459e8e1da3 100644
--- a/lib/python/qmk/cli/__init__.py
+++ b/lib/python/qmk/cli/__init__.py
@@ -8,6 +8,7 @@ from milc import cli
from . import c2json
from . import cformat
+from . import chibios
from . import compile
from . import config
from . import docs
diff --git a/lib/python/qmk/cli/chibios/__init__.py b/lib/python/qmk/cli/chibios/__init__.py
new file mode 100644
index 0000000000..4301837def
--- /dev/null
+++ b/lib/python/qmk/cli/chibios/__init__.py
@@ -0,0 +1 @@
+from . import confmigrate
diff --git a/lib/python/qmk/cli/chibios/confmigrate.py b/lib/python/qmk/cli/chibios/confmigrate.py
new file mode 100644
index 0000000000..eae294a0c6
--- /dev/null
+++ b/lib/python/qmk/cli/chibios/confmigrate.py
@@ -0,0 +1,161 @@
+"""This script automates the copying of the default keymap into your own keymap.
+"""
+import re
+import sys
+import os
+
+from qmk.constants import QMK_FIRMWARE
+from qmk.path import normpath
+from milc import cli
+
+
+def eprint(*args, **kwargs):
+ print(*args, file=sys.stderr, **kwargs)
+
+
+fileHeader = """\
+/* Copyright 2020 QMK
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+/*
+ * This file was auto-generated by:
+ * `qmk chibios-confupdate -i {0} -r {1}`
+ */
+
+#pragma once
+"""
+
+
+def collect_defines(filepath):
+ with open(filepath, 'r') as f:
+ content = f.read()
+ define_search = re.compile(r'(?m)^#\s*define\s+(?:.*\\\r?\n)*.*$', re.MULTILINE)
+ value_search = re.compile(r'^#\s*define\s+(?P[a-zA-Z0-9_]+(\([^\)]*\))?)\s*(?P.*)', re.DOTALL)
+ define_matches = define_search.findall(content)
+
+ defines = {"keys": [], "dict": {}}
+ for define_match in define_matches:
+ value_match = value_search.search(define_match)
+ defines["keys"].append(value_match.group("name"))
+ defines["dict"][value_match.group("name")] = value_match.group("value")
+ return defines
+
+
+def check_diffs(input_defs, reference_defs):
+ not_present_in_input = []
+ not_present_in_reference = []
+ to_override = []
+
+ for key in reference_defs["keys"]:
+ if key not in input_defs["dict"]:
+ not_present_in_input.append(key)
+ continue
+
+ for key in input_defs["keys"]:
+ if key not in input_defs["dict"]:
+ not_present_in_input.append(key)
+ continue
+
+ for key in input_defs["keys"]:
+ if key in reference_defs["keys"] and input_defs["dict"][key] != reference_defs["dict"][key]:
+ to_override.append((key, input_defs["dict"][key]))
+
+ return (to_override, not_present_in_input, not_present_in_reference)
+
+
+def migrate_chconf_h(to_override, outfile):
+ print(fileHeader.format(cli.args.input.relative_to(QMK_FIRMWARE), cli.args.reference.relative_to(QMK_FIRMWARE)), file=outfile)
+
+ for override in to_override:
+ print("#define %s %s" % (override[0], override[1]), file=outfile)
+ print("", file=outfile)
+
+ print("#include_next \n", file=outfile)
+
+
+def migrate_halconf_h(to_override, outfile):
+ print(fileHeader.format(cli.args.input.relative_to(QMK_FIRMWARE), cli.args.reference.relative_to(QMK_FIRMWARE)), file=outfile)
+
+ for override in to_override:
+ print("#define %s %s" % (override[0], override[1]), file=outfile)
+ print("", file=outfile)
+
+ print("#include_next \n", file=outfile)
+
+
+def migrate_mcuconf_h(to_override, outfile):
+ print(fileHeader.format(cli.args.input.relative_to(QMK_FIRMWARE), cli.args.reference.relative_to(QMK_FIRMWARE)), file=outfile)
+
+ print("#include_next \n", file=outfile)
+
+ for override in to_override:
+ print("#undef %s" % (override[0]), file=outfile)
+ print("#define %s %s" % (override[0], override[1]), file=outfile)
+ print("", file=outfile)
+
+
+@cli.argument('-i', '--input', type=normpath, arg_only=True, help='Specify input config file.')
+@cli.argument('-r', '--reference', type=normpath, arg_only=True, help='Specify the reference file to compare against')
+@cli.argument('-o', '--overwrite', arg_only=True, action='store_true', help='Overwrites the input file during migration.')
+@cli.argument('-d', '--delete', arg_only=True, action='store_true', help='If the file has no overrides, migration will delete the input file.')
+@cli.subcommand('Generates a migrated ChibiOS configuration file, as a result of comparing the input against a reference')
+def chibios_confmigrate(cli):
+ """Generates a usable ChibiOS replacement configuration file, based on a fully-defined conf and a reference config.
+ """
+
+ input_defs = collect_defines(cli.args.input)
+ reference_defs = collect_defines(cli.args.reference)
+
+ (to_override, not_present_in_input, not_present_in_reference) = check_diffs(input_defs, reference_defs)
+
+ if len(not_present_in_input) > 0:
+ eprint("Keys not in input, but present inside reference (potential manual migration required):")
+ for key in not_present_in_input:
+ eprint(" %s" % (key))
+
+ if len(not_present_in_reference) > 0:
+ eprint("Keys not in reference, but present inside input (potential manual migration required):")
+ for key in not_present_in_reference:
+ eprint(" %s" % (key))
+
+ if len(to_override) == 0:
+ eprint('No overrides found! If there were no missing keys above, it should be safe to delete the input file.')
+ if cli.args.delete:
+ os.remove(cli.args.input)
+ else:
+ eprint('Overrides found:')
+ for override in to_override:
+ eprint("%40s: %s -> %s" % (override[0], reference_defs["dict"][override[0]].encode('unicode_escape').decode("utf-8"), override[1].encode('unicode_escape').decode("utf-8")))
+
+ eprint('--------------------------------------')
+
+ if "CHCONF_H" in input_defs["dict"] or "_CHCONF_H_" in input_defs["dict"]:
+ migrate_chconf_h(to_override, outfile=sys.stdout)
+ if cli.args.overwrite:
+ with open(cli.args.input, "w") as out_file:
+ migrate_chconf_h(to_override, outfile=out_file)
+
+ elif "HALCONF_H" in input_defs["dict"] or "_HALCONF_H_" in input_defs["dict"]:
+ migrate_halconf_h(to_override, outfile=sys.stdout)
+ if cli.args.overwrite:
+ with open(cli.args.input, "w") as out_file:
+ migrate_halconf_h(to_override, outfile=out_file)
+
+ elif "MCUCONF_H" in input_defs["dict"] or "_MCUCONF_H_" in input_defs["dict"]:
+ migrate_mcuconf_h(to_override, outfile=sys.stdout)
+ if cli.args.overwrite:
+ with open(cli.args.input, "w") as out_file:
+ migrate_mcuconf_h(to_override, outfile=out_file)
diff --git a/platforms/chibios/GENERIC_STM32_F303XC/configs/chconf.h b/platforms/chibios/common/configs/chconf.h
similarity index 100%
rename from platforms/chibios/GENERIC_STM32_F303XC/configs/chconf.h
rename to platforms/chibios/common/configs/chconf.h
diff --git a/platforms/chibios/GENERIC_STM32_F303XC/configs/halconf.h b/platforms/chibios/common/configs/halconf.h
similarity index 100%
rename from platforms/chibios/GENERIC_STM32_F303XC/configs/halconf.h
rename to platforms/chibios/common/configs/halconf.h
diff --git a/platforms/chibios/ld/MKL26Z64.ld b/platforms/chibios/common/ld/MKL26Z64.ld
similarity index 100%
rename from platforms/chibios/ld/MKL26Z64.ld
rename to platforms/chibios/common/ld/MKL26Z64.ld
diff --git a/platforms/chibios/ld/STM32F103x8_stm32duino_bootloader.ld b/platforms/chibios/common/ld/STM32F103x8_stm32duino_bootloader.ld
similarity index 100%
rename from platforms/chibios/ld/STM32F103x8_stm32duino_bootloader.ld
rename to platforms/chibios/common/ld/STM32F103x8_stm32duino_bootloader.ld
diff --git a/tmk_core/chibios.mk b/tmk_core/chibios.mk
index 2bd53f0dc8..e53edccee2 100644
--- a/tmk_core/chibios.mk
+++ b/tmk_core/chibios.mk
@@ -123,6 +123,8 @@ else ifneq ("$(wildcard $(KEYBOARD_PATH_1)/chconf.h)","")
CHCONFDIR = $(KEYBOARD_PATH_1)
else ifneq ("$(wildcard $(TOP_DIR)/platforms/chibios/$(BOARD)/configs/chconf.h)","")
CHCONFDIR = $(TOP_DIR)/platforms/chibios/$(BOARD)/configs
+else ifneq ("$(wildcard $(TOP_DIR)/platforms/chibios/common/configs/chconf.h)","")
+ CHCONFDIR = $(TOP_DIR)/platforms/chibios/common/configs
endif
ifneq ("$(wildcard $(KEYBOARD_PATH_5)/halconf.h)","")
@@ -137,6 +139,8 @@ else ifneq ("$(wildcard $(KEYBOARD_PATH_1)/halconf.h)","")
HALCONFDIR = $(KEYBOARD_PATH_1)
else ifneq ("$(wildcard $(TOP_DIR)/platforms/chibios/$(BOARD)/configs/halconf.h)","")
HALCONFDIR = $(TOP_DIR)/platforms/chibios/$(BOARD)/configs
+else ifneq ("$(wildcard $(TOP_DIR)/platforms/chibios/common/configs/halconf.h)","")
+ HALCONFDIR = $(TOP_DIR)/platforms/chibios/common/configs
endif
# HAL-OSAL files (optional).
@@ -183,8 +187,8 @@ else ifneq ("$(wildcard $(KEYBOARD_PATH_2)/ld/$(MCU_LDSCRIPT).ld)","")
LDSCRIPT = $(KEYBOARD_PATH_2)/ld/$(MCU_LDSCRIPT).ld
else ifneq ("$(wildcard $(KEYBOARD_PATH_1)/ld/$(MCU_LDSCRIPT).ld)","")
LDSCRIPT = $(KEYBOARD_PATH_1)/ld/$(MCU_LDSCRIPT).ld
-else ifneq ("$(wildcard $(TOP_DIR)/platforms/chibios/ld/$(MCU_LDSCRIPT).ld)","")
- LDSCRIPT = $(TOP_DIR)/platforms/chibios/ld/$(MCU_LDSCRIPT).ld
+else ifneq ("$(wildcard $(TOP_DIR)/platforms/chibios/common/ld/$(MCU_LDSCRIPT).ld)","")
+ LDSCRIPT = $(TOP_DIR)/platforms/chibios/common/ld/$(MCU_LDSCRIPT).ld
else ifneq ("$(wildcard $(STARTUPLD_CONTRIB)/$(MCU_LDSCRIPT).ld)","")
LDSCRIPT = $(STARTUPLD_CONTRIB)/$(MCU_LDSCRIPT).ld
USE_CHIBIOS_CONTRIB = yes
@@ -209,6 +213,8 @@ CHIBISRC := $(patsubst $(TOP_DIR)/%,%,$(CHIBISRC))
EXTRAINCDIRS += $(CHIBIOS)/os/license $(CHIBIOS)/os/oslib/include \
$(TOP_DIR)/platforms/chibios/$(BOARD)/configs \
+ $(TOP_DIR)/platforms/chibios/common/configs \
+ $(HALCONFDIR) $(CHCONFDIR) \
$(STARTUPINC) $(KERNINC) $(PORTINC) $(OSALINC) \
$(HALINC) $(PLATFORMINC) $(BOARDINC) $(TESTINC) \
$(STREAMSINC) $(CHIBIOS)/os/various $(COMMON_VPATH)