aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorFabien Poussin <fabien.poussin@gmail.com>2017-05-08 17:20:33 +0200
committerFabien Poussin <fabien.poussin@gmail.com>2017-05-08 17:20:33 +0200
commitb7a700d2d908cbf04f0000d3711a115f2d3070de (patch)
tree60b92052ba9317428cb9f5fa36ad3efaa088c849 /tools
parentfa9b5ac5ae2f6df6b0b861547260fddde3b37830 (diff)
downloadChibiOS-Contrib-b7a700d2d908cbf04f0000d3711a115f2d3070de.tar.gz
ChibiOS-Contrib-b7a700d2d908cbf04f0000d3711a115f2d3070de.tar.bz2
ChibiOS-Contrib-b7a700d2d908cbf04f0000d3711a115f2d3070de.zip
Adding mx2board script
Diffstat (limited to 'tools')
-rw-r--r--tools/board_gpio.tpl53
-rw-r--r--tools/mx2board.py275
2 files changed, 328 insertions, 0 deletions
diff --git a/tools/board_gpio.tpl b/tools/board_gpio.tpl
new file mode 100644
index 0000000..ea72b97
--- /dev/null
+++ b/tools/board_gpio.tpl
@@ -0,0 +1,53 @@
+#ifndef _BOARD_GPIO_H_
+#define _BOARD_GPIO_H_
+
+{% for d, v in defines %}
+#define {{ d }} {{ v }}
+{%- endfor %}
+
+{% for p, v in ports %}
+/* PORT {{p}} */
+#define VAL_GPIO{{p}}_MODER ( \
+ {%- for i in v.MODER %}
+ {{ i }} | \
+ {%- endfor %}
+ 0)
+
+#define VAL_GPIO{{p}}_OTYPER ( \
+ {%- for i in v.OTYPER %}
+ {{ i }} | \
+ {%- endfor %}
+ 0)
+
+#define VAL_GPIO{{p}}_OSPEEDR ( \
+ {%- for i in v.OSPEEDR %}
+ {{ i }} | \
+ {%- endfor %}
+ 0)
+
+#define VAL_GPIO{{p}}_PUPDR ( \
+ {%- for i in v.PUPDR %}
+ {{ i }} | \
+ {%- endfor %}
+ 0)
+
+#define VAL_GPIO{{p}}_ODR ( \
+ {%- for i in v.ODR %}
+ {{ i }} | \
+ {%- endfor %}
+ 0)
+
+#define VAL_GPIO{{p}}_AFRL ( \
+ {%- for i in v.AFRL %}
+ {{ i }} | \
+ {%- endfor %}
+ 0)
+
+#define VAL_GPIO{{p}}_AFRH ( \
+ {%- for i in v.AFRH %}
+ {{ i }} | \
+ {%- endfor %}
+ 0)
+{% endfor %}
+
+#endif \ No newline at end of file
diff --git a/tools/mx2board.py b/tools/mx2board.py
new file mode 100644
index 0000000..6bbd41f
--- /dev/null
+++ b/tools/mx2board.py
@@ -0,0 +1,275 @@
+#!/usr/bin/python
+
+__author__ = 'Fabien Poussin'
+__version__ = '0.2'
+
+
+import re
+from xml.etree import ElementTree as etree
+import argparse
+from jinja2 import Template
+import pprint
+
+pretty_print = pprint.PrettyPrinter(indent=2)
+
+
+def pprint(*kwargs):
+ pretty_print.pprint(kwargs)
+
+PIN_MODE_INPUT = "PIN_MODE_INPUT({0})"
+PIN_MODE_OUTPUT = "PIN_MODE_OUTPUT({0})"
+PIN_MODE_ALTERNATE = "PIN_MODE_ALTERNATE({0})"
+PIN_MODE_ANALOG = "PIN_MODE_ANALOG({0})"
+PIN_ODR_LOW = "PIN_ODR_LOW({0})"
+PIN_ODR_HIGH = "PIN_ODR_HIGH({0})"
+PIN_OTYPE_PUSHPULL = "PIN_OTYPE_PUSHPULL({0})"
+PIN_OTYPE_OPENDRAIN = "PIN_OTYPE_OPENDRAIN({0})"
+PIN_OSPEED_VERYLOW = "PIN_OSPEED_VERYLOW({0})"
+PIN_OSPEED_LOW = "PIN_OSPEED_LOW({0})"
+PIN_OSPEED_MEDIUM = "PIN_OSPEED_MEDIUM({0})"
+PIN_OSPEED_HIGH = "PIN_OSPEED_HIGH({0})"
+PIN_PUPDR_FLOATING = "PIN_PUPDR_FLOATING({0})"
+PIN_PUPDR_PULLUP = "PIN_PUPDR_PULLUP({0})"
+PIN_PUPDR_PULLDOWN = "PIN_PUPDR_PULLDOWN({0})"
+PIN_AFIO_AF = "PIN_AFIO_AF({0}, {1})"
+
+FMT = '{0}'
+FMT_DEF = '({0})'
+
+PIN_CONF_LIST = ['MODER', 'OTYPER', 'OSPEEDR', 'PUPDR', 'ODR']
+PIN_CONF_LIST_AF = ['AFRL', 'AFRH']
+
+DEFAULT_PAD = {"SIGNAL": "UNUSED",
+ "LABEL": "",
+ "MODER": PIN_MODE_ANALOG,
+ "OTYPER": PIN_OTYPE_PUSHPULL,
+ "OSPEEDR": PIN_OSPEED_VERYLOW,
+ "PUPDR": PIN_PUPDR_FLOATING,
+ "ODR": PIN_ODR_HIGH}
+
+PIN_MODE_TRANSLATE = {"GPIO_MODE_AF_PP": PIN_MODE_ALTERNATE,
+ "GPIO_MODE_ANALOG": PIN_MODE_ANALOG,
+ "GPIO_MODE_INPUT": PIN_MODE_INPUT,
+ "GPIO_MODE_OUTPUT": PIN_MODE_OUTPUT,
+ "GPIO_MODE_OUTPUT_PP": PIN_MODE_OUTPUT,
+ "GPIO_MODE_OUTPUT_OD": PIN_MODE_OUTPUT}
+
+PIN_OTYPE_TRANSLATE = {"GPIO_MODE_OUTPUT_PP": PIN_OTYPE_PUSHPULL,
+ "GPIO_MODE_OUTPUT_OD": PIN_OTYPE_OPENDRAIN}
+
+PIN_OSPEED_TRANSLATE = {"GPIO_SPEED_FREQ_LOW": PIN_OSPEED_VERYLOW,
+ "GPIO_SPEED_FREQ_MEDIUM": PIN_OSPEED_LOW,
+ "GPIO_SPEED_FREQ_HIGH": PIN_OSPEED_MEDIUM,
+ "GPIO_SPEED_FREQ_VERY_HIGH": PIN_OSPEED_HIGH
+ }
+
+PIN_PUPDR_TRANSLATE = {"GPIO_NOPULL": PIN_PUPDR_FLOATING,
+ "GPIO_PULLUP": PIN_PUPDR_PULLUP,
+ "GPIO_PULLDOWN": PIN_PUPDR_PULLDOWN}
+
+parser = argparse.ArgumentParser(description='Generate ChibiOS GPIO header file from STM32CubeMX file.')
+parser.add_argument('-g', '--gpio', required=True, type=str)
+parser.add_argument('-b', '--project', required=True, type=str)
+parser.add_argument('-o', '--output', default='board_gpio.h', type=str)
+
+
+def open_xml(filename):
+ # Remove namespace
+ with open(filename, 'r') as xmlfile:
+ xml = re.sub(' xmlns="[^"]+"', '', xmlfile.read(), count=1)
+ return etree.fromstring(xml)
+
+
+def char_range(c1, c2):
+ """Generates the characters from `c1` to `c2`, inclusive."""
+ for c in range(ord(c1), ord(c2)+1):
+ yield chr(c)
+
+
+def read_gpio(filename):
+ gpio = {'ports': {}, 'defaults': {}, 'modes': {}}
+ root = open_xml(filename)
+
+ gpio['defaults']['GPIO_Mode'] = 'GPIO_MODE_ANALOG'
+
+ for modes in root.findall("RefParameter"):
+ try:
+ name = modes.attrib['Name']
+ gpio['defaults'][name] = modes.attrib['DefaultValue']
+ gpio['modes'][name] = []
+ except KeyError as e:
+ continue
+
+ if 'GPIO_' not in name:
+ continue
+
+ for m in modes.findall("PossibleValue"):
+ prop_val = m.attrib['Value']
+ gpio['modes'][name].append(prop_val)
+
+ for pin in root.findall('GPIO_Pin'):
+ try:
+ port = pin.attrib['Name'][1]
+ num = int(pin.attrib['Name'][2:])
+ if port not in gpio['ports']:
+ gpio['ports'][port] = {}
+ if num not in gpio['ports'][port]:
+ gpio['ports'][port][num] = {}
+ except ValueError as e:
+ continue
+
+ for s in pin.findall('PinSignal'):
+ try:
+ af = s.find('SpecificParameter/PossibleValue').text
+ af = int(''.join(af.split('_')[1])[2:])
+ gpio['ports'][port][num][s.attrib['Name']] = af
+ except ValueError as e:
+ print(e)
+ except AttributeError as e:
+ print(e)
+
+ return gpio
+
+
+# Extract signals from IOC
+def read_project(gpio, filename):
+ with open(filename, 'r') as mx_file:
+ tmp = mx_file.readlines()
+ pads = {}
+
+ # Default all pads to analog
+ for p in gpio['ports'].keys():
+ pads[p] = {}
+ for i in range(0, 16):
+ pads[p][i] = DEFAULT_PAD.copy()
+ pads[p][i]['PUPDR'] = PIN_PUPDR_TRANSLATE[gpio['defaults']['GPIO_PuPdOD']]
+ pads[p][i]['OTYPER'] = PIN_OTYPE_TRANSLATE[gpio['defaults']['GPIO_ModeDefaultOutputPP']]
+ pads[p][i]['OSPEEDR'] = PIN_OSPEED_TRANSLATE[gpio['defaults']['GPIO_Speed']]
+
+ for t in tmp:
+ if re.search(r"^P[A-Z]\d{1,2}(-OSC.+)?\.", t, re.M):
+ split = t.split('=')
+ pad_name = split[0].split(".")[0]
+ pad_port = pad_name[1:2]
+ pad_num = int(pad_name[2:4].replace('.', '').replace('-', ''))
+ pad_prop = split[0].split(".")[-1]
+ prop_value = split[-1].rstrip('\r\n')
+
+ if pad_prop == "Signal":
+ if 'S_TIM' in prop_value:
+ prop_value = prop_value[2:]
+
+ if 'ADC' in prop_value or 'DAC' in prop_value or 'OSC' in prop_value:
+ pads[pad_port][pad_num]["MODER"] = PIN_MODE_ANALOG
+ elif 'GPIO_Output' == prop_value:
+ pads[pad_port][pad_num]["MODER"] = PIN_MODE_OUTPUT
+ elif 'GPIO_Input' == prop_value:
+ pads[pad_port][pad_num]["MODER"] = PIN_MODE_INPUT
+ else:
+ pads[pad_port][pad_num]["SIGNAL"] = prop_value
+ pads[pad_port][pad_num]["MODER"] = PIN_MODE_ALTERNATE
+ pads[pad_port][pad_num]["OSPEEDR"] = PIN_OSPEED_MEDIUM
+ elif pad_prop == "GPIO_Mode":
+ pads[pad_port][pad_num]["MODER"] = PIN_MODE_TRANSLATE[prop_value]
+ elif pad_prop == "GPIO_Label":
+ pads[pad_port][pad_num]["LABEL"] = prop_value
+ elif pad_prop == "GPIO_PuPd":
+ pads[pad_port][pad_num]["PUPDR"] = PIN_PUPDR_TRANSLATE[prop_value]
+ elif pad_prop == "GPIO_ModeDefaultOutputPP":
+ pads[pad_port][pad_num]["OTYPER"] = PIN_OTYPE_TRANSLATE[prop_value]
+ pads[pad_port][pad_num]["MODER"] = PIN_MODE_OUTPUT
+ elif pad_prop == "GPIO_Speed":
+ pads[pad_port][pad_num]["OSPEEDR"] = PIN_OSPEED_TRANSLATE[prop_value]
+
+ return pads
+
+
+# Add defines for all pins with labels
+def gen_defines(project):
+ defines = {}
+
+ for port_key in sorted(project.keys()):
+ for pad_key in sorted(project[port_key].keys()):
+
+ pad_data = project[port_key][pad_key]
+ if pad_data['SIGNAL'] != 'UNUSED' and not pad_data['LABEL']:
+ pad_data['LABEL'] = pad_data['SIGNAL']
+ pad_data['LABEL'] = pad_data['LABEL'].replace('-', '_')
+ label = pad_data['LABEL']
+ signal = pad_data['SIGNAL']
+ if not label:
+ continue
+
+ defines['PORT_'+label] = 'GPIO' + port_key
+ defines['PAD_'+label] = pad_key
+
+ if re.search(r"TIM\d_CH\d", signal, re.M):
+ timer = signal.replace('S_TIM', '').replace('_CH', '')[:-1]
+ ch_num = int(signal[-1:])
+
+ defines['TIM_' + label] = timer
+ defines['CCR_' + label] = 'CCR' + timer[-1]
+ defines['PWMD_' + label] = 'PWMD' + timer[-1]
+ defines['ICUD_' + label] = 'ICUD' + timer[-1]
+ defines['CHN_' + label] = ch_num - 1
+
+ return defines
+
+
+# Each Port (A.B.C...)
+def gen_ports(gpio, project):
+ ports = {}
+ for port_key in sorted(project.keys()):
+
+ ports[port_key] = {}
+ # Each property (mode, output/input...)
+ for conf in PIN_CONF_LIST:
+ ports[port_key][conf] = []
+ for pin in project[port_key]:
+ out = project[port_key][pin][conf]
+ out = out.format(pin)
+ ports[port_key][conf].append(out)
+
+ conf = PIN_CONF_LIST_AF[0]
+ ports[port_key][conf] = []
+ for pin in range(0, 8):
+ try:
+ af = project[port_key][pin]['SIGNAL']
+ out = PIN_AFIO_AF.format(pin, gpio['ports'][port_key][pin][af])
+ except KeyError as e:
+ out = PIN_AFIO_AF.format(pin, 0)
+ ports[port_key][conf].append(out)
+
+ conf = PIN_CONF_LIST_AF[1]
+ ports[port_key][conf] = []
+ for pin in range(8, 16):
+ try:
+ af = project[port_key][pin]['SIGNAL']
+ out = PIN_AFIO_AF.format(pin, gpio['ports'][port_key][pin][af])
+ except KeyError:
+ out = PIN_AFIO_AF.format(pin, 0)
+ ports[port_key][conf].append(out)
+
+ return ports
+
+
+if __name__ == '__main__':
+ args = parser.parse_args()
+ gpio = read_gpio(args.gpio)
+ proj = read_project(gpio, args.project)
+ defines = gen_defines(proj)
+ ports = gen_ports(gpio, proj)
+
+ with open('board_gpio.tpl', 'r') as tpl_file:
+ tpl = tpl_file.read()
+ template = Template(tpl)
+
+ defines_sorted = []
+ for d in sorted(defines.keys()):
+ defines_sorted.append((d, defines[d]))
+
+ ports_sorted = []
+ for p in sorted(ports.keys()):
+ ports_sorted.append((p, ports[p]))
+
+ template.stream(defines=defines_sorted, ports=ports_sorted).dump(args.output)