Skip to content
This repository has been archived by the owner on Sep 29, 2019. It is now read-only.

Added support STM32CubeMX v4.20.0 #4

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ build/
test/__pycache__
cubemx2cmake/__pycache__
cubemx2cmake/__init__.pyc
cubemx2cmake/command_line.pyc
cubemx2cmake/command_line.pyc
189 changes: 174 additions & 15 deletions cubemx2cmake/command_line.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,58 @@
""" This is the implementation of cubemx2cmake command """

import shutil
import os.path
import string
import sys
import os
import re
from argparse import ArgumentParser
from configparser import ConfigParser
from string import Template
from pkg_resources import resource_filename
from xml.etree import ElementTree

with open('.cproject', 'rt') as f:
tree = ElementTree.parse(f)


def getDef():
definition = ""
for node in tree.iter('cconfiguration'):
for opt in node.iter('option'):
if(opt.attrib.get('superClass') == 'gnu.c.compiler.option.preprocessor.def.symbols'):
for listOpt in opt.iter('listOptionValue'):
value = ""
if listOpt.attrib.get('value').find('weak') != -1:
value = '\'-D' + listOpt.attrib.get('value') + '\''
elif listOpt.attrib.get('value').find('packed') != -1:
value = '\'-D' + listOpt.attrib.get('value') + '\''
else:
value = '-D' + listOpt.attrib.get('value')
definition += 'add_definitions('+ value +')\n'
break
return definition

# Return codes
C2M_ERR_SUCCESS = 0
C2M_ERR_INVALID_COMMANDLINE = -1
C2M_ERR_LOAD_TEMPLATE = -2
C2M_ERR_NO_PROJECT = -3
C2M_ERR_PROJECT_FILE = -4
C2M_ERR_IO = -5
C2M_ERR_NEED_UPDATE = -6

# Configuration

# STM32 MCU to compiler flags.
mcu_regex_to_cflags_dict = {
'STM32(F|L)0': '-mcpu=cortex-m0',
'STM32(F|L)1': '-mcpu=cortex-m3',
'STM32(F|L)2': '-mcpu=cortex-m3',
'STM32(F|L)3': '-mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard',
'STM32(F|L)4': '-mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard',
'STM32(F|L)7': '-mcpu=cortex-m7 -mfpu=fpv4-sp-d16 -mfloat-abi=hard',
}

def main():
""" Function entry point for running script from command line """
Expand All @@ -15,17 +61,124 @@ def main():

def _main(args):
""" Runnable code with CLI args for testing convenience"""
architecture = {
"STM32L0xx": "-mcpu=cortex-m0",
"STM32F0xx": "-mcpu=cortex-m0",
"STM32L1xx": "-mcpu=cortex-m3",
"STM32F1xx": "-mcpu=cortex-m3",
"STM32F2xx": "-mcpu=cortex-m3",
"STM32L4xx": "-mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16",
"STM32F3xx": "-mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16",
"STM32F4xx": "-mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16",
"STM32F7xx": "-mcpu=cortex-m7 -mfloat-abi=hard -mfpu=fpv5-sp-d16"
}
proj_folder_path = os.path.abspath('.')
if not os.path.isdir(proj_folder_path):
sys.stderr.write("STM32CubeMX \"Toolchain Folder Location\" not found: {}\n".format(proj_folder_path))
sys.exit(C2M_ERR_INVALID_COMMANDLINE)

proj_name = os.path.splitext(os.path.basename(proj_folder_path))[0]
ac6_project_path = os.path.join(proj_folder_path,'.project')
ac6_cproject_path = os.path.join(proj_folder_path,'.cproject')
if not (os.path.isfile(ac6_project_path) and os.path.isfile(ac6_cproject_path)):
sys.stderr.write("SW4STM32 project not found, use STM32CubeMX to generate a SW4STM32 project first\n")
sys.exit(C2M_ERR_NO_PROJECT)


ctx = []

c_set = {}
c_set['source_endswith'] = '.c'
c_set['source_subst'] = ''
c_set['inc_endswith'] = '.h'
c_set['inc_subst'] = ''
c_set['first'] = True
c_set['relpath_stored'] = ''
ctx.append(c_set)

asm_set = {}
asm_set['source_endswith'] = '.s'
asm_set['source_subst'] = ''
asm_set['inc_endswith'] = '.inc'
asm_set['inc_subst'] = 'AS_INCLUDES='
asm_set['first'] = True
asm_set['relpath_stored'] = ''
ctx.append(asm_set)

