2017-07-15 09:06:09 -07:00
|
|
|
import xml.etree.ElementTree as ET
|
|
|
|
import os.path
|
|
|
|
from os import listdir
|
|
|
|
import sys
|
|
|
|
import re
|
|
|
|
import json
|
|
|
|
|
|
|
|
import config
|
|
|
|
|
|
|
|
header_lines = []
|
|
|
|
|
|
|
|
for serie in ['f0', 'f1', 'f2', 'f3', 'f4', 'f7', 'l0', 'l1', 'l4']:
|
|
|
|
with open(config.system_dir + 'STM32' + serie.upper() + '/CMSIS_Inc/stm32' + serie + 'xx.h') as f:
|
|
|
|
header_lines.extend(f.readlines())
|
|
|
|
|
|
|
|
# Returns product line for a chip: STM32F103CB -> STM32F103xB
|
|
|
|
def get_productline_for_include(name):
|
|
|
|
include = False
|
|
|
|
define = False
|
|
|
|
for line in header_lines:
|
|
|
|
if '/* #define' in line:
|
|
|
|
define = line[line.index('#define ')+8:][:11]
|
|
|
|
|
|
|
|
if '#endif' in line:
|
|
|
|
define = False
|
|
|
|
|
|
|
|
if not define:
|
|
|
|
continue
|
|
|
|
|
|
|
|
if (name in line):
|
|
|
|
include = define
|
|
|
|
break
|
|
|
|
if ((name[:-2] + "x" + name[-1:]) in line):
|
|
|
|
include = define
|
|
|
|
break
|
|
|
|
|
|
|
|
if not include:
|
|
|
|
define = False
|
|
|
|
for line in header_lines:
|
|
|
|
if '/* #define' in line:
|
|
|
|
define = line[line.index('#define ')+8:][:11]
|
|
|
|
|
|
|
|
if '#endif' in line:
|
|
|
|
define = False
|
|
|
|
|
|
|
|
if not define:
|
|
|
|
continue
|
|
|
|
|
|
|
|
if ((name[:-2] + "xx") in line):
|
|
|
|
include = define
|
|
|
|
break
|
|
|
|
|
|
|
|
return include
|
|
|
|
|
|
|
|
|
|
|
|
families_xml = os.path.join(config.cubemx_dir, 'db', 'mcu', 'families.xml')
|
|
|
|
if not os.path.exists(families_xml):
|
|
|
|
print 'Could not find CubeMX, please set CubeMX directory'
|
|
|
|
exit(-1)
|
|
|
|
families = ET.parse(families_xml).getroot()
|
|
|
|
ns = {'stm': 'http://mcd.rou.st.com/modules.php?name=mcu'}
|
|
|
|
|
|
|
|
mcus = families.findall(".//Mcu")
|
|
|
|
|
|
|
|
xml_cache = {}
|
|
|
|
|
|
|
|
def load_xml(path):
|
|
|
|
if path in xml_cache:
|
|
|
|
return xml_cache[path]
|
|
|
|
|
|
|
|
ret = ET.parse(path)
|
|
|
|
xml_cache[path] = ret
|
|
|
|
return ret
|
|
|
|
|
|
|
|
class load_mcu:
|
|
|
|
def __init__(self, name):
|
|
|
|
self.mcu_name = name
|
|
|
|
|
|
|
|
if families.find(".//Mcu[@RefName='" + self.mcu_name + "Tx']") is not None:
|
|
|
|
self.mcu_xml_filename = families.find(".//Mcu[@RefName='" + self.mcu_name + "Tx']").attrib['Name'] + '.xml'
|
|
|
|
else:
|
|
|
|
self.mcu_xml_filename = families.find(".//Mcu[@RPN='" + self.mcu_name + "']").attrib['Name'] + '.xml'
|
|
|
|
|
|
|
|
self.mcu_xml = load_xml(os.path.join(config.cubemx_dir, 'db', 'mcu', self.mcu_xml_filename)).getroot()
|
|
|
|
self.remap_xml_filename = 'GPIO-' + self.mcu_xml.find("stm:IP[@Name='GPIO']", ns).attrib['Version'] + '_Modes.xml'
|
|
|
|
|
|
|
|
self.remap_xml = load_xml(os.path.join(config.cubemx_dir, 'db', 'mcu', 'IP', self.remap_xml_filename )).getroot()
|
|
|
|
|
|
|
|
self.mcu_pins = self.mcu_xml.findall('stm:Pin', ns);
|
|
|
|
|
|
|
|
self.pin_to_instance_signals = {}
|
|
|
|
|
|
|
|
self.instance_signal_to_pin_to_af = {}
|
|
|
|
self.instance_signal_to_default_pin = {}
|
|
|
|
|
|
|
|
self.af_functions=[]
|
|
|
|
self.af_function_used=[]
|
|
|
|
self.pins = []
|
|
|
|
self.instances = []
|
|
|
|
self.peripheral_to_signals = {}
|
|
|
|
self.peripheral_to_instances = {}
|
|
|
|
self.peripheral_signal_to_instance_signals = {}
|
|
|
|
|
|
|
|
self.load_rcc()
|
|
|
|
self.find_remaps()
|
|
|
|
self.process_pins()
|
|
|
|
|
|
|
|
self.instances.sort()
|
|
|
|
self.af_functions.sort()
|
|
|
|
|
|
|
|
|
|
|
|
def load_rcc(self):
|
|
|
|
self.rcc_xml = 'RCC-' + self.mcu_xml.find("stm:IP[@Name='RCC']", ns).attrib['Version'] + '_Modes.xml'
|
|
|
|
|
|
|
|
self.rcc_root = load_xml(os.path.join(config.cubemx_dir, 'db', 'mcu', 'IP', self.rcc_xml )).getroot()
|
|
|
|
|
|
|
|
pclk1 = self.rcc_root.find(".//stm:RefParameter[@Name='APB1Freq_Value']", ns)
|
|
|
|
pclk2 = self.rcc_root.find("stm:RefParameter[@Name='APB2Freq_Value']", ns)
|
|
|
|
|
|
|
|
if pclk1 is not None:
|
|
|
|
self.PCLK1_PERIPHERALS = pclk1.attrib['IP'].split(',')
|
|
|
|
else:
|
|
|
|
self.PCLK1_PERIPHERALS = []
|
|
|
|
|
|
|
|
if pclk2 is not None:
|
|
|
|
self.PCLK2_PERIPHERALS = pclk2.attrib['IP'].split(',')
|
|
|
|
else:
|
|
|
|
self.PCLK2_PERIPHERALS = []
|
|
|
|
|
|
|
|
def find_remaps(self):
|
|
|
|
for pin_element in self.mcu_xml.findall('stm:Pin', ns):
|
|
|
|
for signal_element in pin_element.findall('stm:Signal', ns):
|
2017-07-15 11:49:50 -07:00
|
|
|
pin_name = pin_element.attrib['Name']
|
|
|
|
pin_name = re.search('^(\D*\d*)', pin_name).group(1)
|
|
|
|
|
2017-07-15 09:06:09 -07:00
|
|
|
instance_signal = signal_element.attrib['Name']
|
|
|
|
|
2017-07-15 11:49:50 -07:00
|
|
|
self.pin_to_instance_signals.setdefault(pin_name, []).append(instance_signal)
|
2017-07-15 09:06:09 -07:00
|
|
|
|
|
|
|
for pin in self.remap_xml.findall('stm:GPIO_Pin', ns):
|
|
|
|
pin_name = pin.attrib['Name']
|
|
|
|
|
|
|
|
pin_name = re.search('^(\D*\d*)', pin_name).group(1)
|
|
|
|
|
|
|
|
gpio_signals = pin.findall('stm:PinSignal', ns)
|
|
|
|
for gpio_signal in gpio_signals:
|
|
|
|
instance_signal = gpio_signal.attrib['Name']
|
|
|
|
|
|
|
|
if pin_name not in self.pin_to_instance_signals or instance_signal not in self.pin_to_instance_signals[pin_name]:
|
|
|
|
continue
|
|
|
|
|
|
|
|
instance = instance_signal.split('_')[0]
|
|
|
|
if instance_signal not in self.instance_signal_to_pin_to_af:
|
|
|
|
self.instance_signal_to_pin_to_af[instance_signal] = {}
|
|
|
|
|
|
|
|
if self.mcu_name.startswith('STM32F1'):
|
|
|
|
remap_function = False
|
|
|
|
|
|
|
|
remap_block = gpio_signal.find('stm:RemapBlock', ns)
|
|
|
|
if remap_block is not None:
|
|
|
|
if 'DefaultRemap' in remap_block.attrib:
|
|
|
|
remap_function = 'AF__HAL_AFIO_REMAP_' + instance + '_DISABLE'
|
|
|
|
self.instance_signal_to_default_pin[instance_signal] = pin_name
|
|
|
|
else:
|
|
|
|
remap_function = 'AF' + remap_block.find('stm:SpecificParameter', ns).find('stm:PossibleValue', ns).text
|
|
|
|
else:
|
|
|
|
remap_function = 'AF__NO_REMAP'
|
|
|
|
if instance_signal not in self.instance_signal_to_default_pin:
|
|
|
|
self.instance_signal_to_default_pin[instance_signal] = pin_name
|
|
|
|
|
|
|
|
self.instance_signal_to_pin_to_af[instance_signal][pin_name] = remap_function
|
|
|
|
if remap_function not in self.af_functions:
|
|
|
|
self.af_functions.append(remap_function)
|
|
|
|
|
|
|
|
else:
|
|
|
|
gpio_af = gpio_signal.find("stm:SpecificParameter[@Name='GPIO_AF']", ns)
|
|
|
|
self.instance_signal_to_pin_to_af[instance_signal][pin_name] = gpio_af.find("stm:PossibleValue", ns).text
|
|
|
|
|
|
|
|
def process_pins(self):
|
|
|
|
for pin in self.mcu_pins:
|
|
|
|
pin_name = pin.attrib['Name']
|
|
|
|
|
|
|
|
pin_name = re.search('^(\D*\d*)', pin_name).group(1)
|
|
|
|
|
|
|
|
self.pins.append(pin_name)
|
|
|
|
|
|
|
|
if not pin.attrib['Type'] == 'I/O':
|
|
|
|
continue
|
|
|
|
|
|
|
|
instance_signal_elements = pin.findall('stm:Signal', ns)
|
|
|
|
for instance_signal_element in instance_signal_elements:
|
|
|
|
instance_signal = instance_signal_element.attrib['Name']
|
|
|
|
|
|
|
|
if not instance_signal.startswith('USART') \
|
|
|
|
and not instance_signal.startswith('SPI') \
|
|
|
|
and not instance_signal.startswith('I2C') \
|
|
|
|
and not instance_signal.startswith('TIM') \
|
|
|
|
and not instance_signal.startswith('ADC') \
|
|
|
|
and not instance_signal.startswith('ADC_') \
|
|
|
|
and not instance_signal.startswith('I2S') \
|
|
|
|
and not instance_signal.startswith('SDIO') \
|
|
|
|
and not instance_signal.startswith('SDMMC'):
|
|
|
|
pass
|
|
|
|
#continue
|
|
|
|
|
|
|
|
if '_' not in instance_signal: continue
|
|
|
|
#if 'ETH' in instance_signal: print instance_signal
|
|
|
|
|
|
|
|
(instance, sig) = instance_signal.split('_', 1)
|
|
|
|
|
|
|
|
if instance == 'SDIO':
|
|
|
|
instance = 'SDIO1'
|
|
|
|
if instance == 'SDMMC1':
|
|
|
|
instance = 'SDIO1'
|
|
|
|
if instance == 'SDMMC2':
|
|
|
|
instance = 'SDIO2'
|
|
|
|
|
|
|
|
if instance[-1].isdigit() and instance[-2].isdigit():
|
|
|
|
periph = instance[:-2]
|
|
|
|
elif instance[-1].isdigit():
|
|
|
|
periph = instance[:-1]
|
|
|
|
else:
|
|
|
|
periph = instance
|
|
|
|
|
|
|
|
if instance not in self.instances:
|
|
|
|
self.instances.append(instance)
|
|
|
|
|
|
|
|
self.peripheral_to_instances.setdefault(periph, [])
|
|
|
|
if instance not in self.peripheral_to_instances[periph]:
|
|
|
|
self.peripheral_to_instances[periph].append(instance)
|
|
|
|
|
|
|
|
self.peripheral_to_signals.setdefault(periph, []).append(sig)
|
|
|
|
|
|
|
|
self.peripheral_signal_to_instance_signals.setdefault(periph + '_' + sig, []).append(instance_signal)
|
|
|
|
|
|
|
|
if instance_signal not in self.instance_signal_to_default_pin:
|
|
|
|
self.instance_signal_to_default_pin[instance_signal] = pin_name
|
|
|
|
|
|
|
|
if instance_signal not in self.instance_signal_to_pin_to_af:
|
|
|
|
self.instance_signal_to_pin_to_af[instance_signal] = {}
|
|
|
|
self.instance_signal_to_pin_to_af[instance_signal][pin_name] = 'AF_NO_REMAP'
|