[
  {
    "path": ".gitattributes",
    "content": "# Auto detect text files and perform LF normalization\n* text=auto\n\n# Custom for Visual Studio\n*.cs     diff=csharp\n\n# Standard to msysgit\n*.doc\t diff=astextplain\n*.DOC\t diff=astextplain\n*.docx diff=astextplain\n*.DOCX diff=astextplain\n*.dot  diff=astextplain\n*.DOT  diff=astextplain\n*.pdf  diff=astextplain\n*.PDF\t diff=astextplain\n*.rtf\t diff=astextplain\n*.RTF\t diff=astextplain\n"
  },
  {
    "path": ".gitignore",
    "content": "# Windows image file caches\nThumbs.db\nehthumbs.db\n\n# Folder config file\nDesktop.ini\n\n# Recycle Bin used on file shares\n$RECYCLE.BIN/\n\n# Windows Installer files\n*.cab\n*.msi\n*.msm\n*.msp\n\n# Windows shortcuts\n*.lnk\n\n# =========================\n# Operating System Files\n# =========================\n\n# OSX\n# =========================\n\n.DS_Store\n.AppleDouble\n.LSOverride\n\n# Thumbnails\n._*\n\n# Files that might appear on external disk\n.Spotlight-V100\n.Trashes\n\n# Directories potentially created on remote AFP share\n.AppleDB\n.AppleDesktop\nNetwork Trash Folder\nTemporary Items\n.apdisk\n"
  },
  {
    "path": "CubeMX2Makefile.py",
    "content": "#!/usr/bin/env python\n\nimport sys\nimport re\nimport shutil\nimport os\nimport os.path\nimport string\nimport xml.etree.ElementTree\n\n# Return codes\nC2M_ERR_SUCCESS             =  0\nC2M_ERR_INVALID_COMMANDLINE = -1\nC2M_ERR_LOAD_TEMPLATE       = -2\nC2M_ERR_NO_PROJECT          = -3\nC2M_ERR_PROJECT_FILE        = -4\nC2M_ERR_IO                  = -5\nC2M_ERR_NEED_UPDATE         = -6\n\n# Configuration\n\n# STM32 MCU to compiler flags.\nmcu_regex_to_cflags_dict = {\n    'STM32(F|L)0': '-mthumb -mcpu=cortex-m0',\n    'STM32(F|L)1': '-mthumb -mcpu=cortex-m3',\n    'STM32(F|L)2': '-mthumb -mcpu=cortex-m3',\n    'STM32(F|L)3': '-mthumb -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard',\n    'STM32(F|L)4': '-mthumb -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard',\n    'STM32(F|L)7': '-mthumb -mcpu=cortex-m7 -mfpu=fpv4-sp-d16 -mfloat-abi=hard',\n}\n\ndef main():\n    \n    if len(sys.argv) != 2:\n        sys.stderr.write(\"\\nSTM32CubeMX project to Makefile V2.0\\n\")\n        sys.stderr.write(\"-==================================-\\n\")\n        sys.stderr.write(\"Initially written by Baoshi <mail\\x40ba0sh1.com> on 2015-02-22\\n\")\n        sys.stderr.write(\"Updated 2017-04-27 for STM32CubeMX 4.20.1 http://www.st.com/stm32cube\\n\")\n        sys.stderr.write(\"Refer to history.txt for contributors, thanks!\\n\")\n        sys.stderr.write(\"Apache License 2.0 <http://www.apachstme3w2e.org/licenses/LICENSE-2.0>\\n\")\n        sys.stderr.write(\"\\nUsage:\\n\")\n        sys.stderr.write(\"  CubeMX2Makefile.py <SW4STM32 project folder>\\n\")\n        sys.exit(C2M_ERR_INVALID_COMMANDLINE)\n\n    # Load template files\n    app_folder_path = os.path.dirname(os.path.abspath(sys.argv[0]))\n    template_file_path = os.path.join(app_folder_path, 'CubeMX2Makefile.tpl')\n    try:\n        with open(template_file_path, 'r') as f:\n            makefile_template = string.Template(f.read())\n    except EnvironmentError as e:\n        sys.stderr.write(\"Unable to read template file: {}. Error: {}\".format(template_file_path, str(e)))\n        sys.exit(C2M_ERR_LOAD_TEMPLATE)\n\n    proj_folder_path = os.path.abspath(sys.argv[1])\n    if not os.path.isdir(proj_folder_path):\n        sys.stderr.write(\"STM32CubeMX \\\"Toolchain Folder Location\\\" not found: {}\\n\".format(proj_folder_path))\n        sys.exit(C2M_ERR_INVALID_COMMANDLINE)\n\n    proj_name = os.path.splitext(os.path.basename(proj_folder_path))[0]\n    ac6_project_path = os.path.join(proj_folder_path,'.project')\n    ac6_cproject_path = os.path.join(proj_folder_path,'.cproject')\n    if not (os.path.isfile(ac6_project_path) and os.path.isfile(ac6_cproject_path)):\n        sys.stderr.write(\"SW4STM32 project not found, use STM32CubeMX to generate a SW4STM32 project first\\n\")\n        sys.exit(C2M_ERR_NO_PROJECT)\n\n\n    ctx = []\n\n    c_set = {}\n    c_set['source_endswith'] = '.c'\n    c_set['source_subst'] = 'C_SOURCES ='\n    c_set['inc_endswith'] = '.h'\n    c_set['inc_subst'] = 'C_INCLUDES ='\n    c_set['first'] = True\n    c_set['relpath_stored'] = ''\n    ctx.append(c_set)\n\n    asm_set = {}\n    asm_set['source_endswith'] = '.s'\n    asm_set['source_subst'] = 'ASM_SOURCES ='\n    asm_set['inc_endswith'] = '.inc'\n    asm_set['inc_subst'] = 'AS_INCLUDES ='\n    asm_set['first'] = True\n    asm_set['relpath_stored'] = ''\n    ctx.append(asm_set)\n\n    for path, dirs, files in os.walk(proj_folder_path):\n        for file in files:\n            for s in ctx:\n\n                if file.endswith(s['source_endswith']):\n                    s['source_subst'] += ' \\\\\\n  '\n                    relpath = os.path.relpath(path,proj_folder_path)\n\n                    #Split Windows style paths into tokens\n                    #Unix style path emit a single token\n                    relpath_split = relpath.split('\\\\')\n                    for path_tok in relpath_split:\n                        #Last token does not have a trailing slash\n                        if path_tok == relpath_split[0]:\n                            s['source_subst'] += path_tok\n                        else:\n                            s['source_subst'] += '/' + path_tok\n                    s['source_subst'] += '/' + file\n\n                if file.endswith(s['inc_endswith']):\n                    relpath = os.path.relpath(path,proj_folder_path)\n\n                    #only include a path once\n                    if relpath != s['relpath_stored']:\n                        s['relpath_stored'] = relpath\n\n                        #If this is the first include, we already have the 'C_INCLUDES ='\n                        if s['first']:\n                            s['first'] = False\n                            s['inc_subst'] += ' -I'\n                        else:\n                            s['inc_subst'] += '\\nC_INCLUDES += -I'\n\n                        #Split Windows style paths into tokens\n                        #Unix style path emit a single token\n                        relpath_split = relpath.split('\\\\')\n                        for path_tok in relpath_split:\n                            #Last token does not have a trailing slash\n                            if path_tok == relpath_split[0]:\n                                s['inc_subst'] += path_tok\n                            else:\n                                s['inc_subst'] += '/' + path_tok         \n                    \n    # .cproject file\n    try:\n        tree = xml.etree.ElementTree.parse(ac6_cproject_path)\n    except Exception as e:\n        sys.stderr.write(\"Unable to parse SW4STM32 .cproject file: {}. Error: {}\\n\".format(ac6_cproject_path, str(e)))\n        sys.exit(C2M_ERR_PROJECT_FILE)\n    conf = tree.find('.//configuration[@name=\"Debug\"]')\n\n    # MCU\n    try:\n        mcu_node = conf.find('.//option[@name=\"Mcu\"]')\n        mcu_str = mcu_node.attrib.get('value')\n        #sys.stdout.write(\"For MCU: {}\\n\".format(mcu_str))\n    except Exception as e:\n        sys.stderr.write(\"Unable to find target MCU node. Error: {}\\n\".format(str(e)))\n        sys.exit(C2M_ERR_PROJECT_FILE)\n    for mcu_regex_pattern, cflags in mcu_regex_to_cflags_dict.items():\n        if re.match(mcu_regex_pattern, mcu_str):\n            cflags_subst = cflags\n            ld_subst = cflags\n            break\n    else:\n        sys.stderr.write(\"Unknown MCU: {}\\n\".format(mcu_str))\n        sys.stderr.write(\"Please contact author for an update of this utility.\\n\")\n        sys.stderr.exit(C2M_ERR_NEED_UPDATE)\n\n    # AS symbols\n    as_defs_subst = 'AS_DEFS ='\n\n    # C symbols\n    c_defs_subst = 'C_DEFS ='\n    c_def_node_list = conf.findall('.//tool[@name=\"MCU GCC Compiler\"]/option[@valueType=\"definedSymbols\"]/listOptionValue')\n    for c_def_node in c_def_node_list:\n        c_def_str = c_def_node.attrib.get('value')\n        if c_def_str:\n            c_defs_subst += ' -D{}'.format(re.sub(r'([()])', r'\\\\\\1', c_def_str))\n\n    # Link script\n    ld_script_node = conf.find('.//tool[@name=\"MCU GCC Linker\"]/option[@superClass=\"fr.ac6.managedbuild.tool.gnu.cross.c.linker.script\"]')\n    try:\n        ld_script_path = ld_script_node.attrib.get('value')\n    except Exception as e:\n        sys.stderr.write(\"Unable to find link script. Error: {}\\n\".format(str(e)))\n        sys.exit(C2M_ERR_PROJECT_FILE)\n    ld_script_name = os.path.basename(ld_script_path)\n    ld_script_subst = 'LDSCRIPT = {}'.format(ld_script_name)\n\n# Specs\n    specs_node = conf.find('.//tool[@name=\"MCU GCC Linker\"]/option[@superClass=\"gnu.c.link.option.ldflags\"]')\n    try:\n        specs = specs_node.attrib.get('value')\n    except Exception as e:\n        sys.stderr.write(\"Unable to find link specs. Error: {}\\n\".format(str(e)))\n        sys.exit(C2M_ERR_PROJECT_FILE)\n    specs_subst = specs\n    \n    makefile_str = makefile_template.substitute(\n        TARGET = proj_name,\n        MCU = cflags_subst,\n        LDMCU = ld_subst,\n        C_SOURCES = c_set['source_subst'],\n        ASM_SOURCES = asm_set['source_subst'],\n        AS_DEFS = as_defs_subst,\n        AS_INCLUDES = asm_set['inc_subst'],\n        C_DEFS = c_defs_subst,\n        C_INCLUDES = c_set['inc_subst'],\n        LDSCRIPT = ld_script_subst,\n        SPECS = specs_subst)\n\n    makefile_path = os.path.join(proj_folder_path, 'Makefile')\n    try:\n        with open(makefile_path, 'wb') as f:\n            f.write(makefile_str)\n    except EnvironmentError as e:\n        sys.stderr.write(\"Unable to write Makefile: {}. Error: {}\\n\".format(makefile_path, str(e)))\n        sys.exit(C2M_ERR_IO)\n\n    sys.stdout.write(\"Makefile created: {}\\n\".format(makefile_path))\n    \n    sys.exit(C2M_ERR_SUCCESS)\n\n\ndef fix_path(p):\n    return re.sub(r'^..(\\\\|/)..(\\\\|/)..(\\\\|/)', '', p.replace('\\\\', os.path.sep))\n\n\nif __name__ == '__main__':\n    main()\n"
  },
  {
    "path": "CubeMX2Makefile.tpl",
    "content": "######################################\n# Makefile by CubeMX2Makefile.py\n######################################\n\n######################################\n# target\n######################################\nTARGET = $TARGET\n\n######################################\n# building variables\n######################################\n# debug build?\nDEBUG = 1\n# optimization\nOPT = -O0\n\n#######################################\n# pathes\n#######################################\n# Build path\nBUILD_DIR = build\n\n######################################\n# source\n######################################\n$C_SOURCES  \n$ASM_SOURCES\n\n#######################################\n# binaries\n#######################################\nCC = arm-none-eabi-gcc\nAS = arm-none-eabi-gcc -x assembler-with-cpp\nCP = arm-none-eabi-objcopy\nAR = arm-none-eabi-ar\nSZ = arm-none-eabi-size\nHEX = $$(CP) -O ihex\nBIN = $$(CP) -O binary -S\n \n#######################################\n# CFLAGS\n#######################################\n# macros for gcc\n$AS_DEFS\n$C_DEFS\n# includes for gcc\n$AS_INCLUDES\n$C_INCLUDES\n# compile gcc flags\nASFLAGS = $MCU $$(AS_DEFS) $$(AS_INCLUDES) $$(OPT) -Wall -fdata-sections -ffunction-sections\nCFLAGS = $MCU $$(C_DEFS) $$(C_INCLUDES) $$(OPT) -Wall -fdata-sections -ffunction-sections\nifeq ($$(DEBUG), 1)\nCFLAGS += -g -gdwarf-2\nendif\n# Generate dependency information\nCFLAGS += -std=c99 -MD -MP -MF $$(BUILD_DIR)/.dep/$$(@F).d\n\n#######################################\n# LDFLAGS\n#######################################\n# link script\n$LDSCRIPT\n# libraries\nLIBS =\nLIBDIR =\nLDFLAGS = $LDMCU $SPECS -T$$(LDSCRIPT) $$(LIBDIR) $$(LIBS) -Wl,-Map=$$(BUILD_DIR)/$$(TARGET).map,--cref -Wl,--gc-sections\n\n# default action: build all\nall: $$(BUILD_DIR)/$$(TARGET).elf $$(BUILD_DIR)/$$(TARGET).hex $$(BUILD_DIR)/$$(TARGET).bin\n\n#######################################\n# build the application\n#######################################\n# list of objects\nOBJECTS = $$(addprefix $$(BUILD_DIR)/,$$(notdir $$(C_SOURCES:.c=.o)))\nvpath %.c $$(sort $$(dir $$(C_SOURCES)))\n# list of ASM program objects\nOBJECTS += $$(addprefix $$(BUILD_DIR)/,$$(notdir $$(ASM_SOURCES:.s=.o)))\nvpath %.s $$(sort $$(dir $$(ASM_SOURCES)))\n\n$$(BUILD_DIR)/%.o: %.c Makefile | $$(BUILD_DIR) \n\t$$(CC) -c $$(CFLAGS) -Wa,-a,-ad,-alms=$$(BUILD_DIR)/$$(notdir $$(<:.c=.lst)) $$< -o $$@\n\n$$(BUILD_DIR)/%.o: %.s Makefile | $$(BUILD_DIR)\n\t$$(AS) -c $$(CFLAGS) $$< -o $$@\n\n$$(BUILD_DIR)/$$(TARGET).elf: $$(OBJECTS) Makefile\n\t$$(CC) $$(OBJECTS) $$(LDFLAGS) -o $$@\n\t$$(SZ) $$@\n\n$$(BUILD_DIR)/%.hex: $$(BUILD_DIR)/%.elf | $$(BUILD_DIR)\n\t$$(HEX) $$< $$@\n\t\n$$(BUILD_DIR)/%.bin: $$(BUILD_DIR)/%.elf | $$(BUILD_DIR)\n\t$$(BIN) $$< $$@\t\n\t\n$$(BUILD_DIR):\n\tmkdir -p $$@/.dep\n\n#######################################\n# clean up\n#######################################\nclean:\n\t-rm -fR $$(BUILD_DIR)\n  \n#######################################\n# dependencies\n#######################################\n-include $$(shell mkdir -p $$(BUILD_DIR)/.dep 2>/dev/null) $$(wildcard $$(BUILD_DIR)/.dep/*)\n\n.PHONY: clean all\n\n# *** EOF ***\n"
  },
  {
    "path": "history.txt",
    "content": "2015-02-22: V1.0\nInitial release, based on STM32CubeMX 4.6.0\n\n2015-10-03: V1.5\nUpdated with STM32CubeMX 4.10.1\nUse SW4STM32 instead of TrueStudio\n\n2015-10-04:\nDelete obsolete CubeMX2LD.tpl\nFor Linux users (thanks to xaionaro) \nCubeMX2Makefile.py now uses UNIX format (so you can execute directly under Linux)\nFix link script path issue\nST has some upper/lower case issues in their source code which prevent the code to be compiled under Linux. These has to be fixed manually.\n\n2016-02-24:\nMerge PR from rogerdahl (Better Python and fix stray '\\'s)\nUpdate for STM32CubeMX 4.13.0\n\n2016-05-13:\nUpdate for STM32CubeMX 4.14.0 (ST removed all source reference in project file)\nMerge PR from mmprestine and madcowswe (Walk the project folder for source files)\n \n2016-07-14:\nMerged PR from madcowswe (again) for STM32CubeMX 4.15.1 changes.\n\n2017-04-24\nMerged PRs\nUpdate for STM32CubeMX 4.20.1\n"
  },
  {
    "path": "readme.md",
    "content": "# STM32CubeMX to Makefile\n\n## With the release of STM32CubeMX 4.21.0, generating Makefile (which is very similar to my template) is natively supported. I will retire this utility unless ST changes their mind.\n\nThis program generates a Makefile from STM32CubeMX (http://www.st.com/stm32cube) created project. It is intended to be used along with GNU Make utility (www.gnu.org/software/make) and GNU tools for ARM (https://launchpad.net/gcc-arm-embedded) to compile STM32 firmware. Refer to my blog post http://www.ba0sh1.com/opensource-stm32-development for setup of integrated development environment.  \n\nCopyright (c) 2016, Baoshi Zhu. All rights reserved.\n\nSource code in this project is governed by Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)\n"
  }
]