for path, dirs, files in os.walk(proj_folder_path):
for file in files:
for s in ctx:

if file.endswith(s['source_endswith']):
s['source_subst'] += ' '
relpath = os.path.relpath(path,proj_folder_path)

#Split Windows style paths into tokens
#Unix style path emit a single token
relpath_split = relpath.split('\\')
for path_tok in relpath_split:
#Last token does not have a trailing slash
if path_tok == relpath_split[0]:
s['source_subst'] += path_tok
else:
s['source_subst'] += '/' + path_tok
s['source_subst'] += '/' + file

if file.endswith(s['inc_endswith']):
relpath = os.path.relpath(path,proj_folder_path)

#only include a path once
if relpath != s['relpath_stored']:
s['relpath_stored'] = relpath

#If this is the first include, we already have the 'C_INCLUDES ='
if s['first']:
s['first'] = False
s['inc_subst'] += ''
else:
s['inc_subst'] += ' '


#Split Windows style paths into tokens
#Unix style path emit a single token
relpath_split = relpath.split('\\')
for path_tok in relpath_split:
#Last token does not have a trailing slash
if path_tok == relpath_split[0]:
s['inc_subst'] += path_tok
else:
s['inc_subst'] += '/' + path_tok

# .cproject file
root = tree.getroot()

# MCU
mcu_node = root.find('.//toolChain/option[@superClass="fr.ac6.managedbuild.option.gnu.cross.mcu"][@name="Mcu"]')
try:
mcu_str = mcu_node.attrib.get('value')
except Exception as e:
sys.stderr.write("Unable to find target MCU node. Error: {}\n".format(str(e)))
sys.exit(C2M_ERR_PROJECT_FILE)
for mcu_regex_pattern, cflags in mcu_regex_to_cflags_dict.items():
if re.match(mcu_regex_pattern, mcu_str):
cflags_subst = cflags
ld_subst = cflags
break
else:
sys.stderr.write("Unknown MCU: {}\n".format(mcu_str))
sys.stderr.write("Please contact author for an update of this utility.\n")
sys.stderr.exit(C2M_ERR_NEED_UPDATE)

# AS symbols
as_defs_subst = 'AS_DEFS ='

# C symbols
c_defs_subst = 'C_DEFS ='
c_def_node_list = root.findall('.//tool/option[@valueType="definedSymbols"]/listOptionValue')
for c_def_node in c_def_node_list:
c_def_str = c_def_node.attrib.get('value')
if c_def_str:
c_defs_subst += ' -D{}'.format(c_def_str)

# Link script
ld_script_node_list = root.find('.//tool/option[@superClass="fr.ac6.managedbuild.tool.gnu.cross.c.linker.script"]')
try:
ld_script_path = ld_script_node_list.attrib.get('value')
except Exception as e:
sys.stderr.write("Unable to find link script. Error: {}\n".format(str(e)))
sys.exit(C2M_ERR_PROJECT_FILE)
ld_script_name = os.path.basename(ld_script_path)
ld_script_subst = ld_script_name


arg_parser = ArgumentParser()
arg_parser.add_argument("cube_file", default="", nargs='?',
Expand Down Expand Up @@ -73,6 +226,7 @@ def _main(args):
mcu_family = cube_config["mcu.family"]
mcu_username = cube_config["mcu.username"]
prj_name = cube_config["projectmanager.projectname"]
make_defination = getDef()
except KeyError:
print("Input file is broken!")
exit(0)
Expand All @@ -81,12 +235,16 @@ def _main(args):
"PRJ_NAME": prj_name,
"MCU_FAMILY": mcu_family+"xx",
"MCU_LINE": mcu_username[:9]+"x"+cube_config["mcu.name"][13],
"MCU_LINKER_SCRIPT": mcu_username+"_FLASH.ld",
"MCU_ARCH": architecture[mcu_family+"xx"],
"MCU_LINKER_SCRIPT": ld_script_subst,
"MCU_ARCH": cflags_subst,
"TARGET": mcu_family+"x",
"INTERFACE_NAME": args.interface,
"GDB_PORT": args.gdb_port,
"TELNET_PORT": args.telnet_port
"TELNET_PORT": args.telnet_port,
"MAKE_DEFINATION": make_defination,
"MCU_SOURCE": c_set['source_subst'] + ' ' + asm_set['source_subst'],
"MCU_INCLUDE_FOLDER": c_set['inc_subst'],
"MCU_INCLUDE_H": c_set['inc_subst'].replace(' ' , '/*.h ')
}

