1- import sys
2- import re
3- import os
1+ import argparse
42import datetime
3+ import fnmatch
54import json
5+ import os
6+ import re
7+ import sys
8+ import textwrap
69from xml .dom import minidom
710from xml .dom .minidom import parse , Node
8- io_list = [] #'PIN','name'
11+ from argparse import RawTextHelpFormatter
12+ mcu_file = ""
13+ mcu_list = [] #'name'
14+ io_list = [] #'PIN','name'
915adclist = [] #'PIN','name','ADCSignal'
1016daclist = [] #'PIN','name','DACSignal'
1117i2cscl_list = [] #'PIN','name','I2CSCLSignal'
2430eth_list = [] #'PIN','name','ETH'
2531qspi_list = [] #'PIN','name','QUADSPI'
2632
27-
2833def find_gpio_file (xmldoc ):
2934 res = 'ERROR'
3035 itemlist = xmldoc .getElementsByTagName ('IP' )
@@ -35,7 +40,7 @@ def find_gpio_file(xmldoc):
3540 return res
3641
3742def get_gpio_af_num (xml , pintofind , iptofind ):
38- if 'STM32F10' in sys . argv [ 2 ] :
43+ if 'STM32F10' in mcu_file :
3944 return get_gpio_af_numF1 (xml , pintofind , iptofind )
4045# xml = parse('GPIO-STM32L051_gpio_v1_0_Modes.xml')
4146 #xml = parse(gpiofile)
@@ -397,7 +402,7 @@ def print_uart(xml, l):
397402 #2nd element is the UART_XX signal
398403 b = p [2 ].split ('_' )[0 ]
399404 s1 += "%-9s" % (b [:len (b )- 1 ] + b [len (b )- 1 :] + ',' )
400- if 'STM32F10' in sys . argv [ 2 ] and l == uartrx_list :
405+ if 'STM32F10' in mcu_file and l == uartrx_list :
401406 s1 += 'STM_PIN_DATA(STM_MODE_INPUT, GPIO_PULLUP, '
402407 else :
403408 s1 += 'STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, '
@@ -447,7 +452,7 @@ def print_can(xml, l):
447452 instance = p [2 ].split ('_' )[0 ].replace ("CAN" , "" )
448453 if len (instance ) == 0 :
449454 instance = '1'
450- if 'STM32F10' in sys . argv [ 2 ] and l == canrd_list :
455+ if 'STM32F10' in mcu_file and l == canrd_list :
451456 s1 += 'CAN' + instance + ', STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, '
452457 else :
453458 s1 += 'CAN' + instance + ', STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, '
@@ -541,32 +546,35 @@ def sort_my_lists():
541546
542547 return
543548
544- # START MAIN PROGRAM
549+ def clean_all_lists ():
550+ del io_list [:]
551+ del adclist [:]
552+ del daclist [:]
553+ del i2cscl_list [:]
554+ del i2csda_list [:]
555+ del pwm_list [:]
556+ del uarttx_list [:]
557+ del uartrx_list [:]
558+ del uartcts_list [:]
559+ del uartrts_list [:]
560+ del spimosi_list [:]
561+ del spimiso_list [:]
562+ del spissel_list [:]
563+ del spisclk_list [:]
564+ del cantd_list [:]
565+ del canrd_list [:]
566+ del eth_list [:]
567+ del qspi_list [:]
568+
569+ # main
545570cur_dir = os .getcwd ()
546571out_filename = 'PeripheralPins.c'
547572config_filename = 'config.json'
548573
549- if len (sys .argv ) < 3 :
550- print ("Usage: " + sys .argv [0 ] + " <BOARD_NAME> <product xml file name>" )
551- print (" - <BOARD_NAME> is the name of the board as it will be named in mbed" )
552- print (" - <product xml file name> is the STM32 file description in Cube MX" )
553- print (" !!This xml file contains non alpha characters in its name, you should call it with quotes" )
554- print ("" )
555- print (" This script is able to generate the %s for a specific board" % out_filename )
556- print (" After file generation, review it carefully and " )
557- print (" please report any issue to github:" )
558- print (" https://github.com/fpistm/stm32_tools/issues" )
559- print ("" )
560- print (" Once generated, you should comment a line if the pin is generated " )
561- print (" several times for the same IP" )
562- print (" or if the pin should not be used (overlaid with some HW on the board, " )
563- print (" for instance)" )
564- quit ()
565-
566574try :
567575 config_file = open (config_filename , "r" )
568576except IOError :
569- print ("Please set your configuration in %s file" % config_filename )
577+ print ("Please set your configuration in '%s' file" % config_filename )
570578 config_file = open (config_filename , "w" )
571579 if sys .platform .startswith ('win32' ):
572580 print ("Platform is Windows" )
@@ -588,84 +596,119 @@ def sort_my_lists():
588596config_file .close ()
589597cubemxdir = config ["CUBEMX_DIRECTORY" ]
590598
591- cubemxdirIP = os .path .join (cubemxdir , 'IP' )
592- input_file_name = os .path .join (cubemxdir , sys .argv [2 ])
593- out_path = os .path .join (cur_dir , 'Arduino' , sys .argv [1 ])
594- output_filename = os .path .join (out_path , out_filename )
599+ # by default, generate for all mcu xml files description
600+ parser = argparse .ArgumentParser (
601+ description = textwrap .dedent ('''\
602+ By default, generate %s for all xml files description available in
603+ STM32CubeMX directory defined in '%s':
604+ \t %s''' % (out_filename , config_filename , cubemxdir )),
605+ epilog = textwrap .dedent ('''\
606+ After files generation, review them carefully and please report any issue to github:
607+ \t https://github.com/stm32duino/Arduino_Tools/issues\n
608+ Once generated, you have to comment a line if the pin is generated several times
609+ for the same IP or if the pin should not be used (overlaid with some HW on the board,
610+ for instance)''' ),
611+ formatter_class = RawTextHelpFormatter )
612+ group = parser .add_mutually_exclusive_group ()
613+ group .add_argument ("-l" , "--list" , help = "list available xml files description in STM32CubeMX" , action = "store_true" )
614+ group .add_argument ("-m" , "--mcu" , metavar = 'xml' , help = textwrap .dedent ('''\
615+ Generate %s for specified mcu xml file description
616+ in STM32CubeMX. This xml file contains non alpha characters in
617+ its name, you should call it with double quotes''' % out_filename ))
618+ args = parser .parse_args ()
595619
596- #check input file exists
597620if not (os .path .isdir (cubemxdir )):
598621 print ("\n ! ! ! Cube Mx seems not to be installed or not at the requested location" )
599- print ("\n ! ! ! please check the value you set for cubemxdir variable at the top of " + sys .argv [0 ] + " file" )
600- quit ()
601- if not (os .path .isfile (input_file_name )):
602- print ('\n ! ! ! ' + sys .argv [2 ] + ' file not found' )
603- print ("\n ! ! ! Check in " + cubemxdir + " the correct name of this file" )
604- print ("\n ! ! ! You may use double quotes for this file if it contains special characters" )
622+ print ("\n ! ! ! please check the value you set for 'CUBEMX_DIRECTORY' in '%s' file" % config_filename )
605623 quit ()
606624
607- #open input file
608- print (" * * * Opening input file..." )
609- if not (os .path .isdir (out_path )):
610- os .makedirs (out_path )
611- xmldoc = minidom .parse (input_file_name )
612- itemlist = xmldoc .getElementsByTagName ('Pin' )
613- #open output file
614- if (os .path .isfile (output_filename )):
615- print (" * * * * Requested %s file already exists and will be overwritten" % out_filename )
616- os .remove (output_filename )
617-
618- out_file = open (output_filename , 'w' )
619-
620- gpiofile = find_gpio_file (xmldoc )
621- if gpiofile == 'ERROR' :
625+ cubemxdirIP = os .path .join (cubemxdir , 'IP' )
626+
627+ if args .mcu :
628+ #check input file exists
629+ if not (os .path .isfile (os .path .join (cubemxdir , args .mcu ))):
630+ print ("\n ! ! ! " + args .mcu + " file not found" )
631+ print ("\n ! ! ! Check in " + cubemxdir + " the correct name of this file" )
632+ print ("\n ! ! ! You may use double quotes for this file if it contains special characters" )
633+ quit ()
634+ mcu_list .append (args .mcu )
635+ else :
636+ mcu_list = fnmatch .filter (os .listdir (cubemxdir ), 'STM32*.xml' )
637+
638+ if args .list :
639+ print ("Available xml files description: %i" % len (mcu_list ))
640+ for f in mcu_list :
641+ print (f )
622642 quit ()
623- xml = parse (os .path .join (cubemxdirIP , 'GPIO-' + gpiofile + '_Modes.xml' ))
624- print (" * * * Getting pins and Ips for the xml file..." )
625- pinregex = r'^(P[A-Z][0-9][0-5]?)'
626- for s in itemlist :
627- m = re .match (pinregex , s .attributes ['Name' ].value )
628- if m :
629- pin = m .group (0 )[:2 ] + '_' + m .group (0 )[2 :] # pin formatted P<port>_<number>: PF_O
630- name = s .attributes ['Name' ].value .strip () # full name: "PF0 / OSC_IN"
631- if s .attributes ['Type' ].value == "I/O" :
632- store_pin (pin , name )
633- else :
634- continue
635- siglist = s .getElementsByTagName ('Signal' )
636- for a in siglist :
637- sig = a .attributes ['Name' ].value .strip ()
638- if "ADC" in sig :
639- #store ADC pin
640- store_adc (pin , name , sig )
641- if all (["DAC" in sig , "_OUT" in sig ]):
642- #store DAC
643- store_dac (pin , name , sig )
644- if "I2C" in sig :
645- #store DAC
646- store_i2c (pin , name , sig )
647- if re .match ('^TIM' , sig ) is not None : #ignore HRTIM
648- #store PWM
649- store_pwm (pin , name , sig )
650- if re .match ('^(LPU|US|U)ART' , sig ) is not None :
651- store_uart (pin , name , sig )
652- if "SPI" in sig :
653- store_spi (pin , name , sig )
654- if "CAN" in sig :
655- store_can (pin , name , sig )
656- if "ETH" in sig :
657- store_eth (pin , name , sig )
658- if "QUADSPI" in sig :
659- store_qspi (pin , name , sig )
660-
661- print (" * * * Sorting lists..." )
662- sort_my_lists ()
663-
664- print (" * * * Printing lists..." )
665- print_header ()
666- print_all_lists ()
667- out_file .close ()
668-
669- nb_pin = (len (io_list ))
670- print ("nb of I/O pins: %i" % nb_pin )
671- print ('\n * * * ' + sys .argv [1 ]+ ' OK' )
643+
644+ for mcu_file in mcu_list :
645+ print ("Generate %s for '%s'" % (out_filename , mcu_file ))
646+ input_file_name = os .path .join (cubemxdir , mcu_file )
647+ out_path = os .path .join (cur_dir , 'Arduino' , os .path .splitext (mcu_file )[0 ])
648+ output_filename = os .path .join (out_path , out_filename )
649+ if not (os .path .isdir (out_path )):
650+ os .makedirs (out_path )
651+
652+ #open input file
653+ #print (" * * * Opening input file...")
654+ xmldoc = minidom .parse (input_file_name )
655+ itemlist = xmldoc .getElementsByTagName ('Pin' )
656+ #open output file
657+ if (os .path .isfile (output_filename )):
658+ #print (" * * * * Requested %s file already exists and will be overwritten" % out_filename)
659+ os .remove (output_filename )
660+
661+ out_file = open (output_filename , 'w' )
662+
663+ gpiofile = find_gpio_file (xmldoc )
664+ if gpiofile == 'ERROR' :
665+ print ("Could not find GPIO file" )
666+ quit ()
667+
668+ xml = parse (os .path .join (cubemxdirIP , 'GPIO-' + gpiofile + '_Modes.xml' ))
669+ print (" * * * Getting pins and Ips for the xml file..." )
670+ pinregex = r'^(P[A-Z][0-9][0-5]?)'
671+ for s in itemlist :
672+ m = re .match (pinregex , s .attributes ['Name' ].value )
673+ if m :
674+ pin = m .group (0 )[:2 ] + '_' + m .group (0 )[2 :] # pin formatted P<port>_<number>: PF_O
675+ name = s .attributes ['Name' ].value .strip () # full name: "PF0 / OSC_IN"
676+ if s .attributes ['Type' ].value == "I/O" :
677+ store_pin (pin , name )
678+ else :
679+ continue
680+ siglist = s .getElementsByTagName ('Signal' )
681+ for a in siglist :
682+ sig = a .attributes ['Name' ].value .strip ()
683+ if "ADC" in sig :
684+ store_adc (pin , name , sig )
685+ if all (["DAC" in sig , "_OUT" in sig ]):
686+ store_dac (pin , name , sig )
687+ if "I2C" in sig :
688+ store_i2c (pin , name , sig )
689+ if re .match ('^TIM' , sig ) is not None : #ignore HRTIM
690+ store_pwm (pin , name , sig )
691+ if re .match ('^(LPU|US|U)ART' , sig ) is not None :
692+ store_uart (pin , name , sig )
693+ if "SPI" in sig :
694+ store_spi (pin , name , sig )
695+ if "CAN" in sig :
696+ store_can (pin , name , sig )
697+ if "ETH" in sig :
698+ store_eth (pin , name , sig )
699+ if "QUADSPI" in sig :
700+ store_qspi (pin , name , sig )
701+
702+ #print (" * * * Sorting lists...")
703+ sort_my_lists ()
704+
705+ #print (" * * * Printing lists...")
706+ print_header ()
707+ print_all_lists ()
708+
709+ nb_pin = (len (io_list ))
710+ print ("nb of I/O pins: %i" % nb_pin )
711+ print ('\n * * * ' + mcu_file + ' OK' )
712+ clean_all_lists ()
713+
714+ out_file .close ()
0 commit comments