aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rwxr-xr-xtools/chbuild.sh73
-rw-r--r--tools/chibios.el53
-rw-r--r--tools/mx2board.py349
-rw-r--r--tools/templates/board_gpio.tpl55
-rw-r--r--tools/templates/halconf_community.h173
-rw-r--r--tools/templates/mcuconf_community.h157
-rw-r--r--tools/travis/before_install.sh18
-rw-r--r--tools/travis/script.sh45
-rw-r--r--tools/update_configs.py104
9 files changed, 1027 insertions, 0 deletions
diff --git a/tools/chbuild.sh b/tools/chbuild.sh
new file mode 100755
index 0000000..6323dcb
--- /dev/null
+++ b/tools/chbuild.sh
@@ -0,0 +1,73 @@
+#!/bin/bash
+
+#
+# Author: Fabien Poussin
+# Date: 21/04/2017
+# Version: 1.0
+#
+
+renice +10 $$
+JOBS=$(grep -c ^processor /proc/cpuinfo)
+SKIP_ARRAY=(Win32)
+RETCODE=0
+
+
+function test_skip {
+ Array=$1
+ SKIP=0
+ for var in "${SKIP_ARRAY[@]}"
+ do
+ if [[ $1 == *"${var}"* ]]; then
+ SKIP=1
+ break
+ fi
+ done
+ return $SKIP
+}
+
+function chbuild {
+ projects=$(find $1 -name Makefile -printf '%h ')
+ OK=0
+ NOK=0
+ FAIL=()
+ SUCCESS=()
+ SKIPPED=()
+ for t in $projects
+ do
+ test_skip $t
+ if [ $? -ne 0 ]; then
+ printf "SKIPPING: ${t}\n"
+ SKIPPED+=($t)
+ continue
+ fi
+ pushd $t > /dev/null
+ printf "BUILDING: ${t}\n"
+ make --quiet -j $JOBS > /dev/null
+ if [ $? -ne 0 ]; then
+ ((NOK++))
+ FAIL+=($t)
+ RETCODE=1
+ else
+ ((OK++))
+ SUCCESS+=($t)
+ fi
+ popd > /dev/null
+ done
+ printf "\n${1}: ${OK} builds ok, ${NOK} builds failed\n"
+# printf 'SUCCESS: %s\n' "${SUCCESS[@]}"
+ printf 'FAIL: %s\n' "${FAIL[@]}"
+ printf 'SKIPPED: %s\n' "${SKIPPED[@]}"
+ printf "\n"
+ return $NOK
+}
+
+if [ -z "$1" ]
+ then
+ printf "This script looks for Makefiles and tries to build the projects\n"
+ printf "Usage: chbuild.sh PATH\n"
+ exit 1
+fi
+
+chbuild $1
+
+exit $RETCODE
diff --git a/tools/chibios.el b/tools/chibios.el
new file mode 100644
index 0000000..1e638f3
--- /dev/null
+++ b/tools/chibios.el
@@ -0,0 +1,53 @@
+;;;
+;;; Copyright (C) 2016 Stephane D'Alu
+;;;
+;;; Licensed under the Apache License, Version 2.0 (the "License");
+;;; you may not use this file except in compliance with the License.
+;;; You may obtain a copy of the License at
+;;;
+;;; http://www.apache.org/licenses/LICENSE-2.0
+;;;
+;;; Unless required by applicable law or agreed to in writing, software
+;;; distributed under the License is distributed on an "AS IS" BASIS,
+;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+;;; See the License for the specific language governing permissions and
+;;; limitations under the License.
+
+;;;
+;;; See: https://www.emacswiki.org/emacs/IndentingC
+;;;
+
+;;
+;;; Loading of this file can be done in ~/.emacs
+;;; by putting: (load "~/path/to/ChibiOS-Contrib/tools/chibios.el")
+;;;
+;;; Styling can be selected using local variable:
+;;; /* -*- c-file-style: "chibios" -*- */
+;;;
+;;; But will also be automatically apply to a file located in a
+;;; ChibiOS directory. Example: /path/to/../ChibiOS/../file.c
+;;;
+
+
+
+;;
+;; Define ChibiOS prefered styling
+;;
+(defconst chibios-c-style
+ '((indent-tabs-mode . nil)
+ (c-basic-offset . 2))
+ "ChibiOS C Programming Style")
+
+(c-add-style "chibios" chibios-c-style)
+
+
+;;
+;;
+;;
+(defun maybe-chibios-c-style ()
+ (when (and buffer-file-name
+ (string-match "ChibiOS" buffer-file-name))
+ (c-set-style "chibios")))
+
+(add-hook 'c-mode-hook 'maybe-chibios-c-style)
+
diff --git a/tools/mx2board.py b/tools/mx2board.py
new file mode 100644
index 0000000..642a934
--- /dev/null
+++ b/tools/mx2board.py
@@ -0,0 +1,349 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+__author__ = 'Fabien Poussin'
+__version__ = '0.3'
+
+
+from xml.etree import ElementTree as etree
+from jinja2 import Template
+from os.path import expanduser, sep, dirname, abspath
+from argparse import ArgumentParser
+from traceback import print_exc
+import re
+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 = ArgumentParser(description='Generate ChibiOS GPIO header file from STM32CubeMX project files.')
+group = parser.add_mutually_exclusive_group(required=False)
+group.add_argument('-m', '--mx', default='', type=str, help='STM32CubeMX path. Invalid if -g is used.')
+group.add_argument('-g', '--gpio', default='', type=str, help='STM32CubeMX Gpio file, if you don\'t have STM32CubeMX installed. Invalid if -m is used.')
+parser.add_argument('-p', '--project', required=True, type=str, help="STM32CubeMX Project file")
+parser.add_argument('-o', '--output', default='board_gpio.h', type=str, help='Output file name')
+
+
+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 get_gpio_file(proj_file, mx_path):
+
+ mcu_name = None
+ gpio_file = None
+ path = None
+ mcu_info = None
+
+ print('Opening ' + proj_file)
+ with open(proj_file, 'r') as f:
+ proj_data = f.readlines()
+
+ for l in proj_data:
+ if l.startswith('Mcu.Name'):
+ print('MCU is ' + l.split('=')[-1].strip())
+ mcu_name = '{}.xml'.format(l.split('=')[-1].strip())
+
+ if not mcu_name:
+ print('Could not find MCU name in project file')
+ exit(1)
+
+ if "STM32F1" in mcu_name:
+ print('STM32F1xx are not compatible with this script. (old GPIO)')
+ exit(1)
+
+ found = False
+ for p in (mx_path,
+ '{0}{1}STM32CubeMX'.format(expanduser("~"), sep),
+ 'C:{0}Program Files{0}STMicroelectronics{0}STM32Cube{0}STM32CubeMX'.format(sep)):
+
+ if not p:
+ continue
+ try:
+ path = '{1}{0}db{0}mcu{0}'.format(sep, p)
+ mcu_info = open_xml(path + mcu_name)
+ found = True
+ break
+ except IOError:
+ continue
+
+ if not found:
+ print('Could not find GPIO file')
+ exit(1)
+
+ print('Opened ' + path)
+
+ for ip in mcu_info.findall("IP"):
+ if ip.attrib['Name'] == 'GPIO':
+ gpio_file = '{0}{2}IP{2}GPIO-{1}_Modes.xml'.format(path,
+ ip.attrib['Version'],
+ sep)
+
+ return gpio_file
+
+
+def read_gpio(filename):
+ gpio = {'ports': {}, 'defaults': {}, 'modes': {}}
+
+ print('Opening GPIO file ' + filename)
+ 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_exc(e)
+ except AttributeError as e:
+ print_exc(e)
+
+ return gpio
+
+
+# Extract signals from IOC
+def read_project(gpio, filename):
+
+ print('Opening project file ' + 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 prop_value.startswith('ADC') \
+ 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()
+ cur_path = dirname(abspath(__file__))
+
+ if args.gpio:
+ gpio = read_gpio(args.gpio)
+
+ else:
+ gpio_file = get_gpio_file(args.project, args.mx)
+ gpio = read_gpio(gpio_file)
+ proj = read_project(gpio, args.project)
+ defines = gen_defines(proj)
+ ports = gen_ports(gpio, proj)
+
+ with open(cur_path + '/templates/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)
+
+ print('File generated at ' + args.output)
diff --git a/tools/templates/board_gpio.tpl b/tools/templates/board_gpio.tpl
new file mode 100644
index 0000000..07a316d
--- /dev/null
+++ b/tools/templates/board_gpio.tpl
@@ -0,0 +1,55 @@
+#ifndef _BOARD_GPIO_H_
+#define _BOARD_GPIO_H_
+
+/* Generated by mx2board.py */
+
+{% 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/templates/halconf_community.h b/tools/templates/halconf_community.h
new file mode 100644
index 0000000..631bb9f
--- /dev/null
+++ b/tools/templates/halconf_community.h
@@ -0,0 +1,173 @@
+/*
+ ChibiOS - Copyright (C) 2014 Uladzimir Pylinsky aka barthess
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+#ifndef HALCONF_COMMUNITY_H
+#define HALCONF_COMMUNITY_H
+
+/**
+ * @brief Enables the community overlay.
+ */
+#if !defined(HAL_USE_COMMUNITY) || defined(__DOXYGEN__)
+#define HAL_USE_COMMUNITY TRUE
+#endif
+
+/**
+ * @brief Enables the FSMC subsystem.
+ */
+#if !defined(HAL_USE_FSMC) || defined(__DOXYGEN__)
+#define HAL_USE_FSMC FALSE
+#endif
+
+/**
+ * @brief Enables the NAND subsystem.
+ */
+#if !defined(HAL_USE_NAND) || defined(__DOXYGEN__)
+#define HAL_USE_NAND FALSE
+#endif
+
+/**
+ * @brief Enables the 1-wire subsystem.
+ */
+#if !defined(HAL_USE_ONEWIRE) || defined(__DOXYGEN__)
+#define HAL_USE_ONEWIRE FALSE
+#endif
+
+/**
+ * @brief Enables the EICU subsystem.
+ */
+#if !defined(HAL_USE_EICU) || defined(__DOXYGEN__)
+#define HAL_USE_EICU FALSE
+#endif
+
+/**
+ * @brief Enables the CRC subsystem.
+ */
+#if !defined(HAL_USE_CRC) || defined(__DOXYGEN__)
+#define HAL_USE_CRC FALSE
+#endif
+
+/**
+ * @brief Enables the RNG subsystem.
+ */
+#if !defined(HAL_USE_RNG) || defined(__DOXYGEN__)
+#define HAL_USE_RNG FALSE
+#endif
+
+/**
+ * @brief Enables the EEPROM subsystem.
+ */
+#if !defined(HAL_USE_EEPROM) || defined(__DOXYGEN__)
+#define HAL_USE_EEPROM FALSE
+#endif
+
+/**
+ * @brief Enables the TIMCAP subsystem.
+ */
+#if !defined(HAL_USE_TIMCAP) || defined(__DOXYGEN__)
+#define HAL_USE_TIMCAP FALSE
+#endif
+
+/**
+ * @brief Enables the TIMCAP subsystem.
+ */
+#if !defined(HAL_USE_COMP) || defined(__DOXYGEN__)
+#define HAL_USE_COMP FALSE
+#endif
+
+/**
+ * @brief Enables the QEI subsystem.
+ */
+#if !defined(HAL_USE_QEI) || defined(__DOXYGEN__)
+#define HAL_USE_QEI FALSE
+#endif
+
+/**
+ * @brief Enables the USBH subsystem.
+ */
+#if !defined(HAL_USE_USBH) || defined(__DOXYGEN__)
+#define HAL_USE_USBH FALSE
+#endif
+
+/**
+ * @brief Enables the USB_MSD subsystem.
+ */
+#if !defined(HAL_USE_USB_MSD) || defined(__DOXYGEN__)
+#define HAL_USE_USB_MSD FALSE
+#endif
+
+/*===========================================================================*/
+/* FSMCNAND driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables the @p nandAcquireBus() and @p nanReleaseBus() APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(NAND_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
+#define NAND_USE_MUTUAL_EXCLUSION TRUE
+#endif
+
+/*===========================================================================*/
+/* 1-wire driver related settings. */
+/*===========================================================================*/
+/**
+ * @brief Enables strong pull up feature.
+ * @note Disabling this option saves both code and data space.
+ */
+#define ONEWIRE_USE_STRONG_PULLUP FALSE
+
+/**
+ * @brief Enables search ROM feature.
+ * @note Disabling this option saves both code and data space.
+ */
+#define ONEWIRE_USE_SEARCH_ROM TRUE
+
+/*===========================================================================*/
+/* QEI driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables discard of overlow
+ */
+#if !defined(QEI_USE_OVERFLOW_DISCARD) || defined(__DOXYGEN__)
+#define QEI_USE_OVERFLOW_DISCARD FALSE
+#endif
+
+/**
+ * @brief Enables min max of overlow
+ */
+#if !defined(QEI_USE_OVERFLOW_MINMAX) || defined(__DOXYGEN__)
+#define QEI_USE_OVERFLOW_MINMAX FALSE
+#endif
+
+/*===========================================================================*/
+/* EEProm driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables 24xx series I2C eeprom device driver.
+ * @note Disabling this option saves both code and data space.
+ */
+#define EEPROM_USE_EE24XX FALSE
+ /**
+ * @brief Enables 25xx series SPI eeprom device driver.
+ * @note Disabling this option saves both code and data space.
+ */
+#define EEPROM_USE_EE25XX FALSE
+
+#endif /* HALCONF_COMMUNITY_H */
+
+/** @} */
diff --git a/tools/templates/mcuconf_community.h b/tools/templates/mcuconf_community.h
new file mode 100644
index 0000000..1ebe24c
--- /dev/null
+++ b/tools/templates/mcuconf_community.h
@@ -0,0 +1,157 @@
+/*
+ ChibiOS/RT - Copyright (C) 2014 Uladzimir Pylinsky aka barthess
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * FSMC driver system settings.
+ */
+#define STM32_FSMC_USE_FSMC1 FALSE
+#define STM32_FSMC_FSMC1_IRQ_PRIORITY 10
+
+/*
+ * FSMC NAND driver system settings.
+ */
+#define STM32_NAND_USE_FSMC_NAND1 FALSE
+#define STM32_NAND_USE_FSMC_NAND2 FALSE
+#define STM32_NAND_USE_EXT_INT FALSE
+#define STM32_NAND_DMA_STREAM STM32_DMA_STREAM_ID(2, 7)
+#define STM32_NAND_DMA_PRIORITY 0
+#define STM32_NAND_DMA_ERROR_HOOK(nandp) osalSysHalt("DMA failure")
+
+/*
+ * FSMC SRAM driver system settings.
+ */
+#define STM32_USE_FSMC_SRAM FALSE
+#define STM32_SRAM_USE_FSMC_SRAM1 FALSE
+#define STM32_SRAM_USE_FSMC_SRAM2 FALSE
+#define STM32_SRAM_USE_FSMC_SRAM3 FALSE
+#define STM32_SRAM_USE_FSMC_SRAM4 FALSE
+
+/*
+ * FSMC SDRAM driver system settings.
+ */
+#define STM32_USE_FSMC_SDRAM FALSE
+#define STM32_SDRAM_USE_FSMC_SDRAM1 FALSE
+#define STM32_SDRAM_USE_FSMC_SDRAM2 TRUE
+
+/*
+ * TIMCAP driver system settings.
+ */
+#define STM32_TIMCAP_USE_TIM1 TRUE
+#define STM32_TIMCAP_USE_TIM2 FALSE
+#define STM32_TIMCAP_USE_TIM3 TRUE
+#define STM32_TIMCAP_USE_TIM4 TRUE
+#define STM32_TIMCAP_USE_TIM5 TRUE
+#define STM32_TIMCAP_USE_TIM8 TRUE
+#define STM32_TIMCAP_USE_TIM9 TRUE
+#define STM32_TIMCAP_TIM1_IRQ_PRIORITY 3
+#define STM32_TIMCAP_TIM2_IRQ_PRIORITY 3
+#define STM32_TIMCAP_TIM3_IRQ_PRIORITY 3
+#define STM32_TIMCAP_TIM4_IRQ_PRIORITY 3
+#define STM32_TIMCAP_TIM5_IRQ_PRIORITY 3
+#define STM32_TIMCAP_TIM8_IRQ_PRIORITY 3
+#define STM32_TIMCAP_TIM9_IRQ_PRIORITY 3
+
+/*
+ * COMP driver system settings.
+ */
+#define STM32_COMP_USE_COMP1 TRUE
+#define STM32_COMP_USE_COMP2 TRUE
+#define STM32_COMP_USE_COMP3 TRUE
+#define STM32_COMP_USE_COMP4 TRUE
+#define STM32_COMP_USE_COMP5 TRUE
+#define STM32_COMP_USE_COMP6 TRUE
+#define STM32_COMP_USE_COMP7 TRUE
+
+#define STM32_COMP_USE_INTERRUPTS TRUE
+#define STM32_COMP_1_2_3_IRQ_PRIORITY 5
+#define STM32_COMP_4_5_6_IRQ_PRIORITY 5
+#define STM32_COMP_7_IRQ_PRIORITY 5
+
+#if STM32_COMP_USE_INTERRUPTS
+#define STM32_DISABLE_EXTI21_22_29_HANDLER
+#define STM32_DISABLE_EXTI30_32_HANDLER
+#define STM32_DISABLE_EXTI33_HANDLER
+#endif
+
+/*
+ * USBH driver system settings.
+ */
+#define STM32_OTG1_CHANNELS_NUMBER 8
+#define STM32_OTG2_CHANNELS_NUMBER 12
+
+#define STM32_USBH_USE_OTG1 1
+#define STM32_OTG1_RXFIFO_SIZE 1024
+#define STM32_OTG1_PTXFIFO_SIZE 128
+#define STM32_OTG1_NPTXFIFO_SIZE 128
+
+#define STM32_USBH_USE_OTG2 0
+#define STM32_OTG2_RXFIFO_SIZE 2048
+#define STM32_OTG2_PTXFIFO_SIZE 1024
+#define STM32_OTG2_NPTXFIFO_SIZE 1024
+
+#define STM32_USBH_MIN_QSPACE 4
+#define STM32_USBH_CHANNELS_NP 4
+
+/*
+ * CRC driver system settings.
+ */
+#define STM32_CRC_USE_CRC1 TRUE
+#define STM32_CRC_CRC1_DMA_IRQ_PRIORITY 1
+#define STM32_CRC_CRC1_DMA_PRIORITY 2
+#define STM32_CRC_CRC1_DMA_STREAM STM32_DMA1_STREAM2
+
+#define CRCSW_USE_CRC1 FALSE
+#define CRCSW_CRC32_TABLE TRUE
+#define CRCSW_CRC16_TABLE TRUE
+#define CRCSW_PROGRAMMABLE TRUE
+
+/*
+ * EICU driver system settings.
+ */
+#define STM32_EICU_USE_TIM1 TRUE
+#define STM32_EICU_USE_TIM2 FALSE
+#define STM32_EICU_USE_TIM3 TRUE
+#define STM32_EICU_USE_TIM4 TRUE
+#define STM32_EICU_USE_TIM5 TRUE
+#define STM32_EICU_USE_TIM8 TRUE
+#define STM32_EICU_USE_TIM9 TRUE
+#define STM32_EICU_USE_TIM10 TRUE
+#define STM32_EICU_USE_TIM11 TRUE
+#define STM32_EICU_USE_TIM12 TRUE
+#define STM32_EICU_USE_TIM13 TRUE
+#define STM32_EICU_USE_TIM14 TRUE
+#define STM32_EICU_TIM1_IRQ_PRIORITY 7
+#define STM32_EICU_TIM2_IRQ_PRIORITY 7
+#define STM32_EICU_TIM3_IRQ_PRIORITY 7
+#define STM32_EICU_TIM4_IRQ_PRIORITY 7
+#define STM32_EICU_TIM5_IRQ_PRIORITY 7
+#define STM32_EICU_TIM8_IRQ_PRIORITY 7
+#define STM32_EICU_TIM9_IRQ_PRIORITY 7
+#define STM32_EICU_TIM10_IRQ_PRIORITY 7
+#define STM32_EICU_TIM11_IRQ_PRIORITY 7
+#define STM32_EICU_TIM12_IRQ_PRIORITY 7
+#define STM32_EICU_TIM13_IRQ_PRIORITY 7
+#define STM32_EICU_TIM14_IRQ_PRIORITY 7
+
+/*
+ * QEI driver system settings.
+ */
+#define STM32_QEI_USE_TIM1 TRUE
+#define STM32_QEI_USE_TIM2 FALSE
+#define STM32_QEI_USE_TIM3 TRUE
+#define STM32_QEI_TIM1_IRQ_PRIORITY 3
+#define STM32_QEI_TIM2_IRQ_PRIORITY 3
+#define STM32_QEI_TIM3_IRQ_PRIORITY 3
diff --git a/tools/travis/before_install.sh b/tools/travis/before_install.sh
new file mode 100644
index 0000000..0769759
--- /dev/null
+++ b/tools/travis/before_install.sh
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+set -ex
+
+cd /tmp
+
+sudo apt-get install lib32z1
+wget https://launchpad.net/gcc-arm-embedded/4.9/4.9-2015-q3-update/+download/gcc-arm-none-eabi-4_9-2015q3-20150921-linux.tar.bz2
+tar xjf gcc-arm-none-eabi-4_9-2015q3-20150921-linux.tar.bz2
+export PATH=/tmp/gcc-arm-none-eabi-4_9-2015q3/bin:$PATH
+arm-none-eabi-gcc --version
+
+cd -
+cd ..
+
+mkdir ChibiOS-RT
+cd ChibiOS-RT
+git clone https://github.com/ChibiOS/ChibiOS.git .
diff --git a/tools/travis/script.sh b/tools/travis/script.sh
new file mode 100644
index 0000000..e70b114
--- /dev/null
+++ b/tools/travis/script.sh
@@ -0,0 +1,45 @@
+#!/bin/sh
+
+set -ex
+
+export PATH=/tmp/gcc-arm-none-eabi-4_9-2015q3/bin:$PATH
+
+cd ../ChibiOS-RT/ext
+7z x lwip-2.0.3-patched.7z
+cd -
+
+git checkout -- .
+git clean -xfd
+make -C demos/TIVA/RT-TM4C123G-LAUNCHPAD
+
+git checkout -- .
+git clean -xfd
+make -C demos/TIVA/RT-TM4C1294-LAUNCHPAD
+
+git checkout -- .
+git clean -xfd
+make -C demos/TIVA/RT-TM4C1294-LAUNCHPAD-LWIP
+
+git checkout -- .
+git clean -xfd
+make -C testhal/TIVA/TM4C123x/GPT
+
+git checkout -- .
+git clean -xfd
+make -C testhal/TIVA/TM4C123x/I2C
+
+git checkout -- .
+git clean -xfd
+make -C testhal/TIVA/TM4C123x/PWM
+
+git checkout -- .
+git clean -xfd
+make -C testhal/TIVA/TM4C123x/SPI
+
+git checkout -- .
+git clean -xfd
+make -C testhal/TIVA/TM4C123x/WDG
+
+git checkout -- .
+git clean -xfd
+make -C testhal/TIVA/multi/PAL
diff --git a/tools/update_configs.py b/tools/update_configs.py
new file mode 100644
index 0000000..6bc69b9
--- /dev/null
+++ b/tools/update_configs.py
@@ -0,0 +1,104 @@
+#!/usr/bin/python3
+# -*- coding: utf-8 -*-
+__author__ = 'Fabien Poussin'
+__version__ = '0.1'
+
+import os
+import re
+from argparse import ArgumentParser
+from traceback import print_exc
+from shutil import copy
+
+parser = ArgumentParser(description='Generate ChibiOS-Contrib config and make files from ChibiOS')
+parser.add_argument('-s', '--src', default='../../ChibiOS-RT', type=str, help="ChibiOS folder")
+parser.add_argument('-d', '--dst', default='..', type=str, help='ChibiOS-Contrib folder')
+
+
+def makefile(lines):
+
+ for l in range(len(lines)):
+
+ if 'CHIBIOS =' in lines[l]:
+ lines[l] = lines[l][:-1] + '/../ChibiOS-RT\n'
+ lines.insert(l + 1, 'CHIBIOS_CONTRIB = $(CHIBIOS)/../ChibiOS-Contrib\n')
+
+ if '$(CHIBIOS)/os/hal/hal.mk' in lines[l] \
+ or '$(CHIBIOS)/os/hal/ports/' in lines[l] \
+ or '$(CHIBIOS)/os/various' in lines[l] :
+ lines[l] = lines[l].replace('CHIBIOS', 'CHIBIOS_CONTRIB')
+
+ return "".join(lines)
+
+
+def halconf(lines):
+
+ idx_end = lines.index('#endif /* HALCONF_H */\n')
+ lines.insert(idx_end - 1, '\n')
+ lines.insert(idx_end - 1, '#include "halconf_community.h"')
+ lines.insert(idx_end - 1, '\n')
+
+ return "".join(lines)
+
+
+def mcuconf(lines):
+
+ idx_end = lines.index('#endif /* MCUCONF_H */\n')
+ lines.insert(idx_end - 1, '\n')
+ lines.insert(idx_end - 1, '#include "mcuconf_community.h"')
+ lines.insert(idx_end - 1, '\n')
+
+ return "".join(lines)
+
+
+if __name__ == '__main__':
+
+ args = parser.parse_args()
+ sources = {}
+
+ for folder in ['testhal']:
+
+ for family in os.scandir(args.src + '/{}/STM32/'.format(folder)):
+ if not family.name[0].isupper() or not family.is_dir():
+ continue
+
+ for test in os.scandir(family.path):
+ try:
+ sources[family.name] = {'makefile': None, 'halconf': None, 'mcuconf': None}
+
+ with open(test.path + '/Makefile', 'r') as file:
+ sources[family.name]['makefile'] = makefile(file.readlines())
+
+ with open(test.path + '/halconf.h', 'r') as file:
+ sources[family.name]['halconf'] = halconf(file.readlines())
+
+ with open(test.path + '/mcuconf.h', 'r') as file:
+ sources[family.name]['mcuconf'] = mcuconf(file.readlines())
+
+ except Exception as e:
+ print(test.path, e)
+ del sources[family.name]
+ continue
+
+ break
+
+ for family in os.scandir(args.dst + '/{}/STM32/'.format(folder)):
+ if not family.name[0].isupper() or not family.is_dir():
+ continue
+
+ for test in os.scandir(family.path):
+ copy('templates/halconf_community.h', test.path)
+ copy('templates/mcuconf_community.h', test.path)
+
+ try:
+ with open(test.path + '/Makefile', 'w') as file:
+ file.write(sources[family.name]['makefile'])
+
+ with open(test.path + '/halconf.h', 'w') as file:
+ file.write(sources[family.name]['halconf'])
+
+ with open(test.path + '/mcuconf.h', 'w') as file:
+ file.write(sources[family.name]['mcuconf'])
+
+ print('updated', test.path)
+ except KeyError as e:
+ print('Missing family data', e)