templates = os.listdir(resource_filename(__name__, "templates"))
Expand All @@ -96,7 +254,7 @@ def _main(args):
with open(template_fn, "r") as template_file:
template = Template(template_file.read())
try:
with open(template_name, "w") as target_file:
with open(template_name.replace(".template",""), "w") as target_file:
target_file.write(template.safe_substitute(params))
except IOError:
print("Cannot write output files! Maybe write access to the current directory is denied.")
Expand All @@ -105,3 +263,4 @@ def _main(args):
print("All files were successfully generated!")

return params

29 changes: 11 additions & 18 deletions cubemx2cmake/templates/CMakeLists.txt.template
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,21 @@ cmake_minimum_required(VERSION 3.6)

project(${PRJ_NAME} C ASM)

add_definitions(-D${MCU_LINE})
add_definitions(-DUSE_HAL_LIBRARY)
${MAKE_DEFINATION}

set(USER_INCLUDE Inc)
set(CMSIS_DEVICE_INCLUDE Drivers/CMSIS/Device/ST/${MCU_FAMILY}/Include)
set(CMSIS_INCLUDE Drivers/CMSIS/Include)
set(HAL_INCLUDE Drivers/${MCU_FAMILY}_HAL_Driver/Inc)

file(GLOB_RECURSE USER_INCLUDE_F ${USER_INCLUDE}/*.h)
file(GLOB_RECURSE CMSIS_DEVICE_INCLUDE_F ${CMSIS_DEVICE_INCLUDE}/*.h)
file(GLOB_RECURSE CMSIS_INCLUDE_F ${CMSIS_INCLUDE}/*.h)
file(GLOB_RECURSE HAL_INCLUDE_F ${HAL_INCLUDE}/*.h)
file(GLOB_RECURSE USER_INCLUDE_F ${MCU_INCLUDE_H}/*.h)

file(GLOB_RECURSE USER_SOURCES Src/*.c)
file(GLOB_RECURSE HAL_SOURCES Drivers/${MCU_FAMILY}_HAL_DRIVER/Src/*.c)
file(GLOB_RECURSE CMSIS_SYSTEM Drivers/CMSIS/Device/ST/${MCU_FAMILY}/Source/Templates/system_${MCU_FAMILY}.c)
file(GLOB_RECURSE CMSIS_STARTUP Drivers/CMSIS/Device/ST/${MCU_FAMILY}/Source/Templates/gcc/startup_${MCU_LINE}.s)

set(SOURCE_FILES ${USER_SOURCES} ${HAL_SOURCES} ${CMSIS_SYSTEM} ${CMSIS_STARTUP} ${MCU_LINKER_SCRIPT}
${USER_INCLUDE_F} ${CMSIS_DEVICE_INCLUDE_F} ${CMSIS_INCLUDE_F} ${HAL_INCLUDE_F})
file(GLOB_RECURSE USER_SOURCES ${MCU_SOURCE})


set(SOURCE_FILES ${USER_SOURCES} ${MCU_LINKER_SCRIPT}
${USER_INCLUDE_F} )


include_directories(${MCU_INCLUDE_FOLDER})

include_directories(${USER_INCLUDE} ${CMSIS_DEVICE_INCLUDE} ${CMSIS_INCLUDE} ${HAL_INCLUDE})

add_executable(${PROJECT_NAME}.elf ${SOURCE_FILES})

Expand All @@ -47,4 +40,4 @@ add_custom_target(flash
COMMAND openocd -f openocd_flash.cfg
COMMENT "Flashing the target processor..."
DEPENDS ${PROJECT_NAME}.elf)
add_custom_command(TARGET flash POST_BUILD COMMENT "Flashing finished!")
add_custom_command(TARGET flash POST_BUILD COMMENT "Flashing finished!")
1 change: 1 addition & 0 deletions cubemx2cmake/templates/openocd_flash.cfg.template
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ reset init
halt
flash write_image erase build/${PRJ_NAME}.bin ${FLASH_START}
verify_image build/${PRJ_NAME}.bin ${FLASH_START}
reset run
shutdown
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ def readme():

setup(
name='cubemx2cmake',
version='1.2',
version='1.3',
description='Command line tool to generate CMakeLists.txt from STM32CubeMX projects.',
long_description=readme(),
classifiers=[
Expand Down