3
3
import json
4
4
import re
5
5
import string
6
+ import subprocess
6
7
import sys
7
8
import textwrap
8
9
from argparse import RawTextHelpFormatter
@@ -303,7 +304,7 @@ def print_periph_header():
303
304
s = """{}
304
305
/*
305
306
* Automatically generated from {}
306
- * CubeMX DB version {} release {}
307
+ * CubeMX DB release {}
307
308
*/
308
309
#include "Arduino.h"
309
310
#include "{}.h"
@@ -322,8 +323,7 @@ def print_periph_header():
322
323
""" .format (
323
324
license_header ,
324
325
mcu_file .name ,
325
- cubemx_db_version ,
326
- cubemx_db_release ,
326
+ db_release ,
327
327
re .sub ("\\ .c$" , "" , periph_c_filename ),
328
328
)
329
329
periph_c_file .write (s )
@@ -1332,59 +1332,160 @@ def parse_pins():
1332
1332
store_sd (pin , name , sig )
1333
1333
1334
1334
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
+
1335
1444
# main
1336
1445
cur_dir = Path .cwd ()
1337
1446
templates_dir = cur_dir / "templates"
1338
1447
periph_c_filename = "PeripheralPins.c"
1339
1448
pinvar_h_filename = "PinNamesVar.h"
1340
- config_filename = "config.json"
1449
+ config_filename = Path ( "config.json" )
1341
1450
variant_h_filename = "variant.h"
1342
1451
variant_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"
1343
1457
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 ()
1370
1459
1371
1460
# By default, generate for all mcu xml files description
1372
1461
parser = argparse .ArgumentParser (
1373
1462
description = textwrap .dedent (
1374
1463
"""\
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 ,
1379
1480
)
1380
1481
),
1381
1482
epilog = textwrap .dedent (
1382
1483
"""\
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 :
1384
1485
\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. """
1388
1489
),
1389
1490
formatter_class = RawTextHelpFormatter ,
1390
1491
)
@@ -1401,48 +1502,84 @@ def parse_pins():
1401
1502
metavar = "xml" ,
1402
1503
help = textwrap .dedent (
1403
1504
"""\
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
1408
1525
)
1409
1526
),
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" ,
1410
1534
)
1411
1535
args = parser .parse_args ()
1412
1536
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
+ )
1418
1554
)
1419
- )
1420
- quit ()
1555
+ quit ()
1421
1556
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 ))
1435
1572
1436
1573
if 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 ()):
1439
1576
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" )
1441
1578
print ("\n You may use double quotes for file containing special characters" )
1442
1579
quit ()
1443
- mcu_list .append (cubemxdirMCU / args .mcu )
1580
+ mcu_list .append (dirMCU / args .mcu )
1444
1581
else :
1445
- mcu_list = cubemxdirMCU .glob ("STM32*.xml" )
1582
+ mcu_list = dirMCU .glob ("STM32*.xml" )
1446
1583
1447
1584
if args .list :
1448
1585
print ("Available xml files description:" )
@@ -1457,15 +1594,7 @@ def parse_pins():
1457
1594
)
1458
1595
1459
1596
for 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 ))
1469
1598
out_path = cur_dir / "Arduino" / mcu_file .name [:7 ] / mcu_file .stem
1470
1599
periph_c_filepath = out_path / periph_c_filename
1471
1600
periph_h_filepath = out_path / pinvar_h_filename
@@ -1489,7 +1618,7 @@ def parse_pins():
1489
1618
if gpiofile == "ERROR" :
1490
1619
print ("Could not find GPIO file" )
1491
1620
quit ()
1492
- xml_gpio = parse (str (cubemxdirIP / ("GPIO-" + gpiofile + "_Modes.xml" )))
1621
+ xml_gpio = parse (str (dirIP / ("GPIO-" + gpiofile + "_Modes.xml" )))
1493
1622
1494
1623
parse_pins ()
1495
1624
sort_my_lists ()
0 commit comments