STM32GENERIC/tools/script/generate_build_define.py

411 lines
16 KiB
Python
Raw Normal View History

2017-04-09 21:53:07 -07:00
# This file is a mess, but does the job
import xml.etree.ElementTree as ET
import os.path
from os import listdir
import sys
import re
cubemx_dir = 'D:\programs\STM32Cube\STM32CubeMX'
stm32_dir = '../../STM32/cores/arduino/stm32/'
system_dir = '../../STM32/system/'
header_lines = []
with open(system_dir + 'STM32F0/CMSIS_Inc/stm32f0xx.h') as f:
header_lines.extend(f.readlines())
with open(system_dir + 'STM32F1/CMSIS_Inc/stm32f1xx.h') as f:
header_lines.extend(f.readlines())
with open(system_dir + 'STM32F2/CMSIS_Inc/stm32f2xx.h') as f:
header_lines.extend(f.readlines())
with open(system_dir + 'STM32F3/CMSIS_Inc/stm32f3xx.h') as f:
header_lines.extend(f.readlines())
with open(system_dir + 'STM32F4/CMSIS_Inc/stm32f4xx.h') as f:
header_lines.extend(f.readlines())
with open(system_dir + 'STM32F7/CMSIS_Inc/stm32f7xx.h') as f:
header_lines.extend(f.readlines())
with open(system_dir + 'STM32L0/CMSIS_Inc/stm32l0xx.h') as f:
header_lines.extend(f.readlines())
with open(system_dir + 'STM32L1/CMSIS_Inc/stm32l1xx.h') as f:
header_lines.extend(f.readlines())
with open(system_dir + 'STM32L4/CMSIS_Inc/stm32l4xx.h') as f:
header_lines.extend(f.readlines())
def find_header(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
2017-04-10 21:30:57 -07:00
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
#if not include:
# raise Exception(name)
2017-04-09 21:53:07 -07:00
return include
families_xml = os.path.join(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")
2017-04-14 12:37:01 -07:00
def natural_sort_key(s, _nsre=re.compile('([0-9]+)')):
return [int(text) if text.isdigit() else text.lower()
for text in re.split(_nsre, s)]
2017-04-09 21:53:07 -07:00
class load_mcu:
def __init__(self, name):
print name
self.mcu_name = name
if families.find(".//Mcu[@RefName='" + self.mcu_name + "Tx']") is not None:
self.mcu_xml = families.find(".//Mcu[@RefName='" + self.mcu_name + "Tx']").attrib['Name'] + '.xml'
else:
self.mcu_xml = families.find(".//Mcu[@RPN='" + self.mcu_name + "']").attrib['Name'] + '.xml'
self.mcu = ET.parse(os.path.join(cubemx_dir, 'db', 'mcu', self.mcu_xml)).getroot()
self.remap_xml = 'GPIO-' + self.mcu.find("stm:IP[@Name='GPIO']", ns).attrib['Version'] + '_Modes.xml'
self.remap_root = ET.parse(os.path.join(cubemx_dir, 'db', 'mcu', 'IP', self.remap_xml )).getroot()
self.mcu_pins = self.mcu.findall('stm:Pin', ns);
self.available_pin_signals = {}
2017-04-09 21:53:07 -07:00
self.remaps = {}
self.defaultremaps = {}
self.af_functions=[]
self.af_function_used=[]
2017-04-09 21:53:07 -07:00
self.pins = []
self.peripherals = []
self.groups = {}
self.group_signals = {}
def load_rcc(self):
self.rcc_xml = 'RCC-' + self.mcu.find("stm:IP[@Name='RCC']", ns).attrib['Version'] + '_Modes.xml'
self.rcc_root = ET.parse(os.path.join(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 = []
2017-04-09 21:53:07 -07:00
def find_remaps(self):
for pin_element in self.mcu.findall('stm:Pin', ns):
for signal_element in pin_element.findall('stm:Signal', ns):
pin = pin_element.attrib['Name']
instance_signal = signal_element.attrib['Name']
self.available_pin_signals.setdefault(pin, []).append(instance_signal)
2017-04-09 21:53:07 -07:00
for pin in self.remap_root.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']
2017-04-09 21:53:07 -07:00
if pin_name not in self.available_pin_signals or instance_signal not in self.available_pin_signals[pin_name]:
continue
instance = instance_signal.split('_')[0]
if instance_signal not in self.remaps:
self.remaps[instance_signal] = {}
2017-04-09 21:53:07 -07:00
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.defaultremaps[instance_signal] = pin_name
2017-04-09 21:53:07 -07:00
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.defaultremaps:
self.defaultremaps[instance_signal] = pin_name
2017-04-09 21:53:07 -07:00
self.remaps[instance_signal][pin_name] = remap_function
2017-04-09 21:53:07 -07:00
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.remaps[instance_signal][pin_name] = gpio_af.find("stm:PossibleValue", ns).text
2017-04-09 21:53:07 -07:00
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('ADC1') \
and not instance_signal.startswith('ADC_') \
and not instance_signal.startswith('I2S') \
and not instance_signal.startswith('SDIO') \
and not instance_signal.startswith('SDMMC'):
2017-04-09 21:53:07 -07:00
continue
(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():
periph = instance[:-1]
else:
periph = instance
if instance not in self.peripherals:
self.peripherals.append(instance)
2017-04-09 21:53:07 -07:00
self.groups.setdefault(periph, []).append(sig)
2017-04-09 21:53:07 -07:00
self.group_signals.setdefault(periph + '_' + sig, []).append(instance_signal)
2017-04-09 21:53:07 -07:00
if instance_signal not in self.defaultremaps:
self.defaultremaps[instance_signal] = pin_name
2017-04-09 21:53:07 -07:00
if instance_signal not in self.remaps:
self.remaps[instance_signal] = {}
self.remaps[instance_signal][pin_name] = 'AF_NO_REMAP'
2017-04-09 21:53:07 -07:00
def generate_source_code(self):
self.peripherals.sort()
self.af_functions.sort()
source_code = '';
source_code = '//Autogenerated file\n'
source_code += '//MCU name: ' + self.mcu_name+ '\n'
source_code += '//MCU xml: ' + self.mcu_xml+ '\n'
source_code += '//GPIO remap/alternate function xml: ' + self.remap_xml+ '\n'
source_code += '\n'
gpio_pins = [pin for pin in self.pins if pin.startswith('P') and pin != 'PDR_ON']
2017-05-30 08:57:48 -07:00
source_code += '\n'
source_code += '#define VARIANT_PIN_LIST_DEFAULT \\\n'
2017-05-30 20:51:21 -07:00
self.default_pin_list = '#define CHIP_PIN_LIST';
2017-04-09 21:53:07 -07:00
for pin in sorted(gpio_pins, key=lambda x: (x[0:2], int(x[2:]))):
2017-05-30 08:57:48 -07:00
source_code += ' PIN(' + pin[1] + ',' + pin[2:] + '), \\\n'
2017-05-30 20:51:21 -07:00
self.default_pin_list += ' PIN(' + pin[1] + ',' + pin[2:] + '),'
self.default_pin_list += '\n'
2017-04-09 21:53:07 -07:00
source_code += '\n'
2017-05-30 08:57:48 -07:00
source_code += '\n'
2017-04-09 21:53:07 -07:00
periph_source_code = "";
2017-04-15 01:25:11 -07:00
2017-04-09 21:53:07 -07:00
for periph in sorted(self.groups):
periph_source_code += '\n'
periph_source_code += '// --------------------' + periph + '--------------------'
periph_source_code += '\n'
if 'SDIO' in periph:
periph_source_code += '#define STM32_CHIP_HAS_SDIO'
periph_source_code += '\n'
if 'I2S' in periph:
periph_source_code += '#define STM32_CHIP_HAS_I2S'
periph_source_code += '\n'
2017-04-09 21:53:07 -07:00
for sig in sorted(set(self.groups[periph])):
if 'SDIO' not in periph and 'I2S' not in periph and sig not in ['SDA', 'SCL', 'TX', 'RX', 'MISO', 'MOSI', 'SCK', 'NSS']:
2017-04-09 21:53:07 -07:00
continue
if 'I2S' == periph and sig == 'CKIN':
continue
periph_source_code += '\n'
periph_source_code += 'const stm32_af_pin_list_type chip_af_'+(periph + '_' + sig).lower()+' [] = {\n'
2017-04-09 21:53:07 -07:00
#print self.group_signals
old = False
for signal in sorted(set(self.group_signals[periph + '_' +sig])):
if old != signal.split('_')[0]:
periph_source_code += '//' + signal.split('_')[0] + '\n'
2017-04-09 21:53:07 -07:00
p = signal.split('_')[0]
2017-04-14 12:37:01 -07:00
for pin in sorted(set(self.remaps[signal]), key = natural_sort_key):
2017-04-09 21:53:07 -07:00
if pin in self.pins:
remap = self.remaps[signal][pin]
self.af_function_used.append(remap)
2017-04-09 21:53:07 -07:00
split = signal.split('_')
p = split[0]
p = p.replace('I2S', 'SPI');
periph_source_code += ' { ' + p.ljust(6) + ', GPIO' + pin[1:2] + ', GPIO_PIN_' + pin[2:].ljust(3) + ', ' + remap.ljust(15) + '}, \n'
2017-04-09 21:53:07 -07:00
periph_source_code += '}; \n'
periph_source_code += '\n'
if len(self.af_functions) > 0:
source_code += 'static void AF_NO_REMAP (void) { }\n'
for af_function in self.af_functions:
if af_function in self.af_function_used:
source_code += 'static void ' + af_function + '(void) { ' + af_function[2:] + '(); }\n'
source_code += periph_source_code
2017-04-15 01:25:11 -07:00
source_code += 'const stm32_chip_adc1_channel_type chip_adc1_channel[] = {\n'
for instance_signal in sorted(self.defaultremaps.keys(), key = natural_sort_key):
if 'ADC1_IN' not in instance_signal and 'ADC_IN' not in instance_signal:
continue
(_, channel) = instance_signal.split('_', 1)
if not channel[2:].isdigit():
continue
2017-04-15 01:25:11 -07:00
pin = self.defaultremaps[instance_signal]
source_code += ' { GPIO' + pin[1:2] + ', GPIO_PIN_' + pin[2:].ljust(3) + ', ADC_CHANNEL_' + channel[2:].ljust(3) + '}, \n'
source_code += '};\n'
source_code += '\n'
source_code += 'const stm32_clock_freq_list_type chip_clock_freq_list[] = {\n'
for periph in sorted(self.PCLK1_PERIPHERALS):
if not periph.startswith('USART') and not periph.startswith('SPI') and not periph.startswith('I2C'):
continue
2017-04-09 21:53:07 -07:00
if periph not in self.peripherals:
continue
2017-04-15 01:25:11 -07:00
source_code += ' {' + periph.ljust(6) + ', HAL_RCC_GetPCLK1Freq }, \n'
source_code += '\n'
for periph in sorted(self.PCLK2_PERIPHERALS):
if not periph.startswith('USART') and not periph.startswith('SPI') and not periph.startswith('I2C'):
continue
if periph not in self.peripherals:
continue
2017-04-09 21:53:07 -07:00
2017-04-15 01:25:11 -07:00
source_code += ' {' + periph.ljust(6) + ', HAL_RCC_GetPCLK2Freq }, \n'
2017-04-09 21:53:07 -07:00
source_code += '};\n'
source_code += '\n'
2017-04-09 21:53:07 -07:00
dir = system_dir + name[:7] + "/stm32_chip/"
with open(dir + 'stm32_' + self.mcu_name + '.h', 'w') as file:
file.write(source_code)
with open(stm32_dir + 'stm32_build_defines.h', 'w') as file:
file.write('//Autogenerated file\n')
file.write('\n')
file.write('#ifndef STM32_BUILD_DEFINES_H\n')
file.write('#define STM32_BUILD_DEFINES_H\n')
file.write('\n')
name_processed = []
2017-04-10 21:30:57 -07:00
file.write('#if __IGNORE\n')
2017-04-09 21:53:07 -07:00
for mcu in mcus:
name = mcu.attrib['RefName']
name = name[:11]
if name in name_processed:
continue
name_processed.append(name)
dir = system_dir + name[:7] + "/CMSIS_Inc/"
#filename = name.lower()
define = find_header(name)
if not define:
continue
2017-04-09 21:53:07 -07:00
file.write('\n');
2017-04-10 21:30:57 -07:00
file.write('#elif defined(' + name + ')\n')
file.write(' #define ' + define + ' 1\n')
2017-04-09 21:53:07 -07:00
file.write(' #define CMSIS_STARTUP_ASSEMBLY "startup_' + define.lower() + '.s"\n')
file.write(' #define CHIP_PERIPHERAL_INCLUDE "stm32_' + name + '.h"\n')
mcu = load_mcu(name)
mcu.load_rcc()
2017-04-09 21:53:07 -07:00
mcu.find_remaps()
mcu.process_pins()
mcu.generate_source_code()
2017-05-30 20:51:21 -07:00
file.write(' ' + mcu.default_pin_list)
2017-04-10 21:30:57 -07:00
file.write('#else \n')
file.write('#error UNKNOWN CHIP \n')
file.write('#endif\n')
2017-04-09 21:53:07 -07:00
file.write('\n')
file.write('#endif')