33import json
44import re
55import string
6+ import subprocess
67import sys
78import textwrap
89from argparse import RawTextHelpFormatter
@@ -303,7 +304,7 @@ def print_periph_header():
303304 s = """{}
304305/*
305306 * Automatically generated from {}
306- * CubeMX DB version {} release {}
307+ * CubeMX DB release {}
307308 */
308309#include "Arduino.h"
309310#include "{}.h"
@@ -322,8 +323,7 @@ def print_periph_header():
322323""" .format (
323324 license_header ,
324325 mcu_file .name ,
325- cubemx_db_version ,
326- cubemx_db_release ,
326+ db_release ,
327327 re .sub ("\\ .c$" , "" , periph_c_filename ),
328328 )
329329 periph_c_file .write (s )
@@ -1332,59 +1332,160 @@ def parse_pins():
13321332 store_sd (pin , name , sig )
13331333
13341334
1335+ # Config management
1336+ def create_config ():
1337+ # Create a Json file for a better path management
1338+ try :
1339+ print ("Please set your configuration in '{}' file" .format (config_filename ))
1340+ config_file = open (config_filename , "w" , newline = "\n " )
1341+ if sys .platform .startswith ("win32" ):
1342+ print ("Platform is Windows" )
1343+ cubemxdir = Path (
1344+ r"C:\Program Files\STMicroelectronics\STM32Cube\STM32CubeMX"
1345+ )
1346+ elif sys .platform .startswith ("linux" ):
1347+ print ("Platform is Linux" )
1348+ cubemxdir = Path .home () / "STM32CubeMX"
1349+ elif sys .platform .startswith ("darwin" ):
1350+ print ("Platform is Mac OSX" )
1351+ cubemxdir = Path (
1352+ "/Applications/STMicroelectronics/STM32CubeMX.app/Contents/Resources"
1353+ )
1354+ else :
1355+ print ("Platform unknown" )
1356+ cubemxdir = "<Set CubeMX install directory>"
1357+ config_file .write (
1358+ json .dumps (
1359+ {
1360+ "CUBEMX_DIRECTORY" : str (cubemxdir ),
1361+ "REPO_LOCAL_PATH" : str (repo_local_path ),
1362+ },
1363+ indent = 2 ,
1364+ )
1365+ )
1366+ config_file .close ()
1367+ except IOError :
1368+ print ("Failed to open " + config_filename )
1369+ exit (1 )
1370+
1371+
1372+ def check_config ():
1373+ global cubemxdir
1374+ global repo_local_path
1375+ global repo_path
1376+
1377+ if config_filename .is_file ():
1378+ try :
1379+ config_file = open (config_filename , "r" )
1380+ config = json .load (config_file )
1381+ config_file .close ()
1382+
1383+ conf = config ["REPO_LOCAL_PATH" ]
1384+ if conf :
1385+ if conf != "" :
1386+ repo_local_path = Path (conf )
1387+ repo_path = repo_local_path / repo_name
1388+ conf = config ["CUBEMX_DIRECTORY" ]
1389+ if conf :
1390+ cubemxdir = Path (conf )
1391+ except IOError :
1392+ print ("Failed to open " + config_filename )
1393+ else :
1394+ create_config ()
1395+
1396+
1397+ def manage_repo ():
1398+ global db_release
1399+ repo_local_path .mkdir (parents = True , exist_ok = True )
1400+
1401+ print ("Updating " + repo_name + "..." )
1402+ try :
1403+ if not args .skip :
1404+ if repo_path .is_dir ():
1405+ # Get new tags from the remote
1406+ git_cmds = [
1407+ ["git" , "-C" , repo_path , "clean" , "-fdx" ],
1408+ ["git" , "-C" , repo_path , "fetch" ],
1409+ ["git" , "-C" , repo_path , "reset" , "--hard" , "origin/master" ],
1410+ ]
1411+ else :
1412+ # Clone it as it does not exists yet
1413+ git_cmds = [["git" , "-C" , repo_local_path , "clone" , gh_url ]]
1414+
1415+ for cmd in git_cmds :
1416+ subprocess .check_output (cmd ).decode ("utf-8" )
1417+ if repo_path .is_dir ():
1418+ # Get tag
1419+ sha1_id = (
1420+ subprocess .check_output (
1421+ ["git" , "-C" , repo_path , "rev-list" , "--tags" , "--max-count=1" ]
1422+ )
1423+ .decode ("utf-8" )
1424+ .strip ()
1425+ )
1426+ version_tag = (
1427+ subprocess .check_output (
1428+ ["git" , "-C" , repo_path , "describe" , "--tags" , sha1_id ]
1429+ )
1430+ .decode ("utf-8" )
1431+ .strip ()
1432+ )
1433+ subprocess .check_output (
1434+ ["git" , "-C" , repo_path , "checkout" , version_tag ],
1435+ stderr = subprocess .DEVNULL ,
1436+ )
1437+ db_release = version_tag
1438+ return True
1439+ except subprocess .CalledProcessError as e :
1440+ print ("Command {} failed with error code {}" .format (e .cmd , e .returncode ))
1441+ return False
1442+
1443+
13351444# main
13361445cur_dir = Path .cwd ()
13371446templates_dir = cur_dir / "templates"
13381447periph_c_filename = "PeripheralPins.c"
13391448pinvar_h_filename = "PinNamesVar.h"
1340- config_filename = "config.json"
1449+ config_filename = Path ( "config.json" )
13411450variant_h_filename = "variant.h"
13421451variant_cpp_filename = "variant.cpp"
1452+ repo_local_path = cur_dir / "repo"
1453+ gh_url = "https://github.com/STMicroelectronics/STM32_open_pin_data"
1454+ repo_name = gh_url .rsplit ("/" , 1 )[- 1 ]
1455+ repo_path = repo_local_path / repo_name
1456+ db_release = "Unknown"
13431457
1344- try :
1345- config_file = open (config_filename , "r" )
1346- except IOError :
1347- print ("Please set your configuration in '{}' file" .format (config_filename ))
1348- config_file = open (config_filename , "w" , newline = "\n " )
1349- if sys .platform .startswith ("win32" ):
1350- print ("Platform is Windows" )
1351- cubemxdir = Path (r"C:\Program Files\STMicroelectronics\STM32Cube\STM32CubeMX" )
1352- elif sys .platform .startswith ("linux" ):
1353- print ("Platform is Linux" )
1354- cubemxdir = Path .home () / "STM32CubeMX"
1355- elif sys .platform .startswith ("darwin" ):
1356- print ("Platform is Mac OSX" )
1357- cubemxdir = Path (
1358- "/Applications/STMicroelectronics/STM32CubeMX.app/Contents/Resources"
1359- )
1360- else :
1361- print ("Platform unknown" )
1362- cubemxdir = "<Set CubeMX install directory>"
1363- config_file .write (json .dumps ({"CUBEMX_DIRECTORY" : str (cubemxdir )}))
1364- config_file .close ()
1365- exit (1 )
1366-
1367- config = json .load (config_file )
1368- config_file .close ()
1369- cubemxdir = Path (config ["CUBEMX_DIRECTORY" ])
1458+ check_config ()
13701459
13711460# By default, generate for all mcu xml files description
13721461parser = argparse .ArgumentParser (
13731462 description = textwrap .dedent (
13741463 """\
1375- By default, generate {} and {} for all xml files description available in
1376- STM32CubeMX directory defined in '{}':
1377- \t {}""" .format (
1378- periph_c_filename , pinvar_h_filename , config_filename , cubemxdir
1464+ By default, generate {}, {}, {} and {}
1465+ for all xml files description available in STM32CubeMX internal database.
1466+ Internal database path must be defined in {}.
1467+ It can be the one from STM32CubeMX directory if defined:
1468+ \t {}
1469+ or the one from GitHub:
1470+ \t {}
1471+
1472+ """ .format (
1473+ periph_c_filename ,
1474+ pinvar_h_filename ,
1475+ variant_cpp_filename ,
1476+ variant_h_filename ,
1477+ config_filename ,
1478+ cubemxdir ,
1479+ gh_url ,
13791480 )
13801481 ),
13811482 epilog = textwrap .dedent (
13821483 """\
1383- After files generation, review them carefully and please report any issue to github :
1484+ After files generation, review them carefully and please report any issue to GitHub :
13841485\t https://github.com/stm32duino/Arduino_Tools/issues\n
1385- Once generated, you have to comment a line if the pin is generated several times
1386- for the same IP or if the pin should not be used (overlaid with some HW on the board,
1387- for instance) """
1486+ Once generated, you can comment a line if the pin should not be used
1487+ (overlaid with some HW on the board, for instance) and update all undefined pins
1488+ in variant. """
13881489 ),
13891490 formatter_class = RawTextHelpFormatter ,
13901491)
@@ -1401,48 +1502,84 @@ def parse_pins():
14011502 metavar = "xml" ,
14021503 help = textwrap .dedent (
14031504 """\
1404- Generate {} and {} for specified mcu xml file description
1405- in STM32CubeMX. This xml file contains non alpha characters in
1406- its name, you should call it with double quotes""" .format (
1407- periph_c_filename , pinvar_h_filename
1505+ Generate {}, {}, {} and {}
1506+ for specified mcu xml file description in STM32CubeMX.
1507+ This xml file can contain non alpha characters in its name,
1508+ you should call it with double quotes""" .format (
1509+ periph_c_filename ,
1510+ pinvar_h_filename ,
1511+ variant_cpp_filename ,
1512+ variant_h_filename ,
1513+ )
1514+ ),
1515+ )
1516+
1517+ parser .add_argument (
1518+ "-c" ,
1519+ "--cube" ,
1520+ help = textwrap .dedent (
1521+ """\
1522+ Use STM32CubeMX internal database. Default use GitHub {} repository.
1523+ """ .format (
1524+ repo_name
14081525 )
14091526 ),
1527+ action = "store_true" ,
1528+ )
1529+ parser .add_argument (
1530+ "-s" ,
1531+ "--skip" ,
1532+ help = "Skip {} clone/fetch" .format (repo_name ),
1533+ action = "store_true" ,
14101534)
14111535args = parser .parse_args ()
14121536
1413- if not (cubemxdir .is_dir ()):
1414- print ("\n Cube Mx seems not to be installed or not at the requested location." )
1415- print (
1416- "\n Please check the value you set for 'CUBEMX_DIRECTORY' in '{}' file." .format (
1417- config_filename
1537+ # Using GitHub repo is the preferred way, CubeMX used as a fallback
1538+ fallback = False
1539+ if not args .cube :
1540+ if manage_repo ():
1541+ dirMCU = repo_path / "mcu"
1542+ dirIP = dirMCU / "IP"
1543+ else :
1544+ fallback = True
1545+ if fallback or args .cube :
1546+ if not (cubemxdir .is_dir ()):
1547+ print (
1548+ """
1549+ Cube Mx seems not to be installed or not at the specified location.
1550+
1551+ Please check the value set for 'CUBEMX_DIRECTORY' in '{}' file.""" .format (
1552+ config_filename
1553+ )
14181554 )
1419- )
1420- quit ()
1555+ quit ()
14211556
1422- cubemxdirMCU = cubemxdir / "db" / "mcu"
1423- cubemxdirIP = cubemxdirMCU / "IP"
1424- version_file = cubemxdir / "db" / "package.xml"
1425- cubemx_db_version = "Unknown"
1426- cubemx_db_release = "Unknown"
1427- xml_file = parse (str (version_file ))
1428- Package_item = xml_file .getElementsByTagName ("Package" )
1429- for item in Package_item :
1430- cubemx_db_version = item .attributes ["DBVersion" ].value
1431- PackDescription_item = xml_file .getElementsByTagName ("PackDescription" )
1432- for item in PackDescription_item :
1433- cubemx_db_release = item .attributes ["Release" ].value
1434- print ("CubeMX DB version {} release {}\n " .format (cubemx_db_version , cubemx_db_release ))
1557+ dirMCU = cubemxdir / "db" / "mcu"
1558+ dirIP = dirMCU / "IP"
1559+ version_file = cubemxdir / "db" / "package.xml"
1560+ if version_file .is_file ():
1561+ xml_file = parse (str (version_file ))
1562+ PackDescription_item = xml_file .getElementsByTagName ("PackDescription" )
1563+ for item in PackDescription_item :
1564+ db_release = item .attributes ["Release" ].value
1565+
1566+ # Process DB release
1567+ release_regex = r".*(\d+.\d+.\d+)$"
1568+ release_match = re .match (release_regex , db_release )
1569+ if release_match :
1570+ db_release = release_match .group (1 )
1571+ print ("CubeMX DB release {}\n " .format (db_release ))
14351572
14361573if args .mcu :
1437- # check input file exists
1438- if not ((cubemxdirMCU / args .mcu ).is_file ()):
1574+ # Check input file exists
1575+ if not ((dirMCU / args .mcu ).is_file ()):
14391576 print ("\n " + args .mcu + " file not found" )
1440- print ("\n Check in " + cubemxdirMCU + " the correct name of this file" )
1577+ print ("\n Check in " + dirMCU + " the correct name of this file" )
14411578 print ("\n You may use double quotes for file containing special characters" )
14421579 quit ()
1443- mcu_list .append (cubemxdirMCU / args .mcu )
1580+ mcu_list .append (dirMCU / args .mcu )
14441581else :
1445- mcu_list = cubemxdirMCU .glob ("STM32*.xml" )
1582+ mcu_list = dirMCU .glob ("STM32*.xml" )
14461583
14471584if args .list :
14481585 print ("Available xml files description:" )
@@ -1457,15 +1594,7 @@ def parse_pins():
14571594)
14581595
14591596for mcu_file in mcu_list :
1460- print (
1461- "Generating {}, {}, {} and {} for '{}'..." .format (
1462- periph_c_filename ,
1463- pinvar_h_filename ,
1464- variant_cpp_filename ,
1465- variant_h_filename ,
1466- mcu_file .name ,
1467- )
1468- )
1597+ print ("Generating files for '{}'..." .format (mcu_file .name ))
14691598 out_path = cur_dir / "Arduino" / mcu_file .name [:7 ] / mcu_file .stem
14701599 periph_c_filepath = out_path / periph_c_filename
14711600 periph_h_filepath = out_path / pinvar_h_filename
@@ -1489,7 +1618,7 @@ def parse_pins():
14891618 if gpiofile == "ERROR" :
14901619 print ("Could not find GPIO file" )
14911620 quit ()
1492- xml_gpio = parse (str (cubemxdirIP / ("GPIO-" + gpiofile + "_Modes.xml" )))
1621+ xml_gpio = parse (str (dirIP / ("GPIO-" + gpiofile + "_Modes.xml" )))
14931622
14941623 parse_pins ()
14951624 sort_my_lists ()
0 commit comments