diff --git a/.github/workflows/githubci.yml b/.github/workflows/githubci.yml
new file mode 100644
index 000000000..dc6b31a01
--- /dev/null
+++ b/.github/workflows/githubci.yml
@@ -0,0 +1,63 @@
+name: Build
+
+on: [pull_request, push]
+
+jobs:
+  build:
+    strategy:
+      fail-fast: false
+      matrix:
+        arduino-platform: ['metro_m0', 'hallowing', 'circuitplayground_m0',
+                           'metro_m4', 'pybadge_m4', 'pygamer_m4', 'hallowing_m4', 'pyportal_m4', 'pyportal_m4_titano']
+
+    runs-on: ubuntu-latest
+    
+    steps:
+    - name: Setup Python
+      uses: actions/setup-python@v1
+      with:
+        python-version: '3.x'
+        
+    - name: Checkout code
+      uses: actions/checkout@v2
+
+    - name: Checkout submodules
+      shell: bash
+      run: |
+        auth_header="$(git config --local --get http.https://github.com/.extraheader)"
+        git submodule sync --recursive
+        git -c "http.extraheader=$auth_header" -c protocol.version=2 submodule update --init --force --recursive      
+        
+    - name: Install Arduino CLI and Tools
+      run: |
+        # make all our directories we need for files and libraries
+        mkdir $HOME/.arduino15
+        mkdir $HOME/.arduino15/packages
+        mkdir $HOME/Arduino
+        mkdir $HOME/Arduino/libraries
+        curl -fsSL https://raw.githubusercontent.com/arduino/arduino-cli/master/install.sh | sh
+        echo "$GITHUB_WORKSPACE/bin" >> $GITHUB_PATH
+        
+    - name: Install BSP and Libraries
+      env:
+        BSP_URL: https://adafruit.github.io/arduino-board-index/package_adafruit_index.json
+        BSP_PATH: .arduino15/packages/adafruit/hardware/samd
+        LIB_DEPS: FlashStorage SD
+      run: |
+        arduino-cli config init
+        arduino-cli core update-index
+        arduino-cli core update-index --additional-urls $BSP_URL        
+        arduino-cli core install arduino:samd --additional-urls $BSP_URL
+        arduino-cli core install adafruit:samd --additional-urls $BSP_URL
+        # Replace release BSP with our code
+        BSP_VERSION=`eval ls $HOME/$BSP_PATH`
+        rm -r $HOME/$BSP_PATH/*
+        ln -s $GITHUB_WORKSPACE $HOME/$BSP_PATH/$BSP_VERSION
+        arduino-cli lib install $LIB_DEPS
+
+    - name: Build examples
+      run: python3 extras/build_all.py ${{ matrix.arduino-platform }}
+
+    # How to mark this as allowed-to-fail?
+    - name: Build examples (-Wall)
+      run: python3 extras/build_all.py --all_warnings --warnings_do_not_cause_job_failure
diff --git a/.gitignore b/.gitignore
index 2ad1d1f84..22b823b91 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,5 @@
 *.bz2
+*.atsuo
 
 bootloaders/*/build/
+*~
\ No newline at end of file
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 000000000..293215518
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "cores/arduino/TinyUSB/Adafruit_TinyUSB_ArduinoCore"]
+	path = cores/arduino/TinyUSB/Adafruit_TinyUSB_ArduinoCore
+	url = https://github.com/adafruit/Adafruit_TinyUSB_ArduinoCore.git
diff --git a/README.md b/README.md
index fca8a216d..8ed23e3aa 100644
--- a/README.md
+++ b/README.md
@@ -1,53 +1,28 @@
-# Arduino Core for SAMD21 CPU
+# Arduino Core for SAMD21 and SAMD51 CPU
 
-This repository contains the source code and configuration files of the Arduino Core
-for Atmel's SAMD21 processor (used on the Arduino/Genuino Zero, MKR1000 and MKRZero boards).
-
-## Installation on Arduino IDE
+[![Build Status](https://github.com/adafruit/ArduinoCore-samd/workflows/Build/badge.svg)](https://github.com/adafruit/ArduinoCore-samd/actions)
 
-This core is available as a package in the Arduino IDE cores manager.
-Just open the "Boards Manager" and install the package called:
+This repository contains the source code and configuration files of the Arduino Core
+for Atmel's SAMD21 and SAMD51 processor (used on the Arduino/Genuino Zero, MKR1000 and MKRZero boards).
 
-"Arduino SAMD Boards (32-bit ARM Cortex-M0+)"
+In particular, this adds support for the Adafruit SAMD Boards such as the Feather M0
 
-## Support
+## Bugs or Issues
 
-There is a dedicated section of the Arduino Forum for general discussion and project assistance:
+* AREF must be tied to 3.3V for dac to work. This is a bug in the SAMD51 silicon.
+* USB host mode doesn't work yet
 
-http://forum.arduino.cc/index.php?board=98.0
+If you find a bug you can submit an issue here on github:
 
-## Bugs or Issues
+https://github.com/adafruit/ArduinoCore-samd
 
-If you find a bug you can submit an issue here on github:
+or if it is an issue with the upstream:
 
 https://github.com/arduino/ArduinoCore-samd/issues
 
 Before posting a new issue, please check if the same problem has been already reported by someone else
 to avoid duplicates.
 
-## Contributions
-
-Contributions are always welcome. The preferred way to receive code cotribution is by submitting a 
-Pull Request on github.
-
-## Hourly builds
-
-This repository is under a Continuous Integration system that every hour checks if there are updates and
-builds a release for testing (the so called "Hourly builds").
-
-The hourly builds are available through Boards Manager. If you want to install them:
-  1. Open the **Preferences** of the Arduino IDE.
-  2. Add this URL `http://downloads.arduino.cc/Hourly/samd/package_samd-hourly-build_index.json` in the **Additional Boards Manager URLs** field, and click OK.
-  3. Open the **Boards Manager** (menu Tools->Board->Board Manager...)
-  4. Install **Arduino SAMD core - Hourly build**
-  5. Select one of the boards under **SAMD Hourly build XX** in Tools->Board menu
-  6. Compile/Upload as usual
-
-If you already installed an hourly build and you want to update it with the latest:
-  1. Open the **Boards Manager** (menu Tools->Board->Board Manager...)
-  2. Remove **Arduino SAMD core - Hourly build**
-  3. Install again **Arduino SAMD core - Hourly build**, the Board Manager will download the latest build replacing the old one.
-
 ## License and credits
 
 This core has been developed by Arduino LLC in collaboration with Atmel.
diff --git a/boards.txt b/boards.txt
index bffc5e85e..0bb4885cd 100644
--- a/boards.txt
+++ b/boards.txt
@@ -1,4 +1,4 @@
-# Copyright (c) 2014-2017 Arduino LLC.  All right reserved.
+# Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
 #
 # This library is free software; you can redistribute it and/or
 # modify it under the terms of the GNU Lesser General Public
@@ -14,309 +14,194 @@
 # License along with this library; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
-# Arduino/Genuino Zero (Prorgamming Port)
-# ---------------------------------------
-arduino_zero_edbg.name=Arduino/Genuino Zero (Programming Port)
-arduino_zero_edbg.vid.0=0x03eb
-arduino_zero_edbg.pid.0=0x2157
-
-arduino_zero_edbg.upload.tool=openocd
-arduino_zero_edbg.upload.protocol=sam-ba
-arduino_zero_edbg.upload.maximum_size=262144
-arduino_zero_edbg.upload.use_1200bps_touch=false
-arduino_zero_edbg.upload.wait_for_upload_port=false
-arduino_zero_edbg.upload.native_usb=false
-arduino_zero_edbg.build.mcu=cortex-m0plus
-arduino_zero_edbg.build.f_cpu=48000000L
-arduino_zero_edbg.build.usb_product="Arduino Zero"
-arduino_zero_edbg.build.usb_manufacturer="Arduino LLC"
-arduino_zero_edbg.build.board=SAMD_ZERO
-arduino_zero_edbg.build.core=arduino
-arduino_zero_edbg.build.extra_flags=-D__SAMD21G18A__ {build.usb_flags}
-arduino_zero_edbg.build.ldscript=linker_scripts/gcc/flash_with_bootloader.ld
-arduino_zero_edbg.build.openocdscript=openocd_scripts/arduino_zero.cfg
-arduino_zero_edbg.build.variant=arduino_zero
-arduino_zero_edbg.build.variant_system_lib=
-arduino_zero_edbg.build.vid=0x2341
-arduino_zero_edbg.build.pid=0x804d
-arduino_zero_edbg.bootloader.tool=openocd
-arduino_zero_edbg.bootloader.file=zero/samd21_sam_ba.bin
-
-# Arduino/Genuino Zero (Native USB Port)
-# --------------------------------------
-arduino_zero_native.name=Arduino/Genuino Zero (Native USB Port)
-arduino_zero_native.vid.0=0x2341
-arduino_zero_native.pid.0=0x804d
-arduino_zero_native.vid.1=0x2341
-arduino_zero_native.pid.1=0x004d
-
-arduino_zero_native.vid.2=0x2341
-arduino_zero_native.pid.2=0x824d
-# If the board is a 2341:824d use 2341:824d for build and set other parameters as well
-arduino_zero_native.vid.2.build.vid=0x2341
-arduino_zero_native.vid.2.build.pid=0x824d
-arduino_zero_native.vid.2.build.usb_product="Genuino Zero"
-arduino_zero_native.vid.2.bootloader.file=zero/samd21_sam_ba_genuino.bin
-
-arduino_zero_native.vid.3=0x2341
-arduino_zero_native.pid.3=0x024d
-# If the board is a 2341:024d use 2341:824d for build and set other parameters as well
-arduino_zero_native.vid.3.build.vid=0x2341
-arduino_zero_native.vid.3.build.pid=0x824d
-arduino_zero_native.vid.3.build.usb_product="Genuino Zero"
-arduino_zero_native.vid.3.bootloader.file=zero/samd21_sam_ba_genuino.bin
-
-arduino_zero_native.upload.tool=bossac
-arduino_zero_native.upload.protocol=sam-ba
-arduino_zero_native.upload.maximum_size=262144
-arduino_zero_native.upload.use_1200bps_touch=true
-arduino_zero_native.upload.wait_for_upload_port=true
-arduino_zero_native.upload.native_usb=true
-arduino_zero_native.build.mcu=cortex-m0plus
-arduino_zero_native.build.f_cpu=48000000L
-arduino_zero_native.build.usb_product="Arduino Zero"
-arduino_zero_native.build.usb_manufacturer="Arduino LLC"
-arduino_zero_native.build.board=SAMD_ZERO
-arduino_zero_native.build.core=arduino
-arduino_zero_native.build.extra_flags=-D__SAMD21G18A__ {build.usb_flags}
-arduino_zero_native.build.ldscript=linker_scripts/gcc/flash_with_bootloader.ld
-arduino_zero_native.build.openocdscript=openocd_scripts/arduino_zero.cfg
-arduino_zero_native.build.variant=arduino_zero
-arduino_zero_native.build.variant_system_lib=
-arduino_zero_native.build.vid=0x2341
-arduino_zero_native.build.pid=0x804d
-arduino_zero_native.bootloader.tool=openocd
-arduino_zero_native.bootloader.file=zero/samd21_sam_ba.bin
-
-# Arduino/Genuino MKR1000
-# -----------------------
-mkr1000.name=Arduino/Genuino MKR1000
-mkr1000.vid.0=0x2341
-mkr1000.pid.0=0x804e
-mkr1000.vid.1=0x2341
-mkr1000.pid.1=0x004e
-
-mkr1000.vid.2=0x2341
-mkr1000.pid.2=0x824e
-# If the board is a 2341:824e use 2341:824e for build and set other parameters as well
-mkr1000.vid.2.build.vid=0x2341
-mkr1000.vid.2.build.pid=0x824e
-mkr1000.vid.2.build.usb_product="Genuino MKR1000"
-mkr1000.vid.2.bootloader.file=mkr1000/samd21_sam_ba_genuino_mkr1000.bin
-
-mkr1000.vid.3=0x2341
-mkr1000.pid.3=0x024e
-# If the board is a 2341:024e use 2341:824e for build and set other parameters as well
-mkr1000.vid.3.build.vid=0x2341
-mkr1000.vid.3.build.pid=0x824e
-mkr1000.vid.3.build.usb_product="Genuino MKR1000"
-mkr1000.vid.3.bootloader.file=mkr1000/samd21_sam_ba_genuino_mkr1000.bin
-
-mkr1000.upload.tool=bossac
-mkr1000.upload.protocol=sam-ba
-mkr1000.upload.maximum_size=262144
-mkr1000.upload.use_1200bps_touch=true
-mkr1000.upload.wait_for_upload_port=true
-mkr1000.upload.native_usb=true
-mkr1000.build.mcu=cortex-m0plus
-mkr1000.build.f_cpu=48000000L
-mkr1000.build.usb_product="Arduino MKR1000"
-mkr1000.build.usb_manufacturer="Arduino LLC"
-mkr1000.build.board=SAMD_MKR1000
-mkr1000.build.core=arduino
-mkr1000.build.extra_flags=-DUSE_ARDUINO_MKR_PIN_LAYOUT -D__SAMD21G18A__ {build.usb_flags}
-mkr1000.build.ldscript=linker_scripts/gcc/flash_with_bootloader.ld
-mkr1000.build.openocdscript=openocd_scripts/arduino_zero.cfg
-mkr1000.build.variant=mkr1000
-mkr1000.build.vid=0x2341
-mkr1000.build.pid=0x804e
-mkr1000.bootloader.tool=openocd
-mkr1000.bootloader.file=mkr1000/samd21_sam_ba_arduino_mkr1000.bin
-
-# Arduino MKRZero
-# ---------------
-mkrzero.name=Arduino MKRZERO
-mkrzero.vid.0=0x2341
-mkrzero.pid.0=0x804f
-mkrzero.vid.1=0x2341
-mkrzero.pid.1=0x004f
-
-mkrzero.upload.tool=bossac
-mkrzero.upload.protocol=sam-ba
-mkrzero.upload.maximum_size=262144
-mkrzero.upload.use_1200bps_touch=true
-mkrzero.upload.wait_for_upload_port=true
-mkrzero.upload.native_usb=true
-mkrzero.build.mcu=cortex-m0plus
-mkrzero.build.f_cpu=48000000L
-mkrzero.build.usb_product="Arduino MKRZero"
-mkrzero.build.usb_manufacturer="Arduino LLC"
-mkrzero.build.board=SAMD_MKRZERO
-mkrzero.build.core=arduino
-mkrzero.build.extra_flags=-DUSE_ARDUINO_MKR_PIN_LAYOUT -D__SAMD21G18A__ {build.usb_flags}
-mkrzero.build.ldscript=linker_scripts/gcc/flash_with_bootloader.ld
-mkrzero.build.openocdscript=openocd_scripts/arduino_zero.cfg
-mkrzero.build.variant=mkrzero
-mkrzero.build.vid=0x2341
-mkrzero.build.pid=0x804f
-mkrzero.bootloader.tool=openocd
-mkrzero.bootloader.file=mkrzero/samd21_sam_ba_arduino_mkrzero.bin
-
-# Arduino MKR WiFi 1010
-# --------------------
-mkrwifi1010.name=Arduino MKR WiFi 1010
-mkrwifi1010.vid.0=0x2341
-mkrwifi1010.pid.0=0x8054
-mkrwifi1010.vid.1=0x2341
-mkrwifi1010.pid.1=0x0054
-
-mkrwifi1010.upload.tool=bossac
-mkrwifi1010.upload.protocol=sam-ba
-mkrwifi1010.upload.maximum_size=262144
-mkrwifi1010.upload.use_1200bps_touch=true
-mkrwifi1010.upload.wait_for_upload_port=true
-mkrwifi1010.upload.native_usb=true
-mkrwifi1010.build.mcu=cortex-m0plus
-mkrwifi1010.build.f_cpu=48000000L
-mkrwifi1010.build.usb_product="Arduino MKR WiFi 1010"
-mkrwifi1010.build.usb_manufacturer="Arduino LLC"
-mkrwifi1010.build.board=SAMD_MKRWIFI1010
-mkrwifi1010.build.core=arduino
-mkrwifi1010.build.extra_flags=-DUSE_ARDUINO_MKR_PIN_LAYOUT -D__SAMD21G18A__ {build.usb_flags} -DUSE_BQ24195L_PMIC
-mkrwifi1010.build.ldscript=linker_scripts/gcc/flash_with_bootloader.ld
-mkrwifi1010.build.openocdscript=openocd_scripts/arduino_zero.cfg
-mkrwifi1010.build.variant=mkrwifi1010
-mkrwifi1010.build.vid=0x2341
-mkrwifi1010.build.pid=0x8054
-mkrwifi1010.bootloader.tool=openocd
-mkrwifi1010.bootloader.file=mkrwifi1010/samd21_sam_ba_arduino_mkrwifi1010.bin
-
-# Arduino MKR FOX 1200
-# --------------------
-mkrfox1200.name=Arduino MKR FOX 1200
-mkrfox1200.vid.0=0x2341
-mkrfox1200.pid.0=0x8050
-mkrfox1200.vid.1=0x2341
-mkrfox1200.pid.1=0x0050
-
-mkrfox1200.upload.tool=bossac
-mkrfox1200.upload.protocol=sam-ba
-mkrfox1200.upload.maximum_size=262144
-mkrfox1200.upload.use_1200bps_touch=true
-mkrfox1200.upload.wait_for_upload_port=true
-mkrfox1200.upload.native_usb=true
-mkrfox1200.build.mcu=cortex-m0plus
-mkrfox1200.build.f_cpu=48000000L
-mkrfox1200.build.usb_product="Arduino MKR FOX 1200"
-mkrfox1200.build.usb_manufacturer="Arduino LLC"
-mkrfox1200.build.board=SAMD_MKRFox1200
-mkrfox1200.build.core=arduino
-mkrfox1200.build.extra_flags=-DUSE_ARDUINO_MKR_PIN_LAYOUT -D__SAMD21G18A__ {build.usb_flags}
-mkrfox1200.build.ldscript=linker_scripts/gcc/flash_with_bootloader.ld
-mkrfox1200.build.openocdscript=openocd_scripts/arduino_zero.cfg
-mkrfox1200.build.variant=mkrfox1200
-mkrfox1200.build.vid=0x2341
-mkrfox1200.build.pid=0x8050
-mkrfox1200.bootloader.tool=openocd
-mkrfox1200.bootloader.file=mkrfox1200/samd21_sam_ba_arduino_mkrfox1200.bin
-
-# Arduino MKR WAN 1300
-# --------------------
-mkrwan1300.name=Arduino MKR WAN 1300
-mkrwan1300.vid.0=0x2341
-mkrwan1300.pid.0=0x8053
-mkrwan1300.vid.1=0x2341
-mkrwan1300.pid.1=0x0053
-
-mkrwan1300.upload.tool=bossac
-mkrwan1300.upload.protocol=sam-ba
-mkrwan1300.upload.maximum_size=262144
-mkrwan1300.upload.use_1200bps_touch=true
-mkrwan1300.upload.wait_for_upload_port=true
-mkrwan1300.upload.native_usb=true
-mkrwan1300.build.mcu=cortex-m0plus
-mkrwan1300.build.f_cpu=48000000L
-mkrwan1300.build.usb_product="Arduino MKR WAN 1300"
-mkrwan1300.build.usb_manufacturer="Arduino LLC"
-mkrwan1300.build.board=SAMD_MKRWAN1300
-mkrwan1300.build.core=arduino
-mkrwan1300.build.extra_flags=-DUSE_ARDUINO_MKR_PIN_LAYOUT -D__SAMD21G18A__ {build.usb_flags}
-mkrwan1300.build.ldscript=linker_scripts/gcc/flash_with_bootloader.ld
-mkrwan1300.build.openocdscript=openocd_scripts/arduino_zero.cfg
-mkrwan1300.build.variant=mkrwan1300
-mkrwan1300.build.vid=0x2341
-mkrwan1300.build.pid=0x8053
-mkrwan1300.bootloader.tool=openocd
-mkrwan1300.bootloader.file=mkrwan1300/samd21_sam_ba_arduino_mkrwan1300.bin
-
-# Arduino MKR GSM 1400
-# --------------------
-mkrgsm1400.name=Arduino MKR GSM 1400
-mkrgsm1400.vid.0=0x2341
-mkrgsm1400.pid.0=0x8052
-mkrgsm1400.vid.1=0x2341
-mkrgsm1400.pid.1=0x0052
-
-mkrgsm1400.upload.tool=bossac
-mkrgsm1400.upload.protocol=sam-ba
-mkrgsm1400.upload.maximum_size=262144
-mkrgsm1400.upload.use_1200bps_touch=true
-mkrgsm1400.upload.wait_for_upload_port=true
-mkrgsm1400.upload.native_usb=true
-mkrgsm1400.build.mcu=cortex-m0plus
-mkrgsm1400.build.f_cpu=48000000L
-mkrgsm1400.build.usb_product="Arduino MKR GSM 1400"
-mkrgsm1400.build.usb_manufacturer="Arduino LLC"
-mkrgsm1400.build.board=SAMD_MKRGSM1400
-mkrgsm1400.build.core=arduino
-mkrgsm1400.build.extra_flags=-DUSE_ARDUINO_MKR_PIN_LAYOUT -D__SAMD21G18A__ {build.usb_flags} -DUSE_BQ24195L_PMIC
-mkrgsm1400.build.ldscript=linker_scripts/gcc/flash_with_bootloader.ld
-mkrgsm1400.build.openocdscript=openocd_scripts/arduino_zero.cfg
-mkrgsm1400.build.variant=mkrgsm1400
-mkrgsm1400.build.vid=0x2341
-mkrgsm1400.build.pid=0x8052
-mkrgsm1400.bootloader.tool=openocd
-mkrgsm1400.bootloader.file=mkrgsm1400/samd21_sam_ba_arduino_mkrgsm1400.bin
-
-# Arduino MKR NB 1500
-# --------------------
-mkrnb1500.name=Arduino MKR NB 1500
-mkrnb1500.vid.0=0x2341
-mkrnb1500.pid.0=0x8055
-mkrnb1500.vid.1=0x2341
-mkrnb1500.pid.1=0x0055
-
-mkrnb1500.upload.tool=bossac
-mkrnb1500.upload.protocol=sam-ba
-mkrnb1500.upload.maximum_size=262144
-mkrnb1500.upload.use_1200bps_touch=true
-mkrnb1500.upload.wait_for_upload_port=true
-mkrnb1500.upload.native_usb=true
-mkrnb1500.build.mcu=cortex-m0plus
-mkrnb1500.build.f_cpu=48000000L
-mkrnb1500.build.usb_product="Arduino MKR NB 1500"
-mkrnb1500.build.usb_manufacturer="Arduino LLC"
-mkrnb1500.build.board=SAMD_MKRNB1500
-mkrnb1500.build.core=arduino
-mkrnb1500.build.extra_flags=-DUSE_ARDUINO_MKR_PIN_LAYOUT -D__SAMD21G18A__ {build.usb_flags} -DUSE_BQ24195L_PMIC
-mkrnb1500.build.ldscript=linker_scripts/gcc/flash_with_bootloader.ld
-mkrnb1500.build.openocdscript=openocd_scripts/arduino_zero.cfg
-mkrnb1500.build.variant=mkrnb1500
-mkrnb1500.build.vid=0x2341
-mkrnb1500.build.pid=0x8055
-mkrnb1500.bootloader.tool=openocd
-mkrnb1500.bootloader.file=mkrnb1500/samd21_sam_ba_arduino_mkrnb1500.bin
-
-# Adafruit Circuit Playground M0
+menu.cache=Cache
+menu.speed=CPU Speed
+menu.opt=Optimize
+menu.maxqspi=Max QSPI
+menu.usbstack=USB Stack
+menu.debug=Debug
+
+# Adafruit Feather M0 (SAMD21)
+# ------------------------------
+adafruit_feather_m0.name=Adafruit Feather M0
+adafruit_feather_m0.vid.0=0x239A
+adafruit_feather_m0.pid.0=0x800B
+adafruit_feather_m0.vid.1=0x239A
+adafruit_feather_m0.pid.1=0x000B
+adafruit_feather_m0.vid.2=0x239A
+adafruit_feather_m0.pid.2=0x0015
+adafruit_feather_m0.upload.tool=bossac
+adafruit_feather_m0.upload.protocol=sam-ba
+adafruit_feather_m0.upload.maximum_size=262144
+adafruit_feather_m0.upload.offset=0x2000
+adafruit_feather_m0.upload.use_1200bps_touch=true
+adafruit_feather_m0.upload.wait_for_upload_port=true
+adafruit_feather_m0.upload.native_usb=true
+adafruit_feather_m0.build.mcu=cortex-m0plus
+adafruit_feather_m0.build.f_cpu=48000000L
+adafruit_feather_m0.build.usb_product="Feather M0"
+adafruit_feather_m0.build.usb_manufacturer="Adafruit"
+adafruit_feather_m0.build.board=SAMD_ZERO
+adafruit_feather_m0.build.core=arduino
+adafruit_feather_m0.build.extra_flags=-DARDUINO_SAMD_ZERO -DARM_MATH_CM0PLUS -DADAFRUIT_FEATHER_M0 -D__SAMD21G18A__ {build.usb_flags}
+adafruit_feather_m0.build.ldscript=linker_scripts/gcc/flash_with_bootloader.ld
+adafruit_feather_m0.build.openocdscript=openocd_scripts/feather_m0.cfg
+adafruit_feather_m0.build.variant=feather_m0
+adafruit_feather_m0.build.variant_system_lib=
+adafruit_feather_m0.build.vid=0x239A
+adafruit_feather_m0.build.pid=0x800B
+adafruit_feather_m0.bootloader.tool=openocd
+adafruit_feather_m0.bootloader.file=featherM0/bootloader-feather_m0-v2.0.0-adafruit.5.bin
+adafruit_feather_m0.menu.opt.small=Small (-Os) (standard)
+adafruit_feather_m0.menu.opt.small.build.flags.optimize=-Os
+adafruit_feather_m0.menu.opt.fast=Fast (-O2)
+adafruit_feather_m0.menu.opt.fast.build.flags.optimize=-O2
+adafruit_feather_m0.menu.opt.faster=Faster (-O3)
+adafruit_feather_m0.menu.opt.faster.build.flags.optimize=-O3
+adafruit_feather_m0.menu.opt.fastest=Fastest (-Ofast)
+adafruit_feather_m0.menu.opt.fastest.build.flags.optimize=-Ofast
+adafruit_feather_m0.menu.opt.dragons=Here be dragons (-Ofast -funroll-loops)
+adafruit_feather_m0.menu.opt.dragons.build.flags.optimize=-Ofast -funroll-loops
+adafruit_feather_m0.menu.usbstack.arduino=Arduino
+adafruit_feather_m0.menu.usbstack.tinyusb=TinyUSB
+adafruit_feather_m0.menu.usbstack.tinyusb.build.flags.usbstack=-DUSE_TINYUSB
+adafruit_feather_m0.menu.debug.off=Off
+adafruit_feather_m0.menu.debug.on=On
+adafruit_feather_m0.menu.debug.on.build.flags.debug=-g
+
+
+# Adafruit Feather M0 Express (SAMD21)
+# ------------------------------
+adafruit_feather_m0_express.name=Adafruit Feather M0 Express
+adafruit_feather_m0_express.vid.0=0x239A
+adafruit_feather_m0_express.pid.0=0x801B
+adafruit_feather_m0_express.vid.1=0x239A
+adafruit_feather_m0_express.pid.1=0x001B
+adafruit_feather_m0_express.upload.tool=bossac
+adafruit_feather_m0_express.upload.protocol=sam-ba
+adafruit_feather_m0_express.upload.maximum_size=262144
+adafruit_feather_m0_express.upload.offset=0x2000
+adafruit_feather_m0_express.upload.use_1200bps_touch=true
+adafruit_feather_m0_express.upload.wait_for_upload_port=true
+adafruit_feather_m0_express.upload.native_usb=true
+adafruit_feather_m0_express.build.mcu=cortex-m0plus
+adafruit_feather_m0_express.build.f_cpu=48000000L
+adafruit_feather_m0_express.build.usb_product="Feather M0 Express"
+adafruit_feather_m0_express.build.usb_manufacturer="Adafruit"
+adafruit_feather_m0_express.build.board=SAMD_FEATHER_M0_EXPRESS
+adafruit_feather_m0_express.build.core=arduino
+adafruit_feather_m0_express.build.extra_flags=-DARDUINO_SAMD_ZERO -DARDUINO_SAMD_FEATHER_M0 -DARM_MATH_CM0PLUS -DADAFRUIT_FEATHER_M0_EXPRESS -D__SAMD21G18A__ {build.usb_flags}
+adafruit_feather_m0_express.build.ldscript=linker_scripts/gcc/flash_with_bootloader.ld
+adafruit_feather_m0_express.build.openocdscript=openocd_scripts/feather_m0_express.cfg
+adafruit_feather_m0_express.build.variant=feather_m0_express
+adafruit_feather_m0_express.build.variant_system_lib=
+adafruit_feather_m0_express.build.vid=0x239A
+adafruit_feather_m0_express.build.pid=0x801B
+adafruit_feather_m0_express.bootloader.tool=openocd
+adafruit_feather_m0_express.bootloader.file=featherM0/bootloader-feather_m0-v2.0.0-adafruit.5.bin
+adafruit_feather_m0_express.menu.opt.small=Small (-Os) (standard)
+adafruit_feather_m0_express.menu.opt.small.build.flags.optimize=-Os
+adafruit_feather_m0_express.menu.opt.fast=Fast (-O2)
+adafruit_feather_m0_express.menu.opt.fast.build.flags.optimize=-O2
+adafruit_feather_m0_express.menu.opt.faster=Faster (-O3)
+adafruit_feather_m0_express.menu.opt.faster.build.flags.optimize=-O3
+adafruit_feather_m0_express.menu.opt.fastest=Fastest (-Ofast)
+adafruit_feather_m0_express.menu.opt.fastest.build.flags.optimize=-Ofast
+adafruit_feather_m0_express.menu.opt.dragons=Here be dragons (-Ofast -funroll-loops)
+adafruit_feather_m0_express.menu.opt.dragons.build.flags.optimize=-Ofast -funroll-loops
+adafruit_feather_m0_express.menu.usbstack.arduino=Arduino
+adafruit_feather_m0_express.menu.usbstack.tinyusb=TinyUSB
+adafruit_feather_m0_express.menu.usbstack.tinyusb.build.flags.usbstack=-DUSE_TINYUSB
+adafruit_feather_m0_express.menu.debug.off=Off
+adafruit_feather_m0_express.menu.debug.on=On
+adafruit_feather_m0_express.menu.debug.on.build.flags.debug=-g
+
+
+#adafruit_radio_m0.name=Adafruit M0 Radio (Native USB Port)
+#adafruit_radio_m0.vid.0=0x239A
+#adafruit_radio_m0.pid.0=0x8014
+#adafruit_radio_m0.vid.1=0x239A
+#adafruit_radio_m0.pid.1=0x0014
+#adafruit_radio_m0.upload.tool=bossac
+#adafruit_radio_m0.upload.protocol=sam-ba
+#adafruit_radio_m0.upload.maximum_size=262144
+#adafruit_radio_m0.upload.use_1200bps_touch=true
+#adafruit_radio_m0.upload.wait_for_upload_port=true
+#adafruit_radio_m0.upload.native_usb=true
+#adafruit_radio_m0.build.mcu=cortex-m0plus
+#adafruit_radio_m0.build.f_cpu=48000000L
+#adafruit_radio_m0.build.usb_product="Radio M0"
+#adafruit_radio_m0.build.usb_manufacturer="Adafruit"
+#adafruit_radio_m0.build.board=SAMD_ZERO
+#adafruit_radio_m0.build.core=arduino
+#adafruit_radio_m0.build.extra_flags=-D__SAMR21G18A__ -DARM_MATH_CM0PLUS {build.usb_flags}
+#adafruit_radio_m0.build.ldscript=linker_scripts/gcc/flash_with_bootloader.ld
+#adafruit_radio_m0.build.openocdscript=openocd_scripts/zero_radio.cfg
+#adafruit_radio_m0.build.variant=zero_radio
+#adafruit_radio_m0.build.variant_system_lib=
+#adafruit_radio_m0.build.vid=0x239A
+#adafruit_radio_m0.build.pid=0x8014
+#adafruit_radio_m0.bootloader.tool=openocd
+#adafruit_radio_m0.bootloader.file=feather/samr21_sam_ba.bin
+
+# Adafruit Metro M0 Express (SAMD21)
+# ------------------------------
+adafruit_metro_m0.name=Adafruit Metro M0 Express
+adafruit_metro_m0.vid.0=0x239A
+adafruit_metro_m0.pid.0=0x8013
+adafruit_metro_m0.vid.1=0x239A
+adafruit_metro_m0.pid.1=0x0013
+adafruit_metro_m0.upload.tool=bossac
+adafruit_metro_m0.upload.protocol=sam-ba
+adafruit_metro_m0.upload.maximum_size=262144
+adafruit_metro_m0.upload.offset=0x2000
+adafruit_metro_m0.upload.use_1200bps_touch=true
+adafruit_metro_m0.upload.wait_for_upload_port=true
+adafruit_metro_m0.upload.native_usb=true
+adafruit_metro_m0.build.mcu=cortex-m0plus
+adafruit_metro_m0.build.f_cpu=48000000L
+adafruit_metro_m0.build.usb_product="Metro M0 Express"
+adafruit_metro_m0.build.usb_manufacturer="Adafruit"
+adafruit_metro_m0.build.board=SAMD_ZERO
+adafruit_metro_m0.build.core=arduino
+adafruit_metro_m0.build.extra_flags=-D__SAMD21G18A__ -DARDUINO_SAMD_ZERO -DARM_MATH_CM0PLUS -DADAFRUIT_METRO_M0_EXPRESS {build.usb_flags}
+adafruit_metro_m0.build.ldscript=linker_scripts/gcc/flash_with_bootloader.ld
+adafruit_metro_m0.build.openocdscript=openocd_scripts/metro_m0.cfg
+adafruit_metro_m0.build.variant=metro_m0
+adafruit_metro_m0.build.variant_system_lib=
+adafruit_metro_m0.build.vid=0x239A
+adafruit_metro_m0.build.pid=0x8013
+adafruit_metro_m0.bootloader.tool=openocd
+adafruit_metro_m0.bootloader.file=metroM0/bootloader-metro_m0-v2.0.0-adafruit.5.bin
+adafruit_metro_m0.menu.opt.small=Small (-Os) (standard)
+adafruit_metro_m0.menu.opt.small.build.flags.optimize=-Os
+adafruit_metro_m0.menu.opt.fast=Fast (-O2)
+adafruit_metro_m0.menu.opt.fast.build.flags.optimize=-O2
+adafruit_metro_m0.menu.opt.faster=Faster (-O3)
+adafruit_metro_m0.menu.opt.faster.build.flags.optimize=-O3
+adafruit_metro_m0.menu.opt.fastest=Fastest (-Ofast)
+adafruit_metro_m0.menu.opt.fastest.build.flags.optimize=-Ofast
+adafruit_metro_m0.menu.opt.dragons=Here be dragons (-Ofast -funroll-loops)
+adafruit_metro_m0.menu.opt.dragons.build.flags.optimize=-Ofast -funroll-loops
+adafruit_metro_m0.menu.usbstack.arduino=Arduino
+adafruit_metro_m0.menu.usbstack.tinyusb=TinyUSB
+adafruit_metro_m0.menu.usbstack.tinyusb.build.flags.usbstack=-DUSE_TINYUSB
+adafruit_metro_m0.menu.debug.off=Off
+adafruit_metro_m0.menu.debug.on=On
+adafruit_metro_m0.menu.debug.on.build.flags.debug=-g
+
+
+# Adafruit Circuit Playground Express (SAMD21)
 # ------------------------------
 adafruit_circuitplayground_m0.name=Adafruit Circuit Playground Express
 adafruit_circuitplayground_m0.vid.0=0x239A
 adafruit_circuitplayground_m0.pid.0=0x8018
 adafruit_circuitplayground_m0.vid.1=0x239A
-adafruit_circuitplayground_m0.pid.1=0x0018
+adafruit_circuitplayground_m0.pid.1=0x0019
 adafruit_circuitplayground_m0.upload.tool=bossac
 adafruit_circuitplayground_m0.upload.protocol=sam-ba
 adafruit_circuitplayground_m0.upload.maximum_size=262144
+adafruit_circuitplayground_m0.upload.offset=0x2000
 adafruit_circuitplayground_m0.upload.use_1200bps_touch=true
 adafruit_circuitplayground_m0.upload.wait_for_upload_port=true
 adafruit_circuitplayground_m0.upload.native_usb=true
@@ -326,163 +211,1677 @@ adafruit_circuitplayground_m0.build.usb_product="Circuit Playground Express"
 adafruit_circuitplayground_m0.build.usb_manufacturer="Adafruit"
 adafruit_circuitplayground_m0.build.board=SAMD_CIRCUITPLAYGROUND_EXPRESS
 adafruit_circuitplayground_m0.build.core=arduino
-adafruit_circuitplayground_m0.build.extra_flags=-DCRYSTALLESS -DARDUINO_SAMD_ZERO -D__SAMD21G18A__ {build.usb_flags}
+adafruit_circuitplayground_m0.build.extra_flags=-DCRYSTALLESS -DARDUINO_SAMD_ZERO -D__SAMD21G18A__ -DARM_MATH_CM0PLUS -DADAFRUIT_CIRCUITPLAYGROUND_M0 {build.usb_flags}
 adafruit_circuitplayground_m0.build.ldscript=linker_scripts/gcc/flash_with_bootloader.ld
-adafruit_circuitplayground_m0.build.openocdscript=openocd_scripts/arduino_zero.cfg
+adafruit_circuitplayground_m0.build.openocdscript=openocd_scripts/circuit_play.cfg
 adafruit_circuitplayground_m0.build.variant=circuitplay
 adafruit_circuitplayground_m0.build.variant_system_lib=
 adafruit_circuitplayground_m0.build.vid=0x239A
 adafruit_circuitplayground_m0.build.pid=0x8018
 adafruit_circuitplayground_m0.bootloader.tool=openocd
-adafruit_circuitplayground_m0.bootloader.file=circuitplay/circuitplay_m0_samd21g18_sam_ba.bin
-
-# Arduino M0 PRO (with) bootloader - Programming port
-# ---------------------------------------------------
-mzero_pro_bl_dbg.name=Arduino M0 Pro (Programming Port)
-mzero_pro_bl_dbg.vid.0=0x03eb
-mzero_pro_bl_dbg.pid.0=0x2111
-mzero_pro_bl_dbg.upload.tool=openocd-withbootsize
-mzero_pro_bl_dbg.upload.protocol=sam-ba
-mzero_pro_bl_dbg.upload.maximum_size=262144
-mzero_pro_bl_dbg.upload.use_1200bps_touch=false
-mzero_pro_bl_dbg.upload.wait_for_upload_port=false
-mzero_pro_bl_dbg.upload.native_usb=false
-mzero_pro_bl_dbg.build.mcu=cortex-m0plus
-mzero_pro_bl_dbg.build.f_cpu=48000000L
-mzero_pro_bl_dbg.build.usb_product="Arduino M0 Pro"
-mzero_pro_bl_dbg.build.board=SAM_ZERO
-mzero_pro_bl_dbg.build.core=arduino
-mzero_pro_bl_dbg.build.extra_flags=-D__SAMD21G18A__ -mthumb {build.usb_flags}
-mzero_pro_bl_dbg.build.ldscript=linker_scripts/gcc/flash_with_bootloader.ld
-mzero_pro_bl_dbg.build.openocdscript=openocd_scripts/arduino_zero.cfg
-mzero_pro_bl_dbg.build.variant=arduino_mzero
-mzero_pro_bl_dbg.build.variant_system_lib=
-mzero_pro_bl_dbg.build.vid=0x2a03
-mzero_pro_bl_dbg.build.pid=0x804f
-mzero_pro_bl_dbg.build.preferred_out_format=hex
-mzero_pro_bl_dbg.bootloader.size=0x4000
-
-mzero_pro_bl_dbg.bootloader.tool=openocd-withbootsize
-mzero_pro_bl_dbg.bootloader.cmd_unprotect=at91samd bootloader 0
-mzero_pro_bl_dbg.bootloader.cmd_protect=at91samd bootloader 16384
-mzero_pro_bl_dbg.bootloader.cmd_protect_verify=at91samd bootloader
-mzero_pro_bl_dbg.bootloader.file=mzero/Bootloader_D21_M0_Pro_150427.hex
-
-# Arduino M0 PRO (with) bootloader - Native port
-# ----------------------------------------------
-mzero_pro_bl.name=Arduino M0 Pro (Native USB Port)
-mzero_pro_bl.vid.0=0x2a03
-mzero_pro_bl.pid.0=0x004d
-mzero_pro_bl.vid.1=0x2a03
-mzero_pro_bl.pid.1=0x804d
-mzero_pro_bl.vid.2=0x2a03
-mzero_pro_bl.pid.2=0x004f
-mzero_pro_bl.vid.3=0x2a03
-mzero_pro_bl.pid.3=0x804f
-mzero_pro_bl.upload.tool=avrdude
-mzero_pro_bl.upload.protocol=stk500v2
-mzero_pro_bl.upload.maximum_size=262144
-mzero_pro_bl.upload.use_1200bps_touch=true
-mzero_pro_bl.upload.wait_for_upload_port=true
-mzero_pro_bl.upload.native_usb=true
-mzero_pro_bl.upload.speed=57600
-mzero_pro_bl.build.mcu=cortex-m0plus
-mzero_pro_bl.build.f_cpu=48000000L
-mzero_pro_bl.build.usb_product="Arduino M0 Pro"
-mzero_pro_bl.build.board=SAM_ZERO
-mzero_pro_bl.build.core=arduino
-mzero_pro_bl.build.extra_flags=-D__SAMD21G18A__ -mthumb {build.usb_flags}
-mzero_pro_bl.build.ldscript=linker_scripts/gcc/flash_with_bootloader.ld
-mzero_pro_bl.build.openocdscript=openocd_scripts/arduino_zero.cfg
-mzero_pro_bl.build.variant=arduino_mzero
-mzero_pro_bl.build.variant_system_lib=
-mzero_pro_bl.build.vid=0x2a03
-mzero_pro_bl.build.pid=0x804f
-mzero_pro_bl.build.preferred_out_format=hex
-mzero_pro_bl.bootloader.size=0x4000
-mzero_pro_bl.build.emu.mcu=atmega2560
-mzero_pro_bl.bootloader.tool=openocd-withbootsize
-mzero_pro_bl.bootloader.file=mzero/Bootloader_D21_M0_Pro_150427.hex
-mzero_pro_bl.bootloader.low_fuses=0xff
-
-# Arduino M0 (with) Bootloader
-# ----------------------------
-mzero_bl.name=Arduino M0
-mzero_bl.vid.0=0x2a03
-mzero_bl.pid.0=0x004d
-mzero_bl.vid.1=0x2a03
-mzero_bl.pid.1=0x804d
-mzero_bl.vid.2=0x2a03
-mzero_bl.pid.2=0x004e
-mzero_bl.vid.3=0x2a03
-mzero_bl.pid.3=0x804e
-mzero_bl.upload.tool=avrdude
-mzero_bl.upload.protocol=stk500v2
-mzero_bl.upload.maximum_size=262144
-mzero_bl.upload.use_1200bps_touch=true
-mzero_bl.upload.wait_for_upload_port=true
-mzero_bl.upload.native_usb=true
-mzero_bl.upload.speed=57600
-mzero_bl.build.mcu=cortex-m0plus
-mzero_bl.build.f_cpu=48000000L
-mzero_bl.build.usb_product="Arduino M0"
-mzero_bl.build.board=SAM_ZERO
-mzero_bl.build.core=arduino
-mzero_bl.build.extra_flags=-D__SAMD21G18A__ -mthumb {build.usb_flags}
-mzero_bl.build.ldscript=linker_scripts/gcc/flash_with_bootloader.ld
-mzero_bl.build.openocdscript=openocd_scripts/arduino_zero.cfg
-mzero_bl.build.variant=arduino_mzero
-mzero_bl.build.variant_system_lib=
-mzero_bl.build.vid=0x2a03
-mzero_bl.build.pid=0x804e
-mzero_bl.build.preferred_out_format=hex
-mzero_bl.bootloader.size=0x4000
-mzero_bl.build.emu.mcu=atmega2560
-mzero_bl.bootloader.tool=openocd-withbootsize
-mzero_bl.bootloader.low_fuses=0xff
-mzero_bl.bootloader.file=mzero/Bootloader_D21_M0_150515.hex
-
-# Arduino Tian (with) Bootloader
-# ------------------------------
-tian.name=Arduino Tian
-tian.upload.via_ssh=true
-tian.vid.0=0x10C4
-tian.pid.0=0xEA70
-tian.descriptor.0=Enhanced Com Port
-
-tian.upload.tool=avrdude
-#tian.upload.protocol=stk500v2
-tian.upload.protocol=wiring
-tian.upload.maximum_size=262144
-tian.upload.use_1200bps_touch=true
-tian.upload.wait_for_upload_port=true
-tian.upload.native_usb=true
-tian.upload.speed=57600
-tian.build.mcu=cortex-m0plus
-tian.build.f_cpu=48000000L
-tian.build.usb_product="Arduino Tian"
-tian.build.board=SAMD_TIAN
-tian.build.core=arduino
-tian.build.extra_flags=-D__SAMD21G18A__ -mthumb {build.usb_flags}
-tian.build.ldscript=linker_scripts/gcc/flash_with_bootloader.ld
-tian.build.openocdscript=openocd_scripts/arduino_zero.cfg
-tian.build.variant=arduino_mzero
-tian.build.variant_system_lib=
-tian.build.vid=0x2a03
-tian.build.pid=0x8052
-tian.build.preferred_out_format=hex
-tian.bootloader.size=0x4000
-tian.build.emu.mcu=atmega2560
-tian.bootloader.tool=openocd-withbootsize
-tian.bootloader.low_fuses=0xff
-tian.bootloader.file=sofia/Sofia_Tian_151118.hex
-tian.drivers=SiliconLabs-CP2105/Silicon Labs VCP Driver.pkg
-
-# Arduino Tian Console port (not for upload)
-# ------------------------------------------
-tian_cons.name=Arduino Tian (MIPS Console port)
-tian_cons.vid.0=0x10C4
-tian_cons.pid.0=0xEA70
-tian_cons.descriptor.0=Standard Com Port
-tian_cons.hide=true
-tian_cons.build.board=SAMD_TIAN
+adafruit_circuitplayground_m0.bootloader.file=circuitplayM0/bootloader-circuitplay_m0-v2.0.0-adafruit.5.bin
+adafruit_circuitplayground_m0.menu.opt.small=Small (-Os) (standard)
+adafruit_circuitplayground_m0.menu.opt.small.build.flags.optimize=-Os
+adafruit_circuitplayground_m0.menu.opt.fast=Fast (-O2)
+adafruit_circuitplayground_m0.menu.opt.fast.build.flags.optimize=-O2
+adafruit_circuitplayground_m0.menu.opt.faster=Faster (-O3)
+adafruit_circuitplayground_m0.menu.opt.faster.build.flags.optimize=-O3
+adafruit_circuitplayground_m0.menu.opt.fastest=Fastest (-Ofast)
+adafruit_circuitplayground_m0.menu.opt.fastest.build.flags.optimize=-Ofast
+adafruit_circuitplayground_m0.menu.opt.dragons=Here be dragons (-Ofast -funroll-loops)
+adafruit_circuitplayground_m0.menu.opt.dragons.build.flags.optimize=-Ofast -funroll-loops
+adafruit_circuitplayground_m0.menu.usbstack.arduino=Arduino
+adafruit_circuitplayground_m0.menu.usbstack.tinyusb=TinyUSB
+adafruit_circuitplayground_m0.menu.usbstack.tinyusb.build.flags.usbstack=-DUSE_TINYUSB
+adafruit_circuitplayground_m0.menu.debug.off=Off
+adafruit_circuitplayground_m0.menu.debug.on=On
+adafruit_circuitplayground_m0.menu.debug.on.build.flags.debug=-g
+
+
+# Adafruit Gemma M0 (SAMD21)
+# ------------------------------
+adafruit_gemma_m0.name=Adafruit Gemma M0
+adafruit_gemma_m0.vid.0=0x239A
+adafruit_gemma_m0.pid.0=0x801C
+adafruit_gemma_m0.vid.1=0x239A
+adafruit_gemma_m0.pid.1=0x001C
+adafruit_gemma_m0.upload.tool=bossac
+adafruit_gemma_m0.upload.protocol=sam-ba
+adafruit_gemma_m0.upload.maximum_size=262144
+adafruit_gemma_m0.upload.offset=0x2000
+adafruit_gemma_m0.upload.use_1200bps_touch=true
+adafruit_gemma_m0.upload.wait_for_upload_port=true
+adafruit_gemma_m0.upload.native_usb=true
+adafruit_gemma_m0.build.mcu=cortex-m0plus
+adafruit_gemma_m0.build.f_cpu=48000000L
+adafruit_gemma_m0.build.usb_product="Gemma M0"
+adafruit_gemma_m0.build.usb_manufacturer="Adafruit"
+adafruit_gemma_m0.build.board=GEMMA_M0
+adafruit_gemma_m0.build.core=arduino
+adafruit_gemma_m0.build.extra_flags=-DCRYSTALLESS -DADAFRUIT_GEMMA_M0 -D__SAMD21E18A__ -DARM_MATH_CM0PLUS {build.usb_flags}
+adafruit_gemma_m0.build.ldscript=linker_scripts/gcc/flash_with_bootloader.ld
+adafruit_gemma_m0.build.openocdscript=openocd_scripts/gemma_m0.cfg
+adafruit_gemma_m0.build.variant=gemma_m0
+adafruit_gemma_m0.build.variant_system_lib=
+adafruit_gemma_m0.build.vid=0x239A
+adafruit_gemma_m0.build.pid=0x801C
+adafruit_gemma_m0.bootloader.tool=openocd
+adafruit_gemma_m0.bootloader.file=gemmaM0/bootloader-gemma_m0-v2.0.0-adafruit.5.bin
+adafruit_gemma_m0.menu.opt.small=Small (-Os) (standard)
+adafruit_gemma_m0.menu.opt.small.build.flags.optimize=-Os
+adafruit_gemma_m0.menu.opt.fast=Fast (-O2)
+adafruit_gemma_m0.menu.opt.fast.build.flags.optimize=-O2
+adafruit_gemma_m0.menu.opt.faster=Faster (-O3)
+adafruit_gemma_m0.menu.opt.faster.build.flags.optimize=-O3
+adafruit_gemma_m0.menu.opt.fastest=Fastest (-Ofast)
+adafruit_gemma_m0.menu.opt.fastest.build.flags.optimize=-Ofast
+adafruit_gemma_m0.menu.opt.dragons=Here be dragons (-Ofast -funroll-loops)
+adafruit_gemma_m0.menu.opt.dragons.build.flags.optimize=-Ofast -funroll-loops
+adafruit_gemma_m0.menu.usbstack.arduino=Arduino
+adafruit_gemma_m0.menu.usbstack.tinyusb=TinyUSB
+adafruit_gemma_m0.menu.usbstack.tinyusb.build.flags.usbstack=-DUSE_TINYUSB
+adafruit_gemma_m0.menu.debug.off=Off
+adafruit_gemma_m0.menu.debug.on=On
+adafruit_gemma_m0.menu.debug.on.build.flags.debug=-g
+
+# Adafruit Trinket M0 (SAMD21)
+# ------------------------------
+adafruit_trinket_m0.name=Adafruit Trinket M0
+adafruit_trinket_m0.vid.0=0x239A
+adafruit_trinket_m0.pid.0=0x801E
+adafruit_trinket_m0.vid.1=0x239A
+adafruit_trinket_m0.pid.1=0x001E
+adafruit_trinket_m0.upload.tool=bossac
+adafruit_trinket_m0.upload.protocol=sam-ba
+adafruit_trinket_m0.upload.maximum_size=262144
+adafruit_trinket_m0.upload.offset=0x2000
+adafruit_trinket_m0.upload.use_1200bps_touch=true
+adafruit_trinket_m0.upload.wait_for_upload_port=true
+adafruit_trinket_m0.upload.native_usb=true
+adafruit_trinket_m0.build.mcu=cortex-m0plus
+adafruit_trinket_m0.build.f_cpu=48000000L
+adafruit_trinket_m0.build.usb_product="Trinket M0"
+adafruit_trinket_m0.build.usb_manufacturer="Adafruit"
+adafruit_trinket_m0.build.board=TRINKET_M0
+adafruit_trinket_m0.build.core=arduino
+adafruit_trinket_m0.build.extra_flags=-DCRYSTALLESS -DADAFRUIT_TRINKET_M0 -D__SAMD21E18A__ -DARM_MATH_CM0PLUS {build.usb_flags}
+adafruit_trinket_m0.build.ldscript=linker_scripts/gcc/flash_with_bootloader.ld
+adafruit_trinket_m0.build.openocdscript=openocd_scripts/trinket_m0.cfg
+adafruit_trinket_m0.build.variant=trinket_m0
+adafruit_trinket_m0.build.variant_system_lib=
+adafruit_trinket_m0.build.vid=0x239A
+adafruit_trinket_m0.build.pid=0x801E
+adafruit_trinket_m0.bootloader.tool=openocd
+adafruit_trinket_m0.bootloader.file=trinketm0/bootloader-trinket_m0-v2.0.0-adafruit.5.bin
+adafruit_trinket_m0.menu.opt.small=Small (-Os) (standard)
+adafruit_trinket_m0.menu.opt.small.build.flags.optimize=-Os
+adafruit_trinket_m0.menu.opt.fast=Fast (-O2)
+adafruit_trinket_m0.menu.opt.fast.build.flags.optimize=-O2
+adafruit_trinket_m0.menu.opt.faster=Faster (-O3)
+adafruit_trinket_m0.menu.opt.faster.build.flags.optimize=-O3
+adafruit_trinket_m0.menu.opt.fastest=Fastest (-Ofast)
+adafruit_trinket_m0.menu.opt.fastest.build.flags.optimize=-Ofast
+adafruit_trinket_m0.menu.opt.dragons=Here be dragons (-Ofast -funroll-loops)
+adafruit_trinket_m0.menu.opt.dragons.build.flags.optimize=-Ofast -funroll-loops
+adafruit_trinket_m0.menu.usbstack.arduino=Arduino
+adafruit_trinket_m0.menu.usbstack.tinyusb=TinyUSB
+adafruit_trinket_m0.menu.usbstack.tinyusb.build.flags.usbstack=-DUSE_TINYUSB
+adafruit_trinket_m0.menu.debug.off=Off
+adafruit_trinket_m0.menu.debug.on=On
+adafruit_trinket_m0.menu.debug.on.build.flags.debug=-g
+
+# Adafruit QT Py M0 (SAMD21)
+# ------------------------------
+adafruit_qtpy_m0.name=Adafruit QT PY (SAMD21)
+adafruit_qtpy_m0.vid.0=0x239A
+adafruit_qtpy_m0.pid.0=0x80CB
+adafruit_qtpy_m0.vid.1=0x239A
+adafruit_qtpy_m0.pid.1=0x00CB
+adafruit_qtpy_m0.vid.1=0x239A
+adafruit_qtpy_m0.pid.1=0x00CC
+adafruit_qtpy_m0.upload.tool=bossac
+adafruit_qtpy_m0.upload.protocol=sam-ba
+adafruit_qtpy_m0.upload.maximum_size=262144
+adafruit_qtpy_m0.upload.offset=0x2000
+adafruit_qtpy_m0.upload.use_1200bps_touch=true
+adafruit_qtpy_m0.upload.wait_for_upload_port=true
+adafruit_qtpy_m0.upload.native_usb=true
+adafruit_qtpy_m0.build.mcu=cortex-m0plus
+adafruit_qtpy_m0.build.f_cpu=48000000L
+adafruit_qtpy_m0.build.usb_product="QT Py M0"
+adafruit_qtpy_m0.build.usb_manufacturer="Adafruit"
+adafruit_qtpy_m0.build.board=QTPY_M0
+adafruit_qtpy_m0.build.core=arduino
+adafruit_qtpy_m0.build.extra_flags=-DCRYSTALLESS -DADAFRUIT_QTPY_M0 -D__SAMD21E18A__ -DARM_MATH_CM0PLUS {build.usb_flags}
+adafruit_qtpy_m0.build.ldscript=linker_scripts/gcc/flash_with_bootloader.ld
+adafruit_qtpy_m0.build.openocdscript=openocd_scripts/trinket_m0.cfg
+adafruit_qtpy_m0.build.variant=qtpy_m0
+adafruit_qtpy_m0.build.variant_system_lib=
+adafruit_qtpy_m0.build.vid=0x239A
+adafruit_qtpy_m0.build.pid=0x80CB
+adafruit_qtpy_m0.bootloader.tool=openocd
+adafruit_qtpy_m0.bootloader.file=qtpyM0/bootloader-qtpy_m0.bin
+adafruit_qtpy_m0.menu.opt.small=Small (-Os) (standard)
+adafruit_qtpy_m0.menu.opt.small.build.flags.optimize=-Os
+adafruit_qtpy_m0.menu.opt.fast=Fast (-O2)
+adafruit_qtpy_m0.menu.opt.fast.build.flags.optimize=-O2
+adafruit_qtpy_m0.menu.opt.faster=Faster (-O3)
+adafruit_qtpy_m0.menu.opt.faster.build.flags.optimize=-O3
+adafruit_qtpy_m0.menu.opt.fastest=Fastest (-Ofast)
+adafruit_qtpy_m0.menu.opt.fastest.build.flags.optimize=-Ofast
+adafruit_qtpy_m0.menu.opt.dragons=Here be dragons (-Ofast -funroll-loops)
+adafruit_qtpy_m0.menu.opt.dragons.build.flags.optimize=-Ofast -funroll-loops
+adafruit_qtpy_m0.menu.usbstack.arduino=Arduino
+adafruit_qtpy_m0.menu.usbstack.tinyusb=TinyUSB
+adafruit_qtpy_m0.menu.usbstack.tinyusb.build.flags.usbstack=-DUSE_TINYUSB
+adafruit_qtpy_m0.menu.debug.off=Off
+adafruit_qtpy_m0.menu.debug.on=On
+adafruit_qtpy_m0.menu.debug.on.build.flags.debug=-g
+
+# Adafruit NeoPixel Trinkey (SAMD21)
+# ------------------------------
+adafruit_neotrinkey_m0.name=Adafruit Neo Trinkey (SAMD21)
+adafruit_neotrinkey_m0.vid.0=0x239A
+adafruit_neotrinkey_m0.pid.0=0x80EF
+adafruit_neotrinkey_m0.vid.1=0x239A
+adafruit_neotrinkey_m0.pid.1=0x00EF
+adafruit_neotrinkey_m0.vid.1=0x239A
+adafruit_neotrinkey_m0.pid.1=0x80F0
+adafruit_neotrinkey_m0.upload.tool=bossac
+adafruit_neotrinkey_m0.upload.protocol=sam-ba
+adafruit_neotrinkey_m0.upload.maximum_size=262144
+adafruit_neotrinkey_m0.upload.offset=0x2000
+adafruit_neotrinkey_m0.upload.use_1200bps_touch=true
+adafruit_neotrinkey_m0.upload.wait_for_upload_port=true
+adafruit_neotrinkey_m0.upload.native_usb=true
+adafruit_neotrinkey_m0.build.mcu=cortex-m0plus
+adafruit_neotrinkey_m0.build.f_cpu=48000000L
+adafruit_neotrinkey_m0.build.usb_product="NeoPixel Trinkey M0"
+adafruit_neotrinkey_m0.build.usb_manufacturer="Adafruit"
+adafruit_neotrinkey_m0.build.board=NEOTRINKEY_M0
+adafruit_neotrinkey_m0.build.core=arduino
+adafruit_neotrinkey_m0.build.extra_flags=-DCRYSTALLESS -DADAFRUIT_NEOTRINKEY_M0 -D__SAMD21E18A__ -DARM_MATH_CM0PLUS {build.usb_flags}
+adafruit_neotrinkey_m0.build.ldscript=linker_scripts/gcc/flash_with_bootloader.ld
+adafruit_neotrinkey_m0.build.openocdscript=openocd_scripts/neotrinkey_m0.cfg
+adafruit_neotrinkey_m0.build.variant=neotrinkey_m0
+adafruit_neotrinkey_m0.build.variant_system_lib=
+adafruit_neotrinkey_m0.build.vid=0x239A
+adafruit_neotrinkey_m0.build.pid=0x80EF
+adafruit_neotrinkey_m0.bootloader.tool=openocd
+adafruit_neotrinkey_m0.bootloader.file=neotrinkey_m0/bootloader-neotrinkey_m0.bin
+adafruit_neotrinkey_m0.menu.opt.small=Small (-Os) (standard)
+adafruit_neotrinkey_m0.menu.opt.small.build.flags.optimize=-Os
+adafruit_neotrinkey_m0.menu.opt.fast=Fast (-O2)
+adafruit_neotrinkey_m0.menu.opt.fast.build.flags.optimize=-O2
+adafruit_neotrinkey_m0.menu.opt.faster=Faster (-O3)
+adafruit_neotrinkey_m0.menu.opt.faster.build.flags.optimize=-O3
+adafruit_neotrinkey_m0.menu.opt.fastest=Fastest (-Ofast)
+adafruit_neotrinkey_m0.menu.opt.fastest.build.flags.optimize=-Ofast
+adafruit_neotrinkey_m0.menu.opt.dragons=Here be dragons (-Ofast -funroll-loops)
+adafruit_neotrinkey_m0.menu.opt.dragons.build.flags.optimize=-Ofast -funroll-loops
+adafruit_neotrinkey_m0.menu.usbstack.arduino=Arduino
+adafruit_neotrinkey_m0.menu.usbstack.tinyusb=TinyUSB
+adafruit_neotrinkey_m0.menu.usbstack.tinyusb.build.flags.usbstack=-DUSE_TINYUSB
+adafruit_neotrinkey_m0.menu.debug.off=Off
+adafruit_neotrinkey_m0.menu.debug.on=On
+adafruit_neotrinkey_m0.menu.debug.on.build.flags.debug=-g
+
+# Adafruit Rotary Trinkey (SAMD21)
+# ------------------------------
+adafruit_rotarytrinkey_m0.name=Adafruit Rotary Trinkey (SAMD21)
+adafruit_rotarytrinkey_m0.vid.0=0x239A
+adafruit_rotarytrinkey_m0.pid.0=0x80FB
+adafruit_rotarytrinkey_m0.vid.1=0x239A
+adafruit_rotarytrinkey_m0.pid.1=0x00FB
+adafruit_rotarytrinkey_m0.vid.1=0x239A
+adafruit_rotarytrinkey_m0.pid.1=0x80FC
+adafruit_rotarytrinkey_m0.upload.tool=bossac
+adafruit_rotarytrinkey_m0.upload.protocol=sam-ba
+adafruit_rotarytrinkey_m0.upload.maximum_size=262144
+adafruit_rotarytrinkey_m0.upload.offset=0x2000
+adafruit_rotarytrinkey_m0.upload.use_1200bps_touch=true
+adafruit_rotarytrinkey_m0.upload.wait_for_upload_port=true
+adafruit_rotarytrinkey_m0.upload.native_usb=true
+adafruit_rotarytrinkey_m0.build.mcu=cortex-m0plus
+adafruit_rotarytrinkey_m0.build.f_cpu=48000000L
+adafruit_rotarytrinkey_m0.build.usb_product="Rotary Trinkey M0"
+adafruit_rotarytrinkey_m0.build.usb_manufacturer="Adafruit"
+adafruit_rotarytrinkey_m0.build.board=ROTARYTRINKEY_M0
+adafruit_rotarytrinkey_m0.build.core=arduino
+adafruit_rotarytrinkey_m0.build.extra_flags=-DCRYSTALLESS -DADAFRUIT_ROTARYTRINKEY_M0 -D__SAMD21E18A__ -DARM_MATH_CM0PLUS {build.usb_flags}
+adafruit_rotarytrinkey_m0.build.ldscript=linker_scripts/gcc/flash_with_bootloader.ld
+adafruit_rotarytrinkey_m0.build.openocdscript=openocd_scripts/rotarytrinkey_m0.cfg
+adafruit_rotarytrinkey_m0.build.variant=rotarytrinkey_m0
+adafruit_rotarytrinkey_m0.build.variant_system_lib=
+adafruit_rotarytrinkey_m0.build.vid=0x239A
+adafruit_rotarytrinkey_m0.build.pid=0x80FB
+adafruit_rotarytrinkey_m0.bootloader.tool=openocd
+adafruit_rotarytrinkey_m0.bootloader.file=rotarytrinkey_m0/bootloader-rotarytrinkey_m0.bin
+adafruit_rotarytrinkey_m0.menu.opt.small=Small (-Os) (standard)
+adafruit_rotarytrinkey_m0.menu.opt.small.build.flags.optimize=-Os
+adafruit_rotarytrinkey_m0.menu.opt.fast=Fast (-O2)
+adafruit_rotarytrinkey_m0.menu.opt.fast.build.flags.optimize=-O2
+adafruit_rotarytrinkey_m0.menu.opt.faster=Faster (-O3)
+adafruit_rotarytrinkey_m0.menu.opt.faster.build.flags.optimize=-O3
+adafruit_rotarytrinkey_m0.menu.opt.fastest=Fastest (-Ofast)
+adafruit_rotarytrinkey_m0.menu.opt.fastest.build.flags.optimize=-Ofast
+adafruit_rotarytrinkey_m0.menu.opt.dragons=Here be dragons (-Ofast -funroll-loops)
+adafruit_rotarytrinkey_m0.menu.opt.dragons.build.flags.optimize=-Ofast -funroll-loops
+adafruit_rotarytrinkey_m0.menu.usbstack.arduino=Arduino
+adafruit_rotarytrinkey_m0.menu.usbstack.tinyusb=TinyUSB
+adafruit_rotarytrinkey_m0.menu.usbstack.tinyusb.build.flags.usbstack=-DUSE_TINYUSB
+adafruit_rotarytrinkey_m0.menu.debug.off=Off
+adafruit_rotarytrinkey_m0.menu.debug.on=On
+adafruit_rotarytrinkey_m0.menu.debug.on.build.flags.debug=-g
+
+# Adafruit NeoKey Trinkey (SAMD21)
+# ------------------------------
+adafruit_neokeytrinkey_m0.name=Adafruit NeoKey Trinkey (SAMD21)
+adafruit_neokeytrinkey_m0.vid.0=0x239A
+adafruit_neokeytrinkey_m0.pid.0=0x80FF
+adafruit_neokeytrinkey_m0.vid.1=0x239A
+adafruit_neokeytrinkey_m0.pid.1=0x00FF
+adafruit_neokeytrinkey_m0.vid.1=0x239A
+adafruit_neokeytrinkey_m0.pid.1=0x8100
+adafruit_neokeytrinkey_m0.upload.tool=bossac
+adafruit_neokeytrinkey_m0.upload.protocol=sam-ba
+adafruit_neokeytrinkey_m0.upload.maximum_size=262144
+adafruit_neokeytrinkey_m0.upload.offset=0x2000
+adafruit_neokeytrinkey_m0.upload.use_1200bps_touch=true
+adafruit_neokeytrinkey_m0.upload.wait_for_upload_port=true
+adafruit_neokeytrinkey_m0.upload.native_usb=true
+adafruit_neokeytrinkey_m0.build.mcu=cortex-m0plus
+adafruit_neokeytrinkey_m0.build.f_cpu=48000000L
+adafruit_neokeytrinkey_m0.build.usb_product="NeoKey Trinkey M0"
+adafruit_neokeytrinkey_m0.build.usb_manufacturer="Adafruit"
+adafruit_neokeytrinkey_m0.build.board=NEOKEYTRINKEY_M0
+adafruit_neokeytrinkey_m0.build.core=arduino
+adafruit_neokeytrinkey_m0.build.extra_flags=-DCRYSTALLESS -DADAFRUIT_NEOKEYTRINKEY_M0 -D__SAMD21E18A__ -DARM_MATH_CM0PLUS {build.usb_flags}
+adafruit_neokeytrinkey_m0.build.ldscript=linker_scripts/gcc/flash_with_bootloader.ld
+adafruit_neokeytrinkey_m0.build.openocdscript=openocd_scripts/neokeytrinkey_m0.cfg
+adafruit_neokeytrinkey_m0.build.variant=neokeytrinkey_m0
+adafruit_neokeytrinkey_m0.build.variant_system_lib=
+adafruit_neokeytrinkey_m0.build.vid=0x239A
+adafruit_neokeytrinkey_m0.build.pid=0x80FF
+adafruit_neokeytrinkey_m0.bootloader.tool=openocd
+adafruit_neokeytrinkey_m0.bootloader.file=neokeytrinkey_m0/bootloader-neokeytrinkey_m0.bin
+adafruit_neokeytrinkey_m0.menu.opt.small=Small (-Os) (standard)
+adafruit_neokeytrinkey_m0.menu.opt.small.build.flags.optimize=-Os
+adafruit_neokeytrinkey_m0.menu.opt.fast=Fast (-O2)
+adafruit_neokeytrinkey_m0.menu.opt.fast.build.flags.optimize=-O2
+adafruit_neokeytrinkey_m0.menu.opt.faster=Faster (-O3)
+adafruit_neokeytrinkey_m0.menu.opt.faster.build.flags.optimize=-O3
+adafruit_neokeytrinkey_m0.menu.opt.fastest=Fastest (-Ofast)
+adafruit_neokeytrinkey_m0.menu.opt.fastest.build.flags.optimize=-Ofast
+adafruit_neokeytrinkey_m0.menu.opt.dragons=Here be dragons (-Ofast -funroll-loops)
+
+adafruit_neokeytrinkey_m0.menu.opt.dragons.build.flags.optimize=-Ofast -funroll-loops
+adafruit_neokeytrinkey_m0.menu.usbstack.arduino=Arduino
+adafruit_neokeytrinkey_m0.menu.usbstack.tinyusb=TinyUSB
+adafruit_neokeytrinkey_m0.menu.usbstack.tinyusb.build.flags.usbstack=-DUSE_TINYUSB
+adafruit_neokeytrinkey_m0.menu.debug.off=Off
+adafruit_neokeytrinkey_m0.menu.debug.on=On
+adafruit_neokeytrinkey_m0.menu.debug.on.build.flags.debug=-g
+
+
+# Adafruit Slide Trinkey (SAMD21)
+# ------------------------------
+adafruit_slidetrinkey_m0.name=Adafruit Slide Trinkey (SAMD21)
+adafruit_slidetrinkey_m0.vid.0=0x239A
+adafruit_slidetrinkey_m0.pid.0=0x8101
+adafruit_slidetrinkey_m0.vid.1=0x239A
+adafruit_slidetrinkey_m0.pid.1=0x0101
+adafruit_slidetrinkey_m0.vid.1=0x239A
+adafruit_slidetrinkey_m0.pid.1=0x8102
+adafruit_slidetrinkey_m0.upload.tool=bossac
+adafruit_slidetrinkey_m0.upload.protocol=sam-ba
+adafruit_slidetrinkey_m0.upload.maximum_size=262144
+adafruit_slidetrinkey_m0.upload.offset=0x2000
+adafruit_slidetrinkey_m0.upload.use_1200bps_touch=true
+adafruit_slidetrinkey_m0.upload.wait_for_upload_port=true
+adafruit_slidetrinkey_m0.upload.native_usb=true
+adafruit_slidetrinkey_m0.build.mcu=cortex-m0plus
+adafruit_slidetrinkey_m0.build.f_cpu=48000000L
+adafruit_slidetrinkey_m0.build.usb_product="Slide Trinkey M0"
+adafruit_slidetrinkey_m0.build.usb_manufacturer="Adafruit"
+adafruit_slidetrinkey_m0.build.board=SLIDETRINKEY_M0
+adafruit_slidetrinkey_m0.build.core=arduino
+adafruit_slidetrinkey_m0.build.extra_flags=-DCRYSTALLESS -DADAFRUIT_SLIDETRINKEY_M0 -D__SAMD21E18A__ -DARM_MATH_CM0PLUS {build.usb_flags}
+adafruit_slidetrinkey_m0.build.ldscript=linker_scripts/gcc/flash_with_bootloader.ld
+adafruit_slidetrinkey_m0.build.openocdscript=openocd_scripts/slidetrinkey_m0.cfg
+adafruit_slidetrinkey_m0.build.variant=slidetrinkey_m0
+adafruit_slidetrinkey_m0.build.variant_system_lib=
+adafruit_slidetrinkey_m0.build.vid=0x239A
+adafruit_slidetrinkey_m0.build.pid=0x8101
+adafruit_slidetrinkey_m0.bootloader.tool=openocd
+adafruit_slidetrinkey_m0.bootloader.file=slidetrinkey_m0/bootloader-slidetrinkey_m0.bin
+adafruit_slidetrinkey_m0.menu.opt.small=Small (-Os) (standard)
+adafruit_slidetrinkey_m0.menu.opt.small.build.flags.optimize=-Os
+adafruit_slidetrinkey_m0.menu.opt.fast=Fast (-O2)
+adafruit_slidetrinkey_m0.menu.opt.fast.build.flags.optimize=-O2
+adafruit_slidetrinkey_m0.menu.opt.faster=Faster (-O3)
+adafruit_slidetrinkey_m0.menu.opt.faster.build.flags.optimize=-O3
+adafruit_slidetrinkey_m0.menu.opt.fastest=Fastest (-Ofast)
+adafruit_slidetrinkey_m0.menu.opt.fastest.build.flags.optimize=-Ofast
+adafruit_slidetrinkey_m0.menu.opt.dragons=Here be dragons (-Ofast -funroll-loops)
+adafruit_slidetrinkey_m0.menu.opt.dragons.build.flags.optimize=-Ofast -funroll-loops
+adafruit_slidetrinkey_m0.menu.usbstack.arduino=Arduino
+adafruit_slidetrinkey_m0.menu.usbstack.tinyusb=TinyUSB
+adafruit_slidetrinkey_m0.menu.usbstack.tinyusb.build.flags.usbstack=-DUSE_TINYUSB
+adafruit_slidetrinkey_m0.menu.debug.off=Off
+adafruit_slidetrinkey_m0.menu.debug.on=On
+adafruit_slidetrinkey_m0.menu.debug.on.build.flags.debug=-g
+
+# Adafruit ProxLight Trinkey (SAMD21)
+# ------------------------------
+adafruit_proxlighttrinkey_m0.name=Adafruit ProxLight Trinkey (SAMD21)
+adafruit_proxlighttrinkey_m0.vid.0=0x239A
+adafruit_proxlighttrinkey_m0.pid.0=0x8103
+adafruit_proxlighttrinkey_m0.vid.1=0x239A
+adafruit_proxlighttrinkey_m0.pid.1=0x0103
+adafruit_proxlighttrinkey_m0.vid.1=0x239A
+adafruit_proxlighttrinkey_m0.pid.1=0x8104
+adafruit_proxlighttrinkey_m0.upload.tool=bossac
+adafruit_proxlighttrinkey_m0.upload.protocol=sam-ba
+adafruit_proxlighttrinkey_m0.upload.maximum_size=262144
+adafruit_proxlighttrinkey_m0.upload.offset=0x2000
+adafruit_proxlighttrinkey_m0.upload.use_1200bps_touch=true
+adafruit_proxlighttrinkey_m0.upload.wait_for_upload_port=true
+adafruit_proxlighttrinkey_m0.upload.native_usb=true
+adafruit_proxlighttrinkey_m0.build.mcu=cortex-m0plus
+adafruit_proxlighttrinkey_m0.build.f_cpu=48000000L
+adafruit_proxlighttrinkey_m0.build.usb_product="ProxLight Trinkey M0"
+adafruit_proxlighttrinkey_m0.build.usb_manufacturer="Adafruit"
+adafruit_proxlighttrinkey_m0.build.board=PROXLIGHTTRINKEY_M0
+adafruit_proxlighttrinkey_m0.build.core=arduino
+adafruit_proxlighttrinkey_m0.build.extra_flags=-DCRYSTALLESS -DADAFRUIT_PROXLIGHTTRINKEY_M0 -D__SAMD21E18A__ -DARM_MATH_CM0PLUS {build.usb_flags}
+adafruit_proxlighttrinkey_m0.build.ldscript=linker_scripts/gcc/flash_with_bootloader.ld
+adafruit_proxlighttrinkey_m0.build.openocdscript=openocd_scripts/proxlighttrinkey_m0.cfg
+adafruit_proxlighttrinkey_m0.build.variant=proxlighttrinkey_m0
+adafruit_proxlighttrinkey_m0.build.variant_system_lib=
+adafruit_proxlighttrinkey_m0.build.vid=0x239A
+adafruit_proxlighttrinkey_m0.build.pid=0x8103
+adafruit_proxlighttrinkey_m0.bootloader.tool=openocd
+adafruit_proxlighttrinkey_m0.bootloader.file=proxlighttrinkey_m0/bootloader-proxlighttrinkey_m0.bin
+adafruit_proxlighttrinkey_m0.menu.opt.small=Small (-Os) (standard)
+adafruit_proxlighttrinkey_m0.menu.opt.small.build.flags.optimize=-Os
+adafruit_proxlighttrinkey_m0.menu.opt.fast=Fast (-O2)
+adafruit_proxlighttrinkey_m0.menu.opt.fast.build.flags.optimize=-O2
+adafruit_proxlighttrinkey_m0.menu.opt.faster=Faster (-O3)
+adafruit_proxlighttrinkey_m0.menu.opt.faster.build.flags.optimize=-O3
+adafruit_proxlighttrinkey_m0.menu.opt.fastest=Fastest (-Ofast)
+adafruit_proxlighttrinkey_m0.menu.opt.fastest.build.flags.optimize=-Ofast
+adafruit_proxlighttrinkey_m0.menu.opt.dragons=Here be dragons (-Ofast -funroll-loops)
+adafruit_proxlighttrinkey_m0.menu.opt.dragons.build.flags.optimize=-Ofast -funroll-loops
+adafruit_proxlighttrinkey_m0.menu.usbstack.arduino=Arduino
+adafruit_proxlighttrinkey_m0.menu.usbstack.tinyusb=TinyUSB
+adafruit_proxlighttrinkey_m0.menu.usbstack.tinyusb.build.flags.usbstack=-DUSE_TINYUSB
+adafruit_proxlighttrinkey_m0.menu.debug.off=Off
+adafruit_proxlighttrinkey_m0.menu.debug.on=On
+adafruit_proxlighttrinkey_m0.menu.debug.on.build.flags.debug=-g
+
+
+# Adafruit ItsyBitsy M0 (SAMD21)
+# ------------------------------
+adafruit_itsybitsy_m0.name=Adafruit ItsyBitsy M0
+adafruit_itsybitsy_m0.vid.0=0x239A
+adafruit_itsybitsy_m0.pid.0=0x800F
+adafruit_itsybitsy_m0.vid.1=0x239A
+adafruit_itsybitsy_m0.pid.1=0x000F
+adafruit_itsybitsy_m0.vid.2=0x239A
+adafruit_itsybitsy_m0.pid.2=0x8012
+adafruit_itsybitsy_m0.upload.tool=bossac
+adafruit_itsybitsy_m0.upload.protocol=sam-ba
+adafruit_itsybitsy_m0.upload.maximum_size=262144
+adafruit_itsybitsy_m0.upload.offset=0x2000
+adafruit_itsybitsy_m0.upload.use_1200bps_touch=true
+adafruit_itsybitsy_m0.upload.wait_for_upload_port=true
+adafruit_itsybitsy_m0.upload.native_usb=true
+adafruit_itsybitsy_m0.build.mcu=cortex-m0plus
+adafruit_itsybitsy_m0.build.f_cpu=48000000L
+adafruit_itsybitsy_m0.build.usb_product="ItsyBitsy M0 Express"
+adafruit_itsybitsy_m0.build.usb_manufacturer="Adafruit"
+adafruit_itsybitsy_m0.build.board=ITSYBITSY_M0
+adafruit_itsybitsy_m0.build.core=arduino
+adafruit_itsybitsy_m0.build.extra_flags=-DCRYSTALLESS -DADAFRUIT_ITSYBITSY_M0 -D__SAMD21G18A__ -DARM_MATH_CM0PLUS {build.usb_flags}
+adafruit_itsybitsy_m0.build.ldscript=linker_scripts/gcc/flash_with_bootloader.ld
+adafruit_itsybitsy_m0.build.openocdscript=openocd_scripts/itsybitsy_m0.cfg
+adafruit_itsybitsy_m0.build.variant=itsybitsy_m0
+adafruit_itsybitsy_m0.build.variant_system_lib=
+adafruit_itsybitsy_m0.build.vid=0x239A
+adafruit_itsybitsy_m0.build.pid=0x800F
+adafruit_itsybitsy_m0.bootloader.tool=openocd
+adafruit_itsybitsy_m0.bootloader.file=itsybitsyM0/bootloader-itsybitsy_m0-v2.0.0-adafruit.5.bin
+adafruit_itsybitsy_m0.menu.opt.small=Small (-Os) (standard)
+adafruit_itsybitsy_m0.menu.opt.small.build.flags.optimize=-Os
+adafruit_itsybitsy_m0.menu.opt.fast=Fast (-O2)
+adafruit_itsybitsy_m0.menu.opt.fast.build.flags.optimize=-O2
+adafruit_itsybitsy_m0.menu.opt.faster=Faster (-O3)
+adafruit_itsybitsy_m0.menu.opt.faster.build.flags.optimize=-O3
+adafruit_itsybitsy_m0.menu.opt.fastest=Fastest (-Ofast)
+adafruit_itsybitsy_m0.menu.opt.fastest.build.flags.optimize=-Ofast
+adafruit_itsybitsy_m0.menu.opt.dragons=Here be dragons (-Ofast -funroll-loops)
+adafruit_itsybitsy_m0.menu.opt.dragons.build.flags.optimize=-Ofast -funroll-loops
+adafruit_itsybitsy_m0.menu.usbstack.arduino=Arduino
+adafruit_itsybitsy_m0.menu.usbstack.tinyusb=TinyUSB
+adafruit_itsybitsy_m0.menu.usbstack.tinyusb.build.flags.usbstack=-DUSE_TINYUSB
+adafruit_itsybitsy_m0.menu.debug.off=Off
+adafruit_itsybitsy_m0.menu.debug.on=On
+adafruit_itsybitsy_m0.menu.debug.on.build.flags.debug=-g
+
+
+# Adafruit PIRkey (SAMD21)
+# ------------------------------
+adafruit_pirkey.name=Adafruit pIRkey
+adafruit_pirkey.vid.0=0x239A
+adafruit_pirkey.pid.0=0x801E
+adafruit_pirkey.vid.1=0x239A
+adafruit_pirkey.pid.1=0x001E
+adafruit_pirkey.upload.tool=bossac
+adafruit_pirkey.upload.protocol=sam-ba
+adafruit_pirkey.upload.maximum_size=262144
+adafruit_pirkey.upload.offset=0x2000
+adafruit_pirkey.upload.use_1200bps_touch=true
+adafruit_pirkey.upload.wait_for_upload_port=true
+adafruit_pirkey.upload.native_usb=true
+adafruit_pirkey.build.mcu=cortex-m0plus
+adafruit_pirkey.build.f_cpu=48000000L
+adafruit_pirkey.build.usb_product="pIRKey"
+adafruit_pirkey.build.usb_manufacturer="Adafruit"
+adafruit_pirkey.build.board=PIRKEY
+adafruit_pirkey.build.core=arduino
+adafruit_pirkey.build.extra_flags=-DCRYSTALLESS -DADAFRUIT_PIRKEY -D__SAMD21E18A__ -DARM_MATH_CM0PLUS {build.usb_flags}
+adafruit_pirkey.build.ldscript=linker_scripts/gcc/flash_with_bootloader.ld
+adafruit_pirkey.build.openocdscript=openocd_scripts/arduino_zero.cfg
+adafruit_pirkey.build.variant=pirkey
+adafruit_pirkey.build.variant_system_lib=
+adafruit_pirkey.build.vid=0x239A
+adafruit_pirkey.build.pid=0x801E
+adafruit_pirkey.bootloader.tool=openocd
+adafruit_pirkey.bootloader.file=pirkey/bootloader-pirkey-v2.0.0-adafruit.5.bin
+adafruit_pirkey.menu.opt.small=Small (-Os) (standard)
+adafruit_pirkey.menu.opt.small.build.flags.optimize=-Os
+adafruit_pirkey.menu.opt.fast=Fast (-O2)
+adafruit_pirkey.menu.opt.fast.build.flags.optimize=-O2
+adafruit_pirkey.menu.opt.faster=Faster (-O3)
+adafruit_pirkey.menu.opt.faster.build.flags.optimize=-O3
+adafruit_pirkey.menu.opt.fastest=Fastest (-Ofast)
+adafruit_pirkey.menu.opt.fastest.build.flags.optimize=-Ofast
+adafruit_pirkey.menu.opt.dragons=Here be dragons (-Ofast -funroll-loops)
+adafruit_pirkey.menu.opt.dragons.build.flags.optimize=-Ofast -funroll-loops
+adafruit_pirkey.menu.usbstack.arduino=Arduino
+adafruit_pirkey.menu.usbstack.tinyusb=TinyUSB
+adafruit_pirkey.menu.usbstack.tinyusb.build.flags.usbstack=-DUSE_TINYUSB
+
+# Adafruit HalloWing M0 (SAMD21)
+# ------------------------------
+adafruit_hallowing.name=Adafruit Hallowing M0
+adafruit_hallowing.vid.0=0x239A
+adafruit_hallowing.pid.0=0xDEAD
+adafruit_hallowing.vid.1=0x239A
+adafruit_hallowing.pid.1=0xD1ED
+adafruit_hallowing.vid.1=0x239A
+adafruit_hallowing.pid.1=0xB000
+adafruit_hallowing.upload.tool=bossac
+adafruit_hallowing.upload.protocol=sam-ba
+adafruit_hallowing.upload.maximum_size=262144
+adafruit_hallowing.upload.offset=0x2000
+adafruit_hallowing.upload.use_1200bps_touch=true
+adafruit_hallowing.upload.wait_for_upload_port=true
+adafruit_hallowing.upload.native_usb=true
+adafruit_hallowing.build.mcu=cortex-m0plus
+adafruit_hallowing.build.f_cpu=48000000L
+adafruit_hallowing.build.usb_product="Hallowing M0"
+adafruit_hallowing.build.usb_manufacturer="Adafruit"
+adafruit_hallowing.build.board=SAMD_HALLOWING
+adafruit_hallowing.build.core=arduino
+adafruit_hallowing.build.extra_flags=-DCRYSTALLESS -DARDUINO_SAMD_ZERO -DARDUINO_SAMD_HALLOWING_M0 -DARM_MATH_CM0PLUS -DADAFRUIT_HALLOWING -D__SAMD21G18A__ {build.usb_flags}
+adafruit_hallowing.build.ldscript=linker_scripts/gcc/flash_with_bootloader.ld
+adafruit_hallowing.build.openocdscript=openocd_scripts/hallowing_m0_express.cfg
+adafruit_hallowing.build.variant=hallowing_m0_express
+adafruit_hallowing.build.variant_system_lib=
+adafruit_hallowing.build.vid=0x239A
+adafruit_hallowing.build.pid=0xDEAD
+adafruit_hallowing.bootloader.tool=openocd
+adafruit_hallowing.bootloader.file=hallowingM0/bootloader-hallowing_m0-v2.0.0-adafruit.0-21-g887cc30.bin
+adafruit_hallowing.menu.opt.small=Small (-Os) (standard)
+adafruit_hallowing.menu.opt.small.build.flags.optimize=-Os
+adafruit_hallowing.menu.opt.fast=Fast (-O2)
+adafruit_hallowing.menu.opt.fast.build.flags.optimize=-O2
+adafruit_hallowing.menu.opt.faster=Faster (-O3)
+adafruit_hallowing.menu.opt.faster.build.flags.optimize=-O3
+adafruit_hallowing.menu.opt.fastest=Fastest (-Ofast)
+adafruit_hallowing.menu.opt.fastest.build.flags.optimize=-Ofast
+adafruit_hallowing.menu.opt.dragons=Here be dragons (-Ofast -funroll-loops)
+adafruit_hallowing.menu.opt.dragons.build.flags.optimize=-Ofast -funroll-loops
+adafruit_hallowing.menu.usbstack.arduino=Arduino
+adafruit_hallowing.menu.usbstack.tinyusb=TinyUSB
+adafruit_hallowing.menu.usbstack.tinyusb.build.flags.usbstack=-DUSE_TINYUSB
+adafruit_hallowing.menu.debug.off=Off
+adafruit_hallowing.menu.debug.on=On
+adafruit_hallowing.menu.debug.on.build.flags.debug=-g
+
+# Adafruit Crickit M0 (SAMD21)
+# ------------------------------
+adafruit_crickit_m0.name=Adafruit Crickit M0
+adafruit_crickit_m0.vid.0=0x239A
+adafruit_crickit_m0.pid.0=0x802D
+adafruit_crickit_m0.vid.1=0x239A
+adafruit_crickit_m0.pid.1=0x002D
+adafruit_crickit_m0.vid.2=0x239A
+adafruit_crickit_m0.pid.2=0x802D
+adafruit_crickit_m0.upload.tool=bossac
+adafruit_crickit_m0.upload.protocol=sam-ba
+adafruit_crickit_m0.upload.maximum_size=262144
+adafruit_crickit_m0.upload.offset=0x2000
+adafruit_crickit_m0.upload.use_1200bps_touch=true
+adafruit_crickit_m0.upload.wait_for_upload_port=true
+adafruit_crickit_m0.upload.native_usb=true
+adafruit_crickit_m0.build.mcu=cortex-m0plus
+adafruit_crickit_m0.build.f_cpu=48000000L
+adafruit_crickit_m0.build.usb_product="Crickit M0"
+adafruit_crickit_m0.build.usb_manufacturer="Adafruit"
+adafruit_crickit_m0.build.board=CRICKIT_M0
+adafruit_crickit_m0.build.core=arduino
+adafruit_crickit_m0.build.extra_flags=-DCRYSTALLESS -DADAFRUIT_CRICKIT_M0 -D__SAMD21G18A__ -DARM_MATH_CM0PLUS {build.usb_flags}
+adafruit_crickit_m0.build.ldscript=linker_scripts/gcc/flash_with_bootloader.ld
+adafruit_crickit_m0.build.openocdscript=openocd_scripts/crickit_m0.cfg
+adafruit_crickit_m0.build.variant=crickit_m0
+adafruit_crickit_m0.build.variant_system_lib=
+adafruit_crickit_m0.build.vid=0x239A
+adafruit_crickit_m0.build.pid=0x802D
+adafruit_crickit_m0.bootloader.tool=openocd
+adafruit_crickit_m0.bootloader.file=crickit/samd21_sam_ba.bin
+adafruit_crickit_m0.menu.opt.small=Small (-Os) (standard)
+adafruit_crickit_m0.menu.opt.small.build.flags.optimize=-Os
+adafruit_crickit_m0.menu.opt.fast=Fast (-O2)
+adafruit_crickit_m0.menu.opt.fast.build.flags.optimize=-O2
+adafruit_crickit_m0.menu.opt.faster=Faster (-O3)
+adafruit_crickit_m0.menu.opt.faster.build.flags.optimize=-O3
+adafruit_crickit_m0.menu.opt.fastest=Fastest (-Ofast)
+adafruit_crickit_m0.menu.opt.fastest.build.flags.optimize=-Ofast
+adafruit_crickit_m0.menu.opt.dragons=Here be dragons (-Ofast -funroll-loops)
+adafruit_crickit_m0.menu.opt.dragons.build.flags.optimize=-Ofast -funroll-loops
+adafruit_crickit_m0.menu.usbstack.arduino=Arduino
+adafruit_crickit_m0.menu.usbstack.tinyusb=TinyUSB
+adafruit_crickit_m0.menu.usbstack.tinyusb.build.flags.usbstack=-DUSE_TINYUSB
+adafruit_crickit_m0.menu.debug.off=Off
+adafruit_crickit_m0.menu.debug.on=On
+adafruit_crickit_m0.menu.debug.on.build.flags.debug=-g
+
+# Adafruit Metro M4 (SAMD51)
+# ------------------------------
+adafruit_metro_m4.name=Adafruit Metro M4 (SAMD51)
+adafruit_metro_m4.vid.0=0x239A
+adafruit_metro_m4.pid.0=0x8020
+adafruit_metro_m4.vid.1=0x239A
+adafruit_metro_m4.pid.1=0x0020
+adafruit_metro_m4.upload.tool=bossac18
+adafruit_metro_m4.upload.protocol=sam-ba
+adafruit_metro_m4.upload.maximum_size=507904
+adafruit_metro_m4.upload.offset=0x4000
+adafruit_metro_m4.upload.use_1200bps_touch=true
+adafruit_metro_m4.upload.wait_for_upload_port=true
+adafruit_metro_m4.upload.native_usb=true
+adafruit_metro_m4.build.mcu=cortex-m4
+#adafruit_metro_m4.build.f_cpu=120000000L
+adafruit_metro_m4.build.usb_product="Adafruit Metro M4"
+adafruit_metro_m4.build.usb_manufacturer="Adafruit LLC"
+adafruit_metro_m4.build.board=METRO_M4
+adafruit_metro_m4.build.core=arduino
+adafruit_metro_m4.build.extra_flags=-D__SAMD51J19A__ -DADAFRUIT_METRO_M4_EXPRESS -D__SAMD51__ {build.usb_flags} -D__FPU_PRESENT -DARM_MATH_CM4 -mfloat-abi=hard -mfpu=fpv4-sp-d16
+adafruit_metro_m4.build.ldscript=linker_scripts/gcc/flash_with_bootloader.ld
+adafruit_metro_m4.build.openocdscript=openocd_scripts/arduino_zero.cfg
+adafruit_metro_m4.build.variant=metro_m4
+adafruit_metro_m4.build.variant_system_lib=
+adafruit_metro_m4.build.vid=0x239A
+adafruit_metro_m4.build.pid=0x8020
+adafruit_metro_m4.bootloader.tool=openocd
+adafruit_metro_m4.bootloader.file=metroM4/bootloader-metro_m4-v2.0.0-adafruit.5.bin
+adafruit_metro_m4.compiler.arm.cmsis.ldflags="-L{runtime.tools.CMSIS-5.4.0.path}/CMSIS/Lib/GCC/" "-L{build.variant.path}" -larm_cortexM4lf_math -mfloat-abi=hard -mfpu=fpv4-sp-d16
+adafruit_metro_m4.menu.cache.on=Enabled
+adafruit_metro_m4.menu.cache.on.build.cache_flags=-DENABLE_CACHE
+adafruit_metro_m4.menu.cache.off=Disabled
+adafruit_metro_m4.menu.cache.off.build.cache_flags=
+adafruit_metro_m4.menu.speed.120=120 MHz (standard)
+adafruit_metro_m4.menu.speed.120.build.f_cpu=120000000L
+adafruit_metro_m4.menu.speed.150=150 MHz (overclock)
+adafruit_metro_m4.menu.speed.150.build.f_cpu=150000000L
+adafruit_metro_m4.menu.speed.180=180 MHz (overclock)
+adafruit_metro_m4.menu.speed.180.build.f_cpu=180000000L
+adafruit_metro_m4.menu.speed.200=200 MHz (overclock)
+adafruit_metro_m4.menu.speed.200.build.f_cpu=200000000L
+adafruit_metro_m4.menu.opt.small=Small (-Os) (standard)
+adafruit_metro_m4.menu.opt.small.build.flags.optimize=-Os
+adafruit_metro_m4.menu.opt.fast=Fast (-O2)
+adafruit_metro_m4.menu.opt.fast.build.flags.optimize=-O2
+adafruit_metro_m4.menu.opt.faster=Faster (-O3)
+adafruit_metro_m4.menu.opt.faster.build.flags.optimize=-O3
+adafruit_metro_m4.menu.opt.fastest=Fastest (-Ofast)
+adafruit_metro_m4.menu.opt.fastest.build.flags.optimize=-Ofast
+adafruit_metro_m4.menu.opt.dragons=Here be dragons (-Ofast -funroll-loops)
+adafruit_metro_m4.menu.opt.dragons.build.flags.optimize=-Ofast -funroll-loops
+adafruit_metro_m4.menu.maxqspi.50=50 MHz (standard)
+adafruit_metro_m4.menu.maxqspi.50.build.flags.maxqspi=-DVARIANT_QSPI_BAUD_DEFAULT=50000000
+adafruit_metro_m4.menu.maxqspi.fcpu=CPU Speed / 2
+adafruit_metro_m4.menu.maxqspi.fcpu.build.flags.maxqspi=-DVARIANT_QSPI_BAUD_DEFAULT=({build.f_cpu})
+adafruit_metro_m4.menu.usbstack.arduino=Arduino
+adafruit_metro_m4.menu.usbstack.tinyusb=TinyUSB
+adafruit_metro_m4.menu.usbstack.tinyusb.build.flags.usbstack=-DUSE_TINYUSB
+adafruit_metro_m4.menu.debug.off=Off
+adafruit_metro_m4.menu.debug.on=On
+adafruit_metro_m4.menu.debug.on.build.flags.debug=-g
+
+
+# Adafruit Grand Central M4 (SAMD51)
+# ------------------------------
+adafruit_grandcentral_m4.name=Adafruit Grand Central M4 (SAMD51)
+adafruit_grandcentral_m4.vid.0=0x239A
+adafruit_grandcentral_m4.pid.0=0x8031
+adafruit_grandcentral_m4.vid.1=0x239A
+adafruit_grandcentral_m4.pid.1=0x0031
+adafruit_grandcentral_m4.vid.1=0x239A
+adafruit_grandcentral_m4.pid.1=0x0032
+adafruit_grandcentral_m4.upload.tool=bossac18
+adafruit_grandcentral_m4.upload.protocol=sam-ba
+adafruit_grandcentral_m4.upload.maximum_size=1032192
+adafruit_grandcentral_m4.upload.offset=0x4000
+adafruit_grandcentral_m4.upload.use_1200bps_touch=true
+adafruit_grandcentral_m4.upload.wait_for_upload_port=true
+adafruit_grandcentral_m4.upload.native_usb=true
+adafruit_grandcentral_m4.build.mcu=cortex-m4
+#adafruit_grandcentral_m4.build.f_cpu=120000000L
+adafruit_grandcentral_m4.build.usb_product="Adafruit Grand Central M4"
+adafruit_grandcentral_m4.build.usb_manufacturer="Adafruit LLC"
+adafruit_grandcentral_m4.build.board=GRAND_CENTRAL_M4
+adafruit_grandcentral_m4.build.core=arduino
+adafruit_grandcentral_m4.build.extra_flags=-D__SAMD51P20A__ -DADAFRUIT_GRAND_CENTRAL_M4 -D__SAMD51__ {build.usb_flags} -D__FPU_PRESENT -DARM_MATH_CM4 -mfloat-abi=hard -mfpu=fpv4-sp-d16
+adafruit_grandcentral_m4.build.ldscript=linker_scripts/gcc/flash_with_bootloader.ld
+adafruit_grandcentral_m4.build.openocdscript=openocd_scripts/arduino_zero.cfg
+adafruit_grandcentral_m4.build.variant=grand_central_m4
+adafruit_grandcentral_m4.build.variant_system_lib=
+adafruit_grandcentral_m4.build.vid=0x239A
+adafruit_grandcentral_m4.build.pid=0x8031
+adafruit_grandcentral_m4.bootloader.tool=openocd
+adafruit_grandcentral_m4.bootloader.file=grand_central_m4/bootloader-grandcentral_m4.bin
+adafruit_grandcentral_m4.compiler.arm.cmsis.ldflags="-L{runtime.tools.CMSIS-5.4.0.path}/CMSIS/Lib/GCC/" "-L{build.variant.path}" -larm_cortexM4lf_math -mfloat-abi=hard -mfpu=fpv4-sp-d16
+adafruit_grandcentral_m4.menu.cache.on=Enabled
+adafruit_grandcentral_m4.menu.cache.on.build.cache_flags=-DENABLE_CACHE
+adafruit_grandcentral_m4.menu.cache.off=Disabled
+adafruit_grandcentral_m4.menu.cache.off.build.cache_flags=
+adafruit_grandcentral_m4.menu.speed.120=120 MHz (standard)
+adafruit_grandcentral_m4.menu.speed.120.build.f_cpu=120000000L
+adafruit_grandcentral_m4.menu.speed.150=150 MHz (overclock)
+adafruit_grandcentral_m4.menu.speed.150.build.f_cpu=150000000L
+adafruit_grandcentral_m4.menu.speed.180=180 MHz (overclock)
+adafruit_grandcentral_m4.menu.speed.180.build.f_cpu=180000000L
+adafruit_grandcentral_m4.menu.speed.200=200 MHz (overclock)
+adafruit_grandcentral_m4.menu.speed.200.build.f_cpu=200000000L
+adafruit_grandcentral_m4.menu.opt.small=Small (-Os) (standard)
+adafruit_grandcentral_m4.menu.opt.small.build.flags.optimize=-Os
+adafruit_grandcentral_m4.menu.opt.fast=Fast (-O2)
+adafruit_grandcentral_m4.menu.opt.fast.build.flags.optimize=-O2
+adafruit_grandcentral_m4.menu.opt.faster=Faster (-O3)
+adafruit_grandcentral_m4.menu.opt.faster.build.flags.optimize=-O3
+adafruit_grandcentral_m4.menu.opt.fastest=Fastest (-Ofast)
+adafruit_grandcentral_m4.menu.opt.fastest.build.flags.optimize=-Ofast
+adafruit_grandcentral_m4.menu.opt.dragons=Here be dragons (-Ofast -funroll-loops)
+adafruit_grandcentral_m4.menu.opt.dragons.build.flags.optimize=-Ofast -funroll-loops
+adafruit_grandcentral_m4.menu.maxqspi.50=50 MHz (standard)
+adafruit_grandcentral_m4.menu.maxqspi.50.build.flags.maxqspi=-DVARIANT_QSPI_BAUD_DEFAULT=50000000
+adafruit_grandcentral_m4.menu.maxqspi.fcpu=CPU Speed / 2
+adafruit_grandcentral_m4.menu.maxqspi.fcpu.build.flags.maxqspi=-DVARIANT_QSPI_BAUD_DEFAULT=({build.f_cpu})
+adafruit_grandcentral_m4.menu.usbstack.arduino=Arduino
+adafruit_grandcentral_m4.menu.usbstack.tinyusb=TinyUSB
+adafruit_grandcentral_m4.menu.usbstack.tinyusb.build.flags.usbstack=-DUSE_TINYUSB
+adafruit_grandcentral_m4.menu.debug.off=Off
+adafruit_grandcentral_m4.menu.debug.on=On
+adafruit_grandcentral_m4.menu.debug.on.build.flags.debug=-g
+
+# Adafruit ItsyBitsy M4 (SAMD51)
+# ------------------------------
+adafruit_itsybitsy_m4.name=Adafruit ItsyBitsy M4 (SAMD51)
+adafruit_itsybitsy_m4.vid.0=0x239A
+adafruit_itsybitsy_m4.pid.0=0x802B
+adafruit_itsybitsy_m4.vid.1=0x239A
+adafruit_itsybitsy_m4.pid.1=0x002B
+adafruit_itsybitsy_m4.upload.tool=bossac18
+adafruit_itsybitsy_m4.upload.protocol=sam-ba
+adafruit_itsybitsy_m4.upload.maximum_size=507904
+adafruit_itsybitsy_m4.upload.offset=0x4000
+adafruit_itsybitsy_m4.upload.use_1200bps_touch=true
+adafruit_itsybitsy_m4.upload.wait_for_upload_port=true
+adafruit_itsybitsy_m4.upload.native_usb=true
+adafruit_itsybitsy_m4.build.mcu=cortex-m4
+#adafruit_itsybitsy_m4.build.f_cpu=120000000L
+adafruit_itsybitsy_m4.build.usb_product="Adafruit ItsyBitsy M4"
+adafruit_itsybitsy_m4.build.usb_manufacturer="Adafruit LLC"
+adafruit_itsybitsy_m4.build.board=ITSYBITSY_M4
+adafruit_itsybitsy_m4.build.core=arduino
+adafruit_itsybitsy_m4.build.extra_flags=-D__SAMD51G19A__ -DADAFRUIT_ITSYBITSY_M4_EXPRESS -D__SAMD51__ {build.usb_flags} -D__FPU_PRESENT -DARM_MATH_CM4 -DCRYSTALLESS -mfloat-abi=hard -mfpu=fpv4-sp-d16
+adafruit_itsybitsy_m4.build.ldscript=linker_scripts/gcc/flash_with_bootloader.ld
+adafruit_itsybitsy_m4.build.openocdscript=openocd_scripts/arduino_zero.cfg
+adafruit_itsybitsy_m4.build.variant=itsybitsy_m4
+adafruit_itsybitsy_m4.build.variant_system_lib=
+adafruit_itsybitsy_m4.build.vid=0x239A
+adafruit_itsybitsy_m4.build.pid=0x802B
+adafruit_itsybitsy_m4.bootloader.tool=openocd
+adafruit_itsybitsy_m4.bootloader.file=itsybitsyM4/bootloader-itsybitsy_m4-v2.0.0-adafruit.5.bin
+adafruit_itsybitsy_m4.compiler.arm.cmsis.ldflags="-L{runtime.tools.CMSIS-5.4.0.path}/CMSIS/Lib/GCC/" "-L{build.variant.path}" -larm_cortexM4lf_math -mfloat-abi=hard -mfpu=fpv4-sp-d16
+adafruit_itsybitsy_m4.menu.cache.on=Enabled
+adafruit_itsybitsy_m4.menu.cache.on.build.cache_flags=-DENABLE_CACHE
+adafruit_itsybitsy_m4.menu.cache.off=Disabled
+adafruit_itsybitsy_m4.menu.cache.off.build.cache_flags=
+adafruit_itsybitsy_m4.menu.speed.120=120 MHz (standard)
+adafruit_itsybitsy_m4.menu.speed.120.build.f_cpu=120000000L
+adafruit_itsybitsy_m4.menu.speed.150=150 MHz (overclock)
+adafruit_itsybitsy_m4.menu.speed.150.build.f_cpu=150000000L
+adafruit_itsybitsy_m4.menu.speed.180=180 MHz (overclock)
+adafruit_itsybitsy_m4.menu.speed.180.build.f_cpu=180000000L
+adafruit_itsybitsy_m4.menu.speed.200=200 MHz (overclock)
+adafruit_itsybitsy_m4.menu.speed.200.build.f_cpu=200000000L
+adafruit_itsybitsy_m4.menu.opt.small=Small (-Os) (standard)
+adafruit_itsybitsy_m4.menu.opt.small.build.flags.optimize=-Os
+adafruit_itsybitsy_m4.menu.opt.fast=Fast (-O2)
+adafruit_itsybitsy_m4.menu.opt.fast.build.flags.optimize=-O2
+adafruit_itsybitsy_m4.menu.opt.faster=Faster (-O3)
+adafruit_itsybitsy_m4.menu.opt.faster.build.flags.optimize=-O3
+adafruit_itsybitsy_m4.menu.opt.fastest=Fastest (-Ofast)
+adafruit_itsybitsy_m4.menu.opt.fastest.build.flags.optimize=-Ofast
+adafruit_itsybitsy_m4.menu.opt.dragons=Here be dragons (-Ofast -funroll-loops)
+adafruit_itsybitsy_m4.menu.opt.dragons.build.flags.optimize=-Ofast -funroll-loops
+adafruit_itsybitsy_m4.menu.maxqspi.50=50 MHz (standard)
+adafruit_itsybitsy_m4.menu.maxqspi.50.build.flags.maxqspi=-DVARIANT_QSPI_BAUD_DEFAULT=50000000
+adafruit_itsybitsy_m4.menu.maxqspi.fcpu=CPU Speed / 2
+adafruit_itsybitsy_m4.menu.maxqspi.fcpu.build.flags.maxqspi=-DVARIANT_QSPI_BAUD_DEFAULT=({build.f_cpu})
+adafruit_itsybitsy_m4.menu.usbstack.arduino=Arduino
+adafruit_itsybitsy_m4.menu.usbstack.tinyusb=TinyUSB
+adafruit_itsybitsy_m4.menu.usbstack.tinyusb.build.flags.usbstack=-DUSE_TINYUSB
+adafruit_itsybitsy_m4.menu.debug.off=Off
+adafruit_itsybitsy_m4.menu.debug.on=On
+adafruit_itsybitsy_m4.menu.debug.on.build.flags.debug=-g
+
+# Adafruit Feather M4 Express (SAMD51)
+# ------------------------------
+adafruit_feather_m4.name=Adafruit Feather M4 Express (SAMD51)
+adafruit_feather_m4.vid.0=0x239A
+adafruit_feather_m4.pid.0=0x8022
+adafruit_feather_m4.vid.1=0x239A
+adafruit_feather_m4.pid.1=0x0022
+adafruit_feather_m4.upload.tool=bossac18
+adafruit_feather_m4.upload.protocol=sam-ba
+adafruit_feather_m4.upload.maximum_size=507904
+adafruit_feather_m4.upload.offset=0x4000
+adafruit_feather_m4.upload.use_1200bps_touch=true
+adafruit_feather_m4.upload.wait_for_upload_port=true
+adafruit_feather_m4.upload.native_usb=true
+adafruit_feather_m4.build.mcu=cortex-m4
+#adafruit_feather_m4.build.f_cpu=120000000L
+adafruit_feather_m4.build.usb_product="Adafruit Feather M4"
+adafruit_feather_m4.build.usb_manufacturer="Adafruit LLC"
+adafruit_feather_m4.build.board=FEATHER_M4
+adafruit_feather_m4.build.core=arduino
+adafruit_feather_m4.build.extra_flags=-D__SAMD51J19A__ -DADAFRUIT_FEATHER_M4_EXPRESS -D__SAMD51__ {build.usb_flags} -D__FPU_PRESENT -DARM_MATH_CM4 -mfloat-abi=hard -mfpu=fpv4-sp-d16
+adafruit_feather_m4.build.ldscript=linker_scripts/gcc/flash_with_bootloader.ld
+adafruit_feather_m4.build.openocdscript=openocd_scripts/arduino_zero.cfg
+adafruit_feather_m4.build.variant=feather_m4
+adafruit_feather_m4.build.variant_system_lib=
+adafruit_feather_m4.build.vid=0x239A
+adafruit_feather_m4.build.pid=0x8022
+adafruit_feather_m4.bootloader.tool=openocd
+adafruit_feather_m4.bootloader.file=featherM4/bootloader-feather_m4-v2.0.0-adafruit.5.bin
+adafruit_feather_m4.compiler.arm.cmsis.ldflags="-L{runtime.tools.CMSIS-5.4.0.path}/CMSIS/Lib/GCC/" "-L{build.variant.path}" -larm_cortexM4lf_math -mfloat-abi=hard -mfpu=fpv4-sp-d16 
+adafruit_feather_m4.menu.cache.on=Enabled
+adafruit_feather_m4.menu.cache.on.build.cache_flags=-DENABLE_CACHE
+adafruit_feather_m4.menu.cache.off=Disabled
+adafruit_feather_m4.menu.cache.off.build.cache_flags=
+adafruit_feather_m4.menu.speed.120=120 MHz (standard)
+adafruit_feather_m4.menu.speed.120.build.f_cpu=120000000L
+adafruit_feather_m4.menu.speed.150=150 MHz (overclock)
+adafruit_feather_m4.menu.speed.150.build.f_cpu=150000000L
+adafruit_feather_m4.menu.speed.180=180 MHz (overclock)
+adafruit_feather_m4.menu.speed.180.build.f_cpu=180000000L
+adafruit_feather_m4.menu.speed.200=200 MHz (overclock)
+adafruit_feather_m4.menu.speed.200.build.f_cpu=200000000L
+adafruit_feather_m4.menu.opt.small=Small (-Os) (standard)
+adafruit_feather_m4.menu.opt.small.build.flags.optimize=-Os
+adafruit_feather_m4.menu.opt.fast=Fast (-O2)
+adafruit_feather_m4.menu.opt.fast.build.flags.optimize=-O2
+adafruit_feather_m4.menu.opt.faster=Faster (-O3)
+adafruit_feather_m4.menu.opt.faster.build.flags.optimize=-O3
+adafruit_feather_m4.menu.opt.fastest=Fastest (-Ofast)
+adafruit_feather_m4.menu.opt.fastest.build.flags.optimize=-Ofast
+adafruit_feather_m4.menu.opt.dragons=Here be dragons (-Ofast -funroll-loops)
+adafruit_feather_m4.menu.opt.dragons.build.flags.optimize=-Ofast -funroll-loops
+adafruit_feather_m4.menu.maxqspi.50=50 MHz (standard)
+adafruit_feather_m4.menu.maxqspi.50.build.flags.maxqspi=-DVARIANT_QSPI_BAUD_DEFAULT=50000000
+adafruit_feather_m4.menu.maxqspi.fcpu=CPU Speed / 2
+adafruit_feather_m4.menu.maxqspi.fcpu.build.flags.maxqspi=-DVARIANT_QSPI_BAUD_DEFAULT=({build.f_cpu})
+adafruit_feather_m4.menu.usbstack.arduino=Arduino
+adafruit_feather_m4.menu.usbstack.tinyusb=TinyUSB
+adafruit_feather_m4.menu.usbstack.tinyusb.build.flags.usbstack=-DUSE_TINYUSB
+adafruit_feather_m4.menu.debug.off=Off
+adafruit_feather_m4.menu.debug.on=On
+adafruit_feather_m4.menu.debug.on.build.flags.debug=-g
+
+# Adafruit Feather M4 CAN (SAME51)
+# ------------------------------
+adafruit_feather_m4_can.name=Adafruit Feather M4 CAN (SAME51)
+adafruit_feather_m4_can.vid.0=0x239A
+adafruit_feather_m4_can.pid.0=0x80CD
+adafruit_feather_m4_can.vid.1=0x239A
+adafruit_feather_m4_can.pid.1=0x00CD
+adafruit_feather_m4_can.upload.tool=bossac18
+adafruit_feather_m4_can.upload.protocol=sam-ba
+adafruit_feather_m4_can.upload.maximum_size=507904
+adafruit_feather_m4_can.upload.offset=0x4000
+adafruit_feather_m4_can.upload.use_1200bps_touch=true
+adafruit_feather_m4_can.upload.wait_for_upload_port=true
+adafruit_feather_m4_can.upload.native_usb=true
+adafruit_feather_m4_can.build.mcu=cortex-m4
+#adafruit_feather_m4_can.build.f_cpu=120000000L
+adafruit_feather_m4_can.build.usb_product="Adafruit Feather M4 CAN"
+adafruit_feather_m4_can.build.usb_manufacturer="Adafruit LLC"
+adafruit_feather_m4_can.build.board=FEATHER_M4_CAN
+adafruit_feather_m4_can.build.core=arduino
+adafruit_feather_m4_can.build.extra_flags=-D__SAME51J19A__ -DADAFRUIT_FEATHER_M4_EXPRESS -DADAFRUIT_FEATHER_M4_CAN -D__SAMD51__ {build.usb_flags} -D__FPU_PRESENT -DARM_MATH_CM4 -mfloat-abi=hard -mfpu=fpv4-sp-d16
+adafruit_feather_m4_can.build.ldscript=linker_scripts/gcc/flash_with_bootloader.ld
+adafruit_feather_m4_can.build.openocdscript=openocd_scripts/arduino_zero.cfg
+adafruit_feather_m4_can.build.variant=feather_m4_can
+adafruit_feather_m4_can.build.variant_system_lib=
+adafruit_feather_m4_can.build.vid=0x239A
+adafruit_feather_m4_can.build.pid=0x80CD
+adafruit_feather_m4_can.bootloader.tool=openocd
+adafruit_feather_m4_can.bootloader.file=featherM4/bootloader-feather_m4_express-v2.0.0-adafruit.5.bin
+adafruit_feather_m4_can.compiler.arm.cmsis.ldflags="-L{runtime.tools.CMSIS-5.4.0.path}/CMSIS/Lib/GCC/" "-L{build.variant.path}" -larm_cortexM4lf_math -mfloat-abi=hard -mfpu=fpv4-sp-d16
+adafruit_feather_m4_can.menu.cache.on=Enabled
+adafruit_feather_m4_can.menu.cache.on.build.cache_flags=-DENABLE_CACHE
+adafruit_feather_m4_can.menu.cache.off=Disabled
+adafruit_feather_m4_can.menu.cache.off.build.cache_flags=
+adafruit_feather_m4_can.menu.speed.120=120 MHz (standard)
+adafruit_feather_m4_can.menu.speed.120.build.f_cpu=120000000L
+adafruit_feather_m4_can.menu.speed.150=150 MHz (overclock)
+adafruit_feather_m4_can.menu.speed.150.build.f_cpu=150000000L
+adafruit_feather_m4_can.menu.speed.180=180 MHz (overclock)
+adafruit_feather_m4_can.menu.speed.180.build.f_cpu=180000000L
+adafruit_feather_m4_can.menu.speed.200=200 MHz (overclock)
+adafruit_feather_m4_can.menu.speed.200.build.f_cpu=200000000L
+adafruit_feather_m4_can.menu.opt.small=Small (-Os) (standard)
+adafruit_feather_m4_can.menu.opt.small.build.flags.optimize=-Os
+adafruit_feather_m4_can.menu.opt.fast=Fast (-O2)
+adafruit_feather_m4_can.menu.opt.fast.build.flags.optimize=-O2
+adafruit_feather_m4_can.menu.opt.faster=Faster (-O3)
+adafruit_feather_m4_can.menu.opt.faster.build.flags.optimize=-O3
+adafruit_feather_m4_can.menu.opt.fastest=Fastest (-Ofast)
+adafruit_feather_m4_can.menu.opt.fastest.build.flags.optimize=-Ofast
+adafruit_feather_m4_can.menu.opt.dragons=Here be dragons (-Ofast -funroll-loops)
+adafruit_feather_m4_can.menu.opt.dragons.build.flags.optimize=-Ofast -funroll-loops
+adafruit_feather_m4_can.menu.maxqspi.50=50 MHz (standard)
+adafruit_feather_m4_can.menu.maxqspi.50.build.flags.maxqspi=-DVARIANT_QSPI_BAUD_DEFAULT=50000000
+adafruit_feather_m4_can.menu.maxqspi.fcpu=CPU Speed / 2
+adafruit_feather_m4_can.menu.maxqspi.fcpu.build.flags.maxqspi=-DVARIANT_QSPI_BAUD_DEFAULT=({build.f_cpu})
+adafruit_feather_m4_can.menu.usbstack.arduino=Arduino
+adafruit_feather_m4_can.menu.usbstack.tinyusb=TinyUSB
+adafruit_feather_m4_can.menu.usbstack.tinyusb.build.flags.usbstack=-DUSE_TINYUSB
+adafruit_feather_m4_can.menu.debug.off=Off
+adafruit_feather_m4_can.menu.debug.on=On
+adafruit_feather_m4_can.menu.debug.on.build.flags.debug=-g
+
+
+# Adafruit Trellis M4 (SAMD51)
+# ------------------------------
+adafruit_trellis_m4.name=Adafruit Trellis M4 (SAMD51)
+adafruit_trellis_m4.vid.0=0x239A
+adafruit_trellis_m4.pid.0=0x802F
+adafruit_trellis_m4.vid.1=0x239A
+adafruit_trellis_m4.pid.1=0x002F
+adafruit_trellis_m4.vid.2=0x239A
+adafruit_trellis_m4.pid.2=0x0030
+adafruit_trellis_m4.upload.tool=bossac18
+adafruit_trellis_m4.upload.protocol=sam-ba
+adafruit_trellis_m4.upload.maximum_size=507904
+adafruit_trellis_m4.upload.offset=0x4000
+adafruit_trellis_m4.upload.use_1200bps_touch=true
+adafruit_trellis_m4.upload.wait_for_upload_port=true
+adafruit_trellis_m4.upload.native_usb=true
+adafruit_trellis_m4.build.mcu=cortex-m4
+#adafruit_trellis_m4.build.f_cpu=120000000L
+adafruit_trellis_m4.build.usb_product="Adafruit Trellis M4"
+adafruit_trellis_m4.build.usb_manufacturer="Adafruit LLC"
+adafruit_trellis_m4.build.board=TRELLIS_M4
+adafruit_trellis_m4.build.core=arduino
+adafruit_trellis_m4.build.extra_flags=-D__SAMD51G19A__ -DADAFRUIT_TRELLIS_M4_EXPRESS -D__SAMD51__ {build.usb_flags} -D__FPU_PRESENT -DARM_MATH_CM4 -DCRYSTALLESS -mfloat-abi=hard -mfpu=fpv4-sp-d16
+adafruit_trellis_m4.build.ldscript=linker_scripts/gcc/flash_with_bootloader.ld
+adafruit_trellis_m4.build.openocdscript=openocd_scripts/arduino_zero.cfg
+adafruit_trellis_m4.build.variant=trellis_m4
+adafruit_trellis_m4.build.variant_system_lib=
+adafruit_trellis_m4.build.vid=0x239A
+adafruit_trellis_m4.build.pid=0x802F
+adafruit_trellis_m4.bootloader.tool=openocd
+adafruit_trellis_m4.bootloader.file=trellisM4/bootloader-trellis_m4-v2.0.0-adafruit.5.bin
+adafruit_trellis_m4.compiler.arm.cmsis.ldflags="-L{runtime.tools.CMSIS-5.4.0.path}/CMSIS/Lib/GCC/" "-L{build.variant.path}" -larm_cortexM4lf_math -mfloat-abi=hard -mfpu=fpv4-sp-d16
+adafruit_trellis_m4.menu.cache.on=Enabled
+adafruit_trellis_m4.menu.cache.on.build.cache_flags=-DENABLE_CACHE
+adafruit_trellis_m4.menu.cache.off=Disabled
+adafruit_trellis_m4.menu.cache.off.build.cache_flags=
+adafruit_trellis_m4.menu.speed.120=120 MHz (standard)
+adafruit_trellis_m4.menu.speed.120.build.f_cpu=120000000L
+adafruit_trellis_m4.menu.speed.150=150 MHz (overclock)
+adafruit_trellis_m4.menu.speed.150.build.f_cpu=150000000L
+adafruit_trellis_m4.menu.speed.180=180 MHz (overclock)
+adafruit_trellis_m4.menu.speed.180.build.f_cpu=180000000L
+adafruit_trellis_m4.menu.speed.200=200 MHz (overclock)
+adafruit_trellis_m4.menu.speed.200.build.f_cpu=200000000L
+adafruit_trellis_m4.menu.opt.small=Small (-Os) (standard)
+adafruit_trellis_m4.menu.opt.small.build.flags.optimize=-Os
+adafruit_trellis_m4.menu.opt.fast=Fast (-O2)
+adafruit_trellis_m4.menu.opt.fast.build.flags.optimize=-O2
+adafruit_trellis_m4.menu.opt.faster=Faster (-O3)
+adafruit_trellis_m4.menu.opt.faster.build.flags.optimize=-O3
+adafruit_trellis_m4.menu.opt.fastest=Fastest (-Ofast)
+adafruit_trellis_m4.menu.opt.fastest.build.flags.optimize=-Ofast
+adafruit_trellis_m4.menu.opt.dragons=Here be dragons (-Ofast -funroll-loops)
+adafruit_trellis_m4.menu.opt.dragons.build.flags.optimize=-Ofast -funroll-loops
+adafruit_trellis_m4.menu.maxqspi.50=50 MHz (standard)
+adafruit_trellis_m4.menu.maxqspi.50.build.flags.maxqspi=-DVARIANT_QSPI_BAUD_DEFAULT=50000000
+adafruit_trellis_m4.menu.maxqspi.fcpu=CPU Speed / 2
+adafruit_trellis_m4.menu.maxqspi.fcpu.build.flags.maxqspi=-DVARIANT_QSPI_BAUD_DEFAULT=({build.f_cpu})
+adafruit_trellis_m4.menu.usbstack.arduino=Arduino
+adafruit_trellis_m4.menu.usbstack.tinyusb=TinyUSB
+adafruit_trellis_m4.menu.usbstack.tinyusb.build.flags.usbstack=-DUSE_TINYUSB
+adafruit_trellis_m4.menu.debug.off=Off
+adafruit_trellis_m4.menu.debug.on=On
+adafruit_trellis_m4.menu.debug.on.build.flags.debug=-g
+
+# Adafruit PyPortal M4 (SAMD51)
+# ------------------------------
+adafruit_pyportal_m4.name=Adafruit PyPortal M4 (SAMD51)
+adafruit_pyportal_m4.vid.0=0x239A
+adafruit_pyportal_m4.pid.0=0x8035
+adafruit_pyportal_m4.vid.1=0x239A
+adafruit_pyportal_m4.pid.1=0x0035
+adafruit_pyportal_m4.upload.tool=bossac18
+adafruit_pyportal_m4.upload.protocol=sam-ba
+adafruit_pyportal_m4.upload.maximum_size=1032192
+adafruit_pyportal_m4.upload.offset=0x4000
+adafruit_pyportal_m4.upload.use_1200bps_touch=true
+adafruit_pyportal_m4.upload.wait_for_upload_port=true
+adafruit_pyportal_m4.upload.native_usb=true
+adafruit_pyportal_m4.build.mcu=cortex-m4
+#adafruit_pyportal_m4.build.f_cpu=120000000L
+adafruit_pyportal_m4.build.usb_product="Adafruit PyPortal M4"
+adafruit_pyportal_m4.build.usb_manufacturer="Adafruit LLC"
+adafruit_pyportal_m4.build.board=PYPORTAL_M4
+adafruit_pyportal_m4.build.core=arduino
+adafruit_pyportal_m4.build.extra_flags=-D__SAMD51J20A__ -DADAFRUIT_PYPORTAL -DCRYSTALLESS -D__SAMD51__ {build.usb_flags} -D__FPU_PRESENT -DARM_MATH_CM4 -mfloat-abi=hard -mfpu=fpv4-sp-d16
+adafruit_pyportal_m4.build.ldscript=linker_scripts/gcc/flash_with_bootloader.ld
+adafruit_pyportal_m4.build.openocdscript=openocd_scripts/arduino_zero.cfg
+adafruit_pyportal_m4.build.variant=pyportal_m4
+adafruit_pyportal_m4.build.variant_system_lib=
+adafruit_pyportal_m4.build.vid=0x239A
+adafruit_pyportal_m4.build.pid=0x8035
+adafruit_pyportal_m4.bootloader.tool=openocd
+adafruit_pyportal_m4.bootloader.file=metroM4/bootloader-metro_m4-v2.0.0-adafruit.5.bin
+adafruit_pyportal_m4.compiler.arm.cmsis.ldflags="-L{runtime.tools.CMSIS-5.4.0.path}/CMSIS/Lib/GCC/" "-L{build.variant.path}" -larm_cortexM4lf_math -mfloat-abi=hard -mfpu=fpv4-sp-d16
+adafruit_pyportal_m4.menu.cache.on=Enabled
+adafruit_pyportal_m4.menu.cache.on.build.cache_flags=-DENABLE_CACHE
+adafruit_pyportal_m4.menu.cache.off=Disabled
+adafruit_pyportal_m4.menu.cache.off.build.cache_flags=
+adafruit_pyportal_m4.menu.speed.120=120 MHz (standard)
+adafruit_pyportal_m4.menu.speed.120.build.f_cpu=120000000L
+adafruit_pyportal_m4.menu.speed.150=150 MHz (overclock)
+adafruit_pyportal_m4.menu.speed.150.build.f_cpu=150000000L
+adafruit_pyportal_m4.menu.speed.180=180 MHz (overclock)
+adafruit_pyportal_m4.menu.speed.180.build.f_cpu=180000000L
+adafruit_pyportal_m4.menu.speed.200=200 MHz (overclock)
+adafruit_pyportal_m4.menu.speed.200.build.f_cpu=200000000L
+adafruit_pyportal_m4.menu.opt.small=Small (-Os) (standard)
+adafruit_pyportal_m4.menu.opt.small.build.flags.optimize=-Os
+adafruit_pyportal_m4.menu.opt.fast=Fast (-O2)
+adafruit_pyportal_m4.menu.opt.fast.build.flags.optimize=-O2
+adafruit_pyportal_m4.menu.opt.faster=Faster (-O3)
+adafruit_pyportal_m4.menu.opt.faster.build.flags.optimize=-O3
+adafruit_pyportal_m4.menu.opt.fastest=Fastest (-Ofast)
+adafruit_pyportal_m4.menu.opt.fastest.build.flags.optimize=-Ofast
+adafruit_pyportal_m4.menu.opt.dragons=Here be dragons (-Ofast -funroll-loops)
+adafruit_pyportal_m4.menu.opt.dragons.build.flags.optimize=-Ofast -funroll-loops
+adafruit_pyportal_m4.menu.maxqspi.50=50 MHz (standard)
+adafruit_pyportal_m4.menu.maxqspi.50.build.flags.maxqspi=-DVARIANT_QSPI_BAUD_DEFAULT=50000000
+adafruit_pyportal_m4.menu.maxqspi.fcpu=CPU Speed / 2
+adafruit_pyportal_m4.menu.maxqspi.fcpu.build.flags.maxqspi=-DVARIANT_QSPI_BAUD_DEFAULT=({build.f_cpu})
+adafruit_pyportal_m4.menu.usbstack.arduino=Arduino
+adafruit_pyportal_m4.menu.usbstack.tinyusb=TinyUSB
+adafruit_pyportal_m4.menu.usbstack.tinyusb.build.flags.usbstack=-DUSE_TINYUSB
+adafruit_pyportal_m4.menu.debug.off=Off
+adafruit_pyportal_m4.menu.debug.on=On
+adafruit_pyportal_m4.menu.debug.on.build.flags.debug=-g
+
+# Adafruit PyPortal M4 Titano (SAMD51)
+# ------------------------------
+adafruit_pyportal_m4_titano.name=Adafruit PyPortal M4 Titano (SAMD51)
+adafruit_pyportal_m4_titano.vid.0=0x239A
+adafruit_pyportal_m4_titano.pid.0=0x8053
+adafruit_pyportal_m4_titano.vid.1=0x239A
+adafruit_pyportal_m4_titano.pid.1=0x8053
+adafruit_pyportal_m4_titano.upload.tool=bossac18
+adafruit_pyportal_m4_titano.upload.protocol=sam-ba
+adafruit_pyportal_m4_titano.upload.maximum_size=1032192
+adafruit_pyportal_m4_titano.upload.offset=0x4000
+adafruit_pyportal_m4_titano.upload.use_1200bps_touch=true
+adafruit_pyportal_m4_titano.upload.wait_for_upload_port=true
+adafruit_pyportal_m4_titano.upload.native_usb=true
+adafruit_pyportal_m4_titano.build.mcu=cortex-m4
+#adafruit_pyportal_m4_titano.build.f_cpu=120000000L
+adafruit_pyportal_m4_titano.build.usb_product="Adafruit PyPortal M4 Titano"
+adafruit_pyportal_m4_titano.build.usb_manufacturer="Adafruit LLC"
+adafruit_pyportal_m4_titano.build.board=PYPORTAL_M4_TITANO
+adafruit_pyportal_m4_titano.build.core=arduino
+adafruit_pyportal_m4_titano.build.extra_flags=-D__SAMD51J20A__ -DADAFRUIT_PYPORTAL_M4_TITANO -DCRYSTALLESS -D__SAMD51__ {build.usb_flags} -D__FPU_PRESENT -DARM_MATH_CM4 -mfloat-abi=hard -mfpu=fpv4-sp-d16
+adafruit_pyportal_m4_titano.build.ldscript=linker_scripts/gcc/flash_with_bootloader.ld
+adafruit_pyportal_m4_titano.build.openocdscript=openocd_scripts/arduino_zero.cfg
+adafruit_pyportal_m4_titano.build.variant=pyportal_m4_titano
+adafruit_pyportal_m4_titano.build.variant_system_lib=
+adafruit_pyportal_m4_titano.build.vid=0x239A
+adafruit_pyportal_m4_titano.build.pid=0x8035
+adafruit_pyportal_m4_titano.bootloader.tool=openocd
+adafruit_pyportal_m4_titano.bootloader.file=metroM4/bootloader-metro_m4-v2.0.0-adafruit.5.bin
+adafruit_pyportal_m4_titano.compiler.arm.cmsis.ldflags="-L{runtime.tools.CMSIS-5.4.0.path}/CMSIS/Lib/GCC/" "-L{build.variant.path}" -larm_cortexM4lf_math -mfloat-abi=hard -mfpu=fpv4-sp-d16
+adafruit_pyportal_m4_titano.menu.cache.on=Enabled
+adafruit_pyportal_m4_titano.menu.cache.on.build.cache_flags=-DENABLE_CACHE
+adafruit_pyportal_m4_titano.menu.cache.off=Disabled
+adafruit_pyportal_m4_titano.menu.cache.off.build.cache_flags=
+adafruit_pyportal_m4_titano.menu.speed.120=120 MHz (standard)
+adafruit_pyportal_m4_titano.menu.speed.120.build.f_cpu=120000000L
+adafruit_pyportal_m4_titano.menu.speed.150=150 MHz (overclock)
+adafruit_pyportal_m4_titano.menu.speed.150.build.f_cpu=150000000L
+adafruit_pyportal_m4_titano.menu.speed.180=180 MHz (overclock)
+adafruit_pyportal_m4_titano.menu.speed.180.build.f_cpu=180000000L
+adafruit_pyportal_m4_titano.menu.speed.200=200 MHz (overclock)
+adafruit_pyportal_m4_titano.menu.speed.200.build.f_cpu=200000000L
+adafruit_pyportal_m4_titano.menu.opt.small=Small (-Os) (standard)
+adafruit_pyportal_m4_titano.menu.opt.small.build.flags.optimize=-Os
+adafruit_pyportal_m4_titano.menu.opt.fast=Fast (-O2)
+adafruit_pyportal_m4_titano.menu.opt.fast.build.flags.optimize=-O2
+adafruit_pyportal_m4_titano.menu.opt.faster=Faster (-O3)
+adafruit_pyportal_m4_titano.menu.opt.faster.build.flags.optimize=-O3
+adafruit_pyportal_m4_titano.menu.opt.fastest=Fastest (-Ofast)
+adafruit_pyportal_m4_titano.menu.opt.fastest.build.flags.optimize=-Ofast
+adafruit_pyportal_m4_titano.menu.opt.dragons=Here be dragons (-Ofast -funroll-loops)
+adafruit_pyportal_m4_titano.menu.opt.dragons.build.flags.optimize=-Ofast -funroll-loops
+adafruit_pyportal_m4_titano.menu.maxqspi.50=50 MHz (standard)
+adafruit_pyportal_m4_titano.menu.maxqspi.50.build.flags.maxqspi=-DVARIANT_QSPI_BAUD_DEFAULT=50000000
+adafruit_pyportal_m4_titano.menu.maxqspi.fcpu=CPU Speed / 2
+adafruit_pyportal_m4_titano.menu.maxqspi.fcpu.build.flags.maxqspi=-DVARIANT_QSPI_BAUD_DEFAULT=({build.f_cpu})
+adafruit_pyportal_m4_titano.menu.usbstack.arduino=Arduino
+adafruit_pyportal_m4_titano.menu.usbstack.tinyusb=TinyUSB
+adafruit_pyportal_m4_titano.menu.usbstack.tinyusb.build.flags.usbstack=-DUSE_TINYUSB
+adafruit_pyportal_m4_titano.menu.debug.off=Off
+adafruit_pyportal_m4_titano.menu.debug.on=On
+adafruit_pyportal_m4_titano.menu.debug.on.build.flags.debug=-g
+
+# Adafruit pyBadge M4 (SAMD51)
+# ------------------------------
+adafruit_pybadge_m4.name=Adafruit pyBadge M4 Express (SAMD51)
+adafruit_pybadge_m4.vid.0=0x239A
+adafruit_pybadge_m4.pid.0=0x8033
+adafruit_pybadge_m4.vid.1=0x239A
+adafruit_pybadge_m4.pid.1=0x0033
+adafruit_pybadge_m4.vid.1=0x239A
+adafruit_pybadge_m4.pid.1=0x8033
+adafruit_pybadge_m4.upload.tool=bossac18
+adafruit_pybadge_m4.upload.protocol=sam-ba
+adafruit_pybadge_m4.upload.maximum_size=507904
+adafruit_pybadge_m4.upload.offset=0x4000
+adafruit_pybadge_m4.upload.use_1200bps_touch=true
+adafruit_pybadge_m4.upload.wait_for_upload_port=true
+adafruit_pybadge_m4.upload.native_usb=true
+adafruit_pybadge_m4.build.mcu=cortex-m4
+#adafruit_pybadge_m4.build.f_cpu=120000000L
+adafruit_pybadge_m4.build.usb_product="Adafruit pyBadge M4"
+adafruit_pybadge_m4.build.usb_manufacturer="Adafruit LLC"
+adafruit_pybadge_m4.build.board=PYBADGE_M4
+adafruit_pybadge_m4.build.core=arduino
+adafruit_pybadge_m4.build.extra_flags=-D__SAMD51J19A__ -DADAFRUIT_PYBADGE_M4_EXPRESS -DCRYSTALLESS -D__SAMD51__ {build.usb_flags} -D__FPU_PRESENT -DARM_MATH_CM4 -mfloat-abi=hard -mfpu=fpv4-sp-d16
+adafruit_pybadge_m4.build.ldscript=linker_scripts/gcc/flash_with_bootloader.ld
+adafruit_pybadge_m4.build.openocdscript=openocd_scripts/arduino_zero.cfg
+adafruit_pybadge_m4.build.variant=pybadge_m4
+adafruit_pybadge_m4.build.variant_system_lib=
+adafruit_pybadge_m4.build.vid=0x239A
+adafruit_pybadge_m4.build.pid=0x8033
+adafruit_pybadge_m4.bootloader.tool=openocd
+adafruit_pybadge_m4.bootloader.file=featherM4/bootloader-feather_m4-v2.0.0-adafruit.5.bin
+adafruit_pybadge_m4.compiler.arm.cmsis.ldflags="-L{runtime.tools.CMSIS-5.4.0.path}/CMSIS/Lib/GCC/" "-L{build.variant.path}" -larm_cortexM4lf_math -mfloat-abi=hard -mfpu=fpv4-sp-d16
+adafruit_pybadge_m4.menu.cache.on=Enabled
+adafruit_pybadge_m4.menu.cache.on.build.cache_flags=-DENABLE_CACHE
+adafruit_pybadge_m4.menu.cache.off=Disabled
+adafruit_pybadge_m4.menu.cache.off.build.cache_flags=
+adafruit_pybadge_m4.menu.speed.120=120 MHz (standard)
+adafruit_pybadge_m4.menu.speed.120.build.f_cpu=120000000L
+adafruit_pybadge_m4.menu.speed.150=150 MHz (overclock)
+adafruit_pybadge_m4.menu.speed.150.build.f_cpu=150000000L
+adafruit_pybadge_m4.menu.speed.180=180 MHz (overclock)
+adafruit_pybadge_m4.menu.speed.180.build.f_cpu=180000000L
+adafruit_pybadge_m4.menu.speed.200=200 MHz (overclock)
+adafruit_pybadge_m4.menu.speed.200.build.f_cpu=200000000L
+adafruit_pybadge_m4.menu.opt.small=Small (-Os) (standard)
+adafruit_pybadge_m4.menu.opt.small.build.flags.optimize=-Os
+adafruit_pybadge_m4.menu.opt.fast=Fast (-O2)
+adafruit_pybadge_m4.menu.opt.fast.build.flags.optimize=-O2
+adafruit_pybadge_m4.menu.opt.faster=Faster (-O3)
+adafruit_pybadge_m4.menu.opt.faster.build.flags.optimize=-O3
+adafruit_pybadge_m4.menu.opt.fastest=Fastest (-Ofast)
+adafruit_pybadge_m4.menu.opt.fastest.build.flags.optimize=-Ofast
+adafruit_pybadge_m4.menu.opt.dragons=Here be dragons (-Ofast -funroll-loops)
+adafruit_pybadge_m4.menu.opt.dragons.build.flags.optimize=-Ofast -funroll-loops
+adafruit_pybadge_m4.menu.maxqspi.50=50 MHz (standard)
+adafruit_pybadge_m4.menu.maxqspi.50.build.flags.maxqspi=-DVARIANT_QSPI_BAUD_DEFAULT=50000000
+adafruit_pybadge_m4.menu.maxqspi.fcpu=CPU Speed / 2
+adafruit_pybadge_m4.menu.maxqspi.fcpu.build.flags.maxqspi=-DVARIANT_QSPI_BAUD_DEFAULT=({build.f_cpu})
+adafruit_pybadge_m4.menu.usbstack.arduino=Arduino
+adafruit_pybadge_m4.menu.usbstack.tinyusb=TinyUSB
+adafruit_pybadge_m4.menu.usbstack.tinyusb.build.flags.usbstack=-DUSE_TINYUSB
+adafruit_pybadge_m4.menu.debug.off=Off
+adafruit_pybadge_m4.menu.debug.on=On
+adafruit_pybadge_m4.menu.debug.on.build.flags.debug=-g
+
+
+# Adafruit Metro M4 AirLift lite (SAMD51)
+# ------------------------------
+adafruit_metro_m4_airliftlite.name=Adafruit Metro M4 AirLift Lite (SAMD51)
+adafruit_metro_m4_airliftlite.vid.0=0x239A
+adafruit_metro_m4_airliftlite.pid.0=0x8037
+adafruit_metro_m4_airliftlite.vid.1=0x239A
+adafruit_metro_m4_airliftlite.pid.1=0x0037
+adafruit_metro_m4_airliftlite.upload.tool=bossac18
+adafruit_metro_m4_airliftlite.upload.protocol=sam-ba
+adafruit_metro_m4_airliftlite.upload.maximum_size=507904
+adafruit_metro_m4_airliftlite.upload.offset=0x4000
+adafruit_metro_m4_airliftlite.upload.use_1200bps_touch=true
+adafruit_metro_m4_airliftlite.upload.wait_for_upload_port=true
+adafruit_metro_m4_airliftlite.upload.native_usb=true
+adafruit_metro_m4_airliftlite.build.mcu=cortex-m4
+#adafruit_metro_m4_airliftlite.build.f_cpu=120000000L
+adafruit_metro_m4_airliftlite.build.usb_product="Adafruit Metro M4 Airlift Lite"
+adafruit_metro_m4_airliftlite.build.usb_manufacturer="Adafruit LLC"
+adafruit_metro_m4_airliftlite.build.board=METRO_M4_AIRLIFT_LITE
+adafruit_metro_m4_airliftlite.build.core=arduino
+adafruit_metro_m4_airliftlite.build.extra_flags=-D__SAMD51J19A__ -DADAFRUIT_METRO_M4_AIRLIFT_LITE -D__SAMD51__ {build.usb_flags} -D__FPU_PRESENT -DARM_MATH_CM4 -mfloat-abi=hard -mfpu=fpv4-sp-d16
+adafruit_metro_m4_airliftlite.build.ldscript=linker_scripts/gcc/flash_with_bootloader.ld
+adafruit_metro_m4_airliftlite.build.openocdscript=openocd_scripts/arduino_zero.cfg
+adafruit_metro_m4_airliftlite.build.variant=metro_m4_airlift
+adafruit_metro_m4_airliftlite.build.variant_system_lib=
+adafruit_metro_m4_airliftlite.build.vid=0x239A
+adafruit_metro_m4_airliftlite.build.pid=0x8037
+adafruit_metro_m4_airliftlite.bootloader.tool=openocd
+adafruit_metro_m4_airliftlite.bootloader.file=metroM4/bootloader-metro_m4-v2.0.0-adafruit.5.bin
+adafruit_metro_m4_airliftlite.compiler.arm.cmsis.ldflags="-L{runtime.tools.CMSIS-5.4.0.path}/CMSIS/Lib/GCC/" "-L{build.variant.path}" -larm_cortexM4lf_math -mfloat-abi=hard -mfpu=fpv4-sp-d16
+adafruit_metro_m4_airliftlite.menu.cache.on=Enabled
+adafruit_metro_m4_airliftlite.menu.cache.on.build.cache_flags=-DENABLE_CACHE
+adafruit_metro_m4_airliftlite.menu.cache.off=Disabled
+adafruit_metro_m4_airliftlite.menu.cache.off.build.cache_flags=
+adafruit_metro_m4_airliftlite.menu.speed.120=120 MHz (standard)
+adafruit_metro_m4_airliftlite.menu.speed.120.build.f_cpu=120000000L
+adafruit_metro_m4_airliftlite.menu.speed.150=150 MHz (overclock)
+adafruit_metro_m4_airliftlite.menu.speed.150.build.f_cpu=150000000L
+adafruit_metro_m4_airliftlite.menu.speed.180=180 MHz (overclock)
+adafruit_metro_m4_airliftlite.menu.speed.180.build.f_cpu=180000000L
+adafruit_metro_m4_airliftlite.menu.speed.200=200 MHz (overclock)
+adafruit_metro_m4_airliftlite.menu.speed.200.build.f_cpu=200000000L
+adafruit_metro_m4_airliftlite.menu.opt.small=Small (-Os) (standard)
+adafruit_metro_m4_airliftlite.menu.opt.small.build.flags.optimize=-Os
+adafruit_metro_m4_airliftlite.menu.opt.fast=Fast (-O2)
+adafruit_metro_m4_airliftlite.menu.opt.fast.build.flags.optimize=-O2
+adafruit_metro_m4_airliftlite.menu.opt.faster=Faster (-O3)
+adafruit_metro_m4_airliftlite.menu.opt.faster.build.flags.optimize=-O3
+adafruit_metro_m4_airliftlite.menu.opt.fastest=Fastest (-Ofast)
+adafruit_metro_m4_airliftlite.menu.opt.fastest.build.flags.optimize=-Ofast
+adafruit_metro_m4_airliftlite.menu.opt.dragons=Here be dragons (-Ofast -funroll-loops)
+adafruit_metro_m4_airliftlite.menu.opt.dragons.build.flags.optimize=-Ofast -funroll-loops
+adafruit_metro_m4_airliftlite.menu.maxqspi.50=50 MHz (standard)
+adafruit_metro_m4_airliftlite.menu.maxqspi.50.build.flags.maxqspi=-DVARIANT_QSPI_BAUD_DEFAULT=50000000
+adafruit_metro_m4_airliftlite.menu.maxqspi.fcpu=CPU Speed / 2
+adafruit_metro_m4_airliftlite.menu.maxqspi.fcpu.build.flags.maxqspi=-DVARIANT_QSPI_BAUD_DEFAULT=({build.f_cpu})
+adafruit_metro_m4_airliftlite.menu.usbstack.arduino=Arduino
+adafruit_metro_m4_airliftlite.menu.usbstack.tinyusb=TinyUSB
+adafruit_metro_m4_airliftlite.menu.usbstack.tinyusb.build.flags.usbstack=-DUSE_TINYUSB
+adafruit_metro_m4_airliftlite.menu.debug.off=Off
+adafruit_metro_m4_airliftlite.menu.debug.on=On
+adafruit_metro_m4_airliftlite.menu.debug.on.build.flags.debug=-g
+
+# Adafruit pyGamer M4 Express (SAMD51)
+# ------------------------------
+adafruit_pygamer_m4.name=Adafruit PyGamer M4 Express (SAMD51)
+adafruit_pygamer_m4.vid.0=0x239A
+adafruit_pygamer_m4.pid.0=0x803D
+adafruit_pygamer_m4.vid.1=0x239A
+adafruit_pygamer_m4.pid.1=0x003D
+adafruit_pygamer_m4.vid.1=0x239A
+adafruit_pygamer_m4.pid.1=0x803E
+adafruit_pygamer_m4.upload.tool=bossac18
+adafruit_pygamer_m4.upload.protocol=sam-ba
+adafruit_pygamer_m4.upload.maximum_size=507904
+adafruit_pygamer_m4.upload.offset=0x4000
+adafruit_pygamer_m4.upload.use_1200bps_touch=true
+adafruit_pygamer_m4.upload.wait_for_upload_port=true
+adafruit_pygamer_m4.upload.native_usb=true
+adafruit_pygamer_m4.build.mcu=cortex-m4
+#adafruit_pygamer_m4.build.f_cpu=120000000L
+adafruit_pygamer_m4.build.usb_product="Adafruit PyGamer M4"
+adafruit_pygamer_m4.build.usb_manufacturer="Adafruit LLC"
+adafruit_pygamer_m4.build.board=PYGAMER_M4
+adafruit_pygamer_m4.build.core=arduino
+adafruit_pygamer_m4.build.extra_flags=-D__SAMD51J19A__ -DADAFRUIT_PYGAMER_M4_EXPRESS -DCRYSTALLESS -D__SAMD51__ {build.usb_flags} -D__FPU_PRESENT -DARM_MATH_CM4 -mfloat-abi=hard -mfpu=fpv4-sp-d16
+adafruit_pygamer_m4.build.ldscript=linker_scripts/gcc/flash_with_bootloader.ld
+adafruit_pygamer_m4.build.openocdscript=openocd_scripts/arduino_zero.cfg
+adafruit_pygamer_m4.build.variant=pygamer_m4
+adafruit_pygamer_m4.build.variant_system_lib=
+adafruit_pygamer_m4.build.vid=0x239A
+adafruit_pygamer_m4.build.pid=0x803D
+adafruit_pygamer_m4.bootloader.tool=openocd
+adafruit_pygamer_m4.bootloader.file=featherM4/bootloader-feather_m4-v2.0.0-adafruit.5.bin
+adafruit_pygamer_m4.compiler.arm.cmsis.ldflags="-L{runtime.tools.CMSIS-5.4.0.path}/CMSIS/Lib/GCC/" "-L{build.variant.path}" -larm_cortexM4lf_math -mfloat-abi=hard -mfpu=fpv4-sp-d16
+adafruit_pygamer_m4.menu.cache.on=Enabled
+adafruit_pygamer_m4.menu.cache.on.build.cache_flags=-DENABLE_CACHE
+adafruit_pygamer_m4.menu.cache.off=Disabled
+adafruit_pygamer_m4.menu.cache.off.build.cache_flags=
+adafruit_pygamer_m4.menu.speed.120=120 MHz (standard)
+adafruit_pygamer_m4.menu.speed.120.build.f_cpu=120000000L
+adafruit_pygamer_m4.menu.speed.150=150 MHz (overclock)
+adafruit_pygamer_m4.menu.speed.150.build.f_cpu=150000000L
+adafruit_pygamer_m4.menu.speed.180=180 MHz (overclock)
+adafruit_pygamer_m4.menu.speed.180.build.f_cpu=180000000L
+adafruit_pygamer_m4.menu.speed.200=200 MHz (overclock)
+adafruit_pygamer_m4.menu.speed.200.build.f_cpu=200000000L
+adafruit_pygamer_m4.menu.opt.small=Small (-Os) (standard)
+adafruit_pygamer_m4.menu.opt.small.build.flags.optimize=-Os
+adafruit_pygamer_m4.menu.opt.fast=Fast (-O2)
+adafruit_pygamer_m4.menu.opt.fast.build.flags.optimize=-O2
+adafruit_pygamer_m4.menu.opt.faster=Faster (-O3)
+adafruit_pygamer_m4.menu.opt.faster.build.flags.optimize=-O3
+adafruit_pygamer_m4.menu.opt.fastest=Fastest (-Ofast)
+adafruit_pygamer_m4.menu.opt.fastest.build.flags.optimize=-Ofast
+adafruit_pygamer_m4.menu.opt.dragons=Here be dragons (-Ofast -funroll-loops)
+adafruit_pygamer_m4.menu.opt.dragons.build.flags.optimize=-Ofast -funroll-loops
+adafruit_pygamer_m4.menu.maxqspi.50=50 MHz (standard)
+adafruit_pygamer_m4.menu.maxqspi.50.build.flags.maxqspi=-DVARIANT_QSPI_BAUD_DEFAULT=50000000
+adafruit_pygamer_m4.menu.maxqspi.fcpu=CPU Speed / 2
+adafruit_pygamer_m4.menu.maxqspi.fcpu.build.flags.maxqspi=-DVARIANT_QSPI_BAUD_DEFAULT=({build.f_cpu})
+adafruit_pygamer_m4.menu.usbstack.arduino=Arduino
+adafruit_pygamer_m4.menu.usbstack.tinyusb=TinyUSB
+adafruit_pygamer_m4.menu.usbstack.tinyusb.build.flags.usbstack=-DUSE_TINYUSB
+adafruit_pygamer_m4.menu.debug.off=Off
+adafruit_pygamer_m4.menu.debug.on=On
+adafruit_pygamer_m4.menu.debug.on.build.flags.debug=-g
+
+# Adafruit pyGamer M4 Express (SAMD51)
+# ------------------------------
+adafruit_pygamer_advance_m4.name=Adafruit PyGamer Advance M4 (SAMD51)
+adafruit_pygamer_advance_m4.vid.0=0x239A
+adafruit_pygamer_advance_m4.pid.0=0x8041
+adafruit_pygamer_advance_m4.vid.1=0x239A
+adafruit_pygamer_advance_m4.pid.1=0x0041
+adafruit_pygamer_advance_m4.vid.1=0x239A
+adafruit_pygamer_advance_m4.pid.1=0x8042
+adafruit_pygamer_advance_m4.upload.tool=bossac18
+adafruit_pygamer_advance_m4.upload.protocol=sam-ba
+adafruit_pygamer_advance_m4.upload.maximum_size=1032192
+adafruit_pygamer_advance_m4.upload.offset=0x4000
+adafruit_pygamer_advance_m4.upload.use_1200bps_touch=true
+adafruit_pygamer_advance_m4.upload.wait_for_upload_port=true
+adafruit_pygamer_advance_m4.upload.native_usb=true
+adafruit_pygamer_advance_m4.build.mcu=cortex-m4
+adafruit_pygamer_advance_m4.build.usb_product="Adafruit PyGamer Advance M4"
+adafruit_pygamer_advance_m4.build.usb_manufacturer="Adafruit LLC"
+adafruit_pygamer_advance_m4.build.board=PYGAMER_ADVANCE_M4
+adafruit_pygamer_advance_m4.build.core=arduino
+adafruit_pygamer_advance_m4.build.extra_flags=-D__SAMD51J20A__ -DADAFRUIT_PYGAMER_ADVANCE_M4_EXPRESS -DCRYSTALLESS -D__SAMD51__ {build.usb_flags} -D__FPU_PRESENT -DARM_MATH_CM4 -mfloat-abi=hard -mfpu=fpv4-sp-d16
+adafruit_pygamer_advance_m4.build.ldscript=linker_scripts/gcc/flash_with_bootloader.ld
+adafruit_pygamer_advance_m4.build.openocdscript=openocd_scripts/arduino_zero.cfg
+adafruit_pygamer_advance_m4.build.variant=pygamer_advance_m4
+adafruit_pygamer_advance_m4.build.variant_system_lib=
+adafruit_pygamer_advance_m4.build.vid=0x239A
+adafruit_pygamer_advance_m4.build.pid=0x8041
+adafruit_pygamer_advance_m4.bootloader.tool=openocd
+adafruit_pygamer_advance_m4.bootloader.file=featherM4/bootloader-feather_m4-v2.0.0-adafruit.5.bin
+adafruit_pygamer_advance_m4.compiler.arm.cmsis.ldflags="-L{runtime.tools.CMSIS-5.4.0.path}/CMSIS/Lib/GCC/" "-L{build.variant.path}" -larm_cortexM4lf_math -mfloat-abi=hard -mfpu=fpv4-sp-d16
+adafruit_pygamer_advance_m4.menu.cache.on=Enabled
+adafruit_pygamer_advance_m4.menu.cache.on.build.cache_flags=-DENABLE_CACHE
+adafruit_pygamer_advance_m4.menu.cache.off=Disabled
+adafruit_pygamer_advance_m4.menu.cache.off.build.cache_flags=
+adafruit_pygamer_advance_m4.menu.speed.120=120 MHz (standard)
+adafruit_pygamer_advance_m4.menu.speed.120.build.f_cpu=120000000L
+adafruit_pygamer_advance_m4.menu.speed.150=150 MHz (overclock)
+adafruit_pygamer_advance_m4.menu.speed.150.build.f_cpu=150000000L
+adafruit_pygamer_advance_m4.menu.speed.180=180 MHz (overclock)
+adafruit_pygamer_advance_m4.menu.speed.180.build.f_cpu=180000000L
+adafruit_pygamer_advance_m4.menu.speed.200=200 MHz (overclock)
+adafruit_pygamer_advance_m4.menu.speed.200.build.f_cpu=200000000L
+adafruit_pygamer_advance_m4.menu.opt.small=Small (-Os) (standard)
+adafruit_pygamer_advance_m4.menu.opt.small.build.flags.optimize=-Os
+adafruit_pygamer_advance_m4.menu.opt.fast=Fast (-O2)
+adafruit_pygamer_advance_m4.menu.opt.fast.build.flags.optimize=-O2
+adafruit_pygamer_advance_m4.menu.opt.faster=Faster (-O3)
+adafruit_pygamer_advance_m4.menu.opt.faster.build.flags.optimize=-O3
+adafruit_pygamer_advance_m4.menu.opt.fastest=Fastest (-Ofast)
+adafruit_pygamer_advance_m4.menu.opt.fastest.build.flags.optimize=-Ofast
+adafruit_pygamer_advance_m4.menu.opt.dragons=Here be dragons (-Ofast -funroll-loops)
+adafruit_pygamer_advance_m4.menu.opt.dragons.build.flags.optimize=-Ofast -funroll-loops
+adafruit_pygamer_advance_m4.menu.maxqspi.50=50 MHz (standard)
+adafruit_pygamer_advance_m4.menu.maxqspi.fcpu=CPU Speed / 2
+adafruit_pygamer_advance_m4.menu.maxqspi.50.build.flags.maxqspi=-DVARIANT_QSPI_BAUD_DEFAULT=50000000
+adafruit_pygamer_advance_m4.menu.maxqspi.fcpu=CPU Speed / 2
+adafruit_pygamer_advance_m4.menu.maxqspi.fcpu.build.flags.maxqspi=-DVARIANT_QSPI_BAUD_DEFAULT=({build.f_cpu})
+adafruit_pygamer_advance_m4.menu.usbstack.arduino=Arduino
+adafruit_pygamer_advance_m4.menu.usbstack.tinyusb=TinyUSB
+adafruit_pygamer_advance_m4.menu.usbstack.tinyusb.build.flags.usbstack=-DUSE_TINYUSB
+adafruit_pygamer_advance_m4.menu.debug.off=Off
+adafruit_pygamer_advance_m4.menu.debug.on=On
+adafruit_pygamer_advance_m4.menu.debug.on.build.flags.debug=-g
+
+# Adafruit pyBadge AirLift M4 (SAMD51)
+# ------------------------------
+adafruit_pybadge_airlift_m4.name=Adafruit pyBadge AirLift M4 (SAMD51)
+adafruit_pybadge_airlift_m4.vid.0=0x239A
+adafruit_pybadge_airlift_m4.pid.0=0x8043
+adafruit_pybadge_airlift_m4.vid.1=0x239A
+adafruit_pybadge_airlift_m4.pid.1=0x0033
+adafruit_pybadge_airlift_m4.vid.1=0x239A
+adafruit_pybadge_airlift_m4.pid.1=0x8043
+adafruit_pybadge_airlift_m4.upload.tool=bossac18
+adafruit_pybadge_airlift_m4.upload.protocol=sam-ba
+adafruit_pybadge_airlift_m4.upload.maximum_size=1032192
+adafruit_pybadge_airlift_m4.upload.offset=0x4000
+adafruit_pybadge_airlift_m4.upload.use_1200bps_touch=true
+adafruit_pybadge_airlift_m4.upload.wait_for_upload_port=true
+adafruit_pybadge_airlift_m4.upload.native_usb=true
+adafruit_pybadge_airlift_m4.build.mcu=cortex-m4
+#adafruit_pybadge_airlift_m4.build.f_cpu=120000000L
+adafruit_pybadge_airlift_m4.build.usb_product="Adafruit pyBadge AirLift M4"
+adafruit_pybadge_airlift_m4.build.usb_manufacturer="Adafruit LLC"
+adafruit_pybadge_airlift_m4.build.board=PYBADGE_AIRLIFT_M4
+adafruit_pybadge_airlift_m4.build.core=arduino
+adafruit_pybadge_airlift_m4.build.extra_flags=-D__SAMD51J20A__ -DADAFRUIT_PYBADGE_AIRLIFT_M4 -DCRYSTALLESS -D__SAMD51__ {build.usb_flags} -D__FPU_PRESENT -DARM_MATH_CM4 -mfloat-abi=hard -mfpu=fpv4-sp-d16
+adafruit_pybadge_airlift_m4.build.ldscript=linker_scripts/gcc/flash_with_bootloader.ld
+adafruit_pybadge_airlift_m4.build.openocdscript=openocd_scripts/arduino_zero.cfg
+adafruit_pybadge_airlift_m4.build.variant=pybadge_airlift_m4
+adafruit_pybadge_airlift_m4.build.variant_system_lib=
+adafruit_pybadge_airlift_m4.build.vid=0x239A
+adafruit_pybadge_airlift_m4.build.pid=0x8043
+adafruit_pybadge_airlift_m4.bootloader.tool=openocd
+adafruit_pybadge_airlift_m4.bootloader.file=featherM4/bootloader-feather_m4-v2.0.0-adafruit.5.bin
+adafruit_pybadge_airlift_m4.compiler.arm.cmsis.ldflags="-L{runtime.tools.CMSIS-5.4.0.path}/CMSIS/Lib/GCC/" "-L{build.variant.path}" -larm_cortexM4lf_math -mfloat-abi=hard -mfpu=fpv4-sp-d16
+adafruit_pybadge_airlift_m4.menu.cache.on=Enabled
+adafruit_pybadge_airlift_m4.menu.cache.on.build.cache_flags=-DENABLE_CACHE
+adafruit_pybadge_airlift_m4.menu.cache.off=Disabled
+adafruit_pybadge_airlift_m4.menu.cache.off.build.cache_flags=
+adafruit_pybadge_airlift_m4.menu.speed.120=120 MHz (standard)
+adafruit_pybadge_airlift_m4.menu.speed.120.build.f_cpu=120000000L
+adafruit_pybadge_airlift_m4.menu.speed.150=150 MHz (overclock)
+adafruit_pybadge_airlift_m4.menu.speed.150.build.f_cpu=150000000L
+adafruit_pybadge_airlift_m4.menu.speed.180=180 MHz (overclock)
+adafruit_pybadge_airlift_m4.menu.speed.180.build.f_cpu=180000000L
+adafruit_pybadge_airlift_m4.menu.speed.200=200 MHz (overclock)
+adafruit_pybadge_airlift_m4.menu.speed.200.build.f_cpu=200000000L
+adafruit_pybadge_airlift_m4.menu.opt.small=Small (-Os) (standard)
+adafruit_pybadge_airlift_m4.menu.opt.small.build.flags.optimize=-Os
+adafruit_pybadge_airlift_m4.menu.opt.fast=Fast (-O2)
+adafruit_pybadge_airlift_m4.menu.opt.fast.build.flags.optimize=-O2
+adafruit_pybadge_airlift_m4.menu.opt.faster=Faster (-O3)
+adafruit_pybadge_airlift_m4.menu.opt.faster.build.flags.optimize=-O3
+adafruit_pybadge_airlift_m4.menu.opt.fastest=Fastest (-Ofast)
+adafruit_pybadge_airlift_m4.menu.opt.fastest.build.flags.optimize=-Ofast
+adafruit_pybadge_airlift_m4.menu.opt.dragons=Here be dragons (-Ofast -funroll-loops)
+adafruit_pybadge_airlift_m4.menu.opt.dragons.build.flags.optimize=-Ofast -funroll-loops
+adafruit_pybadge_airlift_m4.menu.maxqspi.50=50 MHz (standard)
+adafruit_pybadge_airlift_m4.menu.maxqspi.50.build.flags.maxqspi=-DVARIANT_QSPI_BAUD_DEFAULT=50000000
+adafruit_pybadge_airlift_m4.menu.maxqspi.fcpu=CPU Speed / 2
+adafruit_pybadge_airlift_m4.menu.maxqspi.fcpu.build.flags.maxqspi=-DVARIANT_QSPI_BAUD_DEFAULT=({build.f_cpu})
+adafruit_pybadge_airlift_m4.menu.usbstack.arduino=Arduino
+adafruit_pybadge_airlift_m4.menu.usbstack.tinyusb=TinyUSB
+adafruit_pybadge_airlift_m4.menu.usbstack.tinyusb.build.flags.usbstack=-DUSE_TINYUSB
+adafruit_pybadge_airlift_m4.menu.debug.off=Off
+adafruit_pybadge_airlift_m4.menu.debug.on=On
+adafruit_pybadge_airlift_m4.menu.debug.on.build.flags.debug=-g
+
+
+# Adafruit MONSTER M4SK Express (SAMD51)
+# ------------------------------
+adafruit_monster_m4sk.name=Adafruit MONSTER M4SK (SAMD51)
+adafruit_monster_m4sk.vid.0=0x239A
+adafruit_monster_m4sk.pid.0=0x8047
+adafruit_monster_m4sk.vid.1=0x239A
+adafruit_monster_m4sk.pid.1=0x0047
+adafruit_monster_m4sk.vid.1=0x239A
+adafruit_monster_m4sk.pid.1=0x8048
+adafruit_monster_m4sk.upload.tool=bossac18
+adafruit_monster_m4sk.upload.protocol=sam-ba
+adafruit_monster_m4sk.upload.maximum_size=507904
+adafruit_monster_m4sk.upload.offset=0x4000
+adafruit_monster_m4sk.upload.use_1200bps_touch=true
+adafruit_monster_m4sk.upload.wait_for_upload_port=true
+adafruit_monster_m4sk.upload.native_usb=true
+adafruit_monster_m4sk.build.mcu=cortex-m4
+#adafruit_monster_m4sk.build.f_cpu=120000000L
+adafruit_monster_m4sk.build.usb_product="Adafruit MONSTER M4SK"
+adafruit_monster_m4sk.build.usb_manufacturer="Adafruit LLC"
+adafruit_monster_m4sk.build.board=MONSTER_M4SK
+adafruit_monster_m4sk.build.core=arduino
+adafruit_monster_m4sk.build.extra_flags=-D__SAMD51G19A__ -DADAFRUIT_MONSTER_M4SK_EXPRESS -DCRYSTALLESS -D__SAMD51__ {build.usb_flags} -D__FPU_PRESENT -DARM_MATH_CM4 -mfloat-abi=hard -mfpu=fpv4-sp-d16
+adafruit_monster_m4sk.build.ldscript=linker_scripts/gcc/flash_with_bootloader.ld
+adafruit_monster_m4sk.build.openocdscript=openocd_scripts/arduino_zero.cfg
+adafruit_monster_m4sk.build.variant=monster_m4sk
+adafruit_monster_m4sk.build.variant_system_lib=
+adafruit_monster_m4sk.build.vid=0x239A
+adafruit_monster_m4sk.build.pid=0x8047
+adafruit_monster_m4sk.bootloader.tool=openocd
+adafruit_monster_m4sk.bootloader.file=featherM4/bootloader-feather_m4-v2.0.0-adafruit.5.bin
+adafruit_monster_m4sk.compiler.arm.cmsis.ldflags="-L{runtime.tools.CMSIS-5.4.0.path}/CMSIS/Lib/GCC/" "-L{build.variant.path}" -larm_cortexM4lf_math -mfloat-abi=hard -mfpu=fpv4-sp-d16
+adafruit_monster_m4sk.menu.cache.on=Enabled
+adafruit_monster_m4sk.menu.cache.on.build.cache_flags=-DENABLE_CACHE
+adafruit_monster_m4sk.menu.cache.off=Disabled
+adafruit_monster_m4sk.menu.cache.off.build.cache_flags=
+adafruit_monster_m4sk.menu.speed.120=120 MHz (standard)
+adafruit_monster_m4sk.menu.speed.120.build.f_cpu=120000000L
+adafruit_monster_m4sk.menu.speed.150=150 MHz (overclock)
+adafruit_monster_m4sk.menu.speed.150.build.f_cpu=150000000L
+adafruit_monster_m4sk.menu.speed.180=180 MHz (overclock)
+adafruit_monster_m4sk.menu.speed.180.build.f_cpu=180000000L
+adafruit_monster_m4sk.menu.speed.200=200 MHz (overclock)
+adafruit_monster_m4sk.menu.speed.200.build.f_cpu=200000000L
+adafruit_monster_m4sk.menu.opt.small=Small (-Os) (standard)
+adafruit_monster_m4sk.menu.opt.small.build.flags.optimize=-Os
+adafruit_monster_m4sk.menu.opt.fast=Fast (-O2)
+adafruit_monster_m4sk.menu.opt.fast.build.flags.optimize=-O2
+adafruit_monster_m4sk.menu.opt.faster=Faster (-O3)
+adafruit_monster_m4sk.menu.opt.faster.build.flags.optimize=-O3
+adafruit_monster_m4sk.menu.opt.fastest=Fastest (-Ofast)
+adafruit_monster_m4sk.menu.opt.fastest.build.flags.optimize=-Ofast
+adafruit_monster_m4sk.menu.opt.dragons=Here be dragons (-Ofast -funroll-loops)
+adafruit_monster_m4sk.menu.opt.dragons.build.flags.optimize=-Ofast -funroll-loops
+adafruit_monster_m4sk.menu.maxqspi.50=50 MHz (standard)
+adafruit_monster_m4sk.menu.maxqspi.50.build.flags.maxqspi=-DVARIANT_QSPI_BAUD_DEFAULT=50000000
+adafruit_monster_m4sk.menu.maxqspi.fcpu=CPU Speed / 2
+adafruit_monster_m4sk.menu.maxqspi.fcpu.build.flags.maxqspi=-DVARIANT_QSPI_BAUD_DEFAULT=({build.f_cpu})
+adafruit_monster_m4sk.menu.usbstack.arduino=Arduino
+adafruit_monster_m4sk.menu.usbstack.tinyusb=TinyUSB
+adafruit_monster_m4sk.menu.usbstack.tinyusb.build.flags.usbstack=-DUSE_TINYUSB
+adafruit_monster_m4sk.menu.debug.off=Off
+adafruit_monster_m4sk.menu.debug.on=On
+adafruit_monster_m4sk.menu.debug.on.build.flags.debug=-g
+
+
+# Adafruit Hallowing M4 Express (SAMD51)
+# ------------------------------
+adafruit_hallowing_m4.name=Adafruit Hallowing M4 (SAMD51)
+adafruit_hallowing_m4.vid.0=0x239A
+adafruit_hallowing_m4.pid.0=0x8049
+adafruit_hallowing_m4.vid.1=0x239A
+adafruit_hallowing_m4.pid.1=0x0049
+adafruit_hallowing_m4.vid.1=0x239A
+adafruit_hallowing_m4.pid.1=0x804A
+adafruit_hallowing_m4.upload.tool=bossac18
+adafruit_hallowing_m4.upload.protocol=sam-ba
+adafruit_hallowing_m4.upload.maximum_size=507904
+adafruit_hallowing_m4.upload.offset=0x4000
+adafruit_hallowing_m4.upload.use_1200bps_touch=true
+adafruit_hallowing_m4.upload.wait_for_upload_port=true
+adafruit_hallowing_m4.upload.native_usb=true
+adafruit_hallowing_m4.build.mcu=cortex-m4
+#adafruit_hallowing_m4.build.f_cpu=120000000L
+adafruit_hallowing_m4.build.usb_product="Adafruit Hallowing M4"
+adafruit_hallowing_m4.build.usb_manufacturer="Adafruit LLC"
+adafruit_hallowing_m4.build.board=HALLOWING_M4
+adafruit_hallowing_m4.build.core=arduino
+adafruit_hallowing_m4.build.extra_flags=-D__SAMD51J19A__ -DADAFRUIT_HALLOWING_M4_EXPRESS -DCRYSTALLESS -D__SAMD51__ {build.usb_flags} -D__FPU_PRESENT -DARM_MATH_CM4 -mfloat-abi=hard -mfpu=fpv4-sp-d16
+adafruit_hallowing_m4.build.ldscript=linker_scripts/gcc/flash_with_bootloader.ld
+adafruit_hallowing_m4.build.openocdscript=openocd_scripts/arduino_zero.cfg
+adafruit_hallowing_m4.build.variant=hallowing_m4
+adafruit_hallowing_m4.build.variant_system_lib=
+adafruit_hallowing_m4.build.vid=0x239A
+adafruit_hallowing_m4.build.pid=0x8049
+adafruit_hallowing_m4.bootloader.tool=openocd
+adafruit_hallowing_m4.bootloader.file=featherM4/bootloader-feather_m4-v2.0.0-adafruit.5.bin
+adafruit_hallowing_m4.compiler.arm.cmsis.ldflags="-L{runtime.tools.CMSIS-5.4.0.path}/CMSIS/Lib/GCC/" "-L{build.variant.path}" -larm_cortexM4lf_math -mfloat-abi=hard -mfpu=fpv4-sp-d16
+adafruit_hallowing_m4.menu.cache.on=Enabled
+adafruit_hallowing_m4.menu.cache.on.build.cache_flags=-DENABLE_CACHE
+adafruit_hallowing_m4.menu.cache.off=Disabled
+adafruit_hallowing_m4.menu.cache.off.build.cache_flags=
+adafruit_hallowing_m4.menu.speed.120=120 MHz (standard)
+adafruit_hallowing_m4.menu.speed.120.build.f_cpu=120000000L
+adafruit_hallowing_m4.menu.speed.150=150 MHz (overclock)
+adafruit_hallowing_m4.menu.speed.150.build.f_cpu=150000000L
+adafruit_hallowing_m4.menu.speed.180=180 MHz (overclock)
+adafruit_hallowing_m4.menu.speed.180.build.f_cpu=180000000L
+adafruit_hallowing_m4.menu.speed.200=200 MHz (overclock)
+adafruit_hallowing_m4.menu.speed.200.build.f_cpu=200000000L
+adafruit_hallowing_m4.menu.opt.small=Small (-Os) (standard)
+adafruit_hallowing_m4.menu.opt.small.build.flags.optimize=-Os
+adafruit_hallowing_m4.menu.opt.fast=Fast (-O2)
+adafruit_hallowing_m4.menu.opt.fast.build.flags.optimize=-O2
+adafruit_hallowing_m4.menu.opt.faster=Faster (-O3)
+adafruit_hallowing_m4.menu.opt.faster.build.flags.optimize=-O3
+adafruit_hallowing_m4.menu.opt.fastest=Fastest (-Ofast)
+adafruit_hallowing_m4.menu.opt.fastest.build.flags.optimize=-Ofast
+adafruit_hallowing_m4.menu.opt.dragons=Here be dragons (-Ofast -funroll-loops)
+adafruit_hallowing_m4.menu.opt.dragons.build.flags.optimize=-Ofast -funroll-loops
+adafruit_hallowing_m4.menu.maxqspi.50=50 MHz (standard)
+adafruit_hallowing_m4.menu.maxqspi.50.build.flags.maxqspi=-DVARIANT_QSPI_BAUD_DEFAULT=50000000
+adafruit_hallowing_m4.menu.maxqspi.fcpu=CPU Speed / 2
+adafruit_hallowing_m4.menu.maxqspi.fcpu.build.flags.maxqspi=-DVARIANT_QSPI_BAUD_DEFAULT=({build.f_cpu})
+adafruit_hallowing_m4.menu.usbstack.arduino=Arduino
+adafruit_hallowing_m4.menu.usbstack.tinyusb=TinyUSB
+adafruit_hallowing_m4.menu.usbstack.tinyusb.build.flags.usbstack=-DUSE_TINYUSB
+adafruit_hallowing_m4.menu.debug.off=Off
+adafruit_hallowing_m4.menu.debug.on=On
+adafruit_hallowing_m4.menu.debug.on.build.flags.debug=-g
+
+# Adafruit Matrix Portal M4 (SAMD51)
+# ------------------------------
+adafruit_matrixportal_m4.name=Adafruit Matrix Portal M4 (SAMD51)
+adafruit_matrixportal_m4.vid.0=0x239A
+adafruit_matrixportal_m4.pid.0=0x80C9
+adafruit_matrixportal_m4.vid.1=0x239A
+adafruit_matrixportal_m4.pid.1=0x00C9
+adafruit_matrixportal_m4.vid.1=0x239A
+adafruit_matrixportal_m4.pid.1=0x80CA
+adafruit_matrixportal_m4.upload.tool=bossac18
+adafruit_matrixportal_m4.upload.protocol=sam-ba
+adafruit_matrixportal_m4.upload.maximum_size=507904
+adafruit_matrixportal_m4.upload.offset=0x4000
+adafruit_matrixportal_m4.upload.use_1200bps_touch=true
+adafruit_matrixportal_m4.upload.wait_for_upload_port=true
+adafruit_matrixportal_m4.upload.native_usb=true
+adafruit_matrixportal_m4.build.mcu=cortex-m4
+#adafruit_matrixportal_m4.build.f_cpu=120000000L
+adafruit_matrixportal_m4.build.usb_product="Adafruit Matrix Portal M4"
+adafruit_matrixportal_m4.build.usb_manufacturer="Adafruit LLC"
+adafruit_matrixportal_m4.build.board=MATRIXPORTAL_M4
+adafruit_matrixportal_m4.build.core=arduino
+adafruit_matrixportal_m4.build.extra_flags=-D__SAMD51J19A__ -DADAFRUIT_MATRIXPORTAL_M4_EXPRESS -DCRYSTALLESS -D__SAMD51__ {build.usb_flags} -D__FPU_PRESENT -DARM_MATH_CM4 -mfloat-abi=hard -mfpu=fpv4-sp-d16
+adafruit_matrixportal_m4.build.ldscript=linker_scripts/gcc/flash_with_bootloader.ld
+adafruit_matrixportal_m4.build.openocdscript=openocd_scripts/arduino_zero.cfg
+adafruit_matrixportal_m4.build.variant=matrixportal_m4
+adafruit_matrixportal_m4.build.variant_system_lib=
+adafruit_matrixportal_m4.build.vid=0x239A
+adafruit_matrixportal_m4.build.pid=0x80C9
+adafruit_matrixportal_m4.bootloader.tool=openocd
+adafruit_matrixportal_m4.bootloader.file=matrixportalM4/bootloader-matrixportal_m4.bin
+adafruit_matrixportal_m4.compiler.arm.cmsis.ldflags="-L{runtime.tools.CMSIS-5.4.0.path}/CMSIS/Lib/GCC/" "-L{build.variant.path}" -larm_cortexM4lf_math -mfloat-abi=hard -mfpu=fpv4-sp-d16
+adafruit_matrixportal_m4.menu.cache.on=Enabled
+adafruit_matrixportal_m4.menu.cache.on.build.cache_flags=-DENABLE_CACHE
+adafruit_matrixportal_m4.menu.cache.off=Disabled
+adafruit_matrixportal_m4.menu.cache.off.build.cache_flags=
+adafruit_matrixportal_m4.menu.speed.120=120 MHz (standard)
+adafruit_matrixportal_m4.menu.speed.120.build.f_cpu=120000000L
+adafruit_matrixportal_m4.menu.speed.150=150 MHz (overclock)
+adafruit_matrixportal_m4.menu.speed.150.build.f_cpu=150000000L
+adafruit_matrixportal_m4.menu.speed.180=180 MHz (overclock)
+adafruit_matrixportal_m4.menu.speed.180.build.f_cpu=180000000L
+adafruit_matrixportal_m4.menu.speed.200=200 MHz (overclock)
+adafruit_matrixportal_m4.menu.speed.200.build.f_cpu=200000000L
+adafruit_matrixportal_m4.menu.opt.small=Small (-Os) (standard)
+adafruit_matrixportal_m4.menu.opt.small.build.flags.optimize=-Os
+adafruit_matrixportal_m4.menu.opt.fast=Fast (-O2)
+adafruit_matrixportal_m4.menu.opt.fast.build.flags.optimize=-O2
+adafruit_matrixportal_m4.menu.opt.faster=Faster (-O3)
+adafruit_matrixportal_m4.menu.opt.faster.build.flags.optimize=-O3
+adafruit_matrixportal_m4.menu.opt.fastest=Fastest (-Ofast)
+adafruit_matrixportal_m4.menu.opt.fastest.build.flags.optimize=-Ofast
+adafruit_matrixportal_m4.menu.opt.dragons=Here be dragons (-Ofast -funroll-loops)
+adafruit_matrixportal_m4.menu.opt.dragons.build.flags.optimize=-Ofast -funroll-loops
+adafruit_matrixportal_m4.menu.maxqspi.50=50 MHz (standard)
+adafruit_matrixportal_m4.menu.maxqspi.50.build.flags.maxqspi=-DVARIANT_QSPI_BAUD_DEFAULT=50000000
+adafruit_matrixportal_m4.menu.maxqspi.fcpu=CPU Speed / 2
+adafruit_matrixportal_m4.menu.maxqspi.fcpu.build.flags.maxqspi=-DVARIANT_QSPI_BAUD_DEFAULT=({build.f_cpu})
+adafruit_matrixportal_m4.menu.usbstack.arduino=Arduino
+adafruit_matrixportal_m4.menu.usbstack.tinyusb=TinyUSB
+adafruit_matrixportal_m4.menu.usbstack.tinyusb.build.flags.usbstack=-DUSE_TINYUSB
+adafruit_matrixportal_m4.menu.debug.off=Off
+adafruit_matrixportal_m4.menu.debug.on=On
+adafruit_matrixportal_m4.menu.debug.on.build.flags.debug=-g
+
+# Adafruit BLM Badge (SAMD21)
+# ------------------------------
+adafruit_blm_badge.name=Adafruit BLM Badge
+adafruit_blm_badge.vid.0=0x239A
+adafruit_blm_badge.pid.0=0x80BF
+adafruit_blm_badge.vid.1=0x239A
+adafruit_blm_badge.pid.1=0x00BF
+adafruit_blm_badge.upload.tool=bossac
+adafruit_blm_badge.upload.protocol=sam-ba
+adafruit_blm_badge.upload.maximum_size=262144
+adafruit_blm_badge.upload.offset=0x2000
+adafruit_blm_badge.upload.use_1200bps_touch=true
+adafruit_blm_badge.upload.wait_for_upload_port=true
+adafruit_blm_badge.upload.native_usb=true
+adafruit_blm_badge.build.mcu=cortex-m0plus
+adafruit_blm_badge.build.f_cpu=48000000L
+adafruit_blm_badge.build.usb_product="BLM Badge"
+adafruit_blm_badge.build.usb_manufacturer="Adafruit"
+adafruit_blm_badge.build.board=BLM_BADGE_M0
+adafruit_blm_badge.build.core=arduino
+adafruit_blm_badge.build.extra_flags=-DCRYSTALLESS -DADAFRUIT_BLM_BADGE -D__SAMD21E18A__ -DARDUINO_SAMD_ZERO -DARM_MATH_CM0PLUS {build.usb_flags}
+adafruit_blm_badge.build.ldscript=linker_scripts/gcc/flash_with_bootloader.ld
+adafruit_blm_badge.build.openocdscript=openocd_scripts/=blm_badge.cfg
+adafruit_blm_badge.build.variant=blm_badge
+adafruit_blm_badge.build.variant_system_lib=
+adafruit_blm_badge.build.vid=0x239A
+adafruit_blm_badge.build.pid=0x80BF
+adafruit_blm_badge.bootloader.tool=openocd
+adafruit_blm_badge.bootloader.file=blmbadge/bootloader-blm_badge.bin
+adafruit_blm_badge.menu.opt.small=Small (-Os) (standard)
+adafruit_blm_badge.menu.opt.small.build.flags.optimize=-Os
+adafruit_blm_badge.menu.opt.fast=Fast (-O2)
+adafruit_blm_badge.menu.opt.fast.build.flags.optimize=-O2
+adafruit_blm_badge.menu.opt.faster=Faster (-O3)
+adafruit_blm_badge.menu.opt.faster.build.flags.optimize=-O3
+adafruit_blm_badge.menu.opt.fastest=Fastest (-Ofast)
+adafruit_blm_badge.menu.opt.fastest.build.flags.optimize=-Ofast
+adafruit_blm_badge.menu.opt.dragons=Here be dragons (-Ofast -funroll-loops)
+adafruit_blm_badge.menu.opt.dragons.build.flags.optimize=-Ofast -funroll-loops
+adafruit_blm_badge.menu.usbstack.arduino=Arduino
+adafruit_blm_badge.menu.usbstack.tinyusb=TinyUSB
+adafruit_blm_badge.menu.usbstack.tinyusb.build.flags.usbstack=-DUSE_TINYUSB
+adafruit_blm_badge.menu.debug.off=Off
+adafruit_blm_badge.menu.debug.on=On
+adafruit_blm_badge.menu.debug.on.build.flags.debug=-g
diff --git a/bootloaders/blmbadge/bootloader-blm_badge.bin b/bootloaders/blmbadge/bootloader-blm_badge.bin
new file mode 100644
index 000000000..2e30fc17f
Binary files /dev/null and b/bootloaders/blmbadge/bootloader-blm_badge.bin differ
diff --git a/bootloaders/circuitplayM0/bootloader-circuitplay_m0-v2.0.0-adafruit.5.bin b/bootloaders/circuitplayM0/bootloader-circuitplay_m0-v2.0.0-adafruit.5.bin
new file mode 100755
index 000000000..50ae4b0a8
Binary files /dev/null and b/bootloaders/circuitplayM0/bootloader-circuitplay_m0-v2.0.0-adafruit.5.bin differ
diff --git a/bootloaders/circuitplayM0/bootloader-circuitplay_m0-v2.0.0-adafruit.5.elf b/bootloaders/circuitplayM0/bootloader-circuitplay_m0-v2.0.0-adafruit.5.elf
new file mode 100755
index 000000000..05827e0dc
Binary files /dev/null and b/bootloaders/circuitplayM0/bootloader-circuitplay_m0-v2.0.0-adafruit.5.elf differ
diff --git a/bootloaders/circuitplay/circuitplay_m0_samd21g18_sam_ba.bin b/bootloaders/circuitplayM0/circuitplay_m0_samd21g18_sam_ba.bin
similarity index 100%
rename from bootloaders/circuitplay/circuitplay_m0_samd21g18_sam_ba.bin
rename to bootloaders/circuitplayM0/circuitplay_m0_samd21g18_sam_ba.bin
diff --git a/bootloaders/circuitplayM0/update-bootloader-circuitplay_m0-v2.0.0-adafruit.5.uf2 b/bootloaders/circuitplayM0/update-bootloader-circuitplay_m0-v2.0.0-adafruit.5.uf2
new file mode 100644
index 000000000..0652fa7f6
Binary files /dev/null and b/bootloaders/circuitplayM0/update-bootloader-circuitplay_m0-v2.0.0-adafruit.5.uf2 differ
diff --git a/bootloaders/feather/Makefile b/bootloaders/feather/Makefile
new file mode 100644
index 000000000..297c2098b
--- /dev/null
+++ b/bootloaders/feather/Makefile
@@ -0,0 +1,183 @@
+# Copyright (c) 2015 Atmel Corporation/Thibaut VIARD.  All right reserved.
+# Copyright (c) 2015 Arduino LLC.  All right reserved.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+# -----------------------------------------------------------------------------
+# Paths
+ifeq ($(OS),Windows_NT)
+
+  # Are we using mingw/msys/msys2/cygwin?
+  ifeq ($(TERM),xterm)
+		T=$(shell cygpath -u $(LOCALAPPDATA))
+    MODULE_PATH?=$(T)/Arduino15/packages/arduino
+    ARM_GCC_PATH?=$(MODULE_PATH)/tools/arm-none-eabi-gcc/4.8.3-2014q1/bin/arm-none-eabi-
+    RM=rm
+    SEP=/
+  else
+    MODULE_PATH?=$(LOCALAPPDATA)/Arduino15/packages/arduino
+    ARM_GCC_PATH?=$(MODULE_PATH)/tools/arm-none-eabi-gcc/4.8.3-2014q1/bin/arm-none-eabi-
+    RM=rm
+    SEP=\\
+  endif
+else
+    UNAME_S := $(shell uname -s)
+
+    ifeq ($(UNAME_S),Linux)
+			MODULE_PATH?=$(HOME)/.arduino15/packages/arduino
+			ARM_GCC_PATH?=$(MODULE_PATH)/tools/arm-none-eabi-gcc/4.8.3-2014q1/bin/arm-none-eabi-
+      RM=rm
+	    SEP=/
+    endif
+
+    ifeq ($(UNAME_S),Darwin)
+			MODULE_PATH?=$(HOME)/Library/Arduino15/packages/arduino/
+			ARM_GCC_PATH?=$(MODULE_PATH)/tools/arm-none-eabi-gcc/4.8.3-2014q1/bin/arm-none-eabi-
+      RM=rm
+	    SEP=/
+    endif
+endif
+
+BUILD_PATH=build
+
+# -----------------------------------------------------------------------------
+# Tools
+CC=$(ARM_GCC_PATH)gcc
+OBJCOPY=$(ARM_GCC_PATH)objcopy
+NM=$(ARM_GCC_PATH)nm
+SIZE=$(ARM_GCC_PATH)size
+
+# -----------------------------------------------------------------------------
+# Compiler options
+CFLAGS=-mthumb -mcpu=cortex-m0plus -Wall -c -std=gnu99 -ffunction-sections -fdata-sections -nostdlib -nostartfiles --param max-inline-insns-single=500
+ifdef DEBUG
+CFLAGS+=-g3 -O1 -DDEBUG=1
+else
+CFLAGS+=-Os -DDEBUG=0
+endif
+
+# Adafruit Feather Zero (0x239A 0x000B)
+#CFLAGS_EXTRA?=-D__SAMD21G18A__ -DUSB_PID_HIGH=0x00 -DUSB_PID_LOW=0x0B -DUSB_VID_LOW=0x9A -DUSB_VID_HIGH=0x23
+# Adafruit Feather SAMR (0x239A 0x0014)
+CFLAGS_EXTRA?=-D__SAMR21G18A__ -DUSB_PID_HIGH=0x00 -DUSB_PID_LOW=0x14 -DUSB_VID_LOW=0x9A -DUSB_VID_HIGH=0x23
+# Arduino Zero (PID == 0x004D)
+# CFLAGS_EXTRA?=-D__SAMD21G18A__ -DUSB_PID_HIGH=0x00 -DUSB_PID_LOW=0x4D -DUSB_VID_LOW=0x41 -DUSB_VID_HIGH=0x23
+# Genuino Zero (PID == 0x024D)
+# CFLAGS_EXTRA?=-D__SAMD21G18A__ -DUSB_PID_HIGH=0x02 -DUSB_PID_LOW=0x4D -DUSB_VID_LOW=0x41 -DUSB_VID_HIGH=0x23
+# Arduino MKR1000 (PID == 0x004E)
+# CFLAGS_EXTRA?=-D__SAMD21G18A__ -DUSB_PID_HIGH=0x00 -DUSB_PID_LOW=0x4E -DUSB_VID_LOW=0x41 -DUSB_VID_HIGH=0x23
+# Genuino MKR1000 (PID == 0x024E)
+# CFLAGS_EXTRA?=-D__SAMD21G18A__ -DUSB_PID_HIGH=0x02 -DUSB_PID_LOW=0x4E -DUSB_VID_LOW=0x41 -DUSB_VID_HIGH=0x23
+
+# samd or samr
+NAME=samr21_sam_ba
+
+INCLUDES=-I"$(MODULE_PATH)/tools/CMSIS/4.0.0-atmel/CMSIS/Include/" -I"$(MODULE_PATH)/tools/CMSIS/4.0.0-atmel/Device/ATMEL/"
+
+# -----------------------------------------------------------------------------
+# Linker options
+LDFLAGS=-mthumb -mcpu=cortex-m0plus -Wall -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--unresolved-symbols=report-all
+LDFLAGS+=-Wl,--warn-common -Wl,--warn-section-align -Wl,--warn-unresolved-symbols --specs=nano.specs --specs=nosys.specs
+
+# -----------------------------------------------------------------------------
+# Source files and objects
+SOURCES= \
+board_driver_led.c \
+board_driver_serial.c \
+board_driver_usb.c \
+board_init.c \
+board_startup.c \
+main.c \
+sam_ba_usb.c \
+sam_ba_cdc.c \
+sam_ba_monitor.c \
+sam_ba_serial.c
+
+OBJECTS=$(addprefix $(BUILD_PATH)/, $(SOURCES:.c=.o))
+DEPS=$(addprefix $(BUILD_PATH)/, $(SOURCES:.c=.d))
+
+ELF=$(NAME).elf
+BIN=$(NAME).bin
+HEX=$(NAME).hex
+
+ifneq "test$(AVRSTUDIO_EXE_PATH)" "test"
+AS_BUILD=copy_for_atmel_studio
+AS_CLEAN=clean_for_atmel_studio
+else
+AS_BUILD=
+AS_CLEAN=
+endif
+
+
+all: print_info $(SOURCES) $(BIN) $(HEX) $(AS_BUILD)
+
+$(ELF): Makefile $(BUILD_PATH) $(OBJECTS)
+	@echo ----------------------------------------------------------
+	@echo Creating ELF binary
+	"$(CC)" -L. -L$(BUILD_PATH) $(LDFLAGS) -Os -Wl,--gc-sections -save-temps -Tbootloader_samd21x18.ld -Wl,-Map,"$(BUILD_PATH)/$(NAME).map" -o "$(BUILD_PATH)/$(ELF)" -Wl,--start-group $(OBJECTS) -lm -Wl,--end-group
+	"$(NM)" "$(BUILD_PATH)/$(ELF)" >"$(BUILD_PATH)/$(NAME)_symbols.txt"
+	"$(SIZE)" --format=sysv -t -x $(BUILD_PATH)/$(ELF)
+
+$(BIN): $(ELF)
+	@echo ----------------------------------------------------------
+	@echo Creating flash binary
+	"$(OBJCOPY)" -O binary $(BUILD_PATH)/$< $@
+
+$(HEX): $(ELF)
+	@echo ----------------------------------------------------------
+	@echo Creating flash binary
+	"$(OBJCOPY)" -O ihex $(BUILD_PATH)/$< $@
+
+$(BUILD_PATH)/%.o: %.c
+	@echo ----------------------------------------------------------
+	@echo Compiling $< to $@
+	"$(CC)" $(CFLAGS) $(CFLAGS_EXTRA) $(INCLUDES) $< -o $@
+	@echo ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+$(BUILD_PATH):
+	@echo ----------------------------------------------------------
+	@echo Creating build folder
+	-mkdir $(BUILD_PATH)
+
+print_info:
+	@echo ----------------------------------------------------------
+	@echo Compiling bootloader using
+	@echo BASE PATH = $(MODULE_PATH)
+	@echo GCC  PATH = $(ARM_GCC_PATH)
+#	@echo OS        = $(OS)
+#	@echo SHELL     = $(SHELL)
+#	@echo TERM      = $(TERM)
+#	"$(CC)" -v
+#	env
+
+copy_for_atmel_studio: $(BIN) $(HEX)
+	@echo ----------------------------------------------------------
+	@echo Atmel Studio detected, copying ELF to project root for debug
+	cp $(BUILD_PATH)/$(ELF) .
+
+clean_for_atmel_studio:
+	@echo ----------------------------------------------------------
+	@echo Atmel Studio detected, cleaning ELF from project root
+	-$(RM) ./$(ELF)
+
+clean: $(AS_CLEAN)
+	@echo ----------------------------------------------------------
+	@echo Cleaning project
+	-$(RM) $(BIN)
+	-$(RM) $(HEX)
+	-$(RM) $(BUILD_PATH)/*.*
+	-rmdir $(BUILD_PATH)
+
+.phony: print_info $(BUILD_PATH)
diff --git a/bootloaders/feather/README.md b/bootloaders/feather/README.md
new file mode 100644
index 000000000..44f4e4e02
--- /dev/null
+++ b/bootloaders/feather/README.md
@@ -0,0 +1,75 @@
+# Arduino Zero Bootloader
+
+## 1- Prerequisites
+
+The project build is based on Makefile system.
+Makefile is present at project root and try to handle multi-platform cases.
+
+Multi-plaform GCC is provided by ARM here: https://launchpad.net/gcc-arm-embedded/+download
+
+Atmel Studio contains both make and ARM GCC toolchain. You don't need to install them in this specific use case.
+
+### Windows
+
+* Native command line
+Make binary can be obtained here: http://gnuwin32.sourceforge.net/packages/make.htm
+
+* Cygwin/MSys/MSys2/Babun/etc...
+It is available natively in all distributions.
+
+* Atmel Studio
+An Atmel Studio **7** Makefile-based project is present at project root, just open samd21_sam_ba.atsln file in AS7.
+
+### Linux
+
+Make is usually available by default.
+
+### OS X
+
+Make is available through XCode package.
+
+
+## 2- Selecting available SAM-BA interfaces
+
+By default both USB and UART are made available, but this parameter can be modified in sam_ba_monitor.h, line 31:
+
+Set the define SAM_BA_INTERFACE to
+* SAM_BA_UART_ONLY for only UART interface
+* SAM_BA_USBCDC_ONLY for only USB CDC interface
+* SAM_BA_BOTH_INTERFACES for enabling both the interfaces
+
+## 3- Behaviour
+
+This bootloader implements the double-tap on Reset button.
+By quickly pressing this button two times, the board will reset and stay in bootloader, waiting for communication on either USB or USART.
+
+The USB port in use is the USB Native port, close to the Reset button.
+The USART in use is the one available on pins D0/D1, labelled respectively RX/TX. Communication parameters are a baudrate at 115200, 8bits of data, no parity and 1 stop bit (8N1).
+
+## 4- Description
+
+**Pinmap**
+
+The following pins are used by the program :
+PA25 : input/output (USB DP)
+PA24 : input/output (USB DM)
+PA11 : input (USART RX)
+PA10 : output (USART TX)
+
+The application board shall avoid driving the PA25, PA24, PB23 and PB22 signals while the boot program is running (after a POR for example).
+
+**Clock system**
+
+CPU runs at 48MHz from Generic Clock Generator 0 on DFLL48M.
+
+Generic Clock Generator 1 is using external 32kHz oscillator and is the source of DFLL48M.
+
+USB and USART are using Generic Clock Generator 0 also.
+
+**Memory Mapping**
+
+Bootloader code will be located at 0x0 and executed before any applicative code.
+
+Applications compiled to be executed along with the bootloader will start at 0x2000 (see linker script bootloader_samd21x18.ld).
+
+Before jumping to the application, the bootloader changes the VTOR register to use the interrupt vectors of the application @0x2000.<- not required as application code is taking care of this.
diff --git a/bootloaders/feather/board_definitions.h b/bootloaders/feather/board_definitions.h
new file mode 100644
index 000000000..458e1b0a7
--- /dev/null
+++ b/bootloaders/feather/board_definitions.h
@@ -0,0 +1,72 @@
+/*
+  Copyright (c) 2015 Arduino LLC.  All right reserved.
+  Copyright (c) 2015 Atmel Corporation/Thibaut VIARD.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _BOARD_DEFINITIONS_H_
+#define _BOARD_DEFINITIONS_H_
+
+/*
+ * If BOOT_DOUBLE_TAP_ADDRESS is defined the bootloader is started by
+ * quickly tapping two times on the reset button.
+ * BOOT_DOUBLE_TAP_ADDRESS must point to a free SRAM cell that must not
+ * be touched from the loaded application.
+ */
+#define BOOT_DOUBLE_TAP_ADDRESS           (0x20007FFCul)
+#define BOOT_DOUBLE_TAP_DATA              (*((volatile uint32_t *) BOOT_DOUBLE_TAP_ADDRESS))
+
+/*
+ * If BOOT_LOAD_PIN is defined the bootloader is started if the selected
+ * pin is tied LOW.
+ */
+//#define BOOT_LOAD_PIN                     PIN_PA21 // Pin 7
+//#define BOOT_LOAD_PIN                     PIN_PA15 // Pin 5
+#define BOOT_PIN_MASK                     (1U << (BOOT_LOAD_PIN & 0x1f))
+
+#define CPU_FREQUENCY                     (48000000ul)
+
+#define BOOT_USART_MODULE                 SERCOM0
+#define BOOT_USART_BUS_CLOCK_INDEX        PM_APBCMASK_SERCOM0
+#define BOOT_USART_PER_CLOCK_INDEX        GCLK_ID_SERCOM0_CORE
+#define BOOT_USART_PAD_SETTINGS           UART_RX_PAD3_TX_PAD2
+#define BOOT_USART_PAD3                   PINMUX_PA11C_SERCOM0_PAD3
+#define BOOT_USART_PAD2                   PINMUX_PA10C_SERCOM0_PAD2
+#define BOOT_USART_PAD1                   PINMUX_UNUSED
+#define BOOT_USART_PAD0                   PINMUX_UNUSED
+
+/* Frequency of the board main oscillator */
+#define VARIANT_MAINOSC	                  (32768ul)
+
+/* Master clock frequency */
+#define VARIANT_MCK			                  CPU_FREQUENCY
+
+#define NVM_SW_CALIB_DFLL48M_COARSE_VAL   (58)
+#define NVM_SW_CALIB_DFLL48M_FINE_VAL     (64)
+
+/*
+ * LEDs definitions
+ */
+#define BOARD_LED_PORT                    (0)
+#define BOARD_LED_PIN                     (17)
+
+#define BOARD_LEDRX_PORT                  (1)
+#define BOARD_LEDRX_PIN                   (3)
+
+#define BOARD_LEDTX_PORT                  (0)
+#define BOARD_LEDTX_PIN                   (27)
+
+#endif // _BOARD_DEFINITIONS_H_
diff --git a/bootloaders/feather/board_driver_led.c b/bootloaders/feather/board_driver_led.c
new file mode 100644
index 000000000..1a2430aff
--- /dev/null
+++ b/bootloaders/feather/board_driver_led.c
@@ -0,0 +1,22 @@
+/*
+  Copyright (c) 2015 Arduino LLC.  All right reserved.
+  Copyright (c) 2015 Atmel Corporation/Thibaut VIARD.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "board_driver_led.h"
+
+
diff --git a/bootloaders/feather/board_driver_led.h b/bootloaders/feather/board_driver_led.h
new file mode 100644
index 000000000..6f1fd7580
--- /dev/null
+++ b/bootloaders/feather/board_driver_led.h
@@ -0,0 +1,41 @@
+/*
+  Copyright (c) 2015 Arduino LLC.  All right reserved.
+  Copyright (c) 2015 Atmel Corporation/Thibaut VIARD.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _BOARD_DRIVER_LED_
+#define _BOARD_DRIVER_LED_
+
+#include <sam.h>
+#include "board_definitions.h"
+
+inline void LED_init(void) { PORT->Group[BOARD_LED_PORT].DIRSET.reg = (1<<BOARD_LED_PIN); }
+inline void LED_on(void) { PORT->Group[BOARD_LED_PORT].OUTSET.reg = (1<<BOARD_LED_PIN); }
+inline void LED_off(void) { PORT->Group[BOARD_LED_PORT].OUTCLR.reg = (1<<BOARD_LED_PIN); }
+inline void LED_toggle(void) { PORT->Group[BOARD_LED_PORT].OUTTGL.reg = (1<<BOARD_LED_PIN); }
+
+inline void LEDRX_init(void) { PORT->Group[BOARD_LEDRX_PORT].DIRSET.reg = (1<<BOARD_LEDRX_PIN); }
+inline void LEDRX_on(void) { PORT->Group[BOARD_LEDRX_PORT].OUTSET.reg = (1<<BOARD_LEDRX_PIN); }
+inline void LEDRX_off(void) { PORT->Group[BOARD_LEDRX_PORT].OUTCLR.reg = (1<<BOARD_LEDRX_PIN); }
+inline void LEDRX_toggle(void) { PORT->Group[BOARD_LEDRX_PORT].OUTTGL.reg = (1<<BOARD_LEDRX_PIN); }
+
+inline void LEDTX_init(void) { PORT->Group[BOARD_LEDTX_PORT].DIRSET.reg = (1<<BOARD_LEDTX_PIN); }
+inline void LEDTX_on(void) { PORT->Group[BOARD_LEDTX_PORT].OUTSET.reg = (1<<BOARD_LEDTX_PIN); }
+inline void LEDTX_off(void) { PORT->Group[BOARD_LEDTX_PORT].OUTCLR.reg = (1<<BOARD_LEDTX_PIN); }
+inline void LEDTX_toggle(void) { PORT->Group[BOARD_LEDTX_PORT].OUTTGL.reg = (1<<BOARD_LEDTX_PIN); }
+
+#endif // _BOARD_DRIVER_LED_
diff --git a/bootloaders/feather/board_driver_serial.c b/bootloaders/feather/board_driver_serial.c
new file mode 100644
index 000000000..7a0f57581
--- /dev/null
+++ b/bootloaders/feather/board_driver_serial.c
@@ -0,0 +1,104 @@
+/*
+  Copyright (c) 2015 Arduino LLC.  All right reserved.
+  Copyright (c) 2015 Atmel Corporation/Thibaut VIARD.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "board_driver_serial.h"
+
+bool uart_drv_error_flag = false;
+
+void uart_basic_init(Sercom *sercom, uint16_t baud_val, enum uart_pad_settings pad_conf)
+{
+	/* Wait for synchronization */
+	while(sercom->USART.SYNCBUSY.bit.ENABLE);
+	/* Disable the SERCOM UART module */
+	sercom->USART.CTRLA.bit.ENABLE = 0;
+	/* Wait for synchronization */
+	while(sercom->USART.SYNCBUSY.bit.SWRST);
+	/* Perform a software reset */
+	sercom->USART.CTRLA.bit.SWRST = 1;
+	/* Wait for synchronization */
+	while(sercom->USART.CTRLA.bit.SWRST);
+	/* Wait for synchronization */
+	while(sercom->USART.SYNCBUSY.bit.SWRST || sercom->USART.SYNCBUSY.bit.ENABLE);
+	/* Update the UART pad settings, mode and data order settings */
+	sercom->USART.CTRLA.reg = pad_conf | SERCOM_USART_CTRLA_MODE(1) | SERCOM_USART_CTRLA_DORD;
+	/* Wait for synchronization */
+	while(sercom->USART.SYNCBUSY.bit.CTRLB);
+	/* Enable transmit and receive and set data size to 8 bits */
+	sercom->USART.CTRLB.reg = SERCOM_USART_CTRLB_RXEN | SERCOM_USART_CTRLB_TXEN | SERCOM_USART_CTRLB_CHSIZE(0);
+	/* Load the baud value */
+	sercom->USART.BAUD.reg = baud_val;
+	/* Wait for synchronization */
+	while(sercom->USART.SYNCBUSY.bit.ENABLE);
+	/* Enable SERCOM UART */
+	sercom->USART.CTRLA.bit.ENABLE = 1;
+}
+
+void uart_disable(Sercom *sercom)
+{
+	/* Wait for synchronization */
+	while(sercom->USART.SYNCBUSY.bit.ENABLE);
+	/* Disable SERCOM UART */
+	sercom->USART.CTRLA.bit.ENABLE = 0;
+}
+
+void uart_write_byte(Sercom *sercom, uint8_t data)
+{
+	/* Wait for Data Register Empty flag */
+	while(!sercom->USART.INTFLAG.bit.DRE);
+	/* Write the data to DATA register */
+	sercom->USART.DATA.reg = (uint16_t)data;
+}
+
+uint8_t uart_read_byte(Sercom *sercom)
+{
+	/* Wait for Receive Complete flag */
+	while(!sercom->USART.INTFLAG.bit.RXC);
+	/* Check for errors */
+	if (sercom->USART.STATUS.bit.PERR || sercom->USART.STATUS.bit.FERR || sercom->USART.STATUS.bit.BUFOVF)
+		/* Set the error flag */
+		uart_drv_error_flag = true;
+	/* Return the read data */
+	return((uint8_t)sercom->USART.DATA.reg);
+}
+
+void uart_write_buffer_polled(Sercom *sercom, uint8_t *ptr, uint16_t length)
+{
+	/* Do the following for specified length */
+	do {
+		/* Wait for Data Register Empty flag */
+		while(!sercom->USART.INTFLAG.bit.DRE);
+		/* Send data from the buffer */
+		sercom->USART.DATA.reg = (uint16_t)*ptr++;
+	} while (length--);
+}
+
+void uart_read_buffer_polled(Sercom *sercom, uint8_t *ptr, uint16_t length)
+{
+	/* Do the following for specified length */
+	do {
+		/* Wait for Receive Complete flag */
+		while(!sercom->USART.INTFLAG.bit.RXC);
+		/* Check for errors */
+		if (sercom->USART.STATUS.bit.PERR || sercom->USART.STATUS.bit.FERR || sercom->USART.STATUS.bit.BUFOVF)
+			/* Set the error flag */
+			uart_drv_error_flag = true;
+		/* Store the read data to the buffer */
+		*ptr++ = (uint8_t)sercom->USART.DATA.reg;
+	} while (length--);
+}
diff --git a/bootloaders/feather/board_driver_serial.h b/bootloaders/feather/board_driver_serial.h
new file mode 100644
index 000000000..c752d977d
--- /dev/null
+++ b/bootloaders/feather/board_driver_serial.h
@@ -0,0 +1,90 @@
+/*
+  Copyright (c) 2015 Arduino LLC.  All right reserved.
+  Copyright (c) 2015 Atmel Corporation/Thibaut VIARD.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef UART_DRIVER_H
+#define UART_DRIVER_H
+
+#include <stdio.h>
+#include <stdbool.h>
+#include <sam.h>
+
+#define PINMUX_UNUSED          0xFFFFFFFF
+#define GCLK_ID_SERCOM0_CORE   0x14
+
+/* SERCOM UART available pad settings */
+enum uart_pad_settings {
+	UART_RX_PAD0_TX_PAD2 = SERCOM_USART_CTRLA_RXPO(0) | SERCOM_USART_CTRLA_TXPO(1),
+	UART_RX_PAD1_TX_PAD2 = SERCOM_USART_CTRLA_RXPO(1) | SERCOM_USART_CTRLA_TXPO(1),
+	UART_RX_PAD2_TX_PAD0 = SERCOM_USART_CTRLA_RXPO(2),
+	UART_RX_PAD3_TX_PAD0 = SERCOM_USART_CTRLA_RXPO(3),
+	UART_RX_PAD1_TX_PAD0 = SERCOM_USART_CTRLA_RXPO(1),
+	UART_RX_PAD3_TX_PAD2 = SERCOM_USART_CTRLA_RXPO(3) | SERCOM_USART_CTRLA_TXPO(1),
+};
+
+/**
+ * \brief Initializes the UART
+ *
+ * \param Pointer to SERCOM instance
+ * \param Baud value corresponding to the desired baudrate
+ * \param SERCOM pad settings
+ */
+void uart_basic_init(Sercom *sercom, uint16_t baud_val, enum uart_pad_settings pad_conf);
+
+/**
+ * \brief Disables UART interface
+ *
+ * \param Pointer to SERCOM instance
+ */
+void uart_disable(Sercom *sercom);
+
+/**
+ * \brief Sends a single byte through UART interface
+ *
+ * \param Pointer to SERCOM instance
+ * \param Data to send
+ */
+void uart_write_byte(Sercom *sercom, uint8_t data);
+
+/**
+ * \brief Reads a single character from UART interface
+ *
+ * \param Pointer to SERCOM instance
+ * \return Data byte read
+ */
+uint8_t uart_read_byte(Sercom *sercom);
+
+/**
+ * \brief Sends buffer on UART interface
+ *
+ * \param Pointer to SERCOM instance
+ * \param Pointer to data to send
+ * \param Number of bytes to send
+ */
+void uart_write_buffer_polled(Sercom *sercom, uint8_t *ptr, uint16_t length);
+
+/**
+ * \brief Reads data on UART interface
+ *
+ * \param Pointer to SERCOM instance
+ * \param Pointer to store read data
+ * \param Number of bytes to read
+ */
+void uart_read_buffer_polled(Sercom *sercom, uint8_t *ptr, uint16_t length);
+
+#endif
diff --git a/bootloaders/feather/board_driver_usb.c b/bootloaders/feather/board_driver_usb.c
new file mode 100644
index 000000000..ca1e62a95
--- /dev/null
+++ b/bootloaders/feather/board_driver_usb.c
@@ -0,0 +1,402 @@
+/*
+  Copyright (c) 2015 Arduino LLC.  All right reserved.
+  Copyright (c) 2015 Atmel Corporation/Thibaut VIARD.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include <string.h>
+#include "board_driver_usb.h"
+#include "sam_ba_usb.h"
+#include "sam_ba_cdc.h"
+
+#define NVM_USB_PAD_TRANSN_POS            (45)
+#define NVM_USB_PAD_TRANSN_SIZE           (5)
+#define NVM_USB_PAD_TRANSP_POS            (50)
+#define NVM_USB_PAD_TRANSP_SIZE           (5)
+#define NVM_USB_PAD_TRIM_POS              (55)
+#define NVM_USB_PAD_TRIM_SIZE             (3)
+
+__attribute__((__aligned__(4))) UsbDeviceDescriptor usb_endpoint_table[MAX_EP]; // Initialized to zero in USB_Init
+__attribute__((__aligned__(4))) uint8_t udd_ep_out_cache_buffer[2][64]; //1 for CTRL, 1 for BULK
+__attribute__((__aligned__(4))) uint8_t udd_ep_in_cache_buffer[2][64]; //1 for CTRL, 1 for BULK
+
+static volatile bool read_job = false;
+
+/*----------------------------------------------------------------------------
+ * \brief
+ */
+P_USB_CDC USB_Open(P_USB_CDC pCdc, Usb *pUsb)
+{
+  pCdc->pUsb = pUsb;
+  pCdc->currentConfiguration = 0;
+  pCdc->currentConnection    = 0;
+  pCdc->IsConfigured = USB_IsConfigured;
+//  pCdc->Write        = USB_Write;
+//  pCdc->Read         = USB_Read;
+
+  pCdc->pUsb->HOST.CTRLA.bit.ENABLE = true;
+
+  return pCdc;
+}
+
+/*----------------------------------------------------------------------------
+ * \brief Initializes USB
+ */
+void USB_Init(void)
+{
+  uint32_t pad_transn, pad_transp, pad_trim;
+
+  /* Enable USB clock */
+  PM->APBBMASK.reg |= PM_APBBMASK_USB;
+
+  /* Set up the USB DP/DN pins */
+  PORT->Group[0].PINCFG[PIN_PA24G_USB_DM].bit.PMUXEN = 1;
+  PORT->Group[0].PMUX[PIN_PA24G_USB_DM/2].reg &= ~(0xF << (4 * (PIN_PA24G_USB_DM & 0x01u)));
+  PORT->Group[0].PMUX[PIN_PA24G_USB_DM/2].reg |= MUX_PA24G_USB_DM << (4 * (PIN_PA24G_USB_DM & 0x01u));
+  PORT->Group[0].PINCFG[PIN_PA25G_USB_DP].bit.PMUXEN = 1;
+  PORT->Group[0].PMUX[PIN_PA25G_USB_DP/2].reg &= ~(0xF << (4 * (PIN_PA25G_USB_DP & 0x01u)));
+  PORT->Group[0].PMUX[PIN_PA25G_USB_DP/2].reg |= MUX_PA25G_USB_DP << (4 * (PIN_PA25G_USB_DP & 0x01u));
+
+  /* ----------------------------------------------------------------------------------------------
+   * Put Generic Clock Generator 0 as source for Generic Clock Multiplexer 6 (USB reference)
+   */
+  GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID( 6 ) | // Generic Clock Multiplexer 6
+              GCLK_CLKCTRL_GEN_GCLK0 | // Generic Clock Generator 0 is source
+              GCLK_CLKCTRL_CLKEN ;
+
+  while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY )
+  {
+    /* Wait for synchronization */
+  }
+
+  /* Reset */
+  USB->DEVICE.CTRLA.bit.SWRST = 1;
+  while (USB->DEVICE.SYNCBUSY.bit.SWRST)
+  {
+    /* Sync wait */
+  }
+
+  /* Load Pad Calibration */
+  pad_transn =( *((uint32_t *)(NVMCTRL_OTP4)
+      + (NVM_USB_PAD_TRANSN_POS / 32))
+    >> (NVM_USB_PAD_TRANSN_POS % 32))
+    & ((1 << NVM_USB_PAD_TRANSN_SIZE) - 1);
+
+  if (pad_transn == 0x1F)
+  {
+    pad_transn = 5;
+  }
+
+  USB->HOST.PADCAL.bit.TRANSN = pad_transn;
+
+  pad_transp =( *((uint32_t *)(NVMCTRL_OTP4)
+      + (NVM_USB_PAD_TRANSP_POS / 32))
+      >> (NVM_USB_PAD_TRANSP_POS % 32))
+      & ((1 << NVM_USB_PAD_TRANSP_SIZE) - 1);
+
+  if (pad_transp == 0x1F)
+  {
+    pad_transp = 29;
+  }
+
+  USB->HOST.PADCAL.bit.TRANSP = pad_transp;
+  pad_trim =( *((uint32_t *)(NVMCTRL_OTP4)
+      + (NVM_USB_PAD_TRIM_POS / 32))
+      >> (NVM_USB_PAD_TRIM_POS % 32))
+      & ((1 << NVM_USB_PAD_TRIM_SIZE) - 1);
+
+  if (pad_trim == 0x7)
+  {
+    pad_trim = 3;
+  }
+
+  USB->HOST.PADCAL.bit.TRIM = pad_trim;
+
+  /* Set the configuration */
+  /* Set mode to Device mode */
+  USB->HOST.CTRLA.bit.MODE = 0;
+  /* Enable Run in Standby */
+  USB->HOST.CTRLA.bit.RUNSTDBY = true;
+  /* Set the descriptor address */
+  USB->HOST.DESCADD.reg = (uint32_t)(&usb_endpoint_table[0]);
+  /* Set speed configuration to Full speed */
+  USB->DEVICE.CTRLB.bit.SPDCONF = USB_DEVICE_CTRLB_SPDCONF_FS_Val;
+  /* Attach to the USB host */
+  USB->DEVICE.CTRLB.reg &= ~USB_DEVICE_CTRLB_DETACH;
+
+  /* Initialize endpoint table RAM location to a known value 0 */
+  memset((uint8_t *)(&usb_endpoint_table[0]), 0, sizeof(usb_endpoint_table));
+}
+
+uint32_t USB_Write(Usb *pUsb, const char *pData, uint32_t length, uint8_t ep_num)
+{
+  uint32_t data_address;
+  uint8_t buf_index;
+
+  /* Set buffer index */
+  buf_index = (ep_num == 0) ? 0 : 1;
+
+  /* Check for requirement for multi-packet or auto zlp */
+  if (length >= (1 << (usb_endpoint_table[ep_num].DeviceDescBank[1].PCKSIZE.bit.SIZE + 3)))
+  {
+    /* Update the EP data address */
+    data_address = (uint32_t) pData;
+    /* Enable auto zlp */
+    usb_endpoint_table[ep_num].DeviceDescBank[1].PCKSIZE.bit.AUTO_ZLP = true;
+  }
+  else
+  {
+    /* Copy to local buffer */
+    memcpy(udd_ep_in_cache_buffer[buf_index], pData, length);
+    /* Update the EP data address */
+    data_address = (uint32_t) &udd_ep_in_cache_buffer[buf_index];
+  }
+
+  /* Set the buffer address for ep data */
+  usb_endpoint_table[ep_num].DeviceDescBank[1].ADDR.reg = data_address;
+  /* Set the byte count as zero */
+  usb_endpoint_table[ep_num].DeviceDescBank[1].PCKSIZE.bit.BYTE_COUNT = length;
+  /* Set the multi packet size as zero for multi-packet transfers where length > ep size */
+  usb_endpoint_table[ep_num].DeviceDescBank[1].PCKSIZE.bit.MULTI_PACKET_SIZE = 0;
+  /* Clear the transfer complete flag  */
+
+#ifdef __SAMR21G18A__
+  pUsb->DEVICE.DeviceEndpoint[ep_num].EPINTFLAG.bit.TRCPT1 = true;
+#else
+  pUsb->DEVICE.DeviceEndpoint[ep_num].EPINTFLAG.bit.TRCPT |= (1<<1);
+#endif
+
+  /* Set the bank as ready */
+  pUsb->DEVICE.DeviceEndpoint[ep_num].EPSTATUSSET.bit.BK1RDY = true;
+
+  /* Wait for transfer to complete */
+#ifdef __SAMR21G18A__
+  while ( (pUsb->DEVICE.DeviceEndpoint[ep_num].EPINTFLAG.bit.TRCPT1) == 0 );
+#else
+  while ( (pUsb->DEVICE.DeviceEndpoint[ep_num].EPINTFLAG.bit.TRCPT & (1<<1)) == 0 );
+#endif
+
+  return length;
+}
+
+/*----------------------------------------------------------------------------
+ * \brief Read available data from Endpoint OUT
+ */
+uint32_t USB_Read(Usb *pUsb, char *pData, uint32_t length)
+{
+  uint32_t packetSize = 0;
+
+  if (!read_job)
+  {
+    /* Set the buffer address for ep data */
+    usb_endpoint_table[USB_EP_OUT].DeviceDescBank[0].ADDR.reg = (uint32_t)&udd_ep_out_cache_buffer[USB_EP_OUT-1];
+    /* Set the byte count as zero */
+    usb_endpoint_table[USB_EP_OUT].DeviceDescBank[0].PCKSIZE.bit.BYTE_COUNT = 0;
+    /* Set the byte count as zero */
+    usb_endpoint_table[USB_EP_OUT].DeviceDescBank[0].PCKSIZE.bit.MULTI_PACKET_SIZE = 0;
+    /* Start the reception by clearing the bank 0 ready bit */
+    pUsb->DEVICE.DeviceEndpoint[USB_EP_OUT].EPSTATUSCLR.bit.BK0RDY = true;
+    /* set the user flag */
+    read_job = true;
+  }
+
+  /* Check for Transfer Complete 0 flag */
+#ifdef __SAMR21G18A__
+  if ( pUsb->DEVICE.DeviceEndpoint[USB_EP_OUT].EPINTFLAG.bit.TRCPT0 )
+#else
+  if ( pUsb->DEVICE.DeviceEndpoint[USB_EP_OUT].EPINTFLAG.bit.TRCPT & (1<<0) )
+#endif
+  {
+    /* Set packet size */
+    packetSize = SAM_BA_MIN(usb_endpoint_table[USB_EP_OUT].DeviceDescBank[0].PCKSIZE.bit.BYTE_COUNT, length);
+    /* Copy read data to user buffer */
+    memcpy(pData, udd_ep_out_cache_buffer[USB_EP_OUT-1], packetSize);
+    /* Clear the Transfer Complete 0 flag */
+#ifdef __SAMR21G18A__
+    pUsb->DEVICE.DeviceEndpoint[USB_EP_OUT].EPINTFLAG.bit.TRCPT0 = true;
+#else
+    pUsb->DEVICE.DeviceEndpoint[USB_EP_OUT].EPINTFLAG.bit.TRCPT |= (1 << 0);
+#endif
+    /* Clear the user flag */
+    read_job = false;
+  }
+
+  return packetSize;
+}
+
+uint32_t USB_Read_blocking(Usb *pUsb, char *pData, uint32_t length)
+{
+  if (read_job)
+  {
+    /* Stop the reception by setting the bank 0 ready bit */
+    pUsb->DEVICE.DeviceEndpoint[USB_EP_OUT].EPSTATUSSET.bit.BK0RDY = true;
+    /* Clear the user flag */
+    read_job = false;
+  }
+
+  /* Set the buffer address for ep data */
+  usb_endpoint_table[USB_EP_OUT].DeviceDescBank[0].ADDR.reg = ((uint32_t)pData);
+  /* Set the byte count as zero */
+  usb_endpoint_table[USB_EP_OUT].DeviceDescBank[0].PCKSIZE.bit.BYTE_COUNT = 0;
+  /* Set the multi packet size as zero for multi-packet transfers where length > ep size */
+  usb_endpoint_table[USB_EP_OUT].DeviceDescBank[0].PCKSIZE.bit.MULTI_PACKET_SIZE = length;
+  /* Clear the bank 0 ready flag */
+  pUsb->DEVICE.DeviceEndpoint[USB_EP_OUT].EPSTATUSCLR.bit.BK0RDY = true;
+  /* Wait for transfer to complete */
+
+#ifdef __SAMR21G18A__
+  while (!( pUsb->DEVICE.DeviceEndpoint[USB_EP_OUT].EPINTFLAG.bit.TRCPT0 ));
+  /* Clear Transfer complete 0 flag */
+  pUsb->DEVICE.DeviceEndpoint[USB_EP_OUT].EPINTFLAG.bit.TRCPT0 = true;
+#else
+  while (!( pUsb->DEVICE.DeviceEndpoint[USB_EP_OUT].EPINTFLAG.bit.TRCPT & (1<<0) ));
+  /* Clear Transfer complete 0 flag */
+  pUsb->DEVICE.DeviceEndpoint[USB_EP_OUT].EPINTFLAG.bit.TRCPT |= (1 << 0);
+#endif
+
+  return length;
+}
+
+/*----------------------------------------------------------------------------
+ * \brief Test if the device is configured and handle enumeration
+ */
+uint8_t USB_IsConfigured(P_USB_CDC pCdc)
+{
+  Usb *pUsb = pCdc->pUsb;
+
+  /* Check for End of Reset flag */
+  if (pUsb->DEVICE.INTFLAG.reg & USB_DEVICE_INTFLAG_EORST)
+  {
+    /* Clear the flag */
+    pUsb->DEVICE.INTFLAG.bit.EORST = true;
+    /* Set Device address as 0 */
+    pUsb->DEVICE.DADD.reg = USB_DEVICE_DADD_ADDEN | 0;
+    /* Configure endpoint 0 */
+    /* Configure Endpoint 0 for Control IN and Control OUT */
+    pUsb->DEVICE.DeviceEndpoint[0].EPCFG.reg = USB_DEVICE_EPCFG_EPTYPE0(1) | USB_DEVICE_EPCFG_EPTYPE1(1);
+    pUsb->DEVICE.DeviceEndpoint[0].EPSTATUSSET.reg = USB_DEVICE_EPSTATUSSET_BK0RDY;
+    pUsb->DEVICE.DeviceEndpoint[0].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_BK1RDY;
+    /* Configure control OUT Packet size to 64 bytes */
+    usb_endpoint_table[0].DeviceDescBank[0].PCKSIZE.bit.SIZE = 3;
+    /* Configure control IN Packet size to 64 bytes */
+    usb_endpoint_table[0].DeviceDescBank[1].PCKSIZE.bit.SIZE = 3;
+    /* Configure the data buffer address for control OUT */
+    usb_endpoint_table[0].DeviceDescBank[0].ADDR.reg = (uint32_t)&udd_ep_out_cache_buffer[0];
+    /* Configure the data buffer address for control IN */
+    usb_endpoint_table[0].DeviceDescBank[1].ADDR.reg = (uint32_t)&udd_ep_in_cache_buffer[0];
+    /* Set Multipacket size to 8 for control OUT and byte count to 0*/
+    usb_endpoint_table[0].DeviceDescBank[0].PCKSIZE.bit.MULTI_PACKET_SIZE = 8;
+    usb_endpoint_table[0].DeviceDescBank[0].PCKSIZE.bit.BYTE_COUNT = 0;
+    pUsb->DEVICE.DeviceEndpoint[0].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_BK0RDY;
+
+    // Reset current configuration value to 0
+    pCdc->currentConfiguration = 0;
+  }
+  else
+  {
+    if (pUsb->DEVICE.DeviceEndpoint[0].EPINTFLAG.reg & USB_DEVICE_EPINTFLAG_RXSTP)
+    {
+      sam_ba_usb_CDC_Enumerate(pCdc);
+    }
+  }
+
+  return pCdc->currentConfiguration;
+}
+
+/*----------------------------------------------------------------------------
+ * \brief Stall the control endpoint
+ */
+void USB_SendStall(Usb *pUsb, bool direction_in)
+{
+  /* Check the direction */
+  if (direction_in)
+  {
+    /* Set STALL request on IN direction */
+#ifdef __SAMR21G18A__
+    pUsb->DEVICE.DeviceEndpoint[0].EPSTATUSSET.reg = USB_DEVICE_EPSTATUSSET_STALLRQ1;
+#else
+    pUsb->DEVICE.DeviceEndpoint[0].EPSTATUSSET.bit.STALLRQ = (1<<1);
+#endif
+  }
+  else
+  {
+    /* Set STALL request on OUT direction */
+#ifdef __SAMR21G18A__
+    pUsb->DEVICE.DeviceEndpoint[0].EPSTATUSSET.reg = USB_DEVICE_EPSTATUSSET_STALLRQ0;
+#else
+    pUsb->DEVICE.DeviceEndpoint[0].EPSTATUSSET.bit.STALLRQ = (1<<0);
+#endif
+  }
+}
+
+/*----------------------------------------------------------------------------
+ * \brief Send zero length packet through the control endpoint
+ */
+void USB_SendZlp(Usb *pUsb)
+{
+  /* Set the byte count as zero */
+  usb_endpoint_table[0].DeviceDescBank[1].PCKSIZE.bit.BYTE_COUNT = 0;
+  /* Clear the transfer complete flag  */
+#ifdef __SAMR21G18A__
+  pUsb->DEVICE.DeviceEndpoint[0].EPINTFLAG.bit.TRCPT1 = true;
+#else
+  pUsb->DEVICE.DeviceEndpoint[0].EPINTFLAG.bit.TRCPT |= (1 << 1);
+#endif
+  /* Set the bank as ready */
+  pUsb->DEVICE.DeviceEndpoint[0].EPSTATUSSET.bit.BK1RDY = true;
+  /* Wait for transfer to complete */
+#ifdef __SAMR21G18A__
+  while (!( pUsb->DEVICE.DeviceEndpoint[0].EPINTFLAG.bit.TRCPT1 ));
+#else
+  while (!( pUsb->DEVICE.DeviceEndpoint[0].EPINTFLAG.bit.TRCPT & (1<<1) ));
+#endif
+}
+
+/*----------------------------------------------------------------------------
+ * \brief Set USB device address obtained from host
+ */
+void USB_SetAddress(Usb *pUsb, uint16_t wValue)
+{
+  pUsb->DEVICE.DADD.reg = USB_DEVICE_DADD_ADDEN | wValue;
+}
+
+/*----------------------------------------------------------------------------
+ * \brief Configure USB device
+ */
+void USB_Configure(Usb *pUsb)
+{
+  /* Configure BULK OUT endpoint for CDC Data interface*/
+  pUsb->DEVICE.DeviceEndpoint[USB_EP_OUT].EPCFG.reg = USB_DEVICE_EPCFG_EPTYPE0(3);
+  /* Set maximum packet size as 64 bytes */
+  usb_endpoint_table[USB_EP_OUT].DeviceDescBank[0].PCKSIZE.bit.SIZE = 3;
+  pUsb->DEVICE.DeviceEndpoint[USB_EP_OUT].EPSTATUSSET.reg = USB_DEVICE_EPSTATUSSET_BK0RDY;
+  /* Configure the data buffer */
+  usb_endpoint_table[USB_EP_OUT].DeviceDescBank[0].ADDR.reg = (uint32_t)&udd_ep_out_cache_buffer[1];
+
+  /* Configure BULK IN endpoint for CDC Data interface */
+  pUsb->DEVICE.DeviceEndpoint[USB_EP_IN].EPCFG.reg = USB_DEVICE_EPCFG_EPTYPE1(3);
+  /* Set maximum packet size as 64 bytes */
+  usb_endpoint_table[USB_EP_IN].DeviceDescBank[1].PCKSIZE.bit.SIZE = 3;
+  pUsb->DEVICE.DeviceEndpoint[USB_EP_IN].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_BK1RDY;
+  /* Configure the data buffer */
+  usb_endpoint_table[USB_EP_IN].DeviceDescBank[1].ADDR.reg = (uint32_t)&udd_ep_in_cache_buffer[1];
+
+  /* Configure INTERRUPT IN endpoint for CDC COMM interface*/
+  pUsb->DEVICE.DeviceEndpoint[USB_EP_COMM].EPCFG.reg = USB_DEVICE_EPCFG_EPTYPE1(4);
+  /* Set maximum packet size as 64 bytes */
+  usb_endpoint_table[USB_EP_COMM].DeviceDescBank[1].PCKSIZE.bit.SIZE = 0;
+  pUsb->DEVICE.DeviceEndpoint[USB_EP_COMM].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_BK1RDY;
+}
diff --git a/bootloaders/feather/board_driver_usb.h b/bootloaders/feather/board_driver_usb.h
new file mode 100644
index 000000000..4e71b8c1a
--- /dev/null
+++ b/bootloaders/feather/board_driver_usb.h
@@ -0,0 +1,45 @@
+/*
+  Copyright (c) 2015 Arduino LLC.  All right reserved.
+  Copyright (c) 2015 Atmel Corporation/Thibaut VIARD.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _BOARD_DRIVER_USB_H_
+#define _BOARD_DRIVER_USB_H_
+
+#include "sam_ba_cdc.h"
+
+extern UsbDeviceDescriptor usb_endpoint_table[MAX_EP];
+extern uint8_t udd_ep_out_cache_buffer[2][64]; //1 for CTRL, 1 for BULK
+extern uint8_t udd_ep_in_cache_buffer[2][64]; //1 for CTRL, 1 for BULK
+
+P_USB_CDC USB_Open(P_USB_CDC pCdc, Usb *pUsb);
+
+void USB_Init(void);
+
+uint32_t USB_Write(Usb *pUsb, const char *pData, uint32_t length, uint8_t ep_num);
+uint32_t USB_Read(Usb *pUsb, char *pData, uint32_t length);
+uint32_t USB_Read_blocking(Usb *pUsb, char *pData, uint32_t length);
+
+uint8_t USB_IsConfigured(P_USB_CDC pCdc);
+
+void USB_SendStall(Usb *pUsb, bool direction_in);
+void USB_SendZlp(Usb *pUsb);
+
+void USB_SetAddress(Usb *pUsb, uint16_t wValue);
+void USB_Configure(Usb *pUsb);
+
+#endif // _BOARD_DRIVER_USB_H_
diff --git a/bootloaders/feather/board_init.c b/bootloaders/feather/board_init.c
new file mode 100644
index 000000000..c08aedaae
--- /dev/null
+++ b/bootloaders/feather/board_init.c
@@ -0,0 +1,210 @@
+/*
+  Copyright (c) 2015 Arduino LLC.  All right reserved.
+  Copyright (c) 2015 Atmel Corporation/Thibaut VIARD.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include <sam.h>
+#include "board_definitions.h"
+
+/**
+ * \brief system_init() configures the needed clocks and according Flash Read Wait States.
+ * At reset:
+ * - OSC8M clock source is enabled with a divider by 8 (1MHz).
+ * - Generic Clock Generator 0 (GCLKMAIN) is using OSC8M as source.
+ * We need to:
+ * 1) Enable XOSC32K clock (External on-board 32.768Hz oscillator), will be used as DFLL48M reference.
+ * 2) Put XOSC32K as source of Generic Clock Generator 1
+ * 3) Put Generic Clock Generator 1 as source for Generic Clock Multiplexer 0 (DFLL48M reference)
+ * 4) Enable DFLL48M clock
+ * 5) Switch Generic Clock Generator 0 to DFLL48M. CPU will run at 48MHz.
+ * 6) Modify PRESCaler value of OSCM to have 8MHz
+ * 7) Put OSC8M as source for Generic Clock Generator 3
+ */
+// Constants for Clock generators
+#define GENERIC_CLOCK_GENERATOR_MAIN      (0u)
+#define GENERIC_CLOCK_GENERATOR_XOSC32K   (1u)
+#define GENERIC_CLOCK_GENERATOR_OSCULP32K (2u) /* Initialized at reset for WDT */
+#define GENERIC_CLOCK_GENERATOR_OSC8M     (3u)
+// Constants for Clock multiplexers
+#define GENERIC_CLOCK_MULTIPLEXER_DFLL48M (0u)
+
+void board_init(void)
+{
+  /* Set 1 Flash Wait State for 48MHz, cf tables 20.9 and 35.27 in SAMD21 Datasheet */
+  NVMCTRL->CTRLB.bit.RWS = NVMCTRL_CTRLB_RWS_HALF_Val;
+
+  /* Turn on the digital interface clock */
+  PM->APBAMASK.reg |= PM_APBAMASK_GCLK;
+
+  /* ----------------------------------------------------------------------------------------------
+   * 1) Enable XOSC32K clock (External on-board 32.768Hz oscillator)
+   */
+  SYSCTRL->XOSC32K.reg = SYSCTRL_XOSC32K_STARTUP( 0x6u ) | /* cf table 15.10 of product datasheet in chapter 15.8.6 */
+                         SYSCTRL_XOSC32K_XTALEN | SYSCTRL_XOSC32K_EN32K;
+  SYSCTRL->XOSC32K.bit.ENABLE = 1; /* separate call, as described in chapter 15.6.3 */
+
+  while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_XOSC32KRDY) == 0 )
+  {
+    /* Wait for oscillator stabilization */
+  }
+
+  /* Software reset the module to ensure it is re-initialized correctly */
+  /* Note: Due to synchronization, there is a delay from writing CTRL.SWRST until the reset is complete.
+   * CTRL.SWRST and STATUS.SYNCBUSY will both be cleared when the reset is complete, as described in chapter 13.8.1
+   */
+  GCLK->CTRL.reg = GCLK_CTRL_SWRST;
+
+  while ( (GCLK->CTRL.reg & GCLK_CTRL_SWRST) && (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY) )
+  {
+    /* Wait for reset to complete */
+  }
+
+  /* ----------------------------------------------------------------------------------------------
+   * 2) Put XOSC32K as source of Generic Clock Generator 1
+   */
+  GCLK->GENDIV.reg = GCLK_GENDIV_ID( GENERIC_CLOCK_GENERATOR_XOSC32K ); // Generic Clock Generator 1
+
+  while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY )
+  {
+    /* Wait for synchronization */
+  }
+
+  /* Write Generic Clock Generator 1 configuration */
+  GCLK->GENCTRL.reg = GCLK_GENCTRL_ID( GENERIC_CLOCK_GENERATOR_XOSC32K ) | // Generic Clock Generator 1
+                      GCLK_GENCTRL_SRC_XOSC32K | // Selected source is External 32KHz Oscillator
+//                      GCLK_GENCTRL_OE | // Output clock to a pin for tests
+                      GCLK_GENCTRL_GENEN;
+
+  while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY )
+  {
+    /* Wait for synchronization */
+  }
+
+  /* ----------------------------------------------------------------------------------------------
+   * 3) Put Generic Clock Generator 1 as source for Generic Clock Multiplexer 0 (DFLL48M reference)
+   */
+  GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID( GENERIC_CLOCK_MULTIPLEXER_DFLL48M ) | // Generic Clock Multiplexer 0
+                      GCLK_CLKCTRL_GEN_GCLK1 | // Generic Clock Generator 1 is source
+                      GCLK_CLKCTRL_CLKEN;
+
+  while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY )
+  {
+    /* Wait for synchronization */
+  }
+
+  /* ----------------------------------------------------------------------------------------------
+   * 4) Enable DFLL48M clock
+   */
+
+  /* DFLL Configuration in Closed Loop mode, cf product datasheet chapter 15.6.7.1 - Closed-Loop Operation */
+
+  /* Remove the OnDemand mode, Bug http://avr32.icgroup.norway.atmel.com/bugzilla/show_bug.cgi?id=9905 */
+  SYSCTRL->DFLLCTRL.bit.ONDEMAND = 0;
+
+  while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLRDY) == 0 )
+  {
+    /* Wait for synchronization */
+  }
+
+  SYSCTRL->DFLLMUL.reg = SYSCTRL_DFLLMUL_CSTEP( 31 ) | // Coarse step is 31, half of the max value
+                         SYSCTRL_DFLLMUL_FSTEP( 511 ) | // Fine step is 511, half of the max value
+                         SYSCTRL_DFLLMUL_MUL( (VARIANT_MCK/VARIANT_MAINOSC) ); // External 32KHz is the reference
+
+  while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLRDY) == 0 )
+  {
+    /* Wait for synchronization */
+  }
+
+  /* Write full configuration to DFLL control register */
+  SYSCTRL->DFLLCTRL.reg |= SYSCTRL_DFLLCTRL_MODE | /* Enable the closed loop mode */
+                           SYSCTRL_DFLLCTRL_WAITLOCK |
+                           SYSCTRL_DFLLCTRL_QLDIS; /* Disable Quick lock */
+
+  while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLRDY) == 0 )
+  {
+    /* Wait for synchronization */
+  }
+
+  /* Enable the DFLL */
+  SYSCTRL->DFLLCTRL.reg |= SYSCTRL_DFLLCTRL_ENABLE;
+
+  while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLLCKC) == 0 ||
+          (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLLCKF) == 0 )
+  {
+    /* Wait for locks flags */
+  }
+
+  while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLRDY) == 0 )
+  {
+    /* Wait for synchronization */
+  }
+
+  /* ----------------------------------------------------------------------------------------------
+   * 5) Switch Generic Clock Generator 0 to DFLL48M. CPU will run at 48MHz.
+   */
+  GCLK->GENDIV.reg = GCLK_GENDIV_ID( GENERIC_CLOCK_GENERATOR_MAIN ); // Generic Clock Generator 0
+
+  while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY )
+  {
+    /* Wait for synchronization */
+  }
+
+  /* Write Generic Clock Generator 0 configuration */
+  GCLK->GENCTRL.reg = GCLK_GENCTRL_ID( GENERIC_CLOCK_GENERATOR_MAIN ) | // Generic Clock Generator 0
+                      GCLK_GENCTRL_SRC_DFLL48M | // Selected source is DFLL 48MHz
+//                      GCLK_GENCTRL_OE | // Output clock to a pin for tests
+                      GCLK_GENCTRL_IDC | // Set 50/50 duty cycle
+                      GCLK_GENCTRL_GENEN;
+
+  while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY )
+  {
+    /* Wait for synchronization */
+  }
+
+#if 0
+  /* ----------------------------------------------------------------------------------------------
+   * 6) Modify PRESCaler value of OSC8M to have 8MHz
+   */
+  SYSCTRL->OSC8M.bit.PRESC = SYSCTRL_OSC8M_PRESC_1_Val;
+  SYSCTRL->OSC8M.bit.ONDEMAND = 0;
+
+  /* ----------------------------------------------------------------------------------------------
+   * 7) Put OSC8M as source for Generic Clock Generator 3
+   */
+  GCLK->GENDIV.reg = GCLK_GENDIV_ID( GENERIC_CLOCK_GENERATOR_OSC8M ); // Generic Clock Generator 3
+
+  /* Write Generic Clock Generator 3 configuration */
+  GCLK->GENCTRL.reg = GCLK_GENCTRL_ID( GENERIC_CLOCK_GENERATOR_OSC8M ) | // Generic Clock Generator 3
+                      GCLK_GENCTRL_SRC_OSC8M | // Selected source is RC OSC 8MHz (already enabled at reset)
+//                      GCLK_GENCTRL_OE | // Output clock to a pin for tests
+                      GCLK_GENCTRL_GENEN;
+
+  while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY )
+  {
+    /* Wait for synchronization */
+  }
+#endif //0
+
+  /*
+   * Now that all system clocks are configured, we can set CPU and APBx BUS clocks.
+   * These values are normally the ones present after Reset.
+   */
+  PM->CPUSEL.reg  = PM_CPUSEL_CPUDIV_DIV1;
+  PM->APBASEL.reg = PM_APBASEL_APBADIV_DIV1_Val;
+  PM->APBBSEL.reg = PM_APBBSEL_APBBDIV_DIV1_Val;
+  PM->APBCSEL.reg = PM_APBCSEL_APBCDIV_DIV1_Val;
+}
diff --git a/bootloaders/feather/board_startup.c b/bootloaders/feather/board_startup.c
new file mode 100644
index 000000000..aaa5a019f
--- /dev/null
+++ b/bootloaders/feather/board_startup.c
@@ -0,0 +1,147 @@
+/*
+  Copyright (c) 2015 Arduino LLC.  All right reserved.
+  Copyright (c) 2015 Atmel Corporation/Thibaut VIARD.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include <sam.h>
+
+struct ConstVectors
+{
+  /* Stack pointer */
+  void* pvStack;
+
+  /* Cortex-M handlers */
+  void* pfnReset_Handler;
+  void* pfnNMI_Handler;
+  void* pfnHardFault_Handler;
+  void* pfnReservedM12;
+  void* pfnReservedM11;
+  void* pfnReservedM10;
+  void* pfnReservedM9;
+  void* pfnReservedM8;
+  void* pfnReservedM7;
+  void* pfnReservedM6;
+  void* pfnSVC_Handler;
+  void* pfnReservedM4;
+  void* pfnReservedM3;
+  void* pfnPendSV_Handler;
+  void* pfnSysTick_Handler;
+};
+
+/* Symbols exported from linker script */
+extern uint32_t __etext ;
+extern uint32_t __data_start__ ;
+extern uint32_t __data_end__ ;
+extern uint32_t __bss_start__ ;
+extern uint32_t __bss_end__ ;
+extern uint32_t __StackTop;
+
+extern int main(void);
+extern void __libc_init_array(void);
+
+/* Exception Table */
+__attribute__ ((section(".isr_vector")))
+const struct ConstVectors exception_table =
+{
+  /* Configure Initial Stack Pointer, using linker-generated symbols */
+  .pvStack = (void*) (&__StackTop),
+
+  .pfnReset_Handler      = (void*) Reset_Handler,
+  .pfnNMI_Handler        = (void*) NMI_Handler,
+  .pfnHardFault_Handler  = (void*) HardFault_Handler,
+  .pfnReservedM12        = (void*) (0UL), /* Reserved */
+  .pfnReservedM11        = (void*) (0UL), /* Reserved */
+  .pfnReservedM10        = (void*) (0UL), /* Reserved */
+  .pfnReservedM9         = (void*) (0UL), /* Reserved */
+  .pfnReservedM8         = (void*) (0UL), /* Reserved */
+  .pfnReservedM7         = (void*) (0UL), /* Reserved */
+  .pfnReservedM6         = (void*) (0UL), /* Reserved */
+  .pfnSVC_Handler        = (void*) SVC_Handler,
+  .pfnReservedM4         = (void*) (0UL), /* Reserved */
+  .pfnReservedM3         = (void*) (0UL), /* Reserved */
+  .pfnPendSV_Handler     = (void*) PendSV_Handler,
+  .pfnSysTick_Handler    = (void*) SysTick_Handler,
+};
+
+/**
+ * \brief This is the code that gets called on processor reset.
+ * Initializes the device and call the main() routine.
+ */
+void Reset_Handler( void )
+{
+  uint32_t *pSrc, *pDest;
+
+  /* Initialize the initialized data section */
+  pSrc = &__etext;
+  pDest = &__data_start__;
+
+  if ( (&__data_start__ != &__data_end__) && (pSrc != pDest) )
+  {
+    for (; pDest < &__data_end__ ; pDest++, pSrc++ )
+    {
+      *pDest = *pSrc ;
+    }
+  }
+
+  /* Clear the zero section */
+  if ( &__bss_start__ != &__bss_end__ )
+  {
+    for ( pDest = &__bss_start__ ; pDest < &__bss_end__ ; pDest++ )
+    {
+      *pDest = 0ul ;
+    }
+  }
+
+//  board_init(); // will be done in main() after app check
+
+  /* Initialize the C library */
+//  __libc_init_array();
+
+  main();
+
+  while (1);
+}
+
+void NMI_Handler(void)
+{
+  __BKPT(14);
+  while (1);
+}
+
+void HardFault_Handler(void)
+{
+  __BKPT(13);
+  while (1);
+}
+
+void SVC_Handler(void)
+{
+  __BKPT(5);
+  while (1);
+}
+
+void PendSV_Handler(void)
+{
+  __BKPT(2);
+  while (1);
+}
+
+void SysTick_Handler(void)
+{
+  __BKPT(1);
+  while (1);
+}
diff --git a/bootloaders/feather/bootloader_samd21x18.ld b/bootloaders/feather/bootloader_samd21x18.ld
new file mode 100644
index 000000000..2a8b056d3
--- /dev/null
+++ b/bootloaders/feather/bootloader_samd21x18.ld
@@ -0,0 +1,221 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+  Copyright (c) 2015 Atmel Corporation/Thibaut VIARD.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* Linker script to configure memory regions.
+ * Need modifying for a specific board.
+ *   FLASH.ORIGIN: starting address of flash
+ *   FLASH.LENGTH: length of flash
+ *   RAM.ORIGIN: starting address of RAM bank 0
+ *   RAM.LENGTH: length of RAM bank 0
+ */
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x2000 /* First 8KB used by bootloader */
+  RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000-0x0004 /* 4 bytes used by bootloader to keep data between resets */
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ *   Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ *   __exidx_start
+ *   __exidx_end
+ *   __copy_table_start__
+ *   __copy_table_end__
+ *   __zero_table_start__
+ *   __zero_table_end__
+ *   __etext
+ *   __data_start__
+ *   __preinit_array_start
+ *   __preinit_array_end
+ *   __init_array_start
+ *   __init_array_end
+ *   __fini_array_start
+ *   __fini_array_end
+ *   __data_end__
+ *   __bss_start__
+ *   __bss_end__
+ *   __end__
+ *   end
+ *   __HeapLimit
+ *   __StackLimit
+ *   __StackTop
+ *   __stack
+ *   __sketch_vectors_ptr
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+  . = ORIGIN(FLASH);
+
+  .vectors :
+  {
+    KEEP(*(.isr_vector))
+  } > FLASH
+
+	.text :
+	{
+		*(.text*)
+
+		KEEP(*(.init))
+		KEEP(*(.fini))
+
+		/* .ctors */
+		*crtbegin.o(.ctors)
+		*crtbegin?.o(.ctors)
+		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+		*(SORT(.ctors.*))
+		*(.ctors)
+
+		/* .dtors */
+ 		*crtbegin.o(.dtors)
+ 		*crtbegin?.o(.dtors)
+ 		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ 		*(SORT(.dtors.*))
+ 		*(.dtors)
+
+		*(.rodata*)
+
+		KEEP(*(.eh_frame*))
+	} > FLASH
+
+	.ARM.extab :
+	{
+		*(.ARM.extab* .gnu.linkonce.armextab.*)
+	} > FLASH
+
+	__exidx_start = .;
+	.ARM.exidx :
+	{
+		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
+	} > FLASH
+	__exidx_end = .;
+
+	/* To copy multiple ROM to RAM sections,
+	 * uncomment .copy.table section and,
+	 * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.copy.table :
+	{
+		. = ALIGN(4);
+		__copy_table_start__ = .;
+		LONG (__etext)
+		LONG (__data_start__)
+		LONG (__data_end__ - __data_start__)
+		LONG (__etext2)
+		LONG (__data2_start__)
+		LONG (__data2_end__ - __data2_start__)
+		__copy_table_end__ = .;
+	} > FLASH
+	*/
+
+	/* To clear multiple BSS sections,
+	 * uncomment .zero.table section and,
+	 * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.zero.table :
+	{
+		. = ALIGN(4);
+		__zero_table_start__ = .;
+		LONG (__bss_start__)
+		LONG (__bss_end__ - __bss_start__)
+		LONG (__bss2_start__)
+		LONG (__bss2_end__ - __bss2_start__)
+		__zero_table_end__ = .;
+	} > FLASH
+	*/
+
+	__etext = .;
+  PROVIDE(__sketch_vectors_ptr = ORIGIN(FLASH) + LENGTH(FLASH));
+
+
+	.data : AT (__etext)
+	{
+		__data_start__ = .;
+		*(vtable)
+		*(.data*)
+
+		. = ALIGN(4);
+		/* preinit data */
+		PROVIDE_HIDDEN (__preinit_array_start = .);
+		KEEP(*(.preinit_array))
+		PROVIDE_HIDDEN (__preinit_array_end = .);
+
+		. = ALIGN(4);
+		/* init data */
+		PROVIDE_HIDDEN (__init_array_start = .);
+		KEEP(*(SORT(.init_array.*)))
+		KEEP(*(.init_array))
+		PROVIDE_HIDDEN (__init_array_end = .);
+
+
+		. = ALIGN(4);
+		/* finit data */
+		PROVIDE_HIDDEN (__fini_array_start = .);
+		KEEP(*(SORT(.fini_array.*)))
+		KEEP(*(.fini_array))
+		PROVIDE_HIDDEN (__fini_array_end = .);
+
+		KEEP(*(.jcr*))
+		. = ALIGN(4);
+		/* All data end */
+		__data_end__ = .;
+
+	} > RAM
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start__ = .;
+		*(.bss*)
+		*(COMMON)
+		. = ALIGN(4);
+		__bss_end__ = .;
+	} > RAM
+
+	.heap (COPY):
+	{
+		__end__ = .;
+		PROVIDE(end = .);
+		*(.heap*)
+		__HeapLimit = .;
+	} > RAM
+
+	/* .stack_dummy section doesn't contains any symbols. It is only
+	 * used for linker to calculate size of stack sections, and assign
+	 * values to stack symbols later */
+	.stack_dummy (COPY):
+	{
+		*(.stack*)
+	} > RAM
+
+	/* Set stack top to end of RAM, and stack limit move down by
+	 * size of stack_dummy section */
+	__StackTop = ORIGIN(RAM) + LENGTH(RAM);
+	__StackLimit = __StackTop - SIZEOF(.stack_dummy);
+	PROVIDE(__stack = __StackTop);
+
+	__ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ;
+
+	/* Check if data + heap + stack exceeds RAM limit */
+	ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
+}
diff --git a/bootloaders/feather/main.c b/bootloaders/feather/main.c
new file mode 100644
index 000000000..b490596b4
--- /dev/null
+++ b/bootloaders/feather/main.c
@@ -0,0 +1,247 @@
+/*
+  Copyright (c) 2015 Arduino LLC.  All right reserved.
+  Copyright (c) 2015 Atmel Corporation/Thibaut VIARD.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include <stdio.h>
+#include <sam.h>
+#include "sam_ba_monitor.h"
+#include "sam_ba_serial.h"
+#include "board_definitions.h"
+#include "board_driver_led.h"
+#include "sam_ba_usb.h"
+#include "sam_ba_cdc.h"
+
+extern uint32_t __sketch_vectors_ptr; // Exported value from linker script
+extern void board_init(void);
+
+#if (defined DEBUG) && (DEBUG == 1)
+volatile uint32_t* pulSketch_Start_Address;
+#endif
+
+static volatile bool main_b_cdc_enable = false;
+
+/**
+ * \brief Check the application startup condition
+ *
+ */
+static void check_start_application(void)
+{
+  LED_init();
+  LED_off();
+
+#if defined(BOOT_DOUBLE_TAP_ADDRESS)
+  #define DOUBLE_TAP_MAGIC 0x07738135
+  if (PM->RCAUSE.bit.POR)
+  {
+    /* On power-on initialize double-tap */
+    BOOT_DOUBLE_TAP_DATA = 0;
+  }
+  else
+  {
+    if (BOOT_DOUBLE_TAP_DATA == DOUBLE_TAP_MAGIC)
+    {
+      /* Second tap, stay in bootloader */
+      BOOT_DOUBLE_TAP_DATA = 0;
+      return;
+    }
+
+    /* First tap */
+    BOOT_DOUBLE_TAP_DATA = DOUBLE_TAP_MAGIC;
+
+    /* Wait 0.5sec to see if the user tap reset again.
+     * The loop value is based on SAMD21 default 1MHz clock @ reset.
+     */
+    for (uint32_t i=0; i<125000; i++) /* 500ms */
+      /* force compiler to not optimize this... */
+      __asm__ __volatile__("");
+
+    /* Timeout happened, continue boot... */
+    BOOT_DOUBLE_TAP_DATA = 0;
+  }
+#endif
+
+#if (!defined DEBUG) || ((defined DEBUG) && (DEBUG == 0))
+uint32_t* pulSketch_Start_Address;
+#endif
+
+  /*
+   * Test sketch stack pointer @ &__sketch_vectors_ptr
+   * Stay in SAM-BA if value @ (&__sketch_vectors_ptr) == 0xFFFFFFFF (Erased flash cell value)
+   */
+  if (__sketch_vectors_ptr == 0xFFFFFFFF)
+  {
+    /* Stay in bootloader */
+    return;
+  }
+
+  /*
+   * Load the sketch Reset Handler address
+   * __sketch_vectors_ptr is exported from linker script and point on first 32b word of sketch vector table
+   * First 32b word is sketch stack
+   * Second 32b word is sketch entry point: Reset_Handler()
+   */
+  pulSketch_Start_Address = &__sketch_vectors_ptr ;
+  pulSketch_Start_Address++ ;
+
+  /*
+   * Test vector table address of sketch @ &__sketch_vectors_ptr
+   * Stay in SAM-BA if this function is not aligned enough, ie not valid
+   */
+  if ( ((uint32_t)(&__sketch_vectors_ptr) & ~SCB_VTOR_TBLOFF_Msk) != 0x00)
+  {
+    /* Stay in bootloader */
+    return;
+  }
+
+/*
+#if defined(BOOT_LOAD_PIN)
+  volatile PortGroup *boot_port = (volatile PortGroup *)(&(PORT->Group[BOOT_LOAD_PIN / 32]));
+  volatile bool boot_en;
+
+  // Enable the input mode in Boot GPIO Pin
+  boot_port->DIRCLR.reg = BOOT_PIN_MASK;
+  boot_port->PINCFG[BOOT_LOAD_PIN & 0x1F].reg = PORT_PINCFG_INEN | PORT_PINCFG_PULLEN;
+  boot_port->OUTSET.reg = BOOT_PIN_MASK;
+  // Read the BOOT_LOAD_PIN status
+  boot_en = (boot_port->IN.reg) & BOOT_PIN_MASK;
+
+  // Check the bootloader enable condition
+  if (!boot_en)
+  {
+    // Stay in bootloader
+    return;
+  }
+#endif
+*/
+
+  LED_on();
+
+  /* Rebase the Stack Pointer */
+  __set_MSP( (uint32_t)(__sketch_vectors_ptr) );
+
+  /* Rebase the vector table base address */
+  SCB->VTOR = ((uint32_t)(&__sketch_vectors_ptr) & SCB_VTOR_TBLOFF_Msk);
+
+  /* Jump to application Reset Handler in the application */
+  asm("bx %0"::"r"(*pulSketch_Start_Address));
+}
+
+#if DEBUG_ENABLE
+#	define DEBUG_PIN_HIGH 	port_pin_set_output_level(BOOT_LED, 1)
+#	define DEBUG_PIN_LOW 	port_pin_set_output_level(BOOT_LED, 0)
+#else
+#	define DEBUG_PIN_HIGH 	do{}while(0)
+#	define DEBUG_PIN_LOW 	do{}while(0)
+#endif
+
+/**
+ *  \brief SAMD21 SAM-BA Main loop.
+ *  \return Unused (ANSI-C compatibility).
+ */
+int main(void)
+{
+#if SAM_BA_INTERFACE == SAM_BA_USBCDC_ONLY  ||  SAM_BA_INTERFACE == SAM_BA_BOTH_INTERFACES
+  P_USB_CDC pCdc;
+#endif
+  DEBUG_PIN_HIGH;
+
+  /* Jump in application if condition is satisfied */
+  check_start_application();
+
+  /* We have determined we should stay in the monitor. */
+  /* System initialization */
+  board_init();
+  __enable_irq();
+
+#if SAM_BA_INTERFACE == SAM_BA_UART_ONLY  ||  SAM_BA_INTERFACE == SAM_BA_BOTH_INTERFACES
+  /* UART is enabled in all cases */
+  serial_open();
+#endif
+
+#if SAM_BA_INTERFACE == SAM_BA_USBCDC_ONLY  ||  SAM_BA_INTERFACE == SAM_BA_BOTH_INTERFACES
+  pCdc = usb_init();
+#endif
+
+  DEBUG_PIN_LOW;
+
+  LED_on();
+
+  /* Wait for a complete enum on usb or a '#' char on serial line */
+  while (1)
+  {
+    pulse_led(3); // while we're waiting, blink the D13 
+
+#if SAM_BA_INTERFACE == SAM_BA_USBCDC_ONLY  ||  SAM_BA_INTERFACE == SAM_BA_BOTH_INTERFACES
+    if (pCdc->IsConfigured(pCdc) != 0)
+    {
+      main_b_cdc_enable = true;
+    }
+
+    /* Check if a USB enumeration has succeeded and if comm port has been opened */
+    if (main_b_cdc_enable)
+    {
+      sam_ba_monitor_init(SAM_BA_INTERFACE_USBCDC);
+      /* SAM-BA on USB loop */
+      while( 1 )
+      {
+        sam_ba_monitor_run();
+      }
+    }
+#endif
+
+#if SAM_BA_INTERFACE == SAM_BA_UART_ONLY  ||  SAM_BA_INTERFACE == SAM_BA_BOTH_INTERFACES
+    /* Check if a '#' has been received */
+    if (!main_b_cdc_enable && serial_sharp_received())
+    {
+      sam_ba_monitor_init(SAM_BA_INTERFACE_USART);
+      /* SAM-BA on Serial loop */
+      while(1)
+      {
+        sam_ba_monitor_run();
+      }
+    }
+#endif
+  }
+}
+
+
+// We'll have the D13 LED slowly pulse on and off with bitbang PWM
+// for a nice 'hey we're in bootload mode' indication! -ada
+static uint16_t pulse_tick=0;
+#define BOOT_PULSE_MAX 1000
+static int8_t  pulse_dir=1;
+static int16_t pulse_pwm;
+void pulse_led(int8_t speed) {
+  // blink D13
+  pulse_tick++;
+  if (pulse_tick==BOOT_PULSE_MAX) {
+    pulse_tick = 0;
+    pulse_pwm += pulse_dir * speed;
+    if (pulse_pwm > 255) {
+      pulse_pwm = 255;
+      pulse_dir = -1;
+    }
+    if (pulse_pwm < 0) {
+      pulse_pwm = 0;
+      pulse_dir = +1;
+    }
+    LED_on();
+  }
+  if (pulse_tick==pulse_pwm) 
+    LED_off();
+}
diff --git a/bootloaders/feather/sam_ba_cdc.c b/bootloaders/feather/sam_ba_cdc.c
new file mode 100644
index 000000000..23001cc7f
--- /dev/null
+++ b/bootloaders/feather/sam_ba_cdc.c
@@ -0,0 +1,102 @@
+/*
+  Copyright (c) 2015 Arduino LLC.  All right reserved.
+  Copyright (c) 2015 Atmel Corporation/Thibaut VIARD.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "sam_ba_cdc.h"
+#include "board_driver_usb.h"
+
+usb_cdc_line_coding_t line_coding=
+{
+  115200, // baudrate
+  0,      // 1 Stop Bit
+  0,      // None Parity
+  8     // 8 Data bits
+};
+
+#define pCdc (&sam_ba_cdc)
+
+int cdc_putc(/*P_USB_CDC pCdc,*/ int value)
+{
+  /* Send single byte on USB CDC */
+  USB_Write(pCdc->pUsb, (const char *)&value, 1, USB_EP_IN);
+
+  return 1;
+}
+
+int cdc_getc(/*P_USB_CDC pCdc*/void)
+{
+  uint8_t rx_char;
+
+  /* Read singly byte on USB CDC */
+  USB_Read(pCdc->pUsb, (char *)&rx_char, 1);
+
+  return (int)rx_char;
+}
+
+bool cdc_is_rx_ready(/*P_USB_CDC pCdc*/void)
+{
+  /* Check whether the device is configured */
+  if ( !USB_IsConfigured(pCdc) )
+    return 0;
+
+  /* Return transfer complete 0 flag status */
+#ifdef __SAMR21G18A__
+  return (pCdc->pUsb->DEVICE.DeviceEndpoint[USB_EP_OUT].EPINTFLAG.bit.TRCPT0);
+#else
+  return (pCdc->pUsb->DEVICE.DeviceEndpoint[USB_EP_OUT].EPINTFLAG.bit.TRCPT & (1<<0));
+#endif
+}
+
+uint32_t cdc_write_buf(/*P_USB_CDC pCdc,*/ void const* data, uint32_t length)
+{
+  /* Send the specified number of bytes on USB CDC */
+  USB_Write(pCdc->pUsb, (const char *)data, length, USB_EP_IN);
+  return length;
+}
+
+uint32_t cdc_read_buf(/*P_USB_CDC pCdc,*/ void* data, uint32_t length)
+{
+  /* Check whether the device is configured */
+  if ( !USB_IsConfigured(pCdc) )
+    return 0;
+
+  /* Read from USB CDC */
+  return USB_Read(pCdc->pUsb, (char *)data, length);
+}
+
+uint32_t cdc_read_buf_xmd(/*P_USB_CDC pCdc,*/ void* data, uint32_t length)
+{
+  /* Check whether the device is configured */
+  if ( !USB_IsConfigured(pCdc) )
+    return 0;
+
+  /* Blocking read till specified number of bytes is received */
+  // XXX: USB_Read_blocking is not reliable
+  // return USB_Read_blocking(pCdc, (char *)data, length);
+
+  char *dst = (char *)data;
+  uint32_t remaining = length;
+  while (remaining)
+  {
+    uint32_t readed = USB_Read(pCdc->pUsb, (char *)dst, remaining);
+    remaining -= readed;
+    dst += readed;
+  }
+
+  return length;
+}
diff --git a/bootloaders/feather/sam_ba_cdc.h b/bootloaders/feather/sam_ba_cdc.h
new file mode 100644
index 000000000..49b7643cf
--- /dev/null
+++ b/bootloaders/feather/sam_ba_cdc.h
@@ -0,0 +1,91 @@
+/*
+  Copyright (c) 2015 Arduino LLC.  All right reserved.
+  Copyright (c) 2015 Atmel Corporation/Thibaut VIARD.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _SAM_BA_USB_CDC_H_
+#define _SAM_BA_USB_CDC_H_
+
+#include <stdint.h>
+#include "sam_ba_usb.h"
+
+typedef struct
+{
+	uint32_t dwDTERate;
+	uint8_t bCharFormat;
+	uint8_t bParityType;
+	uint8_t bDataBits;
+} usb_cdc_line_coding_t;
+
+/* CDC Class Specific Request Code */
+#define GET_LINE_CODING               0x21A1
+#define SET_LINE_CODING               0x2021
+#define SET_CONTROL_LINE_STATE        0x2221
+
+extern usb_cdc_line_coding_t line_coding;
+
+
+/**
+ * \brief Sends a single byte through USB CDC
+ *
+ * \param Data to send
+ * \return number of data sent
+ */
+int cdc_putc(/*P_USB_CDC pCdc,*/ int value);
+
+/**
+ * \brief Reads a single byte through USB CDC
+ *
+ * \return Data read through USB
+ */
+int cdc_getc(/*P_USB_CDC pCdc*/);
+
+/**
+ * \brief Checks if a character has been received on USB CDC
+ *
+ * \return \c 1 if a byte is ready to be read.
+ */
+bool cdc_is_rx_ready(/*P_USB_CDC pCdc*/);
+
+/**
+ * \brief Sends buffer on USB CDC
+ *
+ * \param data pointer
+ * \param number of data to send
+ * \return number of data sent
+ */
+uint32_t cdc_write_buf(/*P_USB_CDC pCdc,*/ void const* data, uint32_t length);
+
+/**
+ * \brief Gets data on USB CDC
+ *
+ * \param data pointer
+ * \param number of data to read
+ * \return number of data read
+ */
+uint32_t cdc_read_buf(/*P_USB_CDC pCdc,*/ void* data, uint32_t length);
+
+/**
+ * \brief Gets specified number of bytes on USB CDC
+ *
+ * \param data pointer
+ * \param number of data to read
+ * \return number of data read
+ */
+uint32_t cdc_read_buf_xmd(/*P_USB_CDC pCdc,*/ void* data, uint32_t length);
+
+#endif // _SAM_BA_USB_CDC_H_
diff --git a/bootloaders/feather/sam_ba_monitor.c b/bootloaders/feather/sam_ba_monitor.c
new file mode 100644
index 000000000..ddf7b9773
--- /dev/null
+++ b/bootloaders/feather/sam_ba_monitor.c
@@ -0,0 +1,474 @@
+/*
+  Copyright (c) 2015 Arduino LLC.  All right reserved.
+  Copyright (c) 2015 Atmel Corporation/Thibaut VIARD.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "sam.h"
+#include <string.h>
+#include "sam_ba_monitor.h"
+#include "sam_ba_serial.h"
+#include "board_driver_serial.h"
+#include "board_driver_usb.h"
+#include "sam_ba_usb.h"
+#include "sam_ba_cdc.h"
+
+const char RomBOOT_Version[] = SAM_BA_VERSION;
+const char RomBOOT_ExtendedCapabilities[] = "[Arduino:XYZ]";
+
+/* Provides one common interface to handle both USART and USB-CDC */
+typedef struct
+{
+  /* send one byte of data */
+  int (*put_c)(int value);
+  /* Get one byte */
+  int (*get_c)(void);
+  /* Receive buffer not empty */
+  bool (*is_rx_ready)(void);
+  /* Send given data (polling) */
+  uint32_t (*putdata)(void const* data, uint32_t length);
+  /* Get data from comm. device */
+  uint32_t (*getdata)(void* data, uint32_t length);
+  /* Send given data (polling) using xmodem (if necessary) */
+  uint32_t (*putdata_xmd)(void const* data, uint32_t length);
+  /* Get data from comm. device using xmodem (if necessary) */
+  uint32_t (*getdata_xmd)(void* data, uint32_t length);
+} t_monitor_if;
+
+#if SAM_BA_INTERFACE == SAM_BA_UART_ONLY  ||  SAM_BA_INTERFACE == SAM_BA_BOTH_INTERFACES
+/* Initialize structures with function pointers from supported interfaces */
+const t_monitor_if uart_if =
+{
+  .put_c =       serial_putc,
+  .get_c =       serial_getc,
+  .is_rx_ready = serial_is_rx_ready,
+  .putdata =     serial_putdata,
+  .getdata =     serial_getdata,
+  .putdata_xmd = serial_putdata_xmd,
+  .getdata_xmd = serial_getdata_xmd
+};
+#endif
+
+#if SAM_BA_INTERFACE == SAM_BA_USBCDC_ONLY  ||  SAM_BA_INTERFACE == SAM_BA_BOTH_INTERFACES
+//Please note that USB doesn't use Xmodem protocol, since USB already includes flow control and data verification
+//Data are simply forwarded without further coding.
+const t_monitor_if usbcdc_if =
+{
+  .put_c =         cdc_putc,
+  .get_c =         cdc_getc,
+  .is_rx_ready =   cdc_is_rx_ready,
+  .putdata =       cdc_write_buf,
+  .getdata =       cdc_read_buf,
+  .putdata_xmd =   cdc_write_buf,
+  .getdata_xmd =   cdc_read_buf_xmd
+};
+#endif
+
+/* The pointer to the interface object use by the monitor */
+t_monitor_if * ptr_monitor_if;
+
+/* b_terminal_mode mode (ascii) or hex mode */
+volatile bool b_terminal_mode = false;
+volatile bool b_sam_ba_interface_usart = false;
+
+void sam_ba_monitor_init(uint8_t com_interface)
+{
+#if SAM_BA_INTERFACE == SAM_BA_UART_ONLY  ||  SAM_BA_INTERFACE == SAM_BA_BOTH_INTERFACES
+  //Selects the requested interface for future actions
+  if (com_interface == SAM_BA_INTERFACE_USART)
+  {
+    ptr_monitor_if = (t_monitor_if*) &uart_if;
+    b_sam_ba_interface_usart = true;
+  }
+#endif
+#if SAM_BA_INTERFACE == SAM_BA_USBCDC_ONLY  ||  SAM_BA_INTERFACE == SAM_BA_BOTH_INTERFACES
+  if (com_interface == SAM_BA_INTERFACE_USBCDC)
+  {
+    ptr_monitor_if = (t_monitor_if*) &usbcdc_if;
+  }
+#endif
+}
+
+/**
+ * \brief This function allows data rx by USART
+ *
+ * \param *data  Data pointer
+ * \param length Length of the data
+ */
+void sam_ba_putdata_term(uint8_t* data, uint32_t length)
+{
+  uint8_t temp, buf[12], *data_ascii;
+  uint32_t i, int_value;
+
+  if (b_terminal_mode)
+  {
+    if (length == 4)
+      int_value = *(uint32_t *) data;
+    else if (length == 2)
+      int_value = *(uint16_t *) data;
+    else
+      int_value = *(uint8_t *) data;
+
+    data_ascii = buf + 2;
+    data_ascii += length * 2 - 1;
+
+    for (i = 0; i < length * 2; i++)
+    {
+      temp = (uint8_t) (int_value & 0xf);
+
+      if (temp <= 0x9)
+        *data_ascii = temp | 0x30;
+      else
+        *data_ascii = temp + 0x37;
+
+      int_value >>= 4;
+      data_ascii--;
+    }
+    buf[0] = '0';
+    buf[1] = 'x';
+    buf[length * 2 + 2] = '\n';
+    buf[length * 2 + 3] = '\r';
+    ptr_monitor_if->putdata(buf, length * 2 + 4);
+  }
+  else
+    ptr_monitor_if->putdata(data, length);
+  return;
+}
+
+volatile uint32_t sp;
+void call_applet(uint32_t address)
+{
+  uint32_t app_start_address;
+
+  __disable_irq();
+
+  sp = __get_MSP();
+
+  /* Rebase the Stack Pointer */
+  __set_MSP(*(uint32_t *) address);
+
+  /* Load the Reset Handler address of the application */
+  app_start_address = *(uint32_t *)(address + 4);
+
+  /* Jump to application Reset Handler in the application */
+  asm("bx %0"::"r"(app_start_address));
+}
+
+uint32_t current_number;
+uint32_t i, length;
+uint8_t command, *ptr_data, *ptr, data[SIZEBUFMAX];
+uint8_t j;
+uint32_t u32tmp;
+
+uint32_t PAGE_SIZE, PAGES, MAX_FLASH;
+
+// Prints a 32-bit integer in hex.
+static void put_uint32(uint32_t n)
+{
+  char buff[8];
+  int i;
+  for (i=0; i<8; i++)
+  {
+    int d = n & 0XF;
+    n = (n >> 4);
+
+    buff[7-i] = d > 9 ? 'A' + d - 10 : '0' + d;
+  }
+  ptr_monitor_if->putdata(buff, 8);
+}
+
+static void sam_ba_monitor_loop(void)
+{
+  pulse_led(3);
+
+  length = ptr_monitor_if->getdata(data, SIZEBUFMAX);
+  ptr = data;
+
+  for (i = 0; i < length; i++, ptr++)
+  {
+    if (*ptr == 0xff) continue;
+
+    if (*ptr == '#')
+    {
+      if (b_terminal_mode)
+      {
+        ptr_monitor_if->putdata("\n\r", 2);
+      }
+      if (command == 'S')
+      {
+        //Check if some data are remaining in the "data" buffer
+        if(length>i)
+        {
+          //Move current indexes to next avail data (currently ptr points to "#")
+          ptr++;
+          i++;
+
+          //We need to add first the remaining data of the current buffer already read from usb
+          //read a maximum of "current_number" bytes
+          if ((length-i) < current_number)
+          {
+            u32tmp=(length-i);
+          }
+          else
+          {
+            u32tmp=current_number;
+          }
+
+          memcpy(ptr_data, ptr, u32tmp);
+          i += u32tmp;
+          ptr += u32tmp;
+          j = u32tmp;
+        }
+        //update i with the data read from the buffer
+        i--;
+        ptr--;
+        //Do we expect more data ?
+        if(j<current_number)
+          ptr_monitor_if->getdata_xmd(ptr_data, current_number-j);
+
+        __asm("nop");
+      }
+      else if (command == 'R')
+      {
+        ptr_monitor_if->putdata_xmd(ptr_data, current_number);
+      }
+      else if (command == 'O')
+      {
+        *ptr_data = (char) current_number;
+      }
+      else if (command == 'H')
+      {
+        *((uint16_t *) ptr_data) = (uint16_t) current_number;
+      }
+      else if (command == 'W')
+      {
+        *((int *) ptr_data) = current_number;
+      }
+      else if (command == 'o')
+      {
+        sam_ba_putdata_term(ptr_data, 1);
+      }
+      else if (command == 'h')
+      {
+        current_number = *((uint16_t *) ptr_data);
+        sam_ba_putdata_term((uint8_t*) &current_number, 2);
+      }
+      else if (command == 'w')
+      {
+        current_number = *((uint32_t *) ptr_data);
+        sam_ba_putdata_term((uint8_t*) &current_number, 4);
+      }
+      else if (command == 'G')
+      {
+        call_applet(current_number);
+        /* Rebase the Stack Pointer */
+        __set_MSP(sp);
+        __enable_irq();
+        if (b_sam_ba_interface_usart) {
+          ptr_monitor_if->put_c(0x6);
+        }
+      }
+      else if (command == 'T')
+      {
+        b_terminal_mode = 1;
+        ptr_monitor_if->putdata("\n\r", 2);
+      }
+      else if (command == 'N')
+      {
+        if (b_terminal_mode == 0)
+        {
+          ptr_monitor_if->putdata("\n\r", 2);
+        }
+        b_terminal_mode = 0;
+      }
+      else if (command == 'V')
+      {
+        ptr_monitor_if->putdata("v", 1);
+        ptr_monitor_if->putdata((uint8_t *) RomBOOT_Version, strlen(RomBOOT_Version));
+        ptr_monitor_if->putdata(" ", 1);
+        ptr_monitor_if->putdata((uint8_t *) RomBOOT_ExtendedCapabilities, strlen(RomBOOT_ExtendedCapabilities));
+        ptr_monitor_if->putdata(" ", 1);
+        ptr = (uint8_t*) &(__DATE__);
+        i = 0;
+        while (*ptr++ != '\0')
+          i++;
+        ptr_monitor_if->putdata((uint8_t *) &(__DATE__), i);
+        ptr_monitor_if->putdata(" ", 1);
+        i = 0;
+        ptr = (uint8_t*) &(__TIME__);
+        while (*ptr++ != '\0')
+          i++;
+        ptr_monitor_if->putdata((uint8_t *) &(__TIME__), i);
+        ptr_monitor_if->putdata("\n\r", 2);
+      }
+      else if (command == 'X')
+      {
+        // Syntax: X[ADDR]#
+        // Erase the flash memory starting from ADDR to the end of flash.
+
+        // Note: the flash memory is erased in ROWS, that is in block of 4 pages.
+        //       Even if the starting address is the last byte of a ROW the entire
+        //       ROW is erased anyway.
+
+        uint32_t dst_addr = current_number; // starting address
+
+        while (dst_addr < MAX_FLASH)
+        {
+          // Execute "ER" Erase Row
+          NVMCTRL->ADDR.reg = dst_addr / 2;
+          NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_ER;
+          while (NVMCTRL->INTFLAG.bit.READY == 0)
+            ;
+          dst_addr += PAGE_SIZE * 4; // Skip a ROW
+        }
+
+        // Notify command completed
+        ptr_monitor_if->putdata("X\n\r", 3);
+      }
+      else if (command == 'Y')
+      {
+        // This command writes the content of a buffer in SRAM into flash memory.
+
+        // Syntax: Y[ADDR],0#
+        // Set the starting address of the SRAM buffer.
+
+        // Syntax: Y[ROM_ADDR],[SIZE]#
+        // Write the first SIZE bytes from the SRAM buffer (previously set) into
+        // flash memory starting from address ROM_ADDR
+
+        static uint32_t *src_buff_addr = NULL;
+
+        if (current_number == 0)
+        {
+          // Set buffer address
+          src_buff_addr = (uint32_t*)ptr_data;
+        }
+        else
+        {
+          // Write to flash
+          uint32_t size = current_number/4;
+          uint32_t *src_addr = src_buff_addr;
+          uint32_t *dst_addr = (uint32_t*)ptr_data;
+
+          // Set automatic page write
+          NVMCTRL->CTRLB.bit.MANW = 0;
+
+          // Do writes in pages
+          while (size)
+          {
+            // Execute "PBC" Page Buffer Clear
+            NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_PBC;
+            while (NVMCTRL->INTFLAG.bit.READY == 0)
+              ;
+
+            // Fill page buffer
+            uint32_t i;
+            for (i=0; i<(PAGE_SIZE/4) && i<size; i++)
+            {
+              dst_addr[i] = src_addr[i];
+            }
+
+            // Execute "WP" Write Page
+            //NVMCTRL->ADDR.reg = ((uint32_t)dst_addr) / 2;
+            NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_WP;
+            while (NVMCTRL->INTFLAG.bit.READY == 0)
+              ;
+
+            // Advance to next page
+            dst_addr += i;
+            src_addr += i;
+            size     -= i;
+          }
+        }
+
+        // Notify command completed
+        ptr_monitor_if->putdata("Y\n\r", 3);
+      }
+      else if (command == 'Z')
+      {
+        // This command calculate CRC for a given area of memory.
+        // It's useful to quickly check if a transfer has been done
+        // successfully.
+
+        // Syntax: Z[START_ADDR],[SIZE]#
+        // Returns: Z[CRC]#
+
+        uint8_t *data = (uint8_t *)ptr_data;
+        uint32_t size = current_number;
+        uint16_t crc = 0;
+        uint32_t i = 0;
+        for (i=0; i<size; i++)
+          crc = serial_add_crc(*data++, crc);
+
+        // Send response
+        ptr_monitor_if->putdata("Z", 1);
+        put_uint32(crc);
+        ptr_monitor_if->putdata("#\n\r", 3);
+      }
+
+      command = 'z';
+      current_number = 0;
+
+      if (b_terminal_mode)
+      {
+        ptr_monitor_if->putdata(">", 1);
+      }
+    }
+    else
+    {
+      if (('0' <= *ptr) && (*ptr <= '9'))
+      {
+        current_number = (current_number << 4) | (*ptr - '0');
+      }
+      else if (('A' <= *ptr) && (*ptr <= 'F'))
+      {
+        current_number = (current_number << 4) | (*ptr - 'A' + 0xa);
+      }
+      else if (('a' <= *ptr) && (*ptr <= 'f'))
+      {
+        current_number = (current_number << 4) | (*ptr - 'a' + 0xa);
+      }
+      else if (*ptr == ',')
+      {
+        ptr_data = (uint8_t *) current_number;
+        current_number = 0;
+      }
+      else
+      {
+        command = *ptr;
+        current_number = 0;
+      }
+    }
+  }
+}
+
+/**
+ * \brief This function starts the SAM-BA monitor.
+ */
+void sam_ba_monitor_run(void)
+{
+  uint32_t pageSizes[] = { 8, 16, 32, 64, 128, 256, 512, 1024 };
+  PAGE_SIZE = pageSizes[NVMCTRL->PARAM.bit.PSZ];
+  PAGES = NVMCTRL->PARAM.bit.NVMP;
+  MAX_FLASH = PAGE_SIZE * PAGES;
+
+  ptr_data = NULL;
+  command = 'z';
+  while (1)
+  {
+    sam_ba_monitor_loop();
+  }
+}
diff --git a/bootloaders/feather/sam_ba_monitor.h b/bootloaders/feather/sam_ba_monitor.h
new file mode 100644
index 000000000..e72582bcf
--- /dev/null
+++ b/bootloaders/feather/sam_ba_monitor.h
@@ -0,0 +1,66 @@
+/*
+  Copyright (c) 2015 Arduino LLC.  All right reserved.
+  Copyright (c) 2015 Atmel Corporation/Thibaut VIARD.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _MONITOR_SAM_BA_H_
+#define _MONITOR_SAM_BA_H_
+
+#define SAM_BA_VERSION              "2.0"
+
+/* Enable the interfaces to save code size */
+#define SAM_BA_BOTH_INTERFACES      0
+#define SAM_BA_UART_ONLY            1
+#define SAM_BA_USBCDC_ONLY          2
+
+#ifndef SAM_BA_INTERFACE
+#define SAM_BA_INTERFACE    SAM_BA_BOTH_INTERFACES
+#endif
+
+/* Selects USB as the communication interface of the monitor */
+#define SAM_BA_INTERFACE_USBCDC     0
+/* Selects USART as the communication interface of the monitor */
+#define SAM_BA_INTERFACE_USART      1
+
+/* Selects USB as the communication interface of the monitor */
+#define SIZEBUFMAX                  64
+
+/**
+ * \brief Initialize the monitor
+ *
+ */
+void sam_ba_monitor_init(uint8_t com_interface);
+
+/**
+ * \brief Main function of the SAM-BA Monitor
+ *
+ */
+void sam_ba_monitor_run(void);
+
+/**
+ * \brief
+ *
+ */
+void sam_ba_putdata_term(uint8_t* data, uint32_t length);
+
+/**
+ * \brief
+ *
+ */
+void call_applet(uint32_t address);
+
+#endif // _MONITOR_SAM_BA_H_
diff --git a/bootloaders/feather/sam_ba_serial.c b/bootloaders/feather/sam_ba_serial.c
new file mode 100644
index 000000000..09607ecf6
--- /dev/null
+++ b/bootloaders/feather/sam_ba_serial.c
@@ -0,0 +1,534 @@
+/*
+  Copyright (c) 2015 Arduino LLC.  All right reserved.
+  Copyright (c) 2015 Atmel Corporation/Thibaut VIARD.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include <sam.h>
+#include "board_definitions.h"
+#include "sam_ba_serial.h"
+#include "board_driver_serial.h"
+
+/* Local reference to current Usart instance in use with this driver */
+//struct usart_module usart_sam_ba;
+
+/* Variable to let the main task select the appropriate communication interface */
+volatile uint8_t b_sharp_received;
+
+/* RX and TX Buffers + rw pointers for each buffer */
+volatile uint8_t buffer_rx_usart[USART_BUFFER_SIZE];
+
+volatile uint8_t idx_rx_read;
+volatile uint8_t idx_rx_write;
+
+volatile uint8_t buffer_tx_usart[USART_BUFFER_SIZE];
+
+volatile uint8_t idx_tx_read;
+volatile uint8_t idx_tx_write;
+
+/* Test for timeout in AT91F_GetChar */
+uint8_t error_timeout;
+uint16_t size_of_data;
+uint8_t mode_of_transfer;
+
+#define BOOT_USART_PAD(n) BOOT_USART_PAD##n
+
+/**
+ * \brief Open the given USART
+ */
+void serial_open(void)
+{
+	uint32_t port;
+	uint32_t pin;
+
+	/* Configure the port pins for SERCOM_USART */
+	if (BOOT_USART_PAD0 != PINMUX_UNUSED)
+  {
+		/* Mask 6th bit in pin number to check whether it is greater than 32 i.e., PORTB pin */
+		port = (BOOT_USART_PAD0 & 0x200000) >> 21;
+		pin = (BOOT_USART_PAD0 >> 16);
+		PORT->Group[port].PINCFG[(pin - (port*32))].bit.PMUXEN = 1;
+		PORT->Group[port].PMUX[(pin - (port*32))/2].reg &= ~(0xF << (4 * (pin & 0x01u)));
+		PORT->Group[port].PMUX[(pin - (port*32))/2].reg |= (BOOT_USART_PAD0 & 0xFF) << (4 * (pin & 0x01u));
+	}
+
+	if (BOOT_USART_PAD1 != PINMUX_UNUSED)
+  {
+		/* Mask 6th bit in pin number to check whether it is greater than 32 i.e., PORTB pin */
+		port = (BOOT_USART_PAD1 & 0x200000) >> 21;
+		pin = BOOT_USART_PAD1 >> 16;
+		PORT->Group[port].PINCFG[(pin - (port*32))].bit.PMUXEN = 1;
+		PORT->Group[port].PMUX[(pin - (port*32))/2].reg &= ~(0xF << (4 * (pin & 0x01u)));
+		PORT->Group[port].PMUX[(pin - (port*32))/2].reg |= (BOOT_USART_PAD1 & 0xFF) << (4 * (pin & 0x01u));
+	}
+
+	if (BOOT_USART_PAD2 != PINMUX_UNUSED)
+  {
+		/* Mask 6th bit in pin number to check whether it is greater than 32 i.e., PORTB pin */
+		port = (BOOT_USART_PAD2 & 0x200000) >> 21;
+		pin = BOOT_USART_PAD2 >> 16;
+		PORT->Group[port].PINCFG[(pin - (port*32))].bit.PMUXEN = 1;
+		PORT->Group[port].PMUX[(pin - (port*32))/2].reg &= ~(0xF << (4 * (pin & 0x01u)));
+		PORT->Group[port].PMUX[(pin - (port*32))/2].reg |= (BOOT_USART_PAD2 & 0xFF) << (4 * (pin & 0x01u));
+	}
+
+	if (BOOT_USART_PAD3 != PINMUX_UNUSED)
+  {
+		/* Mask 6th bit in pin number to check whether it is greater than 32 i.e., PORTB pin */
+		port = (BOOT_USART_PAD3 & 0x200000) >> 21;
+		pin = BOOT_USART_PAD3 >> 16;
+		PORT->Group[port].PINCFG[(pin - (port*32))].bit.PMUXEN = 1;
+		PORT->Group[port].PMUX[(pin - (port*32))/2].reg &= ~(0xF << (4 * (pin & 0x01u)));
+		PORT->Group[port].PMUX[(pin - (port*32))/2].reg |= (BOOT_USART_PAD3 & 0xFF) << (4 * (pin & 0x01u));
+	}
+
+	/* Enable clock for BOOT_USART_MODULE */
+	PM->APBCMASK.reg |= BOOT_USART_BUS_CLOCK_INDEX ;
+
+	/* Set GCLK_GEN0 as source for GCLK_ID_SERCOMx_CORE */
+  GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID( BOOT_USART_PER_CLOCK_INDEX ) | // Generic Clock 0 (SERCOMx)
+                      GCLK_CLKCTRL_GEN_GCLK0 | // Generic Clock Generator 0 is source
+                      GCLK_CLKCTRL_CLKEN ;
+
+  while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY )
+  {
+    /* Wait for synchronization */
+  }
+
+	/* Baud rate 115200 - clock 48MHz -> BAUD value-63018 */
+	uart_basic_init(BOOT_USART_MODULE, 63018, BOOT_USART_PAD_SETTINGS);
+
+	//Initialize flag
+	b_sharp_received = false;
+	idx_rx_read = 0;
+	idx_rx_write = 0;
+	idx_tx_read = 0;
+	idx_tx_write = 0;
+
+	error_timeout = 0;
+}
+
+/**
+ * \brief Close communication line
+ */
+void serial_close(void)
+{
+	uart_disable(BOOT_USART_MODULE);
+}
+
+/**
+ * \brief Puts a byte on usart line
+ * The type int is used to support printf redirection from compiler LIB.
+ *
+ * \param value      Value to put
+ *
+ * \return \c 1 if function was successfully done, otherwise \c 0.
+ */
+int serial_putc(int value)
+{
+	uart_write_byte(BOOT_USART_MODULE, (uint8_t)value);
+	return 1;
+}
+
+int serial_getc(void)
+{
+	uint16_t retval;
+	//Wait until input buffer is filled
+	while(!(serial_is_rx_ready()));
+	retval = (uint16_t)uart_read_byte(BOOT_USART_MODULE);
+	//usart_read_wait(&usart_sam_ba, &retval);
+	return (int)retval;
+
+}
+
+int serial_sharp_received(void)
+{
+	if (serial_is_rx_ready())
+  {
+		if (serial_getc() == SHARP_CHARACTER)
+			return (true);
+	}
+	return (false);
+}
+
+bool serial_is_rx_ready(void)
+{
+	return (BOOT_USART_MODULE->USART.INTFLAG.reg & SERCOM_USART_INTFLAG_RXC);
+}
+
+int serial_readc(void)
+{
+	int retval;
+	retval = buffer_rx_usart[idx_rx_read];
+	idx_rx_read = (idx_rx_read + 1) & (USART_BUFFER_SIZE - 1);
+	return (retval);
+}
+
+//Send given data (polling)
+uint32_t serial_putdata(void const* data, uint32_t length)
+{
+	uint32_t i;
+	uint8_t* ptrdata;
+	ptrdata = (uint8_t*) data;
+	for (i = 0; i < length; i++)
+  {
+		serial_putc(*ptrdata);
+		ptrdata++;
+	}
+	return (i);
+}
+
+//Get data from comm. device
+uint32_t serial_getdata(void* data, uint32_t length)
+{
+	uint8_t* ptrdata;
+	ptrdata = (uint8_t*) data;
+	*ptrdata = serial_getc();
+	return (1);
+}
+
+static const uint16_t crc16Table[256]=
+{
+	0x0000,0x1021,0x2042,0x3063,0x4084,0x50a5,0x60c6,0x70e7,
+	0x8108,0x9129,0xa14a,0xb16b,0xc18c,0xd1ad,0xe1ce,0xf1ef,
+	0x1231,0x0210,0x3273,0x2252,0x52b5,0x4294,0x72f7,0x62d6,
+	0x9339,0x8318,0xb37b,0xa35a,0xd3bd,0xc39c,0xf3ff,0xe3de,
+	0x2462,0x3443,0x0420,0x1401,0x64e6,0x74c7,0x44a4,0x5485,
+	0xa56a,0xb54b,0x8528,0x9509,0xe5ee,0xf5cf,0xc5ac,0xd58d,
+	0x3653,0x2672,0x1611,0x0630,0x76d7,0x66f6,0x5695,0x46b4,
+	0xb75b,0xa77a,0x9719,0x8738,0xf7df,0xe7fe,0xd79d,0xc7bc,
+	0x48c4,0x58e5,0x6886,0x78a7,0x0840,0x1861,0x2802,0x3823,
+	0xc9cc,0xd9ed,0xe98e,0xf9af,0x8948,0x9969,0xa90a,0xb92b,
+	0x5af5,0x4ad4,0x7ab7,0x6a96,0x1a71,0x0a50,0x3a33,0x2a12,
+	0xdbfd,0xcbdc,0xfbbf,0xeb9e,0x9b79,0x8b58,0xbb3b,0xab1a,
+	0x6ca6,0x7c87,0x4ce4,0x5cc5,0x2c22,0x3c03,0x0c60,0x1c41,
+	0xedae,0xfd8f,0xcdec,0xddcd,0xad2a,0xbd0b,0x8d68,0x9d49,
+	0x7e97,0x6eb6,0x5ed5,0x4ef4,0x3e13,0x2e32,0x1e51,0x0e70,
+	0xff9f,0xefbe,0xdfdd,0xcffc,0xbf1b,0xaf3a,0x9f59,0x8f78,
+	0x9188,0x81a9,0xb1ca,0xa1eb,0xd10c,0xc12d,0xf14e,0xe16f,
+	0x1080,0x00a1,0x30c2,0x20e3,0x5004,0x4025,0x7046,0x6067,
+	0x83b9,0x9398,0xa3fb,0xb3da,0xc33d,0xd31c,0xe37f,0xf35e,
+	0x02b1,0x1290,0x22f3,0x32d2,0x4235,0x5214,0x6277,0x7256,
+	0xb5ea,0xa5cb,0x95a8,0x8589,0xf56e,0xe54f,0xd52c,0xc50d,
+	0x34e2,0x24c3,0x14a0,0x0481,0x7466,0x6447,0x5424,0x4405,
+	0xa7db,0xb7fa,0x8799,0x97b8,0xe75f,0xf77e,0xc71d,0xd73c,
+	0x26d3,0x36f2,0x0691,0x16b0,0x6657,0x7676,0x4615,0x5634,
+	0xd94c,0xc96d,0xf90e,0xe92f,0x99c8,0x89e9,0xb98a,0xa9ab,
+	0x5844,0x4865,0x7806,0x6827,0x18c0,0x08e1,0x3882,0x28a3,
+	0xcb7d,0xdb5c,0xeb3f,0xfb1e,0x8bf9,0x9bd8,0xabbb,0xbb9a,
+	0x4a75,0x5a54,0x6a37,0x7a16,0x0af1,0x1ad0,0x2ab3,0x3a92,
+	0xfd2e,0xed0f,0xdd6c,0xcd4d,0xbdaa,0xad8b,0x9de8,0x8dc9,
+	0x7c26,0x6c07,0x5c64,0x4c45,0x3ca2,0x2c83,0x1ce0,0x0cc1,
+	0xef1f,0xff3e,0xcf5d,0xdf7c,0xaf9b,0xbfba,0x8fd9,0x9ff8,
+	0x6e17,0x7e36,0x4e55,0x5e74,0x2e93,0x3eb2,0x0ed1,0x1ef0
+};
+
+//*----------------------------------------------------------------------------
+//* \brief Compute the CRC
+//*----------------------------------------------------------------------------
+unsigned short serial_add_crc(char ptr, unsigned short crc)
+{
+	return (crc << 8) ^ crc16Table[((crc >> 8) ^ ptr) & 0xff];
+}
+
+//*----------------------------------------------------------------------------
+//* \brief
+//*----------------------------------------------------------------------------
+static uint16_t getbytes(uint8_t *ptr_data, uint16_t length)
+{
+	uint16_t crc = 0;
+	uint16_t cpt;
+	uint8_t c;
+
+	for (cpt = 0; cpt < length; ++cpt)
+  {
+		c = serial_getc();
+		if (error_timeout)
+			return 1;
+		crc = serial_add_crc(c, crc);
+		//crc = (crc << 8) ^ xcrc16tab[(crc>>8) ^ c];
+		if (size_of_data || mode_of_transfer)
+    {
+			*ptr_data++ = c;
+			if (length == PKTLEN_128)
+				size_of_data--;
+		}
+	}
+
+	return crc;
+}
+
+//*----------------------------------------------------------------------------
+//* \brief Used by Xup to send packets.
+//*----------------------------------------------------------------------------
+static int putPacket(uint8_t *tmppkt, uint8_t sno)
+{
+	uint32_t i;
+	uint16_t chksm;
+	uint8_t data;
+
+	chksm = 0;
+
+	serial_putc(SOH);
+
+	serial_putc(sno);
+	serial_putc((uint8_t) ~(sno));
+
+	for (i = 0; i < PKTLEN_128; i++)
+  {
+		if (size_of_data || mode_of_transfer)
+    {
+			data = *tmppkt++;
+			size_of_data--;
+		}
+    else
+			data = 0x00;
+
+		serial_putc(data);
+
+		//chksm = (chksm<<8) ^ xcrc16tab[(chksm>>8)^data];
+		chksm = serial_add_crc(data, chksm);
+	}
+
+	/* An "endian independent way to extract the CRC bytes. */
+	serial_putc((uint8_t) (chksm >> 8));
+	serial_putc((uint8_t) chksm);
+
+	return (serial_getc()); /* Wait for ack */
+}
+
+//*----------------------------------------------------------------------------
+//* \brief Called when a transfer from target to host is being made (considered
+//*        an upload).
+//*----------------------------------------------------------------------------
+//Send given data (polling) using xmodem (if necessary)
+uint32_t serial_putdata_xmd(void const* data, uint32_t length)
+{
+	uint8_t c, sno = 1;
+	uint8_t done;
+	uint8_t * ptr_data = (uint8_t *) data;
+	error_timeout = 0;
+	if (!length)
+		mode_of_transfer = 1;
+	else
+  {
+		size_of_data = length;
+		mode_of_transfer = 0;
+	}
+
+	if (length & (PKTLEN_128 - 1))
+  {
+		length += PKTLEN_128;
+		length &= ~(PKTLEN_128 - 1);
+	}
+
+	/* Startup synchronization... */
+	/* Wait to receive a NAK or 'C' from receiver. */
+	done = 0;
+	while (!done) {
+		c = (uint8_t) serial_getc();
+		if (error_timeout)
+    { // Test for timeout in serial_getc
+			error_timeout = 0;
+			c = (uint8_t) serial_getc();
+			if (error_timeout)
+      {
+				error_timeout = 0;
+				return (0);
+			}
+		}
+		switch (c)
+    {
+      case NAK:
+        done = 1;
+        // ("CSM");
+			break;
+      case 'C':
+        done = 1;
+        // ("CRC");
+			break;
+      case 'q': /* ELS addition, not part of XMODEM spec. */
+        return (0);
+      default:
+			break;
+		}
+	}
+
+	done = 0;
+	sno = 1;
+	while (!done)
+  {
+		c = (uint8_t) putPacket((uint8_t *) ptr_data, sno);
+		if (error_timeout)
+    { // Test for timeout in serial_getc
+			error_timeout = 0;
+			return (0);
+		}
+		switch (c)
+    {
+      case ACK:
+        ++sno;
+        length -= PKTLEN_128;
+        ptr_data += PKTLEN_128;
+        // ("A");
+			break;
+
+      case NAK:
+        // ("N");
+			break;
+
+      case CAN:
+      case EOT:
+      default:
+        done = 0;
+			break;
+		}
+
+		if (!length)
+    {
+			serial_putc(EOT);
+			serial_getc(); /* Flush the ACK */
+			break;
+		}
+		// ("!");
+	}
+
+	mode_of_transfer = 0;
+	// ("Xup_done.");
+	return (1);
+	//    return(0);
+}
+
+/*----------------------------------------------------------------------------
+ * \brief Used by serial_getdata_xmd to retrieve packets.
+ */
+static uint8_t getPacket(uint8_t *ptr_data, uint8_t sno)
+{
+	uint8_t seq[2];
+	uint16_t crc, xcrc;
+
+	getbytes(seq, 2);
+	xcrc = getbytes(ptr_data, PKTLEN_128);
+	if (error_timeout)
+		return (false);
+
+	/* An "endian independent way to combine the CRC bytes. */
+	crc = (uint16_t) serial_getc() << 8;
+	crc += (uint16_t) serial_getc();
+
+	if (error_timeout == 1)
+		return (false);
+
+	if ((crc != xcrc) || (seq[0] != sno) || (seq[1] != (uint8_t) (~sno)))
+  {
+		serial_putc(CAN);
+		return (false);
+	}
+
+	serial_putc(ACK);
+	return (true);
+}
+
+//*----------------------------------------------------------------------------
+//* \brief Called when a transfer from host to target is being made (considered
+//*        an download).
+//*----------------------------------------------------------------------------
+//Get data from comm. device using xmodem (if necessary)
+uint32_t serial_getdata_xmd(void* data, uint32_t length)
+{
+	uint32_t timeout;
+	char c;
+	uint8_t * ptr_data = (uint8_t *) data;
+	uint32_t b_run, nbr_of_timeout = 100;
+	uint8_t sno = 0x01;
+	uint32_t data_transfered = 0;
+
+	//Copied from legacy source code ... might need some tweaking
+	uint32_t loops_per_second = CPU_FREQUENCY/60;
+
+	error_timeout = 0;
+
+	if (length == 0)
+		mode_of_transfer = 1;
+	else
+  {
+		size_of_data = length;
+		mode_of_transfer = 0;
+	}
+
+	/* Startup synchronization... */
+	/* Continuously send NAK or 'C' until sender responds. */
+	// ("Xdown");
+	while (1)
+  {
+		serial_putc('C');
+		timeout = loops_per_second;
+		while (!(serial_is_rx_ready()) && timeout)
+			timeout--;
+		if (timeout)
+			break;
+
+		if (!(--nbr_of_timeout))
+			return (0);
+//            return -1;
+	}
+
+	b_run = true;
+	// ("Got response");
+	while (b_run != false)
+  {
+		c = (char) serial_getc();
+		if (error_timeout)
+    { // Test for timeout in serial_getc
+			error_timeout = 0;
+			return (0);
+//            return (-1);
+		}
+		switch (c)
+    {
+      case SOH: /* 128-byte incoming packet */
+        // ("O");
+        b_run = getPacket(ptr_data, sno);
+        if (error_timeout)
+        { // Test for timeout in serial_getc
+          error_timeout = 0;
+          return (0);
+  //                return (-1);
+        }
+        if (b_run == true)
+        {
+          ++sno;
+          ptr_data += PKTLEN_128;
+          data_transfered += PKTLEN_128;
+        }
+			break;
+      case EOT: // ("E");
+        serial_putc(ACK);
+        b_run = false;
+			break;
+      case CAN: // ("C");
+      case ESC: /* "X" User-invoked abort */
+      default:
+        b_run = false;
+			break;
+		}
+		// ("!");
+	}
+	mode_of_transfer = 0;
+	return (true);
+//    return(b_run);
+}
+
diff --git a/bootloaders/feather/sam_ba_serial.h b/bootloaders/feather/sam_ba_serial.h
new file mode 100644
index 000000000..cb69f459e
--- /dev/null
+++ b/bootloaders/feather/sam_ba_serial.h
@@ -0,0 +1,143 @@
+/*
+  Copyright (c) 2015 Arduino LLC.  All right reserved.
+  Copyright (c) 2015 Atmel Corporation/Thibaut VIARD.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _SAM_BA_SERIAL_H_
+#define _SAM_BA_SERIAL_H_
+
+#include <stdint.h>
+#include <stdbool.h>
+
+
+/* USART buffer size (must be a power of two) */
+#define USART_BUFFER_SIZE        (128)
+
+/* Define the default time-out value for USART. */
+#define USART_DEFAULT_TIMEOUT    (1000)
+
+/* Xmodem related defines */
+/* CRC16  polynomial */
+#define CRC16POLY                (0x1021)
+
+#define SHARP_CHARACTER          '#'
+
+/* X/Ymodem protocol: */
+#define SOH                      (0x01)
+//#define STX                    (0x02)
+#define EOT                      (0x04)
+#define ACK                      (0x06)
+#define NAK                      (0x15)
+#define CAN                      (0x18)
+#define ESC                      (0x1b)
+
+#define PKTLEN_128               (128)
+
+
+/**
+ * \brief Open the given USART
+ */
+void serial_open(void);
+
+/**
+ * \brief Stops the USART
+ */
+void serial_close(void);
+
+/**
+ * \brief Puts a byte on usart line
+ *
+ * \param value      Value to put
+ *
+ * \return \c 1 if function was successfully done, otherwise \c 0.
+ */
+int serial_putc(int value);
+
+/**
+ * \brief Waits and gets a value on usart line
+ *
+ * \return value read on usart line
+ */
+int serial_getc(void);
+
+/**
+ * \brief Returns true if the SAM-BA Uart received the sharp char
+ *
+ * \return Returns true if the SAM-BA Uart received the sharp char
+ */
+int serial_sharp_received(void);
+
+/**
+ * \brief This function checks if a character has been received on the usart line
+ *
+ * \return \c 1 if a byte is ready to be read.
+ */
+bool serial_is_rx_ready(void);
+
+/**
+ * \brief Gets a value on usart line
+ *
+ * \return value read on usart line
+ */
+int serial_readc(void);
+
+/**
+ * \brief Send buffer on usart line
+ *
+ * \param data pointer
+ * \param number of data to send
+ * \return number of data sent
+ */
+uint32_t serial_putdata(void const* data, uint32_t length); //Send given data (polling)
+
+/**
+ * \brief Gets data from usart line
+ *
+ * \param data pointer
+ * \param number of data to get
+ * \return value read on usart line
+ */
+uint32_t serial_getdata(void* data, uint32_t length); //Get data from comm. device
+
+/**
+ * \brief Send buffer on usart line using Xmodem protocol
+ *
+ * \param data pointer
+ * \param number of data to send
+ * \return number of data sent
+ */
+uint32_t serial_putdata_xmd(void const* data, uint32_t length); //Send given data (polling) using xmodem (if necessary)
+
+/**
+ * \brief Gets data from usart line using Xmodem protocol
+ *
+ * \param data pointer
+ * \param number of data to get
+ * \return value read on usart line
+ */
+uint32_t serial_getdata_xmd(void* data, uint32_t length); //Get data from comm. device using xmodem (if necessary)
+
+/**
+ * \brief Compute the CRC
+ *
+ * \param Char to add to CRC
+ * \param Previous CRC
+ * \return The new computed CRC
+ */
+unsigned short serial_add_crc(char c, unsigned short crc);
+
+#endif // _SAM_BA_SERIAL_H_
diff --git a/bootloaders/feather/sam_ba_usb.c b/bootloaders/feather/sam_ba_usb.c
new file mode 100644
index 000000000..71caa4ba4
--- /dev/null
+++ b/bootloaders/feather/sam_ba_usb.c
@@ -0,0 +1,488 @@
+/*
+  Copyright (c) 2015 Arduino LLC.  All right reserved.
+  Copyright (c) 2015 Atmel Corporation/Thibaut VIARD.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include <stdint.h>
+#include <string.h>
+#include "sam_ba_usb.h"
+#include "board_driver_usb.h"
+#include "sam_ba_cdc.h"
+
+/* This data array will be copied into SRAM as its length is inferior to 64 bytes,
+ * and so can stay in flash.
+ */
+static __attribute__((__aligned__(4)))
+const char devDescriptor[] =
+{
+  /* Device descriptor */
+  0x12,   // bLength
+  0x01,   // bDescriptorType
+  0x00,   // bcdUSB L
+  0x02,   // bcdUSB H
+  0x02,   // bDeviceClass:    CDC class code
+  0x00,   // bDeviceSubclass: CDC class sub code
+  0x00,   // bDeviceProtocol: CDC Device protocol
+  0x40,   // bMaxPacketSize0
+  USB_VID_LOW,   // idVendor L
+  USB_VID_HIGH,   // idVendor H
+  USB_PID_LOW,   // idProduct L
+  USB_PID_HIGH,  // idProduct H
+  0x00,   // bcdDevice L, here matching SAM-BA version
+  0x02,   // bcdDevice H
+#if 0 // TODO: pending validation
+  STRING_INDEX_MANUFACTURER,   // iManufacturer
+  STRING_INDEX_PRODUCT,        // iProduct
+#else
+  0x00,   // iManufacturer
+  0x00,   // iProduct
+#endif // 0
+  0x00,   // SerialNumber, should be based on product unique ID
+  0x01    // bNumConfigs
+};
+
+/* This data array will be consumed directly by USB_Write() and must be in SRAM.
+ * We cannot send data from product internal flash.
+ */
+static __attribute__((__aligned__(4)))
+char cfgDescriptor[] =
+{
+  /* ============== CONFIGURATION 1 =========== */
+  /* Configuration 1 descriptor */
+  0x09,   // CbLength
+  0x02,   // CbDescriptorType
+  0x43,   // CwTotalLength 2 EP + Control
+  0x00,
+  0x02,   // CbNumInterfaces
+  0x01,   // CbConfigurationValue
+  0x00,   // CiConfiguration
+  0x80,   // CbmAttributes Bus powered without remote wakeup: 0x80, Self powered without remote wakeup: 0xc0
+  0x32,   // CMaxPower, report using 100mA, enough for a bootloader
+
+  /* Communication Class Interface Descriptor Requirement */
+  0x09, // bLength
+  0x04, // bDescriptorType
+  0x00, // bInterfaceNumber
+  0x00, // bAlternateSetting
+  0x01, // bNumEndpoints
+  0x02, // bInterfaceClass
+  0x02, // bInterfaceSubclass
+  0x00, // bInterfaceProtocol
+  0x00, // iInterface
+
+  /* Header Functional Descriptor */
+  0x05, // bFunction Length
+  0x24, // bDescriptor type: CS_INTERFACE
+  0x00, // bDescriptor subtype: Header Func Desc
+  0x10, // bcdCDC:1.1
+  0x01,
+
+  /* ACM Functional Descriptor */
+  0x04, // bFunctionLength
+  0x24, // bDescriptor Type: CS_INTERFACE
+  0x02, // bDescriptor Subtype: ACM Func Desc
+  0x00, // bmCapabilities
+
+  /* Union Functional Descriptor */
+  0x05, // bFunctionLength
+  0x24, // bDescriptorType: CS_INTERFACE
+  0x06, // bDescriptor Subtype: Union Func Desc
+  0x00, // bMasterInterface: Communication Class Interface
+  0x01, // bSlaveInterface0: Data Class Interface
+
+  /* Call Management Functional Descriptor */
+  0x05, // bFunctionLength
+  0x24, // bDescriptor Type: CS_INTERFACE
+  0x01, // bDescriptor Subtype: Call Management Func Desc
+  0x00, // bmCapabilities: D1 + D0
+  0x01, // bDataInterface: Data Class Interface 1
+
+  /* Endpoint 1 descriptor */
+  0x07,   // bLength
+  0x05,   // bDescriptorType
+  0x83,   // bEndpointAddress, Endpoint 03 - IN
+  0x03,   // bmAttributes      INT
+  0x08,   // wMaxPacketSize
+  0x00,
+  0xFF,   // bInterval
+
+  /* Data Class Interface Descriptor Requirement */
+  0x09, // bLength
+  0x04, // bDescriptorType
+  0x01, // bInterfaceNumber
+  0x00, // bAlternateSetting
+  0x02, // bNumEndpoints
+  0x0A, // bInterfaceClass
+  0x00, // bInterfaceSubclass
+  0x00, // bInterfaceProtocol
+  0x00, // iInterface
+
+  /* First alternate setting */
+  /* Endpoint 1 descriptor */
+  0x07,   // bLength
+  0x05,   // bDescriptorType
+  0x81,   // bEndpointAddress, Endpoint 01 - IN
+  0x02,   // bmAttributes      BULK
+  USB_EP_IN_SIZE,   // wMaxPacketSize
+  0x00,
+  0x00,   // bInterval
+
+  /* Endpoint 2 descriptor */
+  0x07,   // bLength
+  0x05,   // bDescriptorType
+  0x02,   // bEndpointAddress, Endpoint 02 - OUT
+  0x02,   // bmAttributes      BULK
+  USB_EP_OUT_SIZE,   // wMaxPacketSize
+  0x00,
+  0x00    // bInterval
+};
+
+#ifndef STRING_MANUFACTURER
+#  define STRING_MANUFACTURER "Arduino LLC"
+#endif
+
+#ifndef STRING_PRODUCT
+#  define STRING_PRODUCT "Arduino Zero"
+#endif
+
+USB_CDC sam_ba_cdc;
+
+/*----------------------------------------------------------------------------
+ * \brief This function is a callback invoked when a SETUP packet is received
+ */
+void sam_ba_usb_CDC_Enumerate(P_USB_CDC pCdc)
+{
+  Usb *pUsb = pCdc->pUsb;
+  static volatile uint8_t bmRequestType, bRequest, dir;
+  static volatile uint16_t wValue, wIndex, wLength, wStatus;
+
+  /* Clear the Received Setup flag */
+  pUsb->DEVICE.DeviceEndpoint[0].EPINTFLAG.bit.RXSTP = true;
+
+  /* Read the USB request parameters */
+  bmRequestType = udd_ep_out_cache_buffer[0][0];
+  bRequest      = udd_ep_out_cache_buffer[0][1];
+  wValue        = (udd_ep_out_cache_buffer[0][2] & 0xFF);
+  wValue       |= (udd_ep_out_cache_buffer[0][3] << 8);
+  wIndex        = (udd_ep_out_cache_buffer[0][4] & 0xFF);
+  wIndex       |= (udd_ep_out_cache_buffer[0][5] << 8);
+  wLength       = (udd_ep_out_cache_buffer[0][6] & 0xFF);
+  wLength      |= (udd_ep_out_cache_buffer[0][7] << 8);
+
+  /* Clear the Bank 0 ready flag on Control OUT */
+  pUsb->DEVICE.DeviceEndpoint[0].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_BK0RDY;
+
+  /* Handle supported standard device request Cf Table 9-3 in USB specification Rev 1.1 */
+  switch ((bRequest << 8) | bmRequestType)
+  {
+    case STD_GET_DESCRIPTOR:
+      if (wValue>>8 == STD_GET_DESCRIPTOR_DEVICE)
+      {
+        /* Return Device Descriptor */
+        USB_Write(pCdc->pUsb, devDescriptor, SAM_BA_MIN(sizeof(devDescriptor), wLength), USB_EP_CTRL);
+      }
+      else
+      {
+        if (wValue>>8 == STD_GET_DESCRIPTOR_CONFIGURATION)
+        {
+          /* Return Configuration Descriptor */
+          USB_Write(pCdc->pUsb, cfgDescriptor, SAM_BA_MIN(sizeof(cfgDescriptor), wLength), USB_EP_CTRL);
+        }
+        else
+        {
+#if 0 // TODO: pending validation
+          if (wValue>>8 == STD_GET_DESCRIPTOR_STRING)
+          {
+            switch ( wValue & 0xff )
+            {
+              case STRING_INDEX_LANGUAGES:
+                uint16_t STRING_LANGUAGE[2] = { (STD_GET_DESCRIPTOR_STRING<<8) | 4, 0x0409 };
+
+                USB_Write(pCdc->pUsb, (const char*)STRING_LANGUAGE, SAM_BA_MIN(sizeof(STRING_LANGUAGE), wLength), USB_EP_CTRL);
+              break;
+
+              case STRING_INDEX_MANUFACTURER:
+                USB_SendString(pCdc->pUsb, STRING_MANUFACTURER, strlen(STRING_MANUFACTURER), wLength );
+              break;
+
+              case STRING_INDEX_PRODUCT:
+                USB_SendString(pCdc->pUsb, STRING_PRODUCT, strlen(STRING_PRODUCT), wLength );
+              break;
+              default:
+                /* Stall the request */
+                USB_SendStall(pUsb, true);
+              break;
+            }
+          }
+          else
+#endif // 0
+          {
+            /* Stall the request */
+            USB_SendStall(pUsb, true);
+          }
+        }
+      }
+    break;
+
+    case STD_SET_ADDRESS:
+      /* Send ZLP */
+      USB_SendZlp(pUsb);
+      /* Set device address to the newly received address from host */
+      USB_SetAddress(pCdc->pUsb, wValue);
+    break;
+
+    case STD_SET_CONFIGURATION:
+      /* Store configuration */
+      pCdc->currentConfiguration = (uint8_t)wValue;
+
+      /* Send ZLP */
+      USB_SendZlp(pUsb);
+
+      /* Configure the 3 needed endpoints */
+      USB_Configure(pUsb);
+    break;
+
+    case STD_GET_CONFIGURATION:
+      /* Return current configuration value */
+      USB_Write(pCdc->pUsb, (char *) &(pCdc->currentConfiguration), sizeof(pCdc->currentConfiguration), USB_EP_CTRL);
+    break;
+
+    case STD_GET_STATUS_ZERO:
+      wStatus = 0;
+      USB_Write(pCdc->pUsb, (char *) &wStatus, sizeof(wStatus), USB_EP_CTRL);
+    break;
+
+    case STD_GET_STATUS_INTERFACE:
+      wStatus = 0;
+      USB_Write(pCdc->pUsb, (char *) &wStatus, sizeof(wStatus), USB_EP_CTRL);
+    break;
+
+    case STD_GET_STATUS_ENDPOINT:
+      wStatus = 0;
+      dir = wIndex & 80;
+      wIndex &= 0x0F;
+      if (wIndex <= 3)
+      {
+        if (dir)
+        {
+#ifdef __SAMR21G18A__
+          wStatus = (pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUS.reg & USB_DEVICE_EPSTATUSSET_STALLRQ1) ? 1 : 0;
+#else
+          wStatus = (pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUS.bit.STALLRQ & (1<<1)) ? 1 : 0;
+#endif
+        }
+        else
+        {
+#ifdef __SAMR21G18A__
+          wStatus = (pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUS.reg & USB_DEVICE_EPSTATUSSET_STALLRQ0) ? 1 : 0;
+#else
+          wStatus = (pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUS.bit.STALLRQ & (1<<0)) ? 1 : 0;
+#endif
+        }
+        /* Return current status of endpoint */
+        USB_Write(pCdc->pUsb, (char *) &wStatus, sizeof(wStatus), USB_EP_CTRL);
+      }
+      else
+      {
+        /* Stall the request */
+        USB_SendStall(pUsb, true);
+      }
+    break;
+
+    case STD_SET_FEATURE_ZERO:
+      /* Stall the request */
+      USB_SendStall(pUsb, true);
+    break;
+
+    case STD_SET_FEATURE_INTERFACE:
+      /* Send ZLP */
+      USB_SendZlp(pUsb);
+    break;
+
+    case STD_SET_FEATURE_ENDPOINT:
+      dir = wIndex & 0x80;
+      wIndex &= 0x0F;
+      if ((wValue == 0) && wIndex && (wIndex <= 3))
+      {
+        /* Set STALL request for the endpoint */
+        if (dir)
+        {
+#ifdef __SAMR21G18A__
+          pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUSSET.reg = USB_DEVICE_EPSTATUSSET_STALLRQ1;
+#else
+          pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUSSET.bit.STALLRQ = (1<<1);
+#endif
+        }
+        else
+        {
+#ifdef __SAMR21G18A__
+          pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUSSET.reg = USB_DEVICE_EPSTATUSSET_STALLRQ0;
+#else
+          pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUSSET.bit.STALLRQ = (1<<0);
+#endif
+        }
+
+        /* Send ZLP */
+        USB_SendZlp(pUsb);
+      }
+      else
+      {
+        /* Stall the request */
+        USB_SendStall(pUsb, true);
+      }
+    break;
+
+    case STD_SET_INTERFACE:
+    case STD_CLEAR_FEATURE_ZERO:
+      /* Stall the request */
+      USB_SendStall(pUsb, true);
+    break;
+
+    case STD_CLEAR_FEATURE_INTERFACE:
+      /* Send ZLP */
+      USB_SendZlp(pUsb);
+    break;
+
+    case STD_CLEAR_FEATURE_ENDPOINT:
+      dir = wIndex & 0x80;
+      wIndex &= 0x0F;
+
+      if ((wValue == 0) && wIndex && (wIndex <= 3))
+      {
+        if (dir)
+        {
+#ifdef __SAMR21G18A__
+          if (pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUS.bit.STALLRQ1)
+          {
+            // Remove stall request
+            pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_STALLRQ1;
+            if (pUsb->DEVICE.DeviceEndpoint[wIndex].EPINTFLAG.bit.STALL1)
+            {
+              pUsb->DEVICE.DeviceEndpoint[wIndex].EPINTFLAG.bit.STALL1 = 1;
+#else
+
+          if (pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUS.bit.STALLRQ & (1<<1))
+          {
+            // Remove stall request
+            pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUSCLR.bit.STALLRQ = (1<<1);
+            if (pUsb->DEVICE.DeviceEndpoint[wIndex].EPINTFLAG.bit.STALL & (1<<1))
+            {
+              pUsb->DEVICE.DeviceEndpoint[wIndex].EPINTFLAG.bit.STALL = (1<<1);
+#endif
+              // The Stall has occurred, then reset data toggle
+              pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSSET_DTGLIN;
+            }
+          }
+        }
+        else
+        {
+#ifdef __SAMR21G18A__
+          if (pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUS.bit.STALLRQ0)
+          {
+            // Remove stall request
+            pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_STALLRQ0;
+            if (pUsb->DEVICE.DeviceEndpoint[wIndex].EPINTFLAG.bit.STALL0)
+            {
+              pUsb->DEVICE.DeviceEndpoint[wIndex].EPINTFLAG.bit.STALL0 = 1;
+#else
+          if (pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUS.bit.STALLRQ & (1<<0))
+          {
+            // Remove stall request
+            //pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_STALLRQ0;
+            pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUSCLR.bit.STALLRQ = (1<<0);
+            if (pUsb->DEVICE.DeviceEndpoint[wIndex].EPINTFLAG.bit.STALL & (1<<0))
+            {
+              pUsb->DEVICE.DeviceEndpoint[wIndex].EPINTFLAG.bit.STALL = (1<<0);
+#endif
+              // The Stall has occurred, then reset data toggle
+              pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSSET_DTGLOUT;
+            }
+          }
+        }
+        /* Send ZLP */
+        USB_SendZlp(pUsb);
+      }
+      else
+      {
+        USB_SendStall(pUsb, true);
+      }
+    break;
+
+    // handle CDC class requests
+    case SET_LINE_CODING:
+      /* Send ZLP */
+      USB_SendZlp(pUsb);
+    break;
+
+    case GET_LINE_CODING:
+      /* Send current line coding */
+      USB_Write(pCdc->pUsb, (char *) &line_coding, SAM_BA_MIN(sizeof(usb_cdc_line_coding_t), wLength), USB_EP_CTRL);
+    break;
+
+    case SET_CONTROL_LINE_STATE:
+      /* Store the current connection */
+      pCdc->currentConnection = wValue;
+      /* Send ZLP */
+      USB_SendZlp(pUsb);
+    break;
+
+    default:
+      /* Stall the request */
+      USB_SendStall(pUsb, true);
+    break;
+  }
+}
+
+/*----------------------------------------------------------------------------
+ * \brief
+ */
+P_USB_CDC usb_init(void)
+{
+  sam_ba_cdc.pUsb = USB;
+
+  /* Initialize USB */
+  USB_Init();
+  /* Get the default CDC structure settings */
+  USB_Open(&sam_ba_cdc, sam_ba_cdc.pUsb);
+
+  return &sam_ba_cdc;
+}
+
+#if 0 // TODO: pending validation
+/*----------------------------------------------------------------------------
+ * \brief Send a USB descriptor string.
+ *
+ * The input string is plain ASCII but is sent out as UTF-16 with the correct 2-byte prefix.
+ */
+uint32_t USB_SendString(Usb *pUsb, const char* ascii_string, uint8_t length, uint8_t maxLength)
+{
+  uint8_t string_descriptor[255]; // Max USB-allowed string length
+  uint16_t* unicode_string=(uint16_t*)(string_descriptor+2); // point on 3 bytes of descriptor
+
+  int resulting_length = 1;
+
+  for ( ; *ascii_string && (length>=0) && (resulting_length<(maxLength>>1)) ; ascii_string++, length--, resulting_length++ )
+  {
+    *unicode_string++ = (uint16_t)(*ascii_string);
+  }
+
+  string_descriptor[0] = (resulting_length<<1);
+  string_descriptor[1] = STD_GET_DESCRIPTOR_STRING;
+
+  return USB_Write(pUsb, (const char*)unicode_string, resulting_length, USB_EP_CTRL);
+}
+#endif // 0
diff --git a/bootloaders/feather/sam_ba_usb.h b/bootloaders/feather/sam_ba_usb.h
new file mode 100644
index 000000000..42c0d608f
--- /dev/null
+++ b/bootloaders/feather/sam_ba_usb.h
@@ -0,0 +1,107 @@
+/*
+  Copyright (c) 2015 Arduino LLC.  All right reserved.
+  Copyright (c) 2015 Atmel Corporation/Thibaut VIARD.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef CDC_ENUMERATE_H
+#define CDC_ENUMERATE_H
+
+#include <sam.h>
+#include <stdbool.h>
+
+#define USB_EP_CTRL             (0u)
+#define USB_EP_OUT              (2u)
+#define USB_EP_OUT_SIZE         (0x40u)
+#define USB_EP_IN               (1u)
+#define USB_EP_IN_SIZE          (0x40u)
+#define USB_EP_COMM             (3u)
+#define MAX_EP                  (4u)
+
+/* USB standard request code */
+#define STD_GET_STATUS_ZERO            (0x0080u)
+#define STD_GET_STATUS_INTERFACE       (0x0081u)
+#define STD_GET_STATUS_ENDPOINT        (0x0082u)
+
+#define STD_CLEAR_FEATURE_ZERO         (0x0100u)
+#define STD_CLEAR_FEATURE_INTERFACE    (0x0101u)
+#define STD_CLEAR_FEATURE_ENDPOINT     (0x0102u)
+
+#define STD_SET_FEATURE_ZERO           (0x0300u)
+#define STD_SET_FEATURE_INTERFACE      (0x0301u)
+#define STD_SET_FEATURE_ENDPOINT       (0x0302u)
+
+#define STD_SET_ADDRESS                (0x0500u)
+#define STD_GET_DESCRIPTOR             (0x0680u)
+#define STD_SET_DESCRIPTOR             (0x0700u)
+#define STD_GET_CONFIGURATION          (0x0880u)
+#define STD_SET_CONFIGURATION          (0x0900u)
+#define STD_GET_INTERFACE              (0x0A81u)
+#define STD_SET_INTERFACE              (0x0B01u)
+#define STD_SYNCH_FRAME                (0x0C82u)
+
+#define STD_GET_DESCRIPTOR_DEVICE                          (1u)
+#define STD_GET_DESCRIPTOR_CONFIGURATION                   (2u)
+#define STD_GET_DESCRIPTOR_STRING                          (3u)
+#define STD_GET_DESCRIPTOR_INTERFACE                       (4u)
+#define STD_GET_DESCRIPTOR_ENDPOINT                        (5u)
+#define STD_GET_DESCRIPTOR_DEVICE_QUALIFIER                (6u)
+#define STD_GET_DESCRIPTOR_OTHER_SPEED_CONFIGURATION       (7u)
+#define STD_GET_DESCRIPTOR_INTERFACE_POWER1                (8u)
+
+#define FEATURE_ENDPOINT_HALT          (0u)
+#define FEATURE_DEVICE_REMOTE_WAKEUP   (1u)
+#define FEATURE_TEST_MODE              (2u)
+
+#if 0 // TODO: pending validation
+#define STRING_INDEX_LANGUAGES         (0x00u)
+#define STRING_INDEX_MANUFACTURER      (0x01u)
+#define STRING_INDEX_PRODUCT           (0x02u)
+#endif // 0
+
+#define SAM_BA_MIN(a, b) (((a) < (b)) ? (a) : (b))
+
+
+typedef struct _USB_CDC
+{
+	// Private members
+	Usb *pUsb;
+	uint8_t currentConfiguration;
+	uint8_t currentConnection;
+	// Public Methods:
+	uint8_t (*IsConfigured)(struct _USB_CDC *pCdc);
+//	uint32_t (*Write) (Usb *pUsb, const char *pData, uint32_t length, uint8_t ep_num);
+//	uint32_t (*Read)  (Usb *pUsb, char *pData, uint32_t length);
+} USB_CDC, *P_USB_CDC;
+
+/**
+ * \brief Initializes the USB module
+ *
+ * \return Pointer to the USB CDC structure
+ */
+P_USB_CDC usb_init(void);
+
+void sam_ba_usb_CDC_Enumerate(P_USB_CDC pCdc);
+
+#if 0 // TODO: pending validation
+uint32_t USB_SendString(Usb *pUsb, const char* ascii_string, uint8_t length, uint8_t maxLength);
+#endif // 0
+
+extern USB_CDC sam_ba_cdc;
+
+
+
+#endif // CDC_ENUMERATE_H
diff --git a/bootloaders/feather/samd21_sam_ba.atsln b/bootloaders/feather/samd21_sam_ba.atsln
new file mode 100644
index 000000000..cf1043181
--- /dev/null
+++ b/bootloaders/feather/samd21_sam_ba.atsln
@@ -0,0 +1,22 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Atmel Studio Solution File, Format Version 11.00
+VisualStudioVersion = 14.0.23107.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{54F91283-7BC4-4236-8FF9-10F437C3AD48}") = "samd21_sam_ba", "samd21_sam_ba.cproj", "{DCE6C7E3-EE26-4D79-826B-08594B9AD897}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|ARM = Debug|ARM
+		Release|ARM = Release|ARM
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{DCE6C7E3-EE26-4D79-826B-08594B9AD897}.Debug|ARM.ActiveCfg = Debug|ARM
+		{DCE6C7E3-EE26-4D79-826B-08594B9AD897}.Debug|ARM.Build.0 = Debug|ARM
+		{DCE6C7E3-EE26-4D79-826B-08594B9AD897}.Release|ARM.ActiveCfg = Release|ARM
+		{DCE6C7E3-EE26-4D79-826B-08594B9AD897}.Release|ARM.Build.0 = Release|ARM
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
diff --git a/bootloaders/feather/samd21_sam_ba.bin b/bootloaders/feather/samd21_sam_ba.bin
new file mode 100644
index 000000000..331adde78
Binary files /dev/null and b/bootloaders/feather/samd21_sam_ba.bin differ
diff --git a/bootloaders/feather/samd21_sam_ba.cproj b/bootloaders/feather/samd21_sam_ba.cproj
new file mode 100644
index 000000000..70ee7e93a
--- /dev/null
+++ b/bootloaders/feather/samd21_sam_ba.cproj
@@ -0,0 +1,218 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="14.0">
+  <PropertyGroup>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectVersion>7.0</ProjectVersion>
+    <ToolchainName>com.Atmel.ARMGCC.C</ToolchainName>
+    <ProjectGuid>dce6c7e3-ee26-4d79-826b-08594b9ad897</ProjectGuid>
+    <avrdevice>ATSAMD21G18A</avrdevice>
+    <avrdeviceseries>none</avrdeviceseries>
+    <OutputType>Executable</OutputType>
+    <Language>C</Language>
+    <OutputFileName>$(MSBuildProjectName)</OutputFileName>
+    <OutputFileExtension>.elf</OutputFileExtension>
+    <OutputDirectory>$(MSBuildProjectDirectory)\$(Configuration)</OutputDirectory>
+    <AssemblyName>samd21_sam_ba</AssemblyName>
+    <Name>samd21_sam_ba</Name>
+    <RootNamespace>samd21_sam_ba</RootNamespace>
+    <ToolchainFlavour>Native</ToolchainFlavour>
+    <KeepTimersRunning>true</KeepTimersRunning>
+    <OverrideVtor>false</OverrideVtor>
+    <CacheFlash>true</CacheFlash>
+    <ProgFlashFromRam>true</ProgFlashFromRam>
+    <RamSnippetAddress>0x20000000</RamSnippetAddress>
+    <UncachedRange />
+    <preserveEEPROM>true</preserveEEPROM>
+    <OverrideVtorValue>exception_table</OverrideVtorValue>
+    <BootSegment>2</BootSegment>
+    <eraseonlaunchrule>0</eraseonlaunchrule>
+    <ExternalProgrammingToolCommand />
+    <AsfFrameworkConfig>
+      <framework-data xmlns="">
+        <options />
+        <configurations />
+        <files />
+        <documentation help="" />
+        <offline-documentation help="" />
+        <dependencies>
+          <content-extension eid="atmel.asf" uuidref="Atmel.ASF" version="3.27.3" />
+        </dependencies>
+      </framework-data>
+    </AsfFrameworkConfig>
+    <avrtool>com.atmel.avrdbg.tool.atmelice</avrtool>
+    <avrtoolserialnumber>J41800001895</avrtoolserialnumber>
+    <avrdeviceexpectedsignature>0x10010000</avrdeviceexpectedsignature>
+    <avrtoolinterface>SWD</avrtoolinterface>
+    <com_atmel_avrdbg_tool_atmelice>
+      <ToolOptions>
+        <InterfaceProperties>
+          <SwdClock>2000000</SwdClock>
+        </InterfaceProperties>
+        <InterfaceName>SWD</InterfaceName>
+      </ToolOptions>
+      <ToolType>com.atmel.avrdbg.tool.atmelice</ToolType>
+      <ToolNumber>J41800001895</ToolNumber>
+      <ToolName>Atmel-ICE</ToolName>
+    </com_atmel_avrdbg_tool_atmelice>
+    <avrtoolinterfaceclock>2000000</avrtoolinterfaceclock>
+    <com_atmel_avrdbg_tool_edbg>
+      <ToolOptions>
+        <InterfaceProperties>
+        </InterfaceProperties>
+        <InterfaceName>SWD</InterfaceName>
+      </ToolOptions>
+      <ToolType>com.atmel.avrdbg.tool.edbg</ToolType>
+      <ToolNumber>ATML2320040200000259</ToolNumber>
+      <ToolName>EDBG</ToolName>
+    </com_atmel_avrdbg_tool_edbg>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
+    <ToolchainSettings>
+      <ArmGcc>
+  <armgcc.common.outputfiles.hex>True</armgcc.common.outputfiles.hex>
+  <armgcc.common.outputfiles.lss>True</armgcc.common.outputfiles.lss>
+  <armgcc.common.outputfiles.eep>True</armgcc.common.outputfiles.eep>
+  <armgcc.common.outputfiles.bin>True</armgcc.common.outputfiles.bin>
+  <armgcc.common.outputfiles.srec>True</armgcc.common.outputfiles.srec>
+  <armgcc.compiler.symbols.DefSymbols>
+    <ListValues>
+      <Value>NDEBUG</Value>
+    </ListValues>
+  </armgcc.compiler.symbols.DefSymbols>
+  <armgcc.compiler.optimization.level>Optimize for size (-Os)</armgcc.compiler.optimization.level>
+  <armgcc.compiler.optimization.PrepareFunctionsForGarbageCollection>True</armgcc.compiler.optimization.PrepareFunctionsForGarbageCollection>
+  <armgcc.compiler.warnings.AllWarnings>True</armgcc.compiler.warnings.AllWarnings>
+  <armgcc.linker.libraries.Libraries>
+    <ListValues>
+      <Value>libm</Value>
+    </ListValues>
+  </armgcc.linker.libraries.Libraries>
+  <armgcc.linker.optimization.GarbageCollectUnusedSections>True</armgcc.linker.optimization.GarbageCollectUnusedSections>
+  <armgcc.linker.miscellaneous.LinkerFlags>-Tsamd21j18a_flash.ld</armgcc.linker.miscellaneous.LinkerFlags>
+</ArmGcc>
+    </ToolchainSettings>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
+    <ToolchainSettings>
+      <ArmGcc>
+  <armgcc.common.outputfiles.hex>True</armgcc.common.outputfiles.hex>
+  <armgcc.common.outputfiles.lss>True</armgcc.common.outputfiles.lss>
+  <armgcc.common.outputfiles.eep>True</armgcc.common.outputfiles.eep>
+  <armgcc.common.outputfiles.bin>True</armgcc.common.outputfiles.bin>
+  <armgcc.common.outputfiles.srec>True</armgcc.common.outputfiles.srec>
+  <armgcc.compiler.symbols.DefSymbols>
+    <ListValues>
+      <Value>DEBUG</Value>
+    </ListValues>
+  </armgcc.compiler.symbols.DefSymbols>
+  <armgcc.compiler.optimization.level>Optimize (-O1)</armgcc.compiler.optimization.level>
+  <armgcc.compiler.optimization.PrepareFunctionsForGarbageCollection>True</armgcc.compiler.optimization.PrepareFunctionsForGarbageCollection>
+  <armgcc.compiler.optimization.DebugLevel>Maximum (-g3)</armgcc.compiler.optimization.DebugLevel>
+  <armgcc.compiler.warnings.AllWarnings>True</armgcc.compiler.warnings.AllWarnings>
+  <armgcc.linker.libraries.Libraries>
+    <ListValues>
+      <Value>libm</Value>
+    </ListValues>
+  </armgcc.linker.libraries.Libraries>
+  <armgcc.linker.optimization.GarbageCollectUnusedSections>True</armgcc.linker.optimization.GarbageCollectUnusedSections>
+  <armgcc.linker.miscellaneous.LinkerFlags>-Tsamd21j18a_flash.ld</armgcc.linker.miscellaneous.LinkerFlags>
+  <armgcc.assembler.debugging.DebugLevel>Default (-g)</armgcc.assembler.debugging.DebugLevel>
+  <armgcc.preprocessingassembler.debugging.DebugLevel>Default (-Wa,-g)</armgcc.preprocessingassembler.debugging.DebugLevel>
+</ArmGcc>
+    </ToolchainSettings>
+    <UsesExternalMakeFile>True</UsesExternalMakeFile>
+    <OutputDirectory />
+    <BuildTarget>DEBUG=1 all</BuildTarget>
+    <CleanTarget>clean</CleanTarget>
+    <ExternalMakeFilePath>Makefile</ExternalMakeFilePath>
+  </PropertyGroup>
+  <ItemGroup>
+    <Compile Include="board_definitions.h">
+      <SubType>compile</SubType>
+      <Link>board_definitions.h</Link>
+    </Compile>
+    <Compile Include="board_driver_led.c">
+      <SubType>compile</SubType>
+      <Link>board_driver_led.c</Link>
+    </Compile>
+    <Compile Include="board_driver_led.h">
+      <SubType>compile</SubType>
+      <Link>board_driver_led.h</Link>
+    </Compile>
+    <Compile Include="board_driver_serial.c">
+      <SubType>compile</SubType>
+      <Link>board_driver_serial.c</Link>
+    </Compile>
+    <Compile Include="board_driver_serial.h">
+      <SubType>compile</SubType>
+      <Link>board_driver_serial.h</Link>
+    </Compile>
+    <Compile Include="board_driver_usb.c">
+      <SubType>compile</SubType>
+      <Link>board_driver_usb.c</Link>
+    </Compile>
+    <Compile Include="board_driver_usb.h">
+      <SubType>compile</SubType>
+      <Link>board_driver_usb.h</Link>
+    </Compile>
+    <Compile Include="board_init.c">
+      <SubType>compile</SubType>
+      <Link>board_init.c</Link>
+    </Compile>
+    <Compile Include="board_startup.c">
+      <SubType>compile</SubType>
+      <Link>board_startup.c</Link>
+    </Compile>
+    <Compile Include="main.c">
+      <SubType>compile</SubType>
+      <Link>main.c</Link>
+    </Compile>
+    <Compile Include="sam_ba_cdc.c">
+      <SubType>compile</SubType>
+      <Link>sam_ba_cdc.c</Link>
+    </Compile>
+    <Compile Include="sam_ba_cdc.h">
+      <SubType>compile</SubType>
+      <Link>sam_ba_cdc.h</Link>
+    </Compile>
+    <Compile Include="sam_ba_monitor.c">
+      <SubType>compile</SubType>
+      <Link>sam_ba_monitor.c</Link>
+    </Compile>
+    <Compile Include="sam_ba_monitor.h">
+      <SubType>compile</SubType>
+      <Link>sam_ba_monitor.h</Link>
+    </Compile>
+    <Compile Include="sam_ba_serial.c">
+      <SubType>compile</SubType>
+      <Link>sam_ba_serial.c</Link>
+    </Compile>
+    <Compile Include="sam_ba_serial.h">
+      <SubType>compile</SubType>
+      <Link>sam_ba_serial.h</Link>
+    </Compile>
+    <Compile Include="sam_ba_usb.c">
+      <SubType>compile</SubType>
+      <Link>sam_ba_usb.c</Link>
+    </Compile>
+    <Compile Include="sam_ba_usb.h">
+      <SubType>compile</SubType>
+      <Link>sam_ba_usb.h</Link>
+    </Compile>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Makefile">
+      <SubType>compile</SubType>
+      <Link>Makefile</Link>
+    </None>
+    <None Include="README.md">
+      <SubType>compile</SubType>
+      <Link>README.md</Link>
+    </None>
+    <None Include="bootloader_samd21x18.ld">
+      <SubType>compile</SubType>
+      <Link>bootloader_samd21x18.ld</Link>
+    </None>
+  </ItemGroup>
+  <Import Project="$(AVRSTUDIO_EXE_PATH)\\Vs\\Compiler.targets" />
+</Project>
\ No newline at end of file
diff --git a/bootloaders/feather/samd21_sam_ba.elf b/bootloaders/feather/samd21_sam_ba.elf
new file mode 100644
index 000000000..edee94811
Binary files /dev/null and b/bootloaders/feather/samd21_sam_ba.elf differ
diff --git a/bootloaders/feather/samd21_sam_ba.hex b/bootloaders/feather/samd21_sam_ba.hex
new file mode 100644
index 000000000..5ae649d9d
--- /dev/null
+++ b/bootloaders/feather/samd21_sam_ba.hex
@@ -0,0 +1,386 @@
+:10000000FC7F0020E9050000D5050000D9050000AF
+:1000100000000000000000000000000000000000E0
+:10002000000000000000000000000000DD050000EE
+:100030000000000000000000E1050000E5050000F0
+:1000400010B5064C2378002B07D1054B002B02D0AE
+:10005000044800E000BF0123237010BD5C000020B5
+:10006000000000009817000008B5084B002B03D0D3
+:100070000748084900E000BF07480368002B03D089
+:10008000064B002B00D0984708BDC046000000007A
+:1000900098170000600000205800002000000000B9
+:1000A00010B5C3699C07FCD403680224A343036012
+:1000B000C46901231C42FBD1046823430360036825
+:1000C000DC07FCD4C46901231C42FBD1C469DC40B9
+:1000D0001C42F7D1084B1A430260C3695A07FCD48B
+:1000E000C0239B0243608181C3699C07FCD40368E1
+:1000F00002221343036010BD04000040037EDA07B0
+:10010000FCD5018570470000027E01235107FBD515
+:10011000428B1A4207D1428BDA401A4203D1428BFA
+:1001200092081A4202D0034B01221A70008DC0B20D
+:100130007047C0467800002070B50368041C988B97
+:100140001A1C0821FF32084228D0988B174D014312
+:10015000802099839872112353704021144B917120
+:1001600050715E68C0202E40800506435E605E6967
+:100170003540284358610F4818600F4818615D6882
+:100180000E4828408025AD02284358605868800BEF
+:100190008003586000235171237105E0137ADA0659
+:1001A00002D5201C00F0EEFA207970BDFFFFFF8F12
+:1001B000940100209400002014010020FF3F00F073
+:1001C000002303714371044B016083600B780222AA
+:1001D00013430B707047C0463901000038B5364BE9
+:1001E0002021DA6901200A43DA61344B06241A78A7
+:1001F00002431A70324B0F22197891431970197803
+:10020000214319702F490C782043087019780A404F
+:100210001A701A7860210A431A702B4B2B4A5A80A5
+:100220005A7852B2002AFBDB294B01211A780A4383
+:100230001A709A78D107FCD426480268510B1F2205
+:100240001140914200D1052111408C011D8D2249A0
+:100250002940214319850468A10C0A401F2A00D1B6
+:100260001D221C8D1F210A408C4322431A850268DF
+:100270000721D20D0A408A4200D103220A40188D7C
+:100280001103164A02400A431A8519787F220A4050
+:100290001A701A78042112480A431A7058621A898F
+:1002A0000C218A431A811A8901218A431A8100216B
+:1002B000802201F006F938BD000400405844004196
+:1002C0003C44004159440041000C004006400000FD
+:1002D00000500041246080003FF8FFFFFF8FFFFFC8
+:1002E00094010020F7B5141C234A5F0101971D1CDF
+:1002F000D319061C5869271C4000400F03301033E7
+:10030000C74006D00F1C8022596812060A435A6063
+:1003100009E02F1C7B1E9F41184BBF01FF18381CA2
+:10032000221C01F0C5F801991348083542181761DD
+:10033000131C5269A104920B890C92030A435A615F
+:1003400059690F4A02200A405A616B01F318D979A2
+:10035000032211400143D8799043021C0A43DA7109
+:100360005979802252420A435A716B01F318DB79A2
+:100370009A07FAD5201CFEBD94010020140100202C
+:10038000FF3F00F0F8B51E4E041C3378151C002BFF
+:1003900012D11C4B1C4A1A645A6C920B92035A6479
+:1003A000586C1A4A02405A64A2235B00E25C402067
+:1003B0000243E254012333704827FF37E25D0123F3
+:1003C00013401AD00F4B5A6C9204920CAA4202D2DC
+:1003D0005D6CAD04AD0C081C2A1C0B4901F068F8DB
+:1003E000E25D03231A4001210A43E15D99430B1C9E
+:1003F0001343E3550023337000E01D1C281CF8BD97
+:100400007900002094010020D4000020FF3F00F07C
+:10041000FF30827930239A43131C2022002900D117
+:1004200010221343837170470C4BFF305A6902212D
+:10043000920B92035A61027A03231A400A43017A0B
+:1004400099430B1C13430372827980235B4213434D
+:100450008371037A9A07FCD57047C0469401002047
+:1004600080235B421943C9B28172704770B5A023E3
+:1004700003225B00C254134B134A5C6CC02114402E
+:1004800089050C4346255C64FF35402444550F4DD7
+:1004900030261D6490256D0046555D6B154029433F
+:1004A000922559636D0080214155094D1D63B0258A
+:1004B0006D0044555C6F22405A67B2235B00C15403
+:1004C00070BDC04694010020FFFFFF8FD4000020C4
+:1004D0005401002030B5364A1E2351680820994344
+:1004E00002231943516033498A6902438A613248C1
+:1004F000324A9082908A03439382D3689807FCD54E
+:100500002F4B012018701878C40704D52C48407868
+:1005100040B20028F7DB01209860587840B20028EC
+:10052000FBDB284C26484460587840B20028FBDBAF
+:1005300082242348E4014480587840B20028FBDB41
+:10054000908C8024A0439084D068C506FCD51E4CB6
+:100550001A48C462D4681948E506FBD5848C1B4D43
+:100560002C438484D4681548E506FBD5848C022589
+:100570002C438484D0680406FCD51048C068450626
+:10058000F8D5D068C406FCD500229A605A7852B2D9
+:10059000002AFBDB0E480A4A50605A7852B2002A01
+:1005A000FBDB00230B724B728B72CB7230BDC046EB
+:1005B00000400041000400400C060000000800401C
+:1005C000000C004001050100B805FF7D040A000091
+:1005D000000703000EBEFEE70DBEFEE705BEFEE708
+:1005E00002BEFEE701BEFEE70E4A0F4838B5824262
+:1005F00004D10E4A0E4B93420ED10AE00D4C9442A8
+:10060000F7D00023D1188842F3D9E55804330D60A0
+:10061000F8E700F04DF804E09342FAD2002102C35B
+:10062000FAE7FEE7000000205C000020A0030020A5
+:100630005C0000209C170000194A10B51188FA24AC
+:10064000013189B2174BA400A14201D011801CE0F6
+:1006500000211180144900240C5760431C880019A4
+:1006600080B204B2FF2C01DC188002E0FF20188069
+:1006700008700024185F002803DA00201880012089
+:1006800008708020094980028861128800215B5E21
+:100690009A4203D18022054B92025A6110BDC04696
+:1006A0007A0000207C00002000000020004400416F
+:1006B00038B580222B4B92029A605A612A4A1C1C40
+:1006C000117801221140294B002200290AD1186813
+:1006D000274A904201D1196018E01A60254A013A70
+:1006E000002AFCD11A60244B1A68191C501C0DD02A
+:1006F000D8B200280AD180208002A06182F3088845
+:10070000FF2293431D4A93604B681847FFF7E2FEB0
+:1007100062B600F0FBFC00F0CFF980239B02051CC1
+:10072000A3610320FFF788FFAB68281C9847144B90
+:10073000002801D001221A701A78002A05D0002062
+:1007400000F036FA00F092FAFCE71B78002BE8D1B3
+:1007500000F050FD0028E4D0012000F029FA00F05C
+:1007600085FAFCE70044004138040040FC7F00208B
+:100770003581730748E801000020000000ED00E02B
+:100780007E000020F8B50468051C201CFF30037AA9
+:10079000B64A10210B430372B54F1378B5493B702D
+:1007A0005378B54E0B7093783380D1783388090233
+:1007B0000B4333801179B14B198051791F8809029D
+:1007C0000F431F809779AE490F80D2790F881202AC
+:1007D0003A430A8040224271A648A54F02783878F1
+:1007E000A84F12020243181CBA4200D199E01EDC45
+:1007F000802149008A4200D158E107DC812A6AD071
+:10080000822A6ED0802A00D050E164E081235B0010
+:100810009A4200D1AFE000DA23E1C0239B009A4264
+:1008200000D143E1984B9A4200D11AE13EE1902376
+:100830001B019A4242D015DCD023DB009A4222D021
+:1008400088231B019A4242D0A023DB009A4200D0A9
+:100850002CE1201CFFF7E8FD3188286889B2FFF7FA
+:10086000FFFD27E1894B9A4200D1FAE000DC1DE14F
+:10087000874B9A4200D1E8E0864B9A4200D015E1BE
+:1008800033886B71EDE033881B0A012B08D10B888C
+:1008900012222868934201D80A8892B27E49DCE08D
+:1008A00033881B0A022B00D000E10B884322286802
+:1008B000934201D80A8892B27849CEE03388201C4E
+:1008C0002B71FFF7B1FD201CFFF7D0FDF2E0291CD2
+:1008D00001C90122C1E0724900230B80286802226D
+:1008E000BCE06F4900220A801888502210406D4AEF
+:1008F00010701E880F20304018801888032800D9F7
+:10090000D4E012781B8808335B01E418A379002A2D
+:1009100001D09B0600E0DB06DB0F0B80286802227B
+:100920009BE019887F2291435E4AC9B211701888F2
+:100930000F21014019803188002900D0B6E01988C4
+:10094000002900D1B2E01988032900D9AEE012785D
+:100950001B8808335B01E318002A05D05A7930213F
+:100960008A4320210A4304E05A7930218A43102027
+:1009700002435A7175E002887F239A43494BD2B2F1
+:100980001A7001880F220A4002803288002A00D0A3
+:100990008CE00288002A00D188E00288032A00D96E
+:1009A00084E01B78002B27D0038808335B01E31811
+:1009B0009B79990655D50388302108335B01E318EC
+:1009C0001A798A4320210A431A71038808335B018C
+:1009D000E318DB795A0644D50388602108335B01AC
+:1009E000E318DA798A4340210A43DA710388022244
+:1009F00008335B01E31826E0038808335B01E31842
+:100A00009B79DF062DD50388302108335B01E3187D
+:100A10001A798A4310210A431A71038808335B014B
+:100A2000E318DB7999061CD50388602108335B0144
+:100A3000E318DA798A4320210A43DA710388012214
+:100A400008335B01E3181A710BE00B880822286851
+:100A5000934201D80A8892B213490023FFF742FC5F
+:100A600028E0201CFFF7E0FC24E0C04694000020B2
+:100A7000890000207F0000208000002084000020EA
+:100A80008600002002030000010300002120000076
+:100A9000A121000021220000EC140000040000202D
+:100AA000820000208800002048000020201C012136
+:100AB000FFF7AEFCF8BDC04610B5054B054C2360F2
+:100AC000FFF78CFB201C2168FFF77AFB201C10BD70
+:100AD000005000411402002007B5054B012201908F
+:100AE00001A91868131CFFF7FDFB01200EBDC046CD
+:100AF0001402002013B5054B6C4607341868211CFE
+:100B00000122FFF73FFC207816BDC04614020020EA
+:100B100010B5074C201CFFF70FFB031C002083427D
+:100B200005D022684823FF33D05C0123184010BD54
+:100B30001402002010B5054A0C1C031C191C106877
+:100B40000123221CFFF7CEFB201C10BD1402002045
+:100B500070B5084C061C201C0D1CFFF7EDFA002395
+:100B6000984205D02068311C2A1CFFF70BFC031C9F
+:100B7000181C70BD14020020F8B50C4C051C201C7C
+:100B80000E1CFFF7D9FA0023271C341C98420AD008
+:100B9000002C07D0291C221C3868FFF7F3FB241A0D
+:100BA0002D18F5E7331C181CF8BDC04614020020B0
+:100BB000012805D1054B064A1A60064B187004E05F
+:100BC000002802D1044A014B1A60704784020020B9
+:100BD00020150000910000206C15000030B51A4B64
+:100BE00085B01B78002B29D0042901D1026804E0CC
+:100BF000022901D1028800E00278490004A84318C4
+:100C00000B3B5C1AA3420BD00F201040092802D8DE
+:100C10003025284300E0373018701209013BF1E716
+:100C200001A830230370782343700A2243189A7076
+:100C30000D22DA70054B04311B6801E0034B1B6881
+:100C4000DB68984705B030BD90000020840200208A
+:100C500072B6EFF30883044A1360036883F30888CD
+:100C6000436818477047C04688020020F0B58FB02F
+:100C700006A9CE4A0B1C31CA31C351CA51C360CA3E
+:100C800060C3CB4CCB48A3687A255B035B0F9B000A
+:100C90005B58C9490360A26892B253430A60C749CE
+:100CA000C74A0B6000231360C64B1D700320FFF77B
+:100CB000C3FCC54BC54D1B68281C1B6940219847C8
+:100CC000C34B00221860C34B1D60C34BC24DC04FC5
+:100CD0001A60286839688842E8D2BE4B1B681A78C7
+:100CE000FF2A00D1F6E1232A00D0CDE1BB4E3378B4
+:100CF000002B05D0B44BBA481B680221DB6898472B
+:100D0000B04B1B78532B38D13B682A6893421ED9CD
+:100D1000B04801322A609A1AB24B01681B6801314F
+:100D20000160B14E9A4201D2326000E03360A448C3
+:100D300032680068029000F0BBFB336829685A18DB
+:100D40002A60A44A1668F1181160A84A13702B682B
+:100D5000013B2B609F4B1A68013A1A60A34BA14AD2
+:100D60001B7811688B4206D2974A95481268006832
+:100D7000C91A92699047C04675E1522B07D1904A33
+:100D8000914B10681B68974A5B6911686AE14F2BA9
+:100D900005D18B4B934A1B6812681A7063E1482B8C
+:100DA00005D1874B8F4A1B6812681A805BE1572B6D
+:100DB00005D1834B8B4A1B6812681A6053E16F2B75
+:100DC00003D17F4B0121186807E0682B08D17C4BC9
+:100DD00084481B6802211B880360FFF7FFFE42E185
+:100DE000772B06D1764B7F481B6804211B68036074
+:100DF000F3E7472B13D17B4B1868FFF729FF7C4B98
+:100E00001B6883F3088862B67A4B1B78002B00D1ED
+:100E100029E16D4B06201B681B68984723E1542B82
+:100E200004D101233370684B1B685CE04E2B0BD15F
+:100E30003378002B05D1644B69481B680221DB68BD
+:100E40009847002333700EE1562B50D15E4D01219F
+:100E50002B686948DB6898472B680321DB68674883
+:100E60009847674E2B68301CDB68012198472B6838
+:100E70000D21DB68634898472B68301CDB68012133
+:100E80009847544F604B544E3B60002333603A1CEC
+:100E9000311C1368581C10601B780393002B03D07F
+:100EA0000B6801330B60F4E72B683168DB68564848
+:100EB00098472B685248DB680121984703983060B7
+:100EC00052483860434A1368591C11601A78424BE3
+:100ED000002A03D01A6801321A60F3E72A681968F9
+:100EE000D36898472B68DB683D480221BAE03D4A49
+:100EF000582B15D12F4E314D366813682A68B10032
+:100F0000934208D25808E06141482080207DC507FF
+:100F1000FCD55B18F4E72C4B3E481B68DB68A0E06F
+:100F2000592B33D11268264B3B49002A02D11B684A
+:100F30000B6026E00868196863688025AB43920857
+:100F40006360002A1DD0354B2380237DDE07FCD54E
+:100F50000023184D2D680095AD08AB4202D3304DEB
+:100F6000258006E09342FAD09D00465901334E5148
+:100F7000EFE7257DEE07FCD59D0049194019D21AEF
+:100F8000DFE7114B27481B68DB686AE05A2B6AD100
+:100F90000B4B17681D680026EF19BD4244D0287816
+:100FA000311C00F049F90135061CF6E70015000078
+:100FB000004000413C0200203402002030020020AA
+:100FC000800200202C020020840200204002002029
+:100FD0002402002028020020380200209000002077
+:100FE000601500008C0200209002002020020020EA
+:100FF00088020020910000203C15000065150000CB
+:101000003E15000088150000401500004C1500003A
+:1010100002A5FFFF551500008C00002044A5FFFF2E
+:1010200004A5FFFF591500002E4D2F482B68012104
+:10103000DB68984707230F223240111C36093031F4
+:10104000092A00DD07311020C0186A468154013B8F
+:10105000F1D22B6804A8DB68082198472B68234845
+:10106000DB6803219847224D7A232B70214B002205
+:101070001A60214B1B7893422CD01A4B01211B681C
+:101080001E48DB68984725E0111C3039C8B2194B5F
+:10109000092804D81E683201114319601AE0111C96
+:1010A0004139052903D81868373A010106E0111CB7
+:1010B0006139052904D81D68573A29010A4308E017
+:1010C0002C2A03D10E4A1E68166001E008490A70F6
+:1010D00000221A600B4B1A6801321A600A4B1A6818
+:1010E0000132F3E5840200205D1500005F15000069
+:1010F0002C0200208C0200209000002063150000CC
+:1011000080020020380200202802002010B51C4B6D
+:1011100001201A78022402431A701A4B0F22197800
+:101120009143197019782143197017490C7820439D
+:10113000087019780A401A701A7820210A431A7028
+:10114000124B04211A6A0A431A62114B114A5A803F
+:101150005A7852B2002AFBDBC4220F480F4992038F
+:10116000FEF79EFF0E4A002313700E4A13700E4ABC
+:1011700013700E4A13700E4A13700E4A137010BD8E
+:101180004A440041354400414B44004100040040C2
+:10119000000C004014400000000800422AF6000045
+:1011A000940200201B0300209502002098020020DA
+:1011B0001C0300201903002008B5C1B20248FEF745
+:1011C0009DFF012008BDC04600080042024B187E6A
+:1011D0004007C00F7047C0460008004208B5FFF73F
+:1011E000F5FF0028FBD00248FEF78EFF08BDC04681
+:1011F0000008004208B5FFF7E9FF0023984205D038
+:10120000FFF7ECFF031C233B5A425341181C08BD57
+:1012100070B5041C0D1C4618B44204D02078FFF7AA
+:10122000CBFF0134F8E7281C70BD10B5041CFFF794
+:10123000D5FF2070012010BD0B0A5840034B400021
+:10124000C05A0902484080B27047C0469615000057
+:10125000F7B50024051C0F1C261CBC4220D0FFF74C
+:10126000BDFF114BC0B21B780190002B1AD1311C6D
+:10127000FFF7E2FF0D4B061C1A88002A04D10C4A26
+:1012800011782A1C002907D001996A1C2970802F27
+:1012900002D11988013919800134A4B2151CDCE788
+:1012A000301C00E00120FEBD190300209602002042
+:1012B0001A030020F0B53E4E85B0002203900C1CAE
+:1012C00032703C4B914201D1012201E03A490C803D
+:1012D0001A707F231C4201D080349C43FFF77EFFAD
+:1012E0003378C0B2002B07D000253570FFF776FFAA
+:1012F0003378C0B2AB4236D1432803D0712853D0E3
+:101300001528EBD1012300930120FFF755FF00982A
+:10131000FFF752FF00998025C843C0B2FFF74CFF8A
+:10132000039B00270293244A1388002B1DD12149D7
+:1013300001930978002918D10198FFF73DFF391C66
+:101340000198FFF779FF013D071C002DEBD1000A42
+:10135000C0B2FFF731FFF8B2FFF72EFFFFF73EFFF5
+:101360003378002B0AD035701FE00299013B0978D1
+:101370001380029B019101330293DDE7C0B206287E
+:1013800007D1009B03990133DBB280310093803C8D
+:101390000391002CB8D10420FFF70EFFFFF71EFFCA
+:1013A000044B01251C7000E00025281C05B0F0BD91
+:1013B000190300201A03002096020020F0B5384CD3
+:1013C00087B0002301902370994201D1012301E0ED
+:1013D000344A1180344A642613704320FFF7ECFE30
+:1013E000324FFFF7F3FE002803D1002F03D0013F57
+:1013F000F7E7002F03D1013E002EEED14DE001258D
+:10140000FFF7ECFE2378002B38D1C0B20290012800
+:1014100005D004283DD10620FFF7CEFE39E005AE09
+:101420000221301CFFF714FF01988021FFF710FF05
+:1014300023780390002B18D1FFF7D0FE0702FFF7A7
+:10144000CDFEBFB223783F18BFB2012B0DD0039B56
+:101450009F4207D13378AB4204D1EB437278DBB2C1
+:101460009A4204D01820FFF7A7FE002303E00620CD
+:10147000FFF7A2FE029B2278002A02D000262670E7
+:101480000BE0012B05D1019A6B1C8032DDB2019279
+:10149000B6E7054A002313700126301C07B0F0BDE3
+:1014A00019030020960200201A03002000350C00CA
+:1014B00010B50023934203D0CC5CC4540133F9E748
+:1014C00010BD031C8218934202D019700133FAE751
+:1014D00070470000F8B5C046F8BC08BC9E4670478F
+:1014E000F8B5C046F8BC08BC9E4670471201000221
+:1014F000020000409A230B000002000000010000DF
+:101500000800000010000000200000004000000063
+:101510008000000000010000000200000004000044
+:10152000B9110000DD110000CD1100001112000002
+:101530002B120000B5120000BD1300007600200041
+:101540004D617220203520323031360032313A324E
+:10155000383A333400580A0D00590A0D005A002356
+:101560000A0D003E00322E3000000000D90A0000B3
+:10157000F50A0000110B0000350B0000510B0000B4
+:10158000350B0000790B00005B41726475696E6F6A
+:101590003A58595A5D0000002110422063308440BF
+:1015A000A550C660E770088129914AA16BB18CC132
+:1015B000ADD1CEE1EFF13112100273325222B552A9
+:1015C0009442F772D662399318837BB35AA3BDD382
+:1015D0009CC3FFF3DEE36224433420040114E66479
+:1015E000C774A44485546AA54BB528850995EEE5D2
+:1015F000CFF5ACC58DD55336722611163006D77689
+:10160000F6669556B4465BB77AA719973887DFF721
+:10161000FEE79DD7BCC7C448E5588668A778400850
+:10162000611802282338CCC9EDD98EE9AFF9488971
+:1016300069990AA92BB9F55AD44AB77A966A711AE8
+:10164000500A333A122AFDDBDCCBBFFB9EEB799BC1
+:10165000588B3BBB1AABA66C877CE44CC55C222C38
+:10166000033C600C411CAEED8FFDECCDCDDD2AAD11
+:101670000BBD688D499D977EB66ED55EF44E133EC8
+:10168000322E511E700E9FFFBEEFDDDFFCCF1BBF61
+:101690003AAF599F788F8891A981CAB1EBA10CD13B
+:1016A0002DC14EF16FE18010A100C230E320045043
+:1016B000254046706760B9839893FBA3DAB33DC3B6
+:1016C0001CD37FE35EF3B1029012F322D232354293
+:1016D000145277625672EAB5CBA5A89589856EF546
+:1016E0004FE52CD50DC5E234C324A01481046674E3
+:1016F000476424540544DBA7FAB79987B8975FE796
+:101700007EF71DC73CD7D326F2369106B016576632
+:101710007676154634564CD96DC90EF92FE9C8991D
+:10172000E9898AB9ABA94458654806782768C01882
+:10173000E1088238A3287DCB5CDB3FEB1EFBF98BF5
+:10174000D89BBBAB9ABB754A545A376A167AF10AD2
+:10175000D01AB32A923A2EFD0FED6CDD4DCDAABD05
+:101760008BADE89DC98D267C076C645C454CA23C22
+:10177000832CE01CC10C1FEF3EFF5DCF7CDF9BAFD5
+:10178000BABFD98FF89F176E367E554E745E932E72
+:0C179000B23ED10EF01E00000000000070
+:10179C00010000000902430002010080320904002C
+:1017AC0000010202000005240010010424020005BF
+:1017BC00240600010524010001070583030800FF2E
+:1017CC0009040100020A0000000705810240000024
+:1017DC00070502024000000000C2010000000800E2
+:0C17EC0069000000410000000000000047
+:04000003000005E90B
+:00000001FF
diff --git a/bootloaders/feather/samr21_sam_ba.bin b/bootloaders/feather/samr21_sam_ba.bin
new file mode 100644
index 000000000..aeed6a66d
Binary files /dev/null and b/bootloaders/feather/samr21_sam_ba.bin differ
diff --git a/bootloaders/feather/samr21_sam_ba.hex b/bootloaders/feather/samr21_sam_ba.hex
new file mode 100644
index 000000000..cfead74fb
--- /dev/null
+++ b/bootloaders/feather/samr21_sam_ba.hex
@@ -0,0 +1,380 @@
+:10000000FC7F0020BD050000A9050000AD05000033
+:1000100000000000000000000000000000000000E0
+:10002000000000000000000000000000B10500001A
+:100030000000000000000000B5050000B905000048
+:1000400010B5064C2378002B07D1054B002B02D0AE
+:10005000044800E000BF0123237010BD5C000020B5
+:10006000000000003C17000008B5084B002B03D02F
+:100070000748084900E000BF07480368002B03D089
+:10008000064B002B00D0984708BDC046000000007A
+:100090003C17000060000020580000200000000015
+:1000A00010B5C3699C07FCD403680224A343036012
+:1000B000C46901231C42FBD1046823430360036825
+:1000C000DC07FCD4C46901231C42FBD1C469DC40B9
+:1000D0001C42F7D1084B1A430260C3695A07FCD48B
+:1000E000C0239B0243608181C3699C07FCD40368E1
+:1000F00002221343036010BD04000040037EDA07B0
+:10010000FCD5018570470000027E01235107FBD515
+:10011000428B1A4207D1428BDA401A4203D1428BFA
+:1001200092081A4202D0034B01221A70008DC0B20D
+:100130007047C0467800002070B50368041C988B97
+:100140001A1C0821FF32084228D0988B174D014312
+:10015000802099839872112353704021144B917120
+:1001600050715E68C0202E40800506435E605E6967
+:100170003540284358610F4818600F4818615D6882
+:100180000E4828408025AD02284358605868800BEF
+:100190008003586000235171237105E0137ADA0659
+:1001A00002D5201C00F0D8FA207970BDFFFFFF8F28
+:1001B000940100209400002014010020FF3F00F073
+:1001C000002303714371044B016083600B780222AA
+:1001D00013430B707047C0463901000038B5364BE9
+:1001E0002021DA6901200A43DA61344B06241A78A7
+:1001F00002431A70324B0F22197891431970197803
+:10020000214319702F490C782043087019780A404F
+:100210001A701A7860210A431A702B4B2B4A5A80A5
+:100220005A7852B2002AFBDB294B01211A780A4383
+:100230001A709A78D107FCD426480268510B1F2205
+:100240001140914200D1052111408C011D8D2249A0
+:100250002940214319850468A10C0A401F2A00D1B6
+:100260001D221C8D1F210A408C4322431A850268DF
+:100270000721D20D0A408A4200D103220A40188D7C
+:100280001103164A02400A431A8519787F220A4050
+:100290001A701A78042112480A431A7058621A898F
+:1002A0000C218A431A811A8901218A431A8100216B
+:1002B000802201F0D8F838BD0004004058440041C5
+:1002C0003C44004159440041000C004006400000FD
+:1002D00000500041246080003FF8FFFFFF8FFFFFC8
+:1002E00094010020F7B5141C204A5F0101971D1CE2
+:1002F000D319061C5869271C4000400F03301033E7
+:10030000C74006D00F1C8022596812060A435A6063
+:1003100009E02F1C7B1E9F41154BBF01FF18381CA5
+:10032000221C01F097F8019910480835421817610E
+:10033000131C5269A104920B890C92030A435A615F
+:1003400059690C4A0A405A616B01F318DA790221A3
+:100350000A43DA715979802252420A435A716B0179
+:10036000F318DB799A07FAD5201CFEBD9401002012
+:1003700014010020FF3F00F0F8B51B4E051C337838
+:10038000141C002B12D1194B194A1A645A6C920B87
+:1003900092035A64586C174A02405A64A2235B00C5
+:1003A000EA5C40200243EA54012333704827FF37B8
+:1003B000EA5D0123134014D00C4B5A6C9204920C4A
+:1003C000A24202D25C6CA404A40C081C221C0849A2
+:1003D00001F040F8EB5D01221343EB55002333702D
+:1003E00000E01C1C201CF8BD7900002094010020B6
+:1003F000D4000020FF3F00F0FF302023002900D16F
+:100400001023837170470000094BFF305A69920B2B
+:1004100092035A61037A0222134303728279802382
+:100420005B4213438371037A9A07FCD57047C04639
+:100430009401002080235B421943C9B28172704746
+:1004400070B5A02303225B00C254134B134A5C6CAB
+:10045000C021144089050C4346255C64FF354024C7
+:1004600044550F4D30261D6490256D0046555D6B3B
+:1004700015402943922559636D0080214155094D4E
+:100480001D63B0256D0044555C6F22405A67B2234E
+:100490005B00C15470BDC04694010020FFFFFF8F78
+:1004A000D40000205401002030B5364A1E23516884
+:1004B0000820994302231943516033498A69024352
+:1004C0008A613248324A9082908A03439382D36889
+:1004D0009807FCD52F4B012018701878C40704D555
+:1004E0002C48407840B20028F7DB0120986058780B
+:1004F00040B20028FBDB284C26484460587840B2C4
+:100500000028FBDB82242348E4014480587840B271
+:100510000028FBDB908C8024A0439084D068C50623
+:10052000FCD51E4C1A48C462D4681948E506FBD5B0
+:10053000848C1B4D2C438484D4681548E506FBD578
+:10054000848C02252C438484D0680406FCD5104892
+:10055000C0684506F8D5D068C406FCD500229A606C
+:100560005A7852B2002AFBDB0E480A4A50605A7889
+:1005700052B2002AFBDB00230B724B728B72CB72E0
+:1005800030BDC04600400041000400400C060000A1
+:1005900000080040000C004001050100B805FF7D87
+:1005A000040A0000000703000EBEFEE70DBEFEE7D2
+:1005B00005BEFEE702BEFEE701BEFEE70E4A0F489B
+:1005C00038B5824204D10E4A0E4B93420ED10AE056
+:1005D0000D4C9442F7D00023D1188842F3D9E55846
+:1005E00004330D60F8E700F04DF804E09342FAD2CE
+:1005F000002102C3FAE7FEE7000000205C000020B3
+:10060000A00300205C00002040170000194A10B52C
+:100610001188FA24013189B2174BA400A14201D0FC
+:1006200011801CE000211180144900240C57604304
+:100630001C88001980B204B2FF2C01DC188002E093
+:10064000FF20188008700024185F002803DA0020BB
+:100650001880012008708020094980028861128872
+:1006600000215B5E9A4203D18022054B92025A61BF
+:1006700010BDC0467A0000207C0000200000002051
+:100680000044004138B580222B4B92029A605A6197
+:100690002A4A1C1C117801221140294B00220029F2
+:1006A0000AD11868274A904201D1196018E01A60EF
+:1006B000254A013A002AFCD11A60244B1A68191CF9
+:1006C000501C0DD0D8B200280AD180208002A06131
+:1006D00082F30888FF2293431D4A93604B681847B2
+:1006E000FFF7E2FE62B600F0E3FC00F0B7F980230A
+:1006F0009B02051CA3610320FFF788FFAB68281C41
+:100700009847144B002801D001221A701A78002A49
+:1007100005D0002000F01EFA00F07AFAFCE71B7802
+:10072000002BE8D100F038FD0028E4D0012000F0D3
+:1007300011FA00F06DFAFCE7004400413804004073
+:10074000FC7F00203581730748E80100002000008D
+:1007500000ED00E07E000020F8B50468051C201CB8
+:10076000FF30037AAD4A10210B430372AC4F13786C
+:10077000AC493B705378AC4E0B7093783380D17892
+:10078000338809020B4333801179A84B19805179C2
+:100790001F8809020F431F809779A5490F80D279DE
+:1007A0000F8812023A430A80402242719D489C4FB2
+:1007B000027838789F4F12020243181CBA4200D1C7
+:1007C00099E01EDC802149008A4200D121E107DC4A
+:1007D000812A6AD0822A6ED0802A00D019E164E092
+:1007E00081235B009A4200D1A8E000DA0DE1C0232A
+:1007F0009B009A4200D10CE18F4B9A4200D104E158
+:1008000007E190231B019A4242D015DCD023DB0084
+:100810009A4222D088231B019A4242D0A023DB00B7
+:100820009A4200D0F5E0201CFFF7EEFD31882868E1
+:1008300089B2FFF7FFFDF0E0804B9A4200D1E4E07F
+:1008400000DCE6E07E4B9A4200D1D2E07D4B9A423A
+:1008500000D0DEE033886B71D7E033881B0A012BB0
+:1008600008D10B8812222868934201D80A8892B2D4
+:100870007549C6E033881B0A022B00D0C9E00B88FB
+:1008800043222868934201D80A8892B26F49B8E09F
+:100890003388201C2B71FFF7B7FD201CFFF7D0FD1C
+:1008A000BBE0291C01C90122ABE0694900230B8090
+:1008B00028680222A6E0664900220A801888502291
+:1008C0001040644A10701E880F203040188018882D
+:1008D000032800D99DE012781B8808335B01E418D7
+:1008E000A379002A01D09B0600E0DB06DB0F0B801A
+:1008F0002868022285E019887F229143554AC9B2AF
+:10090000117018880F21014019803188002900D00A
+:100910007FE01988002900D17BE01988032900D9DC
+:1009200077E012781B8808335B01E318002A02D0B5
+:1009300020225A7169E01020587166E002887F23F6
+:100940009A43444BD2B21A7001880F220A400280A7
+:100950003288002A5DD10288002A5AD00288032AF0
+:1009600057D81B78002B21D0038808335B01E3188C
+:100970009B79990649D50388202208335B01E31847
+:100980001A71038808335B01E318DB795A063CD5FA
+:100990000388402108335B01E318DA790A43DA71EE
+:1009A0000388022208335B01E31820E00388083340
+:1009B0005B01E3189B79DF0627D5038810220833F3
+:1009C0005B01E3181A71038808335B01E318DB79D4
+:1009D00099061AD50388202108335B01E318DA79D8
+:1009E0000A43DA710388012208335B01E3181A71A4
+:1009F0000BE00B8808222868934201D80A8892B23B
+:100A000015490023FFF76EFC07E0201CFFF7FCFCF4
+:100A100003E0201C0121FFF7EFFCF8BD940000204B
+:100A2000890000207F000020800000208600002038
+:100A300084000020020300000103000021200000C8
+:100A4000A1210000212200009014000004000020D9
+:100A500082000020880000204800002010B5054BCF
+:100A6000054C2360FFF7BAFB201C2168FFF7A8FBA9
+:100A7000201C10BD005000411402002007B5054B9A
+:100A80000122019001A91868131CFFF72BFC01201B
+:100A90000EBDC0461402002013B5054B6C4607344A
+:100AA0001868211C0122FFF767FC207816BDC0469C
+:100AB0001402002010B5074C201CFFF73DFB031C5F
+:100AC0000020834205D022684823FF33D05C0123F5
+:100AD000184010BD1402002010B5054A0C1C031C60
+:100AE000191C10680123221CFFF7FCFB201C10BD01
+:100AF0001402002070B5084C061C201C0D1CFFF7CA
+:100B00001BFB0023984205D02068311C2A1CFFF7EC
+:100B100033FC031C181C70BD14020020F8B50C4CEB
+:100B2000051C201C0E1CFFF707FB0023271C341C90
+:100B300098420AD0002C07D0291C221C3868FFF7E5
+:100B40001BFC241A2D18F5E7331C181CF8BDC046F1
+:100B500014020020012805D1054B064A1A60064BF5
+:100B6000187004E0002802D1044A014B1A60704753
+:100B700084020020C4140000910000201015000021
+:100B800030B51A4B85B01B78002B29D0042901D130
+:100B9000026804E0022901D1028800E002784900DD
+:100BA00004A843180B3B5C1AA3420BD00F20104043
+:100BB000092802D83025284300E037301870120980
+:100BC000013BF1E701A830230370782343700A2228
+:100BD00043189A700D22DA70054B04311B6801E04E
+:100BE000034B1B68DB68984705B030BD90000020C0
+:100BF0008402002072B6EFF30883044A136003688E
+:100C000083F30888436818477047C046880200206D
+:100C1000F0B58FB006A9CE4A0B1C31CA31C351CAF8
+:100C200051C360CA60C3CB4CCB48A3687A255B0331
+:100C30005B0F9B005B58C9490360A26892B25343A3
+:100C40000A60C749C74A0B6000231360C64B1D707A
+:100C50000320FFF7DBFCC54BC54D1B68281C1B6937
+:100C600040219847C34B00221860C34B1D60C34B03
+:100C7000C24DC04F1A60286839688842E8D2BE4B1E
+:100C80001B681A78FF2A00D1F6E1232A00D0CDE1B3
+:100C9000BB4E3378002B05D0B44BBA481B680221F9
+:100CA000DB689847B04B1B78532B38D13B682A68D8
+:100CB00093421ED9B04801322A609A1AB24B016899
+:100CC0001B6801310160B14E9A4201D2326000E0EE
+:100CD0003360A44832680068029000F0BBFB3368C0
+:100CE00029685A182A60A44A1668F1181160A84A9F
+:100CF00013702B68013B2B609F4B1A68013A1A60F6
+:100D0000A34BA14A1B7811688B4206D2974A95489B
+:100D100012680068C91A92699047C04675E1522B63
+:100D200007D1904A914B10681B68974A5B6911681C
+:100D30006AE14F2B05D18B4B934A1B6812681A70DE
+:100D400063E1482B05D1874B8F4A1B6812681A80D4
+:100D50005BE1572B05D1834B8B4A1B6812681A60E5
+:100D600053E16F2B03D17F4B0121186807E0682BFB
+:100D700008D17C4B84481B6802211B880360FFF765
+:100D8000FFFE42E1772B06D1764B7F481B6804219A
+:100D90001B680360F3E7472B13D17B4B1868FFF701
+:100DA00029FF7C4B1B6883F3088862B67A4B1B785B
+:100DB000002B00D129E16D4B06201B681B6898476A
+:100DC00023E1542B04D101233370684B1B685CE092
+:100DD0004E2B0BD13378002B05D1644B69481B682F
+:100DE0000221DB689847002333700EE1562B50D167
+:100DF0005E4D01212B686948DB6898472B68032109
+:100E0000DB6867489847674E2B68301CDB68012118
+:100E100098472B680D21DB68634898472B68301C86
+:100E2000DB6801219847544F604B544E3B600023D0
+:100E300033603A1C311C1368581C10601B780393F4
+:100E4000002B03D00B6801330B60F4E72B6831688B
+:100E5000DB68564898472B685248DB680121984761
+:100E60000398306052483860434A1368591C116037
+:100E70001A78424B002A03D01A6801321A60F3E74D
+:100E80002A681968D36898472B68DB683D480221B7
+:100E9000BAE03D4A582B15D12F4E314D36681368B4
+:100EA0002A68B100934208D25808E0614148208086
+:100EB000207DC507FCD55B18F4E72C4B3E481B682A
+:100EC000DB68A0E0592B33D11268264B3B49002A3E
+:100ED00002D11B680B6026E00868196863688025EA
+:100EE000AB4392086360002A1DD0354B2380237DDD
+:100EF000DE07FCD50023184D2D680095AD08AB42E8
+:100F000002D3304D258006E09342FAD09D00465929
+:100F100001334E51EFE7257DEE07FCD59D004919C1
+:100F20004019D21ADFE7114B27481B68DB686AE0DB
+:100F30005A2B6AD10B4B17681D680026EF19BD426A
+:100F400044D02878311C00F049F90135061CF6E739
+:100F5000A4140000004000413C02002034020020A4
+:100F600030020020800200202C0200208402002099
+:100F70004002002024020020280200203802002025
+:100F800090000020041500008C0200209002002038
+:100F9000200200208802002091000020E0140000C0
+:100FA00009150000E21400002C150000E4140000F4
+:100FB000F014000002A5FFFFF91400008C000020CF
+:100FC00044A5FFFF04A5FFFFFD1400002E4D2F4890
+:100FD0002B680121DB68984707230F223240111C40
+:100FE00036093031092A00DD07311020C0186A4661
+:100FF0008154013BF1D22B6804A8DB680821984793
+:101000002B682348DB6803219847224D7A232B70F5
+:10101000214B00221A60214B1B7893422CD01A4B93
+:1010200001211B681E48DB68984725E0111C3039F8
+:10103000C8B2194B092804D81E683201114319603F
+:101040001AE0111C4139052903D81868373A010103
+:1010500006E0111C6139052904D81D68573A290199
+:101060000A4308E02C2A03D10E4A1E68166001E0EC
+:1010700008490A7000221A600B4B1A6801321A6084
+:101080000A4B1A680132F3E58402002001150000C2
+:10109000031500002C0200208C020020900000208C
+:1010A00007150000800200203802002028020020DE
+:1010B00010B51C4B01201A78022402431A701A4BF7
+:1010C0000F22197891431970197821431970174923
+:1010D0000C782043087019780A401A701A78202179
+:1010E0000A431A70124B04211A6A0A431A62114BFE
+:1010F000114A5A805A7852B2002AFBDBC4220F48A8
+:101100000F499203FEF7CCFF0E4A002313700E4ADC
+:1011100013700E4A13700E4A13700E4A13700E4A63
+:10112000137010BD4A440041354400414B44004116
+:1011300000040040000C0040144000000008004281
+:101140002AF60000940200201B03002095020020D4
+:10115000980200201C0300201903002008B5C1B22A
+:101160000248FEF7CBFF012008BDC0460008004240
+:10117000024B187E4007C00F7047C046000800426F
+:1011800008B5FFF7F5FF0028FBD00248FEF7BCFFCB
+:1011900008BDC0460008004208B5FFF7E9FF00237C
+:1011A000984205D0FFF7ECFF031C233B5A42534102
+:1011B000181C08BD70B5041C0D1C4618B44204D0A0
+:1011C0002078FFF7CBFF0134F8E7281C70BD10B57D
+:1011D000041CFFF7D5FF2070012010BD0B0A5840FA
+:1011E000034B4000C05A0902484080B27047C046D5
+:1011F0003A150000F7B50024051C0F1C261CBC4244
+:1012000020D0FFF7BDFF114BC0B21B780190002B1F
+:101210001AD1311CFFF7E2FF0D4B061C1A88002A79
+:1012200004D10C4A11782A1C002907D001996A1CA4
+:101230002970802F02D11988013919800134A4B294
+:10124000151CDCE7301C00E00120FEBD1903002066
+:10125000960200201A030020F0B53E4E85B0002211
+:1012600003900C1C32703C4B914201D1012201E0F1
+:101270003A490C801A707F231C4201D080349C4371
+:10128000FFF77EFF3378C0B2002B07D00025357002
+:10129000FFF776FF3378C0B2AB4236D1432803D094
+:1012A000712853D01528EBD1012300930120FFF7BB
+:1012B00055FF0098FFF752FF00998025C843C0B240
+:1012C000FFF74CFF039B00270293244A1388002B4F
+:1012D0001DD1214901930978002918D10198FFF700
+:1012E0003DFF391C0198FFF779FF013D071C002DD8
+:1012F000EBD1000AC0B2FFF731FFF8B2FFF72EFFC3
+:10130000FFF73EFF3378002B0AD035701FE00299BB
+:10131000013B09781380029B019101330293DDE7C1
+:10132000C0B2062807D1009B03990133DBB280319C
+:101330000093803C0391002CB8D10420FFF70EFFEE
+:10134000FFF71EFF044B01251C7000E00025281C40
+:1013500005B0F0BD190300201A03002096020020FA
+:10136000F0B5384C87B0002301902370994201D129
+:10137000012301E0344A1180344A6426137043206B
+:10138000FFF7ECFE324FFFF7F3FE002803D1002FEA
+:1013900003D0013FF7E7002F03D1013E002EEED12D
+:1013A0004DE00125FFF7ECFE2378002B38D1C0B2C9
+:1013B0000290012805D004283DD10620FFF7CEFE7B
+:1013C00039E005AE0221301CFFF714FF019880219F
+:1013D000FFF710FF23780390002B18D1FFF7D0FE02
+:1013E0000702FFF7CDFEBFB223783F18BFB2012B33
+:1013F0000DD0039B9F4207D13378AB4204D1EB431E
+:101400007278DBB29A4204D01820FFF7A7FE0023BF
+:1014100003E00620FFF7A2FE029B2278002A02D0FA
+:10142000002626700BE0012B05D1019A6B1C80323F
+:10143000DDB20192B6E7054A002313700126301C85
+:1014400007B0F0BD19030020960200201A03002007
+:1014500000350C0010B50023934203D0CC5CC4547B
+:101460000133F9E710BD031C8218934202D01970B2
+:101470000133FAE770470000F8B5C046F8BC08BC75
+:101480009E467047F8B5C046F8BC08BC9E467047FB
+:1014900012010002020000409A2314000002000022
+:1014A0000001000008000000100000002000000003
+:1014B0004000000080000000000100000002000069
+:1014C000000400005D110000811100007111000096
+:1014D000B5110000CF110000591200006113000087
+:1014E00076002000417072203137203230313600D2
+:1014F00032323A34393A313900580A0D00590A0D5E
+:10150000005A00230A0D003E00322E300000000079
+:101510007D0A0000990A0000B50A0000D90A0000FF
+:10152000F50A0000D90A00001D0B00005B4172643F
+:1015300075696E6F3A58595A5D00000021104220BB
+:1015400063308440A550C660E770088129914AA1A4
+:101550006BB18CC1ADD1CEE1EFF13112100273321B
+:101560005222B5529442F772D662399318837BB3F4
+:101570005AA3BDD39CC3FFF3DEE3622443342004AB
+:101580000114E664C774A44485546AA54BB5288544
+:101590000995EEE5CFF5ACC58DD5533672261116FB
+:1015A0003006D776F6669556B4465BB77AA7199794
+:1015B0003887DFF7FEE79DD7BCC7C448E558866883
+:1015C000A7784008611802282338CCC9EDD98EE9E4
+:1015D000AFF9488969990AA92BB9F55AD44AB77A5B
+:1015E000966A711A500A333A122AFDDBDCCBBFFB34
+:1015F0009EEB799B588B3BBB1AABA66C877CE44C6B
+:10160000C55C222C033C600C411CAEED8FFDECCD83
+:10161000CDDD2AAD0BBD688D499D977EB66ED55E3A
+:10162000F44E133E322E511E700E9FFFBEEFDDDFD3
+:10163000FCCF1BBF3AAF599F788F8891A981CAB15F
+:10164000EBA10CD12DC14EF16FE18010A100C23091
+:10165000E3200450254046706760B9839893FBA34C
+:10166000DAB33DC31CD37FE35EF3B1029012F322E1
+:10167000D2323542145277625672EAB5CBA5A8959C
+:1016800089856EF54FE52CD50DC5E234C324A01431
+:1016900081046674476424540544DBA7FAB799872C
+:1016A000B8975FE77EF71DC73CD7D326F236910681
+:1016B000B01657667676154634564CD96DC90EF974
+:1016C0002FE9C899E9898AB9ABA9445865480678D1
+:1016D0002768C018E1088238A3287DCB5CDB3FEB8C
+:1016E0001EFBF98BD89BBBAB9ABB754A545A376A21
+:1016F000167AF10AD01AB32A923A2EFD0FED6CDD5C
+:101700004DCDAABD8BADE89DC98D267C076C645C70
+:10171000454CA23C832CE01CC10C1FEF3EFF5DCF6B
+:101720007CDF9BAFBABFD98FF89F176E367E554EC0
+:10173000745E932EB23ED10EF01E00000000000039
+:101740000100000009024300020100803209040088
+:10175000000102020000052400100104240200051B
+:10176000240600010524010001070583030800FF8A
+:1017700009040100020A0000000705810240000080
+:10178000070502024000000000C20100000008003E
+:0C179000690000004100000000000000A3
+:04000003000005BD37
+:00000001FF
diff --git a/bootloaders/featherM0/bootloader-feather_m0-v2.0.0-adafruit.5.bin b/bootloaders/featherM0/bootloader-feather_m0-v2.0.0-adafruit.5.bin
new file mode 100755
index 000000000..4f2a40960
Binary files /dev/null and b/bootloaders/featherM0/bootloader-feather_m0-v2.0.0-adafruit.5.bin differ
diff --git a/bootloaders/featherM0/bootloader-feather_m0-v2.0.0-adafruit.5.elf b/bootloaders/featherM0/bootloader-feather_m0-v2.0.0-adafruit.5.elf
new file mode 100755
index 000000000..0b5e89dca
Binary files /dev/null and b/bootloaders/featherM0/bootloader-feather_m0-v2.0.0-adafruit.5.elf differ
diff --git a/bootloaders/featherM0/update-bootloader-feather_m0-v2.0.0-adafruit.5.uf2 b/bootloaders/featherM0/update-bootloader-feather_m0-v2.0.0-adafruit.5.uf2
new file mode 100644
index 000000000..fe0538459
Binary files /dev/null and b/bootloaders/featherM0/update-bootloader-feather_m0-v2.0.0-adafruit.5.uf2 differ
diff --git a/bootloaders/featherM4/bootloader-feather_m4-v2.0.0-adafruit.5.bin b/bootloaders/featherM4/bootloader-feather_m4-v2.0.0-adafruit.5.bin
new file mode 100755
index 000000000..a7ad465a4
Binary files /dev/null and b/bootloaders/featherM4/bootloader-feather_m4-v2.0.0-adafruit.5.bin differ
diff --git a/bootloaders/featherM4/bootloader-feather_m4-v2.0.0-adafruit.5.elf b/bootloaders/featherM4/bootloader-feather_m4-v2.0.0-adafruit.5.elf
new file mode 100755
index 000000000..0d79d8f5e
Binary files /dev/null and b/bootloaders/featherM4/bootloader-feather_m4-v2.0.0-adafruit.5.elf differ
diff --git a/bootloaders/featherM4/update-bootloader-feather_m4-v2.0.0-adafruit.5.uf2 b/bootloaders/featherM4/update-bootloader-feather_m4-v2.0.0-adafruit.5.uf2
new file mode 100644
index 000000000..dd1bbe2a8
Binary files /dev/null and b/bootloaders/featherM4/update-bootloader-feather_m4-v2.0.0-adafruit.5.uf2 differ
diff --git a/bootloaders/gemmaM0/bootloader-gemma_m0-v2.0.0-adafruit.5.bin b/bootloaders/gemmaM0/bootloader-gemma_m0-v2.0.0-adafruit.5.bin
new file mode 100755
index 000000000..6832a558b
Binary files /dev/null and b/bootloaders/gemmaM0/bootloader-gemma_m0-v2.0.0-adafruit.5.bin differ
diff --git a/bootloaders/gemmaM0/bootloader-gemma_m0-v2.0.0-adafruit.5.elf b/bootloaders/gemmaM0/bootloader-gemma_m0-v2.0.0-adafruit.5.elf
new file mode 100755
index 000000000..c6b954da8
Binary files /dev/null and b/bootloaders/gemmaM0/bootloader-gemma_m0-v2.0.0-adafruit.5.elf differ
diff --git a/bootloaders/gemmaM0/update-bootloader-gemma_m0-v2.0.0-adafruit.5.uf2 b/bootloaders/gemmaM0/update-bootloader-gemma_m0-v2.0.0-adafruit.5.uf2
new file mode 100644
index 000000000..538922beb
Binary files /dev/null and b/bootloaders/gemmaM0/update-bootloader-gemma_m0-v2.0.0-adafruit.5.uf2 differ
diff --git a/bootloaders/grand_central_m4/bootloader-grandcentral_m4.bin b/bootloaders/grand_central_m4/bootloader-grandcentral_m4.bin
new file mode 100644
index 000000000..f341a2d60
Binary files /dev/null and b/bootloaders/grand_central_m4/bootloader-grandcentral_m4.bin differ
diff --git a/bootloaders/hallowingM0/bootloader-hallowing_m0-v2.0.0-adafruit.0-21-g887cc30.bin b/bootloaders/hallowingM0/bootloader-hallowing_m0-v2.0.0-adafruit.0-21-g887cc30.bin
new file mode 100644
index 000000000..608f912d7
Binary files /dev/null and b/bootloaders/hallowingM0/bootloader-hallowing_m0-v2.0.0-adafruit.0-21-g887cc30.bin differ
diff --git a/bootloaders/hallowingM0/bootloader-hallowing_m0-v2.0.0-adafruit.0-21-g887cc30.elf b/bootloaders/hallowingM0/bootloader-hallowing_m0-v2.0.0-adafruit.0-21-g887cc30.elf
new file mode 100644
index 000000000..2a3e19c87
Binary files /dev/null and b/bootloaders/hallowingM0/bootloader-hallowing_m0-v2.0.0-adafruit.0-21-g887cc30.elf differ
diff --git a/bootloaders/hallowingM0/update-bootloader-hallowing_m0-v2.0.0-adafruit.0-21-g887cc30.uf2 b/bootloaders/hallowingM0/update-bootloader-hallowing_m0-v2.0.0-adafruit.0-21-g887cc30.uf2
new file mode 100644
index 000000000..bb4afab70
Binary files /dev/null and b/bootloaders/hallowingM0/update-bootloader-hallowing_m0-v2.0.0-adafruit.0-21-g887cc30.uf2 differ
diff --git a/bootloaders/itsybitsyM0/bootloader-itsybitsy_m0-v2.0.0-adafruit.5.bin b/bootloaders/itsybitsyM0/bootloader-itsybitsy_m0-v2.0.0-adafruit.5.bin
new file mode 100755
index 000000000..21c1fd5bb
Binary files /dev/null and b/bootloaders/itsybitsyM0/bootloader-itsybitsy_m0-v2.0.0-adafruit.5.bin differ
diff --git a/bootloaders/itsybitsyM0/bootloader-itsybitsy_m0-v2.0.0-adafruit.5.elf b/bootloaders/itsybitsyM0/bootloader-itsybitsy_m0-v2.0.0-adafruit.5.elf
new file mode 100755
index 000000000..5ffb6001e
Binary files /dev/null and b/bootloaders/itsybitsyM0/bootloader-itsybitsy_m0-v2.0.0-adafruit.5.elf differ
diff --git a/bootloaders/itsybitsyM0/update-bootloader-itsybitsy_m0-v2.0.0-adafruit.5.uf2 b/bootloaders/itsybitsyM0/update-bootloader-itsybitsy_m0-v2.0.0-adafruit.5.uf2
new file mode 100644
index 000000000..e156e3988
Binary files /dev/null and b/bootloaders/itsybitsyM0/update-bootloader-itsybitsy_m0-v2.0.0-adafruit.5.uf2 differ
diff --git a/bootloaders/itsybitsyM4/bootloader-itsybitsy_m4-v2.0.0-adafruit.5.bin b/bootloaders/itsybitsyM4/bootloader-itsybitsy_m4-v2.0.0-adafruit.5.bin
new file mode 100755
index 000000000..2fe0d2c53
Binary files /dev/null and b/bootloaders/itsybitsyM4/bootloader-itsybitsy_m4-v2.0.0-adafruit.5.bin differ
diff --git a/bootloaders/itsybitsyM4/bootloader-itsybitsy_m4-v2.0.0-adafruit.5.elf b/bootloaders/itsybitsyM4/bootloader-itsybitsy_m4-v2.0.0-adafruit.5.elf
new file mode 100755
index 000000000..127247953
Binary files /dev/null and b/bootloaders/itsybitsyM4/bootloader-itsybitsy_m4-v2.0.0-adafruit.5.elf differ
diff --git a/bootloaders/itsybitsyM4/update-bootloader-itsybitsy_m4-v2.0.0-adafruit.5.uf2 b/bootloaders/itsybitsyM4/update-bootloader-itsybitsy_m4-v2.0.0-adafruit.5.uf2
new file mode 100644
index 000000000..0517c393c
Binary files /dev/null and b/bootloaders/itsybitsyM4/update-bootloader-itsybitsy_m4-v2.0.0-adafruit.5.uf2 differ
diff --git a/bootloaders/matrixportalM4/bootloader-matrixportal_m4.bin b/bootloaders/matrixportalM4/bootloader-matrixportal_m4.bin
new file mode 100644
index 000000000..9a2223ee8
Binary files /dev/null and b/bootloaders/matrixportalM4/bootloader-matrixportal_m4.bin differ
diff --git a/bootloaders/metroM0/bootloader-metro_m0-v2.0.0-adafruit.5.bin b/bootloaders/metroM0/bootloader-metro_m0-v2.0.0-adafruit.5.bin
new file mode 100755
index 000000000..7997b2ab4
Binary files /dev/null and b/bootloaders/metroM0/bootloader-metro_m0-v2.0.0-adafruit.5.bin differ
diff --git a/bootloaders/metroM0/bootloader-metro_m0-v2.0.0-adafruit.5.elf b/bootloaders/metroM0/bootloader-metro_m0-v2.0.0-adafruit.5.elf
new file mode 100755
index 000000000..489b32163
Binary files /dev/null and b/bootloaders/metroM0/bootloader-metro_m0-v2.0.0-adafruit.5.elf differ
diff --git a/bootloaders/metroM0/update-bootloader-metro_m0-v2.0.0-adafruit.5.uf2 b/bootloaders/metroM0/update-bootloader-metro_m0-v2.0.0-adafruit.5.uf2
new file mode 100644
index 000000000..1ef14126b
Binary files /dev/null and b/bootloaders/metroM0/update-bootloader-metro_m0-v2.0.0-adafruit.5.uf2 differ
diff --git a/bootloaders/metroM4/METRO_M4_sam_ba.bin b/bootloaders/metroM4/METRO_M4_sam_ba.bin
new file mode 100644
index 000000000..4ee5cdd83
Binary files /dev/null and b/bootloaders/metroM4/METRO_M4_sam_ba.bin differ
diff --git a/bootloaders/metroM4/METRO_M4_sam_ba.elf b/bootloaders/metroM4/METRO_M4_sam_ba.elf
new file mode 100644
index 000000000..6d93a4fba
Binary files /dev/null and b/bootloaders/metroM4/METRO_M4_sam_ba.elf differ
diff --git a/bootloaders/metroM4/METRO_M4_sam_ba.hex b/bootloaders/metroM4/METRO_M4_sam_ba.hex
new file mode 100644
index 000000000..79a4ed0ca
--- /dev/null
+++ b/bootloaders/metroM4/METRO_M4_sam_ba.hex
@@ -0,0 +1,457 @@
+:10000000FCFF022055060000390600003D060000F6
+:1000100041060000450600004906000000000000FF
+:100020000000000000000000000000004D0600007D
+:10003000000000000000000051060000E50700007D
+:1000400010B5054C237833B9044B13B10448AFF312
+:1000500000800123237010BD5C0000200000000020
+:10006000041C000008B5064B1BB106480649AFF357
+:1000700000800648036813B1054B03B1984708BDDB
+:1000800000000000041C0000600000205800002058
+:10009000000000001A4B1B7813F0FF0F0AD1194B18
+:1000A0001A78194909780A44D2B21A704FF400122A
+:1000B000164BDA61124B1A780132D2B21A70114B18
+:1000C0001B78DBB2F02B04D80E4B1B78DBB2092B6C
+:1000D0000AD80D4B1A785242D2B21A70094A1178D6
+:1000E0001B780B44DBB21370054B1A78054B1B7859
+:1000F000D2B29A4203D14FF40012044BDA61704736
+:100100007800002001000020000000200080004155
+:1001100010B4C36913F0020FFBD104686FF34104FC
+:100120000460C36913F0010FFBD1046844F00104BB
+:100130000460036813F0010FFBD1C36913F0010FD2
+:10014000FBD1C36913F0020FF7D142F0804343F0B3
+:1001500004030360C36913F0040FFBD14FF4403371
+:1001600043608181C36913F0020FFBD1036843F040
+:10017000020303605DF8044B704700BF037E13F079
+:10018000010FFBD081627047037E13F0040FFBD098
+:10019000438B13F0010F07D1438B13F0020F03D1F0
+:1001A000438B13F0040F02D00122024B1A70806AB5
+:1001B000C0B270477900002070B5044603689A8B7E
+:1001C00002F0080292B232B308259D8380229A720F
+:1001D000112183F80011402183F8051183F80421CF
+:1001E000114A5068032666F31E705060506966F32A
+:1001F0001E7050610D4810600D481061506865F325
+:100200009B30506050686FF30D00506083F804110C
+:100210000023237106E093F8073113F0100F01D08B
+:1002200000F022FB207970BD940100209400002092
+:10023000140100200160002303714371054B8360AA
+:100240000B7843F002030B700268937813F0020FEF
+:10025000FBD17047B901000008B5444A936943F0E7
+:1002600001039361424B93F8581041F0010183F868
+:10027000581093F83C1001F0F00183F83C1093F80B
+:100280003C1041F0070183F83C1093F8591041F0FD
+:10029000010183F8591093F83C1001F00F0183F825
+:1002A0003C1093F83C1041F0700183F83C10402161
+:1002B000304BC3F8A810936943F00103936102F532
+:1002C000A052536813F0040FFBD14FF082431A7809
+:1002D00042F001021A701A46937813F0010FFBD115
+:1002E000254B1968C1F34412C1F3822311F01F0199
+:1002F00003D01F2908BF092100E009211AB11F2AD4
+:1003000008BF192200E019221BB1072B08BF0623E2
+:1003100000E0062302F01F0242EA81111B0303F4EE
+:10032000E04319434FF082431985DA7842F0030223
+:10033000DA70DA7842F00C02DA701A786FF3C712CA
+:100340001A701A7842F004021A700C4858621A891E
+:100350006FF383021A811A8922F001021204120C2F
+:100360001A810021802201F0C6FA08BD0008004071
+:1003700000800041001C00408400800094010020A7
+:100380002DE9F041064615461C461F46214B03EB5E
+:10039000441310335B68C3F302730333012202FA80
+:1003A00003F3AB4207D81B4A02EB4412536943F0F4
+:1003B000004353610CE014F1000818BF4FF001082E
+:1003C000154B03EB881840462A4601F08BFA41464C
+:1003D000104A02EB441202F110031161526965F3F5
+:1003E0000D025A605A686FF39B325A60083406EB6C
+:1003F00044140223E371637943F08003637107F1CE
+:10040000080106EB4111CB7913F0020FFBD028460F
+:10041000BDE8F081940100201401002038B50546A4
+:1004200014461B4B1B7813F0FF0F13D1194B1A4ABC
+:100430001A645A6C6FF30D025A645A6C6FF39B3254
+:100440005A6490F8443143F0400380F8443101226B
+:100450000F4B1A7095F8473113F0010F15D00D4B63
+:100460005B6CC3F30D03A34203D20A4B5C6CC4F371
+:100470000D0408460849224601F034FA012385F8A4
+:1004800047310022024B1A7000E00024204638BD9C
+:100490007A00002094010020D400002031B190F8AF
+:1004A000053143F0200380F80531704790F805319D
+:1004B00043F0100380F80531704700BF094B5A69BB
+:1004C0006FF30D025A61022380F8073190F805316D
+:1004D00043F0800380F8053190F8073113F0020FE4
+:1004E000FAD070479401002061F07F01C9B2817297
+:1004F000704700BF10B4032280F84021104B596CA4
+:1005000062F31E715964402180F845110D4C1C6442
+:10051000302480F820415C6B62F31E745C6380229F
+:1005200080F82421084C1C6380F86011596F6FF328
+:100530001E71596780F864215DF8044B704700BF55
+:1005400094010020D400002054010020344B1A886C
+:1005500092B21A8042F20E02324B9A821A46D36845
+:1005600013F0010FFBD02F4B1A7C6FF302021A74A9
+:1005700003F500631A7842F001021A701A465368B4
+:1005800013F0010FFBD140F20512274BDA621A4635
+:10059000536813F0200FFBD14FF48272224B1A6282
+:1005A000A3F5406300221A77204A9A621A4692F80D
+:1005B0002C3013F0100FFAD100221D4B83F82020AD
+:1005C0001A4692F82C3013F0040FFAD1184B1A7F08
+:1005D00042F002021A771A4692F82C3013F0020FFA
+:1005E000FAD1134B5A6A5A621A4692F82C3013F019
+:1005F000080FFAD198220E4B83F820201A4613696F
+:1006000013F4807FFBD040F60632074B1A621A467D
+:10061000536813F0040FFBD10122064B5A71704747
+:100620000040004100140040001C00400000010494
+:1006300000100040000800400EBEFEE70DBEFEE7C1
+:100640000DBEFEE70DBEFEE70DBEFEE705BEFEE7F2
+:1006500002BEFEE710B5174B174A9A4215D0134653
+:10066000164A9A4211D0134B134A9A420DD2131DC7
+:10067000134CE41A24F003040434002310460F49F9
+:100680005A581A500433A342FAD10E4B0E4A9A42DA
+:100690000CD00BD2131D0D49C91A21F003011944C6
+:1006A000043B002243F8042B8B42FBD100F010F8EE
+:1006B000FEE700BF5C00002000000020081C0000D6
+:1006C0005F000020A40300205C000020A70300209E
+:1006D00070B5394B1B68B3F1FF3F2DD0374A384B0B
+:1006E0001A60043A12F07F0F26D1364B1B7813F0B4
+:1006F000010F03D00021344B196011E0324B19680F
+:10070000324B994203D100222F4B1A6014E02F493B
+:100710002D4B19602E4B013BFDD100212A4B196056
+:10072000254B1B6883F3088822F07F02294B9A60CF
+:10073000234B1B681B681847FFF708FF62B600F0E1
+:10074000D1FE00F055F80546234B4FF400129A6095
+:100750004022C3F88820C3F898204FF000629A60C6
+:100760009A611E4B40F2E7325A60C021194A82F862
+:10077000231000229A6007221A60194C0126AB68E8
+:100780002846984700B12670237813F0FF0F05D054
+:10079000002000F02DFB00F0C5FBFCE7237813F0F0
+:1007A000FF0FECD100F016FF0028E8D0012000F088
+:1007B0001FFB00F0B7FBFCE7004000000440000016
+:1007C00014020020000C0040FCFF0220EF6916F02C
+:1007D000808D5B0000ED00E00080004110E000E053
+:1007E0007B00002008B5FFF755FC00F077FB08BD43
+:1007F00010B5064C4FF082432360FFF72DFD2046D5
+:100800002168FFF717FD204610BD00BF1802002029
+:10081000F0B5C1B007460E461546084601F073F81C
+:100820004000831C8DF8003003238DF801303378AD
+:1008300073B16D08012D0DDD6C463146012224F89F
+:10084000023F013211F8013F2BB1AA42F7DB02E06F
+:10085000012200E001223846694652000023FFF7DA
+:100860008FFD41B0F0BD00BFF0B583B0064604680F
+:10087000102384F80731A04B1A78A04D2A705A78BB
+:100880009F490A7098789F4A1080108880B2DF785C
+:1008900040EA0720108018799B4A1080108880B2A7
+:1008A0005F7940EA072010809879984A1080108874
+:1008B00080B2DB7940EA03231380402384F80431BB
+:1008C0000A782B7843EA022340F20232934200F086
+:1008D0002D811EDCB3F5807F00F0598109DC812B6E
+:1008E00000F0C880822B00F0CD80802B40F0F0819A
+:1008F000B8E0B3F5817F00F05381C0F24D81B3F5CC
+:10090000407F00F0EF8040F20132934200F0EF8030
+:10091000DEE1B3F5106F00F093800BDCB3F5D06F20
+:100920001FD0B3F5086F00F09580B3F5A06F40F0CD
+:10093000CF817BE042F22102934200F0AF8105DCDF
+:1009400040F60132934200F02281C1E142F2A1124D
+:10095000934200F0A78142F22122934200F0B1813C
+:10096000B6E1684B1B88C3F30723012B0ED1306817
+:10097000664B1B889BB2122B9DBF644B1A8892B2A8
+:10098000122263490023FFF7FBFCA5E15D4B1B88A6
+:10099000C3F30723022B0ED130685C4B1B889BB23C
+:1009A000432B9DBF594B1A8892B2432259490023C9
+:1009B000FFF7E6FC90E1534B1B88C3F30723032B9F
+:1009C0002FD1504B1B88DBB2012B15D013B1022B5A
+:1009D0001AD021E0504B1868019030684B4B1B88AF
+:1009E0009BB2042B9DBF494B1A8892B2042201A9E5
+:1009F0000023FFF7C5FC6FE1444B1A883068474974
+:100A0000D2B2FFF705FF67E1404B1A8830684449CE
+:100A1000D2B2FFF7FDFE5FE120460121FFF73EFD68
+:100A20005AE120460121FFF739FD55E12046FFF745
+:100A300045FD344B1988306889B2FFF755FD4BE10D
+:100A4000304B1B8833712046FFF738FD2046FFF7F7
+:100A500051FD41E1314651F8040B01220023FFF71B
+:100A60008FFC39E12F4900230B8030680222FFF709
+:100A700087FC31E12B4900230B8030680222FFF70D
+:100A80007FFC29E10022274B1A801F4B198801F0B7
+:100A90005001254A11701A8802F00F021A801B8833
+:100AA0009BB2032B19D8204B1B7813F0FF0F164B6A
+:100AB0001B889BB203F1080304EB4314A27914BF13
+:100AC000C2F34012C2F30012164B1A803068154967
+:100AD00002220023FFF754FCFEE020460121FFF72D
+:100AE000DDFCF9E020460121FFF7D8FCF4E02046C8
+:100AF000FFF7E4FCF0E000BF94000020830000203A
+:100B0000860000207C000020800000207E00002065
+:100B10004C190000040000203019000034190000B6
+:100B20004019000084000020820000206B4B1988CF
+:100B300089B221F07F01C9B2694A11701A8802F0A6
+:100B40000F021A80674B1B889BB2DBB9634B1B8873
+:100B50009BB2BBB1614B1B889BB2032B12D8604B7D
+:100B60001B7813F0FF0F5D4B1B889BB203F108034A
+:100B700004EB431314BF202210225A712046FFF7C2
+:100B80009DFCA9E020460121FFF788FCA4E0204657
+:100B90000121FFF783FC9FE02046FFF78FFC9BE0DD
+:100BA0004E4B198889B221F07F01C9B24C4A1170AD
+:100BB0001A8802F00F021A804A4B1B889BB2002B46
+:100BC00067D1464B1B889BB2002B62D0434B1B88DE
+:100BD0009BB2032B5DD8424B1B7813F0FF0F2AD03A
+:100BE0003E4B1B889BB2083304EB43139B7913F0F5
+:100BF000200F4AD0394B1A8892B2083204EB4212C5
+:100C0000202111711B889BB2083304EB4313DB795D
+:100C100013F0400F39D0314B1A8892B2083204EBEE
+:100C200042124021D1711B889BB2083304EB43135D
+:100C300002221A7129E0294B1B889BB2083304EB6E
+:100C400043139B7913F0100F1FD0244B1A8892B2D4
+:100C5000083204EB4212102111711B889BB2083339
+:100C600004EB4313DB7913F0200F0ED01B4B1A88D3
+:100C700092B2083204EB42122021D1711B889BB240
+:100C8000083304EB431301221A712046FFF716FCC8
+:100C900022E020460121FFF701FC1DE02046FFF77E
+:100CA0000DFC19E03068104B1B889BB2082B9DBFD0
+:100CB0000D4B1A8892B208220C490023FFF760FB03
+:100CC0000AE0084B1B8873712046FFF7F7FB03E02F
+:100CD00020460121FFF7E2FB03B0F0BD80000020B9
+:100CE000820000207C0000207E00002048000020C0
+:100CF00000B583B002A941F8040D054B1868012224
+:100D00001346FFF73DFB012003B05DF804FB00BF75
+:100D10001802002000B583B0054B18680DF10701DB
+:100D20000122FFF77BFB9DF8070003B05DF804FB91
+:100D30001802002008B50648FFF73EFA30B1044B10
+:100D40001B6893F8470100F0010008BD002008BDB2
+:100D50001802002010B503460C46044A10681946D4
+:100D600022460123FFF70CFB204610BD180200208D
+:100D700038B505460C460648FFF71EFA30B1044B5D
+:100D8000186829462246FFF749FB38BD002038BDC8
+:100D900018020020F8B505460F460B48FFF70CFA7D
+:100DA00058B167B13C46084E306829462246FFF7E5
+:100DB00035FB0544241AF7D103E00020F8BD38467E
+:100DC000F8BD3846F8BD00BF1802002008B5C3685A
+:100DD0000846114698474FF00062034B5A6164225F
+:100DE000024B1A8008BD00BF008000419000002027
+:100DF000012806D1054A064B1A600122054B1A70DC
+:100E0000704710B9044A024B1A60704780190000FD
+:100E10008802002092000020D819000070B584B02C
+:100E200004460A46244B1B7813F0FF0F34D00429E4
+:100E300001D1036836E0022901D1038832E003784A
+:100E40004E0004AC34440B3C86BB0CE003F00F05B1
+:100E5000092D94BF45F03005373565701B09013009
+:100E6000013CB042F2D330238DF8043078238DF862
+:100E700005300132520004AB13440A2103F80C1C64
+:100E800004AB1E440D2306F8093C0C4B186801A95D
+:100E90000232FFF79BFF0CE0084B18682146FFF772
+:100EA00095FF06E0560004AC34440B3C013C0020A6
+:100EB000CCE704B070BD00BF8C0000208802002089
+:100EC00072B6EFF30882044B1A60036883F3088854
+:100ED00043681847704700BF8C0200200E4B1B88E8
+:100EE0009BB24BB10C4A1388013B9BB213801BB9D8
+:100EF0004FF00062094B9A61094B1B889BB24BB1C2
+:100F0000074A1388013B9BB213801BB94022034B55
+:100F1000C3F89820704700BF900000200080004177
+:100F20008E0000202DE9F0438BB002AC894D0FCD2F
+:100F30000FC495E80F0084E80F00874A9368C3F355
+:100F400002430AA901EB830353F8203C83490B6059
+:100F5000926892B282490A6002FB03F381490B60F6
+:100F60000022814B1A607A22804B1A707A4C7B4D9A
+:100F70007F4B1B681B697F4840219847034630B16F
+:100F800040217D4AC2F8941064217C4A11807C4A39
+:100F9000136078497B4A116000217B4A1160002B65
+:100FA000E6D0784B1B681B78FF2B00F06682232B62
+:100FB00040F00482754B1B7813F0FF0F05D06C4B8B
+:100FC000186873490222FFF701FF684B1B78532B07
+:100FD00044D16B4B1B686C4A126893421FD9694815
+:100FE0000168013101600132674802609A1A694B59
+:100FF00018688242684B34BF1A601860664E5A4BBC
+:101000001868326800F06EFC33685F4A1168194452
+:1010100011605C4A116819441160604A13705A4BA0
+:101020001A68013A1A60574B1A68013A1A605B4B0A
+:101030001B78584A11688B420ED24D4A1268926949
+:1010400049480068C91A904730B140224A4BC3F85A
+:1010500094206422494B1A8000BF9DE1522B0FD18E
+:10106000434B1B685B69404A10684A4A11689847BD
+:101070004FF00062404B5A616422494B1A808BE169
+:101080004F2B05D1384B1B68424A12681A7083E116
+:10109000482B05D1344B1B683E4A12681A807BE10D
+:1010A000572B05D1304B1A683A4B1B68136073E11C
+:1010B0006F2B05D12C4B18680121FFF7AFFE6BE1B8
+:1010C000682B08D13348284B1B681B88036002211A
+:1010D000FFF7A4FE60E1772B08D1234B1B681B6848
+:1010E0002C4803600421FFF799FE55E1472B14D1EA
+:1010F000284B1868FFF7E4FE2A4B1B6883F3088827
+:1011000062B6294B1B7813F0FF0F00F04581184B96
+:101110001B681B68062098473EE1542B09D1012229
+:101120001A4B1A70124B186819490222FFF74EFE2B
+:1011300032E14E2B3AD1154B1B7813F0FF0F05D13E
+:101140000B4B186812490222FFF740FE00220F4B9A
+:101150001A7021E1601900000040004140020020A7
+:1011600038020020340200208402002030020020D7
+:101170008802002044020020008000418E000020F0
+:10118000280200202C0200203C0200208C000020BD
+:10119000A0190000900200209402002024020020E8
+:1011A000900000208C02002092000020562B57D186
+:1011B000994E306899490122FFF708FE3068984936
+:1011C0000322FFF703FE974F306839460122FFF7ED
+:1011D000FDFD306894490D22FFF7F8FD306839466F
+:1011E0000122FFF7F3FD914B0021914A1160591C38
+:1011F000904A11601B78002B00F04D818C490B68E0
+:1012000001330B601368581C10601B78002BF6D15B
+:10121000814F874E386885493268FFF7D7FD3868B7
+:1012200080490122FFF7D2FD00233360824A814BBF
+:101230001A6041E10B6801330B601368581C1060A1
+:101240001B78002BF6D1744E30687C49784B1A68B5
+:10125000FFF7BCFD30687A490222FFF7B7FD9BE03B
+:10126000582B1DD1774B1A68774B19688A4210D2D8
+:101270002E6836014AF20150638A13F0010FFBD049
+:101280006261A080638A13F0010FFBD032448A426E
+:10129000F2D3614B18686D490322FFF797FD7BE09D
+:1012A000592B44D1674B186820B9694B1A68694BB0
+:1012B0001A6035E0674B1F68654B1E6823889BB238
+:1012C000238080082CD04AF215584FF0000EF146CA
+:1012D0004AF2035CA4F80480638A13F0010FFBD088
+:1012E0002B68032B0DD970B172464B46B958B150DB
+:1012F00001332968B3EB910F06D204328342F5D152
+:1013000002E0734600E073466661A4F804C0628A96
+:1013100012F0010FFBD09A0016441744C01AD9D11D
+:101320003D4B18684C490322FFF750FD34E05A2B1F
+:1013300032D1474B1E68434B1B685BB106EB030879
+:10134000002716F8010B394600F068F907464645B4
+:10135000F7D100E00027304B186840490122FFF721
+:1013600035FD3A460DF107030DF1FF3002F00F0194
+:1013700012090929CCBF3731303103F801198342F2
+:10138000F4D1254E306869460822FFF71FFD30680A
+:1013900033490322FFF71AFD7A22324B1A700022DA
+:1013A000284B1A60304B1B7813F0FF0F65D01A4B97
+:1013B00018682E490122FFF709FD5EE0A3F1300213
+:1013C000D2B2092A06D81F4A303B116843EA0111FC
+:1013D000116052E0A3F14102D2B2052A06D8194A9F
+:1013E000373B116843EA0111116046E0A3F1610245
+:1013F000D2B2052A06D8134A573B116843EA0111B5
+:1014000011603AE02C2B33D10E4B1A6810490A6058
+:1014100000221A6031E000BF88020020A4190000F9
+:101420009C190000A8190000F4190000AC19000074
+:101430003C0200202C020020B9190000B81900005D
+:10144000A01900009002002034020020C4190000FE
+:101450008402002088000020C8190000CC19000078
+:10146000D0190000300200208C000020D4190000A8
+:10147000134A13700022134B1A60134A1368013386
+:101480001360124A116801311160114A12689342C7
+:10149000FFF487AD6CE50F4F0B4E38680E4932688C
+:1014A000FFF794FC38680D490122FFF78FFC0023F9
+:1014B00033600B4A054B1A600349044ABAE600BF81
+:1014C00030020020900200203C0200202C0200206C
+:1014D0002802002088020020AC190000A819000092
+:1014E000B919000008B5234B4022C3F89C204322C1
+:1014F000C3F88C20A3F5A0535A6942F480525A6174
+:101500001D4B93F84B2042F0010283F84B2093F8D7
+:10151000352002F00F0283F8352093F8352042F091
+:10152000200283F8352093F84A2042F0010283F824
+:101530004A2093F8352002F0F00283F8352093F822
+:10154000352042F0020283F835200C484FF22A6120
+:101550004FF44412FEF7DCFD0023094A1370094AD8
+:101560001370094A1370094A1370094A1370094A23
+:10157000137008BD001C0040008000410030004096
+:101580009802002022030020990200209C020020E3
+:10159000230300202003002008B5C1B20248FEF753
+:1015A000EDFD012008BD00BF00300040024B187E59
+:1015B000C0F38000704700BF0030004008B5FFF75F
+:1015C000F5FF0028FBD00248FEF7DEFD08BD00BF96
+:1015D0000030004008B5FFF7E9FF30B1FFF7EEFF3C
+:1015E000232814BF0020012008BD002008BD00BF33
+:1015F00070B504460E4631B1451814F8010BFFF7DB
+:10160000CBFFAC42F9D1304670BD00BF10B50446E7
+:10161000FFF7D4FF2070012010BD00BF80EA112029
+:10162000034B33F8103083EA012080B2704700BFCB
+:10163000041A00002DE9F84F0646884649B30024F5
+:101640002746DFF860A0DFF86090DFF860B0FFF7B2
+:10165000B5FFC5B29AF80030F3B928463946FFF70E
+:10166000DDFF0746B9F8003013B99BF800305BB1D5
+:10167000731C3570B8F1800F02BFB9F8002002F179
+:10168000FF32A9F800201E460134A4B24445DED141
+:1016900005E00020BDE8F88F0120BDE8F88F38464E
+:1016A000BDE8F88F200300209A02002021030020CB
+:1016B0002DE9F04F83B001900022454B1A70009144
+:1016C00019B90122434B1A700DE0434B009A1A805E
+:1016D0000022404B1A70009B13F07F0F03D0803321
+:1016E00023F07F0300933A4C0025FFF767FF237830
+:1016F0004BB12570FFF762FFC0B2237823B10024FD
+:10170000334B1C705FE0C0B2432821D0712859D000
+:101710001528EAD11CE000222D4B1A7053E0C0B20C
+:10172000062809D10BF1010B5FFA8BFB009A803A76
+:101730000092019B80330193009A7AB90420FFF74D
+:101740002BFFFFF73BFF0022224B1A7001243AE0E7
+:101750004FF0010BDFF88080DFF878900120FFF771
+:101760001BFF5846FFF718FF6FEA0B00C0B2FFF7E8
+:1017700013FF019E80240027BA46B8F8003013B941
+:1017800099F800202AB13578013BA8F800300136DD
+:1017900000E055462846FFF7FFFE28463946FFF78A
+:1017A0003DFF0746013CE8D1C0F30720FFF7F4FEF8
+:1017B000F8B2FFF7F1FEFFF701FF054B1B78002B96
+:1017C000ADD0A8E70024204603B0BDE8F08F00BFED
+:1017D00020030020210300209A0200202DE9F0437D
+:1017E00083B0074600223B4B1A7019B901223A4BCD
+:1017F0001A7004E0394A11800022374B1A706425B0
+:101800004FF04308364E4046FFF7C6FE344600E030
+:10181000013CFFF7CBFE10B9002CF9D100E014B960
+:10182000013DF0D151E001262A4C0225FFF7C6FE0A
+:1018300022781AB10025274B1D7046E0C3B2012B58
+:1018400002D0042B34D036E001A82946FFF7F2FE7F
+:1018500038468021FFF7EEFE8046237883BBFFF7F2
+:10186000ADFE00021FFA80F9FFF7A8FE484480B2DF
+:101870002378012B24D0804509D19DF80430B34250
+:1018800005D1F3439DF80520DBB29A4203D018201E
+:10189000FFF782FE14E00620FFF77EFE23781BB1DF
+:1018A00000250C4B1D7010E00136F6B28037BDE705
+:1018B0000620FFF771FE0022074B1A70012504E095
+:1018C000044B1B78002BF6D0EAE7284603B0BDE8AE
+:1018D000F08300BF20030020210300209A02002093
+:1018E00000350C0010B50023934203D0CC5CC454E7
+:1018F0000133F9E710BD02440346934202D003F8D6
+:10190000011BFAE77047034613F8012B002AFBD1AD
+:10191000181A013870470000F8B500BFF8BC08BCC1
+:101920009E467047F8B500BFF8BC08BC9E4670479D
+:101930000403090441726475696E6F204C4C4300C6
+:101940004D6574726F204D340000000012010002DA
+:10195000020000409A232000000201020001000062
+:1019600008000000100000002000000040000000FF
+:1019700080000000000100000002000000040000E0
+:1019800099150000BD150000AD150000F11500000F
+:101990000D160000B1160000DD170000322E3000D9
+:1019A0000A0D000076000000200000004E6F762037
+:1019B000203620323031370031313A30393A33383D
+:1019C00000000000580A0D00590A0D005A000000DE
+:1019D000230A0D003E000000F10C0000150D000070
+:1019E000350D0000550D0000710D0000550D000073
+:1019F000950D00005B41726475696E6F3A58595AD3
+:101A00005D00000000002110422063308440A5509A
+:101A1000C660E770088129914AA16BB18CC1ADD134
+:101A2000CEE1EFF13112100273325222B5529442DC
+:101A3000F772D662399318837BB35AA3BDD39CC384
+:101A4000FFF3DEE36224433420040114E664C77428
+:101A5000A44485546AA54BB528850995EEE5CFF5D4
+:101A6000ACC58DD55336722611163006D776F6667C
+:101A70009556B4465BB77AA719973887DFF7FEE724
+:101A80009DD7BCC7C448E5588668A7784008611848
+:101A900002282338CCC9EDD98EE9AFF94889699974
+:101AA0000AA92BB9F55AD44AB77A966A711A500A1C
+:101AB000333A122AFDDBDCCBBFFB9EEB799B588BC4
+:101AC0003BBB1AABA66C877CE44CC55C222C033C68
+:101AD000600C411CAEED8FFDECCDCDDD2AAD0BBD14
+:101AE000688D499D977EB66ED55EF44E133E322EBC
+:101AF000511E700E9FFFBEEFDDDFFCCF1BBF3AAF64
+:101B0000599F788F8891A981CAB1EBA10CD12DC1C1
+:101B10004EF16FE18010A100C230E3200450254057
+:101B200046706760B9839893FBA3DAB33DC31CD3B7
+:101B30007FE35EF3B1029012F322D23235421452A7
+:101B400077625672EAB5CBA5A89589856EF54FE503
+:101B50002CD50DC5E234C324A014810466744764F7
+:101B600024540544DBA7FAB79987B8975FE77EF757
+:101B70001DC73CD7D326F2369106B0165766767647
+:101B8000154634564CD96DC90EF92FE9C899E98923
+:101B90008AB9ABA94458654806782768C018E10897
+:101BA0008238A3287DCB5CDB3FEB1EFBF98BD89BF7
+:101BB000BBAB9ABB754A545A376A167AF10AD01AE7
+:101BC000B32A923A2EFD0FED6CDD4DCDAABD8BAD43
+:101BD000E89DC98D267C076C645C454CA23C832C37
+:101BE000E01CC10C1FEF3EFF5DCF7CDF9BAFBABF97
+:101BF000D98FF89F176E367E554E745E932EB23E87
+:081C0000D10EF01E00000000EF
+:101C080001140000090243000201008032090400A7
+:101C1800000102020000052400100104240200054E
+:101C2800240600010524010001070583030800FFBD
+:101C380009040100020A00000007058102400000B3
+:101C4800070502024000000000C201000000080071
+:0C1C5800650000004100000000000000DA
+:04000003000006559E
+:00000001FF
diff --git a/bootloaders/metroM4/Makefile b/bootloaders/metroM4/Makefile
new file mode 100644
index 000000000..c84424084
--- /dev/null
+++ b/bootloaders/metroM4/Makefile
@@ -0,0 +1,165 @@
+# Copyright (c) 2015 Atmel Corporation/Thibaut VIARD.  All right reserved.
+# Copyright (c) 2015 Arduino LLC.  All right reserved.
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+# -----------------------------------------------------------------------------
+# Paths
+ifeq ($(OS),Windows_NT)
+  # Are we using mingw/msys/msys2/cygwin?
+  ifeq ($(TERM),xterm)
+    T=$(shell cygpath -u $(LOCALAPPDATA))
+    MODULE_PATH?=$(T)/Arduino15/packages/arduino
+    RM=rm
+    SEP=/
+  else
+    MODULE_PATH?=$(LOCALAPPDATA)/Arduino15/packages/arduino
+    RM=rm
+    SEP=\\
+  endif
+else
+  UNAME_S := $(shell uname -s)
+
+  ifeq ($(UNAME_S),Linux)
+    MODULE_PATH?=$(HOME)/.arduino15/packages/arduino
+    RM=rm
+    SEP=/
+  endif
+
+  ifeq ($(UNAME_S),Darwin)
+    MODULE_PATH?=$(HOME)/Library/Arduino15/packages/arduino/
+    RM=rm
+    SEP=/
+  endif
+endif
+
+ARM_GCC_PATH?=$(MODULE_PATH)/tools/arm-none-eabi-gcc/4.8.3-2014q1/bin/arm-none-eabi-
+BUILD_PATH=build
+
+# -----------------------------------------------------------------------------
+# Tools
+CC=$(ARM_GCC_PATH)gcc
+OBJCOPY=$(ARM_GCC_PATH)objcopy
+NM=$(ARM_GCC_PATH)nm
+SIZE=$(ARM_GCC_PATH)size
+
+# -----------------------------------------------------------------------------
+# Compiler options
+CFLAGS_EXTRA=-D$(BOARD_CHIP) -DBOARD_ID_$(BOARD_ID)
+CFLAGS=-mthumb -mcpu=cortex-m4 -c -std=gnu99 -MD -MP -MF "$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -MT"$(@:%.o=%.o)" -ffunction-sections -fdata-sections -nostdlib -nostartfiles --param max-inline-insns-single=500
+ifdef DEBUG
+  CFLAGS+=-g3 -O1 -DDEBUG=1
+else
+  CFLAGS+=-Os -DDEBUG=0
+endif
+
+ELF=$(BOARD_ID)_sam_ba.elf
+BIN=$(BOARD_ID)_sam_ba.bin
+HEX=$(BOARD_ID)_sam_ba.hex
+
+
+INCLUDES=-I"$(MODULE_PATH)/tools/CMSIS/4.5.0/CMSIS/Include/" -I"$(MODULE_PATH)/tools/CMSIS-Atmel/1.1.0/CMSIS/Device/ATMEL/"
+
+# -----------------------------------------------------------------------------
+# Linker options
+LDFLAGS=-mthumb -mcpu=cortex-m4 -Wall -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--unresolved-symbols=report-all
+LDFLAGS+=-Wl,--warn-common -Wl,--warn-section-align -Wl,--warn-unresolved-symbols --specs=nano.specs --specs=nosys.specs
+
+# -----------------------------------------------------------------------------
+# Source files and objects
+SOURCES= \
+  board_driver_led.c \
+  board_driver_serial.c \
+  board_driver_usb.c \
+  board_init.c \
+  board_startup.c \
+  main.c \
+  sam_ba_usb.c \
+  sam_ba_cdc.c \
+  sam_ba_monitor.c \
+  sam_ba_serial.c
+
+OBJECTS=$(addprefix $(BUILD_PATH)/, $(SOURCES:.c=.o))
+DEPS=$(addprefix $(BUILD_PATH)/, $(SOURCES:.c=.d))
+
+ifneq "test$(AVRSTUDIO_EXE_PATH)" "test"
+  AS_BUILD=copy_for_atmel_studio
+  AS_CLEAN=clean_for_atmel_studio
+else
+  AS_BUILD=
+  AS_CLEAN=
+endif
+
+
+all: print_info $(SOURCES) $(BIN) $(HEX) $(AS_BUILD)
+
+$(ELF): Makefile $(BUILD_PATH) $(OBJECTS)
+	@echo ----------------------------------------------------------
+	@echo Creating ELF binary
+	"$(CC)" -L. -L$(BUILD_PATH) $(LDFLAGS) -Os -Wl,--gc-sections -save-temps -Tbootloader_$(BOARD_ID).ld -Wl,-Map,"$(BUILD_PATH)/$(NAME).map" -o "$(BUILD_PATH)/$(ELF)" -Wl,--start-group $(OBJECTS) -lm -Wl,--end-group
+	"$(NM)" "$(BUILD_PATH)/$(ELF)" >"$(BUILD_PATH)/$(NAME)_symbols.txt"
+	"$(SIZE)" --format=sysv -t -x $(BUILD_PATH)/$(ELF)
+
+$(BIN): $(ELF)
+	@echo ----------------------------------------------------------
+	@echo Creating flash binary
+	"$(OBJCOPY)" -O binary $(BUILD_PATH)/$< $@
+
+$(HEX): $(ELF)
+	@echo ----------------------------------------------------------
+	@echo Creating flash binary
+	"$(OBJCOPY)" -O ihex $(BUILD_PATH)/$< $@
+
+$(BUILD_PATH)/%.o: %.c
+	@echo ----------------------------------------------------------
+	@echo Compiling $< to $@
+	"$(CC)" $(CFLAGS) $(CFLAGS_EXTRA) $(INCLUDES) $< -o $@
+	@echo ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+$(BUILD_PATH):
+	@echo ----------------------------------------------------------
+	@echo Creating build folder
+	-mkdir $(BUILD_PATH)
+
+print_info:
+	@echo ----------------------------------------------------------
+	@echo Compiling bootloader using
+	@echo BASE PATH = $(MODULE_PATH)
+	@echo GCC  PATH = $(ARM_GCC_PATH)
+#	@echo OS        = $(OS)
+#	@echo SHELL     = $(SHELL)
+#	@echo TERM      = $(TERM)
+#	"$(CC)" -v
+#	env
+
+copy_for_atmel_studio: $(BIN) $(HEX)
+	@echo ----------------------------------------------------------
+	@echo Atmel Studio detected, copying ELF to project root for debug
+	cp $(BUILD_PATH)/$(ELF) .
+
+clean_for_atmel_studio:
+	@echo ----------------------------------------------------------
+	@echo Atmel Studio detected, cleaning ELF from project root
+	-$(RM) ./$(ELF)
+
+clean: $(AS_CLEAN)
+	@echo ----------------------------------------------------------
+	@echo Cleaning project
+	-$(RM) $(BIN)
+	-$(RM) $(HEX)
+	-$(RM) $(BUILD_PATH)/*.*
+	-rmdir $(BUILD_PATH)
+
+.phony: print_info $(BUILD_PATH)
diff --git a/bootloaders/metroM4/README.md b/bootloaders/metroM4/README.md
new file mode 100644
index 000000000..98b045e12
--- /dev/null
+++ b/bootloaders/metroM4/README.md
@@ -0,0 +1,86 @@
+# Metro M4 Bootloader
+
+## 1- Prerequisites
+
+The project build is based on Makefile system.
+Makefile is present at project root and try to handle multi-platform cases.
+
+Multi-plaform GCC is provided by ARM here: https://launchpad.net/gcc-arm-embedded/+download
+
+Atmel Studio contains both make and ARM GCC toolchain. You don't need to install them in this specific use case.
+
+### Windows
+
+* Native command line
+Make binary can be obtained here: http://gnuwin32.sourceforge.net/packages/make.htm
+
+* Cygwin/MSys/MSys2/Babun/etc...
+It is available natively in all distributions.
+
+* Atmel Studio
+An Atmel Studio **7** Makefile-based project is present at project root, just open samd21_sam_ba.atsln file in AS7.
+
+### Linux
+
+Make is usually available by default.
+
+### OS X
+
+Make is available through XCode package.
+
+
+## 2- Selecting available SAM-BA interfaces
+
+By default both USB and UART are made available, but this parameter can be modified in sam_ba_monitor.h, line 31:
+
+Set the define SAM_BA_INTERFACE to
+* SAM_BA_UART_ONLY for only UART interface
+* SAM_BA_USBCDC_ONLY for only USB CDC interface
+* SAM_BA_BOTH_INTERFACES for enabling both the interfaces
+
+## 3- Behaviour
+
+This bootloader implements the double-tap on Reset button.
+By quickly pressing this button two times, the board will reset and stay in bootloader, waiting for communication on either USB or USART.
+
+The USB port in use is the USB Native port, close to the Reset button.
+
+The USART in use is the one available on pins D0/D1, labelled respectively RX/TX. Communication parameters are a baudrate at 115200, 8bits of data, no parity and 1 stop bit (8N1).
+
+## 4- Description
+
+**Pinmap**
+
+The following pins are used by the program :
+PA25 : input/output (USB DP)
+PA24 : input/output (USB DM)
+
+PA23 : input (USART RX)
+PA22 : output (USART TX)
+
+The application board shall avoid driving the PA25, PA24, PB23 and PB22 signals while the boot program is running (after a POR for example).
+
+**Clock system**
+
+CPU runs at 48MHz from Generic Clock Generator 0 on DFLL48M.
+
+Generic Clock Generator 1 is using external 32kHz oscillator and is the source of DFLL48M.
+
+USB and USART are using Generic Clock Generator 0 also.
+
+**Memory Mapping**
+
+Bootloader code will be located at 0x0 and executed before any applicative code.
+
+Applications compiled to be executed along with the bootloader will start at 0x2000 (see linker script bootloader_samdx1.ld).
+
+Before jumping to the application, the bootloader changes the VTOR register to use the interrupt vectors of the application @0x2000.<- not required as application code is taking care of this.
+
+## 5- How to build
+
+If not specified the makefile builds for **Metro M4**:
+
+```
+make
+```
+
diff --git a/bootloaders/metroM4/board_definitions.h b/bootloaders/metroM4/board_definitions.h
new file mode 100644
index 000000000..e350d4864
--- /dev/null
+++ b/bootloaders/metroM4/board_definitions.h
@@ -0,0 +1,32 @@
+/*
+  Copyright (c) 2015 Arduino LLC.  All right reserved.
+  Copyright (c) 2015 Atmel Corporation/Thibaut VIARD.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#if defined(BOARD_ID_METRO_M4)
+	#include "board_definitions_metro_m4.h"
+#elif defined(BOARD_ID_FEATHER_M4)
+	#include "board_definitions_feather_m4.h"
+#else
+  #error You must define a BOARD_ID and add the corresponding definitions in board_definitions.h
+#endif
+
+// Common definitions
+// ------------------
+
+#define BOOT_PIN_MASK (1U << (BOOT_LOAD_PIN & 0x1f))
+
diff --git a/bootloaders/metroM4/board_definitions_feather_m4.h b/bootloaders/metroM4/board_definitions_feather_m4.h
new file mode 100644
index 000000000..ae06f384c
--- /dev/null
+++ b/bootloaders/metroM4/board_definitions_feather_m4.h
@@ -0,0 +1,82 @@
+/*
+  Copyright (c) 2015 Arduino LLC.  All right reserved.
+  Copyright (c) 2015 Atmel Corporation/Thibaut VIARD.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _BOARD_DEFINITIONS_H_
+#define _BOARD_DEFINITIONS_H_
+
+/*
+ * USB device definitions
+ */
+#define STRING_PRODUCT "Feather M4"
+#define USB_VID_HIGH   0x23
+#define USB_VID_LOW    0x9A
+#define USB_PID_HIGH   0x00
+#define USB_PID_LOW    0x22
+
+/*
+ * If BOOT_DOUBLE_TAP_ADDRESS is defined the bootloader is started by
+ * quickly tapping two times on the reset button.
+ * BOOT_DOUBLE_TAP_ADDRESS must point to a free SRAM cell that must not
+ * be touched from the loaded application.
+ */
+#define BOOT_DOUBLE_TAP_ADDRESS           (HSRAM_ADDR + HSRAM_SIZE - 4)
+#define BOOT_DOUBLE_TAP_DATA              (*((volatile uint32_t *)BOOT_DOUBLE_TAP_ADDRESS))
+
+/*
+ * If BOOT_LOAD_PIN is defined the bootloader is started if the selected
+ * pin is tied LOW.
+ */
+//#define BOOT_LOAD_PIN                     PIN_PA21 // Pin 7
+//#define BOOT_LOAD_PIN                     PIN_PA15 // Pin 5
+
+#define GPIO(port, pin) ((((port)&0x7u) << 5) + ((pin)&0x1Fu))
+
+#define BOOK_USART_MASK					  APBAMASK
+#define BOOT_USART_MODULE                 SERCOM0
+#define BOOT_USART_BUS_CLOCK_INDEX        MCLK_APBAMASK_SERCOM0
+#define BOOT_GCLK_ID_CORE				  SERCOM0_GCLK_ID_CORE
+#define BOOT_GCLK_ID_SLOW				  SERCOM0_GCLK_ID_SLOW
+#define BOOT_USART_PAD_SETTINGS           UART_RX_PAD3_TX_PAD2
+#define BOOT_USART_PAD3                   PINMUX_UNUSED
+#define BOOT_USART_PAD2                   PINMUX_UNUSED
+
+#define BOOT_USART_PAD1                   PINMUX_PA10C_SERCOM0_PAD2
+#define BOOT_USART_PAD0                   PINMUX_PA11C_SERCOM0_PAD3
+
+/* Master clock frequency */
+#define CPU_FREQUENCY                     (48000000ul)
+#define VARIANT_MCK                       CPU_FREQUENCY
+
+/* Frequency of the board main oscillator */
+#define VARIANT_MAINOSC                   (32768ul)
+
+/* Calibration values for DFLL48 pll */
+#define NVM_SW_CALIB_DFLL48M_COARSE_VAL   (58)
+#define NVM_SW_CALIB_DFLL48M_FINE_VAL     (64)
+
+#define BOARD_LED_PORT                    (0)
+#define BOARD_LED_PIN                     (17)
+
+#define BOARD_LEDRX_PORT                  (1)
+#define BOARD_LEDRX_PIN                   (3)
+
+#define BOARD_LEDTX_PORT                  (0)
+#define BOARD_LEDTX_PIN                   (27)
+
+#endif // _BOARD_DEFINITIONS_H_
diff --git a/bootloaders/metroM4/board_definitions_metro_m4.h b/bootloaders/metroM4/board_definitions_metro_m4.h
new file mode 100644
index 000000000..7bb5357df
--- /dev/null
+++ b/bootloaders/metroM4/board_definitions_metro_m4.h
@@ -0,0 +1,82 @@
+/*
+  Copyright (c) 2015 Arduino LLC.  All right reserved.
+  Copyright (c) 2015 Atmel Corporation/Thibaut VIARD.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _BOARD_DEFINITIONS_H_
+#define _BOARD_DEFINITIONS_H_
+/*
+ * USB device definitions
+ */
+#define STRING_PRODUCT "Metro M4"
+#define USB_VID_HIGH   0x23
+#define USB_VID_LOW    0x9A
+#define USB_PID_HIGH   0x00
+#define USB_PID_LOW    0x20
+
+
+/*
+ * If BOOT_DOUBLE_TAP_ADDRESS is defined the bootloader is started by
+ * quickly tapping two times on the reset button.
+ * BOOT_DOUBLE_TAP_ADDRESS must point to a free SRAM cell that must not
+ * be touched from the loaded application.
+ */
+#define BOOT_DOUBLE_TAP_ADDRESS           (HSRAM_ADDR + HSRAM_SIZE - 4)
+#define BOOT_DOUBLE_TAP_DATA              (*((volatile uint32_t *)BOOT_DOUBLE_TAP_ADDRESS))
+
+/*
+ * If BOOT_LOAD_PIN is defined the bootloader is started if the selected
+ * pin is tied LOW.
+ */
+//#define BOOT_LOAD_PIN                     PIN_PA21 // Pin 7
+//#define BOOT_LOAD_PIN                     PIN_PA15 // Pin 5
+
+#define GPIO(port, pin) ((((port)&0x7u) << 5) + ((pin)&0x1Fu))
+
+#define BOOK_USART_MASK					  APBAMASK
+#define BOOT_USART_MODULE                 SERCOM0
+#define BOOT_USART_BUS_CLOCK_INDEX        MCLK_APBAMASK_SERCOM0
+#define BOOT_GCLK_ID_CORE				  SERCOM0_GCLK_ID_CORE
+#define BOOT_GCLK_ID_SLOW				  SERCOM0_GCLK_ID_SLOW
+#define BOOT_USART_PAD_SETTINGS           UART_RX_PAD3_TX_PAD2
+#define BOOT_USART_PAD3                   PINMUX_UNUSED
+#define BOOT_USART_PAD2                   PINMUX_UNUSED
+
+#define BOOT_USART_PAD1                   PINMUX_PA10C_SERCOM0_PAD2
+#define BOOT_USART_PAD0                   PINMUX_PA11C_SERCOM0_PAD3
+
+/* Master clock frequency */
+#define CPU_FREQUENCY                     (48000000ul)
+#define VARIANT_MCK                       CPU_FREQUENCY
+
+/* Frequency of the board main oscillator */
+#define VARIANT_MAINOSC                   (32768ul)
+
+/* Calibration values for DFLL48 pll */
+#define NVM_SW_CALIB_DFLL48M_COARSE_VAL   (58)
+#define NVM_SW_CALIB_DFLL48M_FINE_VAL     (64)
+
+#define BOARD_LED_PORT                    (0)
+#define BOARD_LED_PIN                     (21)
+
+#define BOARD_LEDRX_PORT                  (1)
+#define BOARD_LEDRX_PIN                   (6)
+
+#define BOARD_LEDTX_PORT                  (0)
+#define BOARD_LEDTX_PIN                   (27)
+
+#endif // _BOARD_DEFINITIONS_H_
diff --git a/bootloaders/metroM4/board_driver_led.c b/bootloaders/metroM4/board_driver_led.c
new file mode 100644
index 000000000..ffa6c4782
--- /dev/null
+++ b/bootloaders/metroM4/board_driver_led.c
@@ -0,0 +1,42 @@
+/*
+  Copyright (c) 2015 Arduino LLC.  All right reserved.
+  Copyright (c) 2015 Atmel Corporation/Thibaut VIARD.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "board_driver_led.h"
+
+volatile uint8_t ledKeepValue = 0;
+volatile uint8_t ledTargetValue = 20;
+volatile int8_t ledDirection = 1;
+
+inline void LED_pulse()
+{
+  if (ledKeepValue == 0) {
+    ledTargetValue += ledDirection;
+    LED_toggle();
+  }
+  ledKeepValue ++;
+
+  if (ledTargetValue > 240 || ledTargetValue < 10) {
+    ledDirection = -ledDirection;
+    ledTargetValue += ledDirection;
+  }
+
+  if (ledKeepValue == ledTargetValue) {
+    LED_toggle();
+  }
+}
diff --git a/bootloaders/metroM4/board_driver_led.h b/bootloaders/metroM4/board_driver_led.h
new file mode 100644
index 000000000..d7d47cad8
--- /dev/null
+++ b/bootloaders/metroM4/board_driver_led.h
@@ -0,0 +1,63 @@
+/*
+  Copyright (c) 2015 Arduino LLC.  All right reserved.
+  Copyright (c) 2015 Atmel Corporation/Thibaut VIARD.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _BOARD_DRIVER_LED_
+#define _BOARD_DRIVER_LED_
+
+#include <sam.h>
+#include "board_definitions.h"
+
+#if defined(BOARD_LED_PORT)
+inline void LED_init(void) { PORT->Group[BOARD_LED_PORT].DIRSET.reg = (1<<BOARD_LED_PIN); }
+inline void LED_on(void) { PORT->Group[BOARD_LED_PORT].OUTSET.reg = (1<<BOARD_LED_PIN); }
+inline void LED_off(void) { PORT->Group[BOARD_LED_PORT].OUTCLR.reg = (1<<BOARD_LED_PIN); }
+inline void LED_toggle(void) { PORT->Group[BOARD_LED_PORT].OUTTGL.reg = (1<<BOARD_LED_PIN); }
+#else
+inline void LED_init(void) { }
+inline void LED_on(void) { }
+inline void LED_off(void) { }
+inline void LED_toggle(void) { }
+#endif
+void LED_pulse();
+
+#if defined(BOARD_LEDRX_PORT)
+inline void LEDRX_init(void) { PORT->Group[BOARD_LEDRX_PORT].DIRSET.reg = (1<<BOARD_LEDRX_PIN); }
+inline void LEDRX_on(void) { PORT->Group[BOARD_LEDRX_PORT].OUTCLR.reg = (1<<BOARD_LEDRX_PIN); }
+inline void LEDRX_off(void) { PORT->Group[BOARD_LEDRX_PORT].OUTSET.reg = (1<<BOARD_LEDRX_PIN); }
+inline void LEDRX_toggle(void) { PORT->Group[BOARD_LEDRX_PORT].OUTTGL.reg = (1<<BOARD_LEDRX_PIN); }
+#else
+inline void LEDRX_init(void) { }
+inline void LEDRX_on(void) { }
+inline void LEDRX_off(void) { }
+inline void LEDRX_toggle(void) { }
+#endif
+
+#if defined(BOARD_LEDTX_PORT)
+inline void LEDTX_init(void) { PORT->Group[BOARD_LEDTX_PORT].DIRSET.reg = (1<<BOARD_LEDTX_PIN); }
+inline void LEDTX_on(void) { PORT->Group[BOARD_LEDTX_PORT].OUTCLR.reg = (1<<BOARD_LEDTX_PIN); }
+inline void LEDTX_off(void) { PORT->Group[BOARD_LEDTX_PORT].OUTSET.reg = (1<<BOARD_LEDTX_PIN); }
+inline void LEDTX_toggle(void) { PORT->Group[BOARD_LEDTX_PORT].OUTTGL.reg = (1<<BOARD_LEDTX_PIN); }
+#else
+inline void LEDTX_init(void) { }
+inline void LEDTX_on(void) { }
+inline void LEDTX_off(void) { }
+inline void LEDTX_toggle(void) { }
+#endif
+
+#endif // _BOARD_DRIVER_LED_
diff --git a/bootloaders/metroM4/board_driver_serial.c b/bootloaders/metroM4/board_driver_serial.c
new file mode 100644
index 000000000..c474c5b75
--- /dev/null
+++ b/bootloaders/metroM4/board_driver_serial.c
@@ -0,0 +1,104 @@
+ /*
+  Copyright (c) 2015 Arduino LLC.  All right reserved.
+  Copyright (c) 2015 Atmel Corporation/Thibaut VIARD.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "board_driver_serial.h"
+
+bool uart_drv_error_flag = false;
+
+void uart_basic_init(Sercom *sercom, uint16_t baud_val, enum uart_pad_settings pad_conf)
+{
+	/* Wait for synchronization */
+	while(sercom->USART.SYNCBUSY.bit.ENABLE);
+	/* Disable the SERCOM UART module */
+	sercom->USART.CTRLA.bit.ENABLE = 0;
+	/* Wait for synchronization */
+	while(sercom->USART.SYNCBUSY.bit.SWRST);
+	/* Perform a software reset */
+	sercom->USART.CTRLA.bit.SWRST = 1;
+	/* Wait for synchronization */
+	while(sercom->USART.CTRLA.bit.SWRST);
+	/* Wait for synchronization */
+	while(sercom->USART.SYNCBUSY.bit.SWRST || sercom->USART.SYNCBUSY.bit.ENABLE);
+	/* Update the UART pad settings, mode and data order settings */
+	sercom->USART.CTRLA.reg = pad_conf | SERCOM_USART_CTRLA_MODE(1) | SERCOM_USART_CTRLA_DORD;
+	/* Wait for synchronization */
+	while(sercom->USART.SYNCBUSY.bit.CTRLB);
+	/* Enable transmit and receive and set data size to 8 bits */
+	sercom->USART.CTRLB.reg = SERCOM_USART_CTRLB_RXEN | SERCOM_USART_CTRLB_TXEN | SERCOM_USART_CTRLB_CHSIZE(0);
+	/* Load the baud value */
+	sercom->USART.BAUD.reg = baud_val;
+	///* Wait for synchronization */
+	while(sercom->USART.SYNCBUSY.bit.ENABLE);
+	/* Enable SERCOM UART */
+	sercom->USART.CTRLA.bit.ENABLE = 1;
+}
+
+void uart_disable(Sercom *sercom)
+{
+	/* Wait for synchronization */
+	while(sercom->USART.SYNCBUSY.bit.ENABLE);
+	/* Disable SERCOM UART */
+	sercom->USART.CTRLA.bit.ENABLE = 0;
+}
+
+void uart_write_byte(Sercom *sercom, uint8_t data)
+{
+	/* Wait for Data Register Empty flag */
+	while(!sercom->USART.INTFLAG.bit.DRE);
+	/* Write the data to DATA register */
+	sercom->USART.DATA.reg = (uint16_t)data;
+}
+
+uint8_t uart_read_byte(Sercom *sercom)
+{
+	/* Wait for Receive Complete flag */
+	while(!sercom->USART.INTFLAG.bit.RXC);
+	/* Check for errors */
+	if (sercom->USART.STATUS.bit.PERR || sercom->USART.STATUS.bit.FERR || sercom->USART.STATUS.bit.BUFOVF)
+		/* Set the error flag */
+		uart_drv_error_flag = true;
+	/* Return the read data */
+	return((uint8_t)sercom->USART.DATA.reg);
+}
+
+void uart_write_buffer_polled(Sercom *sercom, uint8_t *ptr, uint16_t length)
+{
+	/* Do the following for specified length */
+	do {
+		/* Wait for Data Register Empty flag */
+		while(!sercom->USART.INTFLAG.bit.DRE);
+		/* Send data from the buffer */
+		sercom->USART.DATA.reg = (uint16_t)*ptr++;
+	} while (length--);
+}
+
+void uart_read_buffer_polled(Sercom *sercom, uint8_t *ptr, uint16_t length)
+{
+	/* Do the following for specified length */
+	do {
+		/* Wait for Receive Complete flag */
+		while(!sercom->USART.INTFLAG.bit.RXC);
+		/* Check for errors */
+		if (sercom->USART.STATUS.bit.PERR || sercom->USART.STATUS.bit.FERR || sercom->USART.STATUS.bit.BUFOVF)
+			/* Set the error flag */
+			uart_drv_error_flag = true;
+		/* Store the read data to the buffer */
+		*ptr++ = (uint8_t)sercom->USART.DATA.reg;
+	} while (length--);
+}
diff --git a/bootloaders/metroM4/board_driver_serial.h b/bootloaders/metroM4/board_driver_serial.h
new file mode 100644
index 000000000..809f7ec01
--- /dev/null
+++ b/bootloaders/metroM4/board_driver_serial.h
@@ -0,0 +1,89 @@
+/*
+  Copyright (c) 2015 Arduino LLC.  All right reserved.
+  Copyright (c) 2015 Atmel Corporation/Thibaut VIARD.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef UART_DRIVER_H
+#define UART_DRIVER_H
+
+#include <stdio.h>
+#include <stdbool.h>
+#include <sam.h>
+
+#define PINMUX_UNUSED          0xFFFFFFFF
+
+/* SERCOM UART available pad settings */
+enum uart_pad_settings {
+	UART_RX_PAD0_TX_PAD2 = SERCOM_USART_CTRLA_RXPO(0) | SERCOM_USART_CTRLA_TXPO(1),
+	UART_RX_PAD1_TX_PAD2 = SERCOM_USART_CTRLA_RXPO(1) | SERCOM_USART_CTRLA_TXPO(1),
+	UART_RX_PAD2_TX_PAD0 = SERCOM_USART_CTRLA_RXPO(2),
+	UART_RX_PAD3_TX_PAD0 = SERCOM_USART_CTRLA_RXPO(3),
+	UART_RX_PAD1_TX_PAD0 = SERCOM_USART_CTRLA_RXPO(1),
+	UART_RX_PAD3_TX_PAD2 = SERCOM_USART_CTRLA_RXPO(3) | SERCOM_USART_CTRLA_TXPO(1),
+};
+
+/**
+ * \brief Initializes the UART
+ *
+ * \param Pointer to SERCOM instance
+ * \param Baud value corresponding to the desired baudrate
+ * \param SERCOM pad settings
+ */
+void uart_basic_init(Sercom *sercom, uint16_t baud_val, enum uart_pad_settings pad_conf);
+
+/**
+ * \brief Disables UART interface
+ *
+ * \param Pointer to SERCOM instance
+ */
+void uart_disable(Sercom *sercom);
+
+/**
+ * \brief Sends a single byte through UART interface
+ *
+ * \param Pointer to SERCOM instance
+ * \param Data to send
+ */
+void uart_write_byte(Sercom *sercom, uint8_t data);
+
+/**
+ * \brief Reads a single character from UART interface
+ *
+ * \param Pointer to SERCOM instance
+ * \return Data byte read
+ */
+uint8_t uart_read_byte(Sercom *sercom);
+
+/**
+ * \brief Sends buffer on UART interface
+ *
+ * \param Pointer to SERCOM instance
+ * \param Pointer to data to send
+ * \param Number of bytes to send
+ */
+void uart_write_buffer_polled(Sercom *sercom, uint8_t *ptr, uint16_t length);
+
+/**
+ * \brief Reads data on UART interface
+ *
+ * \param Pointer to SERCOM instance
+ * \param Pointer to store read data
+ * \param Number of bytes to read
+ */
+void uart_read_buffer_polled(Sercom *sercom, uint8_t *ptr, uint16_t length);
+
+#endif
diff --git a/bootloaders/metroM4/board_driver_usb.c b/bootloaders/metroM4/board_driver_usb.c
new file mode 100644
index 000000000..2e45b9c2b
--- /dev/null
+++ b/bootloaders/metroM4/board_driver_usb.c
@@ -0,0 +1,359 @@
+/*
+  Copyright (c) 2015 Arduino LLC.  All right reserved.
+  Copyright (c) 2015 Atmel Corporation/Thibaut VIARD.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include <string.h>
+#include "board_driver_usb.h"
+#include "sam_ba_usb.h"
+#include "sam_ba_cdc.h"
+
+#define NVM_USB_PAD_TRANSN_POS 32
+#define NVM_USB_PAD_TRANSN_SIZE 5
+#define NVM_USB_PAD_TRANSP_POS 37
+#define NVM_USB_PAD_TRANSP_SIZE 5
+#define NVM_USB_PAD_TRIM_POS 42
+#define NVM_USB_PAD_TRIM_SIZE 3
+
+__attribute__((__aligned__(4))) UsbDeviceDescriptor usb_endpoint_table[MAX_EP]; // Initialized to zero in USB_Init
+__attribute__((__aligned__(4))) uint8_t udd_ep_out_cache_buffer[2][64]; //1 for CTRL, 1 for BULK
+__attribute__((__aligned__(4))) uint8_t udd_ep_in_cache_buffer[2][64]; //1 for CTRL, 1 for BULK
+
+static volatile bool read_job = false;
+
+/*----------------------------------------------------------------------------
+ * \brief
+ */
+P_USB_CDC USB_Open(P_USB_CDC pCdc, Usb *pUsb)
+{
+  pCdc->pUsb = pUsb;
+  pCdc->currentConfiguration = 0;
+  pCdc->currentConnection    = 0;
+  pCdc->IsConfigured = USB_IsConfigured;
+//  pCdc->Write        = USB_Write;
+//  pCdc->Read         = USB_Read;
+
+  pCdc->pUsb->HOST.CTRLA.bit.ENABLE = true;
+  
+  while( pCdc->pUsb->HOST.SYNCBUSY.reg & USB_SYNCBUSY_ENABLE ); //wait for sync
+
+  return pCdc;
+}
+
+
+/**
+ * \brief Load USB calibration value from NVM
+ */
+static void USB_load_calib(void)
+{
+	Usb *    hw = USB;
+	uint32_t pad_transn
+	    = (*((uint32_t *)(NVMCTRL_SW0) + (NVM_USB_PAD_TRANSN_POS / 32)) >> (NVM_USB_PAD_TRANSN_POS % 32))
+	      & ((1 << NVM_USB_PAD_TRANSN_SIZE) - 1);
+	uint32_t pad_transp
+	    = (*((uint32_t *)(NVMCTRL_SW0) + (NVM_USB_PAD_TRANSP_POS / 32)) >> (NVM_USB_PAD_TRANSP_POS % 32))
+	      & ((1 << NVM_USB_PAD_TRANSP_SIZE) - 1);
+	uint32_t pad_trim = (*((uint32_t *)(NVMCTRL_SW0) + (NVM_USB_PAD_TRIM_POS / 32)) >> (NVM_USB_PAD_TRIM_POS % 32))
+	                    & ((1 << NVM_USB_PAD_TRIM_SIZE) - 1);
+	if (pad_transn == 0 || pad_transn == 0x1F) {
+		pad_transn = 9;
+	}
+	if (pad_transp == 0 || pad_transp == 0x1F) {
+		pad_transp = 25;
+	}
+	if (pad_trim == 0 || pad_trim == 0x7) {
+		pad_trim = 6;
+	}
+
+	hw->DEVICE.PADCAL.reg = USB_PADCAL_TRANSN(pad_transn) | USB_PADCAL_TRANSP(pad_transp) | USB_PADCAL_TRIM(pad_trim);
+
+	hw->DEVICE.QOSCTRL.bit.CQOS = 3;
+	hw->DEVICE.QOSCTRL.bit.DQOS = 3;
+}
+
+/*----------------------------------------------------------------------------
+ * \brief Initializes USB
+ */
+void USB_Init(void)
+{
+  uint32_t pad_transn, pad_transp, pad_trim;
+
+  /* Enable USB clock */
+  MCLK->APBBMASK.bit.USB_ = 1;
+
+  /* Set up the USB DP/DN pins */
+  PORT->Group[0].PINCFG[PIN_PA24H_USB_DM].bit.PMUXEN = 1;
+  PORT->Group[0].PMUX[PIN_PA24H_USB_DM/2].reg &= ~(0xF << (4 * (PIN_PA24H_USB_DM & 0x01u)));
+  PORT->Group[0].PMUX[PIN_PA24H_USB_DM/2].reg |= MUX_PA24H_USB_DM << (4 * (PIN_PA24H_USB_DM & 0x01u));
+  PORT->Group[0].PINCFG[PIN_PA25H_USB_DP].bit.PMUXEN = 1;
+  PORT->Group[0].PMUX[PIN_PA25H_USB_DP/2].reg &= ~(0xF << (4 * (PIN_PA25H_USB_DP & 0x01u)));
+  PORT->Group[0].PMUX[PIN_PA25H_USB_DP/2].reg |= MUX_PA25H_USB_DP << (4 * (PIN_PA25H_USB_DP & 0x01u));
+
+  /* ----------------------------------------------------------------------------------------------
+   * Put Generic Clock Generator 0 as source for Generic Clock Multiplexer 6 (USB reference)
+   *
+	*/
+  GCLK->PCHCTRL[USB_GCLK_ID].reg = GCLK_PCHCTRL_GEN_GCLK0_Val | (1 << GCLK_PCHCTRL_CHEN_Pos);
+  MCLK->APBBMASK.reg |= MCLK_APBBMASK_USB;
+  while(GCLK->SYNCBUSY.bit.GENCTRL0)
+  {
+    /* Wait for synchronization */
+  }
+
+  /* Reset */
+  USB->DEVICE.CTRLA.bit.SWRST = 1;
+  while (USB->DEVICE.SYNCBUSY.bit.SWRST)
+  {
+    /* Sync wait */
+  }
+
+  USB_load_calib();
+
+  /* Set the configuration */
+  /* Set mode to Device mode */
+  USB->HOST.CTRLA.bit.MODE = 0;
+  /* Enable Run in Standby */
+  USB->HOST.CTRLA.bit.RUNSTDBY = true;
+  /* Set the descriptor address */
+  USB->HOST.DESCADD.reg = (uint32_t)(&usb_endpoint_table[0]);
+  /* Set speed configuration to Full speed */
+  USB->DEVICE.CTRLB.bit.SPDCONF = USB_DEVICE_CTRLB_SPDCONF_FS_Val;
+  /* Attach to the USB host */
+  USB->DEVICE.CTRLB.reg &= ~USB_DEVICE_CTRLB_DETACH;
+
+  /* Initialize endpoint table RAM location to a known value 0 */
+  memset((uint8_t *)(&usb_endpoint_table[0]), 0, sizeof(usb_endpoint_table));
+}
+
+uint32_t USB_Write(Usb *pUsb, const char *pData, uint32_t length, uint8_t ep_num)
+{
+  uint32_t data_address;
+  uint8_t buf_index;
+
+  /* Set buffer index */
+  buf_index = (ep_num == 0) ? 0 : 1;
+
+  /* Check for requirement for multi-packet or auto zlp */
+  if (length >= (1 << (usb_endpoint_table[ep_num].DeviceDescBank[1].PCKSIZE.bit.SIZE + 3)))
+  {
+    /* Update the EP data address */
+    data_address = (uint32_t) pData;
+    /* Enable auto zlp */
+    usb_endpoint_table[ep_num].DeviceDescBank[1].PCKSIZE.bit.AUTO_ZLP = true;
+  }
+  else
+  {
+    /* Copy to local buffer */
+    memcpy(udd_ep_in_cache_buffer[buf_index], pData, length);
+    /* Update the EP data address */
+    data_address = (uint32_t) &udd_ep_in_cache_buffer[buf_index];
+  }
+
+  /* Set the buffer address for ep data */
+  usb_endpoint_table[ep_num].DeviceDescBank[1].ADDR.reg = data_address;
+  /* Set the byte count as zero */
+  usb_endpoint_table[ep_num].DeviceDescBank[1].PCKSIZE.bit.BYTE_COUNT = length;
+  /* Set the multi packet size as zero for multi-packet transfers where length > ep size */
+  usb_endpoint_table[ep_num].DeviceDescBank[1].PCKSIZE.bit.MULTI_PACKET_SIZE = 0;
+  /* Clear the transfer complete flag  */
+  pUsb->DEVICE.DeviceEndpoint[ep_num].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_TRCPT1;
+  /* Set the bank as ready */
+  pUsb->DEVICE.DeviceEndpoint[ep_num].EPSTATUSSET.bit.BK1RDY = true;
+
+  /* Wait for transfer to complete */
+  while ( (pUsb->DEVICE.DeviceEndpoint[ep_num].EPINTFLAG.bit.TRCPT1) == 0 );
+
+  return length;
+}
+
+/*----------------------------------------------------------------------------
+ * \brief Read available data from Endpoint OUT
+ */
+uint32_t USB_Read(Usb *pUsb, char *pData, uint32_t length)
+{
+  uint32_t packetSize = 0;
+
+  if (!read_job)
+  {
+    /* Set the buffer address for ep data */
+    usb_endpoint_table[USB_EP_OUT].DeviceDescBank[0].ADDR.reg = (uint32_t)&udd_ep_out_cache_buffer[USB_EP_OUT-1];
+    /* Set the byte count as zero */
+    usb_endpoint_table[USB_EP_OUT].DeviceDescBank[0].PCKSIZE.bit.BYTE_COUNT = 0;
+    /* Set the byte count as zero */
+    usb_endpoint_table[USB_EP_OUT].DeviceDescBank[0].PCKSIZE.bit.MULTI_PACKET_SIZE = 0;
+    /* Start the reception by clearing the bank 0 ready bit */
+    pUsb->DEVICE.DeviceEndpoint[USB_EP_OUT].EPSTATUSCLR.bit.BK0RDY = true;
+    /* set the user flag */
+    read_job = true;
+  }
+
+  /* Check for Transfer Complete 0 flag */
+  if ( pUsb->DEVICE.DeviceEndpoint[USB_EP_OUT].EPINTFLAG.bit.TRCPT0 )
+  {
+    /* Set packet size */
+    packetSize = SAM_BA_MIN(usb_endpoint_table[USB_EP_OUT].DeviceDescBank[0].PCKSIZE.bit.BYTE_COUNT, length);
+    /* Copy read data to user buffer */
+    memcpy(pData, udd_ep_out_cache_buffer[USB_EP_OUT-1], packetSize);
+    /* Clear the Transfer Complete 0 flag */
+    pUsb->DEVICE.DeviceEndpoint[USB_EP_OUT].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_TRCPT0;
+    /* Clear the user flag */
+    read_job = false;
+  }
+
+  return packetSize;
+}
+
+uint32_t USB_Read_blocking(Usb *pUsb, char *pData, uint32_t length)
+{
+  if (read_job)
+  {
+    /* Stop the reception by setting the bank 0 ready bit */
+    pUsb->DEVICE.DeviceEndpoint[USB_EP_OUT].EPSTATUSSET.bit.BK0RDY = true;
+    /* Clear the user flag */
+    read_job = false;
+  }
+
+  /* Set the buffer address for ep data */
+  usb_endpoint_table[USB_EP_OUT].DeviceDescBank[0].ADDR.reg = ((uint32_t)pData);
+  /* Set the byte count as zero */
+  usb_endpoint_table[USB_EP_OUT].DeviceDescBank[0].PCKSIZE.bit.BYTE_COUNT = 0;
+  /* Set the multi packet size as zero for multi-packet transfers where length > ep size */
+  usb_endpoint_table[USB_EP_OUT].DeviceDescBank[0].PCKSIZE.bit.MULTI_PACKET_SIZE = length;
+  /* Clear the bank 0 ready flag */
+  pUsb->DEVICE.DeviceEndpoint[USB_EP_OUT].EPSTATUSCLR.bit.BK0RDY = true;
+  /* Wait for transfer to complete */
+  while (!( pUsb->DEVICE.DeviceEndpoint[USB_EP_OUT].EPINTFLAG.bit.TRCPT0 ));
+  /* Clear Transfer complete 0 flag */
+  pUsb->DEVICE.DeviceEndpoint[USB_EP_OUT].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_TRCPT0;
+
+  return length;
+}
+
+/*----------------------------------------------------------------------------
+ * \brief Test if the device is configured and handle enumeration
+ */
+uint8_t USB_IsConfigured(P_USB_CDC pCdc)
+{
+  Usb *pUsb = pCdc->pUsb;
+
+  /* Check for End of Reset flag */
+  if (pUsb->DEVICE.INTFLAG.reg & USB_DEVICE_INTFLAG_EORST)
+  {
+    /* Clear the flag */
+    pUsb->DEVICE.INTFLAG.reg = USB_DEVICE_INTFLAG_EORST;
+    /* Set Device address as 0 */
+    pUsb->DEVICE.DADD.reg = USB_DEVICE_DADD_ADDEN | 0;
+    /* Configure endpoint 0 */
+    /* Configure Endpoint 0 for Control IN and Control OUT */
+    pUsb->DEVICE.DeviceEndpoint[0].EPCFG.reg = USB_DEVICE_EPCFG_EPTYPE0(1) | USB_DEVICE_EPCFG_EPTYPE1(1);
+    pUsb->DEVICE.DeviceEndpoint[0].EPSTATUSSET.reg = USB_DEVICE_EPSTATUSSET_BK0RDY;
+    pUsb->DEVICE.DeviceEndpoint[0].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_BK1RDY;
+    /* Configure control OUT Packet size to 64 bytes */
+    usb_endpoint_table[0].DeviceDescBank[0].PCKSIZE.bit.SIZE = 3;
+    /* Configure control IN Packet size to 64 bytes */
+    usb_endpoint_table[0].DeviceDescBank[1].PCKSIZE.bit.SIZE = 3;
+    /* Configure the data buffer address for control OUT */
+    usb_endpoint_table[0].DeviceDescBank[0].ADDR.reg = (uint32_t)&udd_ep_out_cache_buffer[0];
+    /* Configure the data buffer address for control IN */
+    usb_endpoint_table[0].DeviceDescBank[1].ADDR.reg = (uint32_t)&udd_ep_in_cache_buffer[0];
+    /* Set Multipacket size to 8 for control OUT and byte count to 0*/
+    usb_endpoint_table[0].DeviceDescBank[0].PCKSIZE.bit.MULTI_PACKET_SIZE = 8;
+    usb_endpoint_table[0].DeviceDescBank[0].PCKSIZE.bit.BYTE_COUNT = 0;
+    pUsb->DEVICE.DeviceEndpoint[0].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_BK0RDY;
+
+    // Reset current configuration value to 0
+    pCdc->currentConfiguration = 0;
+  }
+  else
+  {
+    if (pUsb->DEVICE.DeviceEndpoint[0].EPINTFLAG.reg & USB_DEVICE_EPINTFLAG_RXSTP)
+    {
+      sam_ba_usb_CDC_Enumerate(pCdc);
+    }
+  }
+
+  return pCdc->currentConfiguration;
+}
+
+/*----------------------------------------------------------------------------
+ * \brief Stall the control endpoint
+ */
+void USB_SendStall(Usb *pUsb, bool direction_in)
+{
+  /* Check the direction */
+  if (direction_in)
+  {
+    /* Set STALL request on IN direction */
+    pUsb->DEVICE.DeviceEndpoint[0].EPSTATUSSET.bit.STALLRQ1 = 1;
+  }
+  else
+  {
+    /* Set STALL request on OUT direction */
+    pUsb->DEVICE.DeviceEndpoint[0].EPSTATUSSET.bit.STALLRQ0 = 1;
+  }
+}
+
+/*----------------------------------------------------------------------------
+ * \brief Send zero length packet through the control endpoint
+ */
+void USB_SendZlp(Usb *pUsb)
+{
+  /* Set the byte count as zero */
+  usb_endpoint_table[0].DeviceDescBank[1].PCKSIZE.bit.BYTE_COUNT = 0;
+  /* Clear the transfer complete flag  */
+  pUsb->DEVICE.DeviceEndpoint[0].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_TRCPT1;
+  /* Set the bank as ready */
+  pUsb->DEVICE.DeviceEndpoint[0].EPSTATUSSET.bit.BK1RDY = true;
+  /* Wait for transfer to complete */
+  while (!( pUsb->DEVICE.DeviceEndpoint[0].EPINTFLAG.bit.TRCPT1 ));
+}
+
+/*----------------------------------------------------------------------------
+ * \brief Set USB device address obtained from host
+ */
+void USB_SetAddress(Usb *pUsb, uint16_t wValue)
+{
+  pUsb->DEVICE.DADD.reg = USB_DEVICE_DADD_ADDEN | wValue;
+}
+
+/*----------------------------------------------------------------------------
+ * \brief Configure USB device
+ */
+void USB_Configure(Usb *pUsb)
+{
+  /* Configure BULK OUT endpoint for CDC Data interface*/
+  pUsb->DEVICE.DeviceEndpoint[USB_EP_OUT].EPCFG.reg = USB_DEVICE_EPCFG_EPTYPE0(3);
+  /* Set maximum packet size as 64 bytes */
+  usb_endpoint_table[USB_EP_OUT].DeviceDescBank[0].PCKSIZE.bit.SIZE = 3;
+  pUsb->DEVICE.DeviceEndpoint[USB_EP_OUT].EPSTATUSSET.reg = USB_DEVICE_EPSTATUSSET_BK0RDY;
+  /* Configure the data buffer */
+  usb_endpoint_table[USB_EP_OUT].DeviceDescBank[0].ADDR.reg = (uint32_t)&udd_ep_out_cache_buffer[1];
+
+  /* Configure BULK IN endpoint for CDC Data interface */
+  pUsb->DEVICE.DeviceEndpoint[USB_EP_IN].EPCFG.reg = USB_DEVICE_EPCFG_EPTYPE1(3);
+  /* Set maximum packet size as 64 bytes */
+  usb_endpoint_table[USB_EP_IN].DeviceDescBank[1].PCKSIZE.bit.SIZE = 3;
+  pUsb->DEVICE.DeviceEndpoint[USB_EP_IN].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_BK1RDY;
+  /* Configure the data buffer */
+  usb_endpoint_table[USB_EP_IN].DeviceDescBank[1].ADDR.reg = (uint32_t)&udd_ep_in_cache_buffer[1];
+
+  /* Configure INTERRUPT IN endpoint for CDC COMM interface*/
+  pUsb->DEVICE.DeviceEndpoint[USB_EP_COMM].EPCFG.reg = USB_DEVICE_EPCFG_EPTYPE1(4);
+  /* Set maximum packet size as 64 bytes */
+  usb_endpoint_table[USB_EP_COMM].DeviceDescBank[1].PCKSIZE.bit.SIZE = 0;
+  pUsb->DEVICE.DeviceEndpoint[USB_EP_COMM].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_BK1RDY;
+}
diff --git a/bootloaders/metroM4/board_driver_usb.h b/bootloaders/metroM4/board_driver_usb.h
new file mode 100644
index 000000000..4e71b8c1a
--- /dev/null
+++ b/bootloaders/metroM4/board_driver_usb.h
@@ -0,0 +1,45 @@
+/*
+  Copyright (c) 2015 Arduino LLC.  All right reserved.
+  Copyright (c) 2015 Atmel Corporation/Thibaut VIARD.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _BOARD_DRIVER_USB_H_
+#define _BOARD_DRIVER_USB_H_
+
+#include "sam_ba_cdc.h"
+
+extern UsbDeviceDescriptor usb_endpoint_table[MAX_EP];
+extern uint8_t udd_ep_out_cache_buffer[2][64]; //1 for CTRL, 1 for BULK
+extern uint8_t udd_ep_in_cache_buffer[2][64]; //1 for CTRL, 1 for BULK
+
+P_USB_CDC USB_Open(P_USB_CDC pCdc, Usb *pUsb);
+
+void USB_Init(void);
+
+uint32_t USB_Write(Usb *pUsb, const char *pData, uint32_t length, uint8_t ep_num);
+uint32_t USB_Read(Usb *pUsb, char *pData, uint32_t length);
+uint32_t USB_Read_blocking(Usb *pUsb, char *pData, uint32_t length);
+
+uint8_t USB_IsConfigured(P_USB_CDC pCdc);
+
+void USB_SendStall(Usb *pUsb, bool direction_in);
+void USB_SendZlp(Usb *pUsb);
+
+void USB_SetAddress(Usb *pUsb, uint16_t wValue);
+void USB_Configure(Usb *pUsb);
+
+#endif // _BOARD_DRIVER_USB_H_
diff --git a/bootloaders/metroM4/board_init.c b/bootloaders/metroM4/board_init.c
new file mode 100644
index 000000000..acdb36a23
--- /dev/null
+++ b/bootloaders/metroM4/board_init.c
@@ -0,0 +1,145 @@
+/*
+  Copyright (c) 2015 Arduino LLC.  All right reserved.
+  Copyright (c) 2015 Atmel Corporation/Thibaut VIARD.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include <sam.h>
+#include "board_definitions.h"
+
+/**
+ * \brief system_init() configures the needed clocks and according Flash Read Wait States.
+ * We need to:
+ * 1) Enable XOSC32K clock (External on-board 32.768Hz oscillator), will be used as DFLL48M reference.
+ * 2) Put XOSC32K as source of Generic Clock Generator 3
+ * 3) Put Generic Clock Generator 3 as source for Generic Clock Multiplexer 0 (DFLL48M reference)
+ * 4) Enable DFLL48M clock
+ * 5) Switch Generic Clock Generator 0 to DFLL48M. CPU will run at 48MHz.
+ */
+// Constants for Clock generators
+#define GENERIC_CLOCK_GENERATOR_MAIN      (0u)
+#define GENERIC_CLOCK_GENERATOR_XOSC32K   (3u)
+#define GENERIC_CLOCK_GENERATOR_OSCULP32K (2u) /* Initialized at reset for WDT */
+//#define GENERIC_CLOCK_GENERATOR_OSC8M     (3u)
+// Constants for Clock multiplexers
+#define GENERIC_CLOCK_MULTIPLEXER_DFLL48M (0u)
+
+void board_init(void)
+{
+	
+  /* Set 1 Flash Wait State for 48MHz */
+  NVMCTRL->CTRLA.reg |= NVMCTRL_CTRLA_RWS(0);
+
+  /* ----------------------------------------------------------------------------------------------
+   * 1) Enable XOSC32K clock (External on-board 32.768Hz oscillator)
+   */
+	OSC32KCTRL->XOSC32K.reg = OSC32KCTRL_XOSC32K_ENABLE | OSC32KCTRL_XOSC32K_EN32K | OSC32KCTRL_XOSC32K_EN32K | OSC32KCTRL_XOSC32K_CGM_XT | OSC32KCTRL_XOSC32K_XTALEN;
+	
+	while( (OSC32KCTRL->STATUS.reg & OSC32KCTRL_STATUS_XOSC32KRDY) == 0 ){
+		/* Wait for oscillator to be ready */
+	}
+	
+	OSC32KCTRL->RTCCTRL.bit.RTCSEL = OSC32KCTRL_RTCCTRL_RTCSEL_ULP1K;
+
+
+  /* Software reset the module to ensure it is re-initialized correctly */
+  /* Note: Due to synchronization, there is a delay from writing CTRL.SWRST until the reset is complete.
+   * CTRL.SWRST and STATUS.SYNCBUSY will both be cleared when the reset is complete
+   */
+  GCLK->CTRLA.bit.SWRST = 1;
+  while ( GCLK->SYNCBUSY.reg & GCLK_SYNCBUSY_SWRST ){
+	  /* wait for reset to complete */
+  }
+  
+	/* ----------------------------------------------------------------------------------------------
+	* 2) Put XOSC32K as source of Generic Clock Generator 3
+	*/
+	GCLK->GENCTRL[GENERIC_CLOCK_GENERATOR_XOSC32K].reg = GCLK_GENCTRL_SRC(GCLK_GENCTRL_SRC_XOSC32K) | //generic clock gen 3
+									GCLK_GENCTRL_GENEN;
+
+	while ( GCLK->SYNCBUSY.reg & GCLK_SYNCBUSY_GENCTRL3 ){
+		/* Wait for synchronization */
+	}
+  
+	/* ----------------------------------------------------------------------------------------------
+	* 3) Put Generic Clock Generator 3 as source for Generic Clock Gen 0 (DFLL48M reference)
+	*/
+	GCLK->GENCTRL[0].reg = GCLK_GENCTRL_SRC(GCLK_GENCTRL_SRC_OSCULP32K) | GCLK_GENCTRL_GENEN;
+	
+	/* ----------------------------------------------------------------------------------------------
+	* 4) Enable DFLL48M clock
+	*/
+
+	/* DFLL Configuration in Open Loop mode */
+
+	OSCCTRL->DFLLCTRLA.reg = 0;
+	//GCLK->PCHCTRL[OSCCTRL_GCLK_ID_DFLL48].reg = (1 << GCLK_PCHCTRL_CHEN_Pos) | GCLK_PCHCTRL_GEN(GCLK_PCHCTRL_GEN_GCLK3_Val);
+
+	OSCCTRL->DFLLMUL.reg = OSCCTRL_DFLLMUL_CSTEP( 0x1 ) |
+						OSCCTRL_DFLLMUL_FSTEP( 0x1 ) |
+						OSCCTRL_DFLLMUL_MUL( 0 );
+
+	while ( OSCCTRL->DFLLSYNC.reg & OSCCTRL_DFLLSYNC_DFLLMUL )
+	{
+	/* Wait for synchronization */
+	}
+  
+	OSCCTRL->DFLLCTRLB.reg = 0;
+	while ( OSCCTRL->DFLLSYNC.reg & OSCCTRL_DFLLSYNC_DFLLCTRLB )
+	{
+		/* Wait for synchronization */
+	}
+  
+	OSCCTRL->DFLLCTRLA.reg |= OSCCTRL_DFLLCTRLA_ENABLE;
+	while ( OSCCTRL->DFLLSYNC.reg & OSCCTRL_DFLLSYNC_ENABLE )
+	{
+		/* Wait for synchronization */
+	}
+	
+	OSCCTRL->DFLLVAL.reg = OSCCTRL->DFLLVAL.reg;
+	while( OSCCTRL->DFLLSYNC.bit.DFLLVAL );
+  
+  OSCCTRL->DFLLCTRLB.reg = OSCCTRL_DFLLCTRLB_WAITLOCK |
+  OSCCTRL_DFLLCTRLB_CCDIS | OSCCTRL_DFLLCTRLB_USBCRM ;
+  
+	while ( !OSCCTRL->STATUS.bit.DFLLRDY )
+	{
+		/* Wait for synchronization */
+	}
+
+  /* ----------------------------------------------------------------------------------------------
+   * 5) Switch Generic Clock Generator 0 to DFLL48M. CPU will run at 48MHz.
+   */
+	GCLK->GENCTRL[GENERIC_CLOCK_GENERATOR_MAIN].reg = GCLK_GENCTRL_SRC(GCLK_GENCTRL_SRC_DFLL) |
+					GCLK_GENCTRL_IDC |
+					GCLK_GENCTRL_OE |
+					GCLK_GENCTRL_GENEN;
+
+  while ( GCLK->SYNCBUSY.reg & GCLK_SYNCBUSY_GENCTRL0 )
+  {
+    /* Wait for synchronization */
+  }
+  
+  
+  /* Turn on the digital interface clock */
+  //MCLK->APBAMASK.reg |= MCLK_APBAMASK_GCLK;
+
+  /*
+   * Now that all system clocks are configured, we can set CLKDIV .
+   * These values are normally the ones present after Reset.
+   */
+	MCLK->CPUDIV.reg = MCLK_CPUDIV_DIV_DIV1;
+}
diff --git a/bootloaders/metroM4/board_startup.c b/bootloaders/metroM4/board_startup.c
new file mode 100644
index 000000000..317873fcd
--- /dev/null
+++ b/bootloaders/metroM4/board_startup.c
@@ -0,0 +1,160 @@
+/*
+  Copyright (c) 2015 Arduino LLC.  All right reserved.
+  Copyright (c) 2015 Atmel Corporation/Thibaut VIARD.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include <sam.h>
+
+struct ConstVectors
+{
+  /* Stack pointer */
+  void* pvStack;
+
+  /* Cortex-M handlers */
+  void* pfnReset_Handler;
+  void* pfnNMI_Handler;
+  void* pfnHardFault_Handler;
+  void* pfnMemManage_Handler;
+  void* pfnBusFault_Handler;
+  void* pfnUsageFault_Handler;
+  void* pvReservedM9;
+  void* pvReservedM8;
+  void* pvReservedM7;
+  void* pvReservedM6;
+  void* pfnSVC_Handler;
+  void* pfnDebugMon_Handler;
+  void* pvReservedM3;
+  void* pfnPendSV_Handler;
+  void* pfnSysTick_Handler;
+};
+
+/* Symbols exported from linker script */
+extern uint32_t __etext ;
+extern uint32_t __data_start__ ;
+extern uint32_t __data_end__ ;
+extern uint32_t __bss_start__ ;
+extern uint32_t __bss_end__ ;
+extern uint32_t __StackTop;
+
+extern int main(void);
+extern void __libc_init_array(void);
+
+/* Exception Table */
+__attribute__ ((section(".isr_vector")))
+const struct ConstVectors exception_table =
+{
+  /* Configure Initial Stack Pointer, using linker-generated symbols */
+  .pvStack = (void*) (&__StackTop),
+
+  .pfnReset_Handler      = (void*) Reset_Handler,
+  .pfnNMI_Handler        = (void*) NMI_Handler,
+  .pfnHardFault_Handler  = (void*) HardFault_Handler,
+  .pfnMemManage_Handler        = (void*) MemManage_Handler,
+  .pfnBusFault_Handler        = (void*) BusFault_Handler,
+  .pfnUsageFault_Handler        = (void*) UsageFault_Handler,
+  .pvReservedM9         = (void*) (0UL), /* Reserved */
+  .pvReservedM8         = (void*) (0UL), /* Reserved */
+  .pvReservedM7         = (void*) (0UL), /* Reserved */
+  .pvReservedM6         = (void*) (0UL), /* Reserved */
+  .pfnSVC_Handler        = (void*) SVC_Handler,
+  .pfnDebugMon_Handler         = (void*) (0UL),
+  .pvReservedM3         = (void*) (0UL), /* Reserved */
+  .pfnPendSV_Handler     = (void*) PendSV_Handler,
+  .pfnSysTick_Handler    = (void*) SysTick_Handler,
+  
+};
+
+/**
+ * \brief This is the code that gets called on processor reset.
+ * Initializes the device and call the main() routine.
+ */
+void Reset_Handler( void )
+{
+  uint32_t *pSrc, *pDest;
+
+  /* Initialize the initialized data section */
+  pSrc = &__etext;
+  pDest = &__data_start__;
+
+  if ( (&__data_start__ != &__data_end__) && (pSrc != pDest) )
+  {
+    for (; pDest < &__data_end__ ; pDest++, pSrc++ )
+    {
+      *pDest = *pSrc ;
+    }
+  }
+
+  /* Clear the zero section */
+  if ( &__bss_start__ != &__bss_end__ )
+  {
+    for ( pDest = &__bss_start__ ; pDest < &__bss_end__ ; pDest++ )
+    {
+      *pDest = 0ul ;
+    }
+  }
+
+//  board_init(); // will be done in main() after app check
+
+  /* Initialize the C library */
+//  __libc_init_array();
+
+  main();
+
+  while (1);
+}
+
+void NMI_Handler(void)
+{
+  __BKPT(14);
+  while (1);
+}
+
+void HardFault_Handler(void)
+{
+  __BKPT(13);
+  while (1);
+}
+
+void MemManage_Handler(void)
+{
+  __BKPT(13);
+  while (1);
+}
+
+void BusFault_Handler(void)
+{
+  __BKPT(13);
+  while (1);
+}
+
+void UsageFault_Handler(void)
+{
+  __BKPT(13);
+  while (1);
+}
+
+void SVC_Handler(void)
+{
+  __BKPT(5);
+  while (1);
+}
+
+void PendSV_Handler(void)
+{
+  __BKPT(2);
+  while (1);
+}
diff --git a/bootloaders/metroM4/bootloader-metro_m4-v2.0.0-adafruit.5.bin b/bootloaders/metroM4/bootloader-metro_m4-v2.0.0-adafruit.5.bin
new file mode 100755
index 000000000..35aa5202d
Binary files /dev/null and b/bootloaders/metroM4/bootloader-metro_m4-v2.0.0-adafruit.5.bin differ
diff --git a/bootloaders/metroM4/bootloader-metro_m4-v2.0.0-adafruit.5.elf b/bootloaders/metroM4/bootloader-metro_m4-v2.0.0-adafruit.5.elf
new file mode 100755
index 000000000..553027c2b
Binary files /dev/null and b/bootloaders/metroM4/bootloader-metro_m4-v2.0.0-adafruit.5.elf differ
diff --git a/bootloaders/metroM4/bootloader_FEATHER_M4.ld b/bootloaders/metroM4/bootloader_FEATHER_M4.ld
new file mode 100644
index 000000000..a59547c07
--- /dev/null
+++ b/bootloaders/metroM4/bootloader_FEATHER_M4.ld
@@ -0,0 +1,222 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+  Copyright (c) 2015 Atmel Corporation/Thibaut VIARD.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* Linker script to configure memory regions.
+ * Need modifying for a specific board.
+ *   FLASH.ORIGIN: starting address of flash
+ *   FLASH.LENGTH: length of flash
+ *   RAM.ORIGIN: starting address of RAM bank 0
+ *   RAM.LENGTH: length of RAM bank 0
+ */
+
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x4000 /* First 16KB used by bootloader */
+  RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00030000-0x0004 /* 4 bytes used by bootloader to keep data between resets */
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ *   Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ *   __exidx_start
+ *   __exidx_end
+ *   __copy_table_start__
+ *   __copy_table_end__
+ *   __zero_table_start__
+ *   __zero_table_end__
+ *   __etext
+ *   __data_start__
+ *   __preinit_array_start
+ *   __preinit_array_end
+ *   __init_array_start
+ *   __init_array_end
+ *   __fini_array_start
+ *   __fini_array_end
+ *   __data_end__
+ *   __bss_start__
+ *   __bss_end__
+ *   __end__
+ *   end
+ *   __HeapLimit
+ *   __StackLimit
+ *   __StackTop
+ *   __stack
+ *   __sketch_vectors_ptr
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+  . = ORIGIN(FLASH);
+
+  .vectors :
+  {
+    KEEP(*(.isr_vector))
+  } > FLASH
+
+	.text :
+	{
+		*(.text*)
+
+		KEEP(*(.init))
+		KEEP(*(.fini))
+
+		/* .ctors */
+		*crtbegin.o(.ctors)
+		*crtbegin?.o(.ctors)
+		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+		*(SORT(.ctors.*))
+		*(.ctors)
+
+		/* .dtors */
+ 		*crtbegin.o(.dtors)
+ 		*crtbegin?.o(.dtors)
+ 		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ 		*(SORT(.dtors.*))
+ 		*(.dtors)
+
+		*(.rodata*)
+
+		KEEP(*(.eh_frame*))
+	} > FLASH
+
+	.ARM.extab :
+	{
+		*(.ARM.extab* .gnu.linkonce.armextab.*)
+	} > FLASH
+
+	__exidx_start = .;
+	.ARM.exidx :
+	{
+		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
+	} > FLASH
+	__exidx_end = .;
+
+	/* To copy multiple ROM to RAM sections,
+	 * uncomment .copy.table section and,
+	 * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.copy.table :
+	{
+		. = ALIGN(4);
+		__copy_table_start__ = .;
+		LONG (__etext)
+		LONG (__data_start__)
+		LONG (__data_end__ - __data_start__)
+		LONG (__etext2)
+		LONG (__data2_start__)
+		LONG (__data2_end__ - __data2_start__)
+		__copy_table_end__ = .;
+	} > FLASH
+	*/
+
+	/* To clear multiple BSS sections,
+	 * uncomment .zero.table section and,
+	 * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.zero.table :
+	{
+		. = ALIGN(4);
+		__zero_table_start__ = .;
+		LONG (__bss_start__)
+		LONG (__bss_end__ - __bss_start__)
+		LONG (__bss2_start__)
+		LONG (__bss2_end__ - __bss2_start__)
+		__zero_table_end__ = .;
+	} > FLASH
+	*/
+
+	__etext = .;
+  PROVIDE(__sketch_vectors_ptr = ORIGIN(FLASH) + LENGTH(FLASH));
+
+
+	.data : AT (__etext)
+	{
+		__data_start__ = .;
+		*(vtable)
+		*(.data*)
+
+		. = ALIGN(4);
+		/* preinit data */
+		PROVIDE_HIDDEN (__preinit_array_start = .);
+		KEEP(*(.preinit_array))
+		PROVIDE_HIDDEN (__preinit_array_end = .);
+
+		. = ALIGN(4);
+		/* init data */
+		PROVIDE_HIDDEN (__init_array_start = .);
+		KEEP(*(SORT(.init_array.*)))
+		KEEP(*(.init_array))
+		PROVIDE_HIDDEN (__init_array_end = .);
+
+
+		. = ALIGN(4);
+		/* finit data */
+		PROVIDE_HIDDEN (__fini_array_start = .);
+		KEEP(*(SORT(.fini_array.*)))
+		KEEP(*(.fini_array))
+		PROVIDE_HIDDEN (__fini_array_end = .);
+
+		KEEP(*(.jcr*))
+		. = ALIGN(4);
+		/* All data end */
+		__data_end__ = .;
+
+	} > RAM
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start__ = .;
+		*(.bss*)
+		*(COMMON)
+		. = ALIGN(4);
+		__bss_end__ = .;
+	} > RAM
+
+	.heap (COPY):
+	{
+		__end__ = .;
+		PROVIDE(end = .);
+		*(.heap*)
+		__HeapLimit = .;
+	} > RAM
+
+	/* .stack_dummy section doesn't contains any symbols. It is only
+	 * used for linker to calculate size of stack sections, and assign
+	 * values to stack symbols later */
+	.stack_dummy (COPY):
+	{
+		*(.stack*)
+	} > RAM
+
+	/* Set stack top to end of RAM, and stack limit move down by
+	 * size of stack_dummy section */
+	__StackTop = ORIGIN(RAM) + LENGTH(RAM);
+	__StackLimit = __StackTop - SIZEOF(.stack_dummy);
+	PROVIDE(__stack = __StackTop);
+
+	__ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ;
+
+	/* Check if data + heap + stack exceeds RAM limit */
+	ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
+}
diff --git a/bootloaders/metroM4/bootloader_METRO_M4.ld b/bootloaders/metroM4/bootloader_METRO_M4.ld
new file mode 100644
index 000000000..a59547c07
--- /dev/null
+++ b/bootloaders/metroM4/bootloader_METRO_M4.ld
@@ -0,0 +1,222 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+  Copyright (c) 2015 Atmel Corporation/Thibaut VIARD.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* Linker script to configure memory regions.
+ * Need modifying for a specific board.
+ *   FLASH.ORIGIN: starting address of flash
+ *   FLASH.LENGTH: length of flash
+ *   RAM.ORIGIN: starting address of RAM bank 0
+ *   RAM.LENGTH: length of RAM bank 0
+ */
+
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x4000 /* First 16KB used by bootloader */
+  RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00030000-0x0004 /* 4 bytes used by bootloader to keep data between resets */
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ *   Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ *   __exidx_start
+ *   __exidx_end
+ *   __copy_table_start__
+ *   __copy_table_end__
+ *   __zero_table_start__
+ *   __zero_table_end__
+ *   __etext
+ *   __data_start__
+ *   __preinit_array_start
+ *   __preinit_array_end
+ *   __init_array_start
+ *   __init_array_end
+ *   __fini_array_start
+ *   __fini_array_end
+ *   __data_end__
+ *   __bss_start__
+ *   __bss_end__
+ *   __end__
+ *   end
+ *   __HeapLimit
+ *   __StackLimit
+ *   __StackTop
+ *   __stack
+ *   __sketch_vectors_ptr
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+  . = ORIGIN(FLASH);
+
+  .vectors :
+  {
+    KEEP(*(.isr_vector))
+  } > FLASH
+
+	.text :
+	{
+		*(.text*)
+
+		KEEP(*(.init))
+		KEEP(*(.fini))
+
+		/* .ctors */
+		*crtbegin.o(.ctors)
+		*crtbegin?.o(.ctors)
+		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+		*(SORT(.ctors.*))
+		*(.ctors)
+
+		/* .dtors */
+ 		*crtbegin.o(.dtors)
+ 		*crtbegin?.o(.dtors)
+ 		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ 		*(SORT(.dtors.*))
+ 		*(.dtors)
+
+		*(.rodata*)
+
+		KEEP(*(.eh_frame*))
+	} > FLASH
+
+	.ARM.extab :
+	{
+		*(.ARM.extab* .gnu.linkonce.armextab.*)
+	} > FLASH
+
+	__exidx_start = .;
+	.ARM.exidx :
+	{
+		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
+	} > FLASH
+	__exidx_end = .;
+
+	/* To copy multiple ROM to RAM sections,
+	 * uncomment .copy.table section and,
+	 * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.copy.table :
+	{
+		. = ALIGN(4);
+		__copy_table_start__ = .;
+		LONG (__etext)
+		LONG (__data_start__)
+		LONG (__data_end__ - __data_start__)
+		LONG (__etext2)
+		LONG (__data2_start__)
+		LONG (__data2_end__ - __data2_start__)
+		__copy_table_end__ = .;
+	} > FLASH
+	*/
+
+	/* To clear multiple BSS sections,
+	 * uncomment .zero.table section and,
+	 * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.zero.table :
+	{
+		. = ALIGN(4);
+		__zero_table_start__ = .;
+		LONG (__bss_start__)
+		LONG (__bss_end__ - __bss_start__)
+		LONG (__bss2_start__)
+		LONG (__bss2_end__ - __bss2_start__)
+		__zero_table_end__ = .;
+	} > FLASH
+	*/
+
+	__etext = .;
+  PROVIDE(__sketch_vectors_ptr = ORIGIN(FLASH) + LENGTH(FLASH));
+
+
+	.data : AT (__etext)
+	{
+		__data_start__ = .;
+		*(vtable)
+		*(.data*)
+
+		. = ALIGN(4);
+		/* preinit data */
+		PROVIDE_HIDDEN (__preinit_array_start = .);
+		KEEP(*(.preinit_array))
+		PROVIDE_HIDDEN (__preinit_array_end = .);
+
+		. = ALIGN(4);
+		/* init data */
+		PROVIDE_HIDDEN (__init_array_start = .);
+		KEEP(*(SORT(.init_array.*)))
+		KEEP(*(.init_array))
+		PROVIDE_HIDDEN (__init_array_end = .);
+
+
+		. = ALIGN(4);
+		/* finit data */
+		PROVIDE_HIDDEN (__fini_array_start = .);
+		KEEP(*(SORT(.fini_array.*)))
+		KEEP(*(.fini_array))
+		PROVIDE_HIDDEN (__fini_array_end = .);
+
+		KEEP(*(.jcr*))
+		. = ALIGN(4);
+		/* All data end */
+		__data_end__ = .;
+
+	} > RAM
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start__ = .;
+		*(.bss*)
+		*(COMMON)
+		. = ALIGN(4);
+		__bss_end__ = .;
+	} > RAM
+
+	.heap (COPY):
+	{
+		__end__ = .;
+		PROVIDE(end = .);
+		*(.heap*)
+		__HeapLimit = .;
+	} > RAM
+
+	/* .stack_dummy section doesn't contains any symbols. It is only
+	 * used for linker to calculate size of stack sections, and assign
+	 * values to stack symbols later */
+	.stack_dummy (COPY):
+	{
+		*(.stack*)
+	} > RAM
+
+	/* Set stack top to end of RAM, and stack limit move down by
+	 * size of stack_dummy section */
+	__StackTop = ORIGIN(RAM) + LENGTH(RAM);
+	__StackLimit = __StackTop - SIZEOF(.stack_dummy);
+	PROVIDE(__stack = __StackTop);
+
+	__ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ;
+
+	/* Check if data + heap + stack exceeds RAM limit */
+	ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
+}
diff --git a/bootloaders/metroM4/build_all_bootloaders.sh b/bootloaders/metroM4/build_all_bootloaders.sh
new file mode 100644
index 000000000..62d289cac
--- /dev/null
+++ b/bootloaders/metroM4/build_all_bootloaders.sh
@@ -0,0 +1,20 @@
+#!/bin/bash -ex
+
+BOARD_ID=arduino_zero NAME=samd21_sam_ba make clean all
+
+BOARD_ID=genuino_zero NAME=samd21_sam_ba_genuino make clean all
+
+BOARD_ID=arduino_mkr1000 NAME=samd21_sam_ba_arduino_mkr1000 make clean all
+mv -v samd21_sam_ba_arduino_mkr1000.* ../mkr1000/
+
+BOARD_ID=genuino_mkr1000 NAME=samd21_sam_ba_genuino_mkr1000 make clean all
+mv -v samd21_sam_ba_genuino_mkr1000.* ../mkr1000/
+
+BOARD_ID=arduino_mkrzero NAME=samd21_sam_ba_arduino_mkrzero make clean all
+mv -v samd21_sam_ba_arduino_mkrzero.* ../mkrzero/
+
+BOARD_ID=arduino_mkrfox1200 NAME=samd21_sam_ba_arduino_mkrfox1200 make clean all
+mv -v samd21_sam_ba_arduino_mkrfox1200.* ../mkrfox1200/
+
+echo Done building bootloaders!
+
diff --git a/bootloaders/metroM4/main.c b/bootloaders/metroM4/main.c
new file mode 100644
index 000000000..726a67f19
--- /dev/null
+++ b/bootloaders/metroM4/main.c
@@ -0,0 +1,235 @@
+/*
+  Copyright (c) 2015 Arduino LLC.  All right reserved.
+  Copyright (c) 2015 Atmel Corporation/Thibaut VIARD.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include <stdio.h>
+#include <sam.h>
+#include "sam_ba_monitor.h"
+#include "sam_ba_serial.h"
+#include "board_definitions.h"
+#include "board_driver_led.h"
+#include "sam_ba_usb.h"
+#include "sam_ba_cdc.h"
+
+extern uint32_t __sketch_vectors_ptr; // Exported value from linker script
+extern void board_init(void);
+
+#if (defined DEBUG) && (DEBUG == 1)
+volatile uint32_t* pulSketch_Start_Address;
+#endif
+
+static volatile bool main_b_cdc_enable = false;
+
+/**
+ * \brief Check the application startup condition
+ *
+ */
+static void check_start_application(void)
+{
+//  LED_init();
+//  LED_off();
+
+#if (!defined DEBUG) || ((defined DEBUG) && (DEBUG == 0))
+uint32_t* pulSketch_Start_Address;
+#endif
+
+  /*
+   * Test sketch stack pointer @ &__sketch_vectors_ptr
+   * Stay in SAM-BA if value @ (&__sketch_vectors_ptr) == 0xFFFFFFFF (Erased flash cell value)
+   */
+  if (__sketch_vectors_ptr == 0xFFFFFFFF)
+  {
+    /* Stay in bootloader */
+    return;
+  }
+
+  /*
+   * Load the sketch Reset Handler address
+   * __sketch_vectors_ptr is exported from linker script and point on first 32b word of sketch vector table
+   * First 32b word is sketch stack
+   * Second 32b word is sketch entry point: Reset_Handler()
+   */
+  pulSketch_Start_Address = &__sketch_vectors_ptr ;
+  pulSketch_Start_Address++ ;
+
+  /*
+   * Test vector table address of sketch @ &__sketch_vectors_ptr
+   * Stay in SAM-BA if this function is not aligned enough, ie not valid
+   */
+  if ( ((uint32_t)(&__sketch_vectors_ptr) & ~SCB_VTOR_TBLOFF_Msk) != 0x00)
+  {
+    /* Stay in bootloader */
+    return;
+  }
+
+#if defined(BOOT_DOUBLE_TAP_ADDRESS)
+  #define DOUBLE_TAP_MAGIC 0xf01669efUL
+  //if (PM->RCAUSE.bit.POR)
+  if( RSTC->RCAUSE.bit.POR )
+  {
+    /* On power-on initialize double-tap */
+    BOOT_DOUBLE_TAP_DATA = 0;
+  }
+  else
+  {
+    if (BOOT_DOUBLE_TAP_DATA == DOUBLE_TAP_MAGIC)
+    {
+      /* Second tap, stay in bootloader */
+      BOOT_DOUBLE_TAP_DATA = 0;
+      return;
+    }
+
+    /* First tap */
+    BOOT_DOUBLE_TAP_DATA = DOUBLE_TAP_MAGIC;
+
+    /* Wait 0.5sec to see if the user tap reset again.
+     * The loop value is based on SAMD51 default 48Mhz clock @ reset.
+     */
+    for (uint32_t i=0; i<6000000; i++) /* 500ms */
+      /* force compiler to not optimize this... */
+      __asm__ __volatile__("");
+
+    /* Timeout happened, continue boot... */
+    BOOT_DOUBLE_TAP_DATA = 0;
+  }
+#endif
+
+/*
+#if defined(BOOT_LOAD_PIN)
+  volatile PortGroup *boot_port = (volatile PortGroup *)(&(PORT->Group[BOOT_LOAD_PIN / 32]));
+  volatile bool boot_en;
+
+  // Enable the input mode in Boot GPIO Pin
+  boot_port->DIRCLR.reg = BOOT_PIN_MASK;
+  boot_port->PINCFG[BOOT_LOAD_PIN & 0x1F].reg = PORT_PINCFG_INEN | PORT_PINCFG_PULLEN;
+  boot_port->OUTSET.reg = BOOT_PIN_MASK;
+  // Read the BOOT_LOAD_PIN status
+  boot_en = (boot_port->IN.reg) & BOOT_PIN_MASK;
+
+  // Check the bootloader enable condition
+  if (!boot_en)
+  {
+    // Stay in bootloader
+    return;
+  }
+#endif
+*/
+
+//  LED_on();
+
+  /* Rebase the Stack Pointer */
+  __set_MSP( (uint32_t)(__sketch_vectors_ptr) );
+
+  /* Rebase the vector table base address */
+  SCB->VTOR = ((uint32_t)(&__sketch_vectors_ptr) & SCB_VTOR_TBLOFF_Msk);
+
+  /* Jump to application Reset Handler in the application */
+  asm("bx %0"::"r"(*pulSketch_Start_Address));
+}
+
+#if DEBUG_ENABLE
+#	define DEBUG_PIN_HIGH 	port_pin_set_output_level(BOOT_LED, 1)
+#	define DEBUG_PIN_LOW 	port_pin_set_output_level(BOOT_LED, 0)
+#else
+#	define DEBUG_PIN_HIGH 	do{}while(0)
+#	define DEBUG_PIN_LOW 	do{}while(0)
+#endif
+
+/**
+ *  \brief SAMDx1 SAM-BA Main loop.
+ *  \return Unused (ANSI-C compatibility).
+ */
+int main(void)
+{
+#if SAM_BA_INTERFACE == SAM_BA_USBCDC_ONLY  ||  SAM_BA_INTERFACE == SAM_BA_BOTH_INTERFACES
+  P_USB_CDC pCdc;
+#endif
+  DEBUG_PIN_HIGH;
+
+  /* Jump in application if condition is satisfied */
+  check_start_application();
+
+  /* We have determined we should stay in the monitor. */
+  /* System initialization */
+  board_init();
+  __enable_irq();
+
+#if SAM_BA_INTERFACE == SAM_BA_UART_ONLY  ||  SAM_BA_INTERFACE == SAM_BA_BOTH_INTERFACES
+  /* UART is enabled in all cases */
+  serial_open();
+#endif
+
+#if SAM_BA_INTERFACE == SAM_BA_USBCDC_ONLY  ||  SAM_BA_INTERFACE == SAM_BA_BOTH_INTERFACES
+  pCdc = usb_init();
+#endif
+
+  DEBUG_PIN_LOW;
+
+  /* Initialize LEDs */
+  LED_init();
+  LEDRX_init();
+  LEDRX_off();
+  LEDTX_init();
+  LEDTX_off();
+
+  /* Start the sys tick (1 ms) */
+  SysTick_Config(1000);
+  
+  /* Wait for a complete enum on usb or a '#' char on serial line */
+  while (1)
+  {
+	  
+	  #if SAM_BA_INTERFACE == SAM_BA_USBCDC_ONLY  ||  SAM_BA_INTERFACE == SAM_BA_BOTH_INTERFACES
+	  if (pCdc->IsConfigured(pCdc) != 0)
+	  {
+		  main_b_cdc_enable = true;
+	  }
+
+	  /* Check if a USB enumeration has succeeded and if comm port has been opened */
+	  if (main_b_cdc_enable)
+	  {
+		  sam_ba_monitor_init(SAM_BA_INTERFACE_USBCDC);
+		  /* SAM-BA on USB loop */
+		  while( 1 )
+		  {
+			  sam_ba_monitor_run();
+		  }
+	  }
+	  #endif
+
+	  #if SAM_BA_INTERFACE == SAM_BA_UART_ONLY  ||  SAM_BA_INTERFACE == SAM_BA_BOTH_INTERFACES
+	  /* Check if a '#' has been received */
+	  if (!main_b_cdc_enable && serial_sharp_received())
+	  {
+		  sam_ba_monitor_init(SAM_BA_INTERFACE_USART);
+		  /* SAM-BA on Serial loop */
+		  while(1)
+		  {
+			  sam_ba_monitor_run();
+		  }
+	  }
+	  #endif
+  } 
+}
+
+void SysTick_Handler(void)
+{
+  LED_pulse();
+
+  sam_ba_monitor_sys_tick();
+}
diff --git a/bootloaders/metroM4/sam_ba_cdc.c b/bootloaders/metroM4/sam_ba_cdc.c
new file mode 100644
index 000000000..377340921
--- /dev/null
+++ b/bootloaders/metroM4/sam_ba_cdc.c
@@ -0,0 +1,98 @@
+/*
+  Copyright (c) 2015 Arduino LLC.  All right reserved.
+  Copyright (c) 2015 Atmel Corporation/Thibaut VIARD.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "sam_ba_cdc.h"
+#include "board_driver_usb.h"
+
+usb_cdc_line_coding_t line_coding=
+{
+  115200, // baudrate
+  0,      // 1 Stop Bit
+  0,      // None Parity
+  8     // 8 Data bits
+};
+
+#define pCdc (&sam_ba_cdc)
+
+int cdc_putc(/*P_USB_CDC pCdc,*/ int value)
+{
+  /* Send single byte on USB CDC */
+  USB_Write(pCdc->pUsb, (const char *)&value, 1, USB_EP_IN);
+
+  return 1;
+}
+
+int cdc_getc(/*P_USB_CDC pCdc*/void)
+{
+  uint8_t rx_char;
+
+  /* Read singly byte on USB CDC */
+  USB_Read(pCdc->pUsb, (char *)&rx_char, 1);
+
+  return (int)rx_char;
+}
+
+bool cdc_is_rx_ready(/*P_USB_CDC pCdc*/void)
+{
+  /* Check whether the device is configured */
+  if ( !USB_IsConfigured(pCdc) )
+    return 0;
+
+  /* Return transfer complete 0 flag status */
+  return (pCdc->pUsb->DEVICE.DeviceEndpoint[USB_EP_OUT].EPINTFLAG.bit.TRCPT0);
+}
+
+uint32_t cdc_write_buf(/*P_USB_CDC pCdc,*/ void const* data, uint32_t length)
+{
+  /* Send the specified number of bytes on USB CDC */
+  USB_Write(pCdc->pUsb, (const char *)data, length, USB_EP_IN);
+  return length;
+}
+
+uint32_t cdc_read_buf(/*P_USB_CDC pCdc,*/ void* data, uint32_t length)
+{
+  /* Check whether the device is configured */
+  if ( !USB_IsConfigured(pCdc) )
+    return 0;
+
+  /* Read from USB CDC */
+  return USB_Read(pCdc->pUsb, (char *)data, length);
+}
+
+uint32_t cdc_read_buf_xmd(/*P_USB_CDC pCdc,*/ void* data, uint32_t length)
+{
+  /* Check whether the device is configured */
+  if ( !USB_IsConfigured(pCdc) )
+    return 0;
+
+  /* Blocking read till specified number of bytes is received */
+  // XXX: USB_Read_blocking is not reliable
+  // return USB_Read_blocking(pCdc, (char *)data, length);
+
+  char *dst = (char *)data;
+  uint32_t remaining = length;
+  while (remaining)
+  {
+    uint32_t readed = USB_Read(pCdc->pUsb, (char *)dst, remaining);
+    remaining -= readed;
+    dst += readed;
+  }
+
+  return length;
+}
diff --git a/bootloaders/metroM4/sam_ba_cdc.h b/bootloaders/metroM4/sam_ba_cdc.h
new file mode 100644
index 000000000..49b7643cf
--- /dev/null
+++ b/bootloaders/metroM4/sam_ba_cdc.h
@@ -0,0 +1,91 @@
+/*
+  Copyright (c) 2015 Arduino LLC.  All right reserved.
+  Copyright (c) 2015 Atmel Corporation/Thibaut VIARD.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _SAM_BA_USB_CDC_H_
+#define _SAM_BA_USB_CDC_H_
+
+#include <stdint.h>
+#include "sam_ba_usb.h"
+
+typedef struct
+{
+	uint32_t dwDTERate;
+	uint8_t bCharFormat;
+	uint8_t bParityType;
+	uint8_t bDataBits;
+} usb_cdc_line_coding_t;
+
+/* CDC Class Specific Request Code */
+#define GET_LINE_CODING               0x21A1
+#define SET_LINE_CODING               0x2021
+#define SET_CONTROL_LINE_STATE        0x2221
+
+extern usb_cdc_line_coding_t line_coding;
+
+
+/**
+ * \brief Sends a single byte through USB CDC
+ *
+ * \param Data to send
+ * \return number of data sent
+ */
+int cdc_putc(/*P_USB_CDC pCdc,*/ int value);
+
+/**
+ * \brief Reads a single byte through USB CDC
+ *
+ * \return Data read through USB
+ */
+int cdc_getc(/*P_USB_CDC pCdc*/);
+
+/**
+ * \brief Checks if a character has been received on USB CDC
+ *
+ * \return \c 1 if a byte is ready to be read.
+ */
+bool cdc_is_rx_ready(/*P_USB_CDC pCdc*/);
+
+/**
+ * \brief Sends buffer on USB CDC
+ *
+ * \param data pointer
+ * \param number of data to send
+ * \return number of data sent
+ */
+uint32_t cdc_write_buf(/*P_USB_CDC pCdc,*/ void const* data, uint32_t length);
+
+/**
+ * \brief Gets data on USB CDC
+ *
+ * \param data pointer
+ * \param number of data to read
+ * \return number of data read
+ */
+uint32_t cdc_read_buf(/*P_USB_CDC pCdc,*/ void* data, uint32_t length);
+
+/**
+ * \brief Gets specified number of bytes on USB CDC
+ *
+ * \param data pointer
+ * \param number of data to read
+ * \return number of data read
+ */
+uint32_t cdc_read_buf_xmd(/*P_USB_CDC pCdc,*/ void* data, uint32_t length);
+
+#endif // _SAM_BA_USB_CDC_H_
diff --git a/bootloaders/metroM4/sam_ba_monitor.c b/bootloaders/metroM4/sam_ba_monitor.c
new file mode 100644
index 000000000..5d4d2f5b2
--- /dev/null
+++ b/bootloaders/metroM4/sam_ba_monitor.c
@@ -0,0 +1,552 @@
+/*
+  Copyright (c) 2015 Arduino LLC.  All right reserved.
+  Copyright (c) 2015 Atmel Corporation/Thibaut VIARD.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "sam.h"
+#include <string.h>
+#include "sam_ba_monitor.h"
+#include "sam_ba_serial.h"
+#include "board_driver_serial.h"
+#include "board_driver_usb.h"
+#include "sam_ba_usb.h"
+#include "sam_ba_cdc.h"
+#include "board_driver_led.h"
+
+const char RomBOOT_Version[] = SAM_BA_VERSION;
+const char RomBOOT_ExtendedCapabilities[] = "[Arduino:XYZ]";
+
+/* Provides one common interface to handle both USART and USB-CDC */
+typedef struct
+{
+  /* send one byte of data */
+  int (*put_c)(int value);
+  /* Get one byte */
+  int (*get_c)(void);
+  /* Receive buffer not empty */
+  bool (*is_rx_ready)(void);
+  /* Send given data (polling) */
+  uint32_t (*putdata)(void const* data, uint32_t length);
+  /* Get data from comm. device */
+  uint32_t (*getdata)(void* data, uint32_t length);
+  /* Send given data (polling) using xmodem (if necessary) */
+  uint32_t (*putdata_xmd)(void const* data, uint32_t length);
+  /* Get data from comm. device using xmodem (if necessary) */
+  uint32_t (*getdata_xmd)(void* data, uint32_t length);
+} t_monitor_if;
+
+#if SAM_BA_INTERFACE == SAM_BA_UART_ONLY  ||  SAM_BA_INTERFACE == SAM_BA_BOTH_INTERFACES
+/* Initialize structures with function pointers from supported interfaces */
+const t_monitor_if uart_if =
+{
+  .put_c =       serial_putc,
+  .get_c =       serial_getc,
+  .is_rx_ready = serial_is_rx_ready,
+  .putdata =     serial_putdata,
+  .getdata =     serial_getdata,
+  .putdata_xmd = serial_putdata_xmd,
+  .getdata_xmd = serial_getdata_xmd
+};
+#endif
+
+#if SAM_BA_INTERFACE == SAM_BA_USBCDC_ONLY  ||  SAM_BA_INTERFACE == SAM_BA_BOTH_INTERFACES
+//Please note that USB doesn't use Xmodem protocol, since USB already includes flow control and data verification
+//Data are simply forwarded without further coding.
+const t_monitor_if usbcdc_if =
+{
+  .put_c =         cdc_putc,
+  .get_c =         cdc_getc,
+  .is_rx_ready =   cdc_is_rx_ready,
+  .putdata =       cdc_write_buf,
+  .getdata =       cdc_read_buf,
+  .putdata_xmd =   cdc_write_buf,
+  .getdata_xmd =   cdc_read_buf_xmd
+};
+#endif
+
+/* The pointer to the interface object use by the monitor */
+t_monitor_if * ptr_monitor_if;
+
+/* b_terminal_mode mode (ascii) or hex mode */
+volatile bool b_terminal_mode = false;
+volatile bool b_sam_ba_interface_usart = false;
+
+/* Pulse generation counters to keep track of the time remaining for each pulse type */
+#define TX_RX_LED_PULSE_PERIOD 100
+volatile uint16_t txLEDPulse = 0; // time remaining for Tx LED pulse
+volatile uint16_t rxLEDPulse = 0; // time remaining for Rx LED pulse
+
+void sam_ba_monitor_init(uint8_t com_interface)
+{
+#if SAM_BA_INTERFACE == SAM_BA_UART_ONLY  ||  SAM_BA_INTERFACE == SAM_BA_BOTH_INTERFACES
+  //Selects the requested interface for future actions
+  if (com_interface == SAM_BA_INTERFACE_USART)
+  {
+    ptr_monitor_if = (t_monitor_if*) &uart_if;
+    b_sam_ba_interface_usart = true;
+  }
+#endif
+#if SAM_BA_INTERFACE == SAM_BA_USBCDC_ONLY  ||  SAM_BA_INTERFACE == SAM_BA_BOTH_INTERFACES
+  if (com_interface == SAM_BA_INTERFACE_USBCDC)
+  {
+    ptr_monitor_if = (t_monitor_if*) &usbcdc_if;
+  }
+#endif
+}
+
+/*
+ * Central SAM-BA monitor putdata function using the board LEDs
+ */
+static uint32_t sam_ba_putdata(t_monitor_if* pInterface, void const* data, uint32_t length)
+{
+	uint32_t result ;
+
+	result=pInterface->putdata(data, length);
+
+	LEDTX_on();
+	txLEDPulse = TX_RX_LED_PULSE_PERIOD;
+
+	return result;
+}
+
+/*
+ * Central SAM-BA monitor getdata function using the board LEDs
+ */
+static uint32_t sam_ba_getdata(t_monitor_if* pInterface, void* data, uint32_t length)
+{
+	uint32_t result ;
+
+	result=pInterface->getdata(data, length);
+
+	if (result)
+	{
+		LEDRX_on();
+		rxLEDPulse = TX_RX_LED_PULSE_PERIOD;
+	}
+
+	return result;
+}
+
+/*
+ * Central SAM-BA monitor putdata function using the board LEDs
+ */
+static uint32_t sam_ba_putdata_xmd(t_monitor_if* pInterface, void const* data, uint32_t length)
+{
+	uint32_t result ;
+
+	result=pInterface->putdata_xmd(data, length);
+
+	LEDTX_on();
+	txLEDPulse = TX_RX_LED_PULSE_PERIOD;
+
+	return result;
+}
+
+/*
+ * Central SAM-BA monitor getdata function using the board LEDs
+ */
+static uint32_t sam_ba_getdata_xmd(t_monitor_if* pInterface, void* data, uint32_t length)
+{
+	uint32_t result ;
+
+	result=pInterface->getdata_xmd(data, length);
+
+	if (result)
+	{
+		LEDRX_on();
+		rxLEDPulse = TX_RX_LED_PULSE_PERIOD;
+	}
+
+	return result;
+}
+
+/**
+ * \brief This function allows data emission by USART
+ *
+ * \param *data  Data pointer
+ * \param length Length of the data
+ */
+void sam_ba_putdata_term(uint8_t* data, uint32_t length)
+{
+  uint8_t temp, buf[12], *data_ascii;
+  uint32_t i, int_value;
+
+  if (b_terminal_mode)
+  {
+    if (length == 4)
+      int_value = *(uint32_t *) data;
+    else if (length == 2)
+      int_value = *(uint16_t *) data;
+    else
+      int_value = *(uint8_t *) data;
+
+    data_ascii = buf + 2;
+    data_ascii += length * 2 - 1;
+
+    for (i = 0; i < length * 2; i++)
+    {
+      temp = (uint8_t) (int_value & 0xf);
+
+      if (temp <= 0x9)
+        *data_ascii = temp | 0x30;
+      else
+        *data_ascii = temp + 0x37;
+
+      int_value >>= 4;
+      data_ascii--;
+    }
+    buf[0] = '0';
+    buf[1] = 'x';
+    buf[length * 2 + 2] = '\n';
+    buf[length * 2 + 3] = '\r';
+    sam_ba_putdata(ptr_monitor_if, buf, length * 2 + 4);
+  }
+  else
+    sam_ba_putdata(ptr_monitor_if, data, length);
+  return;
+}
+
+volatile uint32_t sp;
+void call_applet(uint32_t address)
+{
+  uint32_t app_start_address;
+
+  __disable_irq();
+
+  sp = __get_MSP();
+
+  /* Rebase the Stack Pointer */
+  __set_MSP(*(uint32_t *) address);
+
+  /* Load the Reset Handler address of the application */
+  app_start_address = *(uint32_t *)(address + 4);
+
+  /* Jump to application Reset Handler in the application */
+  asm("bx %0"::"r"(app_start_address));
+}
+
+uint32_t current_number;
+uint32_t i, length;
+uint8_t command, *ptr_data, *ptr, data[SIZEBUFMAX];
+uint8_t j;
+uint32_t u32tmp;
+
+uint32_t PAGE_SIZE, PAGES, MAX_FLASH;
+
+// Prints a 32-bit integer in hex.
+static void put_uint32(uint32_t n)
+{
+  char buff[8];
+  int i;
+  for (i=0; i<8; i++)
+  {
+    int d = n & 0XF;
+    n = (n >> 4);
+
+    buff[7-i] = d > 9 ? 'A' + d - 10 : '0' + d;
+  }
+  sam_ba_putdata( ptr_monitor_if, buff, 8);
+}
+
+static void sam_ba_monitor_loop(void)
+{
+  length = sam_ba_getdata(ptr_monitor_if, data, SIZEBUFMAX);
+  ptr = data;
+
+  for (i = 0; i < length; i++, ptr++)
+  {
+    if (*ptr == 0xff) continue;
+
+    if (*ptr == '#')
+    {
+      if (b_terminal_mode)
+      {
+        sam_ba_putdata(ptr_monitor_if, "\n\r", 2);
+      }
+      if (command == 'S')
+      {
+        //Check if some data are remaining in the "data" buffer
+        if(length>i)
+        {
+          //Move current indexes to next avail data (currently ptr points to "#")
+          ptr++;
+          i++;
+
+          //We need to add first the remaining data of the current buffer already read from usb
+          //read a maximum of "current_number" bytes
+          if ((length-i) < current_number)
+          {
+            u32tmp=(length-i);
+          }
+          else
+          {
+            u32tmp=current_number;
+          }
+
+          memcpy(ptr_data, ptr, u32tmp);
+          i += u32tmp;
+          ptr += u32tmp;
+          j = u32tmp;
+        }
+        //update i with the data read from the buffer
+        i--;
+        ptr--;
+        //Do we expect more data ?
+        if(j<current_number)
+          sam_ba_getdata_xmd(ptr_monitor_if, ptr_data, current_number-j);
+
+        __asm("nop");
+      }
+      else if (command == 'R')
+      {
+        sam_ba_putdata_xmd(ptr_monitor_if, ptr_data, current_number);
+      }
+      else if (command == 'O')
+      {
+        *ptr_data = (char) current_number;
+      }
+      else if (command == 'H')
+      {
+        *((uint16_t *) ptr_data) = (uint16_t) current_number;
+      }
+      else if (command == 'W')
+      {
+        *((int *) ptr_data) = current_number;
+      }
+      else if (command == 'o')
+      {
+        sam_ba_putdata_term(ptr_data, 1);
+      }
+      else if (command == 'h')
+      {
+        current_number = *((uint16_t *) ptr_data);
+        sam_ba_putdata_term((uint8_t*) &current_number, 2);
+      }
+      else if (command == 'w')
+      {
+        current_number = *((uint32_t *) ptr_data);
+        sam_ba_putdata_term((uint8_t*) &current_number, 4);
+      }
+      else if (command == 'G')
+      {
+        call_applet(current_number);
+        /* Rebase the Stack Pointer */
+        __set_MSP(sp);
+        __enable_irq();
+        if (b_sam_ba_interface_usart) {
+          ptr_monitor_if->put_c(0x6);
+        }
+      }
+      else if (command == 'T')
+      {
+        b_terminal_mode = 1;
+        sam_ba_putdata(ptr_monitor_if, "\n\r", 2);
+      }
+      else if (command == 'N')
+      {
+        if (b_terminal_mode == 0)
+        {
+          sam_ba_putdata( ptr_monitor_if, "\n\r", 2);
+        }
+        b_terminal_mode = 0;
+      }
+      else if (command == 'V')
+      {
+        sam_ba_putdata( ptr_monitor_if, "v", 1);
+        sam_ba_putdata( ptr_monitor_if, (uint8_t *) RomBOOT_Version, strlen(RomBOOT_Version));
+        sam_ba_putdata( ptr_monitor_if, " ", 1);
+        sam_ba_putdata( ptr_monitor_if, (uint8_t *) RomBOOT_ExtendedCapabilities, strlen(RomBOOT_ExtendedCapabilities));
+        sam_ba_putdata( ptr_monitor_if, " ", 1);
+        ptr = (uint8_t*) &(__DATE__);
+        i = 0;
+        while (*ptr++ != '\0')
+          i++;
+        sam_ba_putdata( ptr_monitor_if, (uint8_t *) &(__DATE__), i);
+        sam_ba_putdata( ptr_monitor_if, " ", 1);
+        i = 0;
+        ptr = (uint8_t*) &(__TIME__);
+        while (*ptr++ != '\0')
+          i++;
+        sam_ba_putdata( ptr_monitor_if, (uint8_t *) &(__TIME__), i);
+        sam_ba_putdata( ptr_monitor_if, "\n\r", 2);
+      }
+      else if (command == 'X')
+      {
+        // Syntax: X[ADDR]#
+        // Erase the flash memory starting from ADDR to the end of flash.
+		
+		//block size 16 pages
+
+        uint32_t dst_addr = current_number; // starting address
+
+        while (dst_addr < MAX_FLASH)
+        {
+		  while (NVMCTRL->STATUS.bit.READY == 0);
+          // Execute "EB" Erase Block
+		  NVMCTRL->ADDR.reg = dst_addr;
+          NVMCTRL->CTRLB.reg = NVMCTRL_CTRLB_CMDEX_KEY | NVMCTRL_CTRLB_CMD_EB;
+		  while (NVMCTRL->STATUS.bit.READY == 0);
+		  
+          dst_addr += PAGE_SIZE * 16; // Skip a block
+        }
+
+        // Notify command completed
+        sam_ba_putdata( ptr_monitor_if, "X\n\r", 3);
+      }
+      else if (command == 'Y')
+      {
+        // This command writes the content of a buffer in SRAM into flash memory.
+
+        // Syntax: Y[ADDR],0#
+        // Set the starting address of the SRAM buffer.
+
+        // Syntax: Y[ROM_ADDR],[SIZE]#
+        // Write the first SIZE bytes from the SRAM buffer (previously set) into
+        // flash memory starting from address ROM_ADDR
+
+        static uint32_t *src_buff_addr = NULL;
+
+        if (current_number == 0)
+        {
+          // Set buffer address
+          src_buff_addr = (uint32_t*)ptr_data;
+        }
+        else
+        {
+          // Write to flash
+          uint32_t size = current_number/4;
+          uint32_t *src_addr = src_buff_addr;
+          uint32_t *dst_addr = (uint32_t*)ptr_data;
+
+          // Set automatic page write
+		  NVMCTRL->CTRLA.reg |= NVMCTRL_CTRLA_WMODE(NVMCTRL_CTRLA_WMODE_AP);
+
+          // Do writes in pages
+          while (size)
+          {
+            // Execute "PBC" Page Buffer Clear
+			NVMCTRL->CTRLB.reg = NVMCTRL_CTRLB_CMDEX_KEY | NVMCTRL_CTRLB_CMD_PBC;
+			while (NVMCTRL->STATUS.bit.READY == 0)
+              ;
+
+            // Fill page buffer
+            uint32_t i;
+            for (i=0; i<(PAGE_SIZE/4) && i<size; i++)
+            {
+              dst_addr[i] = src_addr[i];
+            }
+
+            // Execute "WP" Write Page
+			NVMCTRL->ADDR.reg = ((uint32_t)dst_addr);
+			NVMCTRL->CTRLB.reg = NVMCTRL_CTRLB_CMDEX_KEY | NVMCTRL_CTRLB_CMD_WP;
+			while (NVMCTRL->STATUS.bit.READY == 0)
+              ;
+
+            // Advance to next page
+            dst_addr += i;
+            src_addr += i;
+            size     -= i;
+          }
+        }
+
+        // Notify command completed
+        sam_ba_putdata( ptr_monitor_if, "Y\n\r", 3);
+      }
+      else if (command == 'Z')
+      {
+        // This command calculate CRC for a given area of memory.
+        // It's useful to quickly check if a transfer has been done
+        // successfully.
+
+        // Syntax: Z[START_ADDR],[SIZE]#
+        // Returns: Z[CRC]#
+
+        uint8_t *data = (uint8_t *)ptr_data;
+        uint32_t size = current_number;
+        uint16_t crc = 0;
+        uint32_t i = 0;
+        for (i=0; i<size; i++)
+          crc = serial_add_crc(*data++, crc);
+
+        // Send response
+        sam_ba_putdata( ptr_monitor_if, "Z", 1);
+        put_uint32(crc);
+        sam_ba_putdata( ptr_monitor_if, "#\n\r", 3);
+      }
+
+      command = 'z';
+      current_number = 0;
+
+      if (b_terminal_mode)
+      {
+        sam_ba_putdata( ptr_monitor_if, ">", 1);
+      }
+    }
+    else
+    {
+      if (('0' <= *ptr) && (*ptr <= '9'))
+      {
+        current_number = (current_number << 4) | (*ptr - '0');
+      }
+      else if (('A' <= *ptr) && (*ptr <= 'F'))
+      {
+        current_number = (current_number << 4) | (*ptr - 'A' + 0xa);
+      }
+      else if (('a' <= *ptr) && (*ptr <= 'f'))
+      {
+        current_number = (current_number << 4) | (*ptr - 'a' + 0xa);
+      }
+      else if (*ptr == ',')
+      {
+        ptr_data = (uint8_t *) current_number;
+        current_number = 0;
+      }
+      else
+      {
+        command = *ptr;
+        current_number = 0;
+      }
+    }
+  }
+}
+
+void sam_ba_monitor_sys_tick(void)
+{
+	/* Check whether the TX or RX LED one-shot period has elapsed.  if so, turn off the LED */
+	if (txLEDPulse && !(--txLEDPulse))
+		LEDTX_off();
+	if (rxLEDPulse && !(--rxLEDPulse))
+		LEDRX_off();
+}
+
+/**
+ * \brief This function starts the SAM-BA monitor.
+ */
+void sam_ba_monitor_run(void)
+{
+  uint32_t pageSizes[] = { 8, 16, 32, 64, 128, 256, 512, 1024 };
+  PAGE_SIZE = pageSizes[NVMCTRL->PARAM.bit.PSZ];
+  PAGES = NVMCTRL->PARAM.bit.NVMP;
+  MAX_FLASH = PAGE_SIZE * PAGES;
+
+  ptr_data = NULL;
+  command = 'z';
+  while (1)
+  {
+    sam_ba_monitor_loop();
+  }
+}
diff --git a/bootloaders/metroM4/sam_ba_monitor.h b/bootloaders/metroM4/sam_ba_monitor.h
new file mode 100644
index 000000000..6cfa4db03
--- /dev/null
+++ b/bootloaders/metroM4/sam_ba_monitor.h
@@ -0,0 +1,72 @@
+/*
+  Copyright (c) 2015 Arduino LLC.  All right reserved.
+  Copyright (c) 2015 Atmel Corporation/Thibaut VIARD.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _MONITOR_SAM_BA_H_
+#define _MONITOR_SAM_BA_H_
+
+#define SAM_BA_VERSION              "2.0"
+
+/* Enable the interfaces to save code size */
+#define SAM_BA_BOTH_INTERFACES      0
+#define SAM_BA_UART_ONLY            1
+#define SAM_BA_USBCDC_ONLY          2
+
+#ifndef SAM_BA_INTERFACE
+#define SAM_BA_INTERFACE    SAM_BA_BOTH_INTERFACES
+#endif
+
+/* Selects USB as the communication interface of the monitor */
+#define SAM_BA_INTERFACE_USBCDC     0
+/* Selects USART as the communication interface of the monitor */
+#define SAM_BA_INTERFACE_USART      1
+
+/* Selects USB as the communication interface of the monitor */
+#define SIZEBUFMAX                  64
+
+/**
+ * \brief Initialize the monitor
+ *
+ */
+void sam_ba_monitor_init(uint8_t com_interface);
+
+/**
+ * \brief System tick function of the SAM-BA Monitor
+ *
+ */
+void sam_ba_monitor_sys_tick(void);
+
+/**
+ * \brief Main function of the SAM-BA Monitor
+ *
+ */
+void sam_ba_monitor_run(void);
+
+/**
+ * \brief
+ *
+ */
+void sam_ba_putdata_term(uint8_t* data, uint32_t length);
+
+/**
+ * \brief
+ *
+ */
+void call_applet(uint32_t address);
+
+#endif // _MONITOR_SAM_BA_H_
diff --git a/bootloaders/metroM4/sam_ba_serial.c b/bootloaders/metroM4/sam_ba_serial.c
new file mode 100644
index 000000000..6b02b2850
--- /dev/null
+++ b/bootloaders/metroM4/sam_ba_serial.c
@@ -0,0 +1,529 @@
+/*
+  Copyright (c) 2015 Arduino LLC.  All right reserved.
+  Copyright (c) 2015 Atmel Corporation/Thibaut VIARD.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include <sam.h>
+#include "board_definitions.h"
+#include "sam_ba_serial.h"
+#include "board_driver_serial.h"
+
+/* Local reference to current Usart instance in use with this driver */
+//struct usart_module usart_sam_ba;
+
+/* Variable to let the main task select the appropriate communication interface */
+volatile uint8_t b_sharp_received;
+
+/* RX and TX Buffers + rw pointers for each buffer */
+volatile uint8_t buffer_rx_usart[USART_BUFFER_SIZE];
+
+volatile uint8_t idx_rx_read;
+volatile uint8_t idx_rx_write;
+
+volatile uint8_t buffer_tx_usart[USART_BUFFER_SIZE];
+
+volatile uint8_t idx_tx_read;
+volatile uint8_t idx_tx_write;
+
+/* Test for timeout in AT91F_GetChar */
+uint8_t error_timeout;
+uint16_t size_of_data;
+uint8_t mode_of_transfer;
+
+#define BOOT_USART_PAD(n) BOOT_USART_PAD##n
+
+#define GPIO_PIN(n) (((n)&0x1Fu) << 0)
+#define GPIO_PORT(n) ((n) >> 5)
+
+/**
+ * \brief Open the given USART
+ */
+void serial_open(void)
+{
+	uint32_t port;
+	uint32_t pin;
+	  
+	GCLK->PCHCTRL[BOOT_GCLK_ID_CORE].reg = GCLK_PCHCTRL_GEN_GCLK0_Val | (1 << GCLK_PCHCTRL_CHEN_Pos);
+	GCLK->PCHCTRL[BOOT_GCLK_ID_SLOW].reg = GCLK_PCHCTRL_GEN_GCLK3_Val | (1 << GCLK_PCHCTRL_CHEN_Pos);
+	
+	MCLK->BOOK_USART_MASK.reg |= BOOT_USART_BUS_CLOCK_INDEX ;
+	
+	/* Configure the port pins for SERCOM_USART */
+	if (BOOT_USART_PAD0 != PINMUX_UNUSED)
+  {
+		/* Mask 6th bit in pin number to check whether it is greater than 32 i.e., PORTB pin */
+		port = (BOOT_USART_PAD0 & 0x200000) >> 21;
+		pin = (BOOT_USART_PAD0 >> 16);
+		PORT->Group[port].PINCFG[(pin - (port*32))].bit.PMUXEN = 1;
+		PORT->Group[port].PMUX[(pin - (port*32))/2].reg &= ~(0xF << (4 * (pin & 0x01u)));
+		PORT->Group[port].PMUX[(pin - (port*32))/2].reg |= (BOOT_USART_PAD0 & 0xFF) << (4 * (pin & 0x01u));
+	}
+
+	if (BOOT_USART_PAD1 != PINMUX_UNUSED)
+  {
+		/* Mask 6th bit in pin number to check whether it is greater than 32 i.e., PORTB pin */
+		port = (BOOT_USART_PAD1 & 0x200000) >> 21;
+		pin = BOOT_USART_PAD1 >> 16;
+		PORT->Group[port].PINCFG[(pin - (port*32))].bit.PMUXEN = 1;
+		PORT->Group[port].PMUX[(pin - (port*32))/2].reg &= ~(0xF << (4 * (pin & 0x01u)));
+		PORT->Group[port].PMUX[(pin - (port*32))/2].reg |= (BOOT_USART_PAD1 & 0xFF) << (4 * (pin & 0x01u));
+	}
+
+	if (BOOT_USART_PAD2 != PINMUX_UNUSED)
+  {
+		/* Mask 6th bit in pin number to check whether it is greater than 32 i.e., PORTB pin */
+		port = (BOOT_USART_PAD2 & 0x200000) >> 21;
+		pin = BOOT_USART_PAD2 >> 16;
+		PORT->Group[port].PINCFG[(pin - (port*32))].bit.PMUXEN = 1;
+		PORT->Group[port].PMUX[(pin - (port*32))/2].reg &= ~(0xF << (4 * (pin & 0x01u)));
+		PORT->Group[port].PMUX[(pin - (port*32))/2].reg |= (BOOT_USART_PAD2 & 0xFF) << (4 * (pin & 0x01u));
+	}
+
+	if (BOOT_USART_PAD3 != PINMUX_UNUSED)
+  {
+		/* Mask 6th bit in pin number to check whether it is greater than 32 i.e., PORTB pin */
+		port = (BOOT_USART_PAD3 & 0x200000) >> 21;
+		pin = BOOT_USART_PAD3 >> 16;
+		PORT->Group[port].PINCFG[(pin - (port*32))].bit.PMUXEN = 1;
+		PORT->Group[port].PMUX[(pin - (port*32))/2].reg &= ~(0xF << (4 * (pin & 0x01u)));
+		PORT->Group[port].PMUX[(pin - (port*32))/2].reg |= (BOOT_USART_PAD3 & 0xFF) << (4 * (pin & 0x01u));
+	}
+
+	/* Baud rate 115200 - clock 48MHz -> BAUD value-63018 */
+	uart_basic_init(BOOT_USART_MODULE, 63018, BOOT_USART_PAD_SETTINGS);
+
+	//Initialize flag
+	b_sharp_received = false;
+	idx_rx_read = 0;
+	idx_rx_write = 0;
+	idx_tx_read = 0;
+	idx_tx_write = 0;
+
+	error_timeout = 0;
+}
+
+/**
+ * \brief Close communication line
+ */
+void serial_close(void)
+{
+	uart_disable(BOOT_USART_MODULE);
+}
+
+/**
+ * \brief Puts a byte on usart line
+ * The type int is used to support printf redirection from compiler LIB.
+ *
+ * \param value      Value to put
+ *
+ * \return \c 1 if function was successfully done, otherwise \c 0.
+ */
+int serial_putc(int value)
+{	
+	uart_write_byte(BOOT_USART_MODULE, (uint8_t)value);
+	return 1;
+}
+
+int serial_getc(void)
+{
+	uint16_t retval;
+	//Wait until input buffer is filled
+	while(!(serial_is_rx_ready()));
+	retval = (uint16_t)uart_read_byte(BOOT_USART_MODULE);
+	//usart_read_wait(&usart_sam_ba, &retval);
+	return (int)retval;
+
+}
+
+int serial_sharp_received(void)
+{
+	if (serial_is_rx_ready())
+  {
+		if (serial_getc() == SHARP_CHARACTER)
+			return (true);
+	}
+	return (false);
+}
+
+bool serial_is_rx_ready(void)
+{
+	return (BOOT_USART_MODULE->USART.INTFLAG.reg & SERCOM_USART_INTFLAG_RXC);
+}
+
+int serial_readc(void)
+{
+	int retval;
+	retval = buffer_rx_usart[idx_rx_read];
+	idx_rx_read = (idx_rx_read + 1) & (USART_BUFFER_SIZE - 1);
+	return (retval);
+}
+
+//Send given data (polling)
+uint32_t serial_putdata(void const* data, uint32_t length)
+{
+	uint32_t i;
+	uint8_t* ptrdata;
+	ptrdata = (uint8_t*) data;
+	for (i = 0; i < length; i++)
+  {
+		serial_putc(*ptrdata);
+		ptrdata++;
+	}
+	return (i);
+}
+
+//Get data from comm. device
+uint32_t serial_getdata(void* data, uint32_t length)
+{
+	uint8_t* ptrdata;
+	ptrdata = (uint8_t*) data;
+	*ptrdata = serial_getc();
+	return (1);
+}
+
+static const uint16_t crc16Table[256]=
+{
+	0x0000,0x1021,0x2042,0x3063,0x4084,0x50a5,0x60c6,0x70e7,
+	0x8108,0x9129,0xa14a,0xb16b,0xc18c,0xd1ad,0xe1ce,0xf1ef,
+	0x1231,0x0210,0x3273,0x2252,0x52b5,0x4294,0x72f7,0x62d6,
+	0x9339,0x8318,0xb37b,0xa35a,0xd3bd,0xc39c,0xf3ff,0xe3de,
+	0x2462,0x3443,0x0420,0x1401,0x64e6,0x74c7,0x44a4,0x5485,
+	0xa56a,0xb54b,0x8528,0x9509,0xe5ee,0xf5cf,0xc5ac,0xd58d,
+	0x3653,0x2672,0x1611,0x0630,0x76d7,0x66f6,0x5695,0x46b4,
+	0xb75b,0xa77a,0x9719,0x8738,0xf7df,0xe7fe,0xd79d,0xc7bc,
+	0x48c4,0x58e5,0x6886,0x78a7,0x0840,0x1861,0x2802,0x3823,
+	0xc9cc,0xd9ed,0xe98e,0xf9af,0x8948,0x9969,0xa90a,0xb92b,
+	0x5af5,0x4ad4,0x7ab7,0x6a96,0x1a71,0x0a50,0x3a33,0x2a12,
+	0xdbfd,0xcbdc,0xfbbf,0xeb9e,0x9b79,0x8b58,0xbb3b,0xab1a,
+	0x6ca6,0x7c87,0x4ce4,0x5cc5,0x2c22,0x3c03,0x0c60,0x1c41,
+	0xedae,0xfd8f,0xcdec,0xddcd,0xad2a,0xbd0b,0x8d68,0x9d49,
+	0x7e97,0x6eb6,0x5ed5,0x4ef4,0x3e13,0x2e32,0x1e51,0x0e70,
+	0xff9f,0xefbe,0xdfdd,0xcffc,0xbf1b,0xaf3a,0x9f59,0x8f78,
+	0x9188,0x81a9,0xb1ca,0xa1eb,0xd10c,0xc12d,0xf14e,0xe16f,
+	0x1080,0x00a1,0x30c2,0x20e3,0x5004,0x4025,0x7046,0x6067,
+	0x83b9,0x9398,0xa3fb,0xb3da,0xc33d,0xd31c,0xe37f,0xf35e,
+	0x02b1,0x1290,0x22f3,0x32d2,0x4235,0x5214,0x6277,0x7256,
+	0xb5ea,0xa5cb,0x95a8,0x8589,0xf56e,0xe54f,0xd52c,0xc50d,
+	0x34e2,0x24c3,0x14a0,0x0481,0x7466,0x6447,0x5424,0x4405,
+	0xa7db,0xb7fa,0x8799,0x97b8,0xe75f,0xf77e,0xc71d,0xd73c,
+	0x26d3,0x36f2,0x0691,0x16b0,0x6657,0x7676,0x4615,0x5634,
+	0xd94c,0xc96d,0xf90e,0xe92f,0x99c8,0x89e9,0xb98a,0xa9ab,
+	0x5844,0x4865,0x7806,0x6827,0x18c0,0x08e1,0x3882,0x28a3,
+	0xcb7d,0xdb5c,0xeb3f,0xfb1e,0x8bf9,0x9bd8,0xabbb,0xbb9a,
+	0x4a75,0x5a54,0x6a37,0x7a16,0x0af1,0x1ad0,0x2ab3,0x3a92,
+	0xfd2e,0xed0f,0xdd6c,0xcd4d,0xbdaa,0xad8b,0x9de8,0x8dc9,
+	0x7c26,0x6c07,0x5c64,0x4c45,0x3ca2,0x2c83,0x1ce0,0x0cc1,
+	0xef1f,0xff3e,0xcf5d,0xdf7c,0xaf9b,0xbfba,0x8fd9,0x9ff8,
+	0x6e17,0x7e36,0x4e55,0x5e74,0x2e93,0x3eb2,0x0ed1,0x1ef0
+};
+
+//*----------------------------------------------------------------------------
+//* \brief Compute the CRC
+//*----------------------------------------------------------------------------
+unsigned short serial_add_crc(char ptr, unsigned short crc)
+{
+	return (crc << 8) ^ crc16Table[((crc >> 8) ^ ptr) & 0xff];
+}
+
+//*----------------------------------------------------------------------------
+//* \brief
+//*----------------------------------------------------------------------------
+static uint16_t getbytes(uint8_t *ptr_data, uint16_t length)
+{
+	uint16_t crc = 0;
+	uint16_t cpt;
+	uint8_t c;
+
+	for (cpt = 0; cpt < length; ++cpt)
+  {
+		c = serial_getc();
+		if (error_timeout)
+			return 1;
+		crc = serial_add_crc(c, crc);
+		//crc = (crc << 8) ^ xcrc16tab[(crc>>8) ^ c];
+		if (size_of_data || mode_of_transfer)
+    {
+			*ptr_data++ = c;
+			if (length == PKTLEN_128)
+				size_of_data--;
+		}
+	}
+
+	return crc;
+}
+
+//*----------------------------------------------------------------------------
+//* \brief Used by Xup to send packets.
+//*----------------------------------------------------------------------------
+static int putPacket(uint8_t *tmppkt, uint8_t sno)
+{
+	uint32_t i;
+	uint16_t chksm;
+	uint8_t data;
+
+	chksm = 0;
+
+	serial_putc(SOH);
+
+	serial_putc(sno);
+	serial_putc((uint8_t) ~(sno));
+
+	for (i = 0; i < PKTLEN_128; i++)
+  {
+		if (size_of_data || mode_of_transfer)
+    {
+			data = *tmppkt++;
+			size_of_data--;
+		}
+    else
+			data = 0x00;
+
+		serial_putc(data);
+
+		//chksm = (chksm<<8) ^ xcrc16tab[(chksm>>8)^data];
+		chksm = serial_add_crc(data, chksm);
+	}
+
+	/* An "endian independent way to extract the CRC bytes. */
+	serial_putc((uint8_t) (chksm >> 8));
+	serial_putc((uint8_t) chksm);
+
+	return (serial_getc()); /* Wait for ack */
+}
+
+//*----------------------------------------------------------------------------
+//* \brief Called when a transfer from target to host is being made (considered
+//*        an upload).
+//*----------------------------------------------------------------------------
+//Send given data (polling) using xmodem (if necessary)
+uint32_t serial_putdata_xmd(void const* data, uint32_t length)
+{
+	uint8_t c, sno = 1;
+	uint8_t done;
+	uint8_t * ptr_data = (uint8_t *) data;
+	error_timeout = 0;
+	if (!length)
+		mode_of_transfer = 1;
+	else
+  {
+		size_of_data = length;
+		mode_of_transfer = 0;
+	}
+
+	if (length & (PKTLEN_128 - 1))
+  {
+		length += PKTLEN_128;
+		length &= ~(PKTLEN_128 - 1);
+	}
+
+	/* Startup synchronization... */
+	/* Wait to receive a NAK or 'C' from receiver. */
+	done = 0;
+	while (!done) {
+		c = (uint8_t) serial_getc();
+		if (error_timeout)
+    { // Test for timeout in serial_getc
+			error_timeout = 0;
+			c = (uint8_t) serial_getc();
+			if (error_timeout)
+      {
+				error_timeout = 0;
+				return (0);
+			}
+		}
+		switch (c)
+    {
+      case NAK:
+        done = 1;
+        // ("CSM");
+			break;
+      case 'C':
+        done = 1;
+        // ("CRC");
+			break;
+      case 'q': /* ELS addition, not part of XMODEM spec. */
+        return (0);
+      default:
+			break;
+		}
+	}
+
+	done = 0;
+	sno = 1;
+	while (!done)
+  {
+		c = (uint8_t) putPacket((uint8_t *) ptr_data, sno);
+		if (error_timeout)
+    { // Test for timeout in serial_getc
+			error_timeout = 0;
+			return (0);
+		}
+		switch (c)
+    {
+      case ACK:
+        ++sno;
+        length -= PKTLEN_128;
+        ptr_data += PKTLEN_128;
+        // ("A");
+			break;
+
+      case NAK:
+        // ("N");
+			break;
+
+      case CAN:
+      case EOT:
+      default:
+        done = 0;
+			break;
+		}
+
+		if (!length)
+    {
+			serial_putc(EOT);
+			serial_getc(); /* Flush the ACK */
+			break;
+		}
+		// ("!");
+	}
+
+	mode_of_transfer = 0;
+	// ("Xup_done.");
+	return (1);
+	//    return(0);
+}
+
+/*----------------------------------------------------------------------------
+ * \brief Used by serial_getdata_xmd to retrieve packets.
+ */
+static uint8_t getPacket(uint8_t *ptr_data, uint8_t sno)
+{
+	uint8_t seq[2];
+	uint16_t crc, xcrc;
+
+	getbytes(seq, 2);
+	xcrc = getbytes(ptr_data, PKTLEN_128);
+	if (error_timeout)
+		return (false);
+
+	/* An "endian independent way to combine the CRC bytes. */
+	crc = (uint16_t) serial_getc() << 8;
+	crc += (uint16_t) serial_getc();
+
+	if (error_timeout == 1)
+		return (false);
+
+	if ((crc != xcrc) || (seq[0] != sno) || (seq[1] != (uint8_t) (~sno)))
+  {
+		serial_putc(CAN);
+		return (false);
+	}
+
+	serial_putc(ACK);
+	return (true);
+}
+
+//*----------------------------------------------------------------------------
+//* \brief Called when a transfer from host to target is being made (considered
+//*        an download).
+//*----------------------------------------------------------------------------
+//Get data from comm. device using xmodem (if necessary)
+uint32_t serial_getdata_xmd(void* data, uint32_t length)
+{
+	uint32_t timeout;
+	char c;
+	uint8_t * ptr_data = (uint8_t *) data;
+	uint32_t b_run, nbr_of_timeout = 100;
+	uint8_t sno = 0x01;
+	uint32_t data_transfered = 0;
+
+	//Copied from legacy source code ... might need some tweaking
+	uint32_t loops_per_second = CPU_FREQUENCY/60;
+
+	error_timeout = 0;
+
+	if (length == 0)
+		mode_of_transfer = 1;
+	else
+  {
+		size_of_data = length;
+		mode_of_transfer = 0;
+	}
+
+	/* Startup synchronization... */
+	/* Continuously send NAK or 'C' until sender responds. */
+	// ("Xdown");
+	while (1)
+  {
+		serial_putc('C');
+		timeout = loops_per_second;
+		while (!(serial_is_rx_ready()) && timeout)
+			timeout--;
+		if (timeout)
+			break;
+
+		if (!(--nbr_of_timeout))
+			return (0);
+//            return -1;
+	}
+
+	b_run = true;
+	// ("Got response");
+	while (b_run != false)
+  {
+		c = (char) serial_getc();
+		if (error_timeout)
+    { // Test for timeout in serial_getc
+			error_timeout = 0;
+			return (0);
+//            return (-1);
+		}
+		switch (c)
+    {
+      case SOH: /* 128-byte incoming packet */
+        // ("O");
+        b_run = getPacket(ptr_data, sno);
+        if (error_timeout)
+        { // Test for timeout in serial_getc
+          error_timeout = 0;
+          return (0);
+  //                return (-1);
+        }
+        if (b_run == true)
+        {
+          ++sno;
+          ptr_data += PKTLEN_128;
+          data_transfered += PKTLEN_128;
+        }
+			break;
+      case EOT: // ("E");
+        serial_putc(ACK);
+        b_run = false;
+			break;
+      case CAN: // ("C");
+      case ESC: /* "X" User-invoked abort */
+      default:
+        b_run = false;
+			break;
+		}
+		// ("!");
+	}
+	mode_of_transfer = 0;
+	return (true);
+//    return(b_run);
+}
+
diff --git a/bootloaders/metroM4/sam_ba_serial.h b/bootloaders/metroM4/sam_ba_serial.h
new file mode 100644
index 000000000..cb69f459e
--- /dev/null
+++ b/bootloaders/metroM4/sam_ba_serial.h
@@ -0,0 +1,143 @@
+/*
+  Copyright (c) 2015 Arduino LLC.  All right reserved.
+  Copyright (c) 2015 Atmel Corporation/Thibaut VIARD.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _SAM_BA_SERIAL_H_
+#define _SAM_BA_SERIAL_H_
+
+#include <stdint.h>
+#include <stdbool.h>
+
+
+/* USART buffer size (must be a power of two) */
+#define USART_BUFFER_SIZE        (128)
+
+/* Define the default time-out value for USART. */
+#define USART_DEFAULT_TIMEOUT    (1000)
+
+/* Xmodem related defines */
+/* CRC16  polynomial */
+#define CRC16POLY                (0x1021)
+
+#define SHARP_CHARACTER          '#'
+
+/* X/Ymodem protocol: */
+#define SOH                      (0x01)
+//#define STX                    (0x02)
+#define EOT                      (0x04)
+#define ACK                      (0x06)
+#define NAK                      (0x15)
+#define CAN                      (0x18)
+#define ESC                      (0x1b)
+
+#define PKTLEN_128               (128)
+
+
+/**
+ * \brief Open the given USART
+ */
+void serial_open(void);
+
+/**
+ * \brief Stops the USART
+ */
+void serial_close(void);
+
+/**
+ * \brief Puts a byte on usart line
+ *
+ * \param value      Value to put
+ *
+ * \return \c 1 if function was successfully done, otherwise \c 0.
+ */
+int serial_putc(int value);
+
+/**
+ * \brief Waits and gets a value on usart line
+ *
+ * \return value read on usart line
+ */
+int serial_getc(void);
+
+/**
+ * \brief Returns true if the SAM-BA Uart received the sharp char
+ *
+ * \return Returns true if the SAM-BA Uart received the sharp char
+ */
+int serial_sharp_received(void);
+
+/**
+ * \brief This function checks if a character has been received on the usart line
+ *
+ * \return \c 1 if a byte is ready to be read.
+ */
+bool serial_is_rx_ready(void);
+
+/**
+ * \brief Gets a value on usart line
+ *
+ * \return value read on usart line
+ */
+int serial_readc(void);
+
+/**
+ * \brief Send buffer on usart line
+ *
+ * \param data pointer
+ * \param number of data to send
+ * \return number of data sent
+ */
+uint32_t serial_putdata(void const* data, uint32_t length); //Send given data (polling)
+
+/**
+ * \brief Gets data from usart line
+ *
+ * \param data pointer
+ * \param number of data to get
+ * \return value read on usart line
+ */
+uint32_t serial_getdata(void* data, uint32_t length); //Get data from comm. device
+
+/**
+ * \brief Send buffer on usart line using Xmodem protocol
+ *
+ * \param data pointer
+ * \param number of data to send
+ * \return number of data sent
+ */
+uint32_t serial_putdata_xmd(void const* data, uint32_t length); //Send given data (polling) using xmodem (if necessary)
+
+/**
+ * \brief Gets data from usart line using Xmodem protocol
+ *
+ * \param data pointer
+ * \param number of data to get
+ * \return value read on usart line
+ */
+uint32_t serial_getdata_xmd(void* data, uint32_t length); //Get data from comm. device using xmodem (if necessary)
+
+/**
+ * \brief Compute the CRC
+ *
+ * \param Char to add to CRC
+ * \param Previous CRC
+ * \return The new computed CRC
+ */
+unsigned short serial_add_crc(char c, unsigned short crc);
+
+#endif // _SAM_BA_SERIAL_H_
diff --git a/bootloaders/metroM4/sam_ba_usb.c b/bootloaders/metroM4/sam_ba_usb.c
new file mode 100644
index 000000000..068b81d8b
--- /dev/null
+++ b/bootloaders/metroM4/sam_ba_usb.c
@@ -0,0 +1,436 @@
+/*
+  Copyright (c) 2015 Arduino LLC.  All right reserved.
+  Copyright (c) 2015 Atmel Corporation/Thibaut VIARD.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include <stdint.h>
+#include <string.h>
+#include "board_definitions.h"
+#include "sam_ba_usb.h"
+#include "board_driver_usb.h"
+#include "sam_ba_cdc.h"
+
+/* This data array will be copied into SRAM as its length is inferior to 64 bytes,
+ * and so can stay in flash.
+ */
+static __attribute__((__aligned__(4)))
+const char devDescriptor[] =
+{
+  /* Device descriptor */
+  0x12,   // bLength
+  0x01,   // bDescriptorType
+  0x00,   // bcdUSB L
+  0x02,   // bcdUSB H
+  0x02,   // bDeviceClass:    CDC class code
+  0x00,   // bDeviceSubclass: CDC class sub code
+  0x00,   // bDeviceProtocol: CDC Device protocol
+  0x40,   // bMaxPacketSize0
+  USB_VID_LOW,   // idVendor L
+  USB_VID_HIGH,   // idVendor H
+  USB_PID_LOW,   // idProduct L
+  USB_PID_HIGH,  // idProduct H
+  0x00,   // bcdDevice L, here matching SAM-BA version
+  0x02,   // bcdDevice H
+  STRING_INDEX_MANUFACTURER,   // iManufacturer
+  STRING_INDEX_PRODUCT,        // iProduct
+  0x00,   // SerialNumber, should be based on product unique ID
+  0x01    // bNumConfigs
+};
+
+/* This data array will be consumed directly by USB_Write() and must be in SRAM.
+ * We cannot send data from product internal flash.
+ */
+static __attribute__((__aligned__(4)))
+char cfgDescriptor[] =
+{
+  /* ============== CONFIGURATION 1 =========== */
+  /* Configuration 1 descriptor */
+  0x09,   // CbLength
+  0x02,   // CbDescriptorType
+  0x43,   // CwTotalLength 2 EP + Control
+  0x00,
+  0x02,   // CbNumInterfaces
+  0x01,   // CbConfigurationValue
+  0x00,   // CiConfiguration
+  0x80,   // CbmAttributes Bus powered without remote wakeup: 0x80, Self powered without remote wakeup: 0xc0
+  0x32,   // CMaxPower, report using 100mA, enough for a bootloader
+
+  /* Communication Class Interface Descriptor Requirement */
+  0x09, // bLength
+  0x04, // bDescriptorType
+  0x00, // bInterfaceNumber
+  0x00, // bAlternateSetting
+  0x01, // bNumEndpoints
+  0x02, // bInterfaceClass
+  0x02, // bInterfaceSubclass
+  0x00, // bInterfaceProtocol
+  0x00, // iInterface
+
+  /* Header Functional Descriptor */
+  0x05, // bFunction Length
+  0x24, // bDescriptor type: CS_INTERFACE
+  0x00, // bDescriptor subtype: Header Func Desc
+  0x10, // bcdCDC:1.1
+  0x01,
+
+  /* ACM Functional Descriptor */
+  0x04, // bFunctionLength
+  0x24, // bDescriptor Type: CS_INTERFACE
+  0x02, // bDescriptor Subtype: ACM Func Desc
+  0x00, // bmCapabilities
+
+  /* Union Functional Descriptor */
+  0x05, // bFunctionLength
+  0x24, // bDescriptorType: CS_INTERFACE
+  0x06, // bDescriptor Subtype: Union Func Desc
+  0x00, // bMasterInterface: Communication Class Interface
+  0x01, // bSlaveInterface0: Data Class Interface
+
+  /* Call Management Functional Descriptor */
+  0x05, // bFunctionLength
+  0x24, // bDescriptor Type: CS_INTERFACE
+  0x01, // bDescriptor Subtype: Call Management Func Desc
+  0x00, // bmCapabilities: D1 + D0
+  0x01, // bDataInterface: Data Class Interface 1
+
+  /* Endpoint 1 descriptor */
+  0x07,   // bLength
+  0x05,   // bDescriptorType
+  0x83,   // bEndpointAddress, Endpoint 03 - IN
+  0x03,   // bmAttributes      INT
+  0x08,   // wMaxPacketSize
+  0x00,
+  0xFF,   // bInterval
+
+  /* Data Class Interface Descriptor Requirement */
+  0x09, // bLength
+  0x04, // bDescriptorType
+  0x01, // bInterfaceNumber
+  0x00, // bAlternateSetting
+  0x02, // bNumEndpoints
+  0x0A, // bInterfaceClass
+  0x00, // bInterfaceSubclass
+  0x00, // bInterfaceProtocol
+  0x00, // iInterface
+
+  /* First alternate setting */
+  /* Endpoint 1 descriptor */
+  0x07,   // bLength
+  0x05,   // bDescriptorType
+  0x81,   // bEndpointAddress, Endpoint 01 - IN
+  0x02,   // bmAttributes      BULK
+  USB_EP_IN_SIZE,   // wMaxPacketSize
+  0x00,
+  0x00,   // bInterval
+
+  /* Endpoint 2 descriptor */
+  0x07,   // bLength
+  0x05,   // bDescriptorType
+  0x02,   // bEndpointAddress, Endpoint 02 - OUT
+  0x02,   // bmAttributes      BULK
+  USB_EP_OUT_SIZE,   // wMaxPacketSize
+  0x00,
+  0x00    // bInterval
+};
+
+#ifndef STRING_MANUFACTURER
+#  define STRING_MANUFACTURER "Arduino LLC"
+#endif
+
+#ifndef STRING_PRODUCT
+#  define STRING_PRODUCT "Arduino Zero"
+#endif
+
+USB_CDC sam_ba_cdc;
+
+/*----------------------------------------------------------------------------
+ * \brief This function is a callback invoked when a SETUP packet is received
+ */
+void sam_ba_usb_CDC_Enumerate(P_USB_CDC pCdc)
+{
+  Usb *pUsb = pCdc->pUsb;
+  static volatile uint8_t bmRequestType, bRequest, dir;
+  static volatile uint16_t wValue, wIndex, wLength, wStatus;
+
+  /* Clear the Received Setup flag */
+  pUsb->DEVICE.DeviceEndpoint[0].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_RXSTP;
+
+  /* Read the USB request parameters */
+  bmRequestType = udd_ep_out_cache_buffer[0][0];
+  bRequest      = udd_ep_out_cache_buffer[0][1];
+  wValue        = (udd_ep_out_cache_buffer[0][2] & 0xFF);
+  wValue       |= (udd_ep_out_cache_buffer[0][3] << 8);
+  wIndex        = (udd_ep_out_cache_buffer[0][4] & 0xFF);
+  wIndex       |= (udd_ep_out_cache_buffer[0][5] << 8);
+  wLength       = (udd_ep_out_cache_buffer[0][6] & 0xFF);
+  wLength      |= (udd_ep_out_cache_buffer[0][7] << 8);
+
+  /* Clear the Bank 0 ready flag on Control OUT */
+  pUsb->DEVICE.DeviceEndpoint[0].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_BK0RDY;
+
+  /* Handle supported standard device request Cf Table 9-3 in USB specification Rev 1.1 */
+  switch ((bRequest << 8) | bmRequestType)
+  {
+    case STD_GET_DESCRIPTOR:
+      if (wValue>>8 == STD_GET_DESCRIPTOR_DEVICE)
+      {
+        /* Return Device Descriptor */
+        USB_Write(pCdc->pUsb, devDescriptor, SAM_BA_MIN(sizeof(devDescriptor), wLength), USB_EP_CTRL);
+      }
+      else if (wValue>>8 == STD_GET_DESCRIPTOR_CONFIGURATION)
+      {
+        /* Return Configuration Descriptor */
+        USB_Write(pCdc->pUsb, cfgDescriptor, SAM_BA_MIN(sizeof(cfgDescriptor), wLength), USB_EP_CTRL);
+      }
+      else if (wValue>>8 == STD_GET_DESCRIPTOR_STRING)
+      {
+        switch ( wValue & 0xff )
+        {
+          case STRING_INDEX_LANGUAGES: {
+            uint16_t STRING_LANGUAGE[2] = { (STD_GET_DESCRIPTOR_STRING<<8) | 4, 0x0409 };
+
+            USB_Write(pCdc->pUsb, (const char*)STRING_LANGUAGE, SAM_BA_MIN(sizeof(STRING_LANGUAGE), wLength), USB_EP_CTRL);
+          }
+          break;
+
+          case STRING_INDEX_MANUFACTURER:
+            USB_SendString(pCdc->pUsb, STRING_MANUFACTURER, wLength );
+          break;
+
+          case STRING_INDEX_PRODUCT:
+            USB_SendString(pCdc->pUsb, STRING_PRODUCT, wLength );
+          break;
+          default:
+            /* Stall the request */
+            USB_SendStall(pUsb, true);
+          break;
+        }
+      }
+      else
+      {
+        /* Stall the request */
+        USB_SendStall(pUsb, true);
+      }
+    break;
+
+    case STD_SET_ADDRESS:
+      /* Send ZLP */
+      USB_SendZlp(pUsb);
+      /* Set device address to the newly received address from host */
+      USB_SetAddress(pCdc->pUsb, wValue);
+    break;
+
+    case STD_SET_CONFIGURATION:
+      /* Store configuration */
+      pCdc->currentConfiguration = (uint8_t)wValue;
+
+      /* Send ZLP */
+      USB_SendZlp(pUsb);
+
+      /* Configure the 3 needed endpoints */
+      USB_Configure(pUsb);
+    break;
+
+    case STD_GET_CONFIGURATION:
+      /* Return current configuration value */
+      USB_Write(pCdc->pUsb, (char *) &(pCdc->currentConfiguration), sizeof(pCdc->currentConfiguration), USB_EP_CTRL);
+    break;
+
+    case STD_GET_STATUS_ZERO:
+      wStatus = 0;
+      USB_Write(pCdc->pUsb, (char *) &wStatus, sizeof(wStatus), USB_EP_CTRL);
+    break;
+
+    case STD_GET_STATUS_INTERFACE:
+      wStatus = 0;
+      USB_Write(pCdc->pUsb, (char *) &wStatus, sizeof(wStatus), USB_EP_CTRL);
+    break;
+
+    case STD_GET_STATUS_ENDPOINT:
+      wStatus = 0;
+      dir = wIndex & 80;
+      wIndex &= 0x0F;
+      if (wIndex <= 3)
+      {
+        if (dir)
+        {
+          wStatus = (pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUS.reg & USB_DEVICE_EPSTATUSSET_STALLRQ1) ? 1 : 0;
+        }
+        else
+        {
+          wStatus = (pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUS.reg & USB_DEVICE_EPSTATUSSET_STALLRQ0) ? 1 : 0;
+        }
+        /* Return current status of endpoint */
+        USB_Write(pCdc->pUsb, (char *) &wStatus, sizeof(wStatus), USB_EP_CTRL);
+      }
+      else
+      {
+        /* Stall the request */
+        USB_SendStall(pUsb, true);
+      }
+    break;
+
+    case STD_SET_FEATURE_ZERO:
+      /* Stall the request */
+      USB_SendStall(pUsb, true);
+    break;
+
+    case STD_SET_FEATURE_INTERFACE:
+      /* Send ZLP */
+      USB_SendZlp(pUsb);
+    break;
+
+    case STD_SET_FEATURE_ENDPOINT:
+      dir = wIndex & 0x80;
+      wIndex &= 0x0F;
+      if ((wValue == 0) && wIndex && (wIndex <= 3))
+      {
+        /* Set STALL request for the endpoint */
+        if (dir)
+        {
+          pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUSSET.reg = USB_DEVICE_EPSTATUSSET_STALLRQ1;
+        }
+        else
+        {
+          pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUSSET.reg = USB_DEVICE_EPSTATUSSET_STALLRQ0;
+        }
+
+        /* Send ZLP */
+        USB_SendZlp(pUsb);
+      }
+      else
+      {
+        /* Stall the request */
+        USB_SendStall(pUsb, true);
+      }
+    break;
+
+    case STD_SET_INTERFACE:
+    case STD_CLEAR_FEATURE_ZERO:
+      /* Stall the request */
+      USB_SendStall(pUsb, true);
+    break;
+
+    case STD_CLEAR_FEATURE_INTERFACE:
+      /* Send ZLP */
+      USB_SendZlp(pUsb);
+    break;
+
+    case STD_CLEAR_FEATURE_ENDPOINT:
+      dir = wIndex & 0x80;
+      wIndex &= 0x0F;
+
+      if ((wValue == 0) && wIndex && (wIndex <= 3))
+      {
+        if (dir)
+        {
+          if (pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUS.bit.STALLRQ1)
+          {
+            // Remove stall request
+            pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_STALLRQ1;
+            if (pUsb->DEVICE.DeviceEndpoint[wIndex].EPINTFLAG.bit.STALL1)
+            {
+              pUsb->DEVICE.DeviceEndpoint[wIndex].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_STALL1;
+              // The Stall has occurred, then reset data toggle
+              pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSSET_DTGLIN;
+            }
+          }
+        }
+        else
+        {
+          if (pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUS.bit.STALLRQ0)
+          {
+            // Remove stall request
+            pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_STALLRQ0;
+            if (pUsb->DEVICE.DeviceEndpoint[wIndex].EPINTFLAG.bit.STALL0)
+            {
+              pUsb->DEVICE.DeviceEndpoint[wIndex].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_STALL0;
+              // The Stall has occurred, then reset data toggle
+              pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSSET_DTGLOUT;
+            }
+          }
+        }
+        /* Send ZLP */
+        USB_SendZlp(pUsb);
+      }
+      else
+      {
+        USB_SendStall(pUsb, true);
+      }
+    break;
+
+    // handle CDC class requests
+    case SET_LINE_CODING:
+      /* Send ZLP */
+      USB_SendZlp(pUsb);
+    break;
+
+    case GET_LINE_CODING:
+      /* Send current line coding */
+      USB_Write(pCdc->pUsb, (char *) &line_coding, SAM_BA_MIN(sizeof(usb_cdc_line_coding_t), wLength), USB_EP_CTRL);
+    break;
+
+    case SET_CONTROL_LINE_STATE:
+      /* Store the current connection */
+      pCdc->currentConnection = wValue;
+      /* Send ZLP */
+      USB_SendZlp(pUsb);
+    break;
+
+    default:
+      /* Stall the request */
+      USB_SendStall(pUsb, true);
+    break;
+  }
+}
+
+/*----------------------------------------------------------------------------
+ * \brief
+ */
+P_USB_CDC usb_init(void)
+{
+  sam_ba_cdc.pUsb = USB;
+
+  /* Initialize USB */
+  USB_Init();
+  /* Get the default CDC structure settings */
+  USB_Open(&sam_ba_cdc, sam_ba_cdc.pUsb);
+
+  return &sam_ba_cdc;
+}
+
+/*----------------------------------------------------------------------------
+ * \brief Send a USB descriptor string.
+ *
+ * The input string is plain ASCII but is sent out as UTF-16 with the correct 2-byte prefix.
+ */
+uint32_t USB_SendString(Usb *pUsb, const char* ascii_string, uint8_t maxLength)
+{
+  uint8_t string_descriptor[255]; // Max USB-allowed string length
+  uint16_t* unicode_string=(uint16_t*)(string_descriptor+2); // point on 3 bytes of descriptor
+  int resulting_length;
+
+  string_descriptor[0] = (strlen(ascii_string)<<1) + 2;
+  string_descriptor[1] = STD_GET_DESCRIPTOR_STRING;
+
+  for ( resulting_length = 1 ; *ascii_string && (resulting_length<maxLength>>1) ; resulting_length++ )
+  {
+    *unicode_string++ = (uint16_t)(*ascii_string++);
+  }
+
+  return USB_Write(pUsb, (const char*)string_descriptor, resulting_length<<1, USB_EP_CTRL);
+}
diff --git a/bootloaders/metroM4/sam_ba_usb.h b/bootloaders/metroM4/sam_ba_usb.h
new file mode 100644
index 000000000..457fdbc09
--- /dev/null
+++ b/bootloaders/metroM4/sam_ba_usb.h
@@ -0,0 +1,103 @@
+/*
+  Copyright (c) 2015 Arduino LLC.  All right reserved.
+  Copyright (c) 2015 Atmel Corporation/Thibaut VIARD.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef CDC_ENUMERATE_H
+#define CDC_ENUMERATE_H
+
+#include <sam.h>
+#include <stdbool.h>
+
+#define USB_EP_CTRL             (0u)
+#define USB_EP_OUT              (2u)
+#define USB_EP_OUT_SIZE         (0x40u)
+#define USB_EP_IN               (1u)
+#define USB_EP_IN_SIZE          (0x40u)
+#define USB_EP_COMM             (3u)
+#define MAX_EP                  (4u)
+
+/* USB standard request code */
+#define STD_GET_STATUS_ZERO            (0x0080u)
+#define STD_GET_STATUS_INTERFACE       (0x0081u)
+#define STD_GET_STATUS_ENDPOINT        (0x0082u)
+
+#define STD_CLEAR_FEATURE_ZERO         (0x0100u)
+#define STD_CLEAR_FEATURE_INTERFACE    (0x0101u)
+#define STD_CLEAR_FEATURE_ENDPOINT     (0x0102u)
+
+#define STD_SET_FEATURE_ZERO           (0x0300u)
+#define STD_SET_FEATURE_INTERFACE      (0x0301u)
+#define STD_SET_FEATURE_ENDPOINT       (0x0302u)
+
+#define STD_SET_ADDRESS                (0x0500u)
+#define STD_GET_DESCRIPTOR             (0x0680u)
+#define STD_SET_DESCRIPTOR             (0x0700u)
+#define STD_GET_CONFIGURATION          (0x0880u)
+#define STD_SET_CONFIGURATION          (0x0900u)
+#define STD_GET_INTERFACE              (0x0A81u)
+#define STD_SET_INTERFACE              (0x0B01u)
+#define STD_SYNCH_FRAME                (0x0C82u)
+
+#define STD_GET_DESCRIPTOR_DEVICE                          (1u)
+#define STD_GET_DESCRIPTOR_CONFIGURATION                   (2u)
+#define STD_GET_DESCRIPTOR_STRING                          (3u)
+#define STD_GET_DESCRIPTOR_INTERFACE                       (4u)
+#define STD_GET_DESCRIPTOR_ENDPOINT                        (5u)
+#define STD_GET_DESCRIPTOR_DEVICE_QUALIFIER                (6u)
+#define STD_GET_DESCRIPTOR_OTHER_SPEED_CONFIGURATION       (7u)
+#define STD_GET_DESCRIPTOR_INTERFACE_POWER1                (8u)
+
+#define FEATURE_ENDPOINT_HALT          (0u)
+#define FEATURE_DEVICE_REMOTE_WAKEUP   (1u)
+#define FEATURE_TEST_MODE              (2u)
+
+#define STRING_INDEX_LANGUAGES         (0x00u)
+#define STRING_INDEX_MANUFACTURER      (0x01u)
+#define STRING_INDEX_PRODUCT           (0x02u)
+
+#define SAM_BA_MIN(a, b) (((a) < (b)) ? (a) : (b))
+
+
+typedef struct _USB_CDC
+{
+	// Private members
+	Usb *pUsb;
+	uint8_t currentConfiguration;
+	uint8_t currentConnection;
+	// Public Methods:
+	uint8_t (*IsConfigured)(struct _USB_CDC *pCdc);
+//	uint32_t (*Write) (Usb *pUsb, const char *pData, uint32_t length, uint8_t ep_num);
+//	uint32_t (*Read)  (Usb *pUsb, char *pData, uint32_t length);
+} USB_CDC, *P_USB_CDC;
+
+/**
+ * \brief Initializes the USB module
+ *
+ * \return Pointer to the USB CDC structure
+ */
+P_USB_CDC usb_init(void);
+
+void sam_ba_usb_CDC_Enumerate(P_USB_CDC pCdc);
+
+uint32_t USB_SendString(Usb *pUsb, const char* ascii_string, uint8_t maxLength);
+
+extern USB_CDC sam_ba_cdc;
+
+
+
+#endif // CDC_ENUMERATE_H
diff --git a/bootloaders/metroM4/samd51_sam_ba.componentinfo.xml b/bootloaders/metroM4/samd51_sam_ba.componentinfo.xml
new file mode 100644
index 000000000..e27575522
--- /dev/null
+++ b/bootloaders/metroM4/samd51_sam_ba.componentinfo.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Store xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="AtmelPackComponentManagement">
+	<ProjectComponents />
+</Store>
\ No newline at end of file
diff --git a/bootloaders/metroM4/samd51_sam_ba.cproj b/bootloaders/metroM4/samd51_sam_ba.cproj
new file mode 100644
index 000000000..f5193cae1
--- /dev/null
+++ b/bootloaders/metroM4/samd51_sam_ba.cproj
@@ -0,0 +1,300 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="14.0">
+  <PropertyGroup>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectVersion>7.0</ProjectVersion>
+    <ToolchainName>com.Atmel.ARMGCC.C</ToolchainName>
+    <ProjectGuid>dce6c7e3-ee26-4d79-826b-08594b9ad897</ProjectGuid>
+    <avrdevice>ATSAMD51J19A</avrdevice>
+    <avrdeviceseries>none</avrdeviceseries>
+    <OutputType>Executable</OutputType>
+    <Language>C</Language>
+    <OutputFileName>$(MSBuildProjectName)</OutputFileName>
+    <OutputFileExtension>.elf</OutputFileExtension>
+    <OutputDirectory>$(MSBuildProjectDirectory)\$(Configuration)</OutputDirectory>
+    <AssemblyName>samd21_sam_ba</AssemblyName>
+    <Name>samd51_sam_ba</Name>
+    <RootNamespace>samd21_sam_ba</RootNamespace>
+    <ToolchainFlavour>Native</ToolchainFlavour>
+    <KeepTimersRunning>true</KeepTimersRunning>
+    <OverrideVtor>false</OverrideVtor>
+    <CacheFlash>true</CacheFlash>
+    <ProgFlashFromRam>true</ProgFlashFromRam>
+    <RamSnippetAddress>0x20000000</RamSnippetAddress>
+    <UncachedRange />
+    <preserveEEPROM>true</preserveEEPROM>
+    <OverrideVtorValue>exception_table</OverrideVtorValue>
+    <BootSegment>2</BootSegment>
+    <eraseonlaunchrule>0</eraseonlaunchrule>
+    <ExternalProgrammingToolCommand />
+    <AsfFrameworkConfig>
+      <framework-data xmlns="">
+        <options />
+        <configurations />
+        <files />
+        <documentation help="" />
+        <offline-documentation help="" />
+        <dependencies>
+          <content-extension eid="atmel.asf" uuidref="Atmel.ASF" version="3.27.3" />
+        </dependencies>
+      </framework-data>
+    </AsfFrameworkConfig>
+    <avrtool>com.atmel.avrdbg.tool.edbg</avrtool>
+    <avrtoolserialnumber>00000000EZE000006352</avrtoolserialnumber>
+    <avrdeviceexpectedsignature>0x60060005</avrdeviceexpectedsignature>
+    <avrtoolinterface>SWD</avrtoolinterface>
+    <com_atmel_avrdbg_tool_atmelice>
+      <ToolOptions>
+        <InterfaceProperties>
+          <SwdClock>0</SwdClock>
+        </InterfaceProperties>
+        <InterfaceName>SWD</InterfaceName>
+      </ToolOptions>
+      <ToolType>com.atmel.avrdbg.tool.atmelice</ToolType>
+      <ToolNumber>J41800001895</ToolNumber>
+      <ToolName>Atmel-ICE</ToolName>
+    </com_atmel_avrdbg_tool_atmelice>
+    <avrtoolinterfaceclock>2000000</avrtoolinterfaceclock>
+    <com_atmel_avrdbg_tool_edbg>
+      <ToolOptions>
+        <InterfaceProperties>
+          <SwdClock>2000000</SwdClock>
+        </InterfaceProperties>
+        <InterfaceName>SWD</InterfaceName>
+      </ToolOptions>
+      <ToolType>com.atmel.avrdbg.tool.edbg</ToolType>
+      <ToolNumber>00000000EZE000006352</ToolNumber>
+      <ToolName>EDBG</ToolName>
+    </com_atmel_avrdbg_tool_edbg>
+    <UseGdb>True</UseGdb>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
+    <ToolchainSettings>
+      <ArmGcc>
+  <armgcc.common.outputfiles.hex>True</armgcc.common.outputfiles.hex>
+  <armgcc.common.outputfiles.lss>True</armgcc.common.outputfiles.lss>
+  <armgcc.common.outputfiles.eep>True</armgcc.common.outputfiles.eep>
+  <armgcc.common.outputfiles.bin>True</armgcc.common.outputfiles.bin>
+  <armgcc.common.outputfiles.srec>True</armgcc.common.outputfiles.srec>
+  <armgcc.compiler.symbols.DefSymbols>
+    <ListValues>
+      <Value>NDEBUG</Value>
+    </ListValues>
+  </armgcc.compiler.symbols.DefSymbols>
+  <armgcc.compiler.optimization.level>Optimize for size (-Os)</armgcc.compiler.optimization.level>
+  <armgcc.compiler.optimization.PrepareFunctionsForGarbageCollection>True</armgcc.compiler.optimization.PrepareFunctionsForGarbageCollection>
+  <armgcc.compiler.warnings.AllWarnings>True</armgcc.compiler.warnings.AllWarnings>
+  <armgcc.linker.libraries.Libraries>
+    <ListValues>
+      <Value>libm</Value>
+    </ListValues>
+  </armgcc.linker.libraries.Libraries>
+  <armgcc.linker.optimization.GarbageCollectUnusedSections>True</armgcc.linker.optimization.GarbageCollectUnusedSections>
+  <armgcc.linker.miscellaneous.LinkerFlags>-Tsamd21j18a_flash.ld</armgcc.linker.miscellaneous.LinkerFlags>
+</ArmGcc>
+    </ToolchainSettings>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
+    <ToolchainSettings>
+      <ArmGcc>
+  <armgcc.common.outputfiles.hex>True</armgcc.common.outputfiles.hex>
+  <armgcc.common.outputfiles.lss>True</armgcc.common.outputfiles.lss>
+  <armgcc.common.outputfiles.eep>True</armgcc.common.outputfiles.eep>
+  <armgcc.common.outputfiles.bin>True</armgcc.common.outputfiles.bin>
+  <armgcc.common.outputfiles.srec>True</armgcc.common.outputfiles.srec>
+  <armgcc.compiler.symbols.DefSymbols>
+    <ListValues>
+      <Value>DEBUG</Value>
+    </ListValues>
+  </armgcc.compiler.symbols.DefSymbols>
+  <armgcc.compiler.optimization.level>Optimize (-O1)</armgcc.compiler.optimization.level>
+  <armgcc.compiler.optimization.PrepareFunctionsForGarbageCollection>True</armgcc.compiler.optimization.PrepareFunctionsForGarbageCollection>
+  <armgcc.compiler.optimization.DebugLevel>Maximum (-g3)</armgcc.compiler.optimization.DebugLevel>
+  <armgcc.compiler.warnings.AllWarnings>True</armgcc.compiler.warnings.AllWarnings>
+  <armgcc.linker.libraries.Libraries>
+    <ListValues>
+      <Value>libm</Value>
+    </ListValues>
+  </armgcc.linker.libraries.Libraries>
+  <armgcc.linker.optimization.GarbageCollectUnusedSections>True</armgcc.linker.optimization.GarbageCollectUnusedSections>
+  <armgcc.linker.miscellaneous.LinkerFlags>-Tsamd21j18a_flash.ld</armgcc.linker.miscellaneous.LinkerFlags>
+  <armgcc.assembler.debugging.DebugLevel>Default (-g)</armgcc.assembler.debugging.DebugLevel>
+  <armgcc.preprocessingassembler.debugging.DebugLevel>Default (-Wa,-g)</armgcc.preprocessingassembler.debugging.DebugLevel>
+</ArmGcc>
+    </ToolchainSettings>
+    <UsesExternalMakeFile>True</UsesExternalMakeFile>
+    <OutputDirectory />
+    <BuildTarget>DEBUG=1 all</BuildTarget>
+    <CleanTarget>clean</CleanTarget>
+    <ExternalMakeFilePath>Makefile</ExternalMakeFilePath>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)' == 'featherm4' ">
+    <ToolchainSettings>
+      <ArmGcc>
+  <armgcc.common.outputfiles.hex>True</armgcc.common.outputfiles.hex>
+  <armgcc.common.outputfiles.lss>True</armgcc.common.outputfiles.lss>
+  <armgcc.common.outputfiles.eep>True</armgcc.common.outputfiles.eep>
+  <armgcc.common.outputfiles.bin>True</armgcc.common.outputfiles.bin>
+  <armgcc.common.outputfiles.srec>True</armgcc.common.outputfiles.srec>
+  <armgcc.compiler.symbols.DefSymbols>
+    <ListValues>
+      <Value>DEBUG</Value>
+    </ListValues>
+  </armgcc.compiler.symbols.DefSymbols>
+  <armgcc.compiler.optimization.level>Optimize (-O1)</armgcc.compiler.optimization.level>
+  <armgcc.compiler.optimization.PrepareFunctionsForGarbageCollection>True</armgcc.compiler.optimization.PrepareFunctionsForGarbageCollection>
+  <armgcc.compiler.optimization.DebugLevel>Maximum (-g3)</armgcc.compiler.optimization.DebugLevel>
+  <armgcc.compiler.warnings.AllWarnings>True</armgcc.compiler.warnings.AllWarnings>
+  <armgcc.linker.libraries.Libraries>
+    <ListValues>
+      <Value>libm</Value>
+    </ListValues>
+  </armgcc.linker.libraries.Libraries>
+  <armgcc.linker.optimization.GarbageCollectUnusedSections>True</armgcc.linker.optimization.GarbageCollectUnusedSections>
+  <armgcc.linker.miscellaneous.LinkerFlags>-Tsamd21j18a_flash.ld</armgcc.linker.miscellaneous.LinkerFlags>
+  <armgcc.assembler.debugging.DebugLevel>Default (-g)</armgcc.assembler.debugging.DebugLevel>
+  <armgcc.preprocessingassembler.debugging.DebugLevel>Default (-Wa,-g)</armgcc.preprocessingassembler.debugging.DebugLevel>
+</ArmGcc>
+    </ToolchainSettings>
+    <UsesExternalMakeFile>True</UsesExternalMakeFile>
+    <OutputDirectory />
+    <BuildTarget>DEBUG=1 all BOARD_ID=FEATHER_M4 BOARD_CHIP=__SAMD51G19A__</BuildTarget>
+    <CleanTarget>clean BOARD_ID=FEATHER_M4</CleanTarget>
+    <ExternalMakeFilePath>Makefile</ExternalMakeFilePath>
+    <OutputPath>bin\featherm4\</OutputPath>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)' == 'metrom4' ">
+    <ToolchainSettings>
+      <ArmGcc>
+  <armgcc.common.outputfiles.hex>True</armgcc.common.outputfiles.hex>
+  <armgcc.common.outputfiles.lss>True</armgcc.common.outputfiles.lss>
+  <armgcc.common.outputfiles.eep>True</armgcc.common.outputfiles.eep>
+  <armgcc.common.outputfiles.bin>True</armgcc.common.outputfiles.bin>
+  <armgcc.common.outputfiles.srec>True</armgcc.common.outputfiles.srec>
+  <armgcc.compiler.symbols.DefSymbols>
+    <ListValues>
+      <Value>DEBUG</Value>
+    </ListValues>
+  </armgcc.compiler.symbols.DefSymbols>
+  <armgcc.compiler.optimization.level>Optimize (-O1)</armgcc.compiler.optimization.level>
+  <armgcc.compiler.optimization.PrepareFunctionsForGarbageCollection>True</armgcc.compiler.optimization.PrepareFunctionsForGarbageCollection>
+  <armgcc.compiler.optimization.DebugLevel>Maximum (-g3)</armgcc.compiler.optimization.DebugLevel>
+  <armgcc.compiler.warnings.AllWarnings>True</armgcc.compiler.warnings.AllWarnings>
+  <armgcc.linker.libraries.Libraries>
+    <ListValues>
+      <Value>libm</Value>
+    </ListValues>
+  </armgcc.linker.libraries.Libraries>
+  <armgcc.linker.optimization.GarbageCollectUnusedSections>True</armgcc.linker.optimization.GarbageCollectUnusedSections>
+  <armgcc.linker.miscellaneous.LinkerFlags>-Tsamd21j18a_flash.ld</armgcc.linker.miscellaneous.LinkerFlags>
+  <armgcc.assembler.debugging.DebugLevel>Default (-g)</armgcc.assembler.debugging.DebugLevel>
+  <armgcc.preprocessingassembler.debugging.DebugLevel>Default (-Wa,-g)</armgcc.preprocessingassembler.debugging.DebugLevel>
+</ArmGcc>
+    </ToolchainSettings>
+    <UsesExternalMakeFile>True</UsesExternalMakeFile>
+    <OutputDirectory />
+    <BuildTarget>DEBUG=0 all BOARD_ID=METRO_M4 BOARD_CHIP=__SAMD51J19A__</BuildTarget>
+    <CleanTarget>clean BOARD_ID=METRO_M4</CleanTarget>
+    <ExternalMakeFilePath>Makefile</ExternalMakeFilePath>
+    <OutputPath>bin\metrom4\</OutputPath>
+    <OutputFileName>METRO_M4_sam_ba</OutputFileName>
+    <OutputFileExtension>.elf</OutputFileExtension>
+  </PropertyGroup>
+  <ItemGroup>
+    <Compile Include="board_definitions.h">
+      <SubType>compile</SubType>
+      <Link>board_definitions.h</Link>
+    </Compile>
+    <Compile Include="board_definitions_feather_m4.h">
+      <SubType>compile</SubType>
+    </Compile>
+    <Compile Include="board_definitions_metro_m4.h">
+      <SubType>compile</SubType>
+    </Compile>
+    <Compile Include="board_driver_led.c">
+      <SubType>compile</SubType>
+      <Link>board_driver_led.c</Link>
+    </Compile>
+    <Compile Include="board_driver_led.h">
+      <SubType>compile</SubType>
+      <Link>board_driver_led.h</Link>
+    </Compile>
+    <Compile Include="board_driver_serial.c">
+      <SubType>compile</SubType>
+      <Link>board_driver_serial.c</Link>
+    </Compile>
+    <Compile Include="board_driver_serial.h">
+      <SubType>compile</SubType>
+      <Link>board_driver_serial.h</Link>
+    </Compile>
+    <Compile Include="board_driver_usb.c">
+      <SubType>compile</SubType>
+      <Link>board_driver_usb.c</Link>
+    </Compile>
+    <Compile Include="board_driver_usb.h">
+      <SubType>compile</SubType>
+      <Link>board_driver_usb.h</Link>
+    </Compile>
+    <Compile Include="board_init.c">
+      <SubType>compile</SubType>
+      <Link>board_init.c</Link>
+    </Compile>
+    <Compile Include="board_startup.c">
+      <SubType>compile</SubType>
+      <Link>board_startup.c</Link>
+    </Compile>
+    <Compile Include="main.c">
+      <SubType>compile</SubType>
+      <Link>main.c</Link>
+    </Compile>
+    <Compile Include="sam_ba_cdc.c">
+      <SubType>compile</SubType>
+      <Link>sam_ba_cdc.c</Link>
+    </Compile>
+    <Compile Include="sam_ba_cdc.h">
+      <SubType>compile</SubType>
+      <Link>sam_ba_cdc.h</Link>
+    </Compile>
+    <Compile Include="sam_ba_monitor.c">
+      <SubType>compile</SubType>
+      <Link>sam_ba_monitor.c</Link>
+    </Compile>
+    <Compile Include="sam_ba_monitor.h">
+      <SubType>compile</SubType>
+      <Link>sam_ba_monitor.h</Link>
+    </Compile>
+    <Compile Include="sam_ba_serial.c">
+      <SubType>compile</SubType>
+      <Link>sam_ba_serial.c</Link>
+    </Compile>
+    <Compile Include="sam_ba_serial.h">
+      <SubType>compile</SubType>
+      <Link>sam_ba_serial.h</Link>
+    </Compile>
+    <Compile Include="sam_ba_usb.c">
+      <SubType>compile</SubType>
+      <Link>sam_ba_usb.c</Link>
+    </Compile>
+    <Compile Include="sam_ba_usb.h">
+      <SubType>compile</SubType>
+      <Link>sam_ba_usb.h</Link>
+    </Compile>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="bootloader_FEATHER_M4.ld">
+      <SubType>compile</SubType>
+    </None>
+    <None Include="bootloader_METRO_M4.ld">
+      <SubType>compile</SubType>
+    </None>
+    <None Include="Makefile">
+      <SubType>compile</SubType>
+      <Link>Makefile</Link>
+    </None>
+    <None Include="README.md">
+      <SubType>compile</SubType>
+      <Link>README.md</Link>
+    </None>
+  </ItemGroup>
+  <Import Project="$(AVRSTUDIO_EXE_PATH)\\Vs\\Compiler.targets" />
+</Project>
\ No newline at end of file
diff --git a/bootloaders/metroM4/samdx1_sam_ba.atsln b/bootloaders/metroM4/samdx1_sam_ba.atsln
new file mode 100644
index 000000000..1869bec4c
--- /dev/null
+++ b/bootloaders/metroM4/samdx1_sam_ba.atsln
@@ -0,0 +1,22 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Atmel Studio Solution File, Format Version 11.00
+VisualStudioVersion = 14.0.23107.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{54F91283-7BC4-4236-8FF9-10F437C3AD48}") = "samd51_sam_ba", "samd51_sam_ba.cproj", "{DCE6C7E3-EE26-4D79-826B-08594B9AD897}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|ARM = Debug|ARM
+		Release|ARM = Release|ARM
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{DCE6C7E3-EE26-4D79-826B-08594B9AD897}.Debug|ARM.ActiveCfg = metrom4|ARM
+		{DCE6C7E3-EE26-4D79-826B-08594B9AD897}.Debug|ARM.Build.0 = metrom4|ARM
+		{DCE6C7E3-EE26-4D79-826B-08594B9AD897}.Release|ARM.ActiveCfg = Release|ARM
+		{DCE6C7E3-EE26-4D79-826B-08594B9AD897}.Release|ARM.Build.0 = Release|ARM
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
diff --git a/bootloaders/metroM4/update-bootloader-metro_m4-v2.0.0-adafruit.5.uf2 b/bootloaders/metroM4/update-bootloader-metro_m4-v2.0.0-adafruit.5.uf2
new file mode 100644
index 000000000..c817470a1
Binary files /dev/null and b/bootloaders/metroM4/update-bootloader-metro_m4-v2.0.0-adafruit.5.uf2 differ
diff --git a/bootloaders/mkr1000/samd21_sam_ba_arduino_mkr1000.bin b/bootloaders/mkr1000/samd21_sam_ba_arduino_mkr1000.bin
old mode 100755
new mode 100644
diff --git a/bootloaders/mkr1000/samd21_sam_ba_genuino_mkr1000.bin b/bootloaders/mkr1000/samd21_sam_ba_genuino_mkr1000.bin
old mode 100755
new mode 100644
diff --git a/bootloaders/mzero/Bootloader_D21/src/ASF/sam0/utils/cmsis/samd21/include/samd21e15a.h b/bootloaders/mzero/Bootloader_D21/src/ASF/sam0/utils/cmsis/samd21/include/samd21e15a.h
index 374a532e8..89fe03db6 100644
--- a/bootloaders/mzero/Bootloader_D21/src/ASF/sam0/utils/cmsis/samd21/include/samd21e15a.h
+++ b/bootloaders/mzero/Bootloader_D21/src/ASF/sam0/utils/cmsis/samd21/include/samd21e15a.h
@@ -218,7 +218,11 @@ void I2S_Handler                 ( void );
  * \brief Configuration of the Cortex-M0+ Processor and Core Peripherals
  */
 
-#define LITTLE_ENDIAN          1        
+#if defined(LITTLE_ENDIAN) && (LITTLE_ENDIAN != 1)
+  #error "Little Endian is already defined, but to different value than expected?!"
+#else
+  #define LITTLE_ENDIAN          1
+#endif
 #define __CM0PLUS_REV          1         /*!< Core revision r0p1 */
 #define __MPU_PRESENT          0         /*!< MPU present or not */
 #define __NVIC_PRIO_BITS       2         /*!< Number of bits used for Priority Levels */
diff --git a/bootloaders/mzero/Bootloader_D21/src/ASF/sam0/utils/cmsis/samd21/include/samd21e16a.h b/bootloaders/mzero/Bootloader_D21/src/ASF/sam0/utils/cmsis/samd21/include/samd21e16a.h
index 06bc2012e..c9d769004 100644
--- a/bootloaders/mzero/Bootloader_D21/src/ASF/sam0/utils/cmsis/samd21/include/samd21e16a.h
+++ b/bootloaders/mzero/Bootloader_D21/src/ASF/sam0/utils/cmsis/samd21/include/samd21e16a.h
@@ -218,7 +218,11 @@ void I2S_Handler                 ( void );
  * \brief Configuration of the Cortex-M0+ Processor and Core Peripherals
  */
 
-#define LITTLE_ENDIAN          1        
+#if defined(LITTLE_ENDIAN) && (LITTLE_ENDIAN != 1)
+  #error "Little Endian is already defined, but to different value than expected?!"
+#else
+  #define LITTLE_ENDIAN          1
+#endif
 #define __CM0PLUS_REV          1         /*!< Core revision r0p1 */
 #define __MPU_PRESENT          0         /*!< MPU present or not */
 #define __NVIC_PRIO_BITS       2         /*!< Number of bits used for Priority Levels */
diff --git a/bootloaders/mzero/Bootloader_D21/src/ASF/sam0/utils/cmsis/samd21/include/samd21e17a.h b/bootloaders/mzero/Bootloader_D21/src/ASF/sam0/utils/cmsis/samd21/include/samd21e17a.h
index ab17fbe06..cd2768281 100644
--- a/bootloaders/mzero/Bootloader_D21/src/ASF/sam0/utils/cmsis/samd21/include/samd21e17a.h
+++ b/bootloaders/mzero/Bootloader_D21/src/ASF/sam0/utils/cmsis/samd21/include/samd21e17a.h
@@ -218,7 +218,11 @@ void I2S_Handler                 ( void );
  * \brief Configuration of the Cortex-M0+ Processor and Core Peripherals
  */
 
-#define LITTLE_ENDIAN          1        
+#if defined(LITTLE_ENDIAN) && (LITTLE_ENDIAN != 1)
+  #error "Little Endian is already defined, but to different value than expected?!"
+#else
+  #define LITTLE_ENDIAN          1
+#endif
 #define __CM0PLUS_REV          1         /*!< Core revision r0p1 */
 #define __MPU_PRESENT          0         /*!< MPU present or not */
 #define __NVIC_PRIO_BITS       2         /*!< Number of bits used for Priority Levels */
diff --git a/bootloaders/mzero/Bootloader_D21/src/ASF/sam0/utils/cmsis/samd21/include/samd21e18a.h b/bootloaders/mzero/Bootloader_D21/src/ASF/sam0/utils/cmsis/samd21/include/samd21e18a.h
index df36c1394..f0da13ef3 100644
--- a/bootloaders/mzero/Bootloader_D21/src/ASF/sam0/utils/cmsis/samd21/include/samd21e18a.h
+++ b/bootloaders/mzero/Bootloader_D21/src/ASF/sam0/utils/cmsis/samd21/include/samd21e18a.h
@@ -218,7 +218,11 @@ void I2S_Handler                 ( void );
  * \brief Configuration of the Cortex-M0+ Processor and Core Peripherals
  */
 
-#define LITTLE_ENDIAN          1        
+#if defined(LITTLE_ENDIAN) && (LITTLE_ENDIAN != 1)
+  #error "Little Endian is already defined, but to different value than expected?!"
+#else
+  #define LITTLE_ENDIAN          1
+#endif
 #define __CM0PLUS_REV          1         /*!< Core revision r0p1 */
 #define __MPU_PRESENT          0         /*!< MPU present or not */
 #define __NVIC_PRIO_BITS       2         /*!< Number of bits used for Priority Levels */
diff --git a/bootloaders/mzero/Bootloader_D21/src/ASF/sam0/utils/cmsis/samd21/include/samd21g15a.h b/bootloaders/mzero/Bootloader_D21/src/ASF/sam0/utils/cmsis/samd21/include/samd21g15a.h
index c8b43b465..4b3d8407e 100644
--- a/bootloaders/mzero/Bootloader_D21/src/ASF/sam0/utils/cmsis/samd21/include/samd21g15a.h
+++ b/bootloaders/mzero/Bootloader_D21/src/ASF/sam0/utils/cmsis/samd21/include/samd21g15a.h
@@ -222,7 +222,11 @@ void I2S_Handler                 ( void );
  * \brief Configuration of the Cortex-M0+ Processor and Core Peripherals
  */
 
-#define LITTLE_ENDIAN          1        
+#if defined(LITTLE_ENDIAN) && (LITTLE_ENDIAN != 1)
+  #error "Little Endian is already defined, but to different value than expected?!"
+#else
+  #define LITTLE_ENDIAN          1
+#endif
 #define __CM0PLUS_REV          1         /*!< Core revision r0p1 */
 #define __MPU_PRESENT          0         /*!< MPU present or not */
 #define __NVIC_PRIO_BITS       2         /*!< Number of bits used for Priority Levels */
diff --git a/bootloaders/mzero/Bootloader_D21/src/ASF/sam0/utils/cmsis/samd21/include/samd21g16a.h b/bootloaders/mzero/Bootloader_D21/src/ASF/sam0/utils/cmsis/samd21/include/samd21g16a.h
index ee3957b73..fe4134f28 100644
--- a/bootloaders/mzero/Bootloader_D21/src/ASF/sam0/utils/cmsis/samd21/include/samd21g16a.h
+++ b/bootloaders/mzero/Bootloader_D21/src/ASF/sam0/utils/cmsis/samd21/include/samd21g16a.h
@@ -222,7 +222,11 @@ void I2S_Handler                 ( void );
  * \brief Configuration of the Cortex-M0+ Processor and Core Peripherals
  */
 
-#define LITTLE_ENDIAN          1        
+#if defined(LITTLE_ENDIAN) && (LITTLE_ENDIAN != 1)
+  #error "Little Endian is already defined, but to different value than expected?!"
+#else
+  #define LITTLE_ENDIAN          1
+#endif
 #define __CM0PLUS_REV          1         /*!< Core revision r0p1 */
 #define __MPU_PRESENT          0         /*!< MPU present or not */
 #define __NVIC_PRIO_BITS       2         /*!< Number of bits used for Priority Levels */
diff --git a/bootloaders/mzero/Bootloader_D21/src/ASF/sam0/utils/cmsis/samd21/include/samd21g17a.h b/bootloaders/mzero/Bootloader_D21/src/ASF/sam0/utils/cmsis/samd21/include/samd21g17a.h
index ca2edaf65..837d1eac0 100644
--- a/bootloaders/mzero/Bootloader_D21/src/ASF/sam0/utils/cmsis/samd21/include/samd21g17a.h
+++ b/bootloaders/mzero/Bootloader_D21/src/ASF/sam0/utils/cmsis/samd21/include/samd21g17a.h
@@ -222,7 +222,11 @@ void I2S_Handler                 ( void );
  * \brief Configuration of the Cortex-M0+ Processor and Core Peripherals
  */
 
-#define LITTLE_ENDIAN          1        
+#if defined(LITTLE_ENDIAN) && (LITTLE_ENDIAN != 1)
+  #error "Little Endian is already defined, but to different value than expected?!"
+#else
+  #define LITTLE_ENDIAN          1
+#endif
 #define __CM0PLUS_REV          1         /*!< Core revision r0p1 */
 #define __MPU_PRESENT          0         /*!< MPU present or not */
 #define __NVIC_PRIO_BITS       2         /*!< Number of bits used for Priority Levels */
diff --git a/bootloaders/mzero/Bootloader_D21/src/ASF/sam0/utils/cmsis/samd21/include/samd21g18a.h b/bootloaders/mzero/Bootloader_D21/src/ASF/sam0/utils/cmsis/samd21/include/samd21g18a.h
index db9b3aae9..79fcea154 100644
--- a/bootloaders/mzero/Bootloader_D21/src/ASF/sam0/utils/cmsis/samd21/include/samd21g18a.h
+++ b/bootloaders/mzero/Bootloader_D21/src/ASF/sam0/utils/cmsis/samd21/include/samd21g18a.h
@@ -222,7 +222,11 @@ void I2S_Handler                 ( void );
  * \brief Configuration of the Cortex-M0+ Processor and Core Peripherals
  */
 
-#define LITTLE_ENDIAN          1        
+#if defined(LITTLE_ENDIAN) && (LITTLE_ENDIAN != 1)
+  #error "Little Endian is already defined, but to different value than expected?!"
+#else
+  #define LITTLE_ENDIAN          1
+#endif
 #define __CM0PLUS_REV          1         /*!< Core revision r0p1 */
 #define __MPU_PRESENT          0         /*!< MPU present or not */
 #define __NVIC_PRIO_BITS       2         /*!< Number of bits used for Priority Levels */
diff --git a/bootloaders/mzero/Bootloader_D21/src/ASF/sam0/utils/cmsis/samd21/include/samd21j15a.h b/bootloaders/mzero/Bootloader_D21/src/ASF/sam0/utils/cmsis/samd21/include/samd21j15a.h
index 65dd3f44b..81dbb9d48 100644
--- a/bootloaders/mzero/Bootloader_D21/src/ASF/sam0/utils/cmsis/samd21/include/samd21j15a.h
+++ b/bootloaders/mzero/Bootloader_D21/src/ASF/sam0/utils/cmsis/samd21/include/samd21j15a.h
@@ -226,7 +226,11 @@ void I2S_Handler                 ( void );
  * \brief Configuration of the Cortex-M0+ Processor and Core Peripherals
  */
 
-#define LITTLE_ENDIAN          1        
+#if defined(LITTLE_ENDIAN) && (LITTLE_ENDIAN != 1)
+  #error "Little Endian is already defined, but to different value than expected?!"
+#else
+  #define LITTLE_ENDIAN          1
+#endif
 #define __CM0PLUS_REV          1         /*!< Core revision r0p1 */
 #define __MPU_PRESENT          0         /*!< MPU present or not */
 #define __NVIC_PRIO_BITS       2         /*!< Number of bits used for Priority Levels */
diff --git a/bootloaders/mzero/Bootloader_D21/src/ASF/sam0/utils/cmsis/samd21/include/samd21j16a.h b/bootloaders/mzero/Bootloader_D21/src/ASF/sam0/utils/cmsis/samd21/include/samd21j16a.h
index 4606c9eba..9696f4766 100644
--- a/bootloaders/mzero/Bootloader_D21/src/ASF/sam0/utils/cmsis/samd21/include/samd21j16a.h
+++ b/bootloaders/mzero/Bootloader_D21/src/ASF/sam0/utils/cmsis/samd21/include/samd21j16a.h
@@ -226,7 +226,11 @@ void I2S_Handler                 ( void );
  * \brief Configuration of the Cortex-M0+ Processor and Core Peripherals
  */
 
-#define LITTLE_ENDIAN          1        
+#if defined(LITTLE_ENDIAN) && (LITTLE_ENDIAN != 1)
+  #error "Little Endian is already defined, but to different value than expected?!"
+#else
+  #define LITTLE_ENDIAN          1
+#endif
 #define __CM0PLUS_REV          1         /*!< Core revision r0p1 */
 #define __MPU_PRESENT          0         /*!< MPU present or not */
 #define __NVIC_PRIO_BITS       2         /*!< Number of bits used for Priority Levels */
diff --git a/bootloaders/mzero/Bootloader_D21/src/ASF/sam0/utils/cmsis/samd21/include/samd21j17a.h b/bootloaders/mzero/Bootloader_D21/src/ASF/sam0/utils/cmsis/samd21/include/samd21j17a.h
index 69393f6fb..50f0daa95 100644
--- a/bootloaders/mzero/Bootloader_D21/src/ASF/sam0/utils/cmsis/samd21/include/samd21j17a.h
+++ b/bootloaders/mzero/Bootloader_D21/src/ASF/sam0/utils/cmsis/samd21/include/samd21j17a.h
@@ -226,7 +226,11 @@ void I2S_Handler                 ( void );
  * \brief Configuration of the Cortex-M0+ Processor and Core Peripherals
  */
 
-#define LITTLE_ENDIAN          1        
+#if defined(LITTLE_ENDIAN) && (LITTLE_ENDIAN != 1)
+  #error "Little Endian is already defined, but to different value than expected?!"
+#else
+  #define LITTLE_ENDIAN          1
+#endif
 #define __CM0PLUS_REV          1         /*!< Core revision r0p1 */
 #define __MPU_PRESENT          0         /*!< MPU present or not */
 #define __NVIC_PRIO_BITS       2         /*!< Number of bits used for Priority Levels */
diff --git a/bootloaders/mzero/Bootloader_D21/src/ASF/sam0/utils/cmsis/samd21/include/samd21j18a.h b/bootloaders/mzero/Bootloader_D21/src/ASF/sam0/utils/cmsis/samd21/include/samd21j18a.h
index 3f621f870..a8a34c543 100644
--- a/bootloaders/mzero/Bootloader_D21/src/ASF/sam0/utils/cmsis/samd21/include/samd21j18a.h
+++ b/bootloaders/mzero/Bootloader_D21/src/ASF/sam0/utils/cmsis/samd21/include/samd21j18a.h
@@ -226,7 +226,11 @@ void I2S_Handler                 ( void );
  * \brief Configuration of the Cortex-M0+ Processor and Core Peripherals
  */
 
-#define LITTLE_ENDIAN          1        
+#if defined(LITTLE_ENDIAN) && (LITTLE_ENDIAN != 1)
+  #error "Little Endian is already defined, but to different value than expected?!"
+#else
+  #define LITTLE_ENDIAN          1
+#endif
 #define __CM0PLUS_REV          1         /*!< Core revision r0p1 */
 #define __MPU_PRESENT          0         /*!< MPU present or not */
 #define __NVIC_PRIO_BITS       2         /*!< Number of bits used for Priority Levels */
diff --git a/bootloaders/neokeytrinkey_m0/bootloader-neokeytrinkey_m0.bin b/bootloaders/neokeytrinkey_m0/bootloader-neokeytrinkey_m0.bin
new file mode 100644
index 000000000..ea8af4d4e
Binary files /dev/null and b/bootloaders/neokeytrinkey_m0/bootloader-neokeytrinkey_m0.bin differ
diff --git a/bootloaders/neotrinkey_m0/bootloader-neotrinkey_m0.bin b/bootloaders/neotrinkey_m0/bootloader-neotrinkey_m0.bin
new file mode 100644
index 000000000..faf74ac7d
Binary files /dev/null and b/bootloaders/neotrinkey_m0/bootloader-neotrinkey_m0.bin differ
diff --git a/bootloaders/pirky/bootloader-pirkey-v2.0.0-adafruit.5.bin b/bootloaders/pirky/bootloader-pirkey-v2.0.0-adafruit.5.bin
new file mode 100755
index 000000000..635b684bf
Binary files /dev/null and b/bootloaders/pirky/bootloader-pirkey-v2.0.0-adafruit.5.bin differ
diff --git a/bootloaders/pirky/bootloader-pirkey-v2.0.0-adafruit.5.elf b/bootloaders/pirky/bootloader-pirkey-v2.0.0-adafruit.5.elf
new file mode 100755
index 000000000..7b52cad5a
Binary files /dev/null and b/bootloaders/pirky/bootloader-pirkey-v2.0.0-adafruit.5.elf differ
diff --git a/bootloaders/pirky/update-bootloader-pirkey-v2.0.0-adafruit.5.uf2 b/bootloaders/pirky/update-bootloader-pirkey-v2.0.0-adafruit.5.uf2
new file mode 100644
index 000000000..19c38eb2e
Binary files /dev/null and b/bootloaders/pirky/update-bootloader-pirkey-v2.0.0-adafruit.5.uf2 differ
diff --git a/bootloaders/proxlighttrinkey_m0/bootloader-proxlighttrinkey_m0.bin b/bootloaders/proxlighttrinkey_m0/bootloader-proxlighttrinkey_m0.bin
new file mode 100644
index 000000000..7b1a0b938
Binary files /dev/null and b/bootloaders/proxlighttrinkey_m0/bootloader-proxlighttrinkey_m0.bin differ
diff --git a/bootloaders/qtpyM0/bootloader-qtpy_m0.bin b/bootloaders/qtpyM0/bootloader-qtpy_m0.bin
new file mode 100644
index 000000000..930069d6c
Binary files /dev/null and b/bootloaders/qtpyM0/bootloader-qtpy_m0.bin differ
diff --git a/bootloaders/rotarytrinkey_m0/bootloader-rotarytrinkey_m0.bin b/bootloaders/rotarytrinkey_m0/bootloader-rotarytrinkey_m0.bin
new file mode 100644
index 000000000..b879d7ef8
Binary files /dev/null and b/bootloaders/rotarytrinkey_m0/bootloader-rotarytrinkey_m0.bin differ
diff --git a/bootloaders/slidetrinkey_m0/bootloader-slidetrinkey_m0.bin b/bootloaders/slidetrinkey_m0/bootloader-slidetrinkey_m0.bin
new file mode 100644
index 000000000..e894a13e3
Binary files /dev/null and b/bootloaders/slidetrinkey_m0/bootloader-slidetrinkey_m0.bin differ
diff --git a/bootloaders/sofia/Bootloader_D21_Sofia_V2.1/.DS_Store b/bootloaders/sofia/Bootloader_D21_Sofia_V2.1/.DS_Store
deleted file mode 100755
index d1231f515..000000000
Binary files a/bootloaders/sofia/Bootloader_D21_Sofia_V2.1/.DS_Store and /dev/null differ
diff --git a/bootloaders/sofia/Bootloader_D21_Sofia_V2.1/src/.DS_Store b/bootloaders/sofia/Bootloader_D21_Sofia_V2.1/src/.DS_Store
deleted file mode 100755
index 5008ddfcf..000000000
Binary files a/bootloaders/sofia/Bootloader_D21_Sofia_V2.1/src/.DS_Store and /dev/null differ
diff --git a/bootloaders/sofia/Bootloader_D21_Sofia_V2.1/src/ASF/sam0/utils/cmsis/samd21/include/samd21e15a.h b/bootloaders/sofia/Bootloader_D21_Sofia_V2.1/src/ASF/sam0/utils/cmsis/samd21/include/samd21e15a.h
index 5eeb32a81..92c3c952f 100755
--- a/bootloaders/sofia/Bootloader_D21_Sofia_V2.1/src/ASF/sam0/utils/cmsis/samd21/include/samd21e15a.h
+++ b/bootloaders/sofia/Bootloader_D21_Sofia_V2.1/src/ASF/sam0/utils/cmsis/samd21/include/samd21e15a.h
@@ -218,7 +218,11 @@ void I2S_Handler                 ( void );
  * \brief Configuration of the Cortex-M0+ Processor and Core Peripherals
  */
 
-#define LITTLE_ENDIAN          1        
+#if defined(LITTLE_ENDIAN) && (LITTLE_ENDIAN != 1)
+  #error "Little Endian is already defined, but to different value than expected?!"
+#else
+  #define LITTLE_ENDIAN          1
+#endif
 #define __CM0PLUS_REV          1         /*!< Core revision r0p1 */
 #define __MPU_PRESENT          0         /*!< MPU present or not */
 #define __NVIC_PRIO_BITS       2         /*!< Number of bits used for Priority Levels */
diff --git a/bootloaders/sofia/Bootloader_D21_Sofia_V2.1/src/ASF/sam0/utils/cmsis/samd21/include/samd21e16a.h b/bootloaders/sofia/Bootloader_D21_Sofia_V2.1/src/ASF/sam0/utils/cmsis/samd21/include/samd21e16a.h
index 1732fe899..7544772c3 100755
--- a/bootloaders/sofia/Bootloader_D21_Sofia_V2.1/src/ASF/sam0/utils/cmsis/samd21/include/samd21e16a.h
+++ b/bootloaders/sofia/Bootloader_D21_Sofia_V2.1/src/ASF/sam0/utils/cmsis/samd21/include/samd21e16a.h
@@ -218,7 +218,11 @@ void I2S_Handler                 ( void );
  * \brief Configuration of the Cortex-M0+ Processor and Core Peripherals
  */
 
-#define LITTLE_ENDIAN          1        
+#if defined(LITTLE_ENDIAN) && (LITTLE_ENDIAN != 1)
+  #error "Little Endian is already defined, but to different value than expected?!"
+#else
+  #define LITTLE_ENDIAN          1
+#endif
 #define __CM0PLUS_REV          1         /*!< Core revision r0p1 */
 #define __MPU_PRESENT          0         /*!< MPU present or not */
 #define __NVIC_PRIO_BITS       2         /*!< Number of bits used for Priority Levels */
diff --git a/bootloaders/sofia/Bootloader_D21_Sofia_V2.1/src/ASF/sam0/utils/cmsis/samd21/include/samd21e17a.h b/bootloaders/sofia/Bootloader_D21_Sofia_V2.1/src/ASF/sam0/utils/cmsis/samd21/include/samd21e17a.h
index bad36c60f..985a53228 100755
--- a/bootloaders/sofia/Bootloader_D21_Sofia_V2.1/src/ASF/sam0/utils/cmsis/samd21/include/samd21e17a.h
+++ b/bootloaders/sofia/Bootloader_D21_Sofia_V2.1/src/ASF/sam0/utils/cmsis/samd21/include/samd21e17a.h
@@ -218,7 +218,11 @@ void I2S_Handler                 ( void );
  * \brief Configuration of the Cortex-M0+ Processor and Core Peripherals
  */
 
-#define LITTLE_ENDIAN          1        
+#if defined(LITTLE_ENDIAN) && (LITTLE_ENDIAN != 1)
+  #error "Little Endian is already defined, but to different value than expected?!"
+#else
+  #define LITTLE_ENDIAN          1
+#endif
 #define __CM0PLUS_REV          1         /*!< Core revision r0p1 */
 #define __MPU_PRESENT          0         /*!< MPU present or not */
 #define __NVIC_PRIO_BITS       2         /*!< Number of bits used for Priority Levels */
diff --git a/bootloaders/sofia/Bootloader_D21_Sofia_V2.1/src/ASF/sam0/utils/cmsis/samd21/include/samd21e18a.h b/bootloaders/sofia/Bootloader_D21_Sofia_V2.1/src/ASF/sam0/utils/cmsis/samd21/include/samd21e18a.h
index 839706689..1d668f82d 100755
--- a/bootloaders/sofia/Bootloader_D21_Sofia_V2.1/src/ASF/sam0/utils/cmsis/samd21/include/samd21e18a.h
+++ b/bootloaders/sofia/Bootloader_D21_Sofia_V2.1/src/ASF/sam0/utils/cmsis/samd21/include/samd21e18a.h
@@ -218,7 +218,11 @@ void I2S_Handler                 ( void );
  * \brief Configuration of the Cortex-M0+ Processor and Core Peripherals
  */
 
-#define LITTLE_ENDIAN          1        
+#if defined(LITTLE_ENDIAN) && (LITTLE_ENDIAN != 1)
+  #error "Little Endian is already defined, but to different value than expected?!"
+#else
+  #define LITTLE_ENDIAN          1
+#endif
 #define __CM0PLUS_REV          1         /*!< Core revision r0p1 */
 #define __MPU_PRESENT          0         /*!< MPU present or not */
 #define __NVIC_PRIO_BITS       2         /*!< Number of bits used for Priority Levels */
diff --git a/bootloaders/sofia/Bootloader_D21_Sofia_V2.1/src/ASF/sam0/utils/cmsis/samd21/include/samd21g15a.h b/bootloaders/sofia/Bootloader_D21_Sofia_V2.1/src/ASF/sam0/utils/cmsis/samd21/include/samd21g15a.h
index fbc1116eb..37eef1c48 100755
--- a/bootloaders/sofia/Bootloader_D21_Sofia_V2.1/src/ASF/sam0/utils/cmsis/samd21/include/samd21g15a.h
+++ b/bootloaders/sofia/Bootloader_D21_Sofia_V2.1/src/ASF/sam0/utils/cmsis/samd21/include/samd21g15a.h
@@ -222,7 +222,11 @@ void I2S_Handler                 ( void );
  * \brief Configuration of the Cortex-M0+ Processor and Core Peripherals
  */
 
-#define LITTLE_ENDIAN          1        
+#if defined(LITTLE_ENDIAN) && (LITTLE_ENDIAN != 1)
+  #error "Little Endian is already defined, but to different value than expected?!"
+#else
+  #define LITTLE_ENDIAN          1
+#endif
 #define __CM0PLUS_REV          1         /*!< Core revision r0p1 */
 #define __MPU_PRESENT          0         /*!< MPU present or not */
 #define __NVIC_PRIO_BITS       2         /*!< Number of bits used for Priority Levels */
diff --git a/bootloaders/sofia/Bootloader_D21_Sofia_V2.1/src/ASF/sam0/utils/cmsis/samd21/include/samd21g16a.h b/bootloaders/sofia/Bootloader_D21_Sofia_V2.1/src/ASF/sam0/utils/cmsis/samd21/include/samd21g16a.h
index d8aa2460f..74240e3ca 100755
--- a/bootloaders/sofia/Bootloader_D21_Sofia_V2.1/src/ASF/sam0/utils/cmsis/samd21/include/samd21g16a.h
+++ b/bootloaders/sofia/Bootloader_D21_Sofia_V2.1/src/ASF/sam0/utils/cmsis/samd21/include/samd21g16a.h
@@ -222,7 +222,11 @@ void I2S_Handler                 ( void );
  * \brief Configuration of the Cortex-M0+ Processor and Core Peripherals
  */
 
-#define LITTLE_ENDIAN          1        
+#if defined(LITTLE_ENDIAN) && (LITTLE_ENDIAN != 1)
+  #error "Little Endian is already defined, but to different value than expected?!"
+#else
+  #define LITTLE_ENDIAN          1
+#endif
 #define __CM0PLUS_REV          1         /*!< Core revision r0p1 */
 #define __MPU_PRESENT          0         /*!< MPU present or not */
 #define __NVIC_PRIO_BITS       2         /*!< Number of bits used for Priority Levels */
diff --git a/bootloaders/sofia/Bootloader_D21_Sofia_V2.1/src/ASF/sam0/utils/cmsis/samd21/include/samd21g17a.h b/bootloaders/sofia/Bootloader_D21_Sofia_V2.1/src/ASF/sam0/utils/cmsis/samd21/include/samd21g17a.h
index 0cad9c7fe..44cd3d6ff 100755
--- a/bootloaders/sofia/Bootloader_D21_Sofia_V2.1/src/ASF/sam0/utils/cmsis/samd21/include/samd21g17a.h
+++ b/bootloaders/sofia/Bootloader_D21_Sofia_V2.1/src/ASF/sam0/utils/cmsis/samd21/include/samd21g17a.h
@@ -222,7 +222,11 @@ void I2S_Handler                 ( void );
  * \brief Configuration of the Cortex-M0+ Processor and Core Peripherals
  */
 
-#define LITTLE_ENDIAN          1        
+#if defined(LITTLE_ENDIAN) && (LITTLE_ENDIAN != 1)
+  #error "Little Endian is already defined, but to different value than expected?!"
+#else
+  #define LITTLE_ENDIAN          1
+#endif
 #define __CM0PLUS_REV          1         /*!< Core revision r0p1 */
 #define __MPU_PRESENT          0         /*!< MPU present or not */
 #define __NVIC_PRIO_BITS       2         /*!< Number of bits used for Priority Levels */
diff --git a/bootloaders/sofia/Bootloader_D21_Sofia_V2.1/src/ASF/sam0/utils/cmsis/samd21/include/samd21g18a.h b/bootloaders/sofia/Bootloader_D21_Sofia_V2.1/src/ASF/sam0/utils/cmsis/samd21/include/samd21g18a.h
index 76273e118..b7b0d2b59 100755
--- a/bootloaders/sofia/Bootloader_D21_Sofia_V2.1/src/ASF/sam0/utils/cmsis/samd21/include/samd21g18a.h
+++ b/bootloaders/sofia/Bootloader_D21_Sofia_V2.1/src/ASF/sam0/utils/cmsis/samd21/include/samd21g18a.h
@@ -222,7 +222,11 @@ void I2S_Handler                 ( void );
  * \brief Configuration of the Cortex-M0+ Processor and Core Peripherals
  */
 
-#define LITTLE_ENDIAN          1        
+#if defined(LITTLE_ENDIAN) && (LITTLE_ENDIAN != 1)
+  #error "Little Endian is already defined, but to different value than expected?!"
+#else
+  #define LITTLE_ENDIAN          1
+#endif
 #define __CM0PLUS_REV          1         /*!< Core revision r0p1 */
 #define __MPU_PRESENT          0         /*!< MPU present or not */
 #define __NVIC_PRIO_BITS       2         /*!< Number of bits used for Priority Levels */
diff --git a/bootloaders/sofia/Bootloader_D21_Sofia_V2.1/src/ASF/sam0/utils/cmsis/samd21/include/samd21j15a.h b/bootloaders/sofia/Bootloader_D21_Sofia_V2.1/src/ASF/sam0/utils/cmsis/samd21/include/samd21j15a.h
index a3f771ecc..ea4c601eb 100755
--- a/bootloaders/sofia/Bootloader_D21_Sofia_V2.1/src/ASF/sam0/utils/cmsis/samd21/include/samd21j15a.h
+++ b/bootloaders/sofia/Bootloader_D21_Sofia_V2.1/src/ASF/sam0/utils/cmsis/samd21/include/samd21j15a.h
@@ -226,7 +226,11 @@ void I2S_Handler                 ( void );
  * \brief Configuration of the Cortex-M0+ Processor and Core Peripherals
  */
 
-#define LITTLE_ENDIAN          1        
+#if defined(LITTLE_ENDIAN) && (LITTLE_ENDIAN != 1)
+  #error "Little Endian is already defined, but to different value than expected?!"
+#else
+  #define LITTLE_ENDIAN          1
+#endif
 #define __CM0PLUS_REV          1         /*!< Core revision r0p1 */
 #define __MPU_PRESENT          0         /*!< MPU present or not */
 #define __NVIC_PRIO_BITS       2         /*!< Number of bits used for Priority Levels */
diff --git a/bootloaders/sofia/Bootloader_D21_Sofia_V2.1/src/ASF/sam0/utils/cmsis/samd21/include/samd21j16a.h b/bootloaders/sofia/Bootloader_D21_Sofia_V2.1/src/ASF/sam0/utils/cmsis/samd21/include/samd21j16a.h
index eaa2ec1d2..c510e92c4 100755
--- a/bootloaders/sofia/Bootloader_D21_Sofia_V2.1/src/ASF/sam0/utils/cmsis/samd21/include/samd21j16a.h
+++ b/bootloaders/sofia/Bootloader_D21_Sofia_V2.1/src/ASF/sam0/utils/cmsis/samd21/include/samd21j16a.h
@@ -226,7 +226,11 @@ void I2S_Handler                 ( void );
  * \brief Configuration of the Cortex-M0+ Processor and Core Peripherals
  */
 
-#define LITTLE_ENDIAN          1        
+#if defined(LITTLE_ENDIAN) && (LITTLE_ENDIAN != 1)
+  #error "Little Endian is already defined, but to different value than expected?!"
+#else
+  #define LITTLE_ENDIAN          1
+#endif
 #define __CM0PLUS_REV          1         /*!< Core revision r0p1 */
 #define __MPU_PRESENT          0         /*!< MPU present or not */
 #define __NVIC_PRIO_BITS       2         /*!< Number of bits used for Priority Levels */
diff --git a/bootloaders/sofia/Bootloader_D21_Sofia_V2.1/src/ASF/sam0/utils/cmsis/samd21/include/samd21j17a.h b/bootloaders/sofia/Bootloader_D21_Sofia_V2.1/src/ASF/sam0/utils/cmsis/samd21/include/samd21j17a.h
index 5e956b9ae..8e07a4caf 100755
--- a/bootloaders/sofia/Bootloader_D21_Sofia_V2.1/src/ASF/sam0/utils/cmsis/samd21/include/samd21j17a.h
+++ b/bootloaders/sofia/Bootloader_D21_Sofia_V2.1/src/ASF/sam0/utils/cmsis/samd21/include/samd21j17a.h
@@ -226,7 +226,11 @@ void I2S_Handler                 ( void );
  * \brief Configuration of the Cortex-M0+ Processor and Core Peripherals
  */
 
-#define LITTLE_ENDIAN          1        
+#if defined(LITTLE_ENDIAN) && (LITTLE_ENDIAN != 1)
+  #error "Little Endian is already defined, but to different value than expected?!"
+#else
+  #define LITTLE_ENDIAN          1
+#endif
 #define __CM0PLUS_REV          1         /*!< Core revision r0p1 */
 #define __MPU_PRESENT          0         /*!< MPU present or not */
 #define __NVIC_PRIO_BITS       2         /*!< Number of bits used for Priority Levels */
diff --git a/bootloaders/sofia/Bootloader_D21_Sofia_V2.1/src/ASF/sam0/utils/cmsis/samd21/include/samd21j18a.h b/bootloaders/sofia/Bootloader_D21_Sofia_V2.1/src/ASF/sam0/utils/cmsis/samd21/include/samd21j18a.h
index 1a1d7e8bd..b32987a06 100755
--- a/bootloaders/sofia/Bootloader_D21_Sofia_V2.1/src/ASF/sam0/utils/cmsis/samd21/include/samd21j18a.h
+++ b/bootloaders/sofia/Bootloader_D21_Sofia_V2.1/src/ASF/sam0/utils/cmsis/samd21/include/samd21j18a.h
@@ -226,7 +226,11 @@ void I2S_Handler                 ( void );
  * \brief Configuration of the Cortex-M0+ Processor and Core Peripherals
  */
 
-#define LITTLE_ENDIAN          1        
+#if defined(LITTLE_ENDIAN) && (LITTLE_ENDIAN != 1)
+  #error "Little Endian is already defined, but to different value than expected?!"
+#else
+  #define LITTLE_ENDIAN          1
+#endif
 #define __CM0PLUS_REV          1         /*!< Core revision r0p1 */
 #define __MPU_PRESENT          0         /*!< MPU present or not */
 #define __NVIC_PRIO_BITS       2         /*!< Number of bits used for Priority Levels */
diff --git a/bootloaders/trinketm0/bootloader-trinket_m0-v2.0.0-adafruit.5.bin b/bootloaders/trinketm0/bootloader-trinket_m0-v2.0.0-adafruit.5.bin
new file mode 100755
index 000000000..418928a21
Binary files /dev/null and b/bootloaders/trinketm0/bootloader-trinket_m0-v2.0.0-adafruit.5.bin differ
diff --git a/bootloaders/trinketm0/bootloader-trinket_m0-v2.0.0-adafruit.5.elf b/bootloaders/trinketm0/bootloader-trinket_m0-v2.0.0-adafruit.5.elf
new file mode 100755
index 000000000..9e81cae0d
Binary files /dev/null and b/bootloaders/trinketm0/bootloader-trinket_m0-v2.0.0-adafruit.5.elf differ
diff --git a/bootloaders/trinketm0/update-bootloader-trinket_m0-v2.0.0-adafruit.5.uf2 b/bootloaders/trinketm0/update-bootloader-trinket_m0-v2.0.0-adafruit.5.uf2
new file mode 100644
index 000000000..0c1e589d8
Binary files /dev/null and b/bootloaders/trinketm0/update-bootloader-trinket_m0-v2.0.0-adafruit.5.uf2 differ
diff --git a/bootloaders/zero/Makefile b/bootloaders/zero/Makefile
index 1e5fad5e5..eee929188 100644
--- a/bootloaders/zero/Makefile
+++ b/bootloaders/zero/Makefile
@@ -18,34 +18,44 @@
 # -----------------------------------------------------------------------------
 # Paths
 ifeq ($(OS),Windows_NT)
+
   # Are we using mingw/msys/msys2/cygwin?
   ifeq ($(TERM),xterm)
-    T=$(shell cygpath -u $(LOCALAPPDATA))
+# this is the path coming with night build
+#		T=$(shell cygpath -u $(LOCALAPPDATA))
+# this is the path till 1.6.5 r5
+		T=$(shell cygpath -u $(APPDATA))
     MODULE_PATH?=$(T)/Arduino15/packages/arduino
+    ARM_GCC_PATH?=$(MODULE_PATH)/tools/arm-none-eabi-gcc/4.8.3-2014q1/bin/arm-none-eabi-
     RM=rm
     SEP=/
   else
-    MODULE_PATH?=$(LOCALAPPDATA)/Arduino15/packages/arduino
+# this is the path coming with night build
+#    MODULE_PATH?=$(LOCALAPPDATA)/Arduino15/packages/arduino
+# this is the path till 1.6.5 r5
+    MODULE_PATH?=$(APPDATA)/Arduino15/packages/arduino
+    ARM_GCC_PATH?=$(MODULE_PATH)/tools/arm-none-eabi-gcc/4.8.3-2014q1/bin/arm-none-eabi-
     RM=rm
     SEP=\\
   endif
 else
-  UNAME_S := $(shell uname -s)
-
-  ifeq ($(UNAME_S),Linux)
-    MODULE_PATH?=$(HOME)/.arduino15/packages/arduino
-    RM=rm
-    SEP=/
-  endif
-
-  ifeq ($(UNAME_S),Darwin)
-    MODULE_PATH?=$(HOME)/Library/Arduino15/packages/arduino/
-    RM=rm
-    SEP=/
-  endif
+    UNAME_S := $(shell uname -s)
+
+    ifeq ($(UNAME_S),Linux)
+			MODULE_PATH?=$(HOME)/.arduino15/packages/arduino
+			ARM_GCC_PATH?=$(MODULE_PATH)/tools/arm-none-eabi-gcc/4.8.3-2014q1/bin/arm-none-eabi-
+      RM=rm
+	    SEP=/
+    endif
+
+    ifeq ($(UNAME_S),Darwin)
+			MODULE_PATH?=$(HOME)/Library/Arduino15/packages/arduino/
+			ARM_GCC_PATH?=$(MODULE_PATH)/tools/arm-none-eabi-gcc/4.8.3-2014q1/bin/arm-none-eabi-
+      RM=rm
+	    SEP=/
+    endif
 endif
 
-ARM_GCC_PATH?=$(MODULE_PATH)/tools/arm-none-eabi-gcc/4.8.3-2014q1/bin/arm-none-eabi-
 BUILD_PATH=build
 
 # -----------------------------------------------------------------------------
@@ -55,27 +65,21 @@ OBJCOPY=$(ARM_GCC_PATH)objcopy
 NM=$(ARM_GCC_PATH)nm
 SIZE=$(ARM_GCC_PATH)size
 
-# -----------------------------------------------------------------------------
-# Boards definitions
-BOARD_ID?=arduino_zero
-NAME?=samd21_sam_ba
-
 # -----------------------------------------------------------------------------
 # Compiler options
-CFLAGS_EXTRA=-D__SAMD21G18A__ -DBOARD_ID_$(BOARD_ID)
 CFLAGS=-mthumb -mcpu=cortex-m0plus -Wall -c -std=gnu99 -ffunction-sections -fdata-sections -nostdlib -nostartfiles --param max-inline-insns-single=500
 ifdef DEBUG
-  CFLAGS+=-g3 -O1 -DDEBUG=1
+CFLAGS+=-g3 -O1 -DDEBUG=1
 else
-  CFLAGS+=-Os -DDEBUG=0
+CFLAGS+=-Os -DDEBUG=0
 endif
 
-ELF=$(NAME).elf
-BIN=$(NAME).bin
-HEX=$(NAME).hex
-
+# Arduino Zero (PID == 0x004D)
+CFLAGS_EXTRA?=-D__SAMD21G18A__ -DUSB_PID_HIGH=0x00 -DUSB_PID_LOW=0x4D
+# Genuino Zero (PID == 0x024D)
+# CFLAGS_EXTRA?=-D__SAMD21G18A__ -DUSB_PID_HIGH=0x02 -DUSB_PID_LOW=0x4D
 
-INCLUDES=-I"$(MODULE_PATH)/tools/CMSIS/4.5.0/CMSIS/Include/" -I"$(MODULE_PATH)/tools/CMSIS-Atmel/1.1.0/CMSIS/Device/ATMEL/"
+INCLUDES=-I"$(MODULE_PATH)/tools/CMSIS/4.0.0-atmel/CMSIS/Include/" -I"$(MODULE_PATH)/tools/CMSIS/4.0.0-atmel/Device/ATMEL/"
 
 # -----------------------------------------------------------------------------
 # Linker options
@@ -85,38 +89,40 @@ LDFLAGS+=-Wl,--warn-common -Wl,--warn-section-align -Wl,--warn-unresolved-symbol
 # -----------------------------------------------------------------------------
 # Source files and objects
 SOURCES= \
-  board_driver_i2c.c \
-  board_driver_led.c \
-  board_driver_pmic.c \
-  board_driver_serial.c \
-  board_driver_usb.c \
-  board_init.c \
-  board_startup.c \
-  main.c \
-  sam_ba_usb.c \
-  sam_ba_cdc.c \
-  sam_ba_monitor.c \
-  sam_ba_serial.c
+board_driver_led.c \
+board_driver_serial.c \
+board_driver_usb.c \
+board_init.c \
+board_startup.c \
+main.c \
+sam_ba_usb.c \
+sam_ba_cdc.c \
+sam_ba_monitor.c \
+sam_ba_serial.c
 
 OBJECTS=$(addprefix $(BUILD_PATH)/, $(SOURCES:.c=.o))
 DEPS=$(addprefix $(BUILD_PATH)/, $(SOURCES:.c=.d))
 
+NAME=samd21_sam_ba
+ELF=$(NAME).elf
+BIN=$(NAME).bin
+HEX=$(NAME).hex
+
 ifneq "test$(AVRSTUDIO_EXE_PATH)" "test"
-  AS_BUILD=copy_for_atmel_studio
-  AS_CLEAN=clean_for_atmel_studio
+AS_BUILD=copy_for_atmel_studio
+AS_CLEAN=clean_for_atmel_studio
 else
-  AS_BUILD=
-  AS_CLEAN=
+AS_BUILD=
+AS_CLEAN=
 endif
 
-LD_SCRIPT=bootloader_samd21x18.ld
 
 all: print_info $(SOURCES) $(BIN) $(HEX) $(AS_BUILD)
 
 $(ELF): Makefile $(BUILD_PATH) $(OBJECTS)
 	@echo ----------------------------------------------------------
 	@echo Creating ELF binary
-	"$(CC)" -L. -L$(BUILD_PATH) $(LDFLAGS) -Os -Wl,--gc-sections -save-temps -T$(LD_SCRIPT) -Wl,-Map,"$(BUILD_PATH)/$(NAME).map" -o "$(BUILD_PATH)/$(ELF)" -Wl,--start-group $(OBJECTS) -lm -Wl,--end-group
+	"$(CC)" -L. -L$(BUILD_PATH) $(LDFLAGS) -Os -Wl,--gc-sections -save-temps -Tbootloader_samd21x18.ld -Wl,-Map,"$(BUILD_PATH)/$(NAME).map" -o "$(BUILD_PATH)/$(ELF)" -Wl,--start-group $(OBJECTS) -lm -Wl,--end-group
 	"$(NM)" "$(BUILD_PATH)/$(ELF)" >"$(BUILD_PATH)/$(NAME)_symbols.txt"
 	"$(SIZE)" --format=sysv -t -x $(BUILD_PATH)/$(ELF)
 
diff --git a/bootloaders/zero/README.md b/bootloaders/zero/README.md
index b0d939db9..44f4e4e02 100644
--- a/bootloaders/zero/README.md
+++ b/bootloaders/zero/README.md
@@ -9,10 +9,6 @@ Multi-plaform GCC is provided by ARM here: https://launchpad.net/gcc-arm-embedde
 
 Atmel Studio contains both make and ARM GCC toolchain. You don't need to install them in this specific use case.
 
-For all builds and platforms you will need to have the Arduino IDE installed and the board support
-package for "Arduino SAMD Boards (32-bits ARM Cortex-M0+)". You can install the latter
-from the former's "Boards Manager" UI.
-
 ### Windows
 
 * Native command line
@@ -77,19 +73,3 @@ Bootloader code will be located at 0x0 and executed before any applicative code.
 Applications compiled to be executed along with the bootloader will start at 0x2000 (see linker script bootloader_samd21x18.ld).
 
 Before jumping to the application, the bootloader changes the VTOR register to use the interrupt vectors of the application @0x2000.<- not required as application code is taking care of this.
-
-## 5- How to build
-
-If not specified the makefile builds for **Arduino Zero**:
-
-```
-make
-```
-
-if you want to make a custom bootloader for a derivative board you must supply all the necessary information in a `board_definitions_xxx.h` file, and add the corresponding case in `board_definitions.h`.
-For example for the **Arduino MKR1000** we use `board_definitions_arduino_mkr1000.h` and it is build with the following command:
-
-```
-BOARD_ID=arduino_mkr1000 NAME=samd21_sam_ba_arduino_mkr1000 make clean all
-```
-
diff --git a/bootloaders/zero/board_definitions.h b/bootloaders/zero/board_definitions.h
index 9d6721105..8129e401b 100644
--- a/bootloaders/zero/board_definitions.h
+++ b/bootloaders/zero/board_definitions.h
@@ -17,6 +17,9 @@
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */
 
+#ifndef _BOARD_DEFINITIONS_H_
+#define _BOARD_DEFINITIONS_H_
+
 #if defined(BOARD_ID_arduino_zero)
   #include "board_definitions_arduino_zero.h"
 #elif defined(BOARD_ID_genuino_zero)
@@ -46,3 +49,53 @@
 
 #define BOOT_PIN_MASK (1U << (BOOT_LOAD_PIN & 0x1f))
 
+/*
+ * If BOOT_DOUBLE_TAP_ADDRESS is defined the bootloader is started by
+ * quickly tapping two times on the reset button.
+ * BOOT_DOUBLE_TAP_ADDRESS must point to a free SRAM cell that must not
+ * be touched from the loaded application.
+ */
+#define BOOT_DOUBLE_TAP_ADDRESS           (0x20007FFCul)
+#define BOOT_DOUBLE_TAP_DATA              (*((volatile uint32_t *) BOOT_DOUBLE_TAP_ADDRESS))
+
+/*
+ * If BOOT_LOAD_PIN is defined the bootloader is started if the selected
+ * pin is tied LOW.
+ */
+//#define BOOT_LOAD_PIN                     PIN_PA21 // Pin 7
+//#define BOOT_LOAD_PIN                     PIN_PA15 // Pin 5
+#define BOOT_PIN_MASK                     (1U << (BOOT_LOAD_PIN & 0x1f))
+
+#define CPU_FREQUENCY                     (48000000ul)
+
+#define BOOT_USART_MODULE                 SERCOM0
+#define BOOT_USART_BUS_CLOCK_INDEX        PM_APBCMASK_SERCOM0
+#define BOOT_USART_PER_CLOCK_INDEX        GCLK_ID_SERCOM0_CORE
+#define BOOT_USART_PAD_SETTINGS           UART_RX_PAD3_TX_PAD2
+#define BOOT_USART_PAD3                   PINMUX_PA11C_SERCOM0_PAD3
+#define BOOT_USART_PAD2                   PINMUX_PA10C_SERCOM0_PAD2
+#define BOOT_USART_PAD1                   PINMUX_UNUSED
+#define BOOT_USART_PAD0                   PINMUX_UNUSED
+
+/* Frequency of the board main oscillator */
+#define VARIANT_MAINOSC	                  (32768ul)
+
+/* Master clock frequency */
+#define VARIANT_MCK			                  CPU_FREQUENCY
+
+#define NVM_SW_CALIB_DFLL48M_COARSE_VAL   (58)
+#define NVM_SW_CALIB_DFLL48M_FINE_VAL     (64)
+
+/*
+ * LEDs definitions
+ */
+#define BOARD_LED_PORT                    (0)
+#define BOARD_LED_PIN                     (17)
+
+#define BOARD_LEDRX_PORT                  (1)
+#define BOARD_LEDRX_PIN                   (3)
+
+#define BOARD_LEDTX_PORT                  (0)
+#define BOARD_LEDTX_PIN                   (27)
+
+#endif // _BOARD_DEFINITIONS_H_
diff --git a/bootloaders/zero/board_driver_led.c b/bootloaders/zero/board_driver_led.c
index ffa6c4782..1a2430aff 100644
--- a/bootloaders/zero/board_driver_led.c
+++ b/bootloaders/zero/board_driver_led.c
@@ -19,24 +19,4 @@
 
 #include "board_driver_led.h"
 
-volatile uint8_t ledKeepValue = 0;
-volatile uint8_t ledTargetValue = 20;
-volatile int8_t ledDirection = 1;
 
-inline void LED_pulse()
-{
-  if (ledKeepValue == 0) {
-    ledTargetValue += ledDirection;
-    LED_toggle();
-  }
-  ledKeepValue ++;
-
-  if (ledTargetValue > 240 || ledTargetValue < 10) {
-    ledDirection = -ledDirection;
-    ledTargetValue += ledDirection;
-  }
-
-  if (ledKeepValue == ledTargetValue) {
-    LED_toggle();
-  }
-}
diff --git a/bootloaders/zero/board_driver_led.h b/bootloaders/zero/board_driver_led.h
index d7d47cad8..6f1fd7580 100644
--- a/bootloaders/zero/board_driver_led.h
+++ b/bootloaders/zero/board_driver_led.h
@@ -23,41 +23,19 @@
 #include <sam.h>
 #include "board_definitions.h"
 
-#if defined(BOARD_LED_PORT)
 inline void LED_init(void) { PORT->Group[BOARD_LED_PORT].DIRSET.reg = (1<<BOARD_LED_PIN); }
 inline void LED_on(void) { PORT->Group[BOARD_LED_PORT].OUTSET.reg = (1<<BOARD_LED_PIN); }
 inline void LED_off(void) { PORT->Group[BOARD_LED_PORT].OUTCLR.reg = (1<<BOARD_LED_PIN); }
 inline void LED_toggle(void) { PORT->Group[BOARD_LED_PORT].OUTTGL.reg = (1<<BOARD_LED_PIN); }
-#else
-inline void LED_init(void) { }
-inline void LED_on(void) { }
-inline void LED_off(void) { }
-inline void LED_toggle(void) { }
-#endif
-void LED_pulse();
-
-#if defined(BOARD_LEDRX_PORT)
+
 inline void LEDRX_init(void) { PORT->Group[BOARD_LEDRX_PORT].DIRSET.reg = (1<<BOARD_LEDRX_PIN); }
-inline void LEDRX_on(void) { PORT->Group[BOARD_LEDRX_PORT].OUTCLR.reg = (1<<BOARD_LEDRX_PIN); }
-inline void LEDRX_off(void) { PORT->Group[BOARD_LEDRX_PORT].OUTSET.reg = (1<<BOARD_LEDRX_PIN); }
+inline void LEDRX_on(void) { PORT->Group[BOARD_LEDRX_PORT].OUTSET.reg = (1<<BOARD_LEDRX_PIN); }
+inline void LEDRX_off(void) { PORT->Group[BOARD_LEDRX_PORT].OUTCLR.reg = (1<<BOARD_LEDRX_PIN); }
 inline void LEDRX_toggle(void) { PORT->Group[BOARD_LEDRX_PORT].OUTTGL.reg = (1<<BOARD_LEDRX_PIN); }
-#else
-inline void LEDRX_init(void) { }
-inline void LEDRX_on(void) { }
-inline void LEDRX_off(void) { }
-inline void LEDRX_toggle(void) { }
-#endif
-
-#if defined(BOARD_LEDTX_PORT)
+
 inline void LEDTX_init(void) { PORT->Group[BOARD_LEDTX_PORT].DIRSET.reg = (1<<BOARD_LEDTX_PIN); }
-inline void LEDTX_on(void) { PORT->Group[BOARD_LEDTX_PORT].OUTCLR.reg = (1<<BOARD_LEDTX_PIN); }
-inline void LEDTX_off(void) { PORT->Group[BOARD_LEDTX_PORT].OUTSET.reg = (1<<BOARD_LEDTX_PIN); }
+inline void LEDTX_on(void) { PORT->Group[BOARD_LEDTX_PORT].OUTSET.reg = (1<<BOARD_LEDTX_PIN); }
+inline void LEDTX_off(void) { PORT->Group[BOARD_LEDTX_PORT].OUTCLR.reg = (1<<BOARD_LEDTX_PIN); }
 inline void LEDTX_toggle(void) { PORT->Group[BOARD_LEDTX_PORT].OUTTGL.reg = (1<<BOARD_LEDTX_PIN); }
-#else
-inline void LEDTX_init(void) { }
-inline void LEDTX_on(void) { }
-inline void LEDTX_off(void) { }
-inline void LEDTX_toggle(void) { }
-#endif
 
 #endif // _BOARD_DRIVER_LED_
diff --git a/bootloaders/zero/board_driver_serial.h b/bootloaders/zero/board_driver_serial.h
index 809f7ec01..c752d977d 100644
--- a/bootloaders/zero/board_driver_serial.h
+++ b/bootloaders/zero/board_driver_serial.h
@@ -25,6 +25,7 @@
 #include <sam.h>
 
 #define PINMUX_UNUSED          0xFFFFFFFF
+#define GCLK_ID_SERCOM0_CORE   0x14
 
 /* SERCOM UART available pad settings */
 enum uart_pad_settings {
diff --git a/bootloaders/zero/board_driver_usb.c b/bootloaders/zero/board_driver_usb.c
index f1c83f44f..6534fa338 100644
--- a/bootloaders/zero/board_driver_usb.c
+++ b/bootloaders/zero/board_driver_usb.c
@@ -172,12 +172,13 @@ uint32_t USB_Write(Usb *pUsb, const char *pData, uint32_t length, uint8_t ep_num
   /* Set the multi packet size as zero for multi-packet transfers where length > ep size */
   usb_endpoint_table[ep_num].DeviceDescBank[1].PCKSIZE.bit.MULTI_PACKET_SIZE = 0;
   /* Clear the transfer complete flag  */
-  pUsb->DEVICE.DeviceEndpoint[ep_num].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_TRCPT1;
+  //pUsb->DEVICE.DeviceEndpoint[ep_num].EPINTFLAG.bit.TRCPT1 = true;
+  pUsb->DEVICE.DeviceEndpoint[ep_num].EPINTFLAG.bit.TRCPT |= (1<<1);
   /* Set the bank as ready */
   pUsb->DEVICE.DeviceEndpoint[ep_num].EPSTATUSSET.bit.BK1RDY = true;
 
   /* Wait for transfer to complete */
-  while ( (pUsb->DEVICE.DeviceEndpoint[ep_num].EPINTFLAG.bit.TRCPT1) == 0 );
+  while ( (pUsb->DEVICE.DeviceEndpoint[ep_num].EPINTFLAG.bit.TRCPT & (1<<1)) == 0 );
 
   return length;
 }
@@ -204,14 +205,15 @@ uint32_t USB_Read(Usb *pUsb, char *pData, uint32_t length)
   }
 
   /* Check for Transfer Complete 0 flag */
-  if ( pUsb->DEVICE.DeviceEndpoint[USB_EP_OUT].EPINTFLAG.bit.TRCPT0 )
+  if ( pUsb->DEVICE.DeviceEndpoint[USB_EP_OUT].EPINTFLAG.bit.TRCPT & (1<<0) )
   {
     /* Set packet size */
     packetSize = SAM_BA_MIN(usb_endpoint_table[USB_EP_OUT].DeviceDescBank[0].PCKSIZE.bit.BYTE_COUNT, length);
     /* Copy read data to user buffer */
     memcpy(pData, udd_ep_out_cache_buffer[USB_EP_OUT-1], packetSize);
     /* Clear the Transfer Complete 0 flag */
-    pUsb->DEVICE.DeviceEndpoint[USB_EP_OUT].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_TRCPT0;
+    //pUsb->DEVICE.DeviceEndpoint[USB_EP_OUT].EPINTFLAG.bit.TRCPT0 = true;
+    pUsb->DEVICE.DeviceEndpoint[USB_EP_OUT].EPINTFLAG.bit.TRCPT |= (1 << 0);
     /* Clear the user flag */
     read_job = false;
   }
@@ -238,9 +240,10 @@ uint32_t USB_Read_blocking(Usb *pUsb, char *pData, uint32_t length)
   /* Clear the bank 0 ready flag */
   pUsb->DEVICE.DeviceEndpoint[USB_EP_OUT].EPSTATUSCLR.bit.BK0RDY = true;
   /* Wait for transfer to complete */
-  while (!( pUsb->DEVICE.DeviceEndpoint[USB_EP_OUT].EPINTFLAG.bit.TRCPT0 ));
+  while (!( pUsb->DEVICE.DeviceEndpoint[USB_EP_OUT].EPINTFLAG.bit.TRCPT & (1<<0) ));
   /* Clear Transfer complete 0 flag */
-  pUsb->DEVICE.DeviceEndpoint[USB_EP_OUT].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_TRCPT0;
+  //pUsb->DEVICE.DeviceEndpoint[USB_EP_OUT].EPINTFLAG.bit.TRCPT0 = true;
+  pUsb->DEVICE.DeviceEndpoint[USB_EP_OUT].EPINTFLAG.bit.TRCPT |= (1 << 0);
 
   return length;
 }
@@ -256,7 +259,7 @@ uint8_t USB_IsConfigured(P_USB_CDC pCdc)
   if (pUsb->DEVICE.INTFLAG.reg & USB_DEVICE_INTFLAG_EORST)
   {
     /* Clear the flag */
-    pUsb->DEVICE.INTFLAG.reg = USB_DEVICE_INTFLAG_EORST;
+    pUsb->DEVICE.INTFLAG.bit.EORST = true;
     /* Set Device address as 0 */
     pUsb->DEVICE.DADD.reg = USB_DEVICE_DADD_ADDEN | 0;
     /* Configure endpoint 0 */
@@ -300,12 +303,14 @@ void USB_SendStall(Usb *pUsb, bool direction_in)
   if (direction_in)
   {
     /* Set STALL request on IN direction */
-    pUsb->DEVICE.DeviceEndpoint[0].EPSTATUSSET.bit.STALLRQ1 = 1;
+    //pUsb->DEVICE.DeviceEndpoint[0].EPSTATUSSET.reg = USB_DEVICE_EPSTATUSSET_STALLRQ1;
+    pUsb->DEVICE.DeviceEndpoint[0].EPSTATUSSET.bit.STALLRQ = (1<<1);
   }
   else
   {
     /* Set STALL request on OUT direction */
-    pUsb->DEVICE.DeviceEndpoint[0].EPSTATUSSET.bit.STALLRQ0 = 1;
+    //pUsb->DEVICE.DeviceEndpoint[0].EPSTATUSSET.reg = USB_DEVICE_EPSTATUSSET_STALLRQ0;
+    pUsb->DEVICE.DeviceEndpoint[0].EPSTATUSSET.bit.STALLRQ = (1<<0);
   }
 }
 
@@ -317,11 +322,12 @@ void USB_SendZlp(Usb *pUsb)
   /* Set the byte count as zero */
   usb_endpoint_table[0].DeviceDescBank[1].PCKSIZE.bit.BYTE_COUNT = 0;
   /* Clear the transfer complete flag  */
-  pUsb->DEVICE.DeviceEndpoint[0].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_TRCPT1;
+  //pUsb->DEVICE.DeviceEndpoint[0].EPINTFLAG.bit.TRCPT1 = true;
+  pUsb->DEVICE.DeviceEndpoint[0].EPINTFLAG.bit.TRCPT |= (1 << 1);
   /* Set the bank as ready */
   pUsb->DEVICE.DeviceEndpoint[0].EPSTATUSSET.bit.BK1RDY = true;
   /* Wait for transfer to complete */
-  while (!( pUsb->DEVICE.DeviceEndpoint[0].EPINTFLAG.bit.TRCPT1 ));
+  while (!( pUsb->DEVICE.DeviceEndpoint[0].EPINTFLAG.bit.TRCPT & (1<<1) ));
 }
 
 /*----------------------------------------------------------------------------
diff --git a/bootloaders/zero/board_startup.c b/bootloaders/zero/board_startup.c
index 593d93b60..aaa5a019f 100644
--- a/bootloaders/zero/board_startup.c
+++ b/bootloaders/zero/board_startup.c
@@ -139,3 +139,9 @@ void PendSV_Handler(void)
   __BKPT(2);
   while (1);
 }
+
+void SysTick_Handler(void)
+{
+  __BKPT(1);
+  while (1);
+}
diff --git a/bootloaders/zero/main.c b/bootloaders/zero/main.c
index af004cc68..3b18872a8 100644
--- a/bootloaders/zero/main.c
+++ b/bootloaders/zero/main.c
@@ -23,33 +23,18 @@
 #include "sam_ba_serial.h"
 #include "board_definitions.h"
 #include "board_driver_led.h"
-#include "board_driver_i2c.h"
 #include "sam_ba_usb.h"
 #include "sam_ba_cdc.h"
 
 extern uint32_t __sketch_vectors_ptr; // Exported value from linker script
 extern void board_init(void);
 
+#if (defined DEBUG) && (DEBUG == 1)
 volatile uint32_t* pulSketch_Start_Address;
-
-static void jump_to_application(void) {
-
-  /* Rebase the Stack Pointer */
-  __set_MSP( (uint32_t)(__sketch_vectors_ptr) );
-
-  /* Rebase the vector table base address */
-  SCB->VTOR = ((uint32_t)(&__sketch_vectors_ptr) & SCB_VTOR_TBLOFF_Msk);
-
-  /* Jump to application Reset Handler in the application */
-  asm("bx %0"::"r"(*pulSketch_Start_Address));
-}
+#endif
 
 static volatile bool main_b_cdc_enable = false;
 
-#ifdef CONFIGURE_PMIC
-static volatile bool jump_to_app = false;
-#endif
-
 /**
  * \brief Check the application startup condition
  *
@@ -59,35 +44,6 @@ static void check_start_application(void)
 //  LED_init();
 //  LED_off();
 
-  /*
-   * Test sketch stack pointer @ &__sketch_vectors_ptr
-   * Stay in SAM-BA if value @ (&__sketch_vectors_ptr) == 0xFFFFFFFF (Erased flash cell value)
-   */
-  if (__sketch_vectors_ptr == 0xFFFFFFFF)
-  {
-    /* Stay in bootloader */
-    return;
-  }
-
-  /*
-   * Load the sketch Reset Handler address
-   * __sketch_vectors_ptr is exported from linker script and point on first 32b word of sketch vector table
-   * First 32b word is sketch stack
-   * Second 32b word is sketch entry point: Reset_Handler()
-   */
-  pulSketch_Start_Address = &__sketch_vectors_ptr ;
-  pulSketch_Start_Address++ ;
-
-  /*
-   * Test vector table address of sketch @ &__sketch_vectors_ptr
-   * Stay in SAM-BA if this function is not aligned enough, ie not valid
-   */
-  if ( ((uint32_t)(&__sketch_vectors_ptr) & ~SCB_VTOR_TBLOFF_Msk) != 0x00)
-  {
-    /* Stay in bootloader */
-    return;
-  }
-
 #if defined(BOOT_DOUBLE_TAP_ADDRESS)
   #define DOUBLE_TAP_MAGIC 0x07738135
   if (PM->RCAUSE.bit.POR)
@@ -119,6 +75,39 @@ static void check_start_application(void)
   }
 #endif
 
+#if (!defined DEBUG) || ((defined DEBUG) && (DEBUG == 0))
+uint32_t* pulSketch_Start_Address;
+#endif
+
+  /*
+   * Test sketch stack pointer @ &__sketch_vectors_ptr
+   * Stay in SAM-BA if value @ (&__sketch_vectors_ptr) == 0xFFFFFFFF (Erased flash cell value)
+   */
+  if (__sketch_vectors_ptr == 0xFFFFFFFF)
+  {
+    /* Stay in bootloader */
+    return;
+  }
+
+  /*
+   * Load the sketch Reset Handler address
+   * __sketch_vectors_ptr is exported from linker script and point on first 32b word of sketch vector table
+   * First 32b word is sketch stack
+   * Second 32b word is sketch entry point: Reset_Handler()
+   */
+  pulSketch_Start_Address = &__sketch_vectors_ptr ;
+  pulSketch_Start_Address++ ;
+
+  /*
+   * Test vector table address of sketch @ &__sketch_vectors_ptr
+   * Stay in SAM-BA if this function is not aligned enough, ie not valid
+   */
+  if ( ((uint32_t)(&__sketch_vectors_ptr) & ~SCB_VTOR_TBLOFF_Msk) != 0x00)
+  {
+    /* Stay in bootloader */
+    return;
+  }
+
 /*
 #if defined(BOOT_LOAD_PIN)
   volatile PortGroup *boot_port = (volatile PortGroup *)(&(PORT->Group[BOOT_LOAD_PIN / 32]));
@@ -141,12 +130,15 @@ static void check_start_application(void)
 */
 
 //  LED_on();
-#ifdef CONFIGURE_PMIC
-  jump_to_app = true;
-#else
-  jump_to_application();
-#endif
 
+  /* Rebase the Stack Pointer */
+  __set_MSP( (uint32_t)(__sketch_vectors_ptr) );
+
+  /* Rebase the vector table base address */
+  SCB->VTOR = ((uint32_t)(&__sketch_vectors_ptr) & SCB_VTOR_TBLOFF_Msk);
+
+  /* Jump to application Reset Handler in the application */
+  asm("bx %0"::"r"(*pulSketch_Start_Address));
 }
 
 #if DEBUG_ENABLE
@@ -176,13 +168,6 @@ int main(void)
   board_init();
   __enable_irq();
 
-#ifdef CONFIGURE_PMIC
-  configure_pmic();
-  if (jump_to_app == true) {
-    jump_to_application();
-  }
-#endif
-
 #if SAM_BA_INTERFACE == SAM_BA_UART_ONLY  ||  SAM_BA_INTERFACE == SAM_BA_BOTH_INTERFACES
   /* UART is enabled in all cases */
   serial_open();
@@ -194,16 +179,6 @@ int main(void)
 
   DEBUG_PIN_LOW;
 
-  /* Initialize LEDs */
-  LED_init();
-  LEDRX_init();
-  LEDRX_off();
-  LEDTX_init();
-  LEDTX_off();
-
-  /* Start the sys tick (1 ms) */
-  SysTick_Config(1000);
-
   /* Wait for a complete enum on usb or a '#' char on serial line */
   while (1)
   {
@@ -239,10 +214,3 @@ int main(void)
 #endif
   }
 }
-
-void SysTick_Handler(void)
-{
-  LED_pulse();
-
-  sam_ba_monitor_sys_tick();
-}
diff --git a/bootloaders/zero/main.h b/bootloaders/zero/main.h
new file mode 100644
index 000000000..f2b10dc46
--- /dev/null
+++ b/bootloaders/zero/main.h
@@ -0,0 +1,69 @@
+/* ----------------------------------------------------------------------------
+ *         SAM Software Package License
+ * ----------------------------------------------------------------------------
+ * Copyright (c) 2011-2012, Atmel Corporation
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following condition is met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the disclaimer below.
+ *
+ * Atmel's name may not be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+ * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ----------------------------------------------------------------------------
+ */
+
+#pragma once
+
+// Gently pulse the D13 LED
+#define LED_PIN 17
+#define PORTA   PORT->Group[0]
+#define LED_PORT PORTA
+
+#define LED_ON LED_PORT.OUTSET.reg = (uint32_t)(1 << LED_PIN);
+#define LED_OFF LED_PORT.OUTCLR.reg = (uint32_t)(1 << LED_PIN);
+/*
+ * If BOOT_DOUBLE_TAP_ADDRESS is defined the bootloader is started by
+ * quickly tapping two times on the reset button.
+ * BOOT_DOUBLE_TAP_ADDRESS must point to a free SRAM cell that must not
+ * be touched from the loaded application.
+ */
+#define BOOT_DOUBLE_TAP_ADDRESS           0x20007FFC
+#define BOOT_DOUBLE_TAP_DATA              (*((volatile uint32_t *) BOOT_DOUBLE_TAP_ADDRESS))
+
+/*
+ * If BOOT_LOAD_PIN is defined the bootloader is started if the selected
+ * pin is tied LOW.
+ */
+//#define BOOT_LOAD_PIN                     PIN_PA21 // Pin 7
+//#define BOOT_LOAD_PIN                     PIN_PA15 // Pin 5
+#define BOOT_PIN_MASK                     (1U << (BOOT_LOAD_PIN & 0x1f))
+
+#define CPU_FREQUENCY                     8000000
+#define APP_START_ADDRESS                 0x00002000
+#define FLASH_WAIT_STATES                 1
+
+#define BOOT_USART_MODULE                 SERCOM0
+//#define BOOT_USART_MODULE                 SERCOM5
+#define BOOT_USART_MUX_SETTINGS           UART_RX_PAD3_TX_PAD2
+//#define BOOT_USART_PAD3                   PINMUX_PB23D_SERCOM5_PAD3
+//#define BOOT_USART_PAD2                   PINMUX_PB22D_SERCOM5_PAD2
+#define BOOT_USART_PAD3                   PINMUX_PA11C_SERCOM0_PAD3
+#define BOOT_USART_PAD2                   PINMUX_PA10C_SERCOM0_PAD2
+#define BOOT_USART_PAD1                   PINMUX_UNUSED
+#define BOOT_USART_PAD0                   PINMUX_UNUSED
+
diff --git a/bootloaders/zero/sam_ba_cdc.c b/bootloaders/zero/sam_ba_cdc.c
index 377340921..fc5efe348 100644
--- a/bootloaders/zero/sam_ba_cdc.c
+++ b/bootloaders/zero/sam_ba_cdc.c
@@ -55,7 +55,7 @@ bool cdc_is_rx_ready(/*P_USB_CDC pCdc*/void)
     return 0;
 
   /* Return transfer complete 0 flag status */
-  return (pCdc->pUsb->DEVICE.DeviceEndpoint[USB_EP_OUT].EPINTFLAG.bit.TRCPT0);
+  return (pCdc->pUsb->DEVICE.DeviceEndpoint[USB_EP_OUT].EPINTFLAG.bit.TRCPT & (1<<0));
 }
 
 uint32_t cdc_write_buf(/*P_USB_CDC pCdc,*/ void const* data, uint32_t length)
diff --git a/bootloaders/zero/sam_ba_monitor.c b/bootloaders/zero/sam_ba_monitor.c
index 8b31b9471..7daeb3067 100644
--- a/bootloaders/zero/sam_ba_monitor.c
+++ b/bootloaders/zero/sam_ba_monitor.c
@@ -25,7 +25,6 @@
 #include "board_driver_usb.h"
 #include "sam_ba_usb.h"
 #include "sam_ba_cdc.h"
-#include "board_driver_led.h"
 
 const char RomBOOT_Version[] = SAM_BA_VERSION;
 const char RomBOOT_ExtendedCapabilities[] = "[Arduino:XYZ]";
@@ -85,11 +84,6 @@ t_monitor_if * ptr_monitor_if;
 volatile bool b_terminal_mode = false;
 volatile bool b_sam_ba_interface_usart = false;
 
-/* Pulse generation counters to keep track of the time remaining for each pulse type */
-#define TX_RX_LED_PULSE_PERIOD 100
-volatile uint16_t txLEDPulse = 0; // time remaining for Tx LED pulse
-volatile uint16_t rxLEDPulse = 0; // time remaining for Rx LED pulse
-
 void sam_ba_monitor_init(uint8_t com_interface)
 {
 #if SAM_BA_INTERFACE == SAM_BA_UART_ONLY  ||  SAM_BA_INTERFACE == SAM_BA_BOTH_INTERFACES
@@ -108,74 +102,8 @@ void sam_ba_monitor_init(uint8_t com_interface)
 #endif
 }
 
-/*
- * Central SAM-BA monitor putdata function using the board LEDs
- */
-static uint32_t sam_ba_putdata(t_monitor_if* pInterface, void const* data, uint32_t length)
-{
-	uint32_t result ;
-
-	result=pInterface->putdata(data, length);
-
-	LEDTX_on();
-	txLEDPulse = TX_RX_LED_PULSE_PERIOD;
-
-	return result;
-}
-
-/*
- * Central SAM-BA monitor getdata function using the board LEDs
- */
-static uint32_t sam_ba_getdata(t_monitor_if* pInterface, void* data, uint32_t length)
-{
-	uint32_t result ;
-
-	result=pInterface->getdata(data, length);
-
-	if (result)
-	{
-		LEDRX_on();
-		rxLEDPulse = TX_RX_LED_PULSE_PERIOD;
-	}
-
-	return result;
-}
-
-/*
- * Central SAM-BA monitor putdata function using the board LEDs
- */
-static uint32_t sam_ba_putdata_xmd(t_monitor_if* pInterface, void const* data, uint32_t length)
-{
-	uint32_t result ;
-
-	result=pInterface->putdata_xmd(data, length);
-
-	LEDTX_on();
-	txLEDPulse = TX_RX_LED_PULSE_PERIOD;
-
-	return result;
-}
-
-/*
- * Central SAM-BA monitor getdata function using the board LEDs
- */
-static uint32_t sam_ba_getdata_xmd(t_monitor_if* pInterface, void* data, uint32_t length)
-{
-	uint32_t result ;
-
-	result=pInterface->getdata_xmd(data, length);
-
-	if (result)
-	{
-		LEDRX_on();
-		rxLEDPulse = TX_RX_LED_PULSE_PERIOD;
-	}
-
-	return result;
-}
-
 /**
- * \brief This function allows data emission by USART
+ * \brief This function allows data rx by USART
  *
  * \param *data  Data pointer
  * \param length Length of the data
@@ -213,10 +141,10 @@ void sam_ba_putdata_term(uint8_t* data, uint32_t length)
     buf[1] = 'x';
     buf[length * 2 + 2] = '\n';
     buf[length * 2 + 3] = '\r';
-    sam_ba_putdata(ptr_monitor_if, buf, length * 2 + 4);
+    ptr_monitor_if->putdata(buf, length * 2 + 4);
   }
   else
-    sam_ba_putdata(ptr_monitor_if, data, length);
+    ptr_monitor_if->putdata(data, length);
   return;
 }
 
@@ -259,12 +187,12 @@ static void put_uint32(uint32_t n)
 
     buff[7-i] = d > 9 ? 'A' + d - 10 : '0' + d;
   }
-  sam_ba_putdata( ptr_monitor_if, buff, 8);
+  ptr_monitor_if->putdata(buff, 8);
 }
 
 static void sam_ba_monitor_loop(void)
 {
-  length = sam_ba_getdata(ptr_monitor_if, data, SIZEBUFMAX);
+  length = ptr_monitor_if->getdata(data, SIZEBUFMAX);
   ptr = data;
 
   for (i = 0; i < length; i++, ptr++)
@@ -275,7 +203,7 @@ static void sam_ba_monitor_loop(void)
     {
       if (b_terminal_mode)
       {
-        sam_ba_putdata(ptr_monitor_if, "\n\r", 2);
+        ptr_monitor_if->putdata("\n\r", 2);
       }
       if (command == 'S')
       {
@@ -307,13 +235,13 @@ static void sam_ba_monitor_loop(void)
         ptr--;
         //Do we expect more data ?
         if(j<current_number)
-          sam_ba_getdata_xmd(ptr_monitor_if, ptr_data, current_number-j);
+          ptr_monitor_if->getdata_xmd(ptr_data, current_number-j);
 
         __asm("nop");
       }
       else if (command == 'R')
       {
-        sam_ba_putdata_xmd(ptr_monitor_if, ptr_data, current_number);
+        ptr_monitor_if->putdata_xmd(ptr_data, current_number);
       }
       else if (command == 'O')
       {
@@ -354,35 +282,35 @@ static void sam_ba_monitor_loop(void)
       else if (command == 'T')
       {
         b_terminal_mode = 1;
-        sam_ba_putdata(ptr_monitor_if, "\n\r", 2);
+        ptr_monitor_if->putdata("\n\r", 2);
       }
       else if (command == 'N')
       {
         if (b_terminal_mode == 0)
         {
-          sam_ba_putdata( ptr_monitor_if, "\n\r", 2);
+          ptr_monitor_if->putdata("\n\r", 2);
         }
         b_terminal_mode = 0;
       }
       else if (command == 'V')
       {
-        sam_ba_putdata( ptr_monitor_if, "v", 1);
-        sam_ba_putdata( ptr_monitor_if, (uint8_t *) RomBOOT_Version, strlen(RomBOOT_Version));
-        sam_ba_putdata( ptr_monitor_if, " ", 1);
-        sam_ba_putdata( ptr_monitor_if, (uint8_t *) RomBOOT_ExtendedCapabilities, strlen(RomBOOT_ExtendedCapabilities));
-        sam_ba_putdata( ptr_monitor_if, " ", 1);
+        ptr_monitor_if->putdata("v", 1);
+        ptr_monitor_if->putdata((uint8_t *) RomBOOT_Version, strlen(RomBOOT_Version));
+        ptr_monitor_if->putdata(" ", 1);
+        ptr_monitor_if->putdata((uint8_t *) RomBOOT_ExtendedCapabilities, strlen(RomBOOT_ExtendedCapabilities));
+        ptr_monitor_if->putdata(" ", 1);
         ptr = (uint8_t*) &(__DATE__);
         i = 0;
         while (*ptr++ != '\0')
           i++;
-        sam_ba_putdata( ptr_monitor_if, (uint8_t *) &(__DATE__), i);
-        sam_ba_putdata( ptr_monitor_if, " ", 1);
+        ptr_monitor_if->putdata((uint8_t *) &(__DATE__), i);
+        ptr_monitor_if->putdata(" ", 1);
         i = 0;
         ptr = (uint8_t*) &(__TIME__);
         while (*ptr++ != '\0')
           i++;
-        sam_ba_putdata( ptr_monitor_if, (uint8_t *) &(__TIME__), i);
-        sam_ba_putdata( ptr_monitor_if, "\n\r", 2);
+        ptr_monitor_if->putdata((uint8_t *) &(__TIME__), i);
+        ptr_monitor_if->putdata("\n\r", 2);
       }
       else if (command == 'X')
       {
@@ -406,7 +334,7 @@ static void sam_ba_monitor_loop(void)
         }
 
         // Notify command completed
-        sam_ba_putdata( ptr_monitor_if, "X\n\r", 3);
+        ptr_monitor_if->putdata("X\n\r", 3);
       }
       else if (command == 'Y')
       {
@@ -465,7 +393,7 @@ static void sam_ba_monitor_loop(void)
         }
 
         // Notify command completed
-        sam_ba_putdata( ptr_monitor_if, "Y\n\r", 3);
+        ptr_monitor_if->putdata("Y\n\r", 3);
       }
       else if (command == 'Z')
       {
@@ -484,9 +412,9 @@ static void sam_ba_monitor_loop(void)
           crc = serial_add_crc(*data++, crc);
 
         // Send response
-        sam_ba_putdata( ptr_monitor_if, "Z", 1);
+        ptr_monitor_if->putdata("Z", 1);
         put_uint32(crc);
-        sam_ba_putdata( ptr_monitor_if, "#\n\r", 3);
+        ptr_monitor_if->putdata("#\n\r", 3);
       }
 
       command = 'z';
@@ -494,7 +422,7 @@ static void sam_ba_monitor_loop(void)
 
       if (b_terminal_mode)
       {
-        sam_ba_putdata( ptr_monitor_if, ">", 1);
+        ptr_monitor_if->putdata(">", 1);
       }
     }
     else
@@ -525,15 +453,6 @@ static void sam_ba_monitor_loop(void)
   }
 }
 
-void sam_ba_monitor_sys_tick(void)
-{
-	/* Check whether the TX or RX LED one-shot period has elapsed.  if so, turn off the LED */
-	if (txLEDPulse && !(--txLEDPulse))
-		LEDTX_off();
-	if (rxLEDPulse && !(--rxLEDPulse))
-		LEDRX_off();
-}
-
 /**
  * \brief This function starts the SAM-BA monitor.
  */
diff --git a/bootloaders/zero/sam_ba_serial.c b/bootloaders/zero/sam_ba_serial.c
index 09607ecf6..a06de01dc 100644
--- a/bootloaders/zero/sam_ba_serial.c
+++ b/bootloaders/zero/sam_ba_serial.c
@@ -108,8 +108,8 @@ void serial_open(void)
     /* Wait for synchronization */
   }
 
-	/* Baud rate 115200 - clock 48MHz -> BAUD value-63018 */
-	uart_basic_init(BOOT_USART_MODULE, 63018, BOOT_USART_PAD_SETTINGS);
+	/* Baud rate 115200 - clock 8MHz -> BAUD value-50436 */
+	uart_basic_init(BOOT_USART_MODULE, 50436, BOOT_USART_PAD_SETTINGS);
 
 	//Initialize flag
 	b_sharp_received = false;
diff --git a/bootloaders/zero/sam_ba_usb.c b/bootloaders/zero/sam_ba_usb.c
index 068b81d8b..090375c7f 100644
--- a/bootloaders/zero/sam_ba_usb.c
+++ b/bootloaders/zero/sam_ba_usb.c
@@ -19,7 +19,6 @@
 
 #include <stdint.h>
 #include <string.h>
-#include "board_definitions.h"
 #include "sam_ba_usb.h"
 #include "board_driver_usb.h"
 #include "sam_ba_cdc.h"
@@ -39,14 +38,19 @@ const char devDescriptor[] =
   0x00,   // bDeviceSubclass: CDC class sub code
   0x00,   // bDeviceProtocol: CDC Device protocol
   0x40,   // bMaxPacketSize0
-  USB_VID_LOW,   // idVendor L
-  USB_VID_HIGH,   // idVendor H
+  0x41,   // idVendor L
+  0x23,   // idVendor H
   USB_PID_LOW,   // idProduct L
   USB_PID_HIGH,  // idProduct H
   0x00,   // bcdDevice L, here matching SAM-BA version
   0x02,   // bcdDevice H
+#if 0 // TODO: pending validation
   STRING_INDEX_MANUFACTURER,   // iManufacturer
   STRING_INDEX_PRODUCT,        // iProduct
+#else
+  0x00,   // iManufacturer
+  0x00,   // iProduct
+#endif // 0
   0x00,   // SerialNumber, should be based on product unique ID
   0x01    // bNumConfigs
 };
@@ -167,7 +171,7 @@ void sam_ba_usb_CDC_Enumerate(P_USB_CDC pCdc)
   static volatile uint16_t wValue, wIndex, wLength, wStatus;
 
   /* Clear the Received Setup flag */
-  pUsb->DEVICE.DeviceEndpoint[0].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_RXSTP;
+  pUsb->DEVICE.DeviceEndpoint[0].EPINTFLAG.bit.RXSTP = true;
 
   /* Read the USB request parameters */
   bmRequestType = udd_ep_out_cache_buffer[0][0];
@@ -191,40 +195,47 @@ void sam_ba_usb_CDC_Enumerate(P_USB_CDC pCdc)
         /* Return Device Descriptor */
         USB_Write(pCdc->pUsb, devDescriptor, SAM_BA_MIN(sizeof(devDescriptor), wLength), USB_EP_CTRL);
       }
-      else if (wValue>>8 == STD_GET_DESCRIPTOR_CONFIGURATION)
-      {
-        /* Return Configuration Descriptor */
-        USB_Write(pCdc->pUsb, cfgDescriptor, SAM_BA_MIN(sizeof(cfgDescriptor), wLength), USB_EP_CTRL);
-      }
-      else if (wValue>>8 == STD_GET_DESCRIPTOR_STRING)
+      else
       {
-        switch ( wValue & 0xff )
+        if (wValue>>8 == STD_GET_DESCRIPTOR_CONFIGURATION)
         {
-          case STRING_INDEX_LANGUAGES: {
-            uint16_t STRING_LANGUAGE[2] = { (STD_GET_DESCRIPTOR_STRING<<8) | 4, 0x0409 };
-
-            USB_Write(pCdc->pUsb, (const char*)STRING_LANGUAGE, SAM_BA_MIN(sizeof(STRING_LANGUAGE), wLength), USB_EP_CTRL);
+          /* Return Configuration Descriptor */
+          USB_Write(pCdc->pUsb, cfgDescriptor, SAM_BA_MIN(sizeof(cfgDescriptor), wLength), USB_EP_CTRL);
+        }
+        else
+        {
+#if 0 // TODO: pending validation
+          if (wValue>>8 == STD_GET_DESCRIPTOR_STRING)
+          {
+            switch ( wValue & 0xff )
+            {
+              case STRING_INDEX_LANGUAGES:
+                uint16_t STRING_LANGUAGE[2] = { (STD_GET_DESCRIPTOR_STRING<<8) | 4, 0x0409 };
+
+                USB_Write(pCdc->pUsb, (const char*)STRING_LANGUAGE, SAM_BA_MIN(sizeof(STRING_LANGUAGE), wLength), USB_EP_CTRL);
+              break;
+
+              case STRING_INDEX_MANUFACTURER:
+                USB_SendString(pCdc->pUsb, STRING_MANUFACTURER, strlen(STRING_MANUFACTURER), wLength );
+              break;
+
+              case STRING_INDEX_PRODUCT:
+                USB_SendString(pCdc->pUsb, STRING_PRODUCT, strlen(STRING_PRODUCT), wLength );
+              break;
+              default:
+                /* Stall the request */
+                USB_SendStall(pUsb, true);
+              break;
+            }
           }
-          break;
-
-          case STRING_INDEX_MANUFACTURER:
-            USB_SendString(pCdc->pUsb, STRING_MANUFACTURER, wLength );
-          break;
-
-          case STRING_INDEX_PRODUCT:
-            USB_SendString(pCdc->pUsb, STRING_PRODUCT, wLength );
-          break;
-          default:
+          else
+#endif // 0
+          {
             /* Stall the request */
             USB_SendStall(pUsb, true);
-          break;
+          }
         }
       }
-      else
-      {
-        /* Stall the request */
-        USB_SendStall(pUsb, true);
-      }
     break;
 
     case STD_SET_ADDRESS:
@@ -268,11 +279,13 @@ void sam_ba_usb_CDC_Enumerate(P_USB_CDC pCdc)
       {
         if (dir)
         {
-          wStatus = (pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUS.reg & USB_DEVICE_EPSTATUSSET_STALLRQ1) ? 1 : 0;
+          //wStatus = (pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUS.reg & USB_DEVICE_EPSTATUSSET_STALLRQ1) ? 1 : 0;
+          wStatus = (pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUS.bit.STALLRQ & (1<<1)) ? 1 : 0;
         }
         else
         {
-          wStatus = (pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUS.reg & USB_DEVICE_EPSTATUSSET_STALLRQ0) ? 1 : 0;
+          //wStatus = (pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUS.reg & USB_DEVICE_EPSTATUSSET_STALLRQ0) ? 1 : 0;
+          wStatus = (pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUS.bit.STALLRQ & (1<<0)) ? 1 : 0;
         }
         /* Return current status of endpoint */
         USB_Write(pCdc->pUsb, (char *) &wStatus, sizeof(wStatus), USB_EP_CTRL);
@@ -302,11 +315,13 @@ void sam_ba_usb_CDC_Enumerate(P_USB_CDC pCdc)
         /* Set STALL request for the endpoint */
         if (dir)
         {
-          pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUSSET.reg = USB_DEVICE_EPSTATUSSET_STALLRQ1;
+          //pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUSSET.reg = USB_DEVICE_EPSTATUSSET_STALLRQ1;
+          pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUSSET.bit.STALLRQ = (1<<1);
         }
         else
         {
-          pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUSSET.reg = USB_DEVICE_EPSTATUSSET_STALLRQ0;
+          //pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUSSET.reg = USB_DEVICE_EPSTATUSSET_STALLRQ0;
+          pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUSSET.bit.STALLRQ = (1<<0);
         }
 
         /* Send ZLP */
@@ -338,13 +353,14 @@ void sam_ba_usb_CDC_Enumerate(P_USB_CDC pCdc)
       {
         if (dir)
         {
-          if (pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUS.bit.STALLRQ1)
+          if (pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUS.bit.STALLRQ & (1<<1))
           {
             // Remove stall request
-            pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_STALLRQ1;
-            if (pUsb->DEVICE.DeviceEndpoint[wIndex].EPINTFLAG.bit.STALL1)
+            //pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_STALLRQ1;
+            pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUSCLR.bit.STALLRQ = (1<<1);
+            if (pUsb->DEVICE.DeviceEndpoint[wIndex].EPINTFLAG.bit.STALL & (1<<1))
             {
-              pUsb->DEVICE.DeviceEndpoint[wIndex].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_STALL1;
+              pUsb->DEVICE.DeviceEndpoint[wIndex].EPINTFLAG.bit.STALL = (1<<1);
               // The Stall has occurred, then reset data toggle
               pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSSET_DTGLIN;
             }
@@ -352,13 +368,14 @@ void sam_ba_usb_CDC_Enumerate(P_USB_CDC pCdc)
         }
         else
         {
-          if (pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUS.bit.STALLRQ0)
+          if (pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUS.bit.STALLRQ & (1<<0))
           {
             // Remove stall request
-            pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_STALLRQ0;
-            if (pUsb->DEVICE.DeviceEndpoint[wIndex].EPINTFLAG.bit.STALL0)
+            //pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_STALLRQ0;
+            pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUSCLR.bit.STALLRQ = (1<<0);
+            if (pUsb->DEVICE.DeviceEndpoint[wIndex].EPINTFLAG.bit.STALL & (1<<0))
             {
-              pUsb->DEVICE.DeviceEndpoint[wIndex].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_STALL0;
+              pUsb->DEVICE.DeviceEndpoint[wIndex].EPINTFLAG.bit.STALL = (1<<0);
               // The Stall has occurred, then reset data toggle
               pUsb->DEVICE.DeviceEndpoint[wIndex].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSSET_DTGLOUT;
             }
@@ -413,24 +430,27 @@ P_USB_CDC usb_init(void)
   return &sam_ba_cdc;
 }
 
+#if 0 // TODO: pending validation
 /*----------------------------------------------------------------------------
  * \brief Send a USB descriptor string.
  *
  * The input string is plain ASCII but is sent out as UTF-16 with the correct 2-byte prefix.
  */
-uint32_t USB_SendString(Usb *pUsb, const char* ascii_string, uint8_t maxLength)
+uint32_t USB_SendString(Usb *pUsb, const char* ascii_string, uint8_t length, uint8_t maxLength)
 {
   uint8_t string_descriptor[255]; // Max USB-allowed string length
   uint16_t* unicode_string=(uint16_t*)(string_descriptor+2); // point on 3 bytes of descriptor
-  int resulting_length;
 
-  string_descriptor[0] = (strlen(ascii_string)<<1) + 2;
-  string_descriptor[1] = STD_GET_DESCRIPTOR_STRING;
+  int resulting_length = 1;
 
-  for ( resulting_length = 1 ; *ascii_string && (resulting_length<maxLength>>1) ; resulting_length++ )
+  for ( ; *ascii_string && (length>=0) && (resulting_length<(maxLength>>1)) ; ascii_string++, length--, resulting_length++ )
   {
-    *unicode_string++ = (uint16_t)(*ascii_string++);
+    *unicode_string++ = (uint16_t)(*ascii_string);
   }
 
-  return USB_Write(pUsb, (const char*)string_descriptor, resulting_length<<1, USB_EP_CTRL);
+  string_descriptor[0] = (resulting_length<<1);
+  string_descriptor[1] = STD_GET_DESCRIPTOR_STRING;
+
+  return USB_Write(pUsb, (const char*)unicode_string, resulting_length, USB_EP_CTRL);
 }
+#endif // 0
diff --git a/bootloaders/zero/sam_ba_usb.h b/bootloaders/zero/sam_ba_usb.h
index 457fdbc09..42c0d608f 100644
--- a/bootloaders/zero/sam_ba_usb.h
+++ b/bootloaders/zero/sam_ba_usb.h
@@ -66,9 +66,11 @@
 #define FEATURE_DEVICE_REMOTE_WAKEUP   (1u)
 #define FEATURE_TEST_MODE              (2u)
 
+#if 0 // TODO: pending validation
 #define STRING_INDEX_LANGUAGES         (0x00u)
 #define STRING_INDEX_MANUFACTURER      (0x01u)
 #define STRING_INDEX_PRODUCT           (0x02u)
+#endif // 0
 
 #define SAM_BA_MIN(a, b) (((a) < (b)) ? (a) : (b))
 
@@ -94,7 +96,9 @@ P_USB_CDC usb_init(void);
 
 void sam_ba_usb_CDC_Enumerate(P_USB_CDC pCdc);
 
-uint32_t USB_SendString(Usb *pUsb, const char* ascii_string, uint8_t maxLength);
+#if 0 // TODO: pending validation
+uint32_t USB_SendString(Usb *pUsb, const char* ascii_string, uint8_t length, uint8_t maxLength);
+#endif // 0
 
 extern USB_CDC sam_ba_cdc;
 
diff --git a/bootloaders/zero/samd21_sam_ba.bin b/bootloaders/zero/samd21_sam_ba.bin
old mode 100755
new mode 100644
index cc88fa191..d727d0707
Binary files a/bootloaders/zero/samd21_sam_ba.bin and b/bootloaders/zero/samd21_sam_ba.bin differ
diff --git a/bootloaders/zero/samd21_sam_ba.elf b/bootloaders/zero/samd21_sam_ba.elf
new file mode 100644
index 000000000..edee94811
Binary files /dev/null and b/bootloaders/zero/samd21_sam_ba.elf differ
diff --git a/bootloaders/zero/samd21_sam_ba.hex b/bootloaders/zero/samd21_sam_ba.hex
index 95fe19aa1..12ee99817 100644
--- a/bootloaders/zero/samd21_sam_ba.hex
+++ b/bootloaders/zero/samd21_sam_ba.hex
@@ -1,409 +1,376 @@
-:10000000FC7F002015060000050600000906000020
+:10000000FC7F0020E9050000D5050000D9050000AF
 :1000100000000000000000000000000000000000E0
-:100020000000000000000000000000000D060000BD
-:10003000000000000000000011060000650700003D
+:10002000000000000000000000000000DD050000EE
+:100030000000000000000000E1050000E5050000F0
 :1000400010B5064C2378002B07D1054B002B02D0AE
-:10005000044800E000BF0123237010BD5C000020B5
-:10006000000000000819000008B5084B002B03D061
+:10005000044800E000BF0123237010BD58000020B9
+:1000600000000000F816000008B5084B002B03D074
 :100070000748084900E000BF07480368002B03D089
 :10008000064B002B00D0984708BDC046000000007A
-:100090000819000060000020580000200000000047
-:1000A000154A164B1178002909D115491878097895
-:1000B0004118C9B21970802012498002C8611178B4
-:1000C0000131C9B211701978F02902D819780929BB
-:1000D00009D80B4908784042C0B2087018780978EE
-:1000E0004118C9B2197012781B789A4203D1802244
-:1000F000044B9202DA617047780000200100002072
-:10010000000000200044004110B5C3699C07FCD4E6
-:1001100003680224A3430360C46901231C42FBD18A
-:100120000468234303600368DC07FCD4C46901232B
-:100130001C42FBD1C469DC401C42F7D1084B1A4376
-:100140000260C3695A07FCD4C0239B0243608181CB
-:10015000C3699C07FCD4036802221343036010BDEB
-:1001600004000040037EDA07FCD5018570470000DB
-:10017000027E01235107FBD5428B1A4207D1428BE5
-:10018000DA401A4203D1428B92081A4202D0034B42
-:1001900001221A70008DC0B27047C046790000205D
-:1001A00070B50368041C988B1A1C0821FF320842A2
-:1001B00026D0802099839872112353704021144BCC
-:1001C000917150715E68134DC0202E40800506432A
-:1001D0005E605E693540284358610F4818600F48DB
-:1001E00018615D680E4828408025AD02284358609C
-:1001F0005868800B8003586000235171237105E01B
-:10020000137ADA0602D5201C00F0E6FA207970BDD8
-:1002100098010020FFFFFF8F9800002018010020A8
-:10022000FF3F00F0002303714371044B01608360C2
-:100230000B78022213430B707047C046A1010000E7
-:1002400038B5364B2021DA6901200A43DA61344B94
-:1002500006241A7802431A70324B0F221978914300
-:1002600019701978214319702F490C7820430870B0
-:1002700019780A401A701A7860210A431A702B4BB9
-:100280002B4A5A805A7852B2002AFBDB294B0121B3
-:100290001A780A431A709A78D107FCD42648026863
-:1002A000510B1F221140914200D1052111408C01B8
-:1002B0001D8D22492940214319850468A10C0A405B
-:1002C0001F2A00D11D221C8D1F210A408C4322436E
-:1002D0001A8502680721D20D0A408A4200D1032202
-:1002E0000A40188D1103164A02400A431A851978EC
-:1002F0007F220A401A701A78042112480A431A70A1
-:1003000058621A890C218A431A811A8901218A4369
-:100310001A810021802201F076F938BD00040040E6
-:10032000584400413C44004159440041000C004005
-:100330000640000000500041246080003FF8FFFFAD
-:10034000FF8FFFFF98010020F7B5141C1F4A5F01C3
-:1003500001971D1CD319061C5869271C4000400F2B
-:1003600003301033C74006D00F1C80225968120694
-:100370000A435A6009E02F1C7B1E9F41144BBF01AA
-:10038000FF18381C221C01F035F901990F48083577
-:1003900042181761131C5269A104920B890C920335
-:1003A0000A435A6159690B4A0A405A616B01F318B2
-:1003B0000222DA715979802252420A435A716B0142
-:1003C000F318DB799A07FAD5201CFEBD98010020AE
-:1003D00018010020FF3F00F0F8B51A4E051C3378D5
-:1003E000141C002B12D1184B184A1A645A6C920B29
-:1003F00092035A64586C164A02405A64A2235B0066
-:10040000EA5C40200243EA54012333704827FF3757
-:10041000EA5D0123134012D00B4B5A6C9204920CEC
-:10042000A24202D25C6CA404A40C081C221C074942
-:1004300001F0E0F80123EB550023337000E01C1CB1
-:10044000201CF8BD7A00002098010020D800002070
-:10045000FF3F00F0FF3083792022002900D11022D5
-:100460001343837170470000084BFF305A69920BA9
-:1004700092035A6102230372827980235B42134301
-:100480008371037A9A07FCD57047C0469801002013
-:1004900080235B421943C9B28172704770B5A023B3
-:1004A00003225B00C254134B134A5C6CC0211440FE
-:1004B00089050C4346255C64FF35402444550F4DA7
-:1004C00030261D6490256D0046555D6B154029430F
-:1004D000922559636D0080214155094D1D63B0255A
-:1004E0006D0044555C6F22405A67B2235B00C154D3
-:1004F00070BDC04698010020FFFFFF8FD80000208C
-:100500005801002030B5364A1E235168082099430F
-:1005100002231943516033498A6902438A61324890
-:10052000324A9082908A03439382D3689807FCD51D
-:100530002F4B012018701878C40704D52C48407838
-:1005400040B20028F7DB01209860587840B20028BC
-:10055000FBDB284C26484460587840B20028FBDB7F
-:1005600082242348E4014480587840B20028FBDB11
-:10057000908C8024A0439084D068C506FCD51E4C86
-:100580001A48C462D4681948E506FBD5848C1B4D13
-:100590002C438484D4681548E506FBD5848C022559
-:1005A0002C438484D0680406FCD51048C0684506F6
-:1005B000F8D5D068C406FCD500229A605A7852B2A9
-:1005C000002AFBDB0E480A4A50605A7852B2002AD1
-:1005D000FBDB00230B724B728B72CB7230BDC046BB
-:1005E00000400041000400400C06000000080040EC
-:1005F000000C004001050100B805FF7D040A000061
-:10060000000703000EBEFEE70DBEFEE705BEFEE7D7
-:1006100002BEFEE70E4A0F4838B5824204D10E4AA8
-:100620000E4B93420ED10AE00D4C9442F7D00023BA
-:10063000D1188842F3D9E55804330D60F8E700F08B
-:1006400011F804E09342FAD2002102C3FAE7FEE770
-:10065000000000205C000020A40300205C000020BB
-:100660000C190000334A38B51368141C01331ED02E
-:10067000D1B200291BD1304B1878012318402F4BE1
-:100680000AD11D682E498D4201D118600FE0196012
-:100690002C4901390029FCD11960236883F30888AB
-:1006A000FF239A43284B9A60224B5B681847FFF759
-:1006B00029FF62B600F0CCFD00F05AF8234B8022EF
-:1006C000920223499A6008220A602249041C0A60A7
-:1006D000802212059A609A611F4B204AC0215A60FD
-:1006E000194A0906106A0002000A01431162002239
-:1006F0009A6007221A60A368201C9847184B0028AC
-:1007000001D001221A701A78002A05D0002000F0CA
-:1007100093FA00F019FBFCE71B78002BEBD100F0FB
-:100720000BFE0028E7D0012000F086FA00F00CFB59
-:10073000FCE7C0460020000038040040FC7F002099
-:100740003581730748E8010000ED00E000440041F6
-:10075000884400419844004110E000E0E7030000B5
-:100760007B00002008B5FFF79BFC00F0C9FA08BD2C
-:1007700010B5054B054C2360FFF762FD201C216876
-:10078000FFF750FD201C10BD005000411802002052
-:1007900070B5051CC0B0081C161C0C1C00F03BFFFB
-:1007A00040006A460323023053701070760801231C
-:1007B000E218013A11785A00002906D1281C69462E
-:1007C0000023FFF7C1FD40B070BDB342F6DA6846C2
-:1007D00081520133ECE70000F7B5BA4A0468137898
-:1007E000B949271CFF37051C102038720B7053784D
-:1007F000B648B74E037093783380D17833880902B6
-:100800000B4333801179B34B198051791888090251
-:10081000084318809079B0490880D279088812027C
-:1008200002430A8040227A71A84F3A78A64F1202FA
-:1008300038780F1C0243A9488446181C624500D131
-:10084000C2E020DC802149008A4200D16EE109DC4F
-:10085000812A00D192E0822A00D195E0802A00D03E
-:1008600064E18BE081235B009A4200D1CFE000DAA3
-:1008700058E1C0239B009A4200D157E1984B9A421D
-:1008800000D14FE152E190231B019A4269D015DC5F
-:10089000D023DB009A4222D088231B019A4269D0E0
-:1008A000A023DB009A4200D040E1201CFFF7DCFDD2
-:1008B0003188286889B2FFF7EBFD3BE1894B9A420A
-:1008C00000D12FE100DC31E1874B9A4200D11DE1DC
-:1008D000864B9A4200D029E133886B7122E133883C
-:1008E0001B0A012B08D10B8812222868934201D8D9
-:1008F0000A8892B27E4911E133881B0A022B08D183
-:100900000B8843222868934201D80A8892B2794919
-:1009100004E133881B0A032B00D007E13388DBB2E4
-:10092000012B17D0002B07D0022B00D0FEE00A8845
-:100930002868D2B2704911E0042201A86F4900F082
-:1009400059FE3B8804222868934201D83A8892B223
-:1009500001A9E3E00A8828686949D2B2FFF718FFC5
-:10096000E8E03388201C2B71FFF77EFD201CFFF789
-:1009700095FDDFE0291C01C90122CFE06149002378
-:100980000B8028680222CAE05E4900220A8018888B
-:10099000502210405C4A10701E880F203040188092
-:1009A0001888032800D9C1E012781B8808335B013E
-:1009B000E418A379002A01D09B0600E0DB06DB0FD8
-:1009C0000B8028680222A9E019887F2291434E4AB1
-:1009D000C9B2117018880F2101401980318800298F
-:1009E00000D0A3E01988002900D19FE019880329CD
-:1009F00000D99BE012781B8808335B01E318002ABA
-:100A000002D020225A718DE0102159718AE00288AB
-:100A10007F239A433C4BD2B21A7001880F220A40BE
-:100A200002803288002A00D080E00288002A00D1AB
-:100A30007CE00288032A00D978E01B78002B1FD0C5
-:100A4000038808335B01E3189B799A066AD503880B
-:100A5000202208335B01E3181A71038808335B0115
-:100A6000E318DB795F065DD50388402208335B011C
-:100A7000E318DA710388022208335B01E3181EE0F1
-:100A8000038808335B01E3189B79D9064AD50388AC
-:100A9000102208335B01E3181A71038808335B01E5
-:100AA000E318DB799A063DD50388202208335B01E1
-:100AB000E318DA710388012208335B01E3181A7125
-:100AC00030E0C046980000207D0000208200002019
-:100AD0008400002086000020800000200203000027
-:100AE0000103000021200000A121000021220000BC
-:100AF0005C160000040000204C1600003C160000AC
-:100B0000401600007E0000207C0000200B88082298
-:100B10002868934201D80A8892B207490023FFF758
-:100B200013FC07E0201CFFF79FFC03E0201C0121C1
-:100B3000FFF790FCF7BDC0464800002007B5054B05
-:100B40000122019001A91868131CFFF7FDFB012089
-:100B50000EBDC0461802002013B5054B6C46073485
-:100B60001868211C0122FFF737FC207816BDC0460B
-:100B70001802002010B5074C201CFFF711FB031CC6
-:100B80000020834205D022684823FF33D05C012334
-:100B9000184010BD1802002010B5054A0C1C031C9B
-:100BA000191C10680123221CFFF7CEFB201C10BD6E
-:100BB0001802002070B5084C061C201C0D1CFFF705
-:100BC000EFFA0023984205D02068311C2A1CFFF759
-:100BD00003FC031C181C70BD18020020F8B50C4C57
-:100BE000051C201C0E1CFFF7DBFA0023271C341CFD
-:100BF00098420AD0002C07D0291C221C3868FFF725
-:100C0000EBFB241A2D18F5E7331C181CF8BDC04661
-:100C10001802002008B5031C081C111C9847044B3F
-:100C2000802212055A61034B64221A8008BDC04617
-:100C3000004400418C000020012805D1054B064AE4
-:100C40001A60064B187004E0002802D1044A014BD8
-:100C50001A6070478802002090160000940000205F
-:100C6000DC16000030B50A1C1C4985B00978031C4D
-:100C700000292AD0042A01D1006804E0022A01D107
-:100C8000008800E00078520004A98B180B3B9C1AE6
-:100C9000A3420BD00F210140092902D83025294356
-:100CA00000E0373119700009013BF1E701A9302359
-:100CB0000B7078234B700A208B1898700D20D87019
-:100CC000074B04321B68D86803E005490968C86807
-:100CD000191CFFF79FFF05B030BDC04688000020FB
-:100CE0008802002072B6EFF30883044A1360036899
-:100CF00083F30888436818477047C0468C02002079
-:100D00000D4B1A88002A09D01A88013A92B21A802B
-:100D1000002A03D18022094B12059A61084B1A88D8
-:100D2000002A08D01A88013A92B21A80002A02D109
-:100D3000044B08221A6070478C00002000440041D8
-:100D40008A00002098440041F0B591B008A9CE4A2D
-:100D50000B1C31CA31C351CA51C360CA60C3CB4BEB
-:100D6000CB489A687A255203520F92005258C949CB
-:100D700002609C68A4B262430C60C74900240A6008
-:100D8000C64A1460C64C2570C64CC74D2368281C43
-:100D90001B6940219847002805D0C44B08221A60DF
-:100DA000C34B64221A80C34B00221860C24B1D60E3
-:100DB000C24BC24DBF4F1A602A683B689A42E3D2C9
-:100DC000BD4B1B681A78FF2A00D120E2232A00D0ED
-:100DD000F7E1BB4E3378002B06D0B24BB9491B6804
-:100DE0000222D868FFF716FFAD4B1B78532B3FD17B
-:100DF0003B682A6893421ED9AF4801322A609A1A8A
-:100E0000B14B01681B6801310160B04E9A4201D2BA
-:100E1000326000E03360A14832680068049000F05E
-:100E2000E9FB336829685A182A60A34A1668F11842
-:100E30001160A74A13702B68013B2B609E4B1A6808
-:100E4000013A1A60A24BA04A1B7811688B420DD25E
-:100E500022689248C91A006892699047002805D014
-:100E6000924B08221A60924B64221A80C04696E187
-:100E7000522B0ED18948944A2368006811685B6937
-:100E800003909847934B802212055A616422924B3B
-:100E90000DE04F2B05D1814B8B4A1B6812681A70ED
-:100EA0007DE1482B05D17D4B874A1B6812681A806B
-:100EB00075E1572B05D1794B834A1B6812681A607C
-:100EC0006DE16F2B03D1754B0121186807E0682B8A
-:100ED00008D1724B7C481B6802211B880360FFF716
-:100EE000C1FE5CE1772B06D16C4B77481B6804216F
-:100EF0001B680360F3E7472B13D1734B1868FFF7A8
-:100F0000F1FE764B1B6883F3088862B6744B1B783E
-:100F1000002B00D143E1634B06201B681B689847F8
-:100F20003DE1542B04D1012333705E4B1B6864E018
-:100F30004E2B0CD13378002B06D15A4B61491B68DC
-:100F40000222D868FFF766FE0023337027E1562B94
-:100F500057D123686349D8680122FFF75BFE2368F5
-:100F60006149D8680322FFF755FE604D2368291CAC
-:100F7000D8680122FFF74EFE23685D49D8680D222C
-:100F8000FFF748FE2368291CD8680122FFF742FEBC
-:100F9000494F4A4D5749002339602B603A1C281CA1
-:100FA00013685E1C16601B780593002B03D0036842
-:100FB00001330360F4E73B4E2A683368D868FFF7D3
-:100FC00029FE33684949D8680122FFF723FE0599B5
-:100FD000296049493960384A1368581C10601B78E9
-:100FE000002B04D0354B1A6801321A60F3E73368DE
-:100FF0002A68D868FFF70EFE3368D86831490222A4
-:10100000CBE0314A582B17D1214E234D3668136857
-:101010002A68B10093420AD21C4D5808E86137484B
-:1010200028801A4D287DC607FBD55B18F2E71D4BBB
-:1010300033491B68D868AFE0592B00D07DE01268B7
-:10104000164B3049002A02D11B680B6070E00F4D2F
-:10105000086819686B680D4E8025AB439208736071
-:10106000002A65D0284B094D2B80084E337DDD07C3
-:10107000FBD50023064D2D680195AD08AB4247D343
-:10108000224D024E35804AE07016000000400041BB
-:101090004002002038020020340200208402002098
-:1010A00030020020880200204402002094440041C5
-:1010B0008A000020280200202C0200203C02002090
-:1010C00088000020D016000090020020940200202A
-:1010D00024020020004400418C0000208C020020EB
-:1010E00094000020AC160000D5160000AE160000DB
-:1010F000F8160000B0160000BC16000002A5FFFFA5
-:10110000C51600009000002044A5FFFF04A5FFFFC6
-:101110009342B5D09D00465901334E51AAE7404E47
-:10112000357DEE07FBD59D0049194019D21A97E786
-:101130003C4B3D491B68D8682EE05A2B2FD13B4BC6
-:1011400017681D680026EF19BD4206D02878311CAB
-:1011500000F014F90135061CF6E7324B34491B68E0
-:101160000122D868FFF756FD07230F223240111CD9
-:1011700036093031092A00DD07311820C0186A46C7
-:101180008154013BF1D2236806A9D8680822FFF7F1
-:1011900041FD23682749D8680322FFF73BFD264B12
-:1011A0007A221A70254B00221A60254B1B78934235
-:1011B0002DD01C4B23491B680122D868FFF72AFD5C
-:1011C00025E0111C3039C8B21C4B092804D81D6811
-:1011D0002A01114319601AE0111C4139052903D86D
-:1011E0001E68373A310106E0111C6139052904D81F
-:1011F0001868573A01010A4308E02C2A03D10B4A28
-:101200001968116001E00C490A7000221A600E4B47
-:101210001A6801321A600D4B1A680132C9E5C046DE
-:101220000040004188020020C9160000840200200E
-:10123000CD160000CF1600003002002090020020E2
-:1012400088000020D31600003C0200202C02002061
-:1012500010B51C4B01201A78022402431A701A4B55
-:101260000F22197891431970197821431970174981
-:101270000C782043087019780A401A701A782021D7
-:101280000A431A70124B04211A6A0A431A62114B5C
-:10129000114A5A805A7852B2002AFBDBC4220F4806
-:1012A0000F499203FEF730FF0E4A002313700E4AD7
-:1012B00013700E4A13700E4A13700E4A13700E4AC2
-:1012C000137010BD4A440041354400414B44004175
-:1012D00000040040000C00401440000000080042E0
-:1012E0002AF60000980200201F0300209902002027
-:1012F0009C020020200300201D03002008B5C1B27D
-:101300000248FEF72FFF012008BDC046000800423A
-:10131000024B187E4007C00F7047C04600080042CD
-:1013200008B5FFF7F5FF0028FBD00248FEF720FFC5
-:1013300008BDC0460008004208B5FFF7E9FF0023DA
-:10134000984205D0FFF7ECFF031C233B5A42534160
-:10135000181C08BD70B5041C0D1C4618B44204D0FE
-:101360002078FFF7CBFF0134F8E7281C70BD10B5DB
-:10137000041CFFF7D5FF2070012010BD0B0A584058
-:10138000034B4000C05A0902484080B27047C04633
-:1013900006170000F7B50024051C0F1C261CBC42D4
-:1013A00020D0FFF7BDFF114BC0B21B780190002B7E
-:1013B0001AD1311CFFF7E2FF0D4B061C1A88002AD8
-:1013C00004D10C4A11782A1C002907D001996A1C03
-:1013D0002970802F02D11988013919800134A4B2F3
-:1013E000151CDCE7301C00E00120FEBD1D030020C1
-:1013F0009A0200201E030020F0B53E4E85B0002268
-:1014000003900C1C32703C4B914201D1012201E04F
-:101410003A490C801A707F231C4201D080349C43CF
-:10142000FFF77EFF3378C0B2002B07D00025357060
-:10143000FFF776FF3378C0B2AB4236D1432803D0F2
-:10144000712853D01528EBD1012300930120FFF719
-:1014500055FF0098FFF752FF00998025C843C0B29E
-:10146000FFF74CFF039B00270293244A1388002BAD
-:101470001DD1214901930978002918D10198FFF75E
-:101480003DFF391C0198FFF779FF013D071C002D36
-:10149000EBD1000AC0B2FFF731FFF8B2FFF72EFF21
-:1014A000FFF73EFF3378002B0AD035701FE002991A
-:1014B000013B09781380029B019101330293DDE720
-:1014C000C0B2062807D1009B03990133DBB28031FB
-:1014D0000093803C0391002CB8D10420FFF70EFF4D
-:1014E000FFF71EFF044B01251C7000E00025281C9F
-:1014F00005B0F0BD1D0300201E0300209A0200204D
-:10150000F0B5384C87B0002301902370994201D187
-:10151000012301E0344A1180344A642613704320C9
-:10152000FFF7ECFE324FFFF7F3FE002803D1002F48
-:1015300003D0013FF7E7002F03D1013E002EEED18B
-:101540004DE00125FFF7ECFE2378002B38D1C0B227
-:101550000290012805D004283DD10620FFF7CEFED9
-:1015600039E005AE0221301CFFF714FF01988021FD
-:10157000FFF710FF23780390002B18D1FFF7D0FE60
-:101580000702FFF7CDFEBFB223783F18BFB2012B91
-:101590000DD0039B9F4207D13378AB4204D1EB437C
-:1015A0007278DBB29A4204D01820FFF7A7FE00231E
-:1015B00003E00620FFF7A2FE029B2278002A02D059
-:1015C000002626700BE0012B05D1019A6B1C80329E
-:1015D000DDB20192B6E7054A002313700126301CE4
-:1015E00007B0F0BD1D0300209A0200201E0300205A
-:1015F00000350C0010B50023934203D0CC5CC454DA
-:101600000133F9E710BD031C8218934202D0197010
-:101610000133FAE770470023C25C0133002AFBD193
-:10162000581E7047F8B5C046F8BC08BC9E467047C7
-:10163000F8B5C046F8BC08BC9E46704704030904D0
-:1016400041726475696E6F204C4C43004172647541
-:10165000696E6F205A65726F00000000120100026F
-:101660000200004041234D00000201020001000081
-:1016700008000000100000002000000040000000F2
-:1016800080000000000100000002000000040000D3
-:10169000FD1200002113000011130000551300007B
-:1016A0006F130000F9130000011500007600200000
-:1016B00044656320323020323031360031353A33E0
-:1016C000363A333900580A0D00590A0D005A0023E2
-:1016D0000A0D003E00322E30000000003D0B0000DD
-:1016E000590B0000750B0000990B0000B50B0000B2
-:1016F000990B0000DD0B00005B41726475696E6F31
-:101700003A58595A5D00000021104220633084404D
-:10171000A550C660E770088129914AA16BB18CC1C0
-:10172000ADD1CEE1EFF13112100273325222B55237
-:101730009442F772D662399318837BB35AA3BDD310
-:101740009CC3FFF3DEE36224433420040114E66407
-:10175000C774A44485546AA54BB528850995EEE560
-:10176000CFF5ACC58DD55336722611163006D77617
-:10177000F6669556B4465BB77AA719973887DFF7B0
-:10178000FEE79DD7BCC7C448E5588668A7784008DF
-:10179000611802282338CCC9EDD98EE9AFF9488900
-:1017A00069990AA92BB9F55AD44AB77A966A711A77
-:1017B000500A333A122AFDDBDCCBBFFB9EEB799B50
-:1017C000588B3BBB1AABA66C877CE44CC55C222CC7
-:1017D000033C600C411CAEED8FFDECCDCDDD2AADA0
-:1017E0000BBD688D499D977EB66ED55EF44E133E57
-:1017F000322E511E700E9FFFBEEFDDDFFCCF1BBFF0
-:101800003AAF599F788F8891A981CAB1EBA10CD1C9
-:101810002DC14EF16FE18010A100C230E3200450D1
-:10182000254046706760B9839893FBA3DAB33DC344
-:101830001CD37FE35EF3B1029012F322D232354221
-:10184000145277625672EAB5CBA5A89589856EF5D4
-:101850004FE52CD50DC5E234C324A0148104667471
-:10186000476424540544DBA7FAB79987B8975FE724
-:101870007EF71DC73CD7D326F2369106B0165766C1
-:101880007676154634564CD96DC90EF92FE9C899AC
-:10189000E9898AB9ABA94458654806782768C01811
-:1018A000E1088238A3287DCB5CDB3FEB1EFBF98B84
-:1018B000D89BBBAB9ABB754A545A376A167AF10A61
-:1018C000D01AB32A923A2EFD0FED6CDD4DCDAABD94
-:1018D0008BADE89DC98D267C076C645C454CA23CB1
-:1018E000832CE01CC10C1FEF3EFF5DCF7CDF9BAF64
-:1018F000BABFD98FF89F176E367E554E745E932E01
-:0C190000B23ED10EF01E000000000000FE
-:10190C0001140000090243000201008032090400A6
-:10191C00000102020000052400100104240200054D
-:10192C00240600010524010001070583030800FFBC
-:10193C0009040100020A00000007058102400000B2
-:10194C00070502024000000000C201000000080070
-:0C195C00690000004100000000000000D5
-:0400000300000615DE
+:10009000F81600005C000020540000200000000062
+:1000A00010B5C3699C07FCD403680224A343036012
+:1000B000C46901231C42FBD1046823430360036825
+:1000C000DC07FCD4C46901231C42FBD1C469DC40B9
+:1000D0001C42F7D1084B1A430260C3695A07FCD48B
+:1000E000C0239B0243608181C3699C07FCD40368E1
+:1000F00002221343036010BD04000040037EDA07B0
+:10010000FCD5018570470000027E01235107FBD515
+:10011000428B1A4207D1428BDA401A4203D1428BFA
+:1001200092081A4202D0034B01221A70008DC0B20D
+:100130007047C0467400002070B50368041C988B9B
+:100140001A1C0821FF32084228D0988B174D014312
+:10015000802099839872112353704021144B917120
+:1001600050715E68C0202E40800506435E605E6967
+:100170003540284358610F4818600F4818615D6882
+:100180000E4828408025AD02284358605868800BEF
+:100190008003586000235171237105E0137ADA0659
+:1001A00002D5201C00F0A0FA207970BDFFFFFF8F60
+:1001B0008C0100208C0000200C010020FF3F00F08B
+:1001C000002303714371044B016083600B780222AA
+:1001D00013430B707047C0463901000038B5364BE9
+:1001E0002021DA6901200A43DA61344B06241A78A7
+:1001F00002431A70324B0F22197891431970197803
+:10020000214319702F490C782043087019780A404F
+:100210001A701A7860210A431A702B4B2B4A5A80A5
+:100220005A7852B2002AFBDB294B01211A780A4383
+:100230001A709A78D107FCD426480268510B1F2205
+:100240001140914200D1052111408C011D8D2249A0
+:100250002940214319850468A10C0A401F2A00D1B6
+:100260001D221C8D1F210A408C4322431A850268DF
+:100270000721D20D0A408A4200D103220A40188D7C
+:100280001103164A02400A431A8519787F220A4050
+:100290001A701A78042112480A431A7058621A898F
+:1002A0000C218A431A811A8901218A431A8100216B
+:1002B000802201F0B6F838BD0004004058440041E7
+:1002C0003C44004159440041000C004006400000FD
+:1002D00000500041246080003FF8FFFFFF8FFFFFC8
+:1002E0008C010020F7B5141C234A5F0101971D1CE7
+:1002F000D319061C5869271C4000400F03301033E7
+:10030000C74006D00F1C8022596812060A435A6063
+:1003100009E02F1C7B1E9F41184BBF01FF18381CA2
+:10032000221C01F075F8019913480835421817612D
+:10033000131C5269A104920B890C92030A435A615F
+:1003400059690F4A02200A405A616B01F318D979A2
+:10035000032211400143D8799043021C0A43DA7109
+:100360005979802252420A435A716B01F318DB79A2
+:100370009A07FAD5201CFEBD8C0100200C0100203C
+:10038000FF3F00F0F8B51E4E041C3378151C002BFF
+:1003900012D11C4B1C4A1A645A6C920B92035A6479
+:1003A000586C1A4A02405A64A2235B00E25C402067
+:1003B0000243E254012333704827FF37E25D0123F3
+:1003C00013401AD00F4B5A6C9204920CAA4202D2DC
+:1003D0005D6CAD04AD0C081C2A1C0B4901F018F82B
+:1003E000E25D03231A4001210A43E15D99430B1C9E
+:1003F0001343E3550023337000E01D1C281CF8BD97
+:10040000750000208C010020CC000020FF3F00F090
+:10041000FF30827930239A43131C2022002900D117
+:1004200010221343837170470C4BFF305A6902212D
+:10043000920B92035A61027A03231A400A43017A0B
+:1004400099430B1C13430372827980235B4213434D
+:100450008371037A9A07FCD57047C0468C0100204F
+:1004600080235B421943C9B28172704770B5A023E3
+:1004700003225B00C254134B134A5C6CC02114402E
+:1004800089050C4346255C64FF35402444550F4DD7
+:1004900030261D6490256D0046555D6B154029433F
+:1004A000922559636D0080214155094D1D63B0258A
+:1004B0006D0044555C6F22405A67B2235B00C15403
+:1004C00070BDC0468C010020FFFFFF8FCC000020D4
+:1004D0004C01002030B5364A1E235168082099434C
+:1004E00002231943516033498A6902438A613248C1
+:1004F000324A9082908A03439382D3689807FCD54E
+:100500002F4B012018701878C40704D52C48407868
+:1005100040B20028F7DB01209860587840B20028EC
+:10052000FBDB284C26484460587840B20028FBDBAF
+:1005300082242348E4014480587840B20028FBDB41
+:10054000908C8024A0439084D068C506FCD51E4CB6
+:100550001A48C462D4681948E506FBD5848C1B4D43
+:100560002C438484D4681548E506FBD5848C022589
+:100570002C438484D0680406FCD51048C068450626
+:10058000F8D5D068C406FCD500229A605A7852B2D9
+:10059000002AFBDB0E480A4A50605A7852B2002A01
+:1005A000FBDB00230B724B728B72CB7230BDC046EB
+:1005B00000400041000400400C060000000800401C
+:1005C000000C004001050100B805FF7D040A000091
+:1005D000000703000EBEFEE70DBEFEE705BEFEE708
+:1005E00002BEFEE701BEFEE70E4A0F4838B5824262
+:1005F00004D10E4A0E4B93420ED10AE00D4C9442A8
+:10060000F7D00023D1188842F3D9E55804330D60A0
+:10061000F8E700F011F804E09342FAD2002102C397
+:10062000FAE7FEE7000000205800002098030020B1
+:1006300058000020FC16000010B5244B0022197849
+:1006400001231940224B0AD11868224A904201D155
+:10065000196014E01A60204A013A002AFCD11A609D
+:100660001E4B1968181C4A1C09D0FF22134206D1E0
+:1006700081F3088893431A4A936043681847FFF749
+:1006800029FF62B600F0F2FC00F0C8F9041CA36870
+:10069000201C9847134B002801D001221A701A78A9
+:1006A000002A05D0002000F035FA00F091FAFCE7AE
+:1006B0001B78002BEBD100F04DFD0028E7D0012086
+:1006C00000F028FA00F084FAFCE7C0463804004045
+:1006D000FC7F00203581730748E8010000200000FE
+:1006E00000ED00E076000020F8B50468051C201C31
+:1006F000FF30037AB64A10210B430372B54F1378CB
+:10070000B5493B705378B54E0B7093783380D178F0
+:10071000338809020B4333801179B14B1980517929
+:100720001F8809020F431F809779AE490F80D27945
+:100730000F8812023A430A8040224271A648A54F10
+:1007400002783878A84F12020243181CBA4200D12E
+:1007500099E01EDC802149008A4200D158E107DC83
+:10076000812A6AD0822A6ED0802A00D050E164E0CB
+:1007700081235B009A4200D1AFE000DA23E1C0237D
+:100780009B009A4200D143E1984B9A4200D11AE172
+:100790003EE190231B019A4242D015DCD023DB00BE
+:1007A0009A4222D088231B019A4242D0A023DB0028
+:1007B0009A4200D02CE1201CFFF736FE31882868D1
+:1007C00089B2FFF74DFE27E1894B9A4200D1FAE04A
+:1007D00000DC1DE1874B9A4200D1E8E0864B9A424B
+:1007E00000D015E133886B71EDE033881B0A012BD3
+:1007F00008D10B8812222868934201D80A8892B245
+:100800007E49DCE033881B0A022B00D000E10B8814
+:1008100043222868934201D80A8892B27849CEE0F0
+:100820003388201C2B71FFF7FFFD201CFFF71EFEF5
+:10083000F2E0291C01C90122C1E0724900230B80AA
+:1008400028680222BCE06F4900220A8018885022E2
+:1008500010406D4A10701E880F2030401880188894
+:10086000032800D9D4E012781B8808335B01E41810
+:10087000A379002A01D09B0600E0DB06DB0F0B808A
+:10088000286802229BE019887F2291435E4AC9B200
+:10089000117018880F21014019803188002900D07B
+:1008A000B6E01988002900D1B2E01988032900D9DF
+:1008B000AEE012781B8808335B01E318002A05D0EC
+:1008C0005A7930218A4320210A4304E05A793021A1
+:1008D0008A43102002435A7175E002887F239A43AD
+:1008E000494BD2B21A7001880F220A400280328826
+:1008F000002A00D08CE00288002A00D188E002881B
+:10090000032A00D984E01B78002B27D00388083302
+:100910005B01E3189B79990655D50388302108338C
+:100920005B01E3181A798A4320210A431A7103886C
+:1009300008335B01E318DB795A0644D5038860214C
+:1009400008335B01E318DA798A4340210A43DA71FC
+:100950000388022208335B01E31826E0038808338A
+:100960005B01E3189B79DF062DD50388302108331E
+:100970005B01E3181A798A4310210A431A7103882C
+:1009800008335B01E318DB7999061CD503886021E5
+:1009900008335B01E318DA798A4320210A43DA71CC
+:1009A0000388012208335B01E3181A710BE00B88FE
+:1009B00008222868934201D80A8892B2134900237A
+:1009C000FFF790FC28E0201CFFF72EFD24E0C04636
+:1009D0008C0000208100002077000020780000209B
+:1009E0007C0000207E0000200203000001030000C4
+:1009F00021200000A1210000212200004C14000051
+:100A0000000000207A000020800000204400002028
+:100A1000201C0121FFF7FCFCF8BDC04610B5054BBA
+:100A2000054C2360FFF7DAFB201C2168FFF7C8FBA9
+:100A3000201C10BD005000410C02002007B5054BE2
+:100A40000122019001A91868131CFFF74BFC01203B
+:100A50000EBDC0460C02002013B5054B6C46073492
+:100A60001868211C0122FFF78DFC207816BDC046B6
+:100A70000C02002010B5074C201CFFF75DFB031C87
+:100A80000020834205D022684823FF33D05C012335
+:100A9000184010BD0C02002010B5054A0C1C031CA8
+:100AA000191C10680123221CFFF71CFC201C10BD20
+:100AB0000C02002070B5084C061C201C0D1CFFF712
+:100AC0003BFB0023984205D02068311C2A1CFFF70D
+:100AD00059FC031C181C70BD0C020020F8B50C4C0E
+:100AE000051C201C0E1CFFF727FB0023271C341CB1
+:100AF00098420AD0002C07D0291C221C3868FFF726
+:100B000041FC241A2D18F5E7331C181CF8BDC0460B
+:100B10000C020020012805D1054B064A1A60064B3D
+:100B2000187004E0002802D1044A014B1A60704793
+:100B30007C0200208014000089000020CC140000FA
+:100B400030B51A4B85B01B78002B29D0042901D170
+:100B5000026804E0022901D1028800E0027849001D
+:100B600004A843180B3B5C1AA3420BD00F20104083
+:100B7000092802D83025284300E0373018701209C0
+:100B8000013BF1E701A830230370782343700A2268
+:100B900043189A700D22DA70054B04311B6801E08E
+:100BA000034B1B68DB68984705B030BD8800002008
+:100BB0007C02002072B6EFF30883044A13600368D6
+:100BC00083F30888436818477047C04680020020B6
+:100BD000F0B58FB006A9CD4A0B1C31CA31C351CA3A
+:100BE00051C360CA60C3CA4CCA48A3687A255B0374
+:100BF0005B0F9B005B58C8490360A26892B25343E5
+:100C00000A60C649C64A0B6000231360C54B1D70BD
+:100C1000C54BC64D1B68281C1B6940219847C44B17
+:100C200000221860C34B1D60C34BC34DC04F1A60F8
+:100C3000286839688842EBD2BE4B1B681A78FF2AB5
+:100C400000D1F7E1232A00D0CEE1BC4E3378002B4F
+:100C500005D0B54BBA481B680221DB689847B14BF9
+:100C60001B78532B38D13B682A6893421ED9B14870
+:100C700001322A609A1AB34B01681B680131016086
+:100C8000B14E9A4201D2326000E03360A44832682B
+:100C90000068029000F0BCFB336829685A182A608B
+:100CA000A44A1668F1181160A84A13702B68013B1A
+:100CB0002B60A04B1A68013A1A60A44BA14A1B781A
+:100CC00011688B4206D2984A954812680068C91A82
+:100CD00092699047C04676E1522B07D1904A924BD9
+:100CE00010681B68974A5B6911686BE14F2B05D14F
+:100CF0008B4B944A1B6812681A7064E1482B05D12B
+:100D0000874B904A1B6812681A805CE1572B05D10B
+:100D1000834B8C4A1B6812681A6054E16F2B03D115
+:100D20007F4B0121186807E0682B08D17C4B854870
+:100D30001B6802211B880360FFF702FF43E1772B4A
+:100D400006D1774B7F481B6804211B680360F3E7DB
+:100D5000472B13D17B4B1868FFF72CFF7C4B1B688C
+:100D600083F3088862B67B4B1B78002B00D12AE105
+:100D70006D4B06201B681B68984724E1542B04D157
+:100D800001233370684B1B685CE04E2B0BD133782A
+:100D9000002B05D1644B6A481B680221DB68984729
+:100DA000002333700FE1562B50D15F4D01212B688A
+:100DB0006948DB6898472B680321DB6867489847D8
+:100DC000674E2B68301CDB68012198472B680D218A
+:100DD000DB68644898472B68301CDB680121984722
+:100DE000544F614B544E3B60002333603A1C311C1E
+:100DF0001368581C10601B780393002B03D00B68FA
+:100E000001330B60F4E72B683168DB68564898477C
+:100E10002B685348DB68012198470398306053489A
+:100E20003860444A1368591C11601A78424B002AF2
+:100E300003D01A6801321A60F3E72A681968D36888
+:100E400098472B68DB683E480221BBE03D4A582B9F
+:100E500015D1304E314D366813682A68B10093427F
+:100E600008D25808E06142482080207DC507FCD5A3
+:100E70005B18F4E72C4B3F481B68DB68A1E0592B5B
+:100E800033D11268264B3C49002A02D11B680B6003
+:100E900026E00868196863688025AB4392086360A0
+:100EA000002A1DD0354B2380237DDE07FCD500238F
+:100EB000184D2D680095AD08AB4202D3304D25800A
+:100EC00006E09342FAD09D00465901334E51EFE7B8
+:100ED000257DEE07FCD59D0049194019D21ADFE7A0
+:100EE000114B28481B68DB686BE05A2B6BD10C4B0D
+:100EF00017681D680026EF19BD4245D02878311CBF
+:100F000000F04AF90135061CF6E7C04660140000FF
+:100F100000400041340200202C0200202802002062
+:100F200078020020240200207C02002038020020E9
+:100F30001C02002020020020300200208800002037
+:100F4000C014000084020020880200201802002043
+:100F500080020020890000209C140000C5140000BD
+:100F60009E140000E8140000A0140000AC1400005F
+:100F700002A5FFFFB51400008400002044A5FFFF78
+:100F800004A5FFFFB91400002E4D2F482B68012146
+:100F9000DB68984707230F223240111C3609303195
+:100FA000092A00DD07311020C0186A468154013B30
+:100FB000F1D22B6804A8DB68082198472B682348E6
+:100FC000DB6803219847224D7A232B70214B0022A6
+:100FD0001A60214B1B7893422CD01A4B01211B68BD
+:100FE0001E48DB68984725E0111C3039C8B2194B00
+:100FF000092804D81E683201114319601AE0111C37
+:101000004139052903D81868373A010106E0111C57
+:101010006139052904D81D68573A29010A4308E0B7
+:101020002C2A03D10E4A1E68166001E008490A7096
+:1010300000221A600B4B1A6801321A600A4B1A68B8
+:101040000132F2E57C020020BD140000BF14000054
+:10105000240200208402002088000020C314000025
+:1010600078020020300200202002002010B51C4B26
+:1010700001201A78022402431A701A4B0F221978A1
+:101080009143197019782143197017490C7820433E
+:10109000087019780A401A701A7820210A431A70C9
+:1010A000124B04211A6A0A431A62114B114A5A80E0
+:1010B0005A7852B2002AFBDBC4220F480F49920330
+:1010C000FEF7EEFF0E4A002313700E4A13700E4A0D
+:1010D00013700E4A13700E4A13700E4A137010BD2F
+:1010E0004A440041354400414B4400410004004063
+:1010F000000C0040144000000008004204C500003D
+:101100008C020020130300208D020020900200209A
+:10111000140300201103002008B5C1B20248FEF7F5
+:10112000EDFF012008BDC04600080042024B187EBA
+:101130004007C00F7047C0460008004208B5FFF7DF
+:10114000F5FF0028FBD00248FEF7DEFF08BDC046D1
+:101150000008004208B5FFF7E9FF0023984205D0D8
+:10116000FFF7ECFF031C233B5A425341181C08BDF8
+:1011700070B5041C0D1C4618B44204D02078FFF74B
+:10118000CBFF0134F8E7281C70BD10B5041CFFF735
+:10119000D5FF2070012010BD0B0A5840034B4000C2
+:1011A000C05A0902484080B27047C046F614000099
+:1011B000F7B50024051C0F1C261CBC4220D0FFF7ED
+:1011C000BDFF114BC0B21B780190002B1AD1311C0E
+:1011D000FFF7E2FF0D4B061C1A88002A04D10C4AC7
+:1011E00011782A1C002907D001996A1C2970802FC8
+:1011F00002D11988013919800134A4B2151CDCE729
+:10120000301C00E00120FEBD110300208E020020F2
+:1012100012030020F0B53E4E85B0002203900C1C56
+:1012200032703C4B914201D1012201E03A490C80DD
+:101230001A707F231C4201D080349C43FFF77EFF4D
+:101240003378C0B2002B07D000253570FFF776FF4A
+:101250003378C0B2AB4236D1432803D0712853D083
+:101260001528EBD1012300930120FFF755FF0098CB
+:10127000FFF752FF00998025C843C0B2FFF74CFF2B
+:10128000039B00270293244A1388002B1DD1214978
+:1012900001930978002918D10198FFF73DFF391C07
+:1012A0000198FFF779FF013D071C002DEBD1000AE3
+:1012B000C0B2FFF731FFF8B2FFF72EFFFFF73EFF96
+:1012C0003378002B0AD035701FE00299013B097872
+:1012D0001380029B019101330293DDE7C0B206281F
+:1012E00007D1009B03990133DBB280310093803C2E
+:1012F0000391002CB8D10420FFF70EFFFFF71EFF6B
+:10130000044B01251C7000E00025281C05B0F0BD31
+:1013100011030020120300208E020020F0B5384C8B
+:1013200087B0002301902370994201D1012301E08D
+:10133000344A1180344A642613704320FFF7ECFED0
+:10134000324FFFF7F3FE002803D1002F03D0013FF7
+:10135000F7E7002F03D1013E002EEED14DE001252D
+:10136000FFF7ECFE2378002B38D1C0B202900128A1
+:1013700005D004283DD10620FFF7CEFE39E005AEAA
+:101380000221301CFFF714FF01988021FFF710FFA6
+:1013900023780390002B18D1FFF7D0FE0702FFF748
+:1013A000CDFEBFB223783F18BFB2012B0DD0039BF7
+:1013B0009F4207D13378AB4204D1EB437278DBB262
+:1013C0009A4204D01820FFF7A7FE002303E006206E
+:1013D000FFF7A2FE029B2278002A02D00026267088
+:1013E0000BE0012B05D1019A6B1C8032DDB201921A
+:1013F000B6E7054A002313700126301C07B0F0BD84
+:10140000110300208E0200201203002000350C0082
+:1014100010B50023934203D0CC5CC4540133F9E7E8
+:1014200010BD031C8218934202D019700133FAE7F1
+:1014300070470000F8B5C046F8BC08BC9E4670472F
+:10144000F8B5C046F8BC08BC9E46704712010002C1
+:101450000200004041234D00000200000001000096
+:101460000800000010000000200000004000000004
+:1014700080000000000100000002000000040000E5
+:10148000191100003D1100002D1100007111000024
+:101490008B110000151200001D13000076002000C3
+:1014A0004F637420313020323031350031353A35D8
+:1014B000373A343500580A0D00590A0D005A0023F6
+:1014C0000A0D003E00322E30000000003D0A0000F0
+:1014D000590A0000750A0000990A0000B50A0000C8
+:1014E000990A0000DD0A00005B41726475696E6F45
+:1014F0003A58595A5D000000211042206330844060
+:10150000A550C660E770088129914AA16BB18CC1D2
+:10151000ADD1CEE1EFF13112100273325222B55249
+:101520009442F772D662399318837BB35AA3BDD322
+:101530009CC3FFF3DEE36224433420040114E66419
+:10154000C774A44485546AA54BB528850995EEE572
+:10155000CFF5ACC58DD55336722611163006D77629
+:10156000F6669556B4465BB77AA719973887DFF7C2
+:10157000FEE79DD7BCC7C448E5588668A7784008F1
+:10158000611802282338CCC9EDD98EE9AFF9488912
+:1015900069990AA92BB9F55AD44AB77A966A711A89
+:1015A000500A333A122AFDDBDCCBBFFB9EEB799B62
+:1015B000588B3BBB1AABA66C877CE44CC55C222CD9
+:1015C000033C600C411CAEED8FFDECCDCDDD2AADB2
+:1015D0000BBD688D499D977EB66ED55EF44E133E69
+:1015E000322E511E700E9FFFBEEFDDDFFCCF1BBF02
+:1015F0003AAF599F788F8891A981CAB1EBA10CD1DC
+:101600002DC14EF16FE18010A100C230E3200450E3
+:10161000254046706760B9839893FBA3DAB33DC356
+:101620001CD37FE35EF3B1029012F322D232354233
+:10163000145277625672EAB5CBA5A89589856EF5E6
+:101640004FE52CD50DC5E234C324A0148104667483
+:10165000476424540544DBA7FAB79987B8975FE736
+:101660007EF71DC73CD7D326F2369106B0165766D3
+:101670007676154634564CD96DC90EF92FE9C899BE
+:10168000E9898AB9ABA94458654806782768C01823
+:10169000E1088238A3287DCB5CDB3FEB1EFBF98B96
+:1016A000D89BBBAB9ABB754A545A376A167AF10A73
+:1016B000D01AB32A923A2EFD0FED6CDD4DCDAABDA6
+:1016C0008BADE89DC98D267C076C645C454CA23CC3
+:1016D000832CE01CC10C1FEF3EFF5DCF7CDF9BAF76
+:1016E000BABFD98FF89F176E367E554E745E932E13
+:0C16F000B23ED10EF01E00000000000011
+:1016FC0009024300020100803209040000010202C9
+:10170C000000052400100104240200052406000139
+:10171C000524010001070583030800FF09040100EB
+:10172C00020A0000000705810240000007050202C2
+:10173C004000000000C20100000008006900000029
+:08174C00410000000000000054
+:04000003000005E90B
 :00000001FF
diff --git a/bootloaders/zero/samd21_sam_ba_genuino.bin b/bootloaders/zero/samd21_sam_ba_genuino.bin
old mode 100755
new mode 100644
index 35b766107..47cd3cf05
Binary files a/bootloaders/zero/samd21_sam_ba_genuino.bin and b/bootloaders/zero/samd21_sam_ba_genuino.bin differ
diff --git a/bootloaders/zero/samd21_sam_ba_genuino.hex b/bootloaders/zero/samd21_sam_ba_genuino.hex
index 84119520f..7e45320b7 100644
--- a/bootloaders/zero/samd21_sam_ba_genuino.hex
+++ b/bootloaders/zero/samd21_sam_ba_genuino.hex
@@ -1,409 +1,376 @@
-:10000000FC7F002015060000050600000906000020
+:10000000FC7F0020E9050000D5050000D9050000AF
 :1000100000000000000000000000000000000000E0
-:100020000000000000000000000000000D060000BD
-:10003000000000000000000011060000650700003D
+:10002000000000000000000000000000DD050000EE
+:100030000000000000000000E1050000E5050000F0
 :1000400010B5064C2378002B07D1054B002B02D0AE
-:10005000044800E000BF0123237010BD5C000020B5
-:10006000000000000819000008B5084B002B03D061
+:10005000044800E000BF0123237010BD58000020B9
+:1000600000000000F816000008B5084B002B03D074
 :100070000748084900E000BF07480368002B03D089
 :10008000064B002B00D0984708BDC046000000007A
-:100090000819000060000020580000200000000047
-:1000A000154A164B1178002909D115491878097895
-:1000B0004118C9B21970802012498002C8611178B4
-:1000C0000131C9B211701978F02902D819780929BB
-:1000D00009D80B4908784042C0B2087018780978EE
-:1000E0004118C9B2197012781B789A4203D1802244
-:1000F000044B9202DA617047780000200100002072
-:10010000000000200044004110B5C3699C07FCD4E6
-:1001100003680224A3430360C46901231C42FBD18A
-:100120000468234303600368DC07FCD4C46901232B
-:100130001C42FBD1C469DC401C42F7D1084B1A4376
-:100140000260C3695A07FCD4C0239B0243608181CB
-:10015000C3699C07FCD4036802221343036010BDEB
-:1001600004000040037EDA07FCD5018570470000DB
-:10017000027E01235107FBD5428B1A4207D1428BE5
-:10018000DA401A4203D1428B92081A4202D0034B42
-:1001900001221A70008DC0B27047C046790000205D
-:1001A00070B50368041C988B1A1C0821FF320842A2
-:1001B00026D0802099839872112353704021144BCC
-:1001C000917150715E68134DC0202E40800506432A
-:1001D0005E605E693540284358610F4818600F48DB
-:1001E00018615D680E4828408025AD02284358609C
-:1001F0005868800B8003586000235171237105E01B
-:10020000137ADA0602D5201C00F0E6FA207970BDD8
-:1002100098010020FFFFFF8F9800002018010020A8
-:10022000FF3F00F0002303714371044B01608360C2
-:100230000B78022213430B707047C046A1010000E7
-:1002400038B5364B2021DA6901200A43DA61344B94
-:1002500006241A7802431A70324B0F221978914300
-:1002600019701978214319702F490C7820430870B0
-:1002700019780A401A701A7860210A431A702B4BB9
-:100280002B4A5A805A7852B2002AFBDB294B0121B3
-:100290001A780A431A709A78D107FCD42648026863
-:1002A000510B1F221140914200D1052111408C01B8
-:1002B0001D8D22492940214319850468A10C0A405B
-:1002C0001F2A00D11D221C8D1F210A408C4322436E
-:1002D0001A8502680721D20D0A408A4200D1032202
-:1002E0000A40188D1103164A02400A431A851978EC
-:1002F0007F220A401A701A78042112480A431A70A1
-:1003000058621A890C218A431A811A8901218A4369
-:100310001A810021802201F076F938BD00040040E6
-:10032000584400413C44004159440041000C004005
-:100330000640000000500041246080003FF8FFFFAD
-:10034000FF8FFFFF98010020F7B5141C1F4A5F01C3
-:1003500001971D1CD319061C5869271C4000400F2B
-:1003600003301033C74006D00F1C80225968120694
-:100370000A435A6009E02F1C7B1E9F41144BBF01AA
-:10038000FF18381C221C01F035F901990F48083577
-:1003900042181761131C5269A104920B890C920335
-:1003A0000A435A6159690B4A0A405A616B01F318B2
-:1003B0000222DA715979802252420A435A716B0142
-:1003C000F318DB799A07FAD5201CFEBD98010020AE
-:1003D00018010020FF3F00F0F8B51A4E051C3378D5
-:1003E000141C002B12D1184B184A1A645A6C920B29
-:1003F00092035A64586C164A02405A64A2235B0066
-:10040000EA5C40200243EA54012333704827FF3757
-:10041000EA5D0123134012D00B4B5A6C9204920CEC
-:10042000A24202D25C6CA404A40C081C221C074942
-:1004300001F0E0F80123EB550023337000E01C1CB1
-:10044000201CF8BD7A00002098010020D800002070
-:10045000FF3F00F0FF3083792022002900D11022D5
-:100460001343837170470000084BFF305A69920BA9
-:1004700092035A6102230372827980235B42134301
-:100480008371037A9A07FCD57047C0469801002013
-:1004900080235B421943C9B28172704770B5A023B3
-:1004A00003225B00C254134B134A5C6CC0211440FE
-:1004B00089050C4346255C64FF35402444550F4DA7
-:1004C00030261D6490256D0046555D6B154029430F
-:1004D000922559636D0080214155094D1D63B0255A
-:1004E0006D0044555C6F22405A67B2235B00C154D3
-:1004F00070BDC04698010020FFFFFF8FD80000208C
-:100500005801002030B5364A1E235168082099430F
-:1005100002231943516033498A6902438A61324890
-:10052000324A9082908A03439382D3689807FCD51D
-:100530002F4B012018701878C40704D52C48407838
-:1005400040B20028F7DB01209860587840B20028BC
-:10055000FBDB284C26484460587840B20028FBDB7F
-:1005600082242348E4014480587840B20028FBDB11
-:10057000908C8024A0439084D068C506FCD51E4C86
-:100580001A48C462D4681948E506FBD5848C1B4D13
-:100590002C438484D4681548E506FBD5848C022559
-:1005A0002C438484D0680406FCD51048C0684506F6
-:1005B000F8D5D068C406FCD500229A605A7852B2A9
-:1005C000002AFBDB0E480A4A50605A7852B2002AD1
-:1005D000FBDB00230B724B728B72CB7230BDC046BB
-:1005E00000400041000400400C06000000080040EC
-:1005F000000C004001050100B805FF7D040A000061
-:10060000000703000EBEFEE70DBEFEE705BEFEE7D7
-:1006100002BEFEE70E4A0F4838B5824204D10E4AA8
-:100620000E4B93420ED10AE00D4C9442F7D00023BA
-:10063000D1188842F3D9E55804330D60F8E700F08B
-:1006400011F804E09342FAD2002102C3FAE7FEE770
-:10065000000000205C000020A40300205C000020BB
-:100660000C190000334A38B51368141C01331ED02E
-:10067000D1B200291BD1304B1878012318402F4BE1
-:100680000AD11D682E498D4201D118600FE0196012
-:100690002C4901390029FCD11960236883F30888AB
-:1006A000FF239A43284B9A60224B5B681847FFF759
-:1006B00029FF62B600F0CCFD00F05AF8234B8022EF
-:1006C000920223499A6008220A602249041C0A60A7
-:1006D000802212059A609A611F4B204AC0215A60FD
-:1006E000194A0906106A0002000A01431162002239
-:1006F0009A6007221A60A368201C9847184B0028AC
-:1007000001D001221A701A78002A05D0002000F0CA
-:1007100093FA00F019FBFCE71B78002BEBD100F0FB
-:100720000BFE0028E7D0012000F086FA00F00CFB59
-:10073000FCE7C0460020000038040040FC7F002099
-:100740003581730748E8010000ED00E000440041F6
-:10075000884400419844004110E000E0E7030000B5
-:100760007B00002008B5FFF79BFC00F0C9FA08BD2C
-:1007700010B5054B054C2360FFF762FD201C216876
-:10078000FFF750FD201C10BD005000411802002052
-:1007900070B5051CC0B0081C161C0C1C00F03BFFFB
-:1007A00040006A460323023053701070760801231C
-:1007B000E218013A11785A00002906D1281C69462E
-:1007C0000023FFF7C1FD40B070BDB342F6DA6846C2
-:1007D00081520133ECE70000F7B5BA4A0468137898
-:1007E000B949271CFF37051C102038720B7053784D
-:1007F000B648B74E037093783380D17833880902B6
-:100800000B4333801179B34B198051791888090251
-:10081000084318809079B0490880D279088812027C
-:1008200002430A8040227A71A84F3A78A64F1202FA
-:1008300038780F1C0243A9488446181C624500D131
-:10084000C2E020DC802149008A4200D16EE109DC4F
-:10085000812A00D192E0822A00D195E0802A00D03E
-:1008600064E18BE081235B009A4200D1CFE000DAA3
-:1008700058E1C0239B009A4200D157E1984B9A421D
-:1008800000D14FE152E190231B019A4269D015DC5F
-:10089000D023DB009A4222D088231B019A4269D0E0
-:1008A000A023DB009A4200D040E1201CFFF7DCFDD2
-:1008B0003188286889B2FFF7EBFD3BE1894B9A420A
-:1008C00000D12FE100DC31E1874B9A4200D11DE1DC
-:1008D000864B9A4200D029E133886B7122E133883C
-:1008E0001B0A012B08D10B8812222868934201D8D9
-:1008F0000A8892B27E4911E133881B0A022B08D183
-:100900000B8843222868934201D80A8892B2794919
-:1009100004E133881B0A032B00D007E13388DBB2E4
-:10092000012B17D0002B07D0022B00D0FEE00A8845
-:100930002868D2B2704911E0042201A86F4900F082
-:1009400059FE3B8804222868934201D83A8892B223
-:1009500001A9E3E00A8828686949D2B2FFF718FFC5
-:10096000E8E03388201C2B71FFF77EFD201CFFF789
-:1009700095FDDFE0291C01C90122CFE06149002378
-:100980000B8028680222CAE05E4900220A8018888B
-:10099000502210405C4A10701E880F203040188092
-:1009A0001888032800D9C1E012781B8808335B013E
-:1009B000E418A379002A01D09B0600E0DB06DB0FD8
-:1009C0000B8028680222A9E019887F2291434E4AB1
-:1009D000C9B2117018880F2101401980318800298F
-:1009E00000D0A3E01988002900D19FE019880329CD
-:1009F00000D99BE012781B8808335B01E318002ABA
-:100A000002D020225A718DE0102159718AE00288AB
-:100A10007F239A433C4BD2B21A7001880F220A40BE
-:100A200002803288002A00D080E00288002A00D1AB
-:100A30007CE00288032A00D978E01B78002B1FD0C5
-:100A4000038808335B01E3189B799A066AD503880B
-:100A5000202208335B01E3181A71038808335B0115
-:100A6000E318DB795F065DD50388402208335B011C
-:100A7000E318DA710388022208335B01E3181EE0F1
-:100A8000038808335B01E3189B79D9064AD50388AC
-:100A9000102208335B01E3181A71038808335B01E5
-:100AA000E318DB799A063DD50388202208335B01E1
-:100AB000E318DA710388012208335B01E3181A7125
-:100AC00030E0C046980000207D0000208200002019
-:100AD0008400002086000020800000200203000027
-:100AE0000103000021200000A121000021220000BC
-:100AF0005C160000040000204C1600003C160000AC
-:100B0000401600007E0000207C0000200B88082298
-:100B10002868934201D80A8892B207490023FFF758
-:100B200013FC07E0201CFFF79FFC03E0201C0121C1
-:100B3000FFF790FCF7BDC0464800002007B5054B05
-:100B40000122019001A91868131CFFF7FDFB012089
-:100B50000EBDC0461802002013B5054B6C46073485
-:100B60001868211C0122FFF737FC207816BDC0460B
-:100B70001802002010B5074C201CFFF711FB031CC6
-:100B80000020834205D022684823FF33D05C012334
-:100B9000184010BD1802002010B5054A0C1C031C9B
-:100BA000191C10680123221CFFF7CEFB201C10BD6E
-:100BB0001802002070B5084C061C201C0D1CFFF705
-:100BC000EFFA0023984205D02068311C2A1CFFF759
-:100BD00003FC031C181C70BD18020020F8B50C4C57
-:100BE000051C201C0E1CFFF7DBFA0023271C341CFD
-:100BF00098420AD0002C07D0291C221C3868FFF725
-:100C0000EBFB241A2D18F5E7331C181CF8BDC04661
-:100C10001802002008B5031C081C111C9847044B3F
-:100C2000802212055A61034B64221A8008BDC04617
-:100C3000004400418C000020012805D1054B064AE4
-:100C40001A60064B187004E0002802D1044A014BD8
-:100C50001A6070478802002090160000940000205F
-:100C6000DC16000030B50A1C1C4985B00978031C4D
-:100C700000292AD0042A01D1006804E0022A01D107
-:100C8000008800E00078520004A98B180B3B9C1AE6
-:100C9000A3420BD00F210140092902D83025294356
-:100CA00000E0373119700009013BF1E701A9302359
-:100CB0000B7078234B700A208B1898700D20D87019
-:100CC000074B04321B68D86803E005490968C86807
-:100CD000191CFFF79FFF05B030BDC04688000020FB
-:100CE0008802002072B6EFF30883044A1360036899
-:100CF00083F30888436818477047C0468C02002079
-:100D00000D4B1A88002A09D01A88013A92B21A802B
-:100D1000002A03D18022094B12059A61084B1A88D8
-:100D2000002A08D01A88013A92B21A80002A02D109
-:100D3000044B08221A6070478C00002000440041D8
-:100D40008A00002098440041F0B591B008A9CE4A2D
-:100D50000B1C31CA31C351CA51C360CA60C3CB4BEB
-:100D6000CB489A687A255203520F92005258C949CB
-:100D700002609C68A4B262430C60C74900240A6008
-:100D8000C64A1460C64C2570C64CC74D2368281C43
-:100D90001B6940219847002805D0C44B08221A60DF
-:100DA000C34B64221A80C34B00221860C24B1D60E3
-:100DB000C24BC24DBF4F1A602A683B689A42E3D2C9
-:100DC000BD4B1B681A78FF2A00D120E2232A00D0ED
-:100DD000F7E1BB4E3378002B06D0B24BB9491B6804
-:100DE0000222D868FFF716FFAD4B1B78532B3FD17B
-:100DF0003B682A6893421ED9AF4801322A609A1A8A
-:100E0000B14B01681B6801310160B04E9A4201D2BA
-:100E1000326000E03360A14832680068049000F05E
-:100E2000E9FB336829685A182A60A34A1668F11842
-:100E30001160A74A13702B68013B2B609E4B1A6808
-:100E4000013A1A60A24BA04A1B7811688B420DD25E
-:100E500022689248C91A006892699047002805D014
-:100E6000924B08221A60924B64221A80C04696E187
-:100E7000522B0ED18948944A2368006811685B6937
-:100E800003909847934B802212055A616422924B3B
-:100E90000DE04F2B05D1814B8B4A1B6812681A70ED
-:100EA0007DE1482B05D17D4B874A1B6812681A806B
-:100EB00075E1572B05D1794B834A1B6812681A607C
-:100EC0006DE16F2B03D1754B0121186807E0682B8A
-:100ED00008D1724B7C481B6802211B880360FFF716
-:100EE000C1FE5CE1772B06D16C4B77481B6804216F
-:100EF0001B680360F3E7472B13D1734B1868FFF7A8
-:100F0000F1FE764B1B6883F3088862B6744B1B783E
-:100F1000002B00D143E1634B06201B681B689847F8
-:100F20003DE1542B04D1012333705E4B1B6864E018
-:100F30004E2B0CD13378002B06D15A4B61491B68DC
-:100F40000222D868FFF766FE0023337027E1562B94
-:100F500057D123686349D8680122FFF75BFE2368F5
-:100F60006149D8680322FFF755FE604D2368291CAC
-:100F7000D8680122FFF74EFE23685D49D8680D222C
-:100F8000FFF748FE2368291CD8680122FFF742FEBC
-:100F9000494F4A4D5749002339602B603A1C281CA1
-:100FA00013685E1C16601B780593002B03D0036842
-:100FB00001330360F4E73B4E2A683368D868FFF7D3
-:100FC00029FE33684949D8680122FFF723FE0599B5
-:100FD000296049493960384A1368581C10601B78E9
-:100FE000002B04D0354B1A6801321A60F3E73368DE
-:100FF0002A68D868FFF70EFE3368D86831490222A4
-:10100000CBE0314A582B17D1214E234D3668136857
-:101010002A68B10093420AD21C4D5808E86137484B
-:1010200028801A4D287DC607FBD55B18F2E71D4BBB
-:1010300033491B68D868AFE0592B00D07DE01268B7
-:10104000164B3049002A02D11B680B6070E00F4D2F
-:10105000086819686B680D4E8025AB439208736071
-:10106000002A65D0284B094D2B80084E337DDD07C3
-:10107000FBD50023064D2D680195AD08AB4247D343
-:10108000224D024E35804AE07016000000400041BB
-:101090004002002038020020340200208402002098
-:1010A00030020020880200204402002094440041C5
-:1010B0008A000020280200202C0200203C02002090
-:1010C00088000020D016000090020020940200202A
-:1010D00024020020004400418C0000208C020020EB
-:1010E00094000020AC160000D5160000AE160000DB
-:1010F000F8160000B0160000BC16000002A5FFFFA5
-:10110000C51600009000002044A5FFFF04A5FFFFC6
-:101110009342B5D09D00465901334E51AAE7404E47
-:10112000357DEE07FBD59D0049194019D21A97E786
-:101130003C4B3D491B68D8682EE05A2B2FD13B4BC6
-:1011400017681D680026EF19BD4206D02878311CAB
-:1011500000F014F90135061CF6E7324B34491B68E0
-:101160000122D868FFF756FD07230F223240111CD9
-:1011700036093031092A00DD07311820C0186A46C7
-:101180008154013BF1D2236806A9D8680822FFF7F1
-:1011900041FD23682749D8680322FFF73BFD264B12
-:1011A0007A221A70254B00221A60254B1B78934235
-:1011B0002DD01C4B23491B680122D868FFF72AFD5C
-:1011C00025E0111C3039C8B21C4B092804D81D6811
-:1011D0002A01114319601AE0111C4139052903D86D
-:1011E0001E68373A310106E0111C6139052904D81F
-:1011F0001868573A01010A4308E02C2A03D10B4A28
-:101200001968116001E00C490A7000221A600E4B47
-:101210001A6801321A600D4B1A680132C9E5C046DE
-:101220000040004188020020C9160000840200200E
-:10123000CD160000CF1600003002002090020020E2
-:1012400088000020D31600003C0200202C02002061
-:1012500010B51C4B01201A78022402431A701A4B55
-:101260000F22197891431970197821431970174981
-:101270000C782043087019780A401A701A782021D7
-:101280000A431A70124B04211A6A0A431A62114B5C
-:10129000114A5A805A7852B2002AFBDBC4220F4806
-:1012A0000F499203FEF730FF0E4A002313700E4AD7
-:1012B00013700E4A13700E4A13700E4A13700E4AC2
-:1012C000137010BD4A440041354400414B44004175
-:1012D00000040040000C00401440000000080042E0
-:1012E0002AF60000980200201F0300209902002027
-:1012F0009C020020200300201D03002008B5C1B27D
-:101300000248FEF72FFF012008BDC046000800423A
-:10131000024B187E4007C00F7047C04600080042CD
-:1013200008B5FFF7F5FF0028FBD00248FEF720FFC5
-:1013300008BDC0460008004208B5FFF7E9FF0023DA
-:10134000984205D0FFF7ECFF031C233B5A42534160
-:10135000181C08BD70B5041C0D1C4618B44204D0FE
-:101360002078FFF7CBFF0134F8E7281C70BD10B5DB
-:10137000041CFFF7D5FF2070012010BD0B0A584058
-:10138000034B4000C05A0902484080B27047C04633
-:1013900006170000F7B50024051C0F1C261CBC42D4
-:1013A00020D0FFF7BDFF114BC0B21B780190002B7E
-:1013B0001AD1311CFFF7E2FF0D4B061C1A88002AD8
-:1013C00004D10C4A11782A1C002907D001996A1C03
-:1013D0002970802F02D11988013919800134A4B2F3
-:1013E000151CDCE7301C00E00120FEBD1D030020C1
-:1013F0009A0200201E030020F0B53E4E85B0002268
-:1014000003900C1C32703C4B914201D1012201E04F
-:101410003A490C801A707F231C4201D080349C43CF
-:10142000FFF77EFF3378C0B2002B07D00025357060
-:10143000FFF776FF3378C0B2AB4236D1432803D0F2
-:10144000712853D01528EBD1012300930120FFF719
-:1014500055FF0098FFF752FF00998025C843C0B29E
-:10146000FFF74CFF039B00270293244A1388002BAD
-:101470001DD1214901930978002918D10198FFF75E
-:101480003DFF391C0198FFF779FF013D071C002D36
-:10149000EBD1000AC0B2FFF731FFF8B2FFF72EFF21
-:1014A000FFF73EFF3378002B0AD035701FE002991A
-:1014B000013B09781380029B019101330293DDE720
-:1014C000C0B2062807D1009B03990133DBB28031FB
-:1014D0000093803C0391002CB8D10420FFF70EFF4D
-:1014E000FFF71EFF044B01251C7000E00025281C9F
-:1014F00005B0F0BD1D0300201E0300209A0200204D
-:10150000F0B5384C87B0002301902370994201D187
-:10151000012301E0344A1180344A642613704320C9
-:10152000FFF7ECFE324FFFF7F3FE002803D1002F48
-:1015300003D0013FF7E7002F03D1013E002EEED18B
-:101540004DE00125FFF7ECFE2378002B38D1C0B227
-:101550000290012805D004283DD10620FFF7CEFED9
-:1015600039E005AE0221301CFFF714FF01988021FD
-:10157000FFF710FF23780390002B18D1FFF7D0FE60
-:101580000702FFF7CDFEBFB223783F18BFB2012B91
-:101590000DD0039B9F4207D13378AB4204D1EB437C
-:1015A0007278DBB29A4204D01820FFF7A7FE00231E
-:1015B00003E00620FFF7A2FE029B2278002A02D059
-:1015C000002626700BE0012B05D1019A6B1C80329E
-:1015D000DDB20192B6E7054A002313700126301CE4
-:1015E00007B0F0BD1D0300209A0200201E0300205A
-:1015F00000350C0010B50023934203D0CC5CC454DA
-:101600000133F9E710BD031C8218934202D0197010
-:101610000133FAE770470023C25C0133002AFBD193
-:10162000581E7047F8B5C046F8BC08BC9E467047C7
-:10163000F8B5C046F8BC08BC9E46704704030904D0
-:1016400041726475696E6F204C4C430047656E753E
-:10165000696E6F205A65726F00000000120100026F
-:101660000200004041234D0200020102000100007F
-:1016700008000000100000002000000040000000F2
-:1016800080000000000100000002000000040000D3
-:10169000FD1200002113000011130000551300007B
-:1016A0006F130000F9130000011500007600200000
-:1016B00044656320323020323031360031353A33E0
-:1016C000363A343100580A0D00590A0D005A0023E9
-:1016D0000A0D003E00322E30000000003D0B0000DD
-:1016E000590B0000750B0000990B0000B50B0000B2
-:1016F000990B0000DD0B00005B41726475696E6F31
-:101700003A58595A5D00000021104220633084404D
-:10171000A550C660E770088129914AA16BB18CC1C0
-:10172000ADD1CEE1EFF13112100273325222B55237
-:101730009442F772D662399318837BB35AA3BDD310
-:101740009CC3FFF3DEE36224433420040114E66407
-:10175000C774A44485546AA54BB528850995EEE560
-:10176000CFF5ACC58DD55336722611163006D77617
-:10177000F6669556B4465BB77AA719973887DFF7B0
-:10178000FEE79DD7BCC7C448E5588668A7784008DF
-:10179000611802282338CCC9EDD98EE9AFF9488900
-:1017A00069990AA92BB9F55AD44AB77A966A711A77
-:1017B000500A333A122AFDDBDCCBBFFB9EEB799B50
-:1017C000588B3BBB1AABA66C877CE44CC55C222CC7
-:1017D000033C600C411CAEED8FFDECCDCDDD2AADA0
-:1017E0000BBD688D499D977EB66ED55EF44E133E57
-:1017F000322E511E700E9FFFBEEFDDDFFCCF1BBFF0
-:101800003AAF599F788F8891A981CAB1EBA10CD1C9
-:101810002DC14EF16FE18010A100C230E3200450D1
-:10182000254046706760B9839893FBA3DAB33DC344
-:101830001CD37FE35EF3B1029012F322D232354221
-:10184000145277625672EAB5CBA5A89589856EF5D4
-:101850004FE52CD50DC5E234C324A0148104667471
-:10186000476424540544DBA7FAB79987B8975FE724
-:101870007EF71DC73CD7D326F2369106B0165766C1
-:101880007676154634564CD96DC90EF92FE9C899AC
-:10189000E9898AB9ABA94458654806782768C01811
-:1018A000E1088238A3287DCB5CDB3FEB1EFBF98B84
-:1018B000D89BBBAB9ABB754A545A376A167AF10A61
-:1018C000D01AB32A923A2EFD0FED6CDD4DCDAABD94
-:1018D0008BADE89DC98D267C076C645C454CA23CB1
-:1018E000832CE01CC10C1FEF3EFF5DCF7CDF9BAF64
-:1018F000BABFD98FF89F176E367E554E745E932E01
-:0C190000B23ED10EF01E000000000000FE
-:10190C0001140000090243000201008032090400A6
-:10191C00000102020000052400100104240200054D
-:10192C00240600010524010001070583030800FFBC
-:10193C0009040100020A00000007058102400000B2
-:10194C00070502024000000000C201000000080070
-:0C195C00690000004100000000000000D5
-:0400000300000615DE
+:10009000F81600005C000020540000200000000062
+:1000A00010B5C3699C07FCD403680224A343036012
+:1000B000C46901231C42FBD1046823430360036825
+:1000C000DC07FCD4C46901231C42FBD1C469DC40B9
+:1000D0001C42F7D1084B1A430260C3695A07FCD48B
+:1000E000C0239B0243608181C3699C07FCD40368E1
+:1000F00002221343036010BD04000040037EDA07B0
+:10010000FCD5018570470000027E01235107FBD515
+:10011000428B1A4207D1428BDA401A4203D1428BFA
+:1001200092081A4202D0034B01221A70008DC0B20D
+:100130007047C0467400002070B50368041C988B9B
+:100140001A1C0821FF32084228D0988B174D014312
+:10015000802099839872112353704021144B917120
+:1001600050715E68C0202E40800506435E605E6967
+:100170003540284358610F4818600F4818615D6882
+:100180000E4828408025AD02284358605868800BEF
+:100190008003586000235171237105E0137ADA0659
+:1001A00002D5201C00F0A0FA207970BDFFFFFF8F60
+:1001B0008C0100208C0000200C010020FF3F00F08B
+:1001C000002303714371044B016083600B780222AA
+:1001D00013430B707047C0463901000038B5364BE9
+:1001E0002021DA6901200A43DA61344B06241A78A7
+:1001F00002431A70324B0F22197891431970197803
+:10020000214319702F490C782043087019780A404F
+:100210001A701A7860210A431A702B4B2B4A5A80A5
+:100220005A7852B2002AFBDB294B01211A780A4383
+:100230001A709A78D107FCD426480268510B1F2205
+:100240001140914200D1052111408C011D8D2249A0
+:100250002940214319850468A10C0A401F2A00D1B6
+:100260001D221C8D1F210A408C4322431A850268DF
+:100270000721D20D0A408A4200D103220A40188D7C
+:100280001103164A02400A431A8519787F220A4050
+:100290001A701A78042112480A431A7058621A898F
+:1002A0000C218A431A811A8901218A431A8100216B
+:1002B000802201F0B6F838BD0004004058440041E7
+:1002C0003C44004159440041000C004006400000FD
+:1002D00000500041246080003FF8FFFFFF8FFFFFC8
+:1002E0008C010020F7B5141C234A5F0101971D1CE7
+:1002F000D319061C5869271C4000400F03301033E7
+:10030000C74006D00F1C8022596812060A435A6063
+:1003100009E02F1C7B1E9F41184BBF01FF18381CA2
+:10032000221C01F075F8019913480835421817612D
+:10033000131C5269A104920B890C92030A435A615F
+:1003400059690F4A02200A405A616B01F318D979A2
+:10035000032211400143D8799043021C0A43DA7109
+:100360005979802252420A435A716B01F318DB79A2
+:100370009A07FAD5201CFEBD8C0100200C0100203C
+:10038000FF3F00F0F8B51E4E041C3378151C002BFF
+:1003900012D11C4B1C4A1A645A6C920B92035A6479
+:1003A000586C1A4A02405A64A2235B00E25C402067
+:1003B0000243E254012333704827FF37E25D0123F3
+:1003C00013401AD00F4B5A6C9204920CAA4202D2DC
+:1003D0005D6CAD04AD0C081C2A1C0B4901F018F82B
+:1003E000E25D03231A4001210A43E15D99430B1C9E
+:1003F0001343E3550023337000E01D1C281CF8BD97
+:10040000750000208C010020CC000020FF3F00F090
+:10041000FF30827930239A43131C2022002900D117
+:1004200010221343837170470C4BFF305A6902212D
+:10043000920B92035A61027A03231A400A43017A0B
+:1004400099430B1C13430372827980235B4213434D
+:100450008371037A9A07FCD57047C0468C0100204F
+:1004600080235B421943C9B28172704770B5A023E3
+:1004700003225B00C254134B134A5C6CC02114402E
+:1004800089050C4346255C64FF35402444550F4DD7
+:1004900030261D6490256D0046555D6B154029433F
+:1004A000922559636D0080214155094D1D63B0258A
+:1004B0006D0044555C6F22405A67B2235B00C15403
+:1004C00070BDC0468C010020FFFFFF8FCC000020D4
+:1004D0004C01002030B5364A1E235168082099434C
+:1004E00002231943516033498A6902438A613248C1
+:1004F000324A9082908A03439382D3689807FCD54E
+:100500002F4B012018701878C40704D52C48407868
+:1005100040B20028F7DB01209860587840B20028EC
+:10052000FBDB284C26484460587840B20028FBDBAF
+:1005300082242348E4014480587840B20028FBDB41
+:10054000908C8024A0439084D068C506FCD51E4CB6
+:100550001A48C462D4681948E506FBD5848C1B4D43
+:100560002C438484D4681548E506FBD5848C022589
+:100570002C438484D0680406FCD51048C068450626
+:10058000F8D5D068C406FCD500229A605A7852B2D9
+:10059000002AFBDB0E480A4A50605A7852B2002A01
+:1005A000FBDB00230B724B728B72CB7230BDC046EB
+:1005B00000400041000400400C060000000800401C
+:1005C000000C004001050100B805FF7D040A000091
+:1005D000000703000EBEFEE70DBEFEE705BEFEE708
+:1005E00002BEFEE701BEFEE70E4A0F4838B5824262
+:1005F00004D10E4A0E4B93420ED10AE00D4C9442A8
+:10060000F7D00023D1188842F3D9E55804330D60A0
+:10061000F8E700F011F804E09342FAD2002102C397
+:10062000FAE7FEE7000000205800002098030020B1
+:1006300058000020FC16000010B5244B0022197849
+:1006400001231940224B0AD11868224A904201D155
+:10065000196014E01A60204A013A002AFCD11A609D
+:100660001E4B1968181C4A1C09D0FF22134206D1E0
+:1006700081F3088893431A4A936043681847FFF749
+:1006800029FF62B600F0F2FC00F0C8F9041CA36870
+:10069000201C9847134B002801D001221A701A78A9
+:1006A000002A05D0002000F035FA00F091FAFCE7AE
+:1006B0001B78002BEBD100F04DFD0028E7D0012086
+:1006C00000F028FA00F084FAFCE7C0463804004045
+:1006D000FC7F00203581730748E8010000200000FE
+:1006E00000ED00E076000020F8B50468051C201C31
+:1006F000FF30037AB64A10210B430372B54F1378CB
+:10070000B5493B705378B54E0B7093783380D178F0
+:10071000338809020B4333801179B14B1980517929
+:100720001F8809020F431F809779AE490F80D27945
+:100730000F8812023A430A8040224271A648A54F10
+:1007400002783878A84F12020243181CBA4200D12E
+:1007500099E01EDC802149008A4200D158E107DC83
+:10076000812A6AD0822A6ED0802A00D050E164E0CB
+:1007700081235B009A4200D1AFE000DA23E1C0237D
+:100780009B009A4200D143E1984B9A4200D11AE172
+:100790003EE190231B019A4242D015DCD023DB00BE
+:1007A0009A4222D088231B019A4242D0A023DB0028
+:1007B0009A4200D02CE1201CFFF736FE31882868D1
+:1007C00089B2FFF74DFE27E1894B9A4200D1FAE04A
+:1007D00000DC1DE1874B9A4200D1E8E0864B9A424B
+:1007E00000D015E133886B71EDE033881B0A012BD3
+:1007F00008D10B8812222868934201D80A8892B245
+:100800007E49DCE033881B0A022B00D000E10B8814
+:1008100043222868934201D80A8892B27849CEE0F0
+:100820003388201C2B71FFF7FFFD201CFFF71EFEF5
+:10083000F2E0291C01C90122C1E0724900230B80AA
+:1008400028680222BCE06F4900220A8018885022E2
+:1008500010406D4A10701E880F2030401880188894
+:10086000032800D9D4E012781B8808335B01E41810
+:10087000A379002A01D09B0600E0DB06DB0F0B808A
+:10088000286802229BE019887F2291435E4AC9B200
+:10089000117018880F21014019803188002900D07B
+:1008A000B6E01988002900D1B2E01988032900D9DF
+:1008B000AEE012781B8808335B01E318002A05D0EC
+:1008C0005A7930218A4320210A4304E05A793021A1
+:1008D0008A43102002435A7175E002887F239A43AD
+:1008E000494BD2B21A7001880F220A400280328826
+:1008F000002A00D08CE00288002A00D188E002881B
+:10090000032A00D984E01B78002B27D00388083302
+:100910005B01E3189B79990655D50388302108338C
+:100920005B01E3181A798A4320210A431A7103886C
+:1009300008335B01E318DB795A0644D5038860214C
+:1009400008335B01E318DA798A4340210A43DA71FC
+:100950000388022208335B01E31826E0038808338A
+:100960005B01E3189B79DF062DD50388302108331E
+:100970005B01E3181A798A4310210A431A7103882C
+:1009800008335B01E318DB7999061CD503886021E5
+:1009900008335B01E318DA798A4320210A43DA71CC
+:1009A0000388012208335B01E3181A710BE00B88FE
+:1009B00008222868934201D80A8892B2134900237A
+:1009C000FFF790FC28E0201CFFF72EFD24E0C04636
+:1009D0008C0000208100002077000020780000209B
+:1009E0007C0000207E0000200203000001030000C4
+:1009F00021200000A1210000212200004C14000051
+:100A0000000000207A000020800000204400002028
+:100A1000201C0121FFF7FCFCF8BDC04610B5054BBA
+:100A2000054C2360FFF7DAFB201C2168FFF7C8FBA9
+:100A3000201C10BD005000410C02002007B5054BE2
+:100A40000122019001A91868131CFFF74BFC01203B
+:100A50000EBDC0460C02002013B5054B6C46073492
+:100A60001868211C0122FFF78DFC207816BDC046B6
+:100A70000C02002010B5074C201CFFF75DFB031C87
+:100A80000020834205D022684823FF33D05C012335
+:100A9000184010BD0C02002010B5054A0C1C031CA8
+:100AA000191C10680123221CFFF71CFC201C10BD20
+:100AB0000C02002070B5084C061C201C0D1CFFF712
+:100AC0003BFB0023984205D02068311C2A1CFFF70D
+:100AD00059FC031C181C70BD0C020020F8B50C4C0E
+:100AE000051C201C0E1CFFF727FB0023271C341CB1
+:100AF00098420AD0002C07D0291C221C3868FFF726
+:100B000041FC241A2D18F5E7331C181CF8BDC0460B
+:100B10000C020020012805D1054B064A1A60064B3D
+:100B2000187004E0002802D1044A014B1A60704793
+:100B30007C0200208014000089000020CC140000FA
+:100B400030B51A4B85B01B78002B29D0042901D170
+:100B5000026804E0022901D1028800E0027849001D
+:100B600004A843180B3B5C1AA3420BD00F20104083
+:100B7000092802D83025284300E0373018701209C0
+:100B8000013BF1E701A830230370782343700A2268
+:100B900043189A700D22DA70054B04311B6801E08E
+:100BA000034B1B68DB68984705B030BD8800002008
+:100BB0007C02002072B6EFF30883044A13600368D6
+:100BC00083F30888436818477047C04680020020B6
+:100BD000F0B58FB006A9CD4A0B1C31CA31C351CA3A
+:100BE00051C360CA60C3CA4CCA48A3687A255B0374
+:100BF0005B0F9B005B58C8490360A26892B25343E5
+:100C00000A60C649C64A0B6000231360C54B1D70BD
+:100C1000C54BC64D1B68281C1B6940219847C44B17
+:100C200000221860C34B1D60C34BC34DC04F1A60F8
+:100C3000286839688842EBD2BE4B1B681A78FF2AB5
+:100C400000D1F7E1232A00D0CEE1BC4E3378002B4F
+:100C500005D0B54BBA481B680221DB689847B14BF9
+:100C60001B78532B38D13B682A6893421ED9B14870
+:100C700001322A609A1AB34B01681B680131016086
+:100C8000B14E9A4201D2326000E03360A44832682B
+:100C90000068029000F0BCFB336829685A182A608B
+:100CA000A44A1668F1181160A84A13702B68013B1A
+:100CB0002B60A04B1A68013A1A60A44BA14A1B781A
+:100CC00011688B4206D2984A954812680068C91A82
+:100CD00092699047C04676E1522B07D1904A924BD9
+:100CE00010681B68974A5B6911686BE14F2B05D14F
+:100CF0008B4B944A1B6812681A7064E1482B05D12B
+:100D0000874B904A1B6812681A805CE1572B05D10B
+:100D1000834B8C4A1B6812681A6054E16F2B03D115
+:100D20007F4B0121186807E0682B08D17C4B854870
+:100D30001B6802211B880360FFF702FF43E1772B4A
+:100D400006D1774B7F481B6804211B680360F3E7DB
+:100D5000472B13D17B4B1868FFF72CFF7C4B1B688C
+:100D600083F3088862B67B4B1B78002B00D12AE105
+:100D70006D4B06201B681B68984724E1542B04D157
+:100D800001233370684B1B685CE04E2B0BD133782A
+:100D9000002B05D1644B6A481B680221DB68984729
+:100DA000002333700FE1562B50D15F4D01212B688A
+:100DB0006948DB6898472B680321DB6867489847D8
+:100DC000674E2B68301CDB68012198472B680D218A
+:100DD000DB68644898472B68301CDB680121984722
+:100DE000544F614B544E3B60002333603A1C311C1E
+:100DF0001368581C10601B780393002B03D00B68FA
+:100E000001330B60F4E72B683168DB68564898477C
+:100E10002B685348DB68012198470398306053489A
+:100E20003860444A1368591C11601A78424B002AF2
+:100E300003D01A6801321A60F3E72A681968D36888
+:100E400098472B68DB683E480221BBE03D4A582B9F
+:100E500015D1304E314D366813682A68B10093427F
+:100E600008D25808E06142482080207DC507FCD5A3
+:100E70005B18F4E72C4B3F481B68DB68A1E0592B5B
+:100E800033D11268264B3C49002A02D11B680B6003
+:100E900026E00868196863688025AB4392086360A0
+:100EA000002A1DD0354B2380237DDE07FCD500238F
+:100EB000184D2D680095AD08AB4202D3304D25800A
+:100EC00006E09342FAD09D00465901334E51EFE7B8
+:100ED000257DEE07FCD59D0049194019D21ADFE7A0
+:100EE000114B28481B68DB686BE05A2B6BD10C4B0D
+:100EF00017681D680026EF19BD4245D02878311CBF
+:100F000000F04AF90135061CF6E7C04660140000FF
+:100F100000400041340200202C0200202802002062
+:100F200078020020240200207C02002038020020E9
+:100F30001C02002020020020300200208800002037
+:100F4000C014000084020020880200201802002043
+:100F500080020020890000209C140000C5140000BD
+:100F60009E140000E8140000A0140000AC1400005F
+:100F700002A5FFFFB51400008400002044A5FFFF78
+:100F800004A5FFFFB91400002E4D2F482B68012146
+:100F9000DB68984707230F223240111C3609303195
+:100FA000092A00DD07311020C0186A468154013B30
+:100FB000F1D22B6804A8DB68082198472B682348E6
+:100FC000DB6803219847224D7A232B70214B0022A6
+:100FD0001A60214B1B7893422CD01A4B01211B68BD
+:100FE0001E48DB68984725E0111C3039C8B2194B00
+:100FF000092804D81E683201114319601AE0111C37
+:101000004139052903D81868373A010106E0111C57
+:101010006139052904D81D68573A29010A4308E0B7
+:101020002C2A03D10E4A1E68166001E008490A7096
+:1010300000221A600B4B1A6801321A600A4B1A68B8
+:101040000132F2E57C020020BD140000BF14000054
+:10105000240200208402002088000020C314000025
+:1010600078020020300200202002002010B51C4B26
+:1010700001201A78022402431A701A4B0F221978A1
+:101080009143197019782143197017490C7820433E
+:10109000087019780A401A701A7820210A431A70C9
+:1010A000124B04211A6A0A431A62114B114A5A80E0
+:1010B0005A7852B2002AFBDBC4220F480F49920330
+:1010C000FEF7EEFF0E4A002313700E4A13700E4A0D
+:1010D00013700E4A13700E4A13700E4A137010BD2F
+:1010E0004A440041354400414B4400410004004063
+:1010F000000C0040144000000008004204C500003D
+:101100008C020020130300208D020020900200209A
+:10111000140300201103002008B5C1B20248FEF7F5
+:10112000EDFF012008BDC04600080042024B187EBA
+:101130004007C00F7047C0460008004208B5FFF7DF
+:10114000F5FF0028FBD00248FEF7DEFF08BDC046D1
+:101150000008004208B5FFF7E9FF0023984205D0D8
+:10116000FFF7ECFF031C233B5A425341181C08BDF8
+:1011700070B5041C0D1C4618B44204D02078FFF74B
+:10118000CBFF0134F8E7281C70BD10B5041CFFF735
+:10119000D5FF2070012010BD0B0A5840034B4000C2
+:1011A000C05A0902484080B27047C046F614000099
+:1011B000F7B50024051C0F1C261CBC4220D0FFF7ED
+:1011C000BDFF114BC0B21B780190002B1AD1311C0E
+:1011D000FFF7E2FF0D4B061C1A88002A04D10C4AC7
+:1011E00011782A1C002907D001996A1C2970802FC8
+:1011F00002D11988013919800134A4B2151CDCE729
+:10120000301C00E00120FEBD110300208E020020F2
+:1012100012030020F0B53E4E85B0002203900C1C56
+:1012200032703C4B914201D1012201E03A490C80DD
+:101230001A707F231C4201D080349C43FFF77EFF4D
+:101240003378C0B2002B07D000253570FFF776FF4A
+:101250003378C0B2AB4236D1432803D0712853D083
+:101260001528EBD1012300930120FFF755FF0098CB
+:10127000FFF752FF00998025C843C0B2FFF74CFF2B
+:10128000039B00270293244A1388002B1DD1214978
+:1012900001930978002918D10198FFF73DFF391C07
+:1012A0000198FFF779FF013D071C002DEBD1000AE3
+:1012B000C0B2FFF731FFF8B2FFF72EFFFFF73EFF96
+:1012C0003378002B0AD035701FE00299013B097872
+:1012D0001380029B019101330293DDE7C0B206281F
+:1012E00007D1009B03990133DBB280310093803C2E
+:1012F0000391002CB8D10420FFF70EFFFFF71EFF6B
+:10130000044B01251C7000E00025281C05B0F0BD31
+:1013100011030020120300208E020020F0B5384C8B
+:1013200087B0002301902370994201D1012301E08D
+:10133000344A1180344A642613704320FFF7ECFED0
+:10134000324FFFF7F3FE002803D1002F03D0013FF7
+:10135000F7E7002F03D1013E002EEED14DE001252D
+:10136000FFF7ECFE2378002B38D1C0B202900128A1
+:1013700005D004283DD10620FFF7CEFE39E005AEAA
+:101380000221301CFFF714FF01988021FFF710FFA6
+:1013900023780390002B18D1FFF7D0FE0702FFF748
+:1013A000CDFEBFB223783F18BFB2012B0DD0039BF7
+:1013B0009F4207D13378AB4204D1EB437278DBB262
+:1013C0009A4204D01820FFF7A7FE002303E006206E
+:1013D000FFF7A2FE029B2278002A02D00026267088
+:1013E0000BE0012B05D1019A6B1C8032DDB201921A
+:1013F000B6E7054A002313700126301C07B0F0BD84
+:10140000110300208E0200201203002000350C0082
+:1014100010B50023934203D0CC5CC4540133F9E7E8
+:1014200010BD031C8218934202D019700133FAE7F1
+:1014300070470000F8B5C046F8BC08BC9E4670472F
+:10144000F8B5C046F8BC08BC9E46704712010002C1
+:101450000200004041234D02000200000001000094
+:101460000800000010000000200000004000000004
+:1014700080000000000100000002000000040000E5
+:10148000191100003D1100002D1100007111000024
+:101490008B110000151200001D13000076002000C3
+:1014A0004E6F7620313220323031350031373A32CA
+:1014B000323A323800580A0D00590A0D005A0023FA
+:1014C0000A0D003E00322E30000000003D0A0000F0
+:1014D000590A0000750A0000990A0000B50A0000C8
+:1014E000990A0000DD0A00005B41726475696E6F45
+:1014F0003A58595A5D000000211042206330844060
+:10150000A550C660E770088129914AA16BB18CC1D2
+:10151000ADD1CEE1EFF13112100273325222B55249
+:101520009442F772D662399318837BB35AA3BDD322
+:101530009CC3FFF3DEE36224433420040114E66419
+:10154000C774A44485546AA54BB528850995EEE572
+:10155000CFF5ACC58DD55336722611163006D77629
+:10156000F6669556B4465BB77AA719973887DFF7C2
+:10157000FEE79DD7BCC7C448E5588668A7784008F1
+:10158000611802282338CCC9EDD98EE9AFF9488912
+:1015900069990AA92BB9F55AD44AB77A966A711A89
+:1015A000500A333A122AFDDBDCCBBFFB9EEB799B62
+:1015B000588B3BBB1AABA66C877CE44CC55C222CD9
+:1015C000033C600C411CAEED8FFDECCDCDDD2AADB2
+:1015D0000BBD688D499D977EB66ED55EF44E133E69
+:1015E000322E511E700E9FFFBEEFDDDFFCCF1BBF02
+:1015F0003AAF599F788F8891A981CAB1EBA10CD1DC
+:101600002DC14EF16FE18010A100C230E3200450E3
+:10161000254046706760B9839893FBA3DAB33DC356
+:101620001CD37FE35EF3B1029012F322D232354233
+:10163000145277625672EAB5CBA5A89589856EF5E6
+:101640004FE52CD50DC5E234C324A0148104667483
+:10165000476424540544DBA7FAB79987B8975FE736
+:101660007EF71DC73CD7D326F2369106B0165766D3
+:101670007676154634564CD96DC90EF92FE9C899BE
+:10168000E9898AB9ABA94458654806782768C01823
+:10169000E1088238A3287DCB5CDB3FEB1EFBF98B96
+:1016A000D89BBBAB9ABB754A545A376A167AF10A73
+:1016B000D01AB32A923A2EFD0FED6CDD4DCDAABDA6
+:1016C0008BADE89DC98D267C076C645C454CA23CC3
+:1016D000832CE01CC10C1FEF3EFF5DCF7CDF9BAF76
+:1016E000BABFD98FF89F176E367E554E745E932E13
+:0C16F000B23ED10EF01E00000000000011
+:1016FC0009024300020100803209040000010202C9
+:10170C000000052400100104240200052406000139
+:10171C000524010001070583030800FF09040100EB
+:10172C00020A0000000705810240000007050202C2
+:10173C004000000000C20100000008006900000029
+:08174C00410000000000000054
+:04000003000005E90B
 :00000001FF
diff --git a/cores/arduino/Arduino.h b/cores/arduino/Arduino.h
index e645743b2..9bc114f69 100644
--- a/cores/arduino/Arduino.h
+++ b/cores/arduino/Arduino.h
@@ -46,7 +46,6 @@ extern "C"{
 
 // Include Atmel headers
 #include "sam.h"
-
 #include "wiring_constants.h"
 
 #define clockCyclesPerMicrosecond() ( SystemCoreClock / 1000000L )
@@ -97,8 +96,33 @@ void loop( void ) ;
 #undef abs
 #endif // abs
 
-#define min(a,b) ((a)<(b)?(a):(b))
-#define max(a,b) ((a)>(b)?(a):(b))
+#ifdef __cplusplus
+  template<class T, class L> 
+  auto min(const T& a, const L& b) -> decltype((b < a) ? b : a)
+  {
+    return (b < a) ? b : a;
+  }
+
+  template<class T, class L> 
+  auto max(const T& a, const L& b) -> decltype((b < a) ? b : a)
+  {
+    return (a < b) ? b : a;
+  }
+#else
+#ifndef min
+#define min(a,b) \
+   ({ __typeof__ (a) _a = (a); \
+       __typeof__ (b) _b = (b); \
+     _a < _b ? _a : _b; })
+#endif
+#ifndef max
+#define max(a,b) \
+   ({ __typeof__ (a) _a = (a); \
+       __typeof__ (b) _b = (b); \
+     _a > _b ? _a : _b; })
+#endif
+#endif
+
 #define abs(x) ((x)>0?(x):-(x))
 #define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt)))
 #define round(x)     ((x)>=0?(long)((x)+0.5):(long)((x)-0.5))
@@ -124,10 +148,14 @@ void loop( void ) ;
 #define digitalPinToInterrupt(P)   ( P )
 #endif
 
-// USB Device
+// USB
+#ifdef USE_TINYUSB
+#include "Adafruit_TinyUSB_Core.h"
+#else
 #include "USB/USBDesc.h"
 #include "USB/USBCore.h"
 #include "USB/USBAPI.h"
 #include "USB/USB_host.h"
+#endif
 
 #endif // Arduino_h
diff --git a/cores/arduino/HardwareSerial.h b/cores/arduino/HardwareSerial.h
index 62508e786..6180b0748 100644
--- a/cores/arduino/HardwareSerial.h
+++ b/cores/arduino/HardwareSerial.h
@@ -67,9 +67,9 @@
 class HardwareSerial : public Stream
 {
   public:
-    virtual void begin(unsigned long);
-    virtual void begin(unsigned long baudrate, uint16_t config);
-    virtual void end();
+    virtual void begin(unsigned long) {}
+    virtual void begin(unsigned long, uint16_t) {}
+    virtual void end() {}
     virtual int available(void) = 0;
     virtual int peek(void) = 0;
     virtual int read(void) = 0;
diff --git a/cores/arduino/Print.cpp b/cores/arduino/Print.cpp
index 136329cca..6257542cd 100644
--- a/cores/arduino/Print.cpp
+++ b/cores/arduino/Print.cpp
@@ -186,6 +186,16 @@ size_t Print::println(const Printable& x)
   return n;
 }
 
+void Print::printf(const char format[], ...)
+{
+  char buf[PRINTF_BUF];
+  va_list ap;
+  va_start(ap, format);
+  vsnprintf(buf, sizeof(buf), format, ap);
+  write(buf);
+  va_end(ap);
+}
+
 // Private Methods /////////////////////////////////////////////////////////////
 
 size_t Print::printNumber(unsigned long n, uint8_t base)
@@ -238,14 +248,14 @@ size_t Print::printFloat(double number, uint8_t digits)
 
   // Print the decimal point, but only if there are digits beyond
   if (digits > 0) {
-    n += print('.');
+    n += print(".");
   }
 
   // Extract digits from the remainder one at a time
   while (digits-- > 0)
   {
     remainder *= 10.0;
-    unsigned int toPrint = (unsigned int)(remainder);
+    unsigned int toPrint = (unsigned int)remainder;
     n += print(toPrint);
     remainder -= toPrint;
   }
diff --git a/cores/arduino/Print.h b/cores/arduino/Print.h
index dfb645cbb..1577ceb14 100644
--- a/cores/arduino/Print.h
+++ b/cores/arduino/Print.h
@@ -21,6 +21,8 @@
 
 #include <inttypes.h>
 #include <stdio.h> // for size_t
+#include <stdarg.h> // for printf
+#define PRINTF_BUF 80
 
 #include "WString.h"
 #include "Printable.h"
@@ -28,9 +30,6 @@
 #define DEC 10
 #define HEX 16
 #define OCT 8
-#ifdef BIN // Prevent warnings if BIN is previously defined in "iotnx4.h" or similar
-#undef BIN
-#endif
 #define BIN 2
 
 class Print
@@ -85,6 +84,8 @@ class Print
     size_t println(double, int = 2);
     size_t println(const Printable&);
     size_t println(void);
+    
+    void printf(const char[], ...);
 
     virtual void flush() { /* Empty implementation for backward compatibility */ }
 };
diff --git a/cores/arduino/Reset.cpp b/cores/arduino/Reset.cpp
index 053d7c5f3..9bde4a8c0 100644
--- a/cores/arduino/Reset.cpp
+++ b/cores/arduino/Reset.cpp
@@ -1,5 +1,6 @@
 /*
   Copyright (c) 2015 Arduino LLC.  All right reserved.
+  SAMD51 support added by Adafruit - Copyright (c) 2018 Dean Miller for Adafruit Industries
 
   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
@@ -28,42 +29,74 @@ extern "C" {
 #if (ARDUINO_SAMD_VARIANT_COMPLIANCE >= 10610)
 
 extern const uint32_t __text_start__;
-#define APP_START ((volatile uint32_t)(&__text_start__) + 4)
+#define APP_START ((uint32_t)(&__text_start__) + 4)
 
+#else
+
+#if defined(__SAMD51__)
+#define APP_START 0x00004004
 #else
 #define APP_START 0x00002004
 #endif
 
+#endif
+
 static inline bool nvmReady(void) {
+#if defined(__SAMD51__)
+		return NVMCTRL->STATUS.reg & NVMCTRL_STATUS_READY;
+#else
         return NVMCTRL->INTFLAG.reg & NVMCTRL_INTFLAG_READY;
+#endif
 }
 
 __attribute__ ((long_call, section (".ramfunc")))
 static void banzai() {
 	// Disable all interrupts
 	__disable_irq();
+	
+#if defined(__SAMD51__)
+	//THESE MUST MATCH THE BOOTLOADER
+	#define DOUBLE_TAP_MAGIC 			0xf01669efUL
+	#define BOOT_DOUBLE_TAP_ADDRESS     (HSRAM_ADDR + HSRAM_SIZE - 4)
+
+	unsigned long *a = (unsigned long *)BOOT_DOUBLE_TAP_ADDRESS;
+	*a = DOUBLE_TAP_MAGIC;
+	//NVMCTRL->ADDR.reg  = APP_START;
+	//NVMCTRL->CTRLB.reg = NVMCTRL_CTRLB_CMD_EB | NVMCTRL_CTRLB_CMDEX_KEY;
+	
+	// Reset the device
+	NVIC_SystemReset() ;
 
+	while (true);
+#else
+	
 	// Avoid erasing the application if APP_START is < than the minimum bootloader size
 	// This could happen if without_bootloader linker script was chosen
 	// Minimum bootloader size in SAMD21 family is 512bytes (RM section 22.6.5)
+	
 	if (APP_START < (0x200 + 4)) {
 		goto reset;
 	}
+	
 
 	// Erase application
 	while (!nvmReady())
 		;
+
 	NVMCTRL->STATUS.reg |= NVMCTRL_STATUS_MASK;
 	NVMCTRL->ADDR.reg  = (uintptr_t)&NVM_MEMORY[APP_START / 4];
 	NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMD_ER | NVMCTRL_CTRLA_CMDEX_KEY;
+	
 	while (!nvmReady())
-		;
+	;
 
 reset:
 	// Reset the device
 	NVIC_SystemReset() ;
 
 	while (true);
+#endif
+
 }
 
 static int ticks = -1;
diff --git a/cores/arduino/RingBuffer.h b/cores/arduino/RingBuffer.h
index e706cc4f2..deecb733c 100644
--- a/cores/arduino/RingBuffer.h
+++ b/cores/arduino/RingBuffer.h
@@ -27,8 +27,9 @@
 // using a ring buffer (I think), in which head is the index of the location
 // to which to write the next incoming character and tail is the index of the
 // location from which to read.
+
 #ifndef SERIAL_BUFFER_SIZE
-#define SERIAL_BUFFER_SIZE 256
+#define SERIAL_BUFFER_SIZE 350
 #endif
 
 template <int N>
diff --git a/cores/arduino/SERCOM.cpp b/cores/arduino/SERCOM.cpp
index be7962ec2..9a75730fd 100644
--- a/cores/arduino/SERCOM.cpp
+++ b/cores/arduino/SERCOM.cpp
@@ -1,5 +1,6 @@
 /*
   Copyright (c) 2014 Arduino.  All right reserved.
+  SAMD51 support added by Adafruit - Copyright (c) 2018 Dean Miller for Adafruit Industries
 
   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
@@ -18,6 +19,7 @@
 
 #include "SERCOM.h"
 #include "variant.h"
+#include "Arduino.h"
 
 #ifndef WIRE_RISE_TIME_NANOSECONDS
 // Default rise time in nanoseconds, based on 4.7K ohm pull up resistors
@@ -28,11 +30,29 @@
 SERCOM::SERCOM(Sercom* s)
 {
   sercom = s;
-}
 
-/* 	=========================
- *	===== Sercom UART
- *	=========================
+#if defined(__SAMD51__)
+  // A briefly-available but now deprecated feature had the SPI clock source
+  // set via a compile-time setting (MAX_SPI)...problem was this affected
+  // ALL SERCOMs, whereas some (anything read/write, e.g. SD cards) should
+  // not exceed the standard 24 MHz setting.  Newer code, if it needs faster
+  // write-only SPI (e.g. to screen), should override the SERCOM clock on a
+  // per-peripheral basis.  Nonetheless, we check SERCOM_SPI_FREQ_REF here
+  // (MAX_SPI * 2) to retain compatibility with any interim projects that
+  // might have relied on the compile-time setting.  But please, don't.
+ #if SERCOM_SPI_FREQ_REF == F_CPU       // F_CPU clock = GCLK0
+  clockSource = SERCOM_CLOCK_SOURCE_FCPU;
+ #elif SERCOM_SPI_FREQ_REF == 48000000  // 48 MHz clock = GCLK1 (standard)
+  clockSource = SERCOM_CLOCK_SOURCE_48M;
+ #elif SERCOM_SPI_FREQ_REF == 100000000 // 100 MHz clock = GCLK2
+  clockSource = SERCOM_CLOCK_SOURCE_100M;
+ #endif
+#endif // end __SAMD51__
+}
+
+/* =========================
+ * ===== Sercom UART
+ * =========================
 */
 void SERCOM::initUART(SercomUartMode mode, SercomUartSampleRate sampleRate, uint32_t baudrate)
 {
@@ -40,12 +60,12 @@ void SERCOM::initUART(SercomUartMode mode, SercomUartSampleRate sampleRate, uint
   resetUART();
 
   //Setting the CTRLA register
-  sercom->USART.CTRLA.reg =	SERCOM_USART_CTRLA_MODE(mode) |
-                SERCOM_USART_CTRLA_SAMPR(sampleRate);
+  sercom->USART.CTRLA.reg = SERCOM_USART_CTRLA_MODE(mode) |
+                            SERCOM_USART_CTRLA_SAMPR(sampleRate);
 
   //Setting the Interrupt register
-  sercom->USART.INTENSET.reg =	SERCOM_USART_INTENSET_RXC |  //Received complete
-                                SERCOM_USART_INTENSET_ERROR; //All others errors
+  sercom->USART.INTENSET.reg = SERCOM_USART_INTENSET_RXC |  //Received complete
+                               SERCOM_USART_INTENSET_ERROR; //All others errors
 
   if ( mode == UART_INT_CLOCK )
   {
@@ -60,7 +80,11 @@ void SERCOM::initUART(SercomUartMode mode, SercomUartSampleRate sampleRate, uint
     // Asynchronous fractional mode (Table 24-2 in datasheet)
     //   BAUD = fref / (sampleRateValue * fbaud)
     // (multiply by 8, to calculate fractional piece)
+#if defined(__SAMD51__)
+    uint32_t baudTimes8 = (SERCOM_FREQ_REF * 8) / (sampleRateValue * baudrate);
+#else
     uint32_t baudTimes8 = (SystemCoreClock * 8) / (sampleRateValue * baudrate);
+#endif
 
     sercom->USART.BAUD.FRAC.FP   = (baudTimes8 % 8);
     sercom->USART.BAUD.FRAC.BAUD = (baudTimes8 / 8);
@@ -69,20 +93,22 @@ void SERCOM::initUART(SercomUartMode mode, SercomUartSampleRate sampleRate, uint
 void SERCOM::initFrame(SercomUartCharSize charSize, SercomDataOrder dataOrder, SercomParityMode parityMode, SercomNumberStopBit nbStopBits)
 {
   //Setting the CTRLA register
-  sercom->USART.CTRLA.reg |=	SERCOM_USART_CTRLA_FORM( (parityMode == SERCOM_NO_PARITY ? 0 : 1) ) |
-                dataOrder << SERCOM_USART_CTRLA_DORD_Pos;
+  sercom->USART.CTRLA.reg |=
+    SERCOM_USART_CTRLA_FORM((parityMode == SERCOM_NO_PARITY ? 0 : 1) ) |
+    dataOrder << SERCOM_USART_CTRLA_DORD_Pos;
 
   //Setting the CTRLB register
-  sercom->USART.CTRLB.reg |=	SERCOM_USART_CTRLB_CHSIZE(charSize) |
-                nbStopBits << SERCOM_USART_CTRLB_SBMODE_Pos |
-                (parityMode == SERCOM_NO_PARITY ? 0 : parityMode) << SERCOM_USART_CTRLB_PMODE_Pos; //If no parity use default value
+  sercom->USART.CTRLB.reg |= SERCOM_USART_CTRLB_CHSIZE(charSize) |
+    nbStopBits << SERCOM_USART_CTRLB_SBMODE_Pos |
+    (parityMode == SERCOM_NO_PARITY ? 0 : parityMode) <<
+      SERCOM_USART_CTRLB_PMODE_Pos; //If no parity use default value
 }
 
 void SERCOM::initPads(SercomUartTXPad txPad, SercomRXPad rxPad)
 {
   //Setting the CTRLA register
-  sercom->USART.CTRLA.reg |=	SERCOM_USART_CTRLA_TXPO(txPad) |
-                SERCOM_USART_CTRLA_RXPO(rxPad);
+  sercom->USART.CTRLA.reg |= SERCOM_USART_CTRLA_TXPO(txPad) |
+                             SERCOM_USART_CTRLA_RXPO(rxPad);
 
   // Enable Transceiver and Receiver
   sercom->USART.CTRLB.reg |= SERCOM_USART_CTRLB_TXEN | SERCOM_USART_CTRLB_RXEN ;
@@ -195,26 +221,33 @@ void SERCOM::disableDataRegisterEmptyInterruptUART()
   sercom->USART.INTENCLR.reg = SERCOM_USART_INTENCLR_DRE;
 }
 
-/*	=========================
- *	===== Sercom SPI
- *	=========================
+/* =========================
+ * ===== Sercom SPI
+ * =========================
 */
 void SERCOM::initSPI(SercomSpiTXPad mosi, SercomRXPad miso, SercomSpiCharSize charSize, SercomDataOrder dataOrder)
 {
   resetSPI();
   initClockNVIC();
 
+#if defined(__SAMD51__)
+  sercom->SPI.CTRLA.reg = SERCOM_SPI_CTRLA_MODE(0x3)  |  // master mode
+                          SERCOM_SPI_CTRLA_DOPO(mosi) |
+                          SERCOM_SPI_CTRLA_DIPO(miso) |
+                          dataOrder << SERCOM_SPI_CTRLA_DORD_Pos;
+#else
   //Setting the CTRLA register
-  sercom->SPI.CTRLA.reg =	SERCOM_SPI_CTRLA_MODE_SPI_MASTER |
+  sercom->SPI.CTRLA.reg = SERCOM_SPI_CTRLA_MODE_SPI_MASTER |
                           SERCOM_SPI_CTRLA_DOPO(mosi) |
                           SERCOM_SPI_CTRLA_DIPO(miso) |
                           dataOrder << SERCOM_SPI_CTRLA_DORD_Pos;
+#endif
 
   //Setting the CTRLB register
   sercom->SPI.CTRLB.reg = SERCOM_SPI_CTRLB_CHSIZE(charSize) |
-                          SERCOM_SPI_CTRLB_RXEN;	//Active the SPI receiver.
-
+                          SERCOM_SPI_CTRLB_RXEN; //Active the SPI receiver.
 
+  while( sercom->SPI.SYNCBUSY.bit.CTRLB == 1 );
 }
 
 void SERCOM::initSPIClock(SercomSpiClockMode clockMode, uint32_t baudrate)
@@ -233,8 +266,8 @@ void SERCOM::initSPIClock(SercomSpiClockMode clockMode, uint32_t baudrate)
     cpol = 1;
 
   //Setting the CTRLA register
-  sercom->SPI.CTRLA.reg |=	( cpha << SERCOM_SPI_CTRLA_CPHA_Pos ) |
-                            ( cpol << SERCOM_SPI_CTRLA_CPOL_Pos );
+  sercom->SPI.CTRLA.reg |= ( cpha << SERCOM_SPI_CTRLA_CPHA_Pos ) |
+                           ( cpol << SERCOM_SPI_CTRLA_CPOL_Pos );
 
   //Synchronous arithmetic
   sercom->SPI.BAUD.reg = calculateBaudrateSynchronous(baudrate);
@@ -288,14 +321,13 @@ SercomDataOrder SERCOM::getDataOrderSPI()
 
 void SERCOM::setBaudrateSPI(uint8_t divider)
 {
-  //Can't divide by 0
-  if(divider == 0)
-    return;
+  disableSPI(); // Register is enable-protected
 
-  //Register enable-protected
-  disableSPI();
-
-  sercom->SPI.BAUD.reg = calculateBaudrateSynchronous( SERCOM_FREQ_REF / divider );
+#if defined(__SAMD51__)
+  sercom->SPI.BAUD.reg = calculateBaudrateSynchronous(freqRef / divider);
+#else
+  sercom->SPI.BAUD.reg = calculateBaudrateSynchronous(SERCOM_SPI_FREQ_REF / divider);
+#endif
 
   enableSPI();
 }
@@ -326,10 +358,7 @@ uint8_t SERCOM::transferDataSPI(uint8_t data)
 {
   sercom->SPI.DATA.bit.DATA = data; // Writing data into Data register
 
-  while( sercom->SPI.INTFLAG.bit.RXC == 0 )
-  {
-    // Waiting Complete Reception
-  }
+  while(sercom->SPI.INTFLAG.bit.RXC == 0); // Waiting Complete Reception
 
   return sercom->SPI.DATA.bit.DATA;  // Reading data
 }
@@ -347,25 +376,30 @@ bool SERCOM::isDataRegisterEmptySPI()
 
 //bool SERCOM::isTransmitCompleteSPI()
 //{
-//	//TXC : Transmit complete
-//	return sercom->SPI.INTFLAG.bit.TXC;
+//  //TXC : Transmit complete
+//  return sercom->SPI.INTFLAG.bit.TXC;
 //}
 //
 //bool SERCOM::isReceiveCompleteSPI()
 //{
-//	//RXC : Receive complete
-//	return sercom->SPI.INTFLAG.bit.RXC;
+//  //RXC : Receive complete
+//  return sercom->SPI.INTFLAG.bit.RXC;
 //}
 
-uint8_t SERCOM::calculateBaudrateSynchronous(uint32_t baudrate)
-{
-  return SERCOM_FREQ_REF / (2 * baudrate) - 1;
+uint8_t SERCOM::calculateBaudrateSynchronous(uint32_t baudrate) {
+#if defined(__SAMD51__)
+  uint16_t b = freqRef / (2 * baudrate);
+#else
+  uint16_t b = SERCOM_SPI_FREQ_REF / (2 * baudrate);
+#endif
+  if(b > 0) b--; // Don't -1 on baud calc if already at 0
+  return b;
 }
 
 
-/*	=========================
- *	===== Sercom WIRE
- *	=========================
+/* =========================
+ * ===== Sercom WIRE
+ * =========================
  */
 void SERCOM::resetWIRE()
 {
@@ -457,7 +491,11 @@ void SERCOM::initMasterWIRE( uint32_t baudrate )
 //  sercom->I2CM.INTENSET.reg = SERCOM_I2CM_INTENSET_MB | SERCOM_I2CM_INTENSET_SB | SERCOM_I2CM_INTENSET_ERROR ;
 
   // Synchronous arithmetic baudrate
+#if defined(__SAMD51__)
+  sercom->I2CM.BAUD.bit.BAUD = SERCOM_FREQ_REF / ( 2 * baudrate) - 1 ;
+#else
   sercom->I2CM.BAUD.bit.BAUD = SystemCoreClock / ( 2 * baudrate) - 5 - (((SystemCoreClock / 1000000) * WIRE_RISE_TIME_NANOSECONDS) / (2 * 1000));
+#endif
 }
 
 void SERCOM::prepareNackBitWIRE( void )
@@ -499,8 +537,18 @@ bool SERCOM::startTransmissionWIRE(uint8_t address, SercomWireReadWriteFlag flag
   // 7-bits address + 1-bits R/W
   address = (address << 0x1ul) | flag;
 
-  // Wait idle or owner bus mode
-  while ( !isBusIdleWIRE() && !isBusOwnerWIRE() );
+  // If another master owns the bus or the last bus owner has not properly
+  // sent a stop, return failure early. This will prevent some misbehaved
+  // devices from deadlocking here at the cost of the caller being responsible
+  // for retrying the failed transmission. See SercomWireBusState for the
+  // possible bus states.
+  if(!isBusOwnerWIRE())
+  {
+    if( isBusBusyWIRE() || (isArbLostWIRE() && !isBusIdleWIRE()) || isBusUnknownWIRE() )
+    {
+      return false;
+    }
+  }
 
   // Send start and address
   sercom->I2CM.ADDR.bit.ADDR = address;
@@ -596,6 +644,21 @@ bool SERCOM::isBusOwnerWIRE( void )
   return sercom->I2CM.STATUS.bit.BUSSTATE == WIRE_OWNER_STATE;
 }
 
+bool SERCOM::isBusUnknownWIRE( void )
+{
+  return sercom->I2CM.STATUS.bit.BUSSTATE == WIRE_UNKNOWN_STATE;
+}
+
+bool SERCOM::isArbLostWIRE( void )
+{
+  return sercom->I2CM.STATUS.bit.ARBLOST == 1;
+}
+
+bool SERCOM::isBusBusyWIRE( void )
+{
+  return sercom->I2CM.STATUS.bit.BUSSTATE == WIRE_BUSY_STATE;
+}
+
 bool SERCOM::isDataReadyWIRE( void )
 {
   return sercom->I2CS.INTFLAG.bit.DRDY;
@@ -651,64 +714,152 @@ uint8_t SERCOM::readDataWIRE( void )
   }
 }
 
+#if defined(__SAMD51__)
+
+static const struct {
+  Sercom   *sercomPtr;
+  uint8_t   id_core;
+  uint8_t   id_slow;
+  IRQn_Type irq[4];
+} sercomData[] = {
+  { SERCOM0, SERCOM0_GCLK_ID_CORE, SERCOM0_GCLK_ID_SLOW,
+    SERCOM0_0_IRQn, SERCOM0_1_IRQn, SERCOM0_2_IRQn, SERCOM0_3_IRQn },
+  { SERCOM1, SERCOM1_GCLK_ID_CORE, SERCOM1_GCLK_ID_SLOW,
+    SERCOM1_0_IRQn, SERCOM1_1_IRQn, SERCOM1_2_IRQn, SERCOM1_3_IRQn },
+  { SERCOM2, SERCOM2_GCLK_ID_CORE, SERCOM2_GCLK_ID_SLOW,
+    SERCOM2_0_IRQn, SERCOM2_1_IRQn, SERCOM2_2_IRQn, SERCOM2_3_IRQn },
+  { SERCOM3, SERCOM3_GCLK_ID_CORE, SERCOM3_GCLK_ID_SLOW,
+    SERCOM3_0_IRQn, SERCOM3_1_IRQn, SERCOM3_2_IRQn, SERCOM3_3_IRQn },
+  { SERCOM4, SERCOM4_GCLK_ID_CORE, SERCOM4_GCLK_ID_SLOW,
+    SERCOM4_0_IRQn, SERCOM4_1_IRQn, SERCOM4_2_IRQn, SERCOM4_3_IRQn },
+  { SERCOM5, SERCOM5_GCLK_ID_CORE, SERCOM5_GCLK_ID_SLOW,
+    SERCOM5_0_IRQn, SERCOM5_1_IRQn, SERCOM5_2_IRQn, SERCOM5_3_IRQn },
+#if defined(SERCOM6)
+  { SERCOM6, SERCOM6_GCLK_ID_CORE, SERCOM6_GCLK_ID_SLOW,
+    SERCOM6_0_IRQn, SERCOM6_1_IRQn, SERCOM6_2_IRQn, SERCOM6_3_IRQn },
+#endif
+#if defined(SERCOM7)
+  { SERCOM7, SERCOM7_GCLK_ID_CORE, SERCOM7_GCLK_ID_SLOW,
+    SERCOM7_0_IRQn, SERCOM7_1_IRQn, SERCOM7_2_IRQn, SERCOM7_3_IRQn },
+#endif
+};
+
+#else // end if SAMD51 (prob SAMD21)
+
+static const struct {
+  Sercom   *sercomPtr;
+  uint8_t   clock;
+  IRQn_Type irqn;
+} sercomData[] = {
+  SERCOM0, GCM_SERCOM0_CORE, SERCOM0_IRQn,
+  SERCOM1, GCM_SERCOM1_CORE, SERCOM1_IRQn,
+  SERCOM2, GCM_SERCOM2_CORE, SERCOM2_IRQn,
+  SERCOM3, GCM_SERCOM3_CORE, SERCOM3_IRQn,
+#if defined(SERCOM4)
+  SERCOM4, GCM_SERCOM4_CORE, SERCOM4_IRQn,
+#endif
+#if defined(SERCOM5)
+  SERCOM5, GCM_SERCOM5_CORE, SERCOM5_IRQn,
+#endif
+};
 
-void SERCOM::initClockNVIC( void )
-{
-  uint8_t clockId = 0;
-  IRQn_Type IdNvic=PendSV_IRQn ; // Dummy init to intercept potential error later
+#endif // end !SAMD51
 
-  if(sercom == SERCOM0)
-  {
-    clockId = GCM_SERCOM0_CORE;
-    IdNvic = SERCOM0_IRQn;
-  }
-  else if(sercom == SERCOM1)
-  {
-    clockId = GCM_SERCOM1_CORE;
-    IdNvic = SERCOM1_IRQn;
-  }
-  else if(sercom == SERCOM2)
-  {
-    clockId = GCM_SERCOM2_CORE;
-    IdNvic = SERCOM2_IRQn;
-  }
-  else if(sercom == SERCOM3)
-  {
-    clockId = GCM_SERCOM3_CORE;
-    IdNvic = SERCOM3_IRQn;
-  }
-  #if defined(SERCOM4)
-  else if(sercom == SERCOM4)
-  {
-    clockId = GCM_SERCOM4_CORE;
-    IdNvic = SERCOM4_IRQn;
+int8_t SERCOM::getSercomIndex(void) {
+  for(uint8_t i=0; i<(sizeof(sercomData) / sizeof(sercomData[0])); i++) {
+    if(sercom == sercomData[i].sercomPtr) return i;
   }
-  #endif // SERCOM4
-  #if defined(SERCOM5)
-  else if(sercom == SERCOM5)
-  {
-    clockId = GCM_SERCOM5_CORE;
-    IdNvic = SERCOM5_IRQn;
+  return -1;
+}
+
+#if defined(__SAMD51__)
+// This is currently for overriding an SPI SERCOM's clock source only --
+// NOT for UART or WIRE SERCOMs, where it will have unintended consequences.
+// It does not check.
+// SERCOM clock source override is available only on SAMD51 (not 21).
+// A dummy function for SAMD21 (compiles to nothing) is present in SERCOM.h
+// so user code doesn't require a lot of conditional situations.
+void SERCOM::setClockSource(int8_t idx, SercomClockSource src, bool core) {
+
+  if(src == SERCOM_CLOCK_SOURCE_NO_CHANGE) return;
+
+  uint8_t clk_id = core ? sercomData[idx].id_core : sercomData[idx].id_slow;
+
+  GCLK->PCHCTRL[clk_id].bit.CHEN = 0;     // Disable timer
+  while(GCLK->PCHCTRL[clk_id].bit.CHEN);  // Wait for disable
+
+  if(core) clockSource = src; // Save SercomClockSource value
+
+  // From cores/arduino/startup.c:
+  // GCLK0 = F_CPU
+  // GCLK1 = 48 MHz
+  // GCLK2 = 100 MHz
+  // GCLK3 = XOSC32K
+  // GCLK4 = 12 MHz
+  if(src == SERCOM_CLOCK_SOURCE_FCPU) {
+    GCLK->PCHCTRL[clk_id].reg =
+      GCLK_PCHCTRL_GEN_GCLK0_Val | (1 << GCLK_PCHCTRL_CHEN_Pos);
+    if(core) freqRef = F_CPU; // Save clock frequency value
+  } else if(src == SERCOM_CLOCK_SOURCE_48M) {
+    GCLK->PCHCTRL[clk_id].reg =
+      GCLK_PCHCTRL_GEN_GCLK1_Val | (1 << GCLK_PCHCTRL_CHEN_Pos);
+    if(core) freqRef = 48000000;
+  } else if(src == SERCOM_CLOCK_SOURCE_100M) {
+    GCLK->PCHCTRL[clk_id].reg =
+      GCLK_PCHCTRL_GEN_GCLK2_Val | (1 << GCLK_PCHCTRL_CHEN_Pos);
+    if(core) freqRef = 100000000;
+  } else if(src == SERCOM_CLOCK_SOURCE_32K) {
+    GCLK->PCHCTRL[clk_id].reg =
+      GCLK_PCHCTRL_GEN_GCLK3_Val | (1 << GCLK_PCHCTRL_CHEN_Pos);
+    if(core) freqRef = 32768;
+  } else if(src == SERCOM_CLOCK_SOURCE_12M) {
+    GCLK->PCHCTRL[clk_id].reg =
+      GCLK_PCHCTRL_GEN_GCLK4_Val | (1 << GCLK_PCHCTRL_CHEN_Pos);
+    if(core) freqRef = 12000000;
   }
-  #endif // SERCOM5
 
-  if ( IdNvic == PendSV_IRQn )
-  {
-    // We got a problem here
-    return ;
+  while(!GCLK->PCHCTRL[clk_id].bit.CHEN); // Wait for clock enable
+}
+#endif
+
+void SERCOM::initClockNVIC( void )
+{
+  int8_t idx = getSercomIndex();
+  if(idx < 0) return; // We got a problem here
+
+#if defined(__SAMD51__)
+
+  for(uint8_t i=0; i<4; i++) {
+    NVIC_ClearPendingIRQ(sercomData[idx].irq[i]);
+    NVIC_SetPriority(sercomData[idx].irq[i], SERCOM_NVIC_PRIORITY);
+    NVIC_EnableIRQ(sercomData[idx].irq[i]);
   }
 
+  // SPI DMA speed is dictated by the "slow clock" (I think...maybe) so
+  // BOTH are set to the same clock source (clk_slow isn't sourced from
+  // XOSC32K as in prior versions of SAMD core).
+  // This might have power implications for sleep code.
+
+  setClockSource(idx, clockSource, true);  // true  = core clock
+  setClockSource(idx, clockSource, false); // false = slow clock
+
+#else // end if SAMD51 (prob SAMD21)
+
+  uint8_t   clockId = sercomData[idx].clock;
+  IRQn_Type IdNvic  = sercomData[idx].irqn;
+
   // Setting NVIC
+  NVIC_ClearPendingIRQ(IdNvic);
+  NVIC_SetPriority(IdNvic, SERCOM_NVIC_PRIORITY);
   NVIC_EnableIRQ(IdNvic);
-  NVIC_SetPriority (IdNvic, SERCOM_NVIC_PRIORITY);  /* set Priority */
 
-  //Setting clock
-  GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID( clockId ) | // Generic Clock 0 (SERCOMx)
-                      GCLK_CLKCTRL_GEN_GCLK0 | // Generic Clock Generator 0 is source
-                      GCLK_CLKCTRL_CLKEN ;
+  // Setting clock
+  GCLK->CLKCTRL.reg =
+    GCLK_CLKCTRL_ID( clockId ) | // Generic Clock 0 (SERCOMx)
+    GCLK_CLKCTRL_GEN_GCLK0     | // Generic Clock Generator 0 is source
+    GCLK_CLKCTRL_CLKEN;
 
-  while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY )
-  {
-    /* Wait for synchronization */
-  }
+  while(GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY); // Wait for synchronization
+
+#endif // end !SAMD51
 }
diff --git a/cores/arduino/SERCOM.h b/cores/arduino/SERCOM.h
index 750592aee..c717e78b6 100644
--- a/cores/arduino/SERCOM.h
+++ b/cores/arduino/SERCOM.h
@@ -21,8 +21,19 @@
 
 #include "sam.h"
 
-#define SERCOM_FREQ_REF      48000000
-#define SERCOM_NVIC_PRIORITY ((1<<__NVIC_PRIO_BITS) - 1)
+// SAMD51 has configurable MAX_SPI, else use peripheral clock default.
+// Update: changing MAX_SPI via compiler flags is DEPRECATED, because
+// this affects ALL SPI peripherals including some that should NOT be
+// changed (e.g. anything using SD card). Instead, use setClockSource().
+// This is left here for compatibility w/interim MAX_SPI-dependent code:
+#if defined(MAX_SPI)
+  #define SERCOM_SPI_FREQ_REF (MAX_SPI * 2)
+#else
+  #define SERCOM_SPI_FREQ_REF 48000000ul
+#endif
+// Other SERCOM peripherals always use the 48 MHz clock
+#define SERCOM_FREQ_REF       48000000ul
+#define SERCOM_NVIC_PRIORITY  ((1<<__NVIC_PRIO_BITS) - 1)
 
 typedef enum
 {
@@ -80,23 +91,23 @@ typedef enum
 
 typedef enum
 {
-	UART_TX_PAD_0 = 0x0ul,	// Only for UART
+	UART_TX_PAD_0 = 0x0ul,  // Only for UART
 	UART_TX_PAD_2 = 0x1ul,  // Only for UART
 	UART_TX_RTS_CTS_PAD_0_2_3 = 0x2ul,  // Only for UART with TX on PAD0, RTS on PAD2 and CTS on PAD3
 } SercomUartTXPad;
 
 typedef enum
 {
-	SAMPLE_RATE_x16 = 0x1,	//Fractional
-	SAMPLE_RATE_x8 = 0x3,	//Fractional
+	SAMPLE_RATE_x16 = 0x1,  // Fractional
+	SAMPLE_RATE_x8  = 0x3,  // Fractional
 } SercomUartSampleRate;
 
 typedef enum
 {
-	SERCOM_SPI_MODE_0 = 0,	// CPOL : 0  | CPHA : 0
-	SERCOM_SPI_MODE_1,		// CPOL : 0  | CPHA : 1
-	SERCOM_SPI_MODE_2,		// CPOL : 1  | CPHA : 0
-	SERCOM_SPI_MODE_3		// CPOL : 1  | CPHA : 1
+	SERCOM_SPI_MODE_0 = 0, // CPOL : 0 | CPHA : 0
+	SERCOM_SPI_MODE_1,     // CPOL : 0 | CPHA : 1
+	SERCOM_SPI_MODE_2,     // CPOL : 1 | CPHA : 0
+	SERCOM_SPI_MODE_3      // CPOL : 1 | CPHA : 1
 } SercomSpiClockMode;
 
 typedef enum
@@ -141,6 +152,19 @@ typedef enum
 	WIRE_MASTER_NACK_ACTION
 } SercomMasterAckActionWire;
 
+// SERCOM clock source override is available only on SAMD51 (not 21)
+// but the enumeration is made regardless so user code doesn't need
+// ifdefs or lengthy comments explaining the different situations --
+// the clock-sourcing functions just compile to nothing on SAMD21.
+typedef enum {
+  SERCOM_CLOCK_SOURCE_FCPU,     // F_CPU clock (GCLK0)
+  SERCOM_CLOCK_SOURCE_48M,      // 48 MHz peripheral clock (GCLK1) (standard)
+  SERCOM_CLOCK_SOURCE_100M,     // 100 MHz peripheral clock (GCLK2)
+  SERCOM_CLOCK_SOURCE_32K,      // XOSC32K clock (GCLK3)
+  SERCOM_CLOCK_SOURCE_12M,      // 12 MHz peripheral clock (GCLK4)
+  SERCOM_CLOCK_SOURCE_NO_CHANGE // Leave clock source setting unchanged
+} SercomClockSource;
+
 class SERCOM
 {
 	public:
@@ -171,7 +195,6 @@ class SERCOM
 		/* ========== SPI ========== */
 		void initSPI(SercomSpiTXPad mosi, SercomRXPad miso, SercomSpiCharSize charSize, SercomDataOrder dataOrder) ;
 		void initSPIClock(SercomSpiClockMode clockMode, uint32_t baudrate) ;
-
 		void resetSPI( void ) ;
 		void enableSPI( void ) ;
 		void disableSPI( void ) ;
@@ -202,6 +225,9 @@ class SERCOM
 		bool isSlaveWIRE( void ) ;
 		bool isBusIdleWIRE( void ) ;
 		bool isBusOwnerWIRE( void ) ;
+		bool isBusUnknownWIRE( void ) ;
+		bool isArbLostWIRE( void );
+		bool isBusBusyWIRE( void );
 		bool isDataReadyWIRE( void ) ;
 		bool isStopDetectedWIRE( void ) ;
 		bool isRestartDetectedWIRE( void ) ;
@@ -210,10 +236,30 @@ class SERCOM
     bool isRXNackReceivedWIRE( void ) ;
 		int availableWIRE( void ) ;
 		uint8_t readDataWIRE( void ) ;
+		int8_t getSercomIndex(void);
+#if defined(__SAMD51__)
+		// SERCOM clock source override is only available on
+		// SAMD51 (not 21) ... but these functions are declared
+		// regardless so user code doesn't need ifdefs or lengthy
+		// comments explaining the different situations -- these
+		// just compile to nothing on SAMD21.
+		void setClockSource(int8_t idx, SercomClockSource src, bool core);
+		SercomClockSource getClockSource(void) { return clockSource; };
+		uint32_t getFreqRef(void) { return freqRef; };
+#else
+		// The equivalent SAMD21 dummy functions...
+		void setClockSource(int8_t idx, SercomClockSource src, bool core) { (void)idx; (void)src; (void)core; };
+		SercomClockSource getClockSource(void) { return SERCOM_CLOCK_SOURCE_FCPU; };
+		uint32_t getFreqRef(void) { return F_CPU; };
+#endif
 
 	private:
 		Sercom* sercom;
-		uint8_t calculateBaudrateSynchronous(uint32_t baudrate) ;
+#if defined(__SAMD51__)
+                SercomClockSource clockSource;
+                uint32_t freqRef; // Frequency corresponding to clockSource
+#endif
+		uint8_t calculateBaudrateSynchronous(uint32_t baudrate);
 		uint32_t division(uint32_t dividend, uint32_t divisor) ;
 		void initClockNVIC( void ) ;
 };
diff --git a/cores/arduino/Stream.cpp b/cores/arduino/Stream.cpp
index d2846316d..c32f89d60 100644
--- a/cores/arduino/Stream.cpp
+++ b/cores/arduino/Stream.cpp
@@ -35,6 +35,7 @@ int Stream::timedRead()
   do {
     c = read();
     if (c >= 0) return c;
+    yield(); // running TinyUSB task
   } while(millis() - _startMillis < _timeout);
   return -1;     // -1 indicates timeout
 }
@@ -47,6 +48,7 @@ int Stream::timedPeek()
   do {
     c = peek();
     if (c >= 0) return c;
+    yield(); // running TinyUSB task
   } while(millis() - _startMillis < _timeout);
   return -1;     // -1 indicates timeout
 }
diff --git a/cores/arduino/TinyUSB/Adafruit_TinyUSB_ArduinoCore b/cores/arduino/TinyUSB/Adafruit_TinyUSB_ArduinoCore
new file mode 160000
index 000000000..e7b892095
--- /dev/null
+++ b/cores/arduino/TinyUSB/Adafruit_TinyUSB_ArduinoCore
@@ -0,0 +1 @@
+Subproject commit e7b892095f2bb5d8bef6a748238369bdd268ed5e
diff --git a/cores/arduino/TinyUSB/Adafruit_TinyUSB_SAMD.cpp b/cores/arduino/TinyUSB/Adafruit_TinyUSB_SAMD.cpp
new file mode 100644
index 000000000..867eac926
--- /dev/null
+++ b/cores/arduino/TinyUSB/Adafruit_TinyUSB_SAMD.cpp
@@ -0,0 +1,195 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019, hathach for Adafruit
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifdef USE_TINYUSB
+
+#include "Arduino.h"
+#include "Adafruit_TinyUSB_Core.h"
+#include <Reset.h> // Needed for auto-reset with 1200bps port touch
+
+//--------------------------------------------------------------------+
+// Forward USB interrupt events to TinyUSB IRQ Handler
+//--------------------------------------------------------------------+
+extern "C"
+{
+#if defined(__SAMD51__)
+
+void USB_0_Handler (void) { tud_int_handler(0); }
+void USB_1_Handler (void) { tud_int_handler(0); }
+void USB_2_Handler (void) { tud_int_handler(0); }
+void USB_3_Handler (void) { tud_int_handler(0); }
+
+#else
+
+void USB_Handler(void) { tud_int_handler(0); }
+
+#endif
+} // extern C
+
+
+
+//--------------------------------------------------------------------+
+// MACRO TYPEDEF CONSTANT ENUM DECLARATION
+//--------------------------------------------------------------------+
+static void usb_hardware_init(void);
+
+#if CFG_TUSB_DEBUG
+extern "C" int serial1_printf(const char *__restrict format, ...)
+{
+  char buf[PRINTF_BUF];
+  va_list ap;
+  va_start(ap, format);
+  vsnprintf(buf, sizeof(buf), format, ap);
+  Serial1.write(buf);
+  va_end(ap);
+
+}
+#endif
+
+//--------------------------------------------------------------------+
+// Core Init & Touch1200
+//--------------------------------------------------------------------+
+void Adafruit_TinyUSB_Core_init(void)
+{
+#if CFG_TUSB_DEBUG
+  Serial1.begin(115200);
+  serial1_printf("TinyUSB debugging with Serial1\n");
+#endif
+
+  Serial.setStringDescriptor("TinyUSB Serial");
+  USBDevice.addInterface(Serial);
+  USBDevice.setID(USB_VID, USB_PID);
+  USBDevice.begin();
+
+  usb_hardware_init();
+
+  // Init tinyusb stack
+  tusb_init();
+}
+
+void Adafruit_TinyUSB_Core_touch1200(void)
+{
+  initiateReset(250);
+}
+
+//--------------------------------------------------------------------+
+// Adafruit_USBD_Device platform dependent
+//--------------------------------------------------------------------+
+
+uint8_t Adafruit_USBD_Device::getSerialDescriptor(uint16_t* serial_str)
+{
+  enum { SERIAL_BYTE_LEN = 16 };
+
+#ifdef __SAMD51__
+  uint32_t* id_addresses[4] = {(uint32_t *) 0x008061FC, (uint32_t *) 0x00806010,
+                               (uint32_t *) 0x00806014, (uint32_t *) 0x00806018};
+#else // samd21
+  uint32_t* id_addresses[4] = {(uint32_t *) 0x0080A00C, (uint32_t *) 0x0080A040,
+                               (uint32_t *) 0x0080A044, (uint32_t *) 0x0080A048};
+
+#endif
+
+  uint8_t raw_id[SERIAL_BYTE_LEN];
+
+  for (int i=0; i<4; i++) {
+      for (int k=0; k<4; k++) {
+          raw_id[4 * i + (3 - k)] = (*(id_addresses[i]) >> k * 8) & 0xff;
+      }
+  }
+
+  static const char nibble_to_hex[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
+
+  for (unsigned int i = 0; i < sizeof(raw_id); i++) {
+    for (int j = 0; j < 2; j++) {
+      uint8_t nibble = (raw_id[i] >> (j * 4)) & 0xf;
+      // Strings are UTF-16-LE encoded.
+      serial_str[i * 2 + (1 - j)] = nibble_to_hex[nibble];
+    }
+  }
+
+  return sizeof(raw_id)*2;
+}
+
+//--------------------------------------------------------------------+
+// Helpers
+//--------------------------------------------------------------------+
+
+// Init usb hardware when starting up. Softdevice is not enabled yet
+static void usb_hardware_init(void)
+{
+#ifdef PIN_LED_TXL
+//	txLEDPulse = 0;
+	pinMode(PIN_LED_TXL, OUTPUT);
+	digitalWrite(PIN_LED_TXL, HIGH);
+#endif
+
+#ifdef PIN_LED_RXL
+//	rxLEDPulse = 0;
+	pinMode(PIN_LED_RXL, OUTPUT);
+	digitalWrite(PIN_LED_RXL, HIGH);
+#endif
+
+	/* Enable USB clock */
+#if defined(__SAMD51__)
+	MCLK->APBBMASK.reg |= MCLK_APBBMASK_USB;
+	MCLK->AHBMASK.reg |= MCLK_AHBMASK_USB;
+
+	// Set up the USB DP/DN pins
+	PORT->Group[0].PINCFG[PIN_PA24H_USB_DM].bit.PMUXEN = 1;
+	PORT->Group[0].PMUX[PIN_PA24H_USB_DM/2].reg &= ~(0xF << (4 * (PIN_PA24H_USB_DM & 0x01u)));
+	PORT->Group[0].PMUX[PIN_PA24H_USB_DM/2].reg |= MUX_PA24H_USB_DM << (4 * (PIN_PA24H_USB_DM & 0x01u));
+	PORT->Group[0].PINCFG[PIN_PA25H_USB_DP].bit.PMUXEN = 1;
+	PORT->Group[0].PMUX[PIN_PA25H_USB_DP/2].reg &= ~(0xF << (4 * (PIN_PA25H_USB_DP & 0x01u)));
+	PORT->Group[0].PMUX[PIN_PA25H_USB_DP/2].reg |= MUX_PA25H_USB_DP << (4 * (PIN_PA25H_USB_DP & 0x01u));
+
+
+	GCLK->PCHCTRL[USB_GCLK_ID].reg = GCLK_PCHCTRL_GEN_GCLK1_Val | (1 << GCLK_PCHCTRL_CHEN_Pos);
+
+	NVIC_SetPriority(USB_0_IRQn, 0UL);
+	NVIC_SetPriority(USB_1_IRQn, 0UL);
+	NVIC_SetPriority(USB_2_IRQn, 0UL);
+	NVIC_SetPriority(USB_3_IRQn, 0UL);
+#else
+	PM->APBBMASK.reg |= PM_APBBMASK_USB;
+
+	// Set up the USB DP/DN pins
+	PORT->Group[0].PINCFG[PIN_PA24G_USB_DM].bit.PMUXEN = 1;
+	PORT->Group[0].PMUX[PIN_PA24G_USB_DM/2].reg &= ~(0xF << (4 * (PIN_PA24G_USB_DM & 0x01u)));
+	PORT->Group[0].PMUX[PIN_PA24G_USB_DM/2].reg |= MUX_PA24G_USB_DM << (4 * (PIN_PA24G_USB_DM & 0x01u));
+	PORT->Group[0].PINCFG[PIN_PA25G_USB_DP].bit.PMUXEN = 1;
+	PORT->Group[0].PMUX[PIN_PA25G_USB_DP/2].reg &= ~(0xF << (4 * (PIN_PA25G_USB_DP & 0x01u)));
+	PORT->Group[0].PMUX[PIN_PA25G_USB_DP/2].reg |= MUX_PA25G_USB_DP << (4 * (PIN_PA25G_USB_DP & 0x01u));
+
+	// Put Generic Clock Generator 0 as source for Generic Clock Multiplexer 6 (USB reference)
+	GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(6)     | // Generic Clock Multiplexer 6
+	GCLK_CLKCTRL_GEN_GCLK0 | // Generic Clock Generator 0 is source
+	GCLK_CLKCTRL_CLKEN;
+	while (GCLK->STATUS.bit.SYNCBUSY)
+	;
+
+	NVIC_SetPriority((IRQn_Type) USB_IRQn, 0UL);
+#endif
+}
+
+#endif // USE_TINYUSB
diff --git a/cores/arduino/TinyUSB/tusb_config.h b/cores/arduino/TinyUSB/tusb_config.h
new file mode 100644
index 000000000..70ddbeb64
--- /dev/null
+++ b/cores/arduino/TinyUSB/tusb_config.h
@@ -0,0 +1,93 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018, hathach for Adafruit
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef _TUSB_CONFIG_H_
+#define _TUSB_CONFIG_H_
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+//--------------------------------------------------------------------
+// COMMON CONFIGURATION
+//--------------------------------------------------------------------
+#ifdef __SAMD51__
+  #define CFG_TUSB_MCU                OPT_MCU_SAMD51
+#else
+  #define CFG_TUSB_MCU                OPT_MCU_SAMD21
+#endif
+
+#ifdef USE_TINYUSB
+  #define CFG_TUSB_RHPORT0_MODE       OPT_MODE_DEVICE
+#else
+  #define CFG_TUSB_RHPORT0_MODE       OPT_MODE_NONE
+#endif
+
+#define CFG_TUSB_OS                 OPT_OS_NONE
+
+#define CFG_TUSB_DEBUG              0
+#if CFG_TUSB_DEBUG
+  #define tu_printf                 serial1_printf
+  extern int serial1_printf(const char *__restrict __format, ...);
+#endif
+
+#define CFG_TUSB_MEM_SECTION
+#define CFG_TUSB_MEM_ALIGN          TU_ATTR_ALIGNED(4)
+
+//--------------------------------------------------------------------
+// DEVICE CONFIGURATION
+//--------------------------------------------------------------------
+
+#define CFG_TUD_ENDOINT0_SIZE       64
+
+//------------- CLASS -------------//
+#define CFG_TUD_CDC                 1
+#define CFG_TUD_MSC                 1
+#define CFG_TUD_HID                 1
+#define CFG_TUD_MIDI                1
+#define CFG_TUD_VENDOR              1
+
+// CDC FIFO size of TX and RX
+#define CFG_TUD_CDC_RX_BUFSIZE      256
+#define CFG_TUD_CDC_TX_BUFSIZE      256
+
+// MSC Buffer size of Device Mass storage
+#define CFG_TUD_MSC_BUFSIZE         512
+
+// HID buffer size Should be sufficient to hold ID (if any) + Data
+#define CFG_TUD_HID_BUFSIZE         64
+
+// MIDI FIFO size of TX and RX
+#define CFG_TUD_MIDI_RX_BUFSIZE     128
+#define CFG_TUD_MIDI_TX_BUFSIZE     128
+
+// Vendor FIFO size of TX and RX
+#define CFG_TUD_VENDOR_RX_BUFSIZE   64
+#define CFG_TUD_VENDOR_TX_BUFSIZE   64
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* _TUSB_CONFIG_H_ */
diff --git a/cores/arduino/Tone.cpp b/cores/arduino/Tone.cpp
index 45b438d9b..1d4ddc406 100644
--- a/cores/arduino/Tone.cpp
+++ b/cores/arduino/Tone.cpp
@@ -1,5 +1,6 @@
 /*
   Copyright (c) 2015 Arduino LLC.  All right reserved.
+  SAMD51 support added by Adafruit - Copyright (c) 2018 Dean Miller for Adafruit Industries
 
   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
@@ -19,8 +20,6 @@
 #include "Tone.h"
 #include "variant.h"
 
-#define WAIT_TC16_REGS_SYNC(x) while(x->COUNT16.STATUS.bit.SYNCBUSY);
-
 uint32_t toneMaxFrequency = F_CPU / 2;
 uint32_t lastOutputPin = 0xFFFFFFFF;
 
@@ -31,13 +30,25 @@ volatile int64_t toggleCount;
 volatile bool toneIsActive = false;
 volatile bool firstTimeRunning = false;
 
-#define TONE_TC         TC5
-#define TONE_TC_IRQn    TC5_IRQn
+#if defined(__SAMD51__)
+  #define TONE_TC         TC0
+  #define TONE_TC_IRQn    TC0_IRQn
+  #define TONE_TC_GCLK_ID	TC0_GCLK_ID
+  #define Tone_Handler    TC0_Handler
+
+  #define WAIT_TC16_REGS_SYNC(x) while(x->COUNT16.SYNCBUSY.bit.ENABLE);
+
+#else
+  #define TONE_TC         TC5
+  #define TONE_TC_IRQn    TC5_IRQn
+  #define Tone_Handler    TC5_Handler
+
+  #define WAIT_TC16_REGS_SYNC(x) while(x->COUNT16.STATUS.bit.SYNCBUSY);
+#endif
+
 #define TONE_TC_TOP     0xFFFF
 #define TONE_TC_CHANNEL 0
 
-void TC5_Handler (void) __attribute__ ((weak, alias("Tone_Handler")));
-
 static inline void resetTC (Tc* TCx)
 {
   // Disable TCx
@@ -57,6 +68,14 @@ void toneAccurateClock (uint32_t accurateSystemCoreClockFrequency)
 
 void tone (uint32_t outputPin, uint32_t frequency, uint32_t duration)
 {
+
+  // Avoid divide by zero error by calling 'noTone' instead
+  if (frequency == 0)
+  {
+    noTone(outputPin);
+    return;
+  }
+
   // Configure interrupt request
   NVIC_DisableIRQ(TONE_TC_IRQn);
   NVIC_ClearPendingIRQ(TONE_TC_IRQn);
@@ -65,11 +84,15 @@ void tone (uint32_t outputPin, uint32_t frequency, uint32_t duration)
   {
     firstTimeRunning = true;
     
-    NVIC_SetPriority(TONE_TC_IRQn, 0);
-      
+    NVIC_SetPriority(TONE_TC_IRQn, 5);
+
+#if defined(__SAMD51__)
+    GCLK->PCHCTRL[TONE_TC_GCLK_ID].reg = GCLK_PCHCTRL_GEN_GCLK0_Val | (1 << GCLK_PCHCTRL_CHEN_Pos);
+#else
     // Enable GCLK for TC4 and TC5 (timer counter input clock)
     GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID(GCM_TC4_TC5));
     while (GCLK->STATUS.bit.SYNCBUSY);
+#endif
   }
   
   if (toneIsActive && (outputPin != lastOutputPin))
@@ -120,7 +143,12 @@ void tone (uint32_t outputPin, uint32_t frequency, uint32_t duration)
 
   uint16_t tmpReg = 0;
   tmpReg |= TC_CTRLA_MODE_COUNT16;  // Set Timer counter Mode to 16 bits
+  
+#if defined(__SAMD51__)
+	TONE_TC->COUNT16.WAVE.reg = TC_WAVE_WAVEGEN_MFRQ;  // Set TONE_TC mode as match frequency
+#else
   tmpReg |= TC_CTRLA_WAVEGEN_MFRQ;  // Set TONE_TC mode as match frequency
+#endif
   tmpReg |= prescalerConfigBits;
   TONE_TC->COUNT16.CTRLA.reg |= tmpReg;
   WAIT_TC16_REGS_SYNC(TONE_TC)
@@ -152,9 +180,19 @@ void tone (uint32_t outputPin, uint32_t frequency, uint32_t duration)
 
 void noTone (uint32_t outputPin)
 {
-  resetTC(TONE_TC);
-  digitalWrite(outputPin, LOW);
-  toneIsActive = false;
+  /* 'tone' need to run at least once in order to enable GCLK for
+   * the timers used for the tone-functionality. If 'noTone' is called
+   * without ever calling 'tone' before then 'WAIT_TC16_REGS_SYNC(TCx)'
+   * will wait infinitely. The variable 'firstTimeRunning' is set the
+   * 1st time 'tone' is set so it can be used to detect wether or not
+   * 'tone' has been called before.
+   */
+  if(firstTimeRunning)
+  {
+    resetTC(TONE_TC);
+    digitalWrite(outputPin, LOW);
+    toneIsActive = false;
+  }
 }
 
 #ifdef __cplusplus
diff --git a/cores/arduino/USB/CDC.cpp b/cores/arduino/USB/CDC.cpp
index c60388deb..10710417c 100644
--- a/cores/arduino/USB/CDC.cpp
+++ b/cores/arduino/USB/CDC.cpp
@@ -16,6 +16,8 @@
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */
 
+#ifndef USE_TINYUSB
+
 #include <Arduino.h>
 #include <Reset.h> // Needed for auto-reset with 1200bps port touch
 
@@ -206,7 +208,20 @@ void Serial_::flush(void)
 
 size_t Serial_::write(const uint8_t *buffer, size_t size)
 {
-	uint32_t r = usb.send(CDC_ENDPOINT_IN, buffer, size);
+	/* only try to send bytes if the high-level CDC connection itself
+	 is open (not just the pipe) - the OS should set lineState when the port
+	 is opened and clear lineState when the port is closed.
+	 bytes sent before the user opens the connection or after
+	 the connection is closed are lost - just like with a UART. */
+
+	// TODO - ZE - check behavior on different OSes and test what happens if an
+	// open connection isn't broken cleanly (cable is yanked out, host dies
+	// or locks up, or host virtual serial port hangs)
+	uint32_t r = 0;
+	if (_usbLineInfo.lineState > 0)  // Problem with Windows(R)
+	{
+		r = usb.send(CDC_ENDPOINT_IN, buffer, size);
+	}
 
 	if (r > 0) {
 		return r;
@@ -288,6 +303,8 @@ bool Serial_::rts() {
 	return _usbLineInfo.lineState & 0x2;
 }
 
-Serial_ SerialUSB(USBDevice);
+Serial_ Serial(USBDevice);
 
 #endif
+
+#endif // USE_TINYUSB
diff --git a/cores/arduino/USB/PluggableUSB.cpp b/cores/arduino/USB/PluggableUSB.cpp
index 4c52c1fad..f94c5647f 100644
--- a/cores/arduino/USB/PluggableUSB.cpp
+++ b/cores/arduino/USB/PluggableUSB.cpp
@@ -17,6 +17,8 @@
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */
 
+#ifndef USE_TINYUSB
+
 #include "USBAPI.h"
 #include "USBDesc.h"
 #include "USBCore.h"
@@ -113,4 +115,6 @@ PluggableUSB_::PluggableUSB_() : lastIf(CDC_ACM_INTERFACE + CDC_INTERFACE_COUNT)
 }
 
 #endif
-#endif
\ No newline at end of file
+#endif
+
+#endif // USE_TINYUSB
diff --git a/cores/arduino/USB/SAMD21_USBDevice.cpp b/cores/arduino/USB/SAMD21_USBDevice.cpp
new file mode 100644
index 000000000..f45d256dc
--- /dev/null
+++ b/cores/arduino/USB/SAMD21_USBDevice.cpp
@@ -0,0 +1,41 @@
+/*
+ * SAMD21_USBDevice.cpp
+ *
+ *  Created on: Feb 21, 2018
+ *      Author: deanm
+ */
+
+#ifndef USE_TINYUSB
+
+#include "SAMD21_USBDevice.h"
+
+void USBDevice_SAMD21G18x::reset() {
+    usb.CTRLA.bit.SWRST = 1;
+    memset(EP, 0, sizeof(EP));
+    while (usb.SYNCBUSY.bit.SWRST || usb.SYNCBUSY.bit.ENABLE) {}
+    usb.DESCADD.reg = (uint32_t)(&EP);
+}
+
+void USBDevice_SAMD21G18x::calibrate() {
+    // Load Pad Calibration data from non-volatile memory
+    uint32_t *pad_transn_p = (uint32_t *) USB_FUSES_TRANSN_ADDR;
+    uint32_t *pad_transp_p = (uint32_t *) USB_FUSES_TRANSP_ADDR;
+    uint32_t *pad_trim_p   = (uint32_t *) USB_FUSES_TRIM_ADDR;
+
+    uint32_t pad_transn = (*pad_transn_p & USB_FUSES_TRANSN_Msk) >> USB_FUSES_TRANSN_Pos;
+    uint32_t pad_transp = (*pad_transp_p & USB_FUSES_TRANSP_Msk) >> USB_FUSES_TRANSP_Pos;
+    uint32_t pad_trim   = (*pad_trim_p   & USB_FUSES_TRIM_Msk  ) >> USB_FUSES_TRIM_Pos;
+
+    if (pad_transn == 0x1F)  // maximum value (31)
+        pad_transn = 5;
+    if (pad_transp == 0x1F)  // maximum value (31)
+        pad_transp = 29;
+    if (pad_trim == 0x7)     // maximum value (7)
+        pad_trim = 3;
+
+    usb.PADCAL.bit.TRANSN = pad_transn;
+    usb.PADCAL.bit.TRANSP = pad_transp;
+    usb.PADCAL.bit.TRIM   = pad_trim;
+}
+
+#endif // USE_TINYUSB
diff --git a/cores/arduino/USB/SAMD21_USBDevice.h b/cores/arduino/USB/SAMD21_USBDevice.h
index 3296a1346..00da069db 100644
--- a/cores/arduino/USB/SAMD21_USBDevice.h
+++ b/cores/arduino/USB/SAMD21_USBDevice.h
@@ -1,5 +1,6 @@
 /*
   Copyright (c) 2015 Arduino LLC.  All right reserved.
+  SAMD51 support added by Adafruit - Copyright (c) 2018 Dean Miller for Adafruit Industries
 
   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
@@ -39,8 +40,18 @@ class USBDevice_SAMD21G18x {
 	void reset();
 
 	// Enable
-	inline void enable()  { usb.CTRLA.bit.ENABLE = 1; }
-	inline void disable() { usb.CTRLA.bit.ENABLE = 0; }
+	inline void enable()  { 
+		usb.CTRLA.bit.ENABLE = 1;
+#if defined(__SAMD51__)
+		while( usb.SYNCBUSY.reg & USB_SYNCBUSY_ENABLE ); //wait for sync
+#endif
+	}
+	inline void disable() { 
+		usb.CTRLA.bit.ENABLE = 0;
+#if defined(__SAMD51__)
+		while( usb.SYNCBUSY.reg & USB_SYNCBUSY_ENABLE ); //wait for sync
+#endif
+	}
 
 	// USB mode (device/host)
 	inline void setUSBDeviceMode() { usb.CTRLA.bit.MODE = USB_CTRLA_MODE_DEVICE_Val; }
@@ -167,35 +178,6 @@ class USBDevice_SAMD21G18x {
 	__attribute__((__aligned__(4)))	UsbDeviceDescriptor EP[USB_EPT_NUM];
 };
 
-void USBDevice_SAMD21G18x::reset() {
-	usb.CTRLA.bit.SWRST = 1;
-	memset(EP, 0, sizeof(EP));
-	while (usb.SYNCBUSY.bit.SWRST) {}
-	usb.DESCADD.reg = (uint32_t)(&EP);
-}
-
-void USBDevice_SAMD21G18x::calibrate() {
-	// Load Pad Calibration data from non-volatile memory
-	uint32_t *pad_transn_p = (uint32_t *) USB_FUSES_TRANSN_ADDR;
-	uint32_t *pad_transp_p = (uint32_t *) USB_FUSES_TRANSP_ADDR;
-	uint32_t *pad_trim_p   = (uint32_t *) USB_FUSES_TRIM_ADDR;
-
-	uint32_t pad_transn = (*pad_transn_p & USB_FUSES_TRANSN_Msk) >> USB_FUSES_TRANSN_Pos;
-	uint32_t pad_transp = (*pad_transp_p & USB_FUSES_TRANSP_Msk) >> USB_FUSES_TRANSP_Pos;
-	uint32_t pad_trim   = (*pad_trim_p   & USB_FUSES_TRIM_Msk  ) >> USB_FUSES_TRIM_Pos;
-
-	if (pad_transn == 0x1F)  // maximum value (31)
-		pad_transn = 5;
-	if (pad_transp == 0x1F)  // maximum value (31)
-		pad_transp = 29;
-	if (pad_trim == 0x7)     // maximum value (7)
-		pad_trim = 3;
-
-	usb.PADCAL.bit.TRANSN = pad_transn;
-	usb.PADCAL.bit.TRANSP = pad_transp;
-	usb.PADCAL.bit.TRIM   = pad_trim;
-}
-
 /*
  * Synchronization primitives.
  * TODO: Move into a separate header file and make an API out of it
@@ -221,7 +203,6 @@ class __Guard {
 
 #define synchronized for (__Guard __guard; __guard.enter(); )
 
-
 /*
  * USB EP generic handlers.
  */
@@ -231,6 +212,8 @@ class EPHandler {
 	virtual void handleEndpoint() = 0;
 	virtual uint32_t recv(void *_data, uint32_t len) = 0;
 	virtual uint32_t available() const = 0;
+
+	virtual void init() = 0;
 };
 
 class DoubleBufferedEPOutHandler : public EPHandler {
@@ -258,6 +241,7 @@ class DoubleBufferedEPOutHandler : public EPHandler {
 		free((void*)data0);
 		free((void*)data1);
 	}
+	void init() {};
 
 	virtual uint32_t recv(void *_data, uint32_t len)
 	{
@@ -402,4 +386,3 @@ class DoubleBufferedEPOutHandler : public EPHandler {
 
 	volatile bool notify;
 };
-
diff --git a/cores/arduino/USB/SAMR21_USBDevice.h b/cores/arduino/USB/SAMR21_USBDevice.h
new file mode 100644
index 000000000..1da5579ac
--- /dev/null
+++ b/cores/arduino/USB/SAMR21_USBDevice.h
@@ -0,0 +1,197 @@
+/*
+  Copyright (c) 2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#pragma once
+
+#include <Arduino.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+
+typedef uint8_t ep_t;
+
+class USBDevice_SAMR21G18x {
+public:
+	USBDevice_SAMR21G18x() : usb(USB->DEVICE) {
+		// Empty
+	}
+
+	// USB Device function mapping
+	// ---------------------------
+
+	// Reset USB Device
+	void reset();
+
+	// Enable
+	inline void enable()  { usb.CTRLA.bit.ENABLE = 1; }
+	inline void disable() { usb.CTRLA.bit.ENABLE = 0; }
+
+	// USB mode (device/host)
+	inline void setUSBDeviceMode() { usb.CTRLA.bit.MODE = USB_CTRLA_MODE_DEVICE_Val; }
+	inline void setUSBHostMode()   { usb.CTRLA.bit.MODE = USB_CTRLA_MODE_HOST_Val;   }
+
+	inline void runInStandby()   { usb.CTRLA.bit.RUNSTDBY = 1; }
+	inline void noRunInStandby() { usb.CTRLA.bit.RUNSTDBY = 0; }
+
+	// USB speed
+	inline void setFullSpeed()       { usb.CTRLB.bit.SPDCONF = USB_DEVICE_CTRLB_SPDCONF_FS_Val;   }
+	inline void setLowSpeed()        { usb.CTRLB.bit.SPDCONF = USB_DEVICE_CTRLB_SPDCONF_LS_Val;   }
+	inline void setHiSpeed()         { usb.CTRLB.bit.SPDCONF = USB_DEVICE_CTRLB_SPDCONF_HS_Val;   }
+	inline void setHiSpeedTestMode() { usb.CTRLB.bit.SPDCONF = USB_DEVICE_CTRLB_SPDCONF_HSTM_Val; }
+
+	// Authorize attach if Vbus is present
+	inline void attach() { usb.CTRLB.bit.DETACH = 0; }
+	inline void detach() { usb.CTRLB.bit.DETACH = 1; }
+
+	// USB Interrupts
+	inline bool isEndOfResetInterrupt()        { return usb.INTFLAG.bit.EORST; }
+	inline void ackEndOfResetInterrupt()       { usb.INTFLAG.reg = USB_DEVICE_INTFLAG_EORST; }
+	inline void enableEndOfResetInterrupt()    { usb.INTENSET.bit.EORST = 1; } 
+	inline void disableEndOfResetInterrupt()   { usb.INTENCLR.bit.EORST = 1; } 
+
+	inline bool isStartOfFrameInterrupt()      { return usb.INTFLAG.bit.SOF; }
+	inline void ackStartOfFrameInterrupt()     { usb.INTFLAG.reg = USB_DEVICE_INTFLAG_SOF; }
+	inline void enableStartOfFrameInterrupt()  { usb.INTENSET.bit.SOF = 1; }
+	inline void disableStartOfFrameInterrupt() { usb.INTENCLR.bit.SOF = 1; }
+
+	// USB Address
+	inline void setAddress(uint32_t addr)   { usb.DADD.bit.DADD = addr; usb.DADD.bit.ADDEN = 1; }
+	inline void unsetAddress()              { usb.DADD.bit.DADD = 0;    usb.DADD.bit.ADDEN = 0; }
+
+	// Frame number
+	inline uint16_t frameNumber() { return usb.FNUM.bit.FNUM; }
+
+	// Load calibration values
+	void calibrate();
+
+	// USB Device Endpoints function mapping
+	// -------------------------------------
+
+	// Config
+	inline void epBank0SetType(ep_t ep, uint8_t type) { usb.DeviceEndpoint[ep].EPCFG.bit.EPTYPE0 = type; }
+	inline void epBank1SetType(ep_t ep, uint8_t type) { usb.DeviceEndpoint[ep].EPCFG.bit.EPTYPE1 = type; }
+
+	// Interrupts
+	inline uint16_t epInterruptSummary() { return usb.EPINTSMRY.reg; }
+
+	inline bool epBank0IsSetupReceived(ep_t ep)     { return usb.DeviceEndpoint[ep].EPINTFLAG.bit.RXSTP; }
+	inline bool epBank0IsStalled(ep_t ep)           { return usb.DeviceEndpoint[ep].EPINTFLAG.bit.STALL0; }
+	inline bool epBank1IsStalled(ep_t ep)           { return usb.DeviceEndpoint[ep].EPINTFLAG.bit.STALL1; }
+	inline bool epBank0IsTransferComplete(ep_t ep)  { return usb.DeviceEndpoint[ep].EPINTFLAG.bit.TRCPT0; }
+	inline bool epBank1IsTransferComplete(ep_t ep)  { return usb.DeviceEndpoint[ep].EPINTFLAG.bit.TRCPT1; }
+
+	inline void epBank0AckSetupReceived(ep_t ep)    { usb.DeviceEndpoint[ep].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_RXSTP; }
+	inline void epBank0AckStalled(ep_t ep)          { usb.DeviceEndpoint[ep].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_STALL(1); }
+	inline void epBank1AckStalled(ep_t ep)          { usb.DeviceEndpoint[ep].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_STALL(2); }
+	inline void epBank0AckTransferComplete(ep_t ep) { usb.DeviceEndpoint[ep].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_TRCPT(1); }
+	inline void epBank1AckTransferComplete(ep_t ep) { usb.DeviceEndpoint[ep].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_TRCPT(2); }
+
+	inline void epBank0EnableSetupReceived(ep_t ep)    { usb.DeviceEndpoint[ep].EPINTENSET.bit.RXSTP = 1; }
+	inline void epBank0EnableStalled(ep_t ep)          { usb.DeviceEndpoint[ep].EPINTENSET.bit.STALL0 = 1; }
+	inline void epBank1EnableStalled(ep_t ep)          { usb.DeviceEndpoint[ep].EPINTENSET.bit.STALL1 = 1; }
+	inline void epBank0EnableTransferComplete(ep_t ep) { usb.DeviceEndpoint[ep].EPINTENSET.bit.TRCPT0 = 1; }
+	inline void epBank1EnableTransferComplete(ep_t ep) { usb.DeviceEndpoint[ep].EPINTENSET.bit.TRCPT1 = 1; }
+
+	inline void epBank0DisableSetupReceived(ep_t ep)    { usb.DeviceEndpoint[ep].EPINTENCLR.bit.RXSTP = 1; }
+	inline void epBank0DisableStalled(ep_t ep)          { usb.DeviceEndpoint[ep].EPINTENCLR.bit.STALL0 = 1; }
+	inline void epBank1DisableStalled(ep_t ep)          { usb.DeviceEndpoint[ep].EPINTENCLR.bit.STALL1 = 1; }
+	inline void epBank0DisableTransferComplete(ep_t ep) { usb.DeviceEndpoint[ep].EPINTENCLR.bit.TRCPT0 = 1; }
+	inline void epBank1DisableTransferComplete(ep_t ep) { usb.DeviceEndpoint[ep].EPINTENCLR.bit.TRCPT1 = 1; }
+
+	// Status
+	inline bool epBank0IsReady(ep_t ep)    { return usb.DeviceEndpoint[ep].EPSTATUS.bit.BK0RDY; }
+	inline bool epBank1IsReady(ep_t ep)    { return usb.DeviceEndpoint[ep].EPSTATUS.bit.BK1RDY; }
+	inline void epBank0SetReady(ep_t ep)   { usb.DeviceEndpoint[ep].EPSTATUSSET.bit.BK0RDY = 1; }
+	inline void epBank1SetReady(ep_t ep)   { usb.DeviceEndpoint[ep].EPSTATUSSET.bit.BK1RDY = 1; }
+	inline void epBank0ResetReady(ep_t ep) { usb.DeviceEndpoint[ep].EPSTATUSCLR.bit.BK0RDY = 1; }
+	inline void epBank1ResetReady(ep_t ep) { usb.DeviceEndpoint[ep].EPSTATUSCLR.bit.BK1RDY = 1; }
+
+	inline void epBank0SetStallReq(ep_t ep)   { usb.DeviceEndpoint[ep].EPSTATUSSET.bit.STALLRQ0 = 1; }
+	inline void epBank1SetStallReq(ep_t ep)   { usb.DeviceEndpoint[ep].EPSTATUSSET.bit.STALLRQ1 = 1; }
+	inline void epBank0ResetStallReq(ep_t ep) { usb.DeviceEndpoint[ep].EPSTATUSCLR.bit.STALLRQ0 = 1; }
+	inline void epBank1ResetStallReq(ep_t ep) { usb.DeviceEndpoint[ep].EPSTATUSCLR.bit.STALLRQ1 = 1; }
+
+	// Packet
+	inline uint16_t epBank0ByteCount(ep_t ep) { return EP[ep].DeviceDescBank[0].PCKSIZE.bit.BYTE_COUNT; }
+	inline uint16_t epBank1ByteCount(ep_t ep) { return EP[ep].DeviceDescBank[1].PCKSIZE.bit.BYTE_COUNT; }
+	inline void epBank0SetByteCount(ep_t ep, uint16_t bc) { EP[ep].DeviceDescBank[0].PCKSIZE.bit.BYTE_COUNT = bc; }
+	inline void epBank1SetByteCount(ep_t ep, uint16_t bc) { EP[ep].DeviceDescBank[1].PCKSIZE.bit.BYTE_COUNT = bc; }
+	inline void epBank0SetMultiPacketSize(ep_t ep, uint16_t s) { EP[ep].DeviceDescBank[0].PCKSIZE.bit.MULTI_PACKET_SIZE = s; }
+	inline void epBank1SetMultiPacketSize(ep_t ep, uint16_t s) { EP[ep].DeviceDescBank[1].PCKSIZE.bit.MULTI_PACKET_SIZE = s; }
+
+	inline void epBank0SetAddress(ep_t ep, void *addr) { EP[ep].DeviceDescBank[0].ADDR.reg = (uint32_t)addr; }
+	inline void epBank1SetAddress(ep_t ep, void *addr) { EP[ep].DeviceDescBank[1].ADDR.reg = (uint32_t)addr; }
+	inline void epBank0SetSize(ep_t ep, uint16_t size) { EP[ep].DeviceDescBank[0].PCKSIZE.bit.SIZE = EP_PCKSIZE_SIZE(size); }
+	inline void epBank1SetSize(ep_t ep, uint16_t size) { EP[ep].DeviceDescBank[1].PCKSIZE.bit.SIZE = EP_PCKSIZE_SIZE(size); }
+	inline uint8_t EP_PCKSIZE_SIZE(uint16_t size) {
+		switch (size) {
+		case 8:    return 0;
+		case 16:   return 1;
+		case 32:   return 2;
+		case 64:   return 3;
+		case 128:  return 4;
+		case 256:  return 5;
+		case 512:  return 6;
+		case 1023: return 7;
+		default:   return 0;
+		}
+	}
+
+	inline void epBank0DisableAutoZLP(ep_t ep) { EP[ep].DeviceDescBank[0].PCKSIZE.bit.AUTO_ZLP = 0; }
+	inline void epBank1DisableAutoZLP(ep_t ep) { EP[ep].DeviceDescBank[1].PCKSIZE.bit.AUTO_ZLP = 0; }
+	inline void epBank0EnableAutoZLP(ep_t ep)  { EP[ep].DeviceDescBank[0].PCKSIZE.bit.AUTO_ZLP = 1; }
+	inline void epBank1EnableAutoZLP(ep_t ep)  { EP[ep].DeviceDescBank[1].PCKSIZE.bit.AUTO_ZLP = 1; }
+
+private:
+	// USB Device registers
+	UsbDevice &usb;
+
+	// Endpoints descriptors table
+	__attribute__((__aligned__(4)))	UsbDeviceDescriptor EP[USB_EPT_NUM];
+};
+
+void USBDevice_SAMR21G18x::reset() {
+	usb.CTRLA.bit.SWRST = 1;
+	memset(EP, 0, sizeof(EP));
+	while (usb.SYNCBUSY.bit.SWRST) {}
+	usb.DESCADD.reg = (uint32_t)(&EP);
+}
+
+void USBDevice_SAMR21G18x::calibrate() {
+	// Load Pad Calibration data from non-volatile memory
+	uint32_t *pad_transn_p = (uint32_t *) USB_FUSES_TRANSN_ADDR;
+	uint32_t *pad_transp_p = (uint32_t *) USB_FUSES_TRANSP_ADDR;
+	uint32_t *pad_trim_p   = (uint32_t *) USB_FUSES_TRIM_ADDR;
+
+	uint32_t pad_transn = (*pad_transn_p & USB_FUSES_TRANSN_Msk) >> USB_FUSES_TRANSN_Pos;
+	uint32_t pad_transp = (*pad_transp_p & USB_FUSES_TRANSP_Msk) >> USB_FUSES_TRANSP_Pos;
+	uint32_t pad_trim   = (*pad_trim_p   & USB_FUSES_TRIM_Msk  ) >> USB_FUSES_TRIM_Pos;
+
+	if (pad_transn == 0x1F)  // maximum value (31)
+		pad_transn = 5;
+	if (pad_transp == 0x1F)  // maximum value (31)
+		pad_transp = 29;
+	if (pad_trim == 0x7)     // maximum value (7)
+		pad_trim = 3;
+
+	usb.PADCAL.bit.TRANSN = pad_transn;
+	usb.PADCAL.bit.TRANSP = pad_transp;
+	usb.PADCAL.bit.TRIM   = pad_trim;
+}
+
diff --git a/cores/arduino/USB/USBAPI.h b/cores/arduino/USB/USBAPI.h
index 379f55ed3..6c235867e 100644
--- a/cores/arduino/USB/USBAPI.h
+++ b/cores/arduino/USB/USBAPI.h
@@ -31,10 +31,17 @@
 
 #include "Stream.h"
 #include "RingBuffer.h"
+#ifdef __SAMR21G18A__
+#include "SAMR21_USBDevice.h"
+#else
+#include "SAMD21_USBDevice.h"
+#endif
 
 //================================================================================
 // USB
 
+class EPHandler;
+
 // Low level API
 typedef struct {
 	union {
@@ -86,6 +93,7 @@ class USBDeviceClass {
 	// Generic EndPoint API
 	void initEndpoints(void);
 	void initEP(uint32_t ep, uint32_t type);
+	void setHandler(uint32_t ep, EPHandler *handler);
 	void handleEndpoint(uint8_t ep);
 
 	uint32_t send(uint32_t ep, const void *data, uint32_t len);
@@ -178,7 +186,7 @@ class Serial_ : public Stream
 	RingBuffer *_cdc_rx_buffer;
 	bool stalled;
 };
-extern Serial_ SerialUSB;
+extern Serial_ Serial;
 
 //================================================================================
 //================================================================================
diff --git a/cores/arduino/USB/USBCore.cpp b/cores/arduino/USB/USBCore.cpp
index ee7b90a44..2154fe589 100644
--- a/cores/arduino/USB/USBCore.cpp
+++ b/cores/arduino/USB/USBCore.cpp
@@ -1,5 +1,6 @@
 /*
   Copyright (c) 2016 Arduino LLC.  All right reserved.
+  SAMD51 support added by Adafruit - Copyright (c) 2018 Dean Miller for Adafruit Industries
 
   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
@@ -15,12 +16,18 @@
   License along with this library; if not, write to the Free Software
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */
-
+#ifndef USE_TINYUSB
 #if defined(USBCON)
 
 #include <Arduino.h>
 
-#include "SAMD21_USBDevice.h"
+// there are ~slight~ CMSIS differences :/
+#ifdef __SAMR21G18A__
+  #include "SAMR21_USBDevice.h"
+#else
+  #include "SAMD21_USBDevice.h"
+#endif
+
 #include "PluggableUSB.h"
 
 #include <stdlib.h>
@@ -28,7 +35,12 @@
 #include <stdint.h>
 #include <limits.h>
 
+#ifdef __SAMR21G18A__
+USBDevice_SAMR21G18x usbd;
+#else
 USBDevice_SAMD21G18x usbd;
+#endif
+
 
 /** Pulse generation counters to keep track of the number of milliseconds remaining for each pulse type */
 #define TX_RX_LED_PULSE_MS 100
@@ -232,19 +244,24 @@ bool USBDeviceClass::sendDescriptor(USBSetup &setup)
 		}
 		else if (setup.wValueL == ISERIAL) {
 #ifdef PLUGGABLE_USB_ENABLED
+#ifdef __SAMD51__
+			#define SERIAL_NUMBER_WORD_0	*(volatile uint32_t*)(0x008061FC)
+			#define SERIAL_NUMBER_WORD_1	*(volatile uint32_t*)(0x00806010)
+			#define SERIAL_NUMBER_WORD_2	*(volatile uint32_t*)(0x00806014)
+			#define SERIAL_NUMBER_WORD_3	*(volatile uint32_t*)(0x00806018)
+#else // samd21
 			// from section 9.3.3 of the datasheet
 			#define SERIAL_NUMBER_WORD_0	*(volatile uint32_t*)(0x0080A00C)
 			#define SERIAL_NUMBER_WORD_1	*(volatile uint32_t*)(0x0080A040)
 			#define SERIAL_NUMBER_WORD_2	*(volatile uint32_t*)(0x0080A044)
 			#define SERIAL_NUMBER_WORD_3	*(volatile uint32_t*)(0x0080A048)
-
+#endif
 			char name[ISERIAL_MAX_LEN];
 			utox8(SERIAL_NUMBER_WORD_0, &name[0]);
 			utox8(SERIAL_NUMBER_WORD_1, &name[8]);
 			utox8(SERIAL_NUMBER_WORD_2, &name[16]);
 			utox8(SERIAL_NUMBER_WORD_3, &name[24]);
-
-			PluggableUSB().getShortName(&name[32]);
+			name[32] = '\0';
 			return sendStringDescriptor((uint8_t*)name, setup.wLength);
 #endif
 		}
@@ -313,9 +330,24 @@ void USBDeviceClass::init()
 	digitalWrite(PIN_LED_RXL, HIGH);
 #endif
 
-	// Enable USB clock
+	/* Enable USB clock */
+#if defined(__SAMD51__)
+	MCLK->APBBMASK.reg |= MCLK_APBBMASK_USB;
+	MCLK->AHBMASK.reg |= MCLK_AHBMASK_USB;
+	
+	// Set up the USB DP/DN pins
+	PORT->Group[0].PINCFG[PIN_PA24H_USB_DM].bit.PMUXEN = 1;
+	PORT->Group[0].PMUX[PIN_PA24H_USB_DM/2].reg &= ~(0xF << (4 * (PIN_PA24H_USB_DM & 0x01u)));
+	PORT->Group[0].PMUX[PIN_PA24H_USB_DM/2].reg |= MUX_PA24H_USB_DM << (4 * (PIN_PA24H_USB_DM & 0x01u));
+	PORT->Group[0].PINCFG[PIN_PA25H_USB_DP].bit.PMUXEN = 1;
+	PORT->Group[0].PMUX[PIN_PA25H_USB_DP/2].reg &= ~(0xF << (4 * (PIN_PA25H_USB_DP & 0x01u)));
+	PORT->Group[0].PMUX[PIN_PA25H_USB_DP/2].reg |= MUX_PA25H_USB_DP << (4 * (PIN_PA25H_USB_DP & 0x01u));
+	
+	
+	GCLK->PCHCTRL[USB_GCLK_ID].reg = GCLK_PCHCTRL_GEN_GCLK1_Val | (1 << GCLK_PCHCTRL_CHEN_Pos);
+#else
 	PM->APBBMASK.reg |= PM_APBBMASK_USB;
-
+	
 	// Set up the USB DP/DN pins
 	PORT->Group[0].PINCFG[PIN_PA24G_USB_DM].bit.PMUXEN = 1;
 	PORT->Group[0].PMUX[PIN_PA24G_USB_DM/2].reg &= ~(0xF << (4 * (PIN_PA24G_USB_DM & 0x01u)));
@@ -326,10 +358,11 @@ void USBDeviceClass::init()
 
 	// Put Generic Clock Generator 0 as source for Generic Clock Multiplexer 6 (USB reference)
 	GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(6)     | // Generic Clock Multiplexer 6
-	                    GCLK_CLKCTRL_GEN_GCLK0 | // Generic Clock Generator 0 is source
-	                    GCLK_CLKCTRL_CLKEN;
+	GCLK_CLKCTRL_GEN_GCLK0 | // Generic Clock Generator 0 is source
+	GCLK_CLKCTRL_CLKEN;
 	while (GCLK->STATUS.bit.SYNCBUSY)
-		;
+	;
+#endif
 
 	USB_SetHandler(&UDD_Handler);
 
@@ -342,8 +375,20 @@ void USBDeviceClass::init()
 	usbd.setFullSpeed();
 
 	// Configure interrupts
+#if defined(__SAMD51__)
+	/* Attach to the USB host */
+	NVIC_SetPriority(USB_0_IRQn, 0UL);
+	NVIC_SetPriority(USB_1_IRQn, 0UL);
+	NVIC_SetPriority(USB_2_IRQn, 0UL);
+	NVIC_SetPriority(USB_3_IRQn, 0UL);
+	NVIC_EnableIRQ(USB_0_IRQn);
+	NVIC_EnableIRQ(USB_1_IRQn);
+	NVIC_EnableIRQ(USB_2_IRQn);
+	NVIC_EnableIRQ(USB_3_IRQn);
+#else
 	NVIC_SetPriority((IRQn_Type) USB_IRQn, 0UL);
 	NVIC_EnableIRQ((IRQn_Type) USB_IRQn);
+#endif
 
 	usbd.enable();
 
@@ -356,6 +401,7 @@ bool USBDeviceClass::attach()
 		return false;
 
 	usbd.attach();
+
 	usbd.enableEndOfResetInterrupt();
 	usbd.enableStartOfFrameInterrupt();
 
@@ -466,6 +512,12 @@ void USBDeviceClass::initEP(uint32_t ep, uint32_t config)
 		}
 		epHandlers[ep] = new DoubleBufferedEPOutHandler(usbd, ep, 256);
 	}
+	else if (config == (USB_ENDPOINT_TYPE_INTERRUPT | USB_ENDPOINT_OUT(0)))
+    {
+	    if(epHandlers[ep]){
+	        epHandlers[ep]->init();
+	    }
+    }
 	else if (config == (USB_ENDPOINT_TYPE_BULK | USB_ENDPOINT_IN(0)))
 	{
 		usbd.epBank1SetSize(ep, 64);
@@ -497,6 +549,10 @@ void USBDeviceClass::initEP(uint32_t ep, uint32_t config)
 	}
 }
 
+void USBDeviceClass::setHandler(uint32_t ep, EPHandler *handler) {
+    epHandlers[ep] = handler;
+}
+
 void USBDeviceClass::flush(uint32_t ep)
 {
 	if (available(ep)) {
@@ -692,8 +748,8 @@ uint32_t USBDeviceClass::send(uint32_t ep, const void *data, uint32_t len)
 
 		LastTransmitTimedOut[ep] = 0;
 
-		if (len >= EPX_SIZE) {
-			length = EPX_SIZE - 1;
+		if (len > EPX_SIZE) {
+			length = EPX_SIZE;
 		} else {
 			length = len;
 		}
@@ -821,6 +877,7 @@ bool USBDeviceClass::handleStandardSetup(USBSetup &setup)
 			sendZlp(0);
 			return true;
 		}
+		return false;
 
 	case SET_ADDRESS:
 		setAddress(setup.wValueL);
@@ -954,6 +1011,7 @@ void USBDeviceClass::ISRHandler()
 		// Check if endpoint has a pending interrupt
 		if ((ept_int & (1 << i)) != 0)
 		{
+
 			// Endpoint Transfer Complete (0/1) Interrupt
 			if (usbd.epBank0IsTransferComplete(i) ||
 			    usbd.epBank1IsTransferComplete(i))
@@ -981,3 +1039,4 @@ void USBDeviceClass::ISRHandler()
 USBDeviceClass USBDevice;
 
 #endif
+#endif // USE_TINYUSB
diff --git a/cores/arduino/USB/USBCore.h b/cores/arduino/USB/USBCore.h
index 75fd9e3d3..89fe8db63 100644
--- a/cores/arduino/USB/USBCore.h
+++ b/cores/arduino/USB/USBCore.h
@@ -101,7 +101,7 @@
 // bMaxPower in Configuration Descriptor
 #define USB_CONFIG_POWER_MA(mA)                ((mA)/2)
 #ifndef USB_CONFIG_POWER
- #define USB_CONFIG_POWER                      (500)
+ #define USB_CONFIG_POWER                      (100)
 #endif
 
 #define CDC_V1_10                               0x0110
diff --git a/cores/arduino/USB/samd21_host.c b/cores/arduino/USB/samd21_host.c
index 1a8ae3049..7d59f9c45 100644
--- a/cores/arduino/USB/samd21_host.c
+++ b/cores/arduino/USB/samd21_host.c
@@ -1,5 +1,6 @@
 /*
   Copyright (c) 2014 Arduino LLC.  All right reserved.
+  SAMD51 support added by Adafruit - Copyright (c) 2018 Dean Miller for Adafruit Industries
 
   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
@@ -16,6 +17,7 @@
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */
 
+#ifndef USE_TINYUSB
 
 #include <stdio.h>
 #include <stdint.h>
@@ -66,7 +68,11 @@ void UHD_Init(void)
 	USB_SetHandler(&UHD_Handler);
 
 	/* Enable USB clock */
+#if defined(__SAMD51__)
+	MCLK->APBBMASK.reg |= MCLK_APBBMASK_USB;
+#else
 	PM->APBBMASK.reg |= PM_APBBMASK_USB;
+#endif
 
 	/* Set up the USB DP/DM pins */
 	pinPeripheral( PIN_USB_DM, PIO_COM );
@@ -78,9 +84,14 @@ void UHD_Init(void)
 // 	PORT->Group[0].PMUX[PIN_PA25G_USB_DP/2].reg &= ~(0xF << (4 * (PIN_PA25G_USB_DP & 0x01u)));
 // 	PORT->Group[0].PMUX[PIN_PA25G_USB_DP/2].reg |= MUX_PA25G_USB_DP << (4 * (PIN_PA25G_USB_DP & 0x01u));
 
+
 	/* ----------------------------------------------------------------------------------------------
 	* Put Generic Clock Generator 0 as source for Generic Clock Multiplexer 6 (USB reference)
 	*/
+	
+#if defined(__SAMD51__)
+	GCLK->PCHCTRL[USB_GCLK_ID].reg = GCLK_PCHCTRL_GEN_GCLK1_Val | (1 << GCLK_PCHCTRL_CHEN_Pos);
+#else
 	GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(6) |        // Generic Clock Multiplexer 6
 						GCLK_CLKCTRL_GEN_GCLK0 |    // Generic Clock Generator 0 is source
 						GCLK_CLKCTRL_CLKEN;
@@ -89,6 +100,7 @@ void UHD_Init(void)
 	{
 		/* Wait for synchronization */
 	}
+#endif
 
 	/* Reset */
 	USB->HOST.CTRLA.bit.SWRST = 1;
@@ -102,8 +114,14 @@ void UHD_Init(void)
 	uhd_force_host_mode();
 	while (USB->HOST.SYNCBUSY.reg == USB_SYNCBUSY_ENABLE);
 
+
 	/* Load Pad Calibration */
+#if defined(__SAMD51__)
+	pad_transn = (*((uint32_t *)(NVMCTRL_SW0)       // Non-Volatile Memory Controller
+#else
 	pad_transn = (*((uint32_t *)(NVMCTRL_OTP4)       // Non-Volatile Memory Controller
+#endif
+
 					+ (NVM_USB_PAD_TRANSN_POS / 32))
 					>> (NVM_USB_PAD_TRANSN_POS % 32))
 				& ((1 << NVM_USB_PAD_TRANSN_SIZE) - 1);
@@ -115,7 +133,11 @@ void UHD_Init(void)
 
 	USB->HOST.PADCAL.bit.TRANSN = pad_transn;
 
+#if defined(__SAMD51__)
+	pad_transp = (*((uint32_t *)(NVMCTRL_SW0)
+#else
 	pad_transp = (*((uint32_t *)(NVMCTRL_OTP4)
+#endif
 					+ (NVM_USB_PAD_TRANSP_POS / 32))
 					>> (NVM_USB_PAD_TRANSP_POS % 32))
 				& ((1 << NVM_USB_PAD_TRANSP_SIZE) - 1);
@@ -127,7 +149,11 @@ void UHD_Init(void)
 
 	USB->HOST.PADCAL.bit.TRANSP = pad_transp;
 
+#if defined(__SAMD51__)
+	pad_trim = (*((uint32_t *)(NVMCTRL_SW0)
+#else
 	pad_trim = (*((uint32_t *)(NVMCTRL_OTP4)
+#endif
 					+ (NVM_USB_PAD_TRIM_POS / 32))
 				>> (NVM_USB_PAD_TRIM_POS % 32))
 				& ((1 << NVM_USB_PAD_TRIM_SIZE) - 1);
@@ -163,8 +189,20 @@ void UHD_Init(void)
 	USB->HOST.CTRLB.bit.VBUSOK = 1;
 
 	// Configure interrupts
+#if defined(__SAMD51__)
+	NVIC_SetPriority((IRQn_Type)USB_0_IRQn, 0UL);
+	NVIC_SetPriority((IRQn_Type)USB_1_IRQn, 0UL);
+	NVIC_SetPriority((IRQn_Type)USB_2_IRQn, 0UL);
+	NVIC_SetPriority((IRQn_Type)USB_3_IRQn, 0UL);
+
+	NVIC_EnableIRQ((IRQn_Type)USB_0_IRQn);
+	NVIC_EnableIRQ((IRQn_Type)USB_1_IRQn);
+	NVIC_EnableIRQ((IRQn_Type)USB_2_IRQn);
+	NVIC_EnableIRQ((IRQn_Type)USB_3_IRQn);
+#else
 	NVIC_SetPriority((IRQn_Type)USB_IRQn, 0UL);
 	NVIC_EnableIRQ((IRQn_Type)USB_IRQn);
+#endif
 }
 
 
@@ -516,3 +554,5 @@ uint32_t UHD_Pipe_Is_Transfer_Complete(uint32_t ul_pipe, uint32_t ul_token_type)
 // }
 
 #endif //  HOST_DEFINED
+
+#endif // USE_TINYUSB
diff --git a/cores/arduino/WInterrupts.c b/cores/arduino/WInterrupts.c
index c78ddf62b..85b744673 100644
--- a/cores/arduino/WInterrupts.c
+++ b/cores/arduino/WInterrupts.c
@@ -1,5 +1,6 @@
 /*
   Copyright (c) 2015 Arduino LLC.  All right reserved.
+  SAMD51 support added by Adafruit - Copyright (c) 2018 Dean Miller for Adafruit Industries
 
   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
@@ -33,6 +34,19 @@ static void __initialize()
   memset(ISRcallback, 0, sizeof(ISRcallback));
   nints = 0;
 
+#if defined(__SAMD51__)
+  ///EIC MCLK is enabled by default
+  for (uint32_t i = 0; i <= 15; i++)     // EIC_0_IRQn = 12 ... EIC_15_IRQn = 27
+  {
+    uint8_t irqn = EIC_0_IRQn + i;
+    NVIC_DisableIRQ(irqn);
+    NVIC_ClearPendingIRQ(irqn);
+    NVIC_SetPriority(irqn, 0);
+    NVIC_EnableIRQ(irqn);
+  }
+  
+  GCLK->PCHCTRL[EIC_GCLK_ID].reg = GCLK_PCHCTRL_GEN_GCLK2_Val | (1 << GCLK_PCHCTRL_CHEN_Pos);
+#else
   NVIC_DisableIRQ(EIC_IRQn);
   NVIC_ClearPendingIRQ(EIC_IRQn);
   NVIC_SetPriority(EIC_IRQn, 0);
@@ -40,6 +54,7 @@ static void __initialize()
 
   // Enable GCLK for IEC (External Interrupt Controller)
   GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID(GCM_EIC));
+#endif
 
 /* Shall we do that?
   // Do a software reset on EIC
@@ -48,8 +63,13 @@ static void __initialize()
 */
 
   // Enable EIC
+#if defined(__SAMD51__)
+  EIC->CTRLA.bit.ENABLE = 1;
+  while (EIC->SYNCBUSY.bit.ENABLE == 1) { }
+#else
   EIC->CTRL.bit.ENABLE = 1;
   while (EIC->STATUS.bit.SYNCBUSY == 1) { }
+#endif
 }
 
 /*
@@ -58,88 +78,129 @@ static void __initialize()
  */
 void attachInterrupt(uint32_t pin, voidFuncPtr callback, uint32_t mode)
 {
-  static int enabled = 0;
-  uint32_t config;
-  uint32_t pos;
+	static int enabled = 0;
+	uint32_t config;
+	uint32_t pos;
 
-#if ARDUINO_SAMD_VARIANT_COMPLIANCE >= 10606
-  EExt_Interrupts in = g_APinDescription[pin].ulExtInt;
-#else
-  EExt_Interrupts in = digitalPinToInterrupt(pin);
-#endif
-  if (in == NOT_AN_INTERRUPT || in == EXTERNAL_INT_NMI)
-    return;
+	#if ARDUINO_SAMD_VARIANT_COMPLIANCE >= 10606
+	EExt_Interrupts in = g_APinDescription[pin].ulExtInt;
+	#else
+	EExt_Interrupts in = digitalPinToInterrupt(pin);
+	#endif
+	if (in == NOT_AN_INTERRUPT) return;
 
-  if (!enabled) {
-    __initialize();
-    enabled = 1;
-  }
+	if (!enabled) {
+		__initialize();
+		enabled = 1;
+	}
+	uint32_t inMask = (1UL << in);
+	// Enable wakeup capability on pin in case being used during sleep
+	#if defined(__SAMD51__)
+	//I believe this is done automatically
+	#else
+	EIC->WAKEUP.reg |= (1 << in);
+	#endif
 
-  // Enable wakeup capability on pin in case being used during sleep
-  uint32_t inMask = 1 << in;
-  EIC->WAKEUP.reg |= inMask;
+	// Only store when there is really an ISR to call.
+	// This allow for calling attachInterrupt(pin, NULL, mode), we set up all needed register
+	// but won't service the interrupt, this way we also don't need to check it inside the ISR.
+	if (callback)
+	{
+		if (in == EXTERNAL_INT_NMI) {
+			EIC->NMIFLAG.bit.NMI = 1; // Clear flag
+			switch (mode) {
+			  case LOW:
+				EIC->NMICTRL.bit.NMISENSE = EIC_NMICTRL_NMISENSE_LOW;
+				break;
 
-  // Assign pin to EIC
-  pinPeripheral(pin, PIO_EXTINT);
+			  case HIGH:
+				EIC->NMICTRL.bit.NMISENSE = EIC_NMICTRL_NMISENSE_HIGH;
+				break;
 
-  // Only store when there is really an ISR to call.
-  // This allow for calling attachInterrupt(pin, NULL, mode), we set up all needed register
-  // but won't service the interrupt, this way we also don't need to check it inside the ISR.
-  if (callback)
-  {
-    // Store interrupts to service in order of when they were attached
-    // to allow for first come first serve handler
-    uint32_t current = 0;
-
-    // Check if we already have this interrupt
-    for (current=0; current<nints; current++) {
-      if (ISRlist[current] == inMask) {
-        break;
-      }
-    }
-    if (current == nints) {
-      // Need to make a new entry
-      nints++;
-    }
-    ISRlist[current] = inMask;       // List of interrupt in order of when they were attached
-    ISRcallback[current] = callback; // List of callback adresses
-
-    // Look for right CONFIG register to be addressed
-    if (in > EXTERNAL_INT_7) {
-      config = 1;
-      pos = (in - 8) << 2;
-    } else {
-      config = 0;
-      pos = in << 2;
-    }
+			  case CHANGE:
+				EIC->NMICTRL.bit.NMISENSE = EIC_NMICTRL_NMISENSE_BOTH;
+				break;
 
-    // Configure the interrupt mode
-    EIC->CONFIG[config].reg &=~ (EIC_CONFIG_SENSE0_Msk << pos); // Reset sense mode, important when changing trigger mode during runtime
-    switch (mode)
-    {
-      case LOW:
-        EIC->CONFIG[config].reg |= EIC_CONFIG_SENSE0_LOW_Val << pos;
-        break;
+			  case FALLING:
+				EIC->NMICTRL.bit.NMISENSE = EIC_NMICTRL_NMISENSE_FALL;
+				break;
 
-      case HIGH:
-        EIC->CONFIG[config].reg |= EIC_CONFIG_SENSE0_HIGH_Val << pos;
-        break;
+			  case RISING:
+				EIC->NMICTRL.bit.NMISENSE = EIC_NMICTRL_NMISENSE_RISE;
+				break;
+			}
 
-      case CHANGE:
-        EIC->CONFIG[config].reg |= EIC_CONFIG_SENSE0_BOTH_Val << pos;
-        break;
+			// Assign callback to interrupt
+			ISRcallback[EXTERNAL_INT_NMI] = callback;
 
-      case FALLING:
-        EIC->CONFIG[config].reg |= EIC_CONFIG_SENSE0_FALL_Val << pos;
-        break;
+		} else { // Not NMI, is external interrupt
 
-      case RISING:
-        EIC->CONFIG[config].reg |= EIC_CONFIG_SENSE0_RISE_Val << pos;
-        break;
-    }
-  }
-  // Enable the interrupt
-  EIC->INTENSET.reg = EIC_INTENSET_EXTINT(inMask);
+			// Assign pin to EIC
+			pinPeripheral(pin, PIO_EXTINT);
+
+			// Store interrupts to service in order of when they were attached
+			// to allow for first come first serve handler
+			uint32_t current = 0;
+
+			// Check if we already have this interrupt
+			for (current=0; current<nints; current++) {
+			  if (ISRlist[current] == inMask) {
+				break;
+			  }
+			}
+			if (current == nints) {
+			  // Need to make a new entry
+			  nints++;
+			}
+			ISRlist[current] = inMask;       // List of interrupt in order of when they were attached
+			ISRcallback[current] = callback; // List of callback adresses
+
+			// Look for right CONFIG register to be addressed
+			if (in > EXTERNAL_INT_7) {
+			  config = 1;
+			  pos = (in - 8) << 2;
+			} else {
+			  config = 0;
+			  pos = in << 2;
+			}
+
+			#if defined (__SAMD51__)
+			EIC->CTRLA.bit.ENABLE = 0;
+			while (EIC->SYNCBUSY.bit.ENABLE == 1) { }
+			#endif
+
+			EIC->CONFIG[config].reg &=~ (EIC_CONFIG_SENSE0_Msk << pos); // Reset sense mode, important when changing trigger mode during runtime
+			switch (mode)
+			{
+			  case LOW:
+				EIC->CONFIG[config].reg |= EIC_CONFIG_SENSE0_LOW_Val << pos;
+				break;
+
+			  case HIGH:
+				EIC->CONFIG[config].reg |= EIC_CONFIG_SENSE0_HIGH_Val << pos;
+				break;
+
+			  case CHANGE:
+				EIC->CONFIG[config].reg |= EIC_CONFIG_SENSE0_BOTH_Val << pos;
+				break;
+
+			  case FALLING:
+				EIC->CONFIG[config].reg |= EIC_CONFIG_SENSE0_FALL_Val << pos;
+				break;
+
+			  case RISING:
+				EIC->CONFIG[config].reg |= EIC_CONFIG_SENSE0_RISE_Val << pos;
+				break;
+			}
+		}
+		// Enable the interrupt
+		EIC->INTENSET.reg = EIC_INTENSET_EXTINT(1 << in);
+	}
+
+	#if defined (__SAMD51__)
+	EIC->CTRLA.bit.ENABLE = 1;
+	while (EIC->SYNCBUSY.bit.ENABLE == 1) { }
+	#endif
 }
 
 /*
@@ -152,19 +213,26 @@ void detachInterrupt(uint32_t pin)
 #else
   EExt_Interrupts in = digitalPinToInterrupt(pin);
 #endif 
-  if (in == NOT_AN_INTERRUPT || in == EXTERNAL_INT_NMI)
-    return;
+  if (in == NOT_AN_INTERRUPT) return;
 
-  uint32_t inMask = 1 << in;
-  EIC->INTENCLR.reg = EIC_INTENCLR_EXTINT(inMask);
+  if(in == EXTERNAL_INT_NMI) {
+    EIC->NMICTRL.bit.NMISENSE = 0; // Turn off detection
+  } else {
+    EIC->INTENCLR.reg = EIC_INTENCLR_EXTINT(1 << in);
   
   // Disable wakeup capability on pin during sleep
-  EIC->WAKEUP.reg &= ~inMask;
+#if defined(__SAMD51__)
+//I believe this is done automatically
+#else
+    // Disable wakeup capability on pin during sleep
+  EIC->WAKEUP.reg &= ~(1 << in);
+#endif
+  }
 
   // Remove callback from the ISR list
   uint32_t current;
   for (current=0; current<nints; current++) {
-    if (ISRlist[current] == inMask) {
+    if (ISRlist[current] == (1UL << in)) {
       break;
     }
   }
@@ -181,6 +249,107 @@ void detachInterrupt(uint32_t pin)
 /*
  * External Interrupt Controller NVIC Interrupt Handler
  */
+#if defined(__SAMD51__)
+void InterruptHandler(uint32_t unused_i)
+{
+  (void)unused_i;
+  // Calling the routine directly from -here- takes about 1us
+  // Depending on where you are in the list it will take longer
+
+  // Loop over all enabled interrupts in the list
+  for (uint32_t i=0; i<nints; i++)
+  {
+	if ((EIC->INTFLAG.reg & ISRlist[i]) != 0)
+	{
+	  // Call the callback function
+	  ISRcallback[i]();
+	  // Clear the interrupt
+	  EIC->INTFLAG.reg = ISRlist[i];
+	}
+  }
+}
+
+void EIC_0_Handler(void)
+{
+  InterruptHandler(EXTERNAL_INT_0);
+}
+
+void EIC_1_Handler(void)
+{
+  InterruptHandler(EXTERNAL_INT_1);
+}
+
+void EIC_2_Handler(void)
+{
+  InterruptHandler(EXTERNAL_INT_2);
+}
+
+void EIC_3_Handler(void)
+{
+  InterruptHandler(EXTERNAL_INT_3);
+}
+
+void EIC_4_Handler(void)
+{
+  InterruptHandler(EXTERNAL_INT_4);
+}
+
+void EIC_5_Handler(void)
+{
+  InterruptHandler(EXTERNAL_INT_5);
+}
+
+void EIC_6_Handler(void)
+{
+  InterruptHandler(EXTERNAL_INT_6);
+}
+
+void EIC_7_Handler(void)
+{
+  InterruptHandler(EXTERNAL_INT_7);
+}
+
+void EIC_8_Handler(void)
+{
+  InterruptHandler(EXTERNAL_INT_8);
+}
+
+void EIC_9_Handler(void)
+{
+  InterruptHandler(EXTERNAL_INT_9);
+}
+
+void EIC_10_Handler(void)
+{
+  InterruptHandler(EXTERNAL_INT_10);
+}
+
+void EIC_11_Handler(void)
+{
+  InterruptHandler(EXTERNAL_INT_11);
+}
+
+void EIC_12_Handler(void)
+{
+  InterruptHandler(EXTERNAL_INT_12);
+}
+
+void EIC_13_Handler(void)
+{
+  InterruptHandler(EXTERNAL_INT_13);
+}
+
+void EIC_14_Handler(void)
+{
+  InterruptHandler(EXTERNAL_INT_14);
+}
+
+void EIC_15_Handler(void)
+{
+  InterruptHandler(EXTERNAL_INT_15);
+}
+#else
+
 void EIC_Handler(void)
 {
   // Calling the routine directly from -here- takes about 1us
@@ -198,3 +367,13 @@ void EIC_Handler(void)
     }
   }
 }
+
+/*
+ * NMI Interrupt Handler
+ */
+void NMI_Handler(void)
+{
+  if (ISRcallback[EXTERNAL_INT_NMI]) ISRcallback[EXTERNAL_INT_NMI]();
+  EIC->NMIFLAG.bit.NMI = 1; // Clear interrupt
+}
+#endif
diff --git a/cores/arduino/WInterrupts.h b/cores/arduino/WInterrupts.h
index 5d2b24a0d..daf02afe5 100644
--- a/cores/arduino/WInterrupts.h
+++ b/cores/arduino/WInterrupts.h
@@ -31,7 +31,7 @@ extern "C" {
 #define FALLING 3
 #define RISING 4
 
-#define DEFAULT 1
+//#define DEFAULT 1
 #define EXTERNAL 0
 
 typedef void (*voidFuncPtr)(void);
diff --git a/cores/arduino/WString.cpp b/cores/arduino/WString.cpp
index 71bbc07d1..ed4e706df 100644
--- a/cores/arduino/WString.cpp
+++ b/cores/arduino/WString.cpp
@@ -693,12 +693,21 @@ void String::remove(unsigned int index){
 }
 
 void String::remove(unsigned int index, unsigned int count){
-	if (index >= len) { return; }
-	if (count <= 0) { return; }
-	if (count > len - index) { count = len - index; }
-	char *writeTo = buffer + index;
+	// removes characters from the middle of a string.
+	if (count <= 0) { return; }   // exit if nothing to remove
+	if (index >= len) { return; } // ensure start is within string length; thus, ensures (len-index >= 1)
+	if (count > len - index) {    // ensure characters to remove is no larger than total length remaining
+		count = len - index;
+	}
+	char *writeTo  = buffer + index;
+	char *copyFrom = buffer + index + count;
 	len = len - count;
-	strncpy(writeTo, buffer + index + count,len - index);
+	
+	// strncpy() cannot be used with overlapping buffers, so copy one char at a time
+	unsigned int charactersToMove = len - index; // yes, uses post-adjusted length
+	for (unsigned int i = 0; i < charactersToMove; i++, writeTo++, copyFrom++) {
+		*writeTo = *copyFrom;
+	}
 	buffer[len] = 0;
 }
 
diff --git a/cores/arduino/WVariant.h b/cores/arduino/WVariant.h
index bbe2e0c4e..3699a3217 100644
--- a/cores/arduino/WVariant.h
+++ b/cores/arduino/WVariant.h
@@ -1,5 +1,6 @@
 /*
   Copyright (c) 2015 Arduino LLC.  All right reserved.
+  SAMD51 support added by Adafruit - Copyright (c) 2018 Dean Miller for Adafruit Industries
 
   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
@@ -20,6 +21,7 @@
 
 #include <stdint.h>
 #include "sam.h"
+#include <limits.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -37,13 +39,13 @@ typedef enum _EAnalogChannel
   ADC_Channel5=5,
   ADC_Channel6=6,
   ADC_Channel7=7,
-#if defined __SAMD21J18A__
+#if defined __SAMD21J18A__ || defined(__SAMD51__)
   ADC_Channel8=8,
   ADC_Channel9=9,
 #endif // __SAMD21J18A__
   ADC_Channel10=10,
   ADC_Channel11=11,
-#if defined __SAMD21J18A__
+#if defined __SAMD21J18A__ || defined(__SAMD51__)
   ADC_Channel12=12,
   ADC_Channel13=13,
   ADC_Channel14=14,
@@ -54,8 +56,134 @@ typedef enum _EAnalogChannel
   ADC_Channel18=18,
   ADC_Channel19=19,
   DAC_Channel0,
+  DAC_Channel1,
+  ADC_Channel_Bandgap=0x1B,
+  ADC_Channel_PTAT=0x1C,
 } EAnalogChannel ;
 
+#if defined(__SAMD51__)
+
+#if defined(__SAMD51G19A__)
+
+typedef enum _ETCChannel
+{
+  NOT_ON_TIMER=-1,
+  TCC0_CH0 = (0<<8)|(0),
+  TCC0_CH1 = (0<<8)|(1),
+  TCC0_CH2 = (0<<8)|(2),
+  TCC0_CH3 = (0<<8)|(3),
+  TCC0_CH4 = (0<<8)|(4),
+  TCC0_CH5 = (0<<8)|(5),
+  TCC1_CH0 = (1<<8)|(0),
+  TCC1_CH1 = (1<<8)|(1),
+  TCC1_CH2 = (1<<8)|(2),
+  TCC1_CH3 = (1<<8)|(3),
+  TCC2_CH0 = (2<<8)|(0),
+  TCC2_CH1 = (2<<8)|(1),
+  TCC2_CH2 = (2<<8)|(2),
+  TC0_CH0 =  (3<<8)|(0),
+  TC0_CH1 =  (3<<8)|(1),
+  TC1_CH0 =  (4<<8)|(0),
+  TC1_CH1 =  (4<<8)|(1),
+  TC2_CH0 =  (5<<8)|(0),
+  TC2_CH1 =  (5<<8)|(1),
+  TC3_CH0 =  (6<<8)|(0),
+  TC3_CH1 =  (6<<8)|(1),
+} ETCChannel ;
+#elif defined(__SAMD51J19A__) || defined(__SAMD51J20A__) || defined(__SAME51J19A__)
+
+typedef enum _ETCChannel
+{
+  NOT_ON_TIMER=-1,
+  TCC0_CH0 = (0<<8)|(0),
+  TCC0_CH1 = (0<<8)|(1),
+  TCC0_CH2 = (0<<8)|(2),
+  TCC0_CH3 = (0<<8)|(3),
+  TCC0_CH4 = (0<<8)|(4),
+  TCC0_CH5 = (0<<8)|(5),
+  TCC0_CH6 = (0<<8)|(6),
+  TCC0_CH7 = (0<<8)|(7),
+  TCC1_CH0 = (1<<8)|(0),
+  TCC1_CH1 = (1<<8)|(1),
+  TCC1_CH2 = (1<<8)|(2),
+  TCC1_CH3 = (1<<8)|(3),
+  TCC1_CH4 = (1<<8)|(4),
+  TCC1_CH5 = (1<<8)|(5),
+  TCC1_CH6 = (1<<8)|(6),
+  TCC1_CH7 = (1<<8)|(7),
+  TCC2_CH0 = (2<<8)|(0),
+  TCC2_CH1 = (2<<8)|(1),
+  TCC2_CH2 = (2<<8)|(2),
+  TCC3_CH0 = (3<<8)|(0),
+  TCC3_CH1 = (3<<8)|(1),
+  TCC4_CH0 = (4<<8)|(0),
+  TCC4_CH1 = (4<<8)|(1),
+  TC0_CH0 =  (5<<8)|(0),
+  TC0_CH1 =  (5<<8)|(1),
+  TC1_CH0 =  (6<<8)|(0),
+  TC1_CH1 =  (6<<8)|(1),
+  TC2_CH0 =  (7<<8)|(0),
+  TC2_CH1 =  (7<<8)|(1),
+  TC3_CH0 =  (8<<8)|(0),
+  TC3_CH1 =  (8<<8)|(1),
+  TC4_CH0 =  (9<<8)|(0),
+  TC4_CH1 =  (9<<8)|(1),
+  TC5_CH0 =  (10<<8)|(0),
+  TC5_CH1 =  (10<<8)|(1),
+  TC6_CH0 =  (11<<8)|(0),
+  TC6_CH1 =  (11<<8)|(1),
+  TC7_CH0 =  (12<<8)|(0),
+  TC7_CH1 =  (12<<8)|(1),
+} ETCChannel ;
+
+#elif defined(__SAMD51P19A__) || defined(__SAMD51P20A__)
+
+typedef enum _ETCChannel
+{
+  NOT_ON_TIMER=-1,
+  TCC0_CH0 = (0<<8)|(0),
+  TCC0_CH1 = (0<<8)|(1),
+  TCC0_CH2 = (0<<8)|(2),
+  TCC0_CH3 = (0<<8)|(3),
+  TCC0_CH4 = (0<<8)|(4),
+  TCC0_CH5 = (0<<8)|(5),
+  TCC1_CH0 = (1<<8)|(0),
+  TCC1_CH1 = (1<<8)|(1),
+  TCC1_CH2 = (1<<8)|(2),
+  TCC1_CH3 = (1<<8)|(3),
+  TCC2_CH0 = (2<<8)|(0),
+  TCC2_CH1 = (2<<8)|(1),
+  TCC2_CH2 = (2<<8)|(2),
+  TCC3_CH0 = (3<<8)|(0),
+  TCC3_CH1 = (3<<8)|(1),
+  TCC4_CH0 = (4<<8)|(0),
+  TCC4_CH1 = (4<<8)|(1),
+  TC0_CH0 =  (5<<8)|(0),
+  TC0_CH1 =  (5<<8)|(1),
+  TC1_CH0 =  (6<<8)|(0),
+  TC1_CH1 =  (6<<8)|(1),
+  TC2_CH0 =  (7<<8)|(0),
+  TC2_CH1 =  (7<<8)|(1),
+  TC3_CH0 =  (8<<8)|(0),
+  TC3_CH1 =  (8<<8)|(1),
+  TC4_CH0 =  (9<<8)|(0),
+  TC4_CH1 =  (9<<8)|(1),
+  TC5_CH0 =  (10<<8)|(0),
+  TC5_CH1 =  (10<<8)|(1),
+  TC6_CH0 =  (11<<8)|(0),
+  TC6_CH1 =  (11<<8)|(1),
+  TC7_CH0 =  (12<<8)|(0),
+  TC7_CH1 =  (12<<8)|(1),
+} ETCChannel ;
+
+#endif
+
+typedef ETCChannel EPWMChannel;
+extern const uint32_t GCLK_CLKCTRL_IDs[TCC_INST_NUM+TC_INST_NUM];
+
+#define NOT_ON_PWM NOT_ON_TIMER
+
+#else
 // Definitions for TC channels
 typedef enum _ETCChannel
 {
@@ -82,20 +210,14 @@ typedef enum _ETCChannel
   TC4_CH1  = (4<<8)|(1),
   TC5_CH0  = (5<<8)|(0),
   TC5_CH1  = (5<<8)|(1),
-#if defined __SAMD21J18A__
-  TC6_CH0  = (6<<8)|(0),
-  TC6_CH1  = (6<<8)|(1),
-  TC7_CH0  = (7<<8)|(0),
-  TC7_CH1  = (7<<8)|(1),
-#endif // __SAMD21J18A__
+  #if defined (__SAMD21J18A__) 
+    TC6_CH0  = (6<<8)|(0),
+    TC6_CH1  = (6<<8)|(1),
+    TC7_CH0  = (7<<8)|(0),
+    TC7_CH1  = (7<<8)|(1),
+  #endif // __SAMD21J18A__
 } ETCChannel ;
 
-extern const void* g_apTCInstances[TCC_INST_NUM+TC_INST_NUM] ;
-
-#define GetTCNumber( x ) ( (x) >> 8 )
-#define GetTCChannelNumber( x ) ( (x) & 0xff )
-#define GetTC( x ) ( g_apTCInstances[(x) >> 8] )
-
 // Definitions for PWM channels
 typedef enum _EPWMChannel
 {
@@ -122,7 +244,7 @@ typedef enum _EPWMChannel
   PWM4_CH1=TC4_CH1,
   PWM5_CH0=TC5_CH0,
   PWM5_CH1=TC5_CH1,
-#if defined __SAMD21J18A__
+#if defined(__SAMD21J18A__)
   PWM6_CH0=TC6_CH0,
   PWM6_CH1=TC6_CH1,
   PWM7_CH0=TC7_CH0,
@@ -130,14 +252,25 @@ typedef enum _EPWMChannel
 #endif // __SAMD21J18A__
 } EPWMChannel ;
 
+#endif
+
+extern const void* g_apTCInstances[TCC_INST_NUM+TC_INST_NUM] ;
+
+#define GetTCNumber( x ) ( (x) >> 8 )
+#define GetTCChannelNumber( x ) ( (x) & 0xff )
+#define GetTC( x ) ( g_apTCInstances[(x) >> 8] )
+
 typedef enum _EPortType
 {
   NOT_A_PORT=-1,
   PORTA=0,
   PORTB=1,
   PORTC=2,
+  PORTD=3,
 } EPortType ;
 
+#define PIN_NOT_A_PIN (UINT_MAX)
+
 typedef enum
 {
   EXTERNAL_INT_0 = 0,
@@ -174,8 +307,19 @@ typedef enum _EPioType
   PIO_SERCOM_ALT,       /* The pin is controlled by the associated signal of peripheral D. */
   PIO_TIMER,            /* The pin is controlled by the associated signal of peripheral E. */
   PIO_TIMER_ALT,        /* The pin is controlled by the associated signal of peripheral F. */
+#if defined(__SAMD51__)
+  PIO_TCC_PDEC,			/* The pin is controlled by the associated signal of peripheral G. */
+  PIO_COM,             /* The pin is controlled by the associated signal of peripheral H. */
+  PIO_SDHC,             /* The pin is controlled by the associated signal of peripheral I. */
+  PIO_I2S,              /* The pin is controlled by the associated signal of peripheral J. */
+  PIO_PCC,              /* The pin is controlled by the associated signal of peripheral K. */
+  PIO_GMAC,             /* The pin is controlled by the associated signal of peripheral L. */
+  PIO_AC_CLK,           /* The pin is controlled by the associated signal of peripheral M. */
+  PIO_CCL,              /* The pin is controlled by the associated signal of peripheral N. */
+#else
   PIO_COM,              /* The pin is controlled by the associated signal of peripheral G. */
   PIO_AC_CLK,           /* The pin is controlled by the associated signal of peripheral H. */
+#endif
   PIO_DIGITAL,          /* The pin is controlled by PORT. */
   PIO_INPUT,            /* The pin is controlled by PORT and is an input. */
   PIO_INPUT_PULLUP,     /* The pin is controlled by PORT and is an input with internal pull-up resistor enabled. */
@@ -192,10 +336,19 @@ typedef enum _EPioType
 #define PIN_ATTR_COMBO         (1UL<<0)
 #define PIN_ATTR_ANALOG        (1UL<<1)
 #define PIN_ATTR_DIGITAL       (1UL<<2)
-#define PIN_ATTR_PWM           (1UL<<3)
 #define PIN_ATTR_TIMER         (1UL<<4)
 #define PIN_ATTR_TIMER_ALT     (1UL<<5)
 #define PIN_ATTR_EXTINT        (1UL<<6)
+#define PIN_ATTR_ANALOG_ALT	   (1UL<<7)
+
+#if defined(__SAMD51__)
+// these correspond to the mux table
+#define PIN_ATTR_PWM_E         (1UL<<3)
+#define PIN_ATTR_PWM_F         (1UL<<8)
+#define PIN_ATTR_PWM_G         (1UL<<9)
+#else
+#define PIN_ATTR_PWM           (1UL<<3)
+#endif
 
 /* Types used for the table below */
 typedef struct _PinDescription
diff --git a/cores/arduino/avr/io.h b/cores/arduino/avr/io.h
index 33d20cdd2..5c395fd26 100644
--- a/cores/arduino/avr/io.h
+++ b/cores/arduino/avr/io.h
@@ -25,8 +25,14 @@
 #ifndef _IO_H_
 #define _IO_H_
 
-#define RAMSTART (HMCRAMC0_ADDR)
-#define RAMSIZE  (HMCRAMC0_SIZE)
+#ifdef __SAMD51__
+  #define RAMSTART (HSRAM_ADDR)
+  #define RAMSIZE  (HSRAM_SIZE)
+#else
+  #define RAMSTART (HMCRAMC0_ADDR)
+  #define RAMSIZE  (HMCRAMC0_SIZE)
+#endif
+
 #define RAMEND   (RAMSTART + RAMSIZE - 1)
 
 #endif
diff --git a/cores/arduino/cortex_handlers.c b/cores/arduino/cortex_handlers.c
index a910d0889..b36ecb1e8 100644
--- a/cores/arduino/cortex_handlers.c
+++ b/cores/arduino/cortex_handlers.c
@@ -1,5 +1,6 @@
 /*
   Copyright (c) 2015 Arduino LLC.  All right reserved.
+  SAMD51 support added by Adafruit - Copyright (c) 2018 Dean Miller for Adafruit Industries
 
   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
@@ -34,6 +35,330 @@ void Dummy_Handler(void)
   for (;;) { }
 }
 
+#if defined(__SAMD51__)
+
+/* Cortex-M4 processor handlers */
+void Reset_Handler               ( void );
+void NMI_Handler                 ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void HardFault_Handler           ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void MemManage_Handler           ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void BusFault_Handler            ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void UsageFault_Handler          ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void SVC_Handler                 ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void DebugMon_Handler            ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void PendSV_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void SysTick_Handler			 ( void );
+
+/* Peripherals handlers */
+void PM_Handler                  ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void MCLK_Handler                ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void OSCCTRL_0_Handler           ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void OSCCTRL_1_Handler           ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void OSCCTRL_2_Handler           ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void OSCCTRL_3_Handler           ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void OSCCTRL_4_Handler           ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void OSC32KCTRL_Handler          ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void SUPC_0_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void SUPC_1_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void WDT_Handler                 ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void RTC_Handler                 ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void EIC_0_Handler               ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void EIC_1_Handler               ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void EIC_2_Handler               ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void EIC_3_Handler               ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void EIC_4_Handler               ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void EIC_5_Handler               ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void EIC_6_Handler               ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void EIC_7_Handler               ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void EIC_8_Handler               ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void EIC_9_Handler               ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void EIC_10_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void EIC_11_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void EIC_12_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void EIC_13_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void EIC_14_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void EIC_15_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void FREQM_Handler               ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void NVMCTRL_0_Handler           ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void NVMCTRL_1_Handler           ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void DMAC_0_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void DMAC_1_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void DMAC_2_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void DMAC_3_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void DMAC_4_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void EVSYS_0_Handler             ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void EVSYS_1_Handler             ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void EVSYS_2_Handler             ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void EVSYS_3_Handler             ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void EVSYS_4_Handler             ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void PAC_Handler                 ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void TAL_0_Handler               ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void TAL_1_Handler               ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void RAMECC_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void SERCOM0_0_Handler           ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void SERCOM0_1_Handler           ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void SERCOM0_2_Handler           ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void SERCOM0_3_Handler           ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void SERCOM1_0_Handler           ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void SERCOM1_1_Handler           ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void SERCOM1_2_Handler           ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void SERCOM1_3_Handler           ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void SERCOM2_0_Handler           ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void SERCOM2_1_Handler           ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void SERCOM2_2_Handler           ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void SERCOM2_3_Handler           ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void SERCOM3_0_Handler           ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void SERCOM3_1_Handler           ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void SERCOM3_2_Handler           ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void SERCOM3_3_Handler           ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void SERCOM4_0_Handler           ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void SERCOM4_1_Handler           ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void SERCOM4_2_Handler           ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void SERCOM4_3_Handler           ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void SERCOM5_0_Handler           ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void SERCOM5_1_Handler           ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void SERCOM5_2_Handler           ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void SERCOM5_3_Handler           ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void SERCOM6_0_Handler           ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void SERCOM6_1_Handler           ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void SERCOM6_2_Handler           ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void SERCOM6_3_Handler           ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void SERCOM7_0_Handler           ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void SERCOM7_1_Handler           ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void SERCOM7_2_Handler           ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void SERCOM7_3_Handler           ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void CAN0_Handler                ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void CAN1_Handler                ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void USB_0_Handler               ( void ) __attribute__ ((weak));
+void USB_1_Handler               ( void ) __attribute__ ((weak));
+void USB_2_Handler               ( void ) __attribute__ ((weak));
+void USB_3_Handler               ( void ) __attribute__ ((weak));
+void TCC0_0_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void TCC0_1_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void TCC0_2_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void TCC0_3_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void TCC0_4_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void TCC0_5_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void TCC0_6_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void TCC1_0_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void TCC1_1_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void TCC1_2_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void TCC1_3_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void TCC1_4_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void TCC2_0_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void TCC2_1_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void TCC2_2_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void TCC2_3_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void TCC3_0_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void TCC3_1_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void TCC3_2_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void TCC4_0_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void TCC4_1_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void TCC4_2_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void TC0_Handler                 ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void TC1_Handler                 ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void TC2_Handler                 ( void ) __attribute__ ((weak)); //used in Tone.cpp
+void TC3_Handler                 ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void TC4_Handler                 ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void TC5_Handler                 ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void TC6_Handler                 ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void TC7_Handler                 ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void PDEC_0_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void PDEC_1_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void PDEC_2_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void ADC0_0_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void ADC0_1_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void ADC1_0_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void ADC1_1_Handler              ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void AC_Handler                  ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void DAC_0_Handler               ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void DAC_1_Handler               ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void DAC_2_Handler               ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void DAC_3_Handler               ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void DAC_4_Handler               ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void I2S_Handler                 ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void PCC_Handler                 ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void AES_Handler                 ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void TRNG_Handler                ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void ICM_Handler                 ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void PUKCC_Handler               ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void QSPI_Handler                ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void SDHC0_Handler               ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+void SDHC1_Handler               ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
+
+/* Initialize segments */
+extern uint32_t __etext;
+extern uint32_t __data_start__;
+extern uint32_t __data_end__;
+extern uint32_t __bss_start__;
+extern uint32_t __bss_end__;
+extern uint32_t __StackTop;
+
+/* Exception Table */
+__attribute__ ((section(".isr_vector"))) const DeviceVectors exception_table =
+{
+	/* Configure Initial Stack Pointer, using linker-generated symbols */
+	(void*) (&__StackTop),
+	
+	/* Cortex-M handlers */
+	(void*) Reset_Handler,
+	(void*) NMI_Handler,
+	(void*) HardFault_Handler,
+	(void*) MemManage_Handler,
+	(void*) BusFault_Handler,
+	(void*) UsageFault_Handler,
+	(void*) (0UL), /* Reserved */
+	(void*) (0UL), /* Reserved */
+	(void*) (0UL), /* Reserved */
+	(void*) (0UL), /* Reserved */
+	(void*) SVC_Handler,
+	(void*) DebugMon_Handler,
+	(void*) (0UL), /* Reserved */
+	(void*) PendSV_Handler,
+	(void*) SysTick_Handler,
+
+	/* Peripheral handlers */
+	  (void*) PM_Handler,                    /*  0 Power Manager */
+	  (void*) MCLK_Handler,                  /*  1 Main Clock */
+	  (void*) OSCCTRL_0_Handler,             /*  2 Oscillators Control IRQ 0 */
+	  (void*) OSCCTRL_1_Handler,             /*  3 Oscillators Control IRQ 1 */
+	  (void*) OSCCTRL_2_Handler,             /*  4 Oscillators Control IRQ 2 */
+	  (void*) OSCCTRL_3_Handler,             /*  5 Oscillators Control IRQ 3 */
+	  (void*) OSCCTRL_4_Handler,             /*  6 Oscillators Control IRQ 4 */
+	  (void*) OSC32KCTRL_Handler,            /*  7 32kHz Oscillators Control */
+	  (void*) SUPC_0_Handler,                /*  8 Supply Controller IRQ 0 */
+	  (void*) SUPC_1_Handler,                /*  9 Supply Controller IRQ 1 */
+	  (void*) WDT_Handler,                   /* 10 Watchdog Timer */
+	  (void*) RTC_Handler,                   /* 11 Real-Time Counter */
+	  (void*) EIC_0_Handler,                 /* 12 External Interrupt Controller IRQ 0 */
+	  (void*) EIC_1_Handler,                 /* 13 External Interrupt Controller IRQ 1 */
+	  (void*) EIC_2_Handler,                 /* 14 External Interrupt Controller IRQ 2 */
+	  (void*) EIC_3_Handler,                 /* 15 External Interrupt Controller IRQ 3 */
+	  (void*) EIC_4_Handler,                 /* 16 External Interrupt Controller IRQ 4 */
+	  (void*) EIC_5_Handler,                 /* 17 External Interrupt Controller IRQ 5 */
+	  (void*) EIC_6_Handler,                 /* 18 External Interrupt Controller IRQ 6 */
+	  (void*) EIC_7_Handler,                 /* 19 External Interrupt Controller IRQ 7 */
+	  (void*) EIC_8_Handler,                 /* 20 External Interrupt Controller IRQ 8 */
+	  (void*) EIC_9_Handler,                 /* 21 External Interrupt Controller IRQ 9 */
+	  (void*) EIC_10_Handler,                /* 22 External Interrupt Controller IRQ 10 */
+	  (void*) EIC_11_Handler,                /* 23 External Interrupt Controller IRQ 11 */
+	  (void*) EIC_12_Handler,                /* 24 External Interrupt Controller IRQ 12 */
+	  (void*) EIC_13_Handler,                /* 25 External Interrupt Controller IRQ 13 */
+	  (void*) EIC_14_Handler,                /* 26 External Interrupt Controller IRQ 14 */
+	  (void*) EIC_15_Handler,                /* 27 External Interrupt Controller IRQ 15 */
+	  (void*) FREQM_Handler,                 /* 28 Frequency Meter */
+	  (void*) NVMCTRL_0_Handler,             /* 29 Non-Volatile Memory Controller IRQ 0 */
+	  (void*) NVMCTRL_1_Handler,             /* 30 Non-Volatile Memory Controller IRQ 1 */
+	  (void*) DMAC_0_Handler,                /* 31 Direct Memory Access Controller IRQ 0 */
+	  (void*) DMAC_1_Handler,                /* 32 Direct Memory Access Controller IRQ 1 */
+	  (void*) DMAC_2_Handler,                /* 33 Direct Memory Access Controller IRQ 2 */
+	  (void*) DMAC_3_Handler,                /* 34 Direct Memory Access Controller IRQ 3 */
+	  (void*) DMAC_4_Handler,                /* 35 Direct Memory Access Controller IRQ 4 */
+	  (void*) EVSYS_0_Handler,               /* 36 Event System Interface IRQ 0 */
+	  (void*) EVSYS_1_Handler,               /* 37 Event System Interface IRQ 1 */
+	  (void*) EVSYS_2_Handler,               /* 38 Event System Interface IRQ 2 */
+	  (void*) EVSYS_3_Handler,               /* 39 Event System Interface IRQ 3 */
+	  (void*) EVSYS_4_Handler,               /* 40 Event System Interface IRQ 4 */
+	  (void*) PAC_Handler,                   /* 41 Peripheral Access Controller */
+	  (void*) TAL_0_Handler,                 /* 42 Trigger Allocator IRQ 0 */
+	  (void*) TAL_1_Handler,                 /* 43 Trigger Allocator IRQ 1 */
+	  (void*) (0UL),
+	  (void*) RAMECC_Handler,                /* 45 RAM ECC */
+	  (void*) SERCOM0_0_Handler,             /* 46 Serial Communication Interface 0 IRQ 0 */
+	  (void*) SERCOM0_1_Handler,             /* 47 Serial Communication Interface 0 IRQ 1 */
+	  (void*) SERCOM0_2_Handler,             /* 48 Serial Communication Interface 0 IRQ 2 */
+	  (void*) SERCOM0_3_Handler,             /* 49 Serial Communication Interface 0 IRQ 3 */
+	  (void*) SERCOM1_0_Handler,             /* 50 Serial Communication Interface 1 IRQ 0 */
+	  (void*) SERCOM1_1_Handler,             /* 51 Serial Communication Interface 1 IRQ 1 */
+	  (void*) SERCOM1_2_Handler,             /* 52 Serial Communication Interface 1 IRQ 2 */
+	  (void*) SERCOM1_3_Handler,             /* 53 Serial Communication Interface 1 IRQ 3 */
+	  (void*) SERCOM2_0_Handler,             /* 54 Serial Communication Interface 2 IRQ 0 */
+	  (void*) SERCOM2_1_Handler,             /* 55 Serial Communication Interface 2 IRQ 1 */
+	  (void*) SERCOM2_2_Handler,             /* 56 Serial Communication Interface 2 IRQ 2 */
+	  (void*) SERCOM2_3_Handler,             /* 57 Serial Communication Interface 2 IRQ 3 */
+	  (void*) SERCOM3_0_Handler,             /* 58 Serial Communication Interface 3 IRQ 0 */
+	  (void*) SERCOM3_1_Handler,             /* 59 Serial Communication Interface 3 IRQ 1 */
+	  (void*) SERCOM3_2_Handler,             /* 60 Serial Communication Interface 3 IRQ 2 */
+	  (void*) SERCOM3_3_Handler,             /* 61 Serial Communication Interface 3 IRQ 3 */
+	  (void*) SERCOM4_0_Handler,             /* 62 Serial Communication Interface 4 IRQ 0 */
+	  (void*) SERCOM4_1_Handler,             /* 63 Serial Communication Interface 4 IRQ 1 */
+	  (void*) SERCOM4_2_Handler,             /* 64 Serial Communication Interface 4 IRQ 2 */
+	  (void*) SERCOM4_3_Handler,             /* 65 Serial Communication Interface 4 IRQ 3 */
+	  (void*) SERCOM5_0_Handler,             /* 66 Serial Communication Interface 5 IRQ 0 */
+	  (void*) SERCOM5_1_Handler,             /* 67 Serial Communication Interface 5 IRQ 1 */
+	  (void*) SERCOM5_2_Handler,             /* 68 Serial Communication Interface 5 IRQ 2 */
+	  (void*) SERCOM5_3_Handler,             /* 69 Serial Communication Interface 5 IRQ 3 */
+	  (void*) SERCOM6_0_Handler,             /* 70 Serial Communication Interface 6 IRQ 0 */
+	  (void*) SERCOM6_1_Handler,             /* 71 Serial Communication Interface 6 IRQ 1 */
+	  (void*) SERCOM6_2_Handler,             /* 72 Serial Communication Interface 6 IRQ 2 */
+	  (void*) SERCOM6_3_Handler,             /* 73 Serial Communication Interface 6 IRQ 3 */
+	  (void*) SERCOM7_0_Handler,             /* 74 Serial Communication Interface 7 IRQ 0 */
+	  (void*) SERCOM7_1_Handler,             /* 75 Serial Communication Interface 7 IRQ 1 */
+	  (void*) SERCOM7_2_Handler,             /* 76 Serial Communication Interface 7 IRQ 2 */
+	  (void*) SERCOM7_3_Handler,             /* 77 Serial Communication Interface 7 IRQ 3 */
+	  (void*) CAN0_Handler,                  /* 78 Control Area Network 0 (SAM E5x) */
+	  (void*) CAN1_Handler,                  /* 79 Control Area Network 0 (SAM E5x) */
+	  (void*) USB_0_Handler,                 /* 80 Universal Serial Bus IRQ 0 */
+	  (void*) USB_1_Handler,                 /* 81 Universal Serial Bus IRQ 1 */
+	  (void*) USB_2_Handler,                 /* 82 Universal Serial Bus IRQ 2 */
+	  (void*) USB_3_Handler,                 /* 83 Universal Serial Bus IRQ 3 */
+	  (void*) (0UL),
+	  (void*) TCC0_0_Handler,                /* 85 Timer Counter Control 0 IRQ 0 */
+	  (void*) TCC0_1_Handler,                /* 86 Timer Counter Control 0 IRQ 1 */
+	  (void*) TCC0_2_Handler,                /* 87 Timer Counter Control 0 IRQ 2 */
+	  (void*) TCC0_3_Handler,                /* 88 Timer Counter Control 0 IRQ 3 */
+	  (void*) TCC0_4_Handler,                /* 89 Timer Counter Control 0 IRQ 4 */
+	  (void*) TCC0_5_Handler,                /* 90 Timer Counter Control 0 IRQ 5 */
+	  (void*) TCC0_6_Handler,                /* 91 Timer Counter Control 0 IRQ 6 */
+	  (void*) TCC1_0_Handler,                /* 92 Timer Counter Control 1 IRQ 0 */
+	  (void*) TCC1_1_Handler,                /* 93 Timer Counter Control 1 IRQ 1 */
+	  (void*) TCC1_2_Handler,                /* 94 Timer Counter Control 1 IRQ 2 */
+	  (void*) TCC1_3_Handler,                /* 95 Timer Counter Control 1 IRQ 3 */
+	  (void*) TCC1_4_Handler,                /* 96 Timer Counter Control 1 IRQ 4 */
+	  (void*) TCC2_0_Handler,                /* 97 Timer Counter Control 2 IRQ 0 */
+	  (void*) TCC2_1_Handler,                /* 98 Timer Counter Control 2 IRQ 1 */
+	  (void*) TCC2_2_Handler,                /* 99 Timer Counter Control 2 IRQ 2 */
+	  (void*) TCC2_3_Handler,                /* 100 Timer Counter Control 2 IRQ 3 */
+	  (void*) TCC3_0_Handler,                /* 101 Timer Counter Control 3 IRQ 0 */
+	  (void*) TCC3_1_Handler,                /* 102 Timer Counter Control 3 IRQ 1 */
+	  (void*) TCC3_2_Handler,                /* 103 Timer Counter Control 3 IRQ 2 */
+	  (void*) TCC4_0_Handler,                /* 104 Timer Counter Control 4 IRQ 0 */
+	  (void*) TCC4_1_Handler,                /* 105 Timer Counter Control 4 IRQ 1 */
+	  (void*) TCC4_2_Handler,                /* 106 Timer Counter Control 4 IRQ 2 */
+	  (void*) TC0_Handler,                   /* 107 Basic Timer Counter 0 */
+	  (void*) TC1_Handler,                   /* 108 Basic Timer Counter 1 */
+	  (void*) TC2_Handler,                   /* 109 Basic Timer Counter 2 */
+	  (void*) TC3_Handler,                   /* 110 Basic Timer Counter 3 */
+	  (void*) TC4_Handler,                   /* 111 Basic Timer Counter 4 */
+	  (void*) TC5_Handler,                   /* 112 Basic Timer Counter 5 */
+	  (void*) TC6_Handler,                   /* 113 Basic Timer Counter 6 */
+	  (void*) TC7_Handler,                   /* 114 Basic Timer Counter 7 */
+	  (void*) PDEC_0_Handler,                /* 115 Quadrature Decodeur IRQ 0 */
+	  (void*) PDEC_1_Handler,                /* 116 Quadrature Decodeur IRQ 1 */
+	  (void*) PDEC_2_Handler,                /* 117 Quadrature Decodeur IRQ 2 */
+	  (void*) ADC0_0_Handler,                /* 118 Analog Digital Converter 0 IRQ 0 */
+	  (void*) ADC0_1_Handler,                /* 119 Analog Digital Converter 0 IRQ 1 */
+	  (void*) ADC1_0_Handler,                /* 120 Analog Digital Converter 1 IRQ 0 */
+	  (void*) ADC1_1_Handler,                /* 121 Analog Digital Converter 1 IRQ 1 */
+	  (void*) AC_Handler,                    /* 122 Analog Comparators */
+	  (void*) DAC_0_Handler,                 /* 123 Digital-to-Analog Converter IRQ 0 */
+	  (void*) DAC_1_Handler,                 /* 124 Digital-to-Analog Converter IRQ 1 */
+	  (void*) DAC_2_Handler,                 /* 125 Digital-to-Analog Converter IRQ 2 */
+	  (void*) DAC_3_Handler,                 /* 126 Digital-to-Analog Converter IRQ 3 */
+	  (void*) DAC_4_Handler,                 /* 127 Digital-to-Analog Converter IRQ 4 */
+	  (void*) I2S_Handler,                   /* 128 Inter-IC Sound Interface */
+	  (void*) PCC_Handler,                   /* 129 Parallel Capture Controller */
+	  (void*) AES_Handler,                   /* 130 Advanced Encryption Standard */
+	  (void*) TRNG_Handler,                  /* 131 True Random Generator */
+	  (void*) ICM_Handler,                   /* 132 Integrity Check Monitor */
+	  (void*) PUKCC_Handler,                 /* 133 PUblic-Key Cryptography Controller */
+	  (void*) QSPI_Handler,                  /* 134 Quad SPI interface */
+	  (void*) SDHC0_Handler,                 /* 135 SD/MMC Host Controller 0 */
+	  (void*) SDHC1_Handler,                 /* 136 SD/MMC Host Controller 1 */
+};
+
+#else
+
 /* Cortex-M0+ core handlers */
 void HardFault_Handler(void) __attribute__ ((weak, alias("Dummy_Handler")));
 void Reset_Handler    (void);
@@ -134,6 +459,8 @@ __attribute__ ((section(".isr_vector"))) const DeviceVectors exception_table =
   (void*) (0UL),                  /* Reserved */
 };
 
+#endif
+
 extern int main(void);
 
 /* This is called on processor reset to initialize the device and call main() */
@@ -156,6 +483,13 @@ void Reset_Handler(void)
       *pDest = 0;
   }
 
+#if defined(__FPU_USED) && defined(__SAMD51__)
+	/* Enable FPU */
+	SCB->CPACR |= (0xFu << 20);
+	__DSB();
+	__ISB();
+#endif
+
   SystemInit();
 
   main();
@@ -176,11 +510,34 @@ void SysTick_Handler(void)
 
 static void (*usb_isr)(void) = NULL;
 
+#if defined(__SAMD51__)
+void USB_0_Handler(void)
+{
+	if (usb_isr)
+	usb_isr();
+}
+void USB_1_Handler(void)
+{
+	if (usb_isr)
+	usb_isr();
+}
+void USB_2_Handler(void)
+{
+	if (usb_isr)
+	usb_isr();
+}
+void USB_3_Handler(void)
+{
+	if (usb_isr)
+	usb_isr();
+}
+#else
 void USB_Handler(void)
 {
   if (usb_isr)
     usb_isr();
 }
+#endif
 
 void USB_SetHandler(void (*new_usb_isr)(void))
 {
diff --git a/cores/arduino/delay.c b/cores/arduino/delay.c
index 84c8ea7e4..7833512a6 100644
--- a/cores/arduino/delay.c
+++ b/cores/arduino/delay.c
@@ -61,6 +61,33 @@ unsigned long micros( void )
   // a runtime multiplication and shift, saving a few cycles
 }
 
+#ifdef __SAMD51__
+/*
+ * On SAMD51, use the (32bit) cycle count maintained by the DWT unit,
+ * and count exact number of cycles elapsed, rather than guessing how
+ * many cycles a loop takes, which is dangerous in the presence of
+ * cache.  The overhead of the call and internal code is "about" 20
+ * cycles.  (at 120MHz, that's about 1/6 us)
+ */
+void delayMicroseconds(unsigned int us)
+{
+  uint32_t start, elapsed;
+  uint32_t count;
+
+  if (us == 0)
+    return;
+
+  count = us * (VARIANT_MCK / 1000000) - 20;  // convert us to cycles.
+  start = DWT->CYCCNT;  //CYCCNT is 32bits, takes 37s or so to wrap.
+  while (1) {
+    elapsed = DWT->CYCCNT - start;
+    if (elapsed >= count)
+      return;
+  }
+}
+#endif
+
+
 void delay( unsigned long ms )
 {
   if (ms == 0)
diff --git a/cores/arduino/delay.h b/cores/arduino/delay.h
index 64f39b13f..3d3a6d195 100644
--- a/cores/arduino/delay.h
+++ b/cores/arduino/delay.h
@@ -1,5 +1,6 @@
 /*
   Copyright (c) 2015 Arduino LLC.  All right reserved.
+  SAMD51 support added by Adafruit - Copyright (c) 2018 Dean Miller for Adafruit Industries
 
   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
@@ -60,6 +61,9 @@ extern void delay( unsigned long dwMs ) ;
  *
  * \param dwUs the number of microseconds to pause (uint32_t)
  */
+#if defined(__SAMD51__)
+extern void delayMicroseconds( unsigned int );
+#else
 static __inline__ void delayMicroseconds( unsigned int ) __attribute__((always_inline, unused)) ;
 static __inline__ void delayMicroseconds( unsigned int usec )
 {
@@ -67,7 +71,6 @@ static __inline__ void delayMicroseconds( unsigned int usec )
   {
     return ;
   }
-
   /*
    *  The following loop:
    *
@@ -85,6 +88,7 @@ static __inline__ void delayMicroseconds( unsigned int usec )
   // VARIANT_MCK / 1000000 == cycles needed to delay 1uS
   //                     3 == cycles used in a loop
   uint32_t n = usec * (VARIANT_MCK / 1000000) / 3;
+
   __asm__ __volatile__(
     "1:              \n"
     "   sub %0, #1   \n" // substract 1 from %0 (n)
@@ -96,6 +100,7 @@ static __inline__ void delayMicroseconds( unsigned int usec )
   // https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html
   // https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#Volatile
 }
+#endif
 
 #ifdef __cplusplus
 }
diff --git a/cores/arduino/hooks.c b/cores/arduino/hooks.c
index f87c20444..d3272504f 100644
--- a/cores/arduino/hooks.c
+++ b/cores/arduino/hooks.c
@@ -28,6 +28,7 @@
 static void __empty() {
 	// Empty
 }
+
 void yield(void) __attribute__ ((weak, alias("__empty")));
 
 /**
diff --git a/cores/arduino/main.cpp b/cores/arduino/main.cpp
index 49ebc27f5..10db6a9af 100644
--- a/cores/arduino/main.cpp
+++ b/cores/arduino/main.cpp
@@ -39,7 +39,10 @@ int main( void )
   initVariant();
 
   delay(1);
-#if defined(USBCON)
+
+#if defined(USE_TINYUSB)
+  Adafruit_TinyUSB_Core_init();
+#elif defined(USBCON)
   USBDevice.init();
   USBDevice.attach();
 #endif
@@ -49,8 +52,21 @@ int main( void )
   for (;;)
   {
     loop();
+    yield(); // yield run usb background task
+
     if (serialEventRun) serialEventRun();
   }
 
   return 0;
 }
+
+#if defined(USE_TINYUSB)
+
+// run TinyUSB background task when yield()
+extern  "C" void yield(void)
+{
+  tud_task();
+  tud_cdc_write_flush();
+}
+
+#endif
diff --git a/cores/arduino/math_helper.c b/cores/arduino/math_helper.c
new file mode 100644
index 000000000..60887c708
--- /dev/null
+++ b/cores/arduino/math_helper.c
@@ -0,0 +1,459 @@
+/* ----------------------------------------------------------------------   
+* Copyright (C) 2010-2012 ARM Limited. All rights reserved.   
+*   
+* $Date:        17. January 2013  
+* $Revision: 	V1.4.0    
+*  
+* Project: 	    CMSIS DSP Library 
+*
+* Title:	    math_helper.c
+*
+* Description:	Definition of all helper functions required.  
+*  
+* Target Processor: Cortex-M4/Cortex-M3
+*  
+* Redistribution and use in source and binary forms, with or without 
+* modification, are permitted provided that the following conditions
+* are met:
+*   - Redistributions of source code must retain the above copyright
+*     notice, this list of conditions and the following disclaimer.
+*   - Redistributions in binary form must reproduce the above copyright
+*     notice, this list of conditions and the following disclaimer in
+*     the documentation and/or other materials provided with the 
+*     distribution.
+*   - Neither the name of ARM LIMITED nor the names of its contributors
+*     may be used to endorse or promote products derived from this
+*     software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
+* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+* POSSIBILITY OF SUCH DAMAGE.  
+* -------------------------------------------------------------------- */
+
+/* ----------------------------------------------------------------------
+*		Include standard header files  
+* -------------------------------------------------------------------- */
+#include<math.h>
+
+/* ----------------------------------------------------------------------
+*		Include project header files  
+* -------------------------------------------------------------------- */
+#include "math_helper.h"
+
+/** 
+ * @brief  Caluclation of SNR
+ * @param  float* 	Pointer to the reference buffer
+ * @param  float*	Pointer to the test buffer
+ * @param  uint32_t	total number of samples
+ * @return float	SNR
+ * The function Caluclates signal to noise ratio for the reference output 
+ * and test output 
+ */
+
+float arm_snr_f32(float *pRef, float *pTest, uint32_t buffSize)
+{
+  float EnergySignal = 0.0, EnergyError = 0.0;
+  uint32_t i;
+  float SNR;
+  int temp;
+  int *test;
+
+  for (i = 0; i < buffSize; i++)
+    {
+ 	  /* Checking for a NAN value in pRef array */
+	  test =   (int *)(&pRef[i]);
+      temp =  *test;
+
+	  if(temp == 0x7FC00000)
+	  {
+	  		return(0);
+	  }
+
+	  /* Checking for a NAN value in pTest array */
+	  test =   (int *)(&pTest[i]);
+      temp =  *test;
+
+	  if(temp == 0x7FC00000)
+	  {
+	  		return(0);
+	  }
+      EnergySignal += pRef[i] * pRef[i];
+      EnergyError += (pRef[i] - pTest[i]) * (pRef[i] - pTest[i]); 
+    }
+
+	/* Checking for a NAN value in EnergyError */
+	test =   (int *)(&EnergyError);
+    temp =  *test;
+
+    if(temp == 0x7FC00000)
+    {
+  		return(0);
+    }
+	
+
+  SNR = 10 * log10 (EnergySignal / EnergyError);
+
+  return (SNR);
+
+}
+
+
+/** 
+ * @brief  Provide guard bits for Input buffer
+ * @param  q15_t* 	    Pointer to input buffer
+ * @param  uint32_t 	blockSize
+ * @param  uint32_t 	guard_bits
+ * @return none
+ * The function Provides the guard bits for the buffer 
+ * to avoid overflow 
+ */
+
+void arm_provide_guard_bits_q15 (q15_t * input_buf, uint32_t blockSize,
+                            uint32_t guard_bits)
+{
+  uint32_t i;
+
+  for (i = 0; i < blockSize; i++)
+    {
+      input_buf[i] = input_buf[i] >> guard_bits;
+    }
+}
+
+/** 
+ * @brief  Converts float to fixed in q12.20 format
+ * @param  uint32_t 	number of samples in the buffer
+ * @return none
+ * The function converts floating point values to fixed point(q12.20) values 
+ */
+
+void arm_float_to_q12_20(float *pIn, q31_t * pOut, uint32_t numSamples)
+{
+  uint32_t i;
+
+  for (i = 0; i < numSamples; i++)
+    {
+	  /* 1048576.0f corresponds to pow(2, 20) */
+      pOut[i] = (q31_t) (pIn[i] * 1048576.0f);
+
+      pOut[i] += pIn[i] > 0 ? 0.5 : -0.5;
+
+      if (pIn[i] == (float) 1.0)
+        {
+          pOut[i] = 0x000FFFFF;
+        }
+    }
+}
+
+/** 
+ * @brief  Compare MATLAB Reference Output and ARM Test output
+ * @param  q15_t* 	Pointer to Ref buffer
+ * @param  q15_t* 	Pointer to Test buffer
+ * @param  uint32_t 	number of samples in the buffer
+ * @return none 
+ */
+
+uint32_t arm_compare_fixed_q15(q15_t *pIn, q15_t * pOut, uint32_t numSamples)
+{
+  uint32_t i; 
+  int32_t diff;
+  uint32_t diffCrnt = 0;
+  uint32_t maxDiff = 0;
+
+  for (i = 0; i < numSamples; i++)
+  {
+    diff = pIn[i] - pOut[i];
+    diffCrnt = (uint32_t)( (diff > 0) ? diff : -diff );
+
+    if(diffCrnt > maxDiff)
+    {
+      maxDiff = diffCrnt;
+    }
+  }
+
+  return(maxDiff);
+}
+
+/** 
+ * @brief  Compare MATLAB Reference Output and ARM Test output
+ * @param  q31_t* 	Pointer to Ref buffer
+ * @param  q31_t* 	Pointer to Test buffer
+ * @param  uint32_t 	number of samples in the buffer
+ * @return none 
+ */
+
+uint32_t arm_compare_fixed_q31(q31_t *pIn, q31_t * pOut, uint32_t numSamples)
+{
+  uint32_t i; 
+  int32_t diff;
+  uint32_t diffCrnt = 0;
+  uint32_t maxDiff = 0;
+
+  for (i = 0; i < numSamples; i++)
+  {
+    diff = pIn[i] - pOut[i];
+    diffCrnt = (uint32_t)( (diff > 0) ? diff : -diff );
+
+    if(diffCrnt > maxDiff)
+    {
+      maxDiff = diffCrnt;
+    }
+  }
+
+  return(maxDiff);
+}
+
+/** 
+ * @brief  Provide guard bits for Input buffer
+ * @param  q31_t* 	Pointer to input buffer
+ * @param  uint32_t 	blockSize
+ * @param  uint32_t 	guard_bits
+ * @return none
+ * The function Provides the guard bits for the buffer 
+ * to avoid overflow 
+ */
+
+void arm_provide_guard_bits_q31 (q31_t * input_buf, 
+								 uint32_t blockSize,
+                                 uint32_t guard_bits)
+{
+  uint32_t i;
+
+  for (i = 0; i < blockSize; i++)
+    {
+      input_buf[i] = input_buf[i] >> guard_bits;
+    }
+}
+
+/** 
+ * @brief  Provide guard bits for Input buffer
+ * @param  q31_t* 	Pointer to input buffer
+ * @param  uint32_t 	blockSize
+ * @param  uint32_t 	guard_bits
+ * @return none
+ * The function Provides the guard bits for the buffer 
+ * to avoid overflow 
+ */
+
+void arm_provide_guard_bits_q7 (q7_t * input_buf, 
+								uint32_t blockSize,
+                                uint32_t guard_bits)
+{
+  uint32_t i;
+
+  for (i = 0; i < blockSize; i++)
+    {
+      input_buf[i] = input_buf[i] >> guard_bits;
+    }
+}
+
+
+
+/** 
+ * @brief  Caluclates number of guard bits 
+ * @param  uint32_t 	number of additions
+ * @return none
+ * The function Caluclates the number of guard bits  
+ * depending on the numtaps 
+ */
+
+uint32_t arm_calc_guard_bits (uint32_t num_adds)
+{
+  uint32_t i = 1, j = 0;
+
+  if (num_adds == 1)
+    {
+      return (0);
+    }
+
+  while (i < num_adds)
+    {
+      i = i * 2;
+      j++;
+    }
+
+  return (j);
+}
+
+/** 
+ * @brief  Converts Q15 to floating-point
+ * @param  uint32_t 	number of samples in the buffer
+ * @return none
+ */
+
+void arm_apply_guard_bits (float32_t * pIn, 
+						   uint32_t numSamples, 
+						   uint32_t guard_bits)
+{
+  uint32_t i;
+
+  for (i = 0; i < numSamples; i++)
+    {
+      pIn[i] = pIn[i] * arm_calc_2pow(guard_bits);
+    }
+}
+
+/** 
+ * @brief  Calculates pow(2, numShifts)
+ * @param  uint32_t 	number of shifts
+ * @return pow(2, numShifts)
+ */
+uint32_t arm_calc_2pow(uint32_t numShifts)
+{
+
+  uint32_t i, val = 1;
+
+  for (i = 0; i < numShifts; i++)
+    {
+      val = val * 2;
+    }	
+
+  return(val);
+}
+
+
+
+/** 
+ * @brief  Converts float to fixed q14 
+ * @param  uint32_t 	number of samples in the buffer
+ * @return none
+ * The function converts floating point values to fixed point values 
+ */
+
+void arm_float_to_q14 (float *pIn, q15_t * pOut, 
+                       uint32_t numSamples)
+{
+  uint32_t i;
+
+  for (i = 0; i < numSamples; i++)
+    {
+	  /* 16384.0f corresponds to pow(2, 14) */
+      pOut[i] = (q15_t) (pIn[i] * 16384.0f);
+
+      pOut[i] += pIn[i] > 0 ? 0.5 : -0.5;
+
+      if (pIn[i] == (float) 2.0)
+        {
+          pOut[i] = 0x7FFF;
+        }
+
+    }
+
+}
+
+ 
+/** 
+ * @brief  Converts float to fixed q30 format
+ * @param  uint32_t 	number of samples in the buffer
+ * @return none
+ * The function converts floating point values to fixed point values 
+ */
+
+void arm_float_to_q30 (float *pIn, q31_t * pOut, 
+					   uint32_t numSamples)
+{
+  uint32_t i;
+
+  for (i = 0; i < numSamples; i++)
+    {
+	  /* 1073741824.0f corresponds to pow(2, 30) */
+      pOut[i] = (q31_t) (pIn[i] * 1073741824.0f);
+
+      pOut[i] += pIn[i] > 0 ? 0.5 : -0.5;
+
+      if (pIn[i] == (float) 2.0)
+        {
+          pOut[i] = 0x7FFFFFFF;
+        }
+    }
+}
+
+/** 
+ * @brief  Converts float to fixed q30 format
+ * @param  uint32_t 	number of samples in the buffer
+ * @return none
+ * The function converts floating point values to fixed point values 
+ */
+
+void arm_float_to_q29 (float *pIn, q31_t * pOut, 
+					   uint32_t numSamples)
+{
+  uint32_t i;
+
+  for (i = 0; i < numSamples; i++)
+    {
+	  /* 1073741824.0f corresponds to pow(2, 30) */
+      pOut[i] = (q31_t) (pIn[i] * 536870912.0f);
+
+      pOut[i] += pIn[i] > 0 ? 0.5 : -0.5;
+
+      if (pIn[i] == (float) 4.0)
+        {
+          pOut[i] = 0x7FFFFFFF;
+        }
+    }
+}
+
+
+/** 
+ * @brief  Converts float to fixed q28 format
+ * @param  uint32_t 	number of samples in the buffer
+ * @return none
+ * The function converts floating point values to fixed point values 
+ */
+
+void arm_float_to_q28 (float *pIn, q31_t * pOut, 
+                       uint32_t numSamples)
+{
+  uint32_t i;
+
+  for (i = 0; i < numSamples; i++)
+    {
+	/* 268435456.0f corresponds to pow(2, 28) */
+      pOut[i] = (q31_t) (pIn[i] * 268435456.0f);
+
+      pOut[i] += pIn[i] > 0 ? 0.5 : -0.5;
+
+      if (pIn[i] == (float) 8.0)
+        {
+          pOut[i] = 0x7FFFFFFF;
+        }
+    }
+}
+
+/** 
+ * @brief  Clip the float values to +/- 1 
+ * @param  pIn 	input buffer
+ * @param  numSamples 	number of samples in the buffer
+ * @return none
+ * The function converts floating point values to fixed point values 
+ */
+
+void arm_clip_f32 (float *pIn, uint32_t numSamples)
+{
+  uint32_t i;
+
+  for (i = 0; i < numSamples; i++)
+    {
+      if(pIn[i] > 1.0f)
+	  {
+	    pIn[i] = 1.0;
+	  }
+	  else if( pIn[i] < -1.0f)
+	  {
+	    pIn[i] = -1.0;
+	  }
+	       
+    }
+}
+
+
+
diff --git a/cores/arduino/math_helper.h b/cores/arduino/math_helper.h
new file mode 100644
index 000000000..866c55374
--- /dev/null
+++ b/cores/arduino/math_helper.h
@@ -0,0 +1,63 @@
+
+/* ----------------------------------------------------------------------
+* Copyright (C) 2010-2013 ARM Limited. All rights reserved.
+*
+* $Date:        17. January 2013
+* $Revision: 	V1.4.0
+*
+* Project: 	    CMSIS DSP Library
+*
+* Title:	    math_helper.h
+*
+* Description:	Prototypes of all helper functions required.
+*
+* Target Processor: Cortex-M4/Cortex-M3
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*   - Redistributions of source code must retain the above copyright
+*     notice, this list of conditions and the following disclaimer.
+*   - Redistributions in binary form must reproduce the above copyright
+*     notice, this list of conditions and the following disclaimer in
+*     the documentation and/or other materials provided with the
+*     distribution.
+*   - Neither the name of ARM LIMITED nor the names of its contributors
+*     may be used to endorse or promote products derived from this
+*     software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+* POSSIBILITY OF SUCH DAMAGE.
+* -------------------------------------------------------------------- */
+
+
+#include "arm_math.h"
+
+#ifndef MATH_HELPER_H
+#define MATH_HELPER_H
+
+float arm_snr_f32(float *pRef, float *pTest,  uint32_t buffSize);
+void arm_float_to_q12_20(float *pIn, q31_t * pOut, uint32_t numSamples);
+void arm_provide_guard_bits_q15(q15_t *input_buf, uint32_t blockSize, uint32_t guard_bits);
+void arm_provide_guard_bits_q31(q31_t *input_buf, uint32_t blockSize, uint32_t guard_bits);
+void arm_float_to_q14(float *pIn, q15_t *pOut, uint32_t numSamples);
+void arm_float_to_q29(float *pIn, q31_t *pOut, uint32_t numSamples);
+void arm_float_to_q28(float *pIn, q31_t *pOut, uint32_t numSamples);
+void arm_float_to_q30(float *pIn, q31_t *pOut, uint32_t numSamples);
+void arm_clip_f32(float *pIn, uint32_t numSamples);
+uint32_t arm_calc_guard_bits(uint32_t num_adds);
+void arm_apply_guard_bits (float32_t * pIn, uint32_t numSamples, uint32_t guard_bits);
+uint32_t arm_compare_fixed_q15(q15_t *pIn, q15_t * pOut, uint32_t numSamples);
+uint32_t arm_compare_fixed_q31(q31_t *pIn, q31_t *pOut, uint32_t numSamples);
+uint32_t arm_calc_2pow(uint32_t guard_bits);
+#endif
diff --git a/cores/arduino/pulse.c b/cores/arduino/pulse.c
index 2dd03bf47..6ead704dd 100644
--- a/cores/arduino/pulse.c
+++ b/cores/arduino/pulse.c
@@ -34,6 +34,36 @@ uint32_t pulseIn(uint32_t pin, uint32_t state, uint32_t timeout)
   uint32_t bit = 1 << p.ulPin;
   uint32_t stateMask = state ? bit : 0;
 
+#if defined(__SAMD51__)
+  /*
+   * The SAMD51 is fast enough to use really obvious code (similar to
+   * what was used to produce pulse_asm.S, but using micros() for timing.
+   * No assembly required, no conversion of loop counts to times (which is
+   * worrisome in the presence of cache.)
+   */
+  const volatile uint32_t *port = &(PORT->Group[p.ulPort].IN.reg);
+  uint32_t usCallStart;  // microseconds at start of call, for timeout.
+  uint32_t usPulseStart; // microseconds at start of measured pulse.
+  usCallStart = usPulseStart = micros();
+  // wait for any previous pulse to end
+  while ((*port & bit) == stateMask) {
+      if (micros() - usCallStart > timeout)
+          return -1;
+  }
+  // wait for the pulse to start
+  while ((*port & bit) != stateMask) {
+      usPulseStart = micros();
+      if (usPulseStart - usCallStart > timeout)
+          return -2;
+  }
+
+  // wait for the pulse to stop
+  while ((*port & bit) == stateMask) {
+      if (micros() - usCallStart > timeout)
+          return -3;
+  }
+  return micros() - usPulseStart;
+#else
   // convert the timeout from microseconds to a number of times through
   // the initial loop; it takes (roughly) 13 clock cycles per iteration.
   uint32_t maxloops = microsecondsToClockCycles(timeout) / 13;
@@ -48,5 +78,6 @@ uint32_t pulseIn(uint32_t pin, uint32_t state, uint32_t timeout)
     return clockCyclesToMicroseconds(width * 13 + 16);
   else
     return 0;
+#endif // SAMD51
 }
 
diff --git a/cores/arduino/startup.c b/cores/arduino/startup.c
index d66bfa8e6..8816eb549 100644
--- a/cores/arduino/startup.c
+++ b/cores/arduino/startup.c
@@ -1,5 +1,6 @@
 /*
   Copyright (c) 2015 Arduino LLC.  All right reserved.
+  SAMD51 support added by Adafruit - Copyright (c) 2018 Dean Miller for Adafruit Industries
 
   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
@@ -21,23 +22,29 @@
 
 #include <stdio.h>
 
-/**
- * \brief SystemInit() configures the needed clocks and according Flash Read Wait States.
- * At reset:
- * - OSC8M clock source is enabled with a divider by 8 (1MHz).
- * - Generic Clock Generator 0 (GCLKMAIN) is using OSC8M as source.
- * We need to:
- * 1) Enable XOSC32K clock (External on-board 32.768Hz oscillator), will be used as DFLL48M reference.
- * 2) Put XOSC32K as source of Generic Clock Generator 1
- * 3) Put Generic Clock Generator 1 as source for Generic Clock Multiplexer 0 (DFLL48M reference)
- * 4) Enable DFLL48M clock
- * 5) Switch Generic Clock Generator 0 to DFLL48M. CPU will run at 48MHz.
- * 6) Modify PRESCaler value of OSCM to have 8MHz
- * 7) Put OSC8M as source for Generic Clock Generator 3
- */
 // Constants for Clock generators
 #define GENERIC_CLOCK_GENERATOR_MAIN      (0u)
+
+#if defined(__SAMD51__)
+#define GENERIC_CLOCK_GENERATOR_XOSC32K   (3u)
+#define GENERIC_CLOCK_GENERATOR_48M		  (1u)
+#define GENERIC_CLOCK_GENERATOR_48M_SYNC	GCLK_SYNCBUSY_GENCTRL1
+#define GENERIC_CLOCK_GENERATOR_100M	  (2u)
+#define GENERIC_CLOCK_GENERATOR_100M_SYNC	GCLK_SYNCBUSY_GENCTRL2
+#define GENERIC_CLOCK_GENERATOR_12M       (4u)
+#define GENERIC_CLOCK_GENERATOR_12M_SYNC   GCLK_SYNCBUSY_GENCTRL4
+
+//USE DPLL0 for 120MHZ
+#define MAIN_CLOCK_SOURCE				  GCLK_GENCTRL_SRC_DPLL0
+
+#define GENERIC_CLOCK_GENERATOR_1M		  (5u)
+//#define CRYSTALLESS
+
+#else
+
 #define GENERIC_CLOCK_GENERATOR_XOSC32K   (1u)
+#endif
+
 #define GENERIC_CLOCK_GENERATOR_OSC32K    (1u)
 #define GENERIC_CLOCK_GENERATOR_OSCULP32K (2u) /* Initialized at reset for WDT */
 #define GENERIC_CLOCK_GENERATOR_OSC8M     (3u)
@@ -46,256 +53,527 @@
 
 void SystemInit( void )
 {
-  /* Set 1 Flash Wait State for 48MHz, cf tables 20.9 and 35.27 in SAMD21 Datasheet */
-  NVMCTRL->CTRLB.bit.RWS = NVMCTRL_CTRLB_RWS_HALF_Val ;
-
-  /* Turn on the digital interface clock */
-  PM->APBAMASK.reg |= PM_APBAMASK_GCLK ;
-
-
-#if defined(CRYSTALLESS)
-
-  /* ----------------------------------------------------------------------------------------------
-   * 1) Enable OSC32K clock (Internal 32.768Hz oscillator)
-   */
-
-  uint32_t calib = (*((uint32_t *) FUSES_OSC32K_CAL_ADDR) & FUSES_OSC32K_CAL_Msk) >> FUSES_OSC32K_CAL_Pos;
-
-  SYSCTRL->OSC32K.reg = SYSCTRL_OSC32K_CALIB(calib) |
-                        SYSCTRL_OSC32K_STARTUP( 0x6u ) | // cf table 15.10 of product datasheet in chapter 15.8.6
-                        SYSCTRL_OSC32K_EN32K |
-                        SYSCTRL_OSC32K_ENABLE;
-
-  while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_OSC32KRDY) == 0 ); // Wait for oscillator stabilization
-
-#else // has crystal
 
+//***************** SAMD51 ************************//
+#if defined(__SAMD51__)
+  NVMCTRL->CTRLA.reg |= NVMCTRL_CTRLA_RWS(0);
+  
+  #ifndef CRYSTALLESS
   /* ----------------------------------------------------------------------------------------------
    * 1) Enable XOSC32K clock (External on-board 32.768Hz oscillator)
    */
-  SYSCTRL->XOSC32K.reg = SYSCTRL_XOSC32K_STARTUP( 0x6u ) | /* cf table 15.10 of product datasheet in chapter 15.8.6 */
-                         SYSCTRL_XOSC32K_XTALEN | SYSCTRL_XOSC32K_EN32K ;
-  SYSCTRL->XOSC32K.bit.ENABLE = 1 ; /* separate call, as described in chapter 15.6.3 */
-
-  while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_XOSC32KRDY) == 0 )
-  {
-    /* Wait for oscillator stabilization */
+  
+  OSC32KCTRL->XOSC32K.reg = OSC32KCTRL_XOSC32K_ENABLE | OSC32KCTRL_XOSC32K_EN32K | OSC32KCTRL_XOSC32K_EN32K | OSC32KCTRL_XOSC32K_CGM_XT | OSC32KCTRL_XOSC32K_XTALEN;
+  
+  while( (OSC32KCTRL->STATUS.reg & OSC32KCTRL_STATUS_XOSC32KRDY) == 0 ){
+    /* Wait for oscillator to be ready */
   }
 
-#endif
-
-  /* Software reset the module to ensure it is re-initialized correctly */
-  /* Note: Due to synchronization, there is a delay from writing CTRL.SWRST until the reset is complete.
-   * CTRL.SWRST and STATUS.SYNCBUSY will both be cleared when the reset is complete, as described in chapter 13.8.1
-   */
-  GCLK->CTRL.reg = GCLK_CTRL_SWRST ;
+  #endif //CRYSTALLESS
 
-  while ( (GCLK->CTRL.reg & GCLK_CTRL_SWRST) && (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY) )
-  {
-    /* Wait for reset to complete */
+  //software reset
+	
+  GCLK->CTRLA.bit.SWRST = 1;
+  while ( GCLK->SYNCBUSY.reg & GCLK_SYNCBUSY_SWRST ){
+	  /* wait for reset to complete */
   }
 
+  #ifndef CRYSTALLESS  
   /* ----------------------------------------------------------------------------------------------
-   * 2) Put XOSC32K as source of Generic Clock Generator 1
+   * 2) Put XOSC32K as source of Generic Clock Generator 3
    */
-  GCLK->GENDIV.reg = GCLK_GENDIV_ID( GENERIC_CLOCK_GENERATOR_XOSC32K ) ; // Generic Clock Generator 1
-
-  while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY )
-  {
-    /* Wait for synchronization */
-  }
-
-  /* Write Generic Clock Generator 1 configuration */
-  GCLK->GENCTRL.reg = GCLK_GENCTRL_ID( GENERIC_CLOCK_GENERATOR_OSC32K ) | // Generic Clock Generator 1
-#if defined(CRYSTALLESS)
-                      GCLK_GENCTRL_SRC_OSC32K | // Selected source is Internal 32KHz Oscillator
-#else
-                      GCLK_GENCTRL_SRC_XOSC32K | // Selected source is External 32KHz Oscillator
-#endif
-//                      GCLK_GENCTRL_OE | // Output clock to a pin for tests
-                      GCLK_GENCTRL_GENEN ;
-
-  while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY )
-  {
-    /* Wait for synchronization */
-  }
-
+  GCLK->GENCTRL[GENERIC_CLOCK_GENERATOR_XOSC32K].reg = GCLK_GENCTRL_SRC(GCLK_GENCTRL_SRC_XOSC32K) | //generic clock gen 3
+    GCLK_GENCTRL_GENEN;
+  #else
   /* ----------------------------------------------------------------------------------------------
-   * 3) Put Generic Clock Generator 1 as source for Generic Clock Multiplexer 0 (DFLL48M reference)
+   * 2) Put OSCULP32K as source of Generic Clock Generator 3
    */
-  GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID( GENERIC_CLOCK_MULTIPLEXER_DFLL48M ) | // Generic Clock Multiplexer 0
-                      GCLK_CLKCTRL_GEN_GCLK1 | // Generic Clock Generator 1 is source
-                      GCLK_CLKCTRL_CLKEN ;
+  GCLK->GENCTRL[GENERIC_CLOCK_GENERATOR_XOSC32K].reg = GCLK_GENCTRL_SRC(GCLK_GENCTRL_SRC_OSCULP32K) | GCLK_GENCTRL_GENEN; //generic clock gen 3
+  #endif
+  
 
-  while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY )
-  {
+  while ( GCLK->SYNCBUSY.reg & GCLK_SYNCBUSY_GENCTRL3 ){
     /* Wait for synchronization */
   }
-
+  
+  /* ----------------------------------------------------------------------------------------------
+   * 3) Put OSCULP32K as source for Generic Clock Generator 0
+   */
+  GCLK->GENCTRL[0].reg = GCLK_GENCTRL_SRC(GCLK_GENCTRL_SRC_OSCULP32K) | GCLK_GENCTRL_GENEN;
+  
   /* ----------------------------------------------------------------------------------------------
    * 4) Enable DFLL48M clock
    */
 
-  /* DFLL Configuration in Closed Loop mode, cf product datasheet chapter 15.6.7.1 - Closed-Loop Operation */
-
-  /* Remove the OnDemand mode, Bug http://avr32.icgroup.norway.atmel.com/bugzilla/show_bug.cgi?id=9905 */
-  SYSCTRL->DFLLCTRL.reg = SYSCTRL_DFLLCTRL_ENABLE;
-
-  while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLRDY) == 0 )
-  {
-    /* Wait for synchronization */
-  }
-
-  SYSCTRL->DFLLMUL.reg = SYSCTRL_DFLLMUL_CSTEP( 31 ) | // Coarse step is 31, half of the max value
-                         SYSCTRL_DFLLMUL_FSTEP( 511 ) | // Fine step is 511, half of the max value
-                         SYSCTRL_DFLLMUL_MUL( (VARIANT_MCK + VARIANT_MAINOSC/2) / VARIANT_MAINOSC ) ; // External 32KHz is the reference
-
-  while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLRDY) == 0 )
-  {
-    /* Wait for synchronization */
-  }
-
-#if defined(CRYSTALLESS)
-
-  #define NVM_SW_CALIB_DFLL48M_COARSE_VAL 58
-
-  // Turn on DFLL
-  uint32_t coarse =( *((uint32_t *)(NVMCTRL_OTP4) + (NVM_SW_CALIB_DFLL48M_COARSE_VAL / 32)) >> (NVM_SW_CALIB_DFLL48M_COARSE_VAL % 32) )
-                   & ((1 << 6) - 1);
-  if (coarse == 0x3f) {
-    coarse = 0x1f;
-  }
-  // TODO(tannewt): Load this value from memory we've written previously. There
-  // isn't a value from the Atmel factory.
-  uint32_t fine = 0x1ff;
-
-  SYSCTRL->DFLLVAL.bit.COARSE = coarse;
-  SYSCTRL->DFLLVAL.bit.FINE = fine;
-  /* Write full configuration to DFLL control register */
-  SYSCTRL->DFLLMUL.reg = SYSCTRL_DFLLMUL_CSTEP( 0x1f / 4 ) | // Coarse step is 31, half of the max value
-                         SYSCTRL_DFLLMUL_FSTEP( 10 ) |
-                         SYSCTRL_DFLLMUL_MUL( (48000) ) ;
-
-  SYSCTRL->DFLLCTRL.reg = 0;
-
-  while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLRDY) == 0 )
-  {
+  while ( GCLK->SYNCBUSY.reg & GCLK_SYNCBUSY_GENCTRL0 ){
     /* Wait for synchronization */
   }
 
-  SYSCTRL->DFLLCTRL.reg =  SYSCTRL_DFLLCTRL_MODE |
-                           SYSCTRL_DFLLCTRL_CCDIS |
-                           SYSCTRL_DFLLCTRL_USBCRM | /* USB correction */
-                           SYSCTRL_DFLLCTRL_BPLCKC;
-
-  while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLRDY) == 0 )
-  {
+  /* DFLL Configuration in Open Loop mode */
+  
+  OSCCTRL->DFLLCTRLA.reg = 0;
+  //GCLK->PCHCTRL[OSCCTRL_GCLK_ID_DFLL48].reg = (1 << GCLK_PCHCTRL_CHEN_Pos) | GCLK_PCHCTRL_GEN(GCLK_PCHCTRL_GEN_GCLK3_Val);
+  
+  OSCCTRL->DFLLMUL.reg = OSCCTRL_DFLLMUL_CSTEP( 0x1 ) |
+    OSCCTRL_DFLLMUL_FSTEP( 0x1 ) |
+    OSCCTRL_DFLLMUL_MUL( 0 );
+  
+  while ( OSCCTRL->DFLLSYNC.reg & OSCCTRL_DFLLSYNC_DFLLMUL )
+    {
+      /* Wait for synchronization */
+    }
+  
+  OSCCTRL->DFLLCTRLB.reg = 0;
+  while ( OSCCTRL->DFLLSYNC.reg & OSCCTRL_DFLLSYNC_DFLLCTRLB )
+    {
+      /* Wait for synchronization */
+    }
+  
+  OSCCTRL->DFLLCTRLA.reg |= OSCCTRL_DFLLCTRLA_ENABLE;
+  while ( OSCCTRL->DFLLSYNC.reg & OSCCTRL_DFLLSYNC_ENABLE )
+    {
+      /* Wait for synchronization */
+    }
+  
+  OSCCTRL->DFLLVAL.reg = OSCCTRL->DFLLVAL.reg;
+  while( OSCCTRL->DFLLSYNC.bit.DFLLVAL );
+  
+  OSCCTRL->DFLLCTRLB.reg = OSCCTRL_DFLLCTRLB_WAITLOCK |
+  OSCCTRL_DFLLCTRLB_CCDIS | OSCCTRL_DFLLCTRLB_USBCRM ;
+  
+  while ( !OSCCTRL->STATUS.bit.DFLLRDY )
+    {
+      /* Wait for synchronization */
+    }
+  
+  GCLK->GENCTRL[GENERIC_CLOCK_GENERATOR_1M].reg = GCLK_GENCTRL_SRC(GCLK_GENCTRL_SRC_DFLL_Val) | GCLK_GENCTRL_GENEN | GCLK_GENCTRL_DIV(48u);
+  
+  while ( GCLK->SYNCBUSY.bit.GENCTRL5 ){
     /* Wait for synchronization */
   }
-
-  /* Enable the DFLL */
-  SYSCTRL->DFLLCTRL.reg |= SYSCTRL_DFLLCTRL_ENABLE ;
-
-#else   // has crystal
-
-  /* Write full configuration to DFLL control register */
-  SYSCTRL->DFLLCTRL.reg |= SYSCTRL_DFLLCTRL_MODE | /* Enable the closed loop mode */
-                           SYSCTRL_DFLLCTRL_WAITLOCK |
-                           SYSCTRL_DFLLCTRL_QLDIS ; /* Disable Quick lock */
-
-  while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLRDY) == 0 )
-  {
-    /* Wait for synchronization */
-  }
-
-  /* Enable the DFLL */
-  SYSCTRL->DFLLCTRL.reg |= SYSCTRL_DFLLCTRL_ENABLE ;
-
-  while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLLCKC) == 0 ||
-          (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLLCKF) == 0 )
-  {
-    /* Wait for locks flags */
-  }
-
+  
+	  
+  /* ------------------------------------------------------------------------
+  * Set up the PLLs
+  */
+	
+  //PLL0 is 120MHz
+  GCLK->PCHCTRL[OSCCTRL_GCLK_ID_FDPLL0].reg = (1 << GCLK_PCHCTRL_CHEN_Pos) | GCLK_PCHCTRL_GEN(GCLK_PCHCTRL_GEN_GCLK5_Val);
+  
+  // This rounds to nearest full-MHz increment; not currently using frac
+  OSCCTRL->Dpll[0].DPLLRATIO.reg = OSCCTRL_DPLLRATIO_LDRFRAC(0x00) | OSCCTRL_DPLLRATIO_LDR((F_CPU - 500000) / 1000000);
+  
+  while(OSCCTRL->Dpll[0].DPLLSYNCBUSY.bit.DPLLRATIO);
+  
+  //MUST USE LBYPASS DUE TO BUG IN REV A OF SAMD51
+  OSCCTRL->Dpll[0].DPLLCTRLB.reg = OSCCTRL_DPLLCTRLB_REFCLK_GCLK | OSCCTRL_DPLLCTRLB_LBYPASS;
+  
+  OSCCTRL->Dpll[0].DPLLCTRLA.reg = OSCCTRL_DPLLCTRLA_ENABLE;
+  
+  while( OSCCTRL->Dpll[0].DPLLSTATUS.bit.CLKRDY == 0 || OSCCTRL->Dpll[0].DPLLSTATUS.bit.LOCK == 0 );
+  
+  //PLL1 is 100MHz
+  GCLK->PCHCTRL[OSCCTRL_GCLK_ID_FDPLL1].reg = (1 << GCLK_PCHCTRL_CHEN_Pos) | GCLK_PCHCTRL_GEN(GCLK_PCHCTRL_GEN_GCLK5_Val);
+  
+  OSCCTRL->Dpll[1].DPLLRATIO.reg = OSCCTRL_DPLLRATIO_LDRFRAC(0x00) | OSCCTRL_DPLLRATIO_LDR(99); //100 Mhz
+  
+  while(OSCCTRL->Dpll[1].DPLLSYNCBUSY.bit.DPLLRATIO);
+  
+  //MUST USE LBYPASS DUE TO BUG IN REV A OF SAMD51
+  OSCCTRL->Dpll[1].DPLLCTRLB.reg = OSCCTRL_DPLLCTRLB_REFCLK_GCLK | OSCCTRL_DPLLCTRLB_LBYPASS;
+  
+  OSCCTRL->Dpll[1].DPLLCTRLA.reg = OSCCTRL_DPLLCTRLA_ENABLE;
+  
+  while( OSCCTRL->Dpll[1].DPLLSTATUS.bit.CLKRDY == 0 || OSCCTRL->Dpll[1].DPLLSTATUS.bit.LOCK == 0 );
+  
+  
+  /* ------------------------------------------------------------------------
+  * Set up the peripheral clocks
+  */
+  
+  //48MHZ CLOCK FOR USB AND STUFF
+  GCLK->GENCTRL[GENERIC_CLOCK_GENERATOR_48M].reg = GCLK_GENCTRL_SRC(GCLK_GENCTRL_SRC_DFLL_Val) |
+    GCLK_GENCTRL_IDC |
+    //GCLK_GENCTRL_OE |
+    GCLK_GENCTRL_GENEN;
+  
+  while ( GCLK->SYNCBUSY.reg & GENERIC_CLOCK_GENERATOR_48M_SYNC)
+    {
+      /* Wait for synchronization */
+    }
+  
+  //100MHZ CLOCK FOR OTHER PERIPHERALS
+  GCLK->GENCTRL[GENERIC_CLOCK_GENERATOR_100M].reg = GCLK_GENCTRL_SRC(GCLK_GENCTRL_SRC_DPLL1_Val) |
+    GCLK_GENCTRL_IDC |
+    //GCLK_GENCTRL_OE |
+    GCLK_GENCTRL_GENEN;
+  
+  while ( GCLK->SYNCBUSY.reg & GENERIC_CLOCK_GENERATOR_100M_SYNC)
+    {
+      /* Wait for synchronization */
+    }
+  
+  //12MHZ CLOCK FOR DAC
+  GCLK->GENCTRL[GENERIC_CLOCK_GENERATOR_12M].reg = GCLK_GENCTRL_SRC(GCLK_GENCTRL_SRC_DFLL_Val) |
+    GCLK_GENCTRL_IDC |
+    GCLK_GENCTRL_DIV(4) |
+    //GCLK_GENCTRL_DIVSEL |
+    //GCLK_GENCTRL_OE |
+    GCLK_GENCTRL_GENEN;
+  
+  while ( GCLK->SYNCBUSY.reg & GENERIC_CLOCK_GENERATOR_12M_SYNC)
+    {
+      /* Wait for synchronization */
+    }
+  
+  /*---------------------------------------------------------------------
+   * Set up main clock
+   */
+  
+  GCLK->GENCTRL[GENERIC_CLOCK_GENERATOR_MAIN].reg = GCLK_GENCTRL_SRC(MAIN_CLOCK_SOURCE) |
+    GCLK_GENCTRL_IDC |
+    //GCLK_GENCTRL_OE |
+    GCLK_GENCTRL_GENEN;
+  
+
+  while ( GCLK->SYNCBUSY.reg & GCLK_SYNCBUSY_GENCTRL0 )
+    {
+      /* Wait for synchronization */
+    }
+  
+  MCLK->CPUDIV.reg = MCLK_CPUDIV_DIV_DIV1;
+  
+  /* Use the LDO regulator by default */
+  SUPC->VREG.bit.SEL = 0; 
+  
+  
+  /* If desired, enable cache! */
+#if defined(ENABLE_CACHE)
+  __disable_irq();
+  CMCC->CTRL.reg = 1;
+  __enable_irq();
 #endif
 
-  while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLRDY) == 0 )
-  {
-    /* Wait for synchronization */
-  }
-
-  /* ----------------------------------------------------------------------------------------------
-   * 5) Switch Generic Clock Generator 0 to DFLL48M. CPU will run at 48MHz.
+  /*---------------------------------------------------------------------
+   * Start up the "Debug Watchpoint and Trace" unit, so that we can use
+   * it's 32bit cycle counter for timing.
    */
-  GCLK->GENDIV.reg = GCLK_GENDIV_ID( GENERIC_CLOCK_GENERATOR_MAIN ) ; // Generic Clock Generator 0
-
-  while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY )
-  {
-    /* Wait for synchronization */
-  }
-
-  /* Write Generic Clock Generator 0 configuration */
-  GCLK->GENCTRL.reg = GCLK_GENCTRL_ID( GENERIC_CLOCK_GENERATOR_MAIN ) | // Generic Clock Generator 0
-                      GCLK_GENCTRL_SRC_DFLL48M | // Selected source is DFLL 48MHz
-//                      GCLK_GENCTRL_OE | // Output clock to a pin for tests
-                      GCLK_GENCTRL_IDC | // Set 50/50 duty cycle
-                      GCLK_GENCTRL_GENEN ;
-
-  while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY )
-  {
-    /* Wait for synchronization */
-  }
+  CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
+  DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
 
   /* ----------------------------------------------------------------------------------------------
-   * 6) Modify PRESCaler value of OSC8M to have 8MHz
+   * 5) Load AC factory calibration values
    */
-  SYSCTRL->OSC8M.bit.PRESC = SYSCTRL_OSC8M_PRESC_0_Val ;  //CMSIS 4.5 changed the prescaler defines
-  SYSCTRL->OSC8M.bit.ONDEMAND = 0 ;
+
+  uint32_t bias0 = (*((uint32_t *)AC_FUSES_BIAS0_ADDR) & AC_FUSES_BIAS0_Msk) >> AC_FUSES_BIAS0_Pos;
+  AC->CALIB.reg = AC_CALIB_BIAS0(bias0);
 
   /* ----------------------------------------------------------------------------------------------
-   * 7) Put OSC8M as source for Generic Clock Generator 3
+   * 6) Load ADC factory calibration values
    */
-  GCLK->GENDIV.reg = GCLK_GENDIV_ID( GENERIC_CLOCK_GENERATOR_OSC8M ) ; // Generic Clock Generator 3
 
-  /* Write Generic Clock Generator 3 configuration */
-  GCLK->GENCTRL.reg = GCLK_GENCTRL_ID( GENERIC_CLOCK_GENERATOR_OSC8M ) | // Generic Clock Generator 3
-                      GCLK_GENCTRL_SRC_OSC8M | // Selected source is RC OSC 8MHz (already enabled at reset)
-//                      GCLK_GENCTRL_OE | // Output clock to a pin for tests
-                      GCLK_GENCTRL_GENEN ;
+  // ADC0 Bias Calibration
+  uint32_t biascomp = (*((uint32_t *)ADC0_FUSES_BIASCOMP_ADDR) & ADC0_FUSES_BIASCOMP_Msk) >> ADC0_FUSES_BIASCOMP_Pos;
+  uint32_t biasr2r = (*((uint32_t *)ADC0_FUSES_BIASR2R_ADDR) & ADC0_FUSES_BIASR2R_Msk) >> ADC0_FUSES_BIASR2R_Pos;
+  uint32_t biasref = (*((uint32_t *)ADC0_FUSES_BIASREFBUF_ADDR) & ADC0_FUSES_BIASREFBUF_Msk) >> ADC0_FUSES_BIASREFBUF_Pos;
 
-  while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY )
-  {
-    /* Wait for synchronization */
-  }
+  ADC0->CALIB.reg = ADC_CALIB_BIASREFBUF(biasref)
+                    | ADC_CALIB_BIASR2R(biasr2r)
+                    | ADC_CALIB_BIASCOMP(biascomp);
 
-  /*
-   * Now that all system clocks are configured, we can set CPU and APBx BUS clocks.
-   * There values are normally the one present after Reset.
-   */
-  PM->CPUSEL.reg  = PM_CPUSEL_CPUDIV_DIV1 ;
-  PM->APBASEL.reg = PM_APBASEL_APBADIV_DIV1_Val ;
-  PM->APBBSEL.reg = PM_APBBSEL_APBBDIV_DIV1_Val ;
-  PM->APBCSEL.reg = PM_APBCSEL_APBCDIV_DIV1_Val ;
+  // ADC1 Bias Calibration
+  biascomp = (*((uint32_t *)ADC1_FUSES_BIASCOMP_ADDR) & ADC1_FUSES_BIASCOMP_Msk) >> ADC1_FUSES_BIASCOMP_Pos;
+  biasr2r = (*((uint32_t *)ADC1_FUSES_BIASR2R_ADDR) & ADC1_FUSES_BIASR2R_Msk) >> ADC1_FUSES_BIASR2R_Pos;
+  biasref = (*((uint32_t *)ADC1_FUSES_BIASREFBUF_ADDR) & ADC1_FUSES_BIASREFBUF_Msk) >> ADC1_FUSES_BIASREFBUF_Pos;
 
-  SystemCoreClock=VARIANT_MCK ;
+  ADC1->CALIB.reg = ADC_CALIB_BIASREFBUF(biasref)
+                    | ADC_CALIB_BIASR2R(biasr2r)
+                    | ADC_CALIB_BIASCOMP(biascomp);
 
   /* ----------------------------------------------------------------------------------------------
-   * 8) Load ADC factory calibration values
+   * 7) Load USB factory calibration values
    */
 
-  // ADC Bias Calibration
-  uint32_t bias = (*((uint32_t *) ADC_FUSES_BIASCAL_ADDR) & ADC_FUSES_BIASCAL_Msk) >> ADC_FUSES_BIASCAL_Pos;
+  //USB Calibration
+  uint32_t usbtransn = (*((uint32_t *)USB_FUSES_TRANSN_ADDR) & USB_FUSES_TRANSN_Msk) >> USB_FUSES_TRANSN_Pos;
+  uint32_t usbtransp = (*((uint32_t *)USB_FUSES_TRANSP_ADDR) & USB_FUSES_TRANSP_Msk) >> USB_FUSES_TRANSP_Pos;
+  uint32_t usbtrim = (*((uint32_t *)USB_FUSES_TRIM_ADDR) & USB_FUSES_TRIM_Msk) >> USB_FUSES_TRIM_Pos;
+  USB->DEVICE.PADCAL.reg = USB_PADCAL_TRIM(usbtrim)
+                           | USB_PADCAL_TRANSN(usbtransn)
+                           | USB_PADCAL_TRANSP(usbtransp);
 
-  // ADC Linearity bits 4:0
-  uint32_t linearity = (*((uint32_t *) ADC_FUSES_LINEARITY_0_ADDR) & ADC_FUSES_LINEARITY_0_Msk) >> ADC_FUSES_LINEARITY_0_Pos;
+//*************** END SAMD51 *************************//
+  
+#else
+//********************** SAMD21 *********************//
 
-  // ADC Linearity bits 7:5
-  linearity |= ((*((uint32_t *) ADC_FUSES_LINEARITY_1_ADDR) & ADC_FUSES_LINEARITY_1_Msk) >> ADC_FUSES_LINEARITY_1_Pos) << 5;
+	/**
+ * \brief SystemInit() configures the needed clocks and according Flash Read Wait States.
+ * At reset:
+ * - OSC8M clock source is enabled with a divider by 8 (1MHz).
+ * - Generic Clock Generator 0 (GCLKMAIN) is using OSC8M as source.
+ * We need to:
+ * 1) Enable XOSC32K clock (External on-board 32.768Hz oscillator), will be used as DFLL48M reference.
+ * 2) Put XOSC32K as source of Generic Clock Generator 1
+ * 3) Put Generic Clock Generator 1 as source for Generic Clock Multiplexer 0 (DFLL48M reference)
+ * 4) Enable DFLL48M clock
+ * 5) Switch Generic Clock Generator 0 to DFLL48M. CPU will run at 48MHz.
+ * 6) Modify PRESCaler value of OSCM to have 8MHz
+ * 7) Put OSC8M as source for Generic Clock Generator 3
+ */
 
-  ADC->CALIB.reg = ADC_CALIB_BIAS_CAL(bias) | ADC_CALIB_LINEARITY_CAL(linearity);
+	
+  /* Set 1 Flash Wait State for 48MHz, cf tables 20.9 and 35.27 in SAMD21 Datasheet */
+    NVMCTRL->CTRLB.bit.RWS = NVMCTRL_CTRLB_RWS_HALF_Val ;
+
+    /* Turn on the digital interface clock */
+    PM->APBAMASK.reg |= PM_APBAMASK_GCLK ;
+
+
+  #if defined(CRYSTALLESS)
+
+    /* ----------------------------------------------------------------------------------------------
+     * 1) Enable OSC32K clock (Internal 32.768Hz oscillator)
+     */
 
-  /*
-   * 9) Disable automatic NVM write operations
-   */
-  NVMCTRL->CTRLB.bit.MANW = 1;
+    uint32_t calib = (*((uint32_t *) FUSES_OSC32K_CAL_ADDR) & FUSES_OSC32K_CAL_Msk) >> FUSES_OSC32K_CAL_Pos;
+
+    SYSCTRL->OSC32K.reg = SYSCTRL_OSC32K_CALIB(calib) |
+                          SYSCTRL_OSC32K_STARTUP( 0x6u ) | // cf table 15.10 of product datasheet in chapter 15.8.6
+                          SYSCTRL_OSC32K_EN32K |
+                          SYSCTRL_OSC32K_ENABLE;
+
+    while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_OSC32KRDY) == 0 ); // Wait for oscillator stabilization
+
+  #else // has crystal
+
+    /* ----------------------------------------------------------------------------------------------
+     * 1) Enable XOSC32K clock (External on-board 32.768Hz oscillator)
+     */
+    SYSCTRL->XOSC32K.reg = SYSCTRL_XOSC32K_STARTUP( 0x6u ) | /* cf table 15.10 of product datasheet in chapter 15.8.6 */
+                           SYSCTRL_XOSC32K_XTALEN | SYSCTRL_XOSC32K_EN32K ;
+    SYSCTRL->XOSC32K.bit.ENABLE = 1 ; /* separate call, as described in chapter 15.6.3 */
+
+    while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_XOSC32KRDY) == 0 )
+    {
+      /* Wait for oscillator stabilization */
+    }
+
+  #endif
+
+    /* Software reset the module to ensure it is re-initialized correctly */
+    /* Note: Due to synchronization, there is a delay from writing CTRL.SWRST until the reset is complete.
+     * CTRL.SWRST and STATUS.SYNCBUSY will both be cleared when the reset is complete, as described in chapter 13.8.1
+     */
+    GCLK->CTRL.reg = GCLK_CTRL_SWRST ;
+
+    while ( (GCLK->CTRL.reg & GCLK_CTRL_SWRST) && (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY) )
+    {
+      /* Wait for reset to complete */
+    }
+
+    /* ----------------------------------------------------------------------------------------------
+     * 2) Put XOSC32K as source of Generic Clock Generator 1
+     */
+    GCLK->GENDIV.reg = GCLK_GENDIV_ID( GENERIC_CLOCK_GENERATOR_XOSC32K ) ; // Generic Clock Generator 1
+
+    while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY )
+    {
+      /* Wait for synchronization */
+    }
+
+    /* Write Generic Clock Generator 1 configuration */
+    GCLK->GENCTRL.reg = GCLK_GENCTRL_ID( GENERIC_CLOCK_GENERATOR_OSC32K ) | // Generic Clock Generator 1
+  #if defined(CRYSTALLESS)
+                        GCLK_GENCTRL_SRC_OSC32K | // Selected source is Internal 32KHz Oscillator
+  #else
+                        GCLK_GENCTRL_SRC_XOSC32K | // Selected source is External 32KHz Oscillator
+  #endif
+  //                      GCLK_GENCTRL_OE | // Output clock to a pin for tests
+                        GCLK_GENCTRL_GENEN ;
+
+    while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY )
+    {
+      /* Wait for synchronization */
+    }
+
+    /* ----------------------------------------------------------------------------------------------
+     * 3) Put Generic Clock Generator 1 as source for Generic Clock Multiplexer 0 (DFLL48M reference)
+     */
+    GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID( GENERIC_CLOCK_MULTIPLEXER_DFLL48M ) | // Generic Clock Multiplexer 0
+                        GCLK_CLKCTRL_GEN_GCLK1 | // Generic Clock Generator 1 is source
+                        GCLK_CLKCTRL_CLKEN ;
+
+    while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY )
+    {
+      /* Wait for synchronization */
+    }
+
+    /* ----------------------------------------------------------------------------------------------
+     * 4) Enable DFLL48M clock
+     */
+
+    /* DFLL Configuration in Closed Loop mode, cf product datasheet chapter 15.6.7.1 - Closed-Loop Operation */
+
+    /* Remove the OnDemand mode, Bug http://avr32.icgroup.norway.atmel.com/bugzilla/show_bug.cgi?id=9905 */
+    SYSCTRL->DFLLCTRL.reg = SYSCTRL_DFLLCTRL_ENABLE;
+
+    while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLRDY) == 0 )
+    {
+      /* Wait for synchronization */
+    }
+
+    SYSCTRL->DFLLMUL.reg = SYSCTRL_DFLLMUL_CSTEP( 31 ) | // Coarse step is 31, half of the max value
+                           SYSCTRL_DFLLMUL_FSTEP( 511 ) | // Fine step is 511, half of the max value
+                           SYSCTRL_DFLLMUL_MUL( (VARIANT_MCK + VARIANT_MAINOSC/2) / VARIANT_MAINOSC ) ; // External 32KHz is the reference
+
+    while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLRDY) == 0 )
+    {
+      /* Wait for synchronization */
+    }
+
+  #if defined(CRYSTALLESS)
+
+    #define NVM_SW_CALIB_DFLL48M_COARSE_VAL 58
+
+    // Turn on DFLL
+    uint32_t coarse =( *((uint32_t *)(NVMCTRL_OTP4) + (NVM_SW_CALIB_DFLL48M_COARSE_VAL / 32)) >> (NVM_SW_CALIB_DFLL48M_COARSE_VAL % 32) )
+                     & ((1 << 6) - 1);
+    if (coarse == 0x3f) {
+      coarse = 0x1f;
+    }
+    // TODO(tannewt): Load this value from memory we've written previously. There
+    // isn't a value from the Atmel factory.
+    uint32_t fine = 0x1ff;
+
+    SYSCTRL->DFLLVAL.bit.COARSE = coarse;
+    SYSCTRL->DFLLVAL.bit.FINE = fine;
+    /* Write full configuration to DFLL control register */
+    SYSCTRL->DFLLMUL.reg = SYSCTRL_DFLLMUL_CSTEP( 0x1f / 4 ) | // Coarse step is 31, half of the max value
+                           SYSCTRL_DFLLMUL_FSTEP( 10 ) |
+                           SYSCTRL_DFLLMUL_MUL( (48000) ) ;
+
+    SYSCTRL->DFLLCTRL.reg = 0;
+
+    while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLRDY) == 0 )
+    {
+      /* Wait for synchronization */
+    }
+
+    SYSCTRL->DFLLCTRL.reg =  SYSCTRL_DFLLCTRL_MODE |
+                             SYSCTRL_DFLLCTRL_CCDIS |
+                             SYSCTRL_DFLLCTRL_USBCRM | /* USB correction */
+                             SYSCTRL_DFLLCTRL_BPLCKC;
+
+    while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLRDY) == 0 )
+    {
+      /* Wait for synchronization */
+    }
+
+    /* Enable the DFLL */
+    SYSCTRL->DFLLCTRL.reg |= SYSCTRL_DFLLCTRL_ENABLE ;
+
+  #else   // has crystal
+
+    /* Write full configuration to DFLL control register */
+    SYSCTRL->DFLLCTRL.reg |= SYSCTRL_DFLLCTRL_MODE | /* Enable the closed loop mode */
+                             SYSCTRL_DFLLCTRL_WAITLOCK |
+                             SYSCTRL_DFLLCTRL_QLDIS ; /* Disable Quick lock */
+
+    while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLRDY) == 0 )
+    {
+      /* Wait for synchronization */
+    }
+
+    /* Enable the DFLL */
+    SYSCTRL->DFLLCTRL.reg |= SYSCTRL_DFLLCTRL_ENABLE ;
+
+    while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLLCKC) == 0 ||
+            (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLLCKF) == 0 )
+    {
+      /* Wait for locks flags */
+    }
+
+  #endif
+
+    while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLRDY) == 0 )
+    {
+      /* Wait for synchronization */
+    }
+
+    /* ----------------------------------------------------------------------------------------------
+     * 5) Switch Generic Clock Generator 0 to DFLL48M. CPU will run at 48MHz.
+     */
+    GCLK->GENDIV.reg = GCLK_GENDIV_ID( GENERIC_CLOCK_GENERATOR_MAIN ) ; // Generic Clock Generator 0
+
+    while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY )
+    {
+      /* Wait for synchronization */
+    }
+
+    /* Write Generic Clock Generator 0 configuration */
+    GCLK->GENCTRL.reg = GCLK_GENCTRL_ID( GENERIC_CLOCK_GENERATOR_MAIN ) | // Generic Clock Generator 0
+                        GCLK_GENCTRL_SRC_DFLL48M | // Selected source is DFLL 48MHz
+  //                      GCLK_GENCTRL_OE | // Output clock to a pin for tests
+                        GCLK_GENCTRL_IDC | // Set 50/50 duty cycle
+                        GCLK_GENCTRL_GENEN ;
+
+    while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY )
+    {
+      /* Wait for synchronization */
+    }
+
+    /* ----------------------------------------------------------------------------------------------
+     * 6) Modify PRESCaler value of OSC8M to have 8MHz
+     */
+    SYSCTRL->OSC8M.bit.PRESC = SYSCTRL_OSC8M_PRESC_0_Val ;  //CMSIS 4.5 changed the prescaler defines
+    SYSCTRL->OSC8M.bit.ONDEMAND = 0 ;
+
+    /* ----------------------------------------------------------------------------------------------
+     * 7) Put OSC8M as source for Generic Clock Generator 3
+     */
+    GCLK->GENDIV.reg = GCLK_GENDIV_ID( GENERIC_CLOCK_GENERATOR_OSC8M ) ; // Generic Clock Generator 3
+
+    /* Write Generic Clock Generator 3 configuration */
+    GCLK->GENCTRL.reg = GCLK_GENCTRL_ID( GENERIC_CLOCK_GENERATOR_OSC8M ) | // Generic Clock Generator 3
+                        GCLK_GENCTRL_SRC_OSC8M | // Selected source is RC OSC 8MHz (already enabled at reset)
+  //                      GCLK_GENCTRL_OE | // Output clock to a pin for tests
+                        GCLK_GENCTRL_GENEN ;
+
+    while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY )
+    {
+      /* Wait for synchronization */
+    }
+
+    /*
+     * Now that all system clocks are configured, we can set CPU and APBx BUS clocks.
+     * There values are normally the one present after Reset.
+     */
+    PM->CPUSEL.reg  = PM_CPUSEL_CPUDIV_DIV1 ;
+    PM->APBASEL.reg = PM_APBASEL_APBADIV_DIV1_Val ;
+    PM->APBBSEL.reg = PM_APBBSEL_APBBDIV_DIV1_Val ;
+    PM->APBCSEL.reg = PM_APBCSEL_APBCDIV_DIV1_Val ;
+
+    SystemCoreClock=VARIANT_MCK ;
+
+    /* ----------------------------------------------------------------------------------------------
+     * 8) Load ADC factory calibration values
+     */
+
+    // ADC Bias Calibration
+    uint32_t bias = (*((uint32_t *) ADC_FUSES_BIASCAL_ADDR) & ADC_FUSES_BIASCAL_Msk) >> ADC_FUSES_BIASCAL_Pos;
+
+    // ADC Linearity bits 4:0
+    uint32_t linearity = (*((uint32_t *) ADC_FUSES_LINEARITY_0_ADDR) & ADC_FUSES_LINEARITY_0_Msk) >> ADC_FUSES_LINEARITY_0_Pos;
+
+    // ADC Linearity bits 7:5
+    linearity |= ((*((uint32_t *) ADC_FUSES_LINEARITY_1_ADDR) & ADC_FUSES_LINEARITY_1_Msk) >> ADC_FUSES_LINEARITY_1_Pos) << 5;
+
+    ADC->CALIB.reg = ADC_CALIB_BIAS_CAL(bias) | ADC_CALIB_LINEARITY_CAL(linearity);
+
+    /*
+     * 9) Disable automatic NVM write operations
+     */
+    NVMCTRL->CTRLB.bit.MANW = 1;
+  #endif
 }
diff --git a/cores/arduino/wiring.c b/cores/arduino/wiring.c
index c52a6e1dc..ad6c7982d 100644
--- a/cores/arduino/wiring.c
+++ b/cores/arduino/wiring.c
@@ -1,5 +1,6 @@
 /*
   Copyright (c) 2015 Arduino LLC.  All right reserved.
+  SAMD51 support added by Adafruit - Copyright (c) 2018 Dean Miller for Adafruit Industries
 
   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
@@ -22,11 +23,16 @@
 extern "C" {
 #endif
 
+
+#if defined(__SAMD51__)
+uint32_t SystemCoreClock=F_CPU;
+#else
 /*
  * System Core Clock is at 1MHz (8MHz/8) at Reset.
  * It is switched to 48MHz in the Reset Handler (startup.c)
  */
 uint32_t SystemCoreClock=1000000ul ;
+#endif
 
 /*
 void calibrateADC()
@@ -71,23 +77,88 @@ void init( void )
 //  // Clock EIC for I/O interrupts
 //  PM->APBAMASK.reg |= PM_APBAMASK_EIC ;
 
+#if defined(__SAMD51__)
+  MCLK->APBAMASK.reg |= MCLK_APBAMASK_SERCOM0 | MCLK_APBAMASK_SERCOM1 | MCLK_APBAMASK_TC0 | MCLK_APBAMASK_TC1;
+  
+  MCLK->APBBMASK.reg |= MCLK_APBBMASK_SERCOM2 | MCLK_APBBMASK_SERCOM3 | MCLK_APBBMASK_TCC0 | MCLK_APBBMASK_TCC1 | MCLK_APBBMASK_TC3 | MCLK_APBBMASK_TC2;
+  
+  MCLK->APBCMASK.reg |= MCLK_APBCMASK_TCC2 | MCLK_APBCMASK_TCC3 | MCLK_APBCMASK_TC4 | MCLK_APBCMASK_TC5;
+  
+  MCLK->APBDMASK.reg |= MCLK_APBDMASK_DAC | MCLK_APBDMASK_SERCOM4 | MCLK_APBDMASK_SERCOM5 | MCLK_APBDMASK_ADC0 | MCLK_APBDMASK_ADC1 | MCLK_APBDMASK_TCC4
+		  | MCLK_APBDMASK_TC6 | MCLK_APBDMASK_TC7 | MCLK_APBDMASK_SERCOM6 | MCLK_APBDMASK_SERCOM7;
+
+#else
   // Clock SERCOM for Serial
   PM->APBCMASK.reg |= PM_APBCMASK_SERCOM0 | PM_APBCMASK_SERCOM1 | PM_APBCMASK_SERCOM2 | PM_APBCMASK_SERCOM3 | PM_APBCMASK_SERCOM4 | PM_APBCMASK_SERCOM5 ;
 
   // Clock TC/TCC for Pulse and Analog
-  PM->APBCMASK.reg |= PM_APBCMASK_TCC0 | PM_APBCMASK_TCC1 | PM_APBCMASK_TCC2 | PM_APBCMASK_TC3 | PM_APBCMASK_TC4 | PM_APBCMASK_TC5 ;
+  PM->APBCMASK.reg |= PM_APBCMASK_TCC0 | PM_APBCMASK_TCC1 | PM_APBCMASK_TCC2 | PM_APBCMASK_TC3 | PM_APBCMASK_TC4 | PM_APBCMASK_TC5 | PM_APBCMASK_TC6 | PM_APBCMASK_TC7;
 
-  // Clock ADC/DAC for Analog
-  PM->APBCMASK.reg |= PM_APBCMASK_ADC | PM_APBCMASK_DAC ;
+  // ATSAMR, for example, doesn't have a DAC
+  #ifdef PM_APBCMASK_DAC
+   // Clock ADC/DAC for Analog
+   PM->APBCMASK.reg |= PM_APBCMASK_ADC | PM_APBCMASK_DAC ;
+  #endif
+#endif
 
+/* 
+  Commented out to leave pins in default tri-state.  This is
+  aimed at avoiding power consumption in DeepSleep.
+  
   // Setup all pins (digital and analog) in INPUT mode (default is nothing)
   for (uint32_t ul = 0 ; ul < NUM_DIGITAL_PINS ; ul++ )
   {
     pinMode( ul, INPUT ) ;
   }
+*/
 
   // Initialize Analog Controller
   // Setting clock
+#if defined(__SAMD51__)
+  //set to 1/(1/(48000000/32) * 6) = 250000 SPS
+	GCLK->PCHCTRL[ADC0_GCLK_ID].reg = GCLK_PCHCTRL_GEN_GCLK1_Val | (1 << GCLK_PCHCTRL_CHEN_Pos); //use clock generator 1 (48Mhz)
+	GCLK->PCHCTRL[ADC1_GCLK_ID].reg = GCLK_PCHCTRL_GEN_GCLK1_Val | (1 << GCLK_PCHCTRL_CHEN_Pos); //use clock generator 1 (48Mhz)
+	Adc *adcs[] = {ADC0, ADC1};
+		for(int i=0; i<2; i++){
+
+		adcs[i]->CTRLA.bit.PRESCALER = ADC_CTRLA_PRESCALER_DIV32_Val;
+		adcs[i]->CTRLB.bit.RESSEL = ADC_CTRLB_RESSEL_10BIT_Val;
+
+		while( adcs[i]->SYNCBUSY.reg & ADC_SYNCBUSY_CTRLB );  //wait for sync
+
+		adcs[i]->SAMPCTRL.reg = 5;                        // sampling Time Length
+
+		while( adcs[i]->SYNCBUSY.reg & ADC_SYNCBUSY_SAMPCTRL );  //wait for sync
+
+		adcs[i]->INPUTCTRL.reg = ADC_INPUTCTRL_MUXNEG_GND;   // No Negative input (Internal Ground)
+
+		while( adcs[i]->SYNCBUSY.reg & ADC_SYNCBUSY_INPUTCTRL );  //wait for sync
+
+		// Averaging (see datasheet table in AVGCTRL register description)
+		adcs[i]->AVGCTRL.reg = ADC_AVGCTRL_SAMPLENUM_1 |    // 1 sample only (no oversampling nor averaging)
+							ADC_AVGCTRL_ADJRES(0x0ul);   // Adjusting result by 0
+
+		while( adcs[i]->SYNCBUSY.reg & ADC_SYNCBUSY_AVGCTRL );  //wait for sync
+	}
+
+	analogReference( AR_DEFAULT ) ; // Analog Reference is AREF pin (3.3v)
+	
+	GCLK->PCHCTRL[DAC_GCLK_ID].reg = GCLK_PCHCTRL_GEN_GCLK4_Val | (1 << GCLK_PCHCTRL_CHEN_Pos); //use clock generator 4 (12mhz)
+	while (GCLK->PCHCTRL[DAC_GCLK_ID].bit.CHEN == 0);
+	
+	while ( DAC->SYNCBUSY.bit.SWRST == 1 ); // Wait for synchronization of registers between the clock domains
+	DAC->CTRLA.bit.SWRST = 1;
+	while ( DAC->SYNCBUSY.bit.SWRST == 1 ); // Wait for synchronization of registers between the clock domains
+	
+	DAC->CTRLB.reg = DAC_CTRLB_REFSEL_VREFPU; // TODO: fix this once silicon bug is fixed
+	
+	//set refresh rates
+	DAC->DACCTRL[0].bit.REFRESH = 2;
+	DAC->DACCTRL[1].bit.REFRESH = 2;
+
+#else
+  //set to 1/(1/(48000000/32) * 6) = 250000 SPS
+
   while(GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY);
 
   GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID( GCM_ADC ) | // Generic Clock ADC
@@ -96,10 +167,10 @@ void init( void )
 
   while( ADC->STATUS.bit.SYNCBUSY == 1 );          // Wait for synchronization of registers between the clock domains
 
-  ADC->CTRLB.reg = ADC_CTRLB_PRESCALER_DIV512 |    // Divide Clock by 512.
+  ADC->CTRLB.reg = ADC_CTRLB_PRESCALER_DIV32 |    // Divide Clock by 32.
                    ADC_CTRLB_RESSEL_10BIT;         // 10 bits resolution as default
 
-  ADC->SAMPCTRL.reg = 0x3f;                        // Set max Sampling Time Length
+  ADC->SAMPCTRL.reg = 5;                        // Sampling Time Length
 
   while( ADC->STATUS.bit.SYNCBUSY == 1 );          // Wait for synchronization of registers between the clock domains
 
@@ -118,9 +189,15 @@ void init( void )
                       GCLK_CLKCTRL_GEN_GCLK0     | // Generic Clock Generator 0 is source
                       GCLK_CLKCTRL_CLKEN ;
 
+ // ATSAMR, for example, doesn't have a DAC
+ #ifdef DAC
   while ( DAC->STATUS.bit.SYNCBUSY == 1 ); // Wait for synchronization of registers between the clock domains
   DAC->CTRLB.reg = DAC_CTRLB_REFSEL_AVCC | // Using the 3.3V reference
                    DAC_CTRLB_EOEN ;        // External Output Enable (Vout)
+ #endif
+
+
+#endif //SAMD51
 }
 
 #ifdef __cplusplus
diff --git a/cores/arduino/wiring_analog.c b/cores/arduino/wiring_analog.c
index b58509c06..f809c32a4 100644
--- a/cores/arduino/wiring_analog.c
+++ b/cores/arduino/wiring_analog.c
@@ -1,5 +1,6 @@
 /*
   Copyright (c) 2014 Arduino LLC.  All right reserved.
+  SAMD51 support added by Adafruit - Copyright (c) 2018 Dean Miller for Adafruit Industries
 
   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
@@ -25,8 +26,17 @@ extern "C" {
 
 static int _readResolution = 10;
 static int _ADCResolution = 10;
+
+#if defined(__SAMD51__)
+static int _writeResolution = 12;
+static int _dacResolution = 12;
+#else
 static int _writeResolution = 8;
+//static int _dacResolution = 10;
+#endif
 
+
+#if !defined(__SAMD51__)
 // Wait for synchronization of registers between the clock domains
 static __inline__ void syncADC() __attribute__((always_inline, unused));
 static void syncADC() {
@@ -34,12 +44,15 @@ static void syncADC() {
     ;
 }
 
+ // ATSAMR, for example, doesn't have a DAC
+#ifdef DAC
 // Wait for synchronization of registers between the clock domains
 static __inline__ void syncDAC() __attribute__((always_inline, unused));
 static void syncDAC() {
   while (DAC->STATUS.bit.SYNCBUSY == 1)
     ;
 }
+#endif
 
 // Wait for synchronization of registers between the clock domains
 static __inline__ void syncTC_16(Tc* TCx) __attribute__((always_inline, unused));
@@ -53,20 +66,47 @@ static void syncTCC(Tcc* TCCx) {
   while (TCCx->SYNCBUSY.reg & TCC_SYNCBUSY_MASK);
 }
 
+#else
+static bool dacEnabled[2];
+#endif
+
 void analogReadResolution(int res)
 {
   _readResolution = res;
-  if (res > 10) {
-    ADC->CTRLB.bit.RESSEL = ADC_CTRLB_RESSEL_12BIT_Val;
-    _ADCResolution = 12;
-  } else if (res > 8) {
-    ADC->CTRLB.bit.RESSEL = ADC_CTRLB_RESSEL_10BIT_Val;
-    _ADCResolution = 10;
-  } else {
-    ADC->CTRLB.bit.RESSEL = ADC_CTRLB_RESSEL_8BIT_Val;
-    _ADCResolution = 8;
-  }
+#if defined(__SAMD51__)
+
+	if (res > 10) {
+		ADC0->CTRLB.bit.RESSEL = ADC_CTRLB_RESSEL_12BIT_Val;
+		ADC1->CTRLB.bit.RESSEL = ADC_CTRLB_RESSEL_12BIT_Val;
+		_ADCResolution = 12;
+		} else if (res > 8) {
+		ADC0->CTRLB.bit.RESSEL = ADC_CTRLB_RESSEL_10BIT_Val;
+		ADC1->CTRLB.bit.RESSEL = ADC_CTRLB_RESSEL_10BIT_Val;
+		_ADCResolution = 10;
+		} else {
+		ADC0->CTRLB.bit.RESSEL = ADC_CTRLB_RESSEL_8BIT_Val;
+		ADC1->CTRLB.bit.RESSEL = ADC_CTRLB_RESSEL_8BIT_Val;
+		_ADCResolution = 8;
+	}
+
+
+	while(ADC0->SYNCBUSY.reg & ADC_SYNCBUSY_CTRLB); //wait for sync
+	while(ADC1->SYNCBUSY.reg & ADC_SYNCBUSY_CTRLB); //wait for sync
+#else
+
+	if (res > 10) {
+		ADC->CTRLB.bit.RESSEL = ADC_CTRLB_RESSEL_12BIT_Val;
+		_ADCResolution = 12;
+		} else if (res > 8) {
+		ADC->CTRLB.bit.RESSEL = ADC_CTRLB_RESSEL_10BIT_Val;
+		_ADCResolution = 10;
+		} else {
+		ADC->CTRLB.bit.RESSEL = ADC_CTRLB_RESSEL_8BIT_Val;
+		_ADCResolution = 8;
+	}
+
   syncADC();
+#endif
 }
 
 void analogWriteResolution(int res)
@@ -93,10 +133,101 @@ static inline uint32_t mapResolution(uint32_t value, uint32_t from, uint32_t to)
  */
 void analogReference(eAnalogReference mode)
 {
+#if defined(__SAMD51__)
+	while(ADC0->SYNCBUSY.reg & ADC_SYNCBUSY_REFCTRL); //wait for sync
+	while(ADC1->SYNCBUSY.reg & ADC_SYNCBUSY_REFCTRL); //wait for sync
+	
+	//TODO: fix gains
+	switch (mode)
+	{
+		case AR_INTERNAL1V0:
+		//ADC0->GAINCORR.reg = ADC_GAINCORR_GAINCORR();      // Gain Factor Selection
+		SUPC->VREF.bit.SEL = SUPC_VREF_SEL_1V0_Val;		// select 1.0V
+		SUPC->VREF.bit.VREFOE = 1;	//	Turn on for use with ADC
+		ADC0->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_INTREF_Val; // Use SUPC.VREF
+		ADC1->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_INTREF_Val; // 
+		break;
+		
+		case AR_INTERNAL1V1:
+		//ADC0->GAINCORR.reg = ADC_GAINCORR_GAINCORR();      // Gain Factor Selection
+		SUPC->VREF.bit.SEL = SUPC_VREF_SEL_1V1_Val;		// select 1.1V
+		SUPC->VREF.bit.VREFOE = 1;	//	Turn on for use with ADC
+		ADC0->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_INTREF_Val; // Use SUPC.VREF
+		ADC1->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_INTREF_Val; // 
+		break;
+		
+		case AR_INTERNAL1V2:
+		//ADC0->GAINCORR.reg = ADC_GAINCORR_GAINCORR();      // Gain Factor Selection
+		SUPC->VREF.bit.SEL = SUPC_VREF_SEL_1V2_Val;		// select 1V2
+		SUPC->VREF.bit.VREFOE = 1;	//	Turn on for use with ADC
+		ADC0->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_INTREF_Val; // Use SUPC.VREF
+		ADC1->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_INTREF_Val; // 
+		break;
+
+		case AR_INTERNAL1V25:
+		//ADC0->GAINCORR.reg = ADC_GAINCORR_GAINCORR();      // Gain Factor Selection
+		SUPC->VREF.bit.SEL = SUPC_VREF_SEL_1V25_Val;		// select 1.25V
+		SUPC->VREF.bit.VREFOE = 1;	//	Turn on for use with ADC
+		ADC0->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_INTREF_Val; // Use SUPC.VREF
+		ADC1->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_INTREF_Val; // 
+		break;
+		
+		case AR_INTERNAL2V0:
+		//ADC0->GAINCORR.reg = ADC_GAINCORR_GAINCORR();      // Gain Factor Selection
+		SUPC->VREF.bit.SEL = SUPC_VREF_SEL_2V0_Val;		// select 2.0V
+		SUPC->VREF.bit.VREFOE = 1;	//	Turn on for use with ADC
+		ADC0->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_INTREF_Val; // Use SUPC.VREF
+		ADC1->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_INTREF_Val; // 
+		break;
+		
+		case AR_INTERNAL2V2:
+		//ADC0->GAINCORR.reg = ADC_GAINCORR_GAINCORR();      // Gain Factor Selection
+		SUPC->VREF.bit.SEL = SUPC_VREF_SEL_2V2_Val;		// select 2.2V
+		SUPC->VREF.bit.VREFOE = 1;	//	Turn on for use with ADC
+		ADC0->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_INTREF_Val; // Use SUPC.VREF
+		ADC1->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_INTREF_Val; // 
+		break;
+		
+		case AR_INTERNAL2V4:
+		//ADC0->GAINCORR.reg = ADC_GAINCORR_GAINCORR();      // Gain Factor Selection
+		SUPC->VREF.bit.SEL = SUPC_VREF_SEL_2V4_Val;		// select 2.4V
+		SUPC->VREF.bit.VREFOE = 1;	//	Turn on for use with ADC
+		ADC0->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_INTREF_Val; // Use SUPC.VREF
+		ADC1->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_INTREF_Val; // 
+		break;
+		
+		case AR_INTERNAL2V5:
+		//ADC0->GAINCORR.reg = ADC_GAINCORR_GAINCORR();      // Gain Factor Selection
+		SUPC->VREF.bit.SEL = SUPC_VREF_SEL_2V5_Val;		// select 2.5V
+		SUPC->VREF.bit.VREFOE = 1;	//	Turn on for use with ADC
+		ADC0->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_INTREF_Val; // Use SUPC.VREF
+		ADC1->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_INTREF_Val; // 
+		break;
+		
+		case AR_EXTERNAL:
+		//ADC0->INPUTCTRL.bit.GAIN = ADC_INPUTCTRL_GAIN_1X_Val;      // Gain Factor Selection
+		ADC0->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_AREFA_Val;	// AREF is jumpered to VCC, so 3.3V
+		ADC1->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_AREFA_Val;
+		break;
+
+		case AR_INTERNAL1V65:
+		//ADC0->INPUTCTRL.bit.GAIN = ADC_INPUTCTRL_GAIN_DIV2_Val;
+		ADC0->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_INTVCC0_Val; // 1/2 VDDANA = 1.65
+		ADC1->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_INTVCC0_Val; // 
+		break;
+		
+		case AR_DEFAULT:
+		default:
+		//ADC0->INPUTCTRL.bit.GAIN = ADC_INPUTCTRL_GAIN_DIV2_Val;
+		ADC0->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_INTVCC1_Val; // VDDANA = 3V3
+		ADC1->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_INTVCC1_Val; // 
+		break;
+	}
+	
+#else
   syncADC();
   switch (mode)
   {
-    case AR_INTERNAL:
     case AR_INTERNAL2V23:
       ADC->INPUTCTRL.bit.GAIN = ADC_INPUTCTRL_GAIN_1X_Val;      // Gain Factor Selection
       ADC->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_INTVCC0_Val; // 1/1.48 VDDANA = 1/1.48* 3V3 = 2.2297
@@ -123,29 +254,108 @@ void analogReference(eAnalogReference mode)
       ADC->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_INTVCC1_Val; // 1/2 VDDANA = 0.5* 3V3 = 1.65V
       break;
   }
+#endif
 }
 
 uint32_t analogRead(uint32_t pin)
 {
   uint32_t valueRead = 0;
 
-  if (pin < A0) {
+#if defined(PIN_A6)
+  if (pin == 6) {
+    pin = PIN_A6;
+  } else
+#endif
+#if defined(PIN_A7)
+  if (pin == 7) {
+    pin = PIN_A7;
+  } else 
+#endif
+  if (pin <= 5) {
     pin += A0;
   }
 
   pinPeripheral(pin, PIO_ANALOG);
+ //ATSAMR, for example, doesn't have a DAC
+#ifdef DAC
+
+	#if defined(__SAMD51__)
+	  if (pin == PIN_DAC0 || pin == PIN_DAC1) { // Disable DAC, if analogWrite(A0,dval) used previously the DAC is enabled
+		uint8_t channel = (pin == PIN_DAC0 ? 0 : 1);
+		
+		if(dacEnabled[channel]){
+			dacEnabled[channel] = false;
+			
+			while (DAC->SYNCBUSY.bit.ENABLE || DAC->SYNCBUSY.bit.SWRST);
+			DAC->CTRLA.bit.ENABLE = 0;     // disable DAC
+			
+			while (DAC->SYNCBUSY.bit.ENABLE || DAC->SYNCBUSY.bit.SWRST);
+			DAC->DACCTRL[channel].bit.ENABLE = 0;
+			
+			while (DAC->SYNCBUSY.bit.ENABLE || DAC->SYNCBUSY.bit.SWRST);
+			DAC->CTRLA.bit.ENABLE = 1;     // enable DAC
+		}
+		
+		while (DAC->SYNCBUSY.bit.ENABLE);
+	#else
+	  if (pin == PIN_DAC0) { // Disable DAC, if analogWrite(A0,dval) used previously the DAC is enabled
+	    syncDAC();
+		
+		DAC->CTRLA.bit.ENABLE = 0x00; // Disable DAC
+		//DAC->CTRLB.bit.EOEN = 0x00; // The DAC output is turned off.
+		syncDAC();
+	#endif
+	  }
 
-  // Disable DAC, if analogWrite() was used previously to enable the DAC
-  if ((g_APinDescription[pin].ulADCChannelNumber == ADC_Channel0) || (g_APinDescription[pin].ulADCChannelNumber == DAC_Channel0)) {
-    syncDAC();
-    DAC->CTRLA.bit.ENABLE = 0x00; // Disable DAC
-    //DAC->CTRLB.bit.EOEN = 0x00; // The DAC output is turned off.
-    syncDAC();
-  }
+#endif
+
+#if defined(__SAMD51__)
+  Adc *adc;
+  if(g_APinDescription[pin].ulPinAttribute & PIN_ATTR_ANALOG) adc = ADC0;
+  else if(g_APinDescription[pin].ulPinAttribute & PIN_ATTR_ANALOG_ALT) adc = ADC1;
+  else return 0;
+
+  while( adc->SYNCBUSY.reg & ADC_SYNCBUSY_INPUTCTRL ); //wait for sync
+  adc->INPUTCTRL.bit.MUXPOS = g_APinDescription[pin].ulADCChannelNumber; // Selection for the positive ADC input
+  
+  // Control A
+  /*
+   * Bit 1 ENABLE: Enable
+   *   0: The ADC is disabled.
+   *   1: The ADC is enabled.
+   * Due to synchronization, there is a delay from writing CTRLA.ENABLE until the peripheral is enabled/disabled. The
+   * value written to CTRL.ENABLE will read back immediately and the Synchronization Busy bit in the Status register
+   * (STATUS.SYNCBUSY) will be set. STATUS.SYNCBUSY will be cleared when the operation is complete.
+   *
+   * Before enabling the ADC, the asynchronous clock source must be selected and enabled, and the ADC reference must be
+   * configured. The first conversion after the reference is changed must not be used.
+   */
+  while( adc->SYNCBUSY.reg & ADC_SYNCBUSY_ENABLE ); //wait for sync
+  adc->CTRLA.bit.ENABLE = 0x01;             // Enable ADC
+
+  // Start conversion
+  while( adc->SYNCBUSY.reg & ADC_SYNCBUSY_ENABLE ); //wait for sync
+  
+  adc->SWTRIG.bit.START = 1;
+
+  // Clear the Data Ready flag
+  adc->INTFLAG.reg = ADC_INTFLAG_RESRDY;
+
+  // Start conversion again, since The first conversion after the reference is changed must not be used.
+  adc->SWTRIG.bit.START = 1;
 
+  // Store the value
+  while (adc->INTFLAG.bit.RESRDY == 0);   // Waiting for conversion to complete
+  valueRead = adc->RESULT.reg;
+
+  while( adc->SYNCBUSY.reg & ADC_SYNCBUSY_ENABLE ); //wait for sync
+  adc->CTRLA.bit.ENABLE = 0x00;             // Disable ADC
+  while( adc->SYNCBUSY.reg & ADC_SYNCBUSY_ENABLE ); //wait for sync
+  
+#else
   syncADC();
   ADC->INPUTCTRL.bit.MUXPOS = g_APinDescription[pin].ulADCChannelNumber; // Selection for the positive ADC input
-
+  
   // Control A
   /*
    * Bit 1 ENABLE: Enable
@@ -179,6 +389,7 @@ uint32_t analogRead(uint32_t pin)
   syncADC();
   ADC->CTRLA.bit.ENABLE = 0x00;             // Disable ADC
   syncADC();
+#endif
 
   return mapResolution(valueRead, _ADCResolution, _readResolution);
 }
@@ -193,115 +404,273 @@ void analogWrite(uint32_t pin, uint32_t value)
   PinDescription pinDesc = g_APinDescription[pin];
   uint32_t attr = pinDesc.ulPinAttribute;
 
-  if ((attr & PIN_ATTR_ANALOG) == PIN_ATTR_ANALOG)
-  {
-    // DAC handling code
+ // ATSAMR, for example, doesn't have a DAC
+#ifdef DAC
+	  if ((attr & PIN_ATTR_ANALOG) == PIN_ATTR_ANALOG)
+	  {
+	    // DAC handling code
+#if defined(__SAMD51__)
+		if (pin == PIN_DAC0 || pin == PIN_DAC1) { // 2 DACs on A0 (PA02) and A1 (PA05)
+#else
+	    if (pin == PIN_DAC0) { // Only 1 DAC on A0 (PA02)
+#endif
 
-    if ((pinDesc.ulADCChannelNumber != ADC_Channel0) && (pinDesc.ulADCChannelNumber != DAC_Channel0)) { // Only 1 DAC on AIN0 / PA02
-      return;
-    }
+#if defined(__SAMD51__)
 
-    value = mapResolution(value, _writeResolution, 10);
+	    value = mapResolution(value, _writeResolution, _dacResolution);
 
-    syncDAC();
-    DAC->DATA.reg = value & 0x3FF;  // DAC on 10 bits.
-    syncDAC();
-    DAC->CTRLA.bit.ENABLE = 0x01;     // Enable DAC
-    syncDAC();
-    return;
-  }
+
+			uint8_t channel = (pin == PIN_DAC0 ? 0 : 1);
+
+			pinPeripheral(pin, PIO_ANALOG);
+
+			if(!dacEnabled[channel]){
+				dacEnabled[channel] = true;
+
+				while (DAC->SYNCBUSY.bit.ENABLE || DAC->SYNCBUSY.bit.SWRST);
+				DAC->CTRLA.bit.ENABLE = 0;     // disable DAC
+
+				while (DAC->SYNCBUSY.bit.ENABLE || DAC->SYNCBUSY.bit.SWRST);
+				DAC->DACCTRL[channel].bit.ENABLE = 1;
+
+				while (DAC->SYNCBUSY.bit.ENABLE || DAC->SYNCBUSY.bit.SWRST);
+				DAC->CTRLA.bit.ENABLE = 1;     // enable DAC
+
+				if(channel == 0){
+
+					while ( !DAC->STATUS.bit.READY0 );
+
+					while (DAC->SYNCBUSY.bit.DATA0);
+					DAC->DATA[0].reg = value;
+				}
+				else if(channel == 1){
+					while ( !DAC->STATUS.bit.READY1 );
+
+					while (DAC->SYNCBUSY.bit.DATA1);
+					DAC->DATA[1].reg = value;
+				}
+
+				delayMicroseconds(10000);
+			}
+
+			//ERROR!
+			while(!DAC->DACCTRL[channel].bit.ENABLE);
+
+			if(channel == 0){
+
+				while ( !DAC->STATUS.bit.READY0 );
+
+				while (DAC->SYNCBUSY.bit.DATA0);
+				DAC->DATA[0].reg = value;  // DAC on 10 bits.
+			}
+			else if(channel == 1){
+				while ( !DAC->STATUS.bit.READY1 );
+
+				while (DAC->SYNCBUSY.bit.DATA1);
+				DAC->DATA[1].reg = value;  // DAC on 10 bits.
+			}
+
+
+#else
+			syncDAC();
+			DAC->DATA.reg = value & 0x3FF;  // DAC on 10 bits.
+			syncDAC();
+			DAC->CTRLA.bit.ENABLE = 0x01;     // Enable DAC
+			syncDAC();
+#endif // __SAMD51__
+				return;
+	  }
+	}
+#endif // DAC
+
+#if defined(__SAMD51__)
+	if(attr & (PIN_ATTR_PWM_E|PIN_ATTR_PWM_F|PIN_ATTR_PWM_G)){
+
+		uint32_t tcNum = GetTCNumber(pinDesc.ulPWMChannel);
+		uint8_t tcChannel = GetTCChannelNumber(pinDesc.ulPWMChannel);
+		static bool tcEnabled[TCC_INST_NUM+TC_INST_NUM];
+
+		if(attr & PIN_ATTR_PWM_E)
+			pinPeripheral(pin, PIO_TIMER);
+		else if(attr & PIN_ATTR_PWM_F)
+			pinPeripheral(pin, PIO_TIMER_ALT);
+		else if(attr & PIN_ATTR_PWM_G)
+			pinPeripheral(pin, PIO_TCC_PDEC);
+
+		if (!tcEnabled[tcNum]) {
+		  tcEnabled[tcNum] = true;
+	      GCLK->PCHCTRL[GCLK_CLKCTRL_IDs[tcNum]].reg = GCLK_PCHCTRL_GEN_GCLK0_Val | (1 << GCLK_PCHCTRL_CHEN_Pos); //use clock generator 0
+
+	      // Set PORT
+	      if (tcNum >= TCC_INST_NUM) {
+				// -- Configure TC
+				Tc* TCx = (Tc*) GetTC(pinDesc.ulPWMChannel);
+
+				//reset
+				TCx->COUNT8.CTRLA.bit.SWRST = 1;
+				while (TCx->COUNT8.SYNCBUSY.bit.SWRST);
+
+				// Disable TCx
+				TCx->COUNT8.CTRLA.bit.ENABLE = 0;
+				while (TCx->COUNT8.SYNCBUSY.bit.ENABLE);
+				// Set Timer counter Mode to 8 bits, normal PWM, prescaler 1/256
+				TCx->COUNT8.CTRLA.reg = TC_CTRLA_MODE_COUNT8 | TC_CTRLA_PRESCALER_DIV256;
+				TCx->COUNT8.WAVE.reg = TC_WAVE_WAVEGEN_NPWM;
+
+				while (TCx->COUNT8.SYNCBUSY.bit.CC0);
+				// Set the initial value
+				TCx->COUNT8.CC[tcChannel].reg = (uint8_t) value;
+				while (TCx->COUNT8.SYNCBUSY.bit.CC0);
+				// Set PER to maximum counter value (resolution : 0xFF)
+				TCx->COUNT8.PER.reg = 0xFF;
+				while (TCx->COUNT8.SYNCBUSY.bit.PER);
+				// Enable TCx
+				TCx->COUNT8.CTRLA.bit.ENABLE = 1;
+				while (TCx->COUNT8.SYNCBUSY.bit.ENABLE);
+			} else {
+				// -- Configure TCC
+				Tcc* TCCx = (Tcc*) GetTC(pinDesc.ulPWMChannel);
+
+				TCCx->CTRLA.bit.SWRST = 1;
+				while (TCCx->SYNCBUSY.bit.SWRST);
+
+				// Disable TCCx
+				TCCx->CTRLA.bit.ENABLE = 0;
+				while (TCCx->SYNCBUSY.bit.ENABLE);
+				// Set prescaler to 1/256
+				TCCx->CTRLA.reg = TCC_CTRLA_PRESCALER_DIV256 | TCC_CTRLA_PRESCSYNC_GCLK;
+
+				// Set TCx as normal PWM
+				TCCx->WAVE.reg = TCC_WAVE_WAVEGEN_NPWM;
+				while ( TCCx->SYNCBUSY.bit.WAVE );
+
+				while (TCCx->SYNCBUSY.bit.CC0 || TCCx->SYNCBUSY.bit.CC1);
+				// Set the initial value
+				TCCx->CC[tcChannel].reg = (uint32_t) value;
+				while (TCCx->SYNCBUSY.bit.CC0 || TCCx->SYNCBUSY.bit.CC1);
+				// Set PER to maximum counter value (resolution : 0xFF)
+				TCCx->PER.reg = 0xFF;
+				while (TCCx->SYNCBUSY.bit.PER);
+				// Enable TCCx
+				TCCx->CTRLA.bit.ENABLE = 1;
+				while (TCCx->SYNCBUSY.bit.ENABLE);
+			}
+		}
+		else {
+			if (tcNum >= TCC_INST_NUM) {
+				Tc* TCx = (Tc*) GetTC(pinDesc.ulPWMChannel);
+				TCx->COUNT8.CC[tcChannel].reg = (uint8_t) value;
+				while (TCx->COUNT8.SYNCBUSY.bit.CC0 || TCx->COUNT8.SYNCBUSY.bit.CC1);
+				} else {
+				Tcc* TCCx = (Tcc*) GetTC(pinDesc.ulPWMChannel);
+				while (TCCx->SYNCBUSY.bit.CTRLB);
+				while (TCCx->SYNCBUSY.bit.CC0 || TCCx->SYNCBUSY.bit.CC1);
+				TCCx->CCBUF[tcChannel].reg = (uint32_t) value;
+				while (TCCx->SYNCBUSY.bit.CC0 || TCCx->SYNCBUSY.bit.CC1);
+				TCCx->CTRLBCLR.bit.LUPD = 1;
+				while (TCCx->SYNCBUSY.bit.CTRLB);
+				}
+		}
+
+		return;
+	}
+	  
+#else
 
   if ((attr & PIN_ATTR_PWM) == PIN_ATTR_PWM)
-  {
-    value = mapResolution(value, _writeResolution, 16);
-
-    uint32_t tcNum = GetTCNumber(pinDesc.ulPWMChannel);
-    uint8_t tcChannel = GetTCChannelNumber(pinDesc.ulPWMChannel);
-    static bool tcEnabled[TCC_INST_NUM+TC_INST_NUM];
-
-    if (attr & PIN_ATTR_TIMER) {
-      #if !(ARDUINO_SAMD_VARIANT_COMPLIANCE >= 10603)
-      // Compatibility for cores based on SAMD core <=1.6.2
-      if (pinDesc.ulPinType == PIO_TIMER_ALT) {
-        pinPeripheral(pin, PIO_TIMER_ALT);
-      } else
-      #endif
-      {
-        pinPeripheral(pin, PIO_TIMER);
-      }
-    } else {
-      // We suppose that attr has PIN_ATTR_TIMER_ALT bit set...
-      pinPeripheral(pin, PIO_TIMER_ALT);
-    }
-
-    if (!tcEnabled[tcNum]) {
-      tcEnabled[tcNum] = true;
-
-      uint16_t GCLK_CLKCTRL_IDs[] = {
-        GCLK_CLKCTRL_ID(GCM_TCC0_TCC1), // TCC0
-        GCLK_CLKCTRL_ID(GCM_TCC0_TCC1), // TCC1
-        GCLK_CLKCTRL_ID(GCM_TCC2_TC3),  // TCC2
-        GCLK_CLKCTRL_ID(GCM_TCC2_TC3),  // TC3
-        GCLK_CLKCTRL_ID(GCM_TC4_TC5),   // TC4
-        GCLK_CLKCTRL_ID(GCM_TC4_TC5),   // TC5
-        GCLK_CLKCTRL_ID(GCM_TC6_TC7),   // TC6
-        GCLK_CLKCTRL_ID(GCM_TC6_TC7),   // TC7
-      };
-      GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_IDs[tcNum]);
-      while (GCLK->STATUS.bit.SYNCBUSY == 1);
-
-      // Set PORT
-      if (tcNum >= TCC_INST_NUM) {
-        // -- Configure TC
-        Tc* TCx = (Tc*) GetTC(pinDesc.ulPWMChannel);
-        // Disable TCx
-        TCx->COUNT16.CTRLA.bit.ENABLE = 0;
-        syncTC_16(TCx);
-        // Set Timer counter Mode to 16 bits, normal PWM
-        TCx->COUNT16.CTRLA.reg |= TC_CTRLA_MODE_COUNT16 | TC_CTRLA_WAVEGEN_NPWM;
-        syncTC_16(TCx);
-        // Set the initial value
-        TCx->COUNT16.CC[tcChannel].reg = (uint32_t) value;
-        syncTC_16(TCx);
-        // Enable TCx
-        TCx->COUNT16.CTRLA.bit.ENABLE = 1;
-        syncTC_16(TCx);
-      } else {
-        // -- Configure TCC
-        Tcc* TCCx = (Tcc*) GetTC(pinDesc.ulPWMChannel);
-        // Disable TCCx
-        TCCx->CTRLA.bit.ENABLE = 0;
-        syncTCC(TCCx);
-        // Set TCCx as normal PWM
-        TCCx->WAVE.reg |= TCC_WAVE_WAVEGEN_NPWM;
-        syncTCC(TCCx);
-        // Set the initial value
-        TCCx->CC[tcChannel].reg = (uint32_t) value;
-        syncTCC(TCCx);
-        // Set PER to maximum counter value (resolution : 0xFFFF)
-        TCCx->PER.reg = 0xFFFF;
-        syncTCC(TCCx);
-        // Enable TCCx
-        TCCx->CTRLA.bit.ENABLE = 1;
-        syncTCC(TCCx);
-      }
-    } else {
-      if (tcNum >= TCC_INST_NUM) {
-        Tc* TCx = (Tc*) GetTC(pinDesc.ulPWMChannel);
-        TCx->COUNT16.CC[tcChannel].reg = (uint32_t) value;
-        syncTC_16(TCx);
-      } else {
-        Tcc* TCCx = (Tcc*) GetTC(pinDesc.ulPWMChannel);
-        TCCx->CTRLBSET.bit.LUPD = 1;
-        syncTCC(TCCx);
-        TCCx->CCB[tcChannel].reg = (uint32_t) value;
-        syncTCC(TCCx);
-        TCCx->CTRLBCLR.bit.LUPD = 1;
-        syncTCC(TCCx);
-      }
-    }
-    return;
+	  {
+	  value = mapResolution(value, _writeResolution, 16);
+
+	  uint32_t tcNum = GetTCNumber(pinDesc.ulPWMChannel);
+	  uint8_t tcChannel = GetTCChannelNumber(pinDesc.ulPWMChannel);
+	  static bool tcEnabled[TCC_INST_NUM+TC_INST_NUM];
+
+	    if (attr & PIN_ATTR_TIMER) {
+#if !(ARDUINO_SAMD_VARIANT_COMPLIANCE >= 10603)
+	      // Compatibility for cores based on SAMD core <=1.6.2
+	      if (pinDesc.ulPinType == PIO_TIMER_ALT) {
+	        pinPeripheral(pin, PIO_TIMER_ALT);
+	      } else
+#endif
+	      {
+	        pinPeripheral(pin, PIO_TIMER);
+	      }
+	    } else if ((attr & PIN_ATTR_TIMER_ALT) == PIN_ATTR_TIMER_ALT){
+	        //this is on an alt timer
+	        pinPeripheral(pin, PIO_TIMER_ALT);
+	    }
+	    else{
+	        return;
+	    }
+
+	    if (!tcEnabled[tcNum]) {
+	      tcEnabled[tcNum] = true;
+		  uint16_t GCLK_CLKCTRL_IDs[] = {
+			GCLK_CLKCTRL_ID(GCM_TCC0_TCC1), // TCC0
+			GCLK_CLKCTRL_ID(GCM_TCC0_TCC1), // TCC1
+			GCLK_CLKCTRL_ID(GCM_TCC2_TC3),  // TCC2
+			GCLK_CLKCTRL_ID(GCM_TCC2_TC3),  // TC3
+			GCLK_CLKCTRL_ID(GCM_TC4_TC5),   // TC4
+			GCLK_CLKCTRL_ID(GCM_TC4_TC5),   // TC5
+			GCLK_CLKCTRL_ID(GCM_TC6_TC7),   // TC6
+			GCLK_CLKCTRL_ID(GCM_TC6_TC7),   // TC7
+		  };
+		  GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_IDs[tcNum]);
+		  while (GCLK->STATUS.bit.SYNCBUSY == 1);
+
+		  // Set PORT
+		  if (tcNum >= TCC_INST_NUM) {
+			// -- Configure TC
+			Tc* TCx = (Tc*) GetTC(pinDesc.ulPWMChannel);
+			// Disable TCx
+			TCx->COUNT16.CTRLA.bit.ENABLE = 0;
+			syncTC_16(TCx);
+			// Set Timer counter Mode to 16 bits, normal PWM
+			TCx->COUNT16.CTRLA.reg |= TC_CTRLA_MODE_COUNT16 | TC_CTRLA_WAVEGEN_NPWM;
+			syncTC_16(TCx);
+			// Set the initial value
+			TCx->COUNT16.CC[tcChannel].reg = (uint32_t) value;
+			syncTC_16(TCx);
+			// Enable TCx
+			TCx->COUNT16.CTRLA.bit.ENABLE = 1;
+			syncTC_16(TCx);
+		  } else {
+			// -- Configure TCC
+			Tcc* TCCx = (Tcc*) GetTC(pinDesc.ulPWMChannel);
+			// Disable TCCx
+			TCCx->CTRLA.bit.ENABLE = 0;
+			syncTCC(TCCx);
+			// Set TCCx as normal PWM
+			TCCx->WAVE.reg |= TCC_WAVE_WAVEGEN_NPWM;
+			syncTCC(TCCx);
+			// Set the initial value
+			TCCx->CC[tcChannel].reg = (uint32_t) value;
+			syncTCC(TCCx);
+			// Set PER to maximum counter value (resolution : 0xFFFF)
+			TCCx->PER.reg = 0xFFFF;
+			syncTCC(TCCx);
+			// Enable TCCx
+			TCCx->CTRLA.bit.ENABLE = 1;
+			syncTCC(TCCx);
+		  }
+		} else {
+		  if (tcNum >= TCC_INST_NUM) {
+			Tc* TCx = (Tc*) GetTC(pinDesc.ulPWMChannel);
+			TCx->COUNT16.CC[tcChannel].reg = (uint32_t) value;
+			syncTC_16(TCx);
+		  } else {
+			Tcc* TCCx = (Tcc*) GetTC(pinDesc.ulPWMChannel);
+			TCCx->CTRLBSET.bit.LUPD = 1;
+			syncTCC(TCCx);
+			TCCx->CCB[tcChannel].reg = (uint32_t) value;
+			syncTCC(TCCx);
+			TCCx->CTRLBCLR.bit.LUPD = 1;
+			syncTCC(TCCx);
+		  }
+		}
+	  return;
   }
+#endif
 
   // -- Defaults to digital write
   pinMode(pin, OUTPUT);
diff --git a/cores/arduino/wiring_analog.h b/cores/arduino/wiring_analog.h
index cca46359c..d8dce7335 100644
--- a/cores/arduino/wiring_analog.h
+++ b/cores/arduino/wiring_analog.h
@@ -27,14 +27,21 @@ extern "C" {
 /*
  * \brief SAMD products have only one reference for ADC
  */
+ // add internal voltages for ATSAMD51 SUPC VREF register
 typedef enum _eAnalogReference
 {
   AR_DEFAULT,
-  AR_INTERNAL,
-  AR_EXTERNAL,
   AR_INTERNAL1V0,
+  AR_INTERNAL1V1,
+  AR_INTERNAL1V2,
+  AR_INTERNAL1V25,
+  AR_INTERNAL2V0,
+  AR_INTERNAL2V2,
+  AR_INTERNAL2V23,
+  AR_INTERNAL2V4,
+  AR_INTERNAL2V5,
   AR_INTERNAL1V65,
-  AR_INTERNAL2V23
+  AR_EXTERNAL
 } eAnalogReference ;
 
 
diff --git a/cores/arduino/wiring_digital.c b/cores/arduino/wiring_digital.c
index 026af80df..0e35ffe42 100644
--- a/cores/arduino/wiring_digital.c
+++ b/cores/arduino/wiring_digital.c
@@ -30,39 +30,43 @@ void pinMode( uint32_t ulPin, uint32_t ulMode )
     return ;
   }
 
+  EPortType port = g_APinDescription[ulPin].ulPort;
+  uint32_t pin = g_APinDescription[ulPin].ulPin;
+  uint32_t pinMask = (1ul << pin);
+
   // Set pin mode according to chapter '22.6.3 I/O Pin Configuration'
   switch ( ulMode )
   {
     case INPUT:
       // Set pin to input mode
-      PORT->Group[g_APinDescription[ulPin].ulPort].PINCFG[g_APinDescription[ulPin].ulPin].reg=(uint8_t)(PORT_PINCFG_INEN) ;
-      PORT->Group[g_APinDescription[ulPin].ulPort].DIRCLR.reg = (uint32_t)(1<<g_APinDescription[ulPin].ulPin) ;
+      PORT->Group[port].PINCFG[pin].reg=(uint8_t)(PORT_PINCFG_INEN) ;
+      PORT->Group[port].DIRCLR.reg = pinMask ;
     break ;
 
     case INPUT_PULLUP:
       // Set pin to input mode with pull-up resistor enabled
-      PORT->Group[g_APinDescription[ulPin].ulPort].PINCFG[g_APinDescription[ulPin].ulPin].reg=(uint8_t)(PORT_PINCFG_INEN|PORT_PINCFG_PULLEN) ;
-      PORT->Group[g_APinDescription[ulPin].ulPort].DIRCLR.reg = (uint32_t)(1<<g_APinDescription[ulPin].ulPin) ;
+      PORT->Group[port].PINCFG[pin].reg=(uint8_t)(PORT_PINCFG_INEN|PORT_PINCFG_PULLEN) ;
+      PORT->Group[port].DIRCLR.reg = pinMask ;
 
       // Enable pull level (cf '22.6.3.2 Input Configuration' and '22.8.7 Data Output Value Set')
-      PORT->Group[g_APinDescription[ulPin].ulPort].OUTSET.reg = (uint32_t)(1<<g_APinDescription[ulPin].ulPin) ;
+      PORT->Group[port].OUTSET.reg = pinMask ;
     break ;
 
     case INPUT_PULLDOWN:
       // Set pin to input mode with pull-down resistor enabled
-      PORT->Group[g_APinDescription[ulPin].ulPort].PINCFG[g_APinDescription[ulPin].ulPin].reg=(uint8_t)(PORT_PINCFG_INEN|PORT_PINCFG_PULLEN) ;
-      PORT->Group[g_APinDescription[ulPin].ulPort].DIRCLR.reg = (uint32_t)(1<<g_APinDescription[ulPin].ulPin) ;
+      PORT->Group[port].PINCFG[pin].reg=(uint8_t)(PORT_PINCFG_INEN|PORT_PINCFG_PULLEN) ;
+      PORT->Group[port].DIRCLR.reg = pinMask ;
 
       // Enable pull level (cf '22.6.3.2 Input Configuration' and '22.8.6 Data Output Value Clear')
-      PORT->Group[g_APinDescription[ulPin].ulPort].OUTCLR.reg = (uint32_t)(1<<g_APinDescription[ulPin].ulPin) ;
+      PORT->Group[port].OUTCLR.reg = pinMask ;
     break ;
 
     case OUTPUT:
       // enable input, to support reading back values, with pullups disabled
-      PORT->Group[g_APinDescription[ulPin].ulPort].PINCFG[g_APinDescription[ulPin].ulPin].reg=(uint8_t)(PORT_PINCFG_INEN) ;
+      PORT->Group[port].PINCFG[pin].reg=(uint8_t)(PORT_PINCFG_INEN) ;
 
       // Set pin to output mode
-      PORT->Group[g_APinDescription[ulPin].ulPort].DIRSET.reg = (uint32_t)(1<<g_APinDescription[ulPin].ulPin) ;
+      PORT->Group[port].DIRSET.reg = pinMask ;
     break ;
 
     default:
diff --git a/cores/arduino/wiring_private.c b/cores/arduino/wiring_private.c
index a5aaba42c..954f854af 100644
--- a/cores/arduino/wiring_private.c
+++ b/cores/arduino/wiring_private.c
@@ -1,5 +1,6 @@
 /*
   Copyright (c) 2015 Arduino LLC.  All right reserved.
+  SAMD51 support added by Adafruit - Copyright (c) 2018 Dean Miller for Adafruit Industries
 
   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
@@ -67,8 +68,19 @@ int pinPeripheral( uint32_t ulPin, EPioType ulPeripheral )
     case PIO_TIMER:
     case PIO_TIMER_ALT:
     case PIO_EXTINT:
+#if defined(__SAMD51__)
+    case PIO_TCC_PDEC:
     case PIO_COM:
+    case PIO_SDHC:
+    case PIO_I2S:
+    case PIO_PCC:
+    case PIO_GMAC:
     case PIO_AC_CLK:
+    case PIO_CCL:
+#else
+    case PIO_COM:
+    case PIO_AC_CLK:
+#endif
 #if 0
       // Is the pio pin in the lower 16 ones?
       // The WRCONFIG register allows update of only 16 pin max out of 32
@@ -95,7 +107,7 @@ int pinPeripheral( uint32_t ulPin, EPioType ulPeripheral )
         // Set new muxing
         PORT->Group[g_APinDescription[ulPin].ulPort].PMUX[g_APinDescription[ulPin].ulPin >> 1].reg = temp|PORT_PMUX_PMUXO( ulPeripheral ) ;
         // Enable port mux
-        PORT->Group[g_APinDescription[ulPin].ulPort].PINCFG[g_APinDescription[ulPin].ulPin].reg |= PORT_PINCFG_PMUXEN ;
+        PORT->Group[g_APinDescription[ulPin].ulPort].PINCFG[g_APinDescription[ulPin].ulPin].reg |= PORT_PINCFG_PMUXEN | PORT_PINCFG_DRVSTR;
       }
       else // even pin
       {
@@ -103,7 +115,7 @@ int pinPeripheral( uint32_t ulPin, EPioType ulPeripheral )
 
         temp = (PORT->Group[g_APinDescription[ulPin].ulPort].PMUX[g_APinDescription[ulPin].ulPin >> 1].reg) & PORT_PMUX_PMUXO( 0xF ) ;
         PORT->Group[g_APinDescription[ulPin].ulPort].PMUX[g_APinDescription[ulPin].ulPin >> 1].reg = temp|PORT_PMUX_PMUXE( ulPeripheral ) ;
-        PORT->Group[g_APinDescription[ulPin].ulPort].PINCFG[g_APinDescription[ulPin].ulPin].reg |= PORT_PINCFG_PMUXEN ; // Enable port mux
+        PORT->Group[g_APinDescription[ulPin].ulPort].PINCFG[g_APinDescription[ulPin].ulPin].reg |= PORT_PINCFG_PMUXEN | PORT_PINCFG_DRVSTR ; // Enable port mux
       }
 #endif
     break ;
diff --git a/drivers/prewin10/adafruit_circuit_playground_express.cat b/drivers/prewin10/adafruit_circuit_playground_express.cat
index 1a54878e4..92f460109 100644
Binary files a/drivers/prewin10/adafruit_circuit_playground_express.cat and b/drivers/prewin10/adafruit_circuit_playground_express.cat differ
diff --git a/drivers/prewin10/adafruit_circuit_playground_express.inf b/drivers/prewin10/adafruit_circuit_playground_express.inf
index 248caec08..110b9b738 100644
--- a/drivers/prewin10/adafruit_circuit_playground_express.inf
+++ b/drivers/prewin10/adafruit_circuit_playground_express.inf
@@ -46,6 +46,14 @@ StartType=3
 ErrorControl=1
 ServiceBinary=%12%\%DRIVERFILENAME%.sys
 
+[NullInstall.nt]
+; nothing to do for a null driver
+
+[NullInstall.nt.Services]
+; null driver has no service and no service name
+AddService=, 0x00000002
+
+
 ;------------------------------------------------------------------------------
 ;  Vista-64bit Sections
 ;------------------------------------------------------------------------------
@@ -73,6 +81,13 @@ StartType=3
 ErrorControl=1
 ServiceBinary=%12%\%DRIVERFILENAME%.sys
 
+[NullInstall.NTamd64]
+; nothing to do for a null driver
+
+[NullInstall.NTamd64.Services]
+; null driver has no service and no service name
+AddService=, 0x00000002
+
 
 ;------------------------------------------------------------------------------
 ;  Vendor and Product ID Definitions
@@ -87,14 +102,14 @@ ServiceBinary=%12%\%DRIVERFILENAME%.sys
 [SourceDisksNames]
 [DeviceList]
 "%DESCRIPTION% UF2 Bootloader (0018:00) BSP"=DriverInstall, USB\VID_239A&PID_0018&MI_00
-"%DESCRIPTION% UF2 WebUSB dummy (0018:04) BSP"=DriverInstall, USB\VID_239A&PID_0018&MI_00
+"%DESCRIPTION% UF2 WebUSB dummy (0018:04) BSP"=NullInstall, USB\VID_239A&PID_0018&MI_04
 "%DESCRIPTION% (0019:00) BSP"=DriverInstall, USB\VID_239A&PID_0019&MI_00
 "%DESCRIPTION% Arduino (8018:00) BSP"=DriverInstall, USB\VID_239A&PID_8018&MI_00
 "%DESCRIPTION% CircuitPython (8019:00) BSP"=DriverInstall, USB\VID_239A&PID_8019&MI_00
 
 [DeviceList.NTamd64]
 "%DESCRIPTION% UF2 Bootloader (0018:00) BSP"=DriverInstall, USB\VID_239A&PID_0018&MI_00
-"%DESCRIPTION% UF2 WebUSB dummy (0018:04) BSP"=DriverInstall, USB\VID_239A&PID_0018&MI_00
+"%DESCRIPTION% UF2 WebUSB dummy (0018:04) BSP"=NullInstall, USB\VID_239A&PID_0018&MI_04
 "%DESCRIPTION% (0019:00) BSP"=DriverInstall, USB\VID_239A&PID_0019&MI_00
 "%DESCRIPTION% Arduino (8018:00) BSP"=DriverInstall, USB\VID_239A&PID_8018&MI_00
 "%DESCRIPTION% CircuitPython (8019:00) BSP"=DriverInstall, USB\VID_239A&PID_8019&MI_00
diff --git a/extras/build_all.py b/extras/build_all.py
new file mode 100644
index 000000000..4e701ace9
--- /dev/null
+++ b/extras/build_all.py
@@ -0,0 +1,124 @@
+import os
+import glob
+import sys
+import subprocess
+import time
+import argparse
+
+FQBN_PREFIX='adafruit:samd:adafruit_'
+
+
+parser = argparse.ArgumentParser(
+    description='python wrapper for adafruit arduino CI workflows',
+    allow_abbrev=False
+    )
+parser.add_argument(
+    '--all_warnings', '--Wall',
+    action='store_true',
+    help='build with all warnings enabled (`--warnings all`)',
+    )
+parser.add_argument(
+    '--warnings_do_not_cause_job_failure',
+    action='store_true',
+    help='failed builds will be listed as failed, but not cause job to exit with an error status',
+    )
+parser.add_argument(
+    'build_boards',
+    metavar='board',
+    nargs='*',
+    help='list of boards to be built -- Note that the fqbn is created by prepending "{}"'.format(FQBN_PREFIX),
+    default= [ 'metro_m0', 'metro_m4', 'circuitplayground_m0' ]
+    )
+args = parser.parse_args()
+
+exit_status = 0
+success_count = 0
+fail_count = 0
+skip_count = 0
+build_format = '| {:22} | {:30} | {:9} '
+build_separator = '-' * 80
+
+def errorOutputFilter(line: str):
+    if len(line) == 0:
+        return False
+    if line.isspace(): # Note: empty string does not match here!
+        return False
+    # TODO: additional items to remove?
+    return True
+
+def build_examples(variant: str):
+    global args, exit_status, success_count, fail_count, skip_count, build_format, build_separator
+
+    print('\n')
+    print(build_separator)
+    print('| {:^76} |'.format('Board ' + variant))
+    print(build_separator)
+    print((build_format + '| {:6} |').format('Library', 'Example', 'Result', 'Time'))
+    print(build_separator)
+    
+    fqbn = "{}{}".format(FQBN_PREFIX, variant)
+
+    for sketch in glob.iglob('libraries/**/*.ino', recursive=True):
+        start_time = time.monotonic()
+
+        # Skip if contains: ".board.test.skip" or ".all.test.skip"
+        # Skip if not contains: ".board.test.only" for a specific board
+        sketchdir = os.path.dirname(sketch)
+        if os.path.exists(sketchdir + '/.all.test.skip') or os.path.exists(sketchdir + '/.' + variant + '.test.skip'):
+            success = "\033[33mskipped\033[0m  "
+        elif glob.glob(sketchdir+"/.*.test.only") and not os.path.exists(sketchdir + '/.build.' + variant):
+            success = "\033[33mskipped\033[0m  "
+        else:
+            # TODO - preferably, would have STDERR show up in **both** STDOUT and STDERR.
+            #        preferably, would use Python logging handler to get both distinct outputs and one merged output
+            #        for now, split STDERR when building with all warnings enabled, so can detect warning/error output.
+            if args.all_warnings:
+                build_result = subprocess.run("arduino-cli compile --warnings all --fqbn {} {}".format(fqbn, sketch), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+            else:
+                build_result = subprocess.run("arduino-cli compile --warnings default --fqbn {} {}".format(fqbn, sketch), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+
+            # get stderr into a form where len(warningLines) indicates a true warning was output to stderr
+            warningLines = [];
+            if args.all_warnings and build_result.stderr:
+                tmpWarningLines = build_result.stderr.decode("utf-8").splitlines()
+                warningLines = list(filter(errorOutputFilter, (tmpWarningLines)))
+
+            if build_result.returncode != 0:
+                exit_status = build_result.returncode
+                success = "\033[31mfailed\033[0m   "
+                fail_count += 1
+            elif len(warningLines) != 0:
+                if not args.warnings_do_not_cause_job_failure:
+                    exit_status = -1
+                success = "\033[31mwarnings\033[0m "
+                fail_count += 1
+            else:
+                success = "\033[32msucceeded\033[0m"
+                success_count += 1
+
+        build_duration = time.monotonic() - start_time
+
+        print((build_format + '| {:5.2f}s |').format(sketch.split(os.path.sep)[1], os.path.basename(sketch), success, build_duration))
+
+        if success != "\033[33mskipped\033[0m  ":
+            if build_result.returncode != 0:
+                print(build_result.stdout.decode("utf-8"))
+                if (build_result.stderr):
+                    print(build_result.stderr.decode("utf-8"))
+            if len(warningLines) != 0:
+                for line in warningLines:
+                    print(line)
+        else:
+            skip_count += 1
+
+build_time = time.monotonic()
+
+for board in args.build_boards:
+    build_examples(board)
+
+print(build_separator)
+build_time = time.monotonic() - build_time
+print("Build Summary: {} \033[32msucceeded\033[0m, {} \033[31mfailed\033[0m, {} \033[33mskipped\033[0m and took {:.2f}s".format(success_count, fail_count, skip_count, build_time))
+print(build_separator)
+
+sys.exit(exit_status)
diff --git a/libraries/Adafruit_ZeroDMA/Adafruit_ZeroDMA.cpp b/libraries/Adafruit_ZeroDMA/Adafruit_ZeroDMA.cpp
new file mode 100644
index 000000000..0adb78470
--- /dev/null
+++ b/libraries/Adafruit_ZeroDMA/Adafruit_ZeroDMA.cpp
@@ -0,0 +1,654 @@
+#include <Adafruit_ZeroDMA.h>
+#include <malloc.h> // memalign() function
+
+#include "utility/dma.h"
+static volatile uint32_t _channelMask = 0; // Bitmask of allocated channels
+
+// DMA descriptor list entry point (and writeback buffer) per channel
+__attribute__((__aligned__(16))) static DmacDescriptor // 128 bit alignment
+  _descriptor[DMAC_CH_NUM] SECTION_DMAC_DESCRIPTOR,
+  _writeback[DMAC_CH_NUM]  SECTION_DMAC_DESCRIPTOR;
+
+// Pointer to ZeroDMA object for each channel is needed for the
+// ISR (in C, outside of class context) to access callbacks.
+static Adafruit_ZeroDMA *_dmaPtr[DMAC_CH_NUM] = { 0 }; // Init to NULL
+
+// Adapted from ASF3 interrupt_sam_nvic.c:
+
+static volatile unsigned long cpu_irq_critical_section_counter = 0;
+static volatile unsigned char cpu_irq_prev_interrupt_state     = 0;
+
+static void cpu_irq_enter_critical(void) {
+    if(!cpu_irq_critical_section_counter) {
+        if(__get_PRIMASK() == 0) { // IRQ enabled?
+            __disable_irq();   // Disable it
+            __DMB();
+            cpu_irq_prev_interrupt_state = 1;
+        } else {
+            // Make sure the to save the prev state as false
+            cpu_irq_prev_interrupt_state = 0;
+        }
+    }
+
+    cpu_irq_critical_section_counter++;
+}
+
+static void cpu_irq_leave_critical(void) {
+    // Check if the user is trying to leave a critical section
+    // when not in a critical section
+    if(cpu_irq_critical_section_counter > 0) {
+        cpu_irq_critical_section_counter--;
+
+        // Only enable global interrupts when the counter
+        // reaches 0 and the state of the global interrupt flag
+        // was enabled when entering critical state */
+        if((!cpu_irq_critical_section_counter) &&
+            cpu_irq_prev_interrupt_state) {
+                __DMB();
+                __enable_irq();
+        }
+    }
+}
+
+// CONSTRUCTOR -------------------------------------------------------------
+
+// Constructor initializes Adafruit_ZeroDMA basics but does NOT allocate a
+// DMA channel (that's done in allocate()) or start a job (that's done in
+// startJob()).  This is because constructors in a global context are called
+// before a sketch's setup() function, which may have some other hardware
+// initialization of its own, don't want it clobbering us.
+Adafruit_ZeroDMA::Adafruit_ZeroDMA(void) {
+    channel           = 0xFF;  // Channel not yet allocated
+    jobStatus         = DMA_STATUS_OK;
+    hasDescriptors    = false; // No descriptors allocated yet
+    loopFlag          = false;
+    peripheralTrigger = 0;     // Software trigger only by default
+    triggerAction     = DMA_TRIGGER_ACTON_TRANSACTION;
+    memset(callback, 0, sizeof(callback));
+}
+
+// TODO: add destructor? Should stop job, delete descriptors, free channel.
+
+// INTERRUPT SERVICE ROUTINE -----------------------------------------------
+
+// This is a C function that exists outside the Adafruit_ZeroDMA context.
+// DMA channel number is determined from the INTPEND register, from this
+// we get a ZeroDMA object pointer through the _dmaPtr[] array.
+// (It's done this way because jobStatus and callback[] are protected
+// elements in the ZeroDMA object -- we can't touch them in C, but the
+// next function after this, being part of the ZeroDMA class, can.)
+
+#ifdef __SAMD51__
+void DMAC_0_Handler(void) {
+#else
+void DMAC_Handler(void) {
+#endif
+    cpu_irq_enter_critical();
+
+    uint8_t channel = DMAC->INTPEND.bit.ID; // Channel # causing interrupt
+    if(channel < DMAC_CH_NUM) {
+        Adafruit_ZeroDMA *dma;
+        if((dma = _dmaPtr[channel])) { // -> Channel's ZeroDMA object
+#ifdef __SAMD51__
+            // Call IRQ handler with channel #
+            dma->_IRQhandler(channel);
+#else
+            DMAC->CHID.bit.ID = channel;
+            // Call IRQ handler with interrupt flag(s)
+            dma->_IRQhandler(DMAC->CHINTFLAG.reg);
+#endif
+        }
+    }
+
+    cpu_irq_leave_critical();
+}
+
+#ifdef __SAMD51__
+void DMAC_1_Handler(void) __attribute__((weak, alias("DMAC_0_Handler")));
+void DMAC_2_Handler(void) __attribute__((weak, alias("DMAC_0_Handler")));
+void DMAC_3_Handler(void) __attribute__((weak, alias("DMAC_0_Handler")));
+void DMAC_4_Handler(void) __attribute__((weak, alias("DMAC_0_Handler")));
+#endif
+
+void Adafruit_ZeroDMA::_IRQhandler(uint8_t flags) {
+#ifdef __SAMD51__
+    // 'flags' is initially passed in as channel number,
+    // from which we look up the actual interrupt flags...
+    flags = DMAC->Channel[flags].CHINTFLAG.reg;
+#endif
+    if(flags & DMAC_CHINTENCLR_TERR) {
+        // Clear error flag
+#ifdef __SAMD51__
+        DMAC->Channel[channel].CHINTFLAG.reg = DMAC_CHINTENCLR_TERR;
+#else
+        DMAC->CHINTFLAG.reg = DMAC_CHINTENCLR_TERR;
+#endif
+        jobStatus           = DMA_STATUS_ERR_IO;
+        if(callback[DMA_CALLBACK_TRANSFER_ERROR]) {
+            callback[DMA_CALLBACK_TRANSFER_ERROR](this);
+        }
+    } else if(flags & DMAC_CHINTENCLR_TCMPL) {
+        // Clear transfer complete flag
+#ifdef __SAMD51__
+        DMAC->Channel[channel].CHINTFLAG.reg = DMAC_CHINTENCLR_TCMPL;
+#else
+        DMAC->CHINTFLAG.reg = DMAC_CHINTENCLR_TCMPL;
+#endif
+        jobStatus           = DMA_STATUS_OK;
+        if(callback[DMA_CALLBACK_TRANSFER_DONE]) {
+            callback[DMA_CALLBACK_TRANSFER_DONE](this);
+        }
+    } else if(flags & DMAC_CHINTENCLR_SUSP) {
+        // Clear channel suspend flag
+#ifdef __SAMD51__
+        DMAC->Channel[channel].CHINTFLAG.reg = DMAC_CHINTENCLR_SUSP;
+#else
+        DMAC->CHINTFLAG.reg = DMAC_CHINTENCLR_SUSP;
+#endif
+        jobStatus           = DMA_STATUS_SUSPEND;
+        if(callback[DMA_CALLBACK_CHANNEL_SUSPEND]) {
+            callback[DMA_CALLBACK_CHANNEL_SUSPEND](this);
+        }
+    }
+}
+
+// DMA CHANNEL FUNCTIONS ---------------------------------------------------
+
+// Allocates channel for ZeroDMA object
+ZeroDMAstatus Adafruit_ZeroDMA::allocate(void) {
+
+    if(channel < DMAC_CH_NUM) return DMA_STATUS_OK; // Already alloc'd!
+
+    // Find index of first free DMA channel.  As currently written,
+    // this "does not play well with others" as it assumes _channelMask
+    // is the final arbiter of channels in use (this is true only within
+    // this library -- but other DMA-driven code may have allocated its
+    // own channel(s) elsewhere, sometimes with an equally broken
+    // approach).  A possible alternate approach, I haven't tested this
+    // yet, might be to loop through each channel, set DMAC->CHID.bit.ID
+    // and then test whether CHCTRLA.bit.ENABLE is set?  But for now...
+    for(channel=0; (channel < DMAC_CH_NUM) &&
+      (_channelMask & (1 << channel)); channel++);
+    // Doesn't help that code later does a software reset of the DMA
+    // controller, which would blow out other DMA-using libraries
+    // anyway (or they're just as likely to blow out this one).
+    // I think it's just an all-or-nothing affair...use one library
+    // for DMA everything, never mix and match.
+
+    if(channel >= DMAC_CH_NUM) { // No free channel!
+        return DMA_STATUS_ERR_NOT_FOUND;
+    }
+
+    cpu_irq_enter_critical();
+
+    if(!_channelMask) { // No channels allocated yet; initialize DMA!
+#if (SAML21) || (SAML22) || (SAMC20) || (SAMC21)
+        PM->AHBMASK.bit.DMAC_       = 1;
+#elif defined(__SAMD51__)
+        MCLK->AHBMASK.bit.DMAC_     = 1; // Initialize DMA clocks
+#else
+        PM->AHBMASK.bit.DMAC_       = 1; // Initialize DMA clocks
+        PM->APBBMASK.bit.DMAC_      = 1;
+#endif
+        DMAC->CTRL.bit.DMAENABLE    = 0; // Disable DMA controller
+        DMAC->CTRL.bit.SWRST        = 1; // Perform software reset
+
+        // Initialize descriptor list addresses
+        DMAC->BASEADDR.bit.BASEADDR = (uint32_t)_descriptor;
+        DMAC->WRBADDR.bit.WRBADDR   = (uint32_t)_writeback;
+        memset(_descriptor, 0, sizeof(_descriptor));
+        memset(_writeback , 0, sizeof(_writeback));
+
+        // Re-enable DMA controller with all priority levels
+        DMAC->CTRL.reg = DMAC_CTRL_DMAENABLE | DMAC_CTRL_LVLEN(0xF);
+
+        // Enable DMA interrupt at lowest priority
+#ifdef __SAMD51__
+        IRQn_Type irqs[] = { DMAC_0_IRQn, DMAC_1_IRQn, DMAC_2_IRQn,
+                             DMAC_3_IRQn, DMAC_4_IRQn };
+        for(uint8_t i=0; i<(sizeof irqs / sizeof irqs[0]); i++) {
+            NVIC_EnableIRQ(irqs[i]);
+            NVIC_SetPriority(irqs[i], (1<<__NVIC_PRIO_BITS)-1);
+        }
+#else
+        NVIC_EnableIRQ(DMAC_IRQn);
+        NVIC_SetPriority(DMAC_IRQn, (1 << __NVIC_PRIO_BITS) - 1);
+#endif
+    }
+
+    _channelMask    |= 1 << channel; // Mark channel as allocated
+    _dmaPtr[channel] = this;         // Channel-index-to-object pointer
+
+    // Reset the allocated channel
+#ifdef __SAMD51__
+    DMAC->Channel[channel].CHCTRLA.bit.ENABLE  = 0;
+    DMAC->Channel[channel].CHCTRLA.bit.SWRST   = 1;
+#else
+    DMAC->CHID.bit.ID         = channel;
+    DMAC->CHCTRLA.bit.ENABLE  = 0;
+    DMAC->CHCTRLA.bit.SWRST   = 1;
+#endif
+
+    // Clear software trigger
+    DMAC->SWTRIGCTRL.reg     &= ~(1 << channel);
+
+    // Configure default behaviors
+#ifdef __SAMD51__
+    DMAC->Channel[channel].CHPRILVL.bit.PRILVL = 0;
+    DMAC->Channel[channel].CHCTRLA.bit.TRIGSRC = peripheralTrigger;
+    DMAC->Channel[channel].CHCTRLA.bit.TRIGACT = triggerAction;
+    DMAC->Channel[channel].CHCTRLA.bit.BURSTLEN =
+      DMAC_CHCTRLA_BURSTLEN_SINGLE_Val; // Single-beat burst length
+#else
+    DMAC->CHCTRLB.bit.LVL     = 0;
+    DMAC->CHCTRLB.bit.TRIGSRC = peripheralTrigger;
+    DMAC->CHCTRLB.bit.TRIGACT = triggerAction;
+#endif
+
+    cpu_irq_leave_critical();
+
+    return DMA_STATUS_OK;
+}
+
+void Adafruit_ZeroDMA::setPriority(dma_priority pri) const {
+#ifdef __SAMD51__
+    DMAC->Channel[channel].CHPRILVL.bit.PRILVL = pri;
+#else
+    DMAC->CHCTRLB.bit.LVL = pri;
+#endif
+}
+
+// Deallocate DMA channel
+// TODO: should this delete/deallocate the descriptor list?
+ZeroDMAstatus Adafruit_ZeroDMA::free(void) {
+
+    ZeroDMAstatus status = DMA_STATUS_OK;
+
+    cpu_irq_enter_critical(); // jobStatus is volatile
+
+    if(jobStatus == DMA_STATUS_BUSY) {
+        status = DMA_STATUS_BUSY; // Can't leave when busy
+    } else if((channel < DMAC_CH_NUM) && (_channelMask & (1 << channel))) {
+        // Valid in-use channel; release it
+        _channelMask &= ~(1 << channel); // Clear bit
+        if(!_channelMask) {              // No more channels in use?
+#ifdef __SAMD51__
+            NVIC_DisableIRQ(DMAC_0_IRQn); // Disable DMA interrupt
+            DMAC->CTRL.bit.DMAENABLE = 0; // Disable DMA
+            MCLK->AHBMASK.bit.DMAC_  = 0; // Disable DMA clock
+#else
+            NVIC_DisableIRQ(DMAC_IRQn);   // Disable DMA interrupt
+            DMAC->CTRL.bit.DMAENABLE = 0; // Disable DMA
+            PM->APBBMASK.bit.DMAC_   = 0; // Disable DMA clocks
+            PM->AHBMASK.bit.DMAC_    = 0;
+#endif
+        }
+        _dmaPtr[channel] = NULL;
+        channel          = 0xFF;
+    } else {
+        status = DMA_STATUS_ERR_NOT_INITIALIZED; // Channel not in use
+    }
+
+    cpu_irq_leave_critical();
+
+    return status;
+}
+
+// Start DMA transfer job.  Channel and descriptors should be allocated
+// before calling this.
+ZeroDMAstatus Adafruit_ZeroDMA::startJob(void) {
+    ZeroDMAstatus status = DMA_STATUS_OK;
+
+    cpu_irq_enter_critical(); // Job status is volatile
+
+    if(jobStatus == DMA_STATUS_BUSY) {
+        status = DMA_STATUS_BUSY; // Resource is busy
+    } else if(channel >= DMAC_CH_NUM) {
+        status = DMA_STATUS_ERR_NOT_INITIALIZED; // Channel not in use
+    } else if(!hasDescriptors || (_descriptor[channel].BTCNT.reg <= 0)) {
+        status = DMA_STATUS_ERR_INVALID_ARG; // Bad transfer size
+    } else {
+        uint8_t i, interruptMask = 0;
+        for(i=0; i<DMA_CALLBACK_N; i++) {
+            if(callback[i]) interruptMask |= (1 << i);
+        }
+        jobStatus            = DMA_STATUS_BUSY;
+#ifdef __SAMD51__
+        DMAC->Channel[channel].CHINTENSET.reg =
+          DMAC_CHINTENSET_MASK &  interruptMask;
+        DMAC->Channel[channel].CHINTENCLR.reg =
+          DMAC_CHINTENCLR_MASK & ~interruptMask;
+        DMAC->Channel[channel].CHCTRLA.bit.ENABLE = 1;
+#else
+        DMAC->CHID.bit.ID    = channel;
+        DMAC->CHINTENSET.reg = DMAC_CHINTENSET_MASK &  interruptMask;
+        DMAC->CHINTENCLR.reg = DMAC_CHINTENCLR_MASK & ~interruptMask;
+        DMAC->CHCTRLA.bit.ENABLE = 1; // Enable the transfer channel
+#endif
+    }
+
+    cpu_irq_leave_critical();
+
+    return status;
+}
+
+// Set and enable callback function for ZeroDMA object. This can be called
+// before or after channel and/or descriptors are allocated, but needs
+// to be called before job is started.
+void Adafruit_ZeroDMA::setCallback(
+  void (*cb)(Adafruit_ZeroDMA *), dma_callback_type type) {
+    callback[type] = cb;
+}
+
+// Suspend/resume don't quite do what I thought -- avoid using for now.
+void Adafruit_ZeroDMA::suspend(void) const {
+    cpu_irq_enter_critical();
+#ifdef __SAMD51__
+    DMAC->Channel[channel].CHCTRLB.reg |= DMAC_CHCTRLB_CMD_SUSPEND;
+#else
+    DMAC->CHID.bit.ID  = channel;
+    DMAC->CHCTRLB.reg |= DMAC_CHCTRLB_CMD_SUSPEND;
+#endif
+    cpu_irq_leave_critical();
+}
+
+#define MAX_JOB_RESUME_COUNT 10000
+void Adafruit_ZeroDMA::resume(void) {
+    cpu_irq_enter_critical(); // jobStatus is volatile
+    if(jobStatus == DMA_STATUS_SUSPEND) {
+        int      count;
+        uint32_t bitMask   = 1 << channel;
+#ifdef __SAMD51__
+        DMAC->Channel[channel].CHCTRLB.reg |= DMAC_CHCTRLB_CMD_RESUME;
+#else
+        DMAC->CHID.bit.ID  = channel;
+        DMAC->CHCTRLB.reg |= DMAC_CHCTRLB_CMD_RESUME;
+#endif
+
+        for(count = 0; (count < MAX_JOB_RESUME_COUNT) &&
+          !(DMAC->BUSYCH.reg & bitMask); count++);
+
+        jobStatus = (count < MAX_JOB_RESUME_COUNT) ?
+          DMA_STATUS_BUSY : DMA_STATUS_ERR_TIMEOUT;
+    }
+    cpu_irq_leave_critical();
+}
+
+// Abort is OK though.
+void Adafruit_ZeroDMA::abort(void) {
+    if(channel <= DMAC_CH_NUM) {
+        cpu_irq_enter_critical();
+#ifdef __SAMD51__
+        DMAC->Channel[channel].CHCTRLA.reg = 0; // Disable channel
+#else
+        DMAC->CHID.bit.ID = channel; // Select channel
+        DMAC->CHCTRLA.reg = 0;       // Disable
+#endif
+        jobStatus         = DMA_STATUS_ABORTED;
+        cpu_irq_leave_critical();
+    }
+}
+
+// Set DMA peripheral trigger.
+// This can be done before or after channel is allocated.
+void Adafruit_ZeroDMA::setTrigger(uint8_t trigger) {
+    peripheralTrigger = trigger; // Save value for allocate()
+
+    // If channel already allocated, configure peripheral trigger
+    // (old lib required configure before alloc -- either way OK now)
+    if(channel < DMAC_CH_NUM) {
+        cpu_irq_enter_critical();
+#ifdef __SAMD51__
+        DMAC->Channel[channel].CHCTRLA.bit.TRIGSRC = trigger;
+#else
+        DMAC->CHID.bit.ID         = channel;
+        DMAC->CHCTRLB.bit.TRIGSRC = trigger;
+#endif
+        cpu_irq_leave_critical();
+    }
+}
+
+// Set DMA trigger action.
+// This can be done before or after channel is allocated.
+void Adafruit_ZeroDMA::setAction(dma_transfer_trigger_action action) {
+    triggerAction = action; // Save value for allocate()
+
+    // If channel already allocated, configure trigger action
+    // (old lib required configure before alloc -- either way OK now)
+    if(channel < DMAC_CH_NUM) {
+        cpu_irq_enter_critical();
+#ifdef __SAMD51__
+        DMAC->Channel[channel].CHCTRLA.bit.TRIGACT = action;
+#else
+        DMAC->CHID.bit.ID         = channel;
+        DMAC->CHCTRLB.bit.TRIGACT = action;
+#endif
+        cpu_irq_leave_critical();
+    }
+}
+
+// Issue software trigger. Channel must be allocated & descriptors added!
+void Adafruit_ZeroDMA::trigger(void) const {
+    if((channel <= DMAC_CH_NUM) & hasDescriptors) {
+        DMAC->SWTRIGCTRL.reg |= (1 << channel);
+    }
+}
+
+// Returns true if DMA transfer in progress.
+bool Adafruit_ZeroDMA::isActive(void) const {
+    return _writeback[channel].BTCTRL.bit.VALID;
+}
+
+// DMA DESCRIPTOR FUNCTIONS ------------------------------------------------
+
+// Allocates a new DMA descriptor (if needed) and appends it to the
+// channel's descriptor list.  Returns pointer to DmacDescriptor,
+// or NULL on various errors.  You'll want to keep the pointer for
+// later if you need to modify or free the descriptor.
+// Channel must be allocated first!
+DmacDescriptor *Adafruit_ZeroDMA::addDescriptor(
+  void           *src,
+  void           *dst,
+  uint32_t        count,
+  dma_beat_size   size,
+  bool            srcInc,
+  bool            dstInc,
+  uint32_t        stepSize,
+  bool            stepSel) {
+
+    // Channel must be allocated first
+       if(channel >= DMAC_CH_NUM) return NULL;
+
+    // Can't do while job's busy
+    if(jobStatus == DMA_STATUS_BUSY) return NULL;
+
+    DmacDescriptor *desc;
+
+    // Scan descriptor list to find last entry.  If an entry's
+    // DESCADDR value is 0, that's the end of the list and it's
+    // currently un-looped.  If the DESCADDR value is the same
+    // as the first entry, that's the end of the list and it's
+    // looped.  Either way, set the last entry's DESCADDR value
+    // to the new descriptor, and the descriptor's own DESCADDR
+    // will be set later either to 0 or the list head.
+    if(hasDescriptors) {
+        // DMA descriptors must be 128-bit (16 byte) aligned.
+        // memalign() is considered 'obsolete' but it's replacements
+        // (aligned_alloc() or posix_memalign()) are not currently
+        // available in the version of ARM GCC in use, but this is,
+        // so here we are.
+        if(!(desc = (DmacDescriptor *)memalign(16, sizeof(DmacDescriptor)))) {
+            return NULL;
+        }
+        DmacDescriptor *prev = &_descriptor[channel];
+        while(prev->DESCADDR.reg &&
+             (prev->DESCADDR.reg != (uint32_t)&_descriptor[channel])) {
+            prev = (DmacDescriptor *)prev->DESCADDR.reg;
+        }
+        prev->DESCADDR.reg = (uint32_t)desc;
+    } else {
+        desc = &_descriptor[channel];
+    }
+    hasDescriptors = true;
+
+    uint8_t bytesPerBeat; // Beat transfer size IN BYTES
+    switch(size) {
+       default:                  bytesPerBeat = 1; break;
+       case DMA_BEAT_SIZE_HWORD: bytesPerBeat = 2; break;
+       case DMA_BEAT_SIZE_WORD:  bytesPerBeat = 4; break;
+    }
+
+    desc->BTCTRL.bit.VALID     = true;
+    desc->BTCTRL.bit.EVOSEL    = DMA_EVENT_OUTPUT_DISABLE;
+    desc->BTCTRL.bit.BLOCKACT  = DMA_BLOCK_ACTION_NOACT;
+    desc->BTCTRL.bit.BEATSIZE  = size;
+    desc->BTCTRL.bit.SRCINC    = srcInc;
+    desc->BTCTRL.bit.DSTINC    = dstInc;
+    desc->BTCTRL.bit.STEPSEL   = stepSel;
+    desc->BTCTRL.bit.STEPSIZE  = stepSize;
+    desc->BTCNT.reg            = count;
+    desc->SRCADDR.reg          = (uint32_t)src;
+
+    if(srcInc) {
+        if(stepSel) {
+            desc->SRCADDR.reg += bytesPerBeat * count * (1 << stepSize);
+        } else {
+            desc->SRCADDR.reg += bytesPerBeat * count;
+        }
+    }
+
+    desc->DSTADDR.reg          = (uint32_t)dst;
+
+    if(dstInc) {
+        if(!stepSel) {
+            desc->DSTADDR.reg += bytesPerBeat * count * (1 << stepSize);
+        } else {
+            desc->DSTADDR.reg += bytesPerBeat * count;
+        }
+    }
+
+    desc->DESCADDR.reg = loopFlag ? (uint32_t)&_descriptor[channel] : 0;
+
+    return desc;
+}
+
+// Modify DMA descriptor with a new source address, destination address &
+// block transfer count.  All other attributes (including increment enables,
+// etc.) are unchanged.  Mostly for changing the data being pushed to a
+// peripheral (DAC, SPI, whatev.)
+void Adafruit_ZeroDMA::changeDescriptor(DmacDescriptor *desc,
+  void *src, void *dst, uint32_t count) {
+
+    uint8_t bytesPerBeat; // Beat transfer size IN BYTES
+    switch(desc->BTCTRL.bit.BEATSIZE) {
+       default:                  bytesPerBeat = 1; break;
+       case DMA_BEAT_SIZE_HWORD: bytesPerBeat = 2; break;
+       case DMA_BEAT_SIZE_WORD:  bytesPerBeat = 4; break;
+    }
+
+    if(count) desc->BTCNT.reg = count;
+
+    if(src) {
+        desc->SRCADDR.reg = (uint32_t)src;
+        if(desc->BTCTRL.bit.SRCINC) {
+            if(desc->BTCTRL.bit.STEPSEL) {
+                desc->SRCADDR.reg += desc->BTCNT.reg *
+                  bytesPerBeat * (1 << desc->BTCTRL.bit.STEPSIZE);
+            } else {
+                desc->SRCADDR.reg += desc->BTCNT.reg * bytesPerBeat;
+            }
+        }
+    }
+
+    if(dst) {
+        desc->DSTADDR.reg = (uint32_t)dst;
+        if(desc->BTCTRL.bit.DSTINC) {
+            if(!desc->BTCTRL.bit.STEPSEL) {
+                desc->DSTADDR.reg += desc->BTCNT.reg *
+                  bytesPerBeat * (1 << desc->BTCTRL.bit.STEPSIZE);
+            } else {
+                desc->DSTADDR.reg += desc->BTCNT.reg * bytesPerBeat;
+            }
+        }
+    }
+
+// I think this code is here by accident -- disabling for now.
+#if 0
+    cpu_irq_enter_critical();
+    jobStatus          = DMA_STATUS_OK;
+#ifdef __SAMD51__
+    DMAC->Channel[channel].CHCTRLA.bit.ENABLE = 1;
+#else
+    DMAC->CHID.bit.ID  = channel;
+    DMAC->CHCTRLA.reg |= DMAC_CHCTRLA_ENABLE;
+#endif
+    cpu_irq_leave_critical();
+#endif
+}
+
+// TODO: delete descriptor, delete whole descriptor chain
+
+// Select whether channel's descriptor list should repeat or not.
+// This can be done before or after channel & any descriptors are allocated.
+void Adafruit_ZeroDMA::loop(boolean flag) {
+    // The loop selection is 'sticky' -- that is, you can enable or
+    // disable looping before a descriptor list is built, or after
+    // the fact.  This requires some extra steps in the library code
+    // but avoids a must-do-in-X-order constraint on user.
+    loopFlag = flag;
+
+    if(hasDescriptors) { // Descriptor list already started?
+        // Scan descriptor list to find last entry.  If an entry's
+        // DESCADDR value is 0, that's the end of the list and it's
+        // currently un-looped.  If the DESCADDR value is the same
+        // as the first entry, that's the end of the list and it's
+        // already looped.
+        DmacDescriptor *desc = &_descriptor[channel];
+        while(desc->DESCADDR.reg &&
+          (desc->DESCADDR.reg != (uint32_t)&_descriptor[channel])) {
+            desc = (DmacDescriptor *)desc->DESCADDR.reg;
+        }
+        // Loop or unloop descriptor list as appropriate
+        desc->DESCADDR.reg = loopFlag ?  (uint32_t)&_descriptor[channel] : 0;
+    }
+}
+
+// MISCELLANY --------------------------------------------------------------
+
+void Adafruit_ZeroDMA::printStatus(ZeroDMAstatus s) const {
+    if(s == DMA_STATUS_JOBSTATUS) s = jobStatus;
+    Serial.print("Status: ");
+    switch(s) {
+       case DMA_STATUS_OK:
+            Serial.println("OK");
+            break;
+       case DMA_STATUS_ERR_NOT_FOUND:
+            Serial.println("NOT FOUND");
+            break;
+       case DMA_STATUS_ERR_NOT_INITIALIZED:
+            Serial.println("NOT INITIALIZED");
+            break;
+       case DMA_STATUS_ERR_INVALID_ARG:
+            Serial.println("INVALID ARGUMENT");
+            break;
+       case DMA_STATUS_ERR_IO:
+            Serial.println("IO ERROR");
+            break;
+       case DMA_STATUS_ERR_TIMEOUT:
+            Serial.println("TIMEOUT");
+            break;
+       case DMA_STATUS_BUSY:
+            Serial.println("BUSY");
+            break;
+       case DMA_STATUS_SUSPEND:
+            Serial.println("SUSPENDED");
+            break;
+       case DMA_STATUS_ABORTED:
+            Serial.println("ABORTED");
+            break;
+       default:
+            Serial.print("Unknown 0x");
+            Serial.println((int)s);
+            break;
+    }
+}
diff --git a/libraries/Adafruit_ZeroDMA/Adafruit_ZeroDMA.h b/libraries/Adafruit_ZeroDMA/Adafruit_ZeroDMA.h
new file mode 100644
index 000000000..fc8461993
--- /dev/null
+++ b/libraries/Adafruit_ZeroDMA/Adafruit_ZeroDMA.h
@@ -0,0 +1,66 @@
+#ifndef _ADAFRUIT_ZERODMA_H_
+#define _ADAFRUIT_ZERODMA_H_
+
+#include "Arduino.h"
+#include "utility/dma.h"
+
+// Status codes returned by some DMA functions and/or held in
+// a channel's jobStatus variable.
+enum ZeroDMAstatus {
+    DMA_STATUS_OK = 0,
+    DMA_STATUS_ERR_NOT_FOUND,
+    DMA_STATUS_ERR_NOT_INITIALIZED,
+    DMA_STATUS_ERR_INVALID_ARG,
+    DMA_STATUS_ERR_IO,
+    DMA_STATUS_ERR_TIMEOUT,
+    DMA_STATUS_BUSY,
+    DMA_STATUS_SUSPEND,
+    DMA_STATUS_ABORTED,
+    DMA_STATUS_JOBSTATUS = -1 // For printStatus() function
+};
+
+class Adafruit_ZeroDMA {
+ public:
+  Adafruit_ZeroDMA(void);
+
+  // DMA channel functions
+  ZeroDMAstatus   allocate(void), // Allocates DMA channel
+                  startJob(void),
+                  free(void);     // Deallocates DMA channel
+  void            trigger(void) const,
+                  setTrigger(uint8_t trigger),
+                  setAction(dma_transfer_trigger_action action),
+                  setCallback(void (*callback)(Adafruit_ZeroDMA *) = NULL,
+                    dma_callback_type type = DMA_CALLBACK_TRANSFER_DONE),
+                  loop(boolean flag),
+                  suspend(void) const,
+                  resume(void),
+                  abort(void),
+                  setPriority(dma_priority pri) const,
+                  printStatus(ZeroDMAstatus s = DMA_STATUS_JOBSTATUS) const;
+  uint8_t         getChannel(void) const { return channel; }
+
+  // DMA descriptor functions
+  DmacDescriptor *addDescriptor(void *src, void *dst, uint32_t count = 0,
+                    dma_beat_size size = DMA_BEAT_SIZE_BYTE,
+                    bool srcInc = true, bool dstInc = true, 
+                    uint32_t stepSize = DMA_ADDRESS_INCREMENT_STEP_SIZE_1, 
+                    bool stepSel = DMA_STEPSEL_DST);
+  void            changeDescriptor(DmacDescriptor *d, void *src = NULL,
+                    void *dst = NULL, uint32_t count = 0);
+  bool            isActive(void) const;
+
+  void            _IRQhandler(uint8_t flags); // DO NOT TOUCH
+
+
+ protected:  
+  uint8_t                     channel;
+  volatile enum ZeroDMAstatus jobStatus;
+  bool                        hasDescriptors;
+  bool                        loopFlag;
+  uint8_t                     peripheralTrigger;
+  dma_transfer_trigger_action triggerAction;
+  void                      (*callback[DMA_CALLBACK_N])(Adafruit_ZeroDMA *);
+};
+
+#endif // _ADAFRUIT_ZERODMA_H_
diff --git a/libraries/Adafruit_ZeroDMA/LICENSE b/libraries/Adafruit_ZeroDMA/LICENSE
new file mode 100644
index 000000000..ee356f7b7
--- /dev/null
+++ b/libraries/Adafruit_ZeroDMA/LICENSE
@@ -0,0 +1,22 @@
+The MIT License (MIT)
+
+Copyright (c) 2016 Adafruit Industries
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
diff --git a/libraries/Adafruit_ZeroDMA/README.md b/libraries/Adafruit_ZeroDMA/README.md
new file mode 100644
index 000000000..cbc5441cc
--- /dev/null
+++ b/libraries/Adafruit_ZeroDMA/README.md
@@ -0,0 +1,6 @@
+# Adafruit_ZeroDMA
+DMA helper/wrapped for ATSAMD21 such as Arduino Zero &amp; Feather M0
+
+Current version of this library no longer requires Adafruit_ASFcore as a prerequisite. However...IT BREAKS COMPATIBILITY WITH PRIOR VERSIONS. Function names, calling sequence and return types/values have changed. See examples!
+
+Item(s) in 'utility' directory are much pared-down derivatives of Atmel ASFcore 3 files. Please keep their original copyright and license intact when editing.
diff --git a/libraries/Adafruit_ZeroDMA/examples/zerodma_memcpy/zerodma_memcpy.ino b/libraries/Adafruit_ZeroDMA/examples/zerodma_memcpy/zerodma_memcpy.ino
new file mode 100644
index 000000000..5a48a6b56
--- /dev/null
+++ b/libraries/Adafruit_ZeroDMA/examples/zerodma_memcpy/zerodma_memcpy.ino
@@ -0,0 +1,95 @@
+// Simple ZeroDMA example -- an equivalent to the memcpy() function.
+// Decause it uses DMA, unlike memcpy(), your code could be doing other
+// things simultaneously while the copy operation runs.
+
+#include <Adafruit_ZeroDMA.h>
+#include "utility/dma.h"
+
+Adafruit_ZeroDMA myDMA;
+ZeroDMAstatus    stat; // DMA status codes returned by some functions
+
+// The memory we'll be moving:
+#define DATA_LENGTH 1024
+uint8_t source_memory[DATA_LENGTH],
+        destination_memory[DATA_LENGTH];
+
+volatile bool transfer_is_done = false; // Done yet?
+
+// Callback for end-of-DMA-transfer
+void dma_callback(Adafruit_ZeroDMA *dma) {
+  (void)dma; // avoid compiler warning about unused function parameter
+  transfer_is_done = true;
+}
+
+void setup() {
+  uint32_t t;
+  pinMode(LED_BUILTIN, OUTPUT);   // Onboard LED can be used for precise
+  digitalWrite(LED_BUILTIN, LOW); // benchmarking with an oscilloscope
+  Serial.begin(115200);
+  while(!Serial);                 // Wait for Serial monitor before continuing
+
+  Serial.println("DMA test: memory copy");
+
+  Serial.print("Allocating DMA channel...");
+  stat = myDMA.allocate();
+  myDMA.printStatus(stat);
+
+  Serial.println("Setting up transfer");
+  myDMA.addDescriptor(source_memory, destination_memory, DATA_LENGTH);
+
+  Serial.println("Adding callback");
+  // register_callback() can optionally take a second argument
+  // (callback type), default is DMA_CALLBACK_TRANSFER_DONE
+  myDMA.setCallback(dma_callback);
+
+  // Fill the source buffer with incrementing bytes, dest buf with 0's
+  for(uint32_t i=0; i<DATA_LENGTH; i++) source_memory[i] = i;
+  memset(destination_memory, 0, DATA_LENGTH);
+
+  // Show the destination buffer is empty before transfer
+  Serial.println("Destination buffer before transfer:");
+  dump();
+
+  Serial.println("Starting transfer job");
+  stat = myDMA.startJob();
+  myDMA.printStatus(stat);
+
+  Serial.println("Triggering DMA transfer...");
+  t = micros();
+  digitalWrite(LED_BUILTIN, HIGH);
+  myDMA.trigger();
+
+  // Your code could do other things here while copy happens!
+
+  while(!transfer_is_done); // Chill until DMA transfer completes
+
+  digitalWrite(LED_BUILTIN, LOW);
+  t = micros() - t; // Elapsed time
+
+  Serial.print("Done! ");
+  Serial.print(t);
+  Serial.println(" microseconds");
+
+  Serial.println("Destination buffer after transfer:");
+  dump();
+
+  // Now repeat the same operation, but 'manually' using memcpy() (not DMA):
+  t = micros();
+  digitalWrite(LED_BUILTIN, HIGH);
+  memcpy(destination_memory, source_memory,  DATA_LENGTH);
+  digitalWrite(LED_BUILTIN, LOW);
+  t = micros() - t; // Elapsed time
+  Serial.print("Same operation without DMA: ");
+  Serial.print(t);
+  Serial.println(" microseconds");
+}
+
+// Show contents of destination_memory[] array
+void dump() {
+  for(uint32_t i=0; i<DATA_LENGTH; i++) {
+    Serial.print(destination_memory[i], HEX); Serial.print(' ');
+    if ((i & 15) == 15) Serial.println();
+  }
+}
+
+void loop() { }
diff --git a/libraries/Adafruit_ZeroDMA/examples/zerodma_spi1/zerodma_spi1.ino b/libraries/Adafruit_ZeroDMA/examples/zerodma_spi1/zerodma_spi1.ino
new file mode 100644
index 000000000..ea29a25d1
--- /dev/null
+++ b/libraries/Adafruit_ZeroDMA/examples/zerodma_spi1/zerodma_spi1.ino
@@ -0,0 +1,98 @@
+// DMA-based SPI buffer write.  This is transmit-only as written, i.e.
+// not equivalent to Arduino's SPI.transfer() which both sends and
+// receives a single byte or word.  Also, this is single-buffered to
+// demonstrate a simple SPI write case.  See zerodma_spi2.ino for an
+// example using double buffering (2 buffers alternating fill & transmit).
+
+#include <SPI.h>
+#include <Adafruit_ZeroDMA.h>
+#include "utility/dma.h"
+
+Adafruit_ZeroDMA myDMA;
+ZeroDMAstatus    stat; // DMA status codes returned by some functions
+
+// The memory we'll be issuing to SPI:
+#define DATA_LENGTH 2048
+uint8_t source_memory[DATA_LENGTH];
+
+volatile bool transfer_is_done = false; // Done yet?
+
+// Callback for end-of-DMA-transfer
+void dma_callback(Adafruit_ZeroDMA *dma) {
+  (void)dma; // avoid compiler warning about unused parameter
+  transfer_is_done = true;
+}
+
+void setup() {
+  uint32_t t;
+  pinMode(LED_BUILTIN, OUTPUT);   // Onboard LED can be used for precise
+  digitalWrite(LED_BUILTIN, LOW); // benchmarking with an oscilloscope
+  Serial.begin(115200);
+  while(!Serial);                 // Wait for Serial monitor before continuing
+
+  Serial.println("DMA test: SPI data out");
+
+  SPI.begin();
+
+  Serial.println("Configuring DMA trigger");
+#ifdef __SAMD51__
+  // SERCOM2 is the 'native' SPI SERCOM on Metro M4
+  myDMA.setTrigger(SERCOM2_DMAC_ID_TX);
+#else
+  // SERCOM4 is the 'native' SPI SERCOM on most M0 boards
+  myDMA.setTrigger(SERCOM4_DMAC_ID_TX);
+#endif
+  myDMA.setAction(DMA_TRIGGER_ACTON_BEAT);
+
+  Serial.print("Allocating DMA channel...");
+  stat = myDMA.allocate();
+  myDMA.printStatus(stat);
+
+  Serial.println("Setting up transfer");
+  myDMA.addDescriptor(
+    source_memory,                    // move data from here
+#ifdef __SAMD51__
+    (void *)(&SERCOM2->SPI.DATA.reg), // to here (M4)
+#else
+    (void *)(&SERCOM4->SPI.DATA.reg), // to here (M0)
+#endif
+    DATA_LENGTH,                      // this many...
+    DMA_BEAT_SIZE_BYTE,               // bytes/hword/words
+    true,                             // increment source addr?
+    false);                           // increment dest addr?
+
+  Serial.println("Adding callback");
+  // register_callback() can optionally take a second argument
+  // (callback type), default is DMA_CALLBACK_TRANSFER_DONE
+  myDMA.setCallback(dma_callback);
+
+  // Fill the source buffer with incrementing bytes
+  for(uint32_t i=0; i<DATA_LENGTH; i++) source_memory[i] = i;
+
+  // Start SPI transaction at 12 MHz
+  SPI.beginTransaction(SPISettings(12000000, MSBFIRST, SPI_MODE0));
+
+  Serial.println("Starting transfer job");
+  t = micros();
+  digitalWrite(LED_BUILTIN, HIGH);
+
+  // Because we've configured a peripheral trigger (SPI), there's
+  // no need to manually trigger transfer, it starts up on its own.
+  stat = myDMA.startJob();
+
+  // Your code could do other things here while SPI write happens!
+
+  while(!transfer_is_done); // Chill until DMA transfer completes
+
+  digitalWrite(LED_BUILTIN, LOW);
+  t = micros() - t; // Elapsed time
+
+  SPI.endTransaction();
+  myDMA.printStatus(stat); // Results of start_transfer_job()
+
+  Serial.print("Done! ");
+  Serial.print(t);
+  Serial.println(" microseconds");
+}
+
+void loop() { }
diff --git a/libraries/Adafruit_ZeroDMA/examples/zerodma_spi2/zerodma_spi2.ino b/libraries/Adafruit_ZeroDMA/examples/zerodma_spi2/zerodma_spi2.ino
new file mode 100644
index 000000000..f33839283
--- /dev/null
+++ b/libraries/Adafruit_ZeroDMA/examples/zerodma_spi2/zerodma_spi2.ino
@@ -0,0 +1,104 @@
+// Double-buffered DMA on auxiliary SPI peripheral on pins 11/12/13.
+// Continuously alternates between two data buffers...one is filled
+// with new data as the other is being transmitted.
+
+#include <SPI.h>
+#include <Adafruit_ZeroDMA.h>
+#include "utility/dma.h"
+#include "wiring_private.h" // pinPeripheral() function
+
+// Declare our own SPI peripheral 'mySPI' on pins 11/12/13:
+// (Do not call this SPI1; Arduino Zero and Metro M0 already
+// have an SPI1 (the EDBG interface) and it won't compile.)
+SPIClass mySPI(
+  &sercom1,         // -> Sercom peripheral
+  34,               // MISO pin (also digital pin 12)
+  37,               // SCK pin  (also digital pin 13)
+  35,               // MOSI pin (also digital pin 11)
+  SPI_PAD_0_SCK_1,  // TX pad (MOSI, SCK pads)
+  SERCOM_RX_PAD_3); // RX pad (MISO pad)
+
+Adafruit_ZeroDMA myDMA;
+ZeroDMAstatus    stat; // DMA status codes returned by some functions
+
+// Data we'll issue to mySPI.  There are TWO buffers; one being
+// filled with new data while the other's being transmitted in
+// the background.
+#define DATA_LENGTH 512
+uint8_t source_memory[2][DATA_LENGTH],
+        buffer_being_filled = 0, // Index of 'filling' buffer
+        buffer_value        = 0; // Value of fill
+
+volatile bool transfer_is_done = true; // Done yet?
+
+// Callback for end-of-DMA-transfer
+void dma_callback(Adafruit_ZeroDMA *dma) {
+  (void)dma; // avoid compiler warning about unused parameter
+  transfer_is_done = true;
+}
+
+DmacDescriptor *desc; // DMA descriptor address (so we can change contents)
+
+void setup() {
+  Serial.begin(115200);
+  while(!Serial); // Wait for Serial monitor before continuing
+
+  Serial.println("DMA test: SPI data out");
+
+  mySPI.begin();
+  // Assign pins 11, 12, 13 to SERCOM functionality
+  pinPeripheral(11, PIO_SERCOM);
+  pinPeripheral(12, PIO_SERCOM);
+  pinPeripheral(13, PIO_SERCOM);
+
+  // Configure DMA for SERCOM1 (our 'mySPI' port on 11/12/13)
+  Serial.println("Configuring DMA trigger");
+  myDMA.setTrigger(SERCOM1_DMAC_ID_TX);
+  myDMA.setAction(DMA_TRIGGER_ACTON_BEAT);
+
+  Serial.print("Allocating DMA channel...");
+  stat = myDMA.allocate();
+  myDMA.printStatus(stat);
+
+  desc = myDMA.addDescriptor(
+    source_memory[buffer_being_filled], // move data from here
+    (void *)(&SERCOM1->SPI.DATA.reg),   // to here
+    DATA_LENGTH,                        // this many...
+    DMA_BEAT_SIZE_BYTE,                 // bytes/hword/words
+    true,                               // increment source addr?
+    false);                             // increment dest addr?
+
+  Serial.println("Adding callback");
+  // register_callback() can optionally take a second argument
+  // (callback type), default is DMA_CALLBACK_TRANSFER_DONE
+  myDMA.setCallback(dma_callback);
+}
+
+void loop() {
+  // Fill buffer with new data.  The other buffer might
+  // still be transmitting in the background via DMA.
+  memset(source_memory[buffer_being_filled], buffer_value, DATA_LENGTH);
+
+  // Wait for prior transfer to complete before starting new one...
+  Serial.print("Waiting on prior transfer...");
+  while(!transfer_is_done) Serial.write('.');
+  mySPI.endTransaction();
+  Serial.println("Done!");
+
+  // Modify the DMA descriptor using the newly-filled buffer as source...
+  myDMA.changeDescriptor(desc,           // DMA descriptor address
+    source_memory[buffer_being_filled]); // New src; dst & count don't change
+
+  // Begin new transfer...
+  Serial.println("Starting new transfer job");
+  mySPI.beginTransaction(SPISettings(12000000, MSBFIRST, SPI_MODE0));
+  transfer_is_done = false;            // Reset 'done' flag
+  stat             = myDMA.startJob(); // Go!
+  myDMA.printStatus(stat);
+
+  // Switch buffer indices so the alternate buffer is filled/xfer'd
+  // on the next pass.
+  buffer_being_filled = 1 - buffer_being_filled;
+  buffer_value++;
+}
+
diff --git a/libraries/Adafruit_ZeroDMA/library.properties b/libraries/Adafruit_ZeroDMA/library.properties
new file mode 100644
index 000000000..32ce0a1c1
--- /dev/null
+++ b/libraries/Adafruit_ZeroDMA/library.properties
@@ -0,0 +1,9 @@
+name=Adafruit Zero DMA Library
+version=1.0.4
+author=Adafruit
+maintainer=Adafruit <info@adafruit.com>
+sentence=DMA helper/wrapped for ATSAMD21 such as Arduino Zero & Feather M0
+paragraph=DMA helper/wrapped for ATSAMD21 such as Arduino Zero & Feather M0
+category=Signal Input/Output
+url=https://github.com/adafruit/Adafruit_ZeroDMA
+architectures=samd
diff --git a/libraries/Adafruit_ZeroDMA/utility/dma.h b/libraries/Adafruit_ZeroDMA/utility/dma.h
new file mode 100644
index 000000000..bafd36ae2
--- /dev/null
+++ b/libraries/Adafruit_ZeroDMA/utility/dma.h
@@ -0,0 +1,145 @@
+/**
+ * \file
+ *
+ * \brief SAM Direct Memory Access Controller Driver
+ *
+ * Copyright (C) 2014-2015 Atmel Corporation. All rights reserved.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * 3. The name of Atmel may not be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * 4. This software may only be redistributed and used in connection with an
+ *    Atmel microcontroller product.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * \asf_license_stop
+ *
+ */
+/*
+ * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
+ */
+#ifndef DMA_H_INCLUDED
+#define DMA_H_INCLUDED
+
+// THIS IS A PARED-DOWN VERSION OF DMA.H FROM ATMEL ASFCORE 3.
+// Please keep original copyright and license intact!
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if (SAML21) || (SAML22) || (SAMC20) || (SAMC21) || defined(__DOXYGEN__) || defined(__SAMD51__)
+#define FEATURE_DMA_CHANNEL_STANDBY
+#endif
+
+enum dma_transfer_trigger_action{
+#ifdef __SAMD51__
+    // SAMD51 has a 'burst' transfer which can be set to one
+    // beat to accomplish same idea as SAMD21's 'beat' transfer.
+    // Trigger name is ACTON_BEAT for backward compatibility.
+    DMA_TRIGGER_ACTON_BLOCK       = DMAC_CHCTRLA_TRIGACT_BLOCK_Val,
+    DMA_TRIGGER_ACTON_BEAT        = DMAC_CHCTRLA_TRIGACT_BURST_Val,
+    DMA_TRIGGER_ACTON_TRANSACTION = DMAC_CHCTRLA_TRIGACT_TRANSACTION_Val,
+#else
+    DMA_TRIGGER_ACTON_BLOCK       = DMAC_CHCTRLB_TRIGACT_BLOCK_Val,
+    DMA_TRIGGER_ACTON_BEAT        = DMAC_CHCTRLB_TRIGACT_BEAT_Val,
+    DMA_TRIGGER_ACTON_TRANSACTION = DMAC_CHCTRLB_TRIGACT_TRANSACTION_Val,
+#endif
+};
+
+enum dma_callback_type {
+    // First item here is for any transfer errors. A transfer error is
+    // flagged if a bus error is detected during an AHB access or when
+    // the DMAC fetches an invalid descriptor
+    DMA_CALLBACK_TRANSFER_ERROR,
+    DMA_CALLBACK_TRANSFER_DONE,
+    DMA_CALLBACK_CHANNEL_SUSPEND,
+    DMA_CALLBACK_N, // Number of available callbacks
+};
+
+enum dma_beat_size {
+    DMA_BEAT_SIZE_BYTE = 0, // 8-bit
+    DMA_BEAT_SIZE_HWORD,    // 16-bit
+    DMA_BEAT_SIZE_WORD,     // 32-bit
+};
+
+enum dma_event_output_selection {
+    DMA_EVENT_OUTPUT_DISABLE = 0, // Disable event generation
+    DMA_EVENT_OUTPUT_BLOCK,       // Event strobe when block xfer complete
+    DMA_EVENT_OUTPUT_RESERVED,
+    DMA_EVENT_OUTPUT_BEAT,        // Event strobe when beat xfer complete
+};
+
+enum dma_block_action {
+    DMA_BLOCK_ACTION_NOACT = 0,
+    // Channel in normal operation and sets transfer complete interrupt
+    // flag after block transfer
+    DMA_BLOCK_ACTION_INT,
+    // Trigger channel suspend after block transfer and sets channel
+    // suspend interrupt flag once the channel is suspended
+    DMA_BLOCK_ACTION_SUSPEND,
+    // Sets transfer complete interrupt flag after a block transfer and
+    // trigger channel suspend. The channel suspend interrupt flag will
+    // be set once the channel is suspended.
+    DMA_BLOCK_ACTION_BOTH,
+};
+
+// DMA step selection. This bit determines whether the step size setting
+// is applied to source or destination address.
+enum dma_step_selection {
+    DMA_STEPSEL_DST = 0,
+    DMA_STEPSEL_SRC,
+};
+
+// Address increment step size. These bits select the address increment step
+// size. The setting apply to source or destination address, depending on
+// STEPSEL setting.
+enum dma_address_increment_stepsize {
+    DMA_ADDRESS_INCREMENT_STEP_SIZE_1 = 0, // beat size * 1
+    DMA_ADDRESS_INCREMENT_STEP_SIZE_2,     // beat size * 2
+    DMA_ADDRESS_INCREMENT_STEP_SIZE_4,     // beat size * 4
+    DMA_ADDRESS_INCREMENT_STEP_SIZE_8,     // etc...
+    DMA_ADDRESS_INCREMENT_STEP_SIZE_16,
+    DMA_ADDRESS_INCREMENT_STEP_SIZE_32,
+    DMA_ADDRESS_INCREMENT_STEP_SIZE_64,
+    DMA_ADDRESS_INCREMENT_STEP_SIZE_128,
+};
+
+// higher numbers are higher priority
+enum dma_priority {
+    DMA_PRIORITY_0, // lowest (default)
+    DMA_PRIORITY_1,
+    DMA_PRIORITY_2,
+    DMA_PRIORITY_3, // highest
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // DMA_H_INCLUDED
diff --git a/libraries/CI_Tests/CI_Tests.h b/libraries/CI_Tests/CI_Tests.h
new file mode 100644
index 000000000..2cfb22acd
--- /dev/null
+++ b/libraries/CI_Tests/CI_Tests.h
@@ -0,0 +1 @@
+// fake empty header file to make Arduino IDE happy
diff --git a/libraries/CI_Tests/examples/test_cmsis_fast_rfft/test_cmsis_fast_rfft.ino b/libraries/CI_Tests/examples/test_cmsis_fast_rfft/test_cmsis_fast_rfft.ino
new file mode 100644
index 000000000..45c8c08db
--- /dev/null
+++ b/libraries/CI_Tests/examples/test_cmsis_fast_rfft/test_cmsis_fast_rfft.ino
@@ -0,0 +1,12 @@
+#include <arm_math.h>
+
+arm_rfft_fast_instance_f32 plan;
+
+void setup() {
+  arm_rfft_fast_init_f32(&plan, 256);
+}
+
+void loop() {
+    float in[256] = { 0 }, out[256] = { 0 };
+    arm_rfft_fast_f32(&plan, in, out, 0);
+}
diff --git a/libraries/I2S/examples/InputSerialPlotter/.metro_m0.test.only b/libraries/I2S/examples/InputSerialPlotter/.metro_m0.test.only
new file mode 100644
index 000000000..e69de29bb
diff --git a/libraries/I2S/examples/SimpleTone/.metro_m0.test.only b/libraries/I2S/examples/SimpleTone/.metro_m0.test.only
new file mode 100644
index 000000000..e69de29bb
diff --git a/libraries/I2S/src/I2S.cpp b/libraries/I2S/src/I2S.cpp
index 9f86a4138..4c8ab68e8 100644
--- a/libraries/I2S/src/I2S.cpp
+++ b/libraries/I2S/src/I2S.cpp
@@ -20,10 +20,21 @@
 #include <wiring_private.h>
 
 #include "utility/DMA.h"
+
+#if defined(__SAMD51__)
+
+#include "utility/SAMD51_I2SDevice.h"
+
+static I2SDevice_SAMD51 i2sd(*I2S);
+
+#else
+
 #include "utility/SAMD21_I2SDevice.h"
 
 static I2SDevice_SAMD21G18x i2sd(*I2S);
 
+#endif
+
 #include "I2S.h"
 
 int I2SClass::_beginCount = 0;
@@ -98,7 +109,11 @@ int I2SClass::begin(int mode, long sampleRate, int bitsPerSample, bool driveCloc
 
   if (_beginCount == 0) {
     // enable the I2S interface
+#if defined(__SAMD51__)
+    MCLK->APBDMASK.reg |= MCLK_APBDMASK_I2S;
+#else
     PM->APBCMASK.reg |= PM_APBCMASK_I2S;
+#endif
 
     // reset the device
     i2sd.reset();
@@ -176,7 +191,11 @@ void I2SClass::end()
     i2sd.disable();
 
     // disable the I2S interface
+#if defined(__SAMD51__)
+  MCLK->APBDMASK.reg &= ~(MCLK_APBDMASK_I2S);
+#else
     PM->APBCMASK.reg &= ~PM_APBCMASK_I2S;
+#endif
   }
 }
 
diff --git a/libraries/I2S/src/utility/DMA.cpp b/libraries/I2S/src/utility/DMA.cpp
index 74eb58d48..45b166650 100644
--- a/libraries/I2S/src/utility/DMA.cpp
+++ b/libraries/I2S/src/utility/DMA.cpp
@@ -39,9 +39,14 @@ DMAClass::~DMAClass()
 void DMAClass::begin()
 {
   if (_beginCount == 0) {
+
+#if defined(__SAMD51__)
+    MCLK->AHBMASK.bit.DMAC_ = 1;
+#else
     // enable the DMA interface
     PM->AHBMASK.bit.DMAC_ = 1;
     PM->APBBMASK.bit.DMAC_ = 1;
+#endif
 
     // perform a reset
     DMAC->CTRL.bit.SWRST = 1;
@@ -57,9 +62,35 @@ void DMAClass::begin()
     DMAC->CTRL.bit.LVLEN3 = 1;
     DMAC->CTRL.bit.DMAENABLE = 1;
 
-    // enable the interrupt at lowest priority
+#if defined(__SAMD51__)
+    NVIC_DisableIRQ(DMAC_0_IRQn);
+    NVIC_ClearPendingIRQ(DMAC_0_IRQn);
+    NVIC_EnableIRQ(DMAC_0_IRQn);
+    NVIC_SetPriority(DMAC_0_IRQn, (1 << __NVIC_PRIO_BITS) - 1);
+
+    NVIC_DisableIRQ(DMAC_1_IRQn);
+    NVIC_ClearPendingIRQ(DMAC_1_IRQn);
+    NVIC_EnableIRQ(DMAC_1_IRQn);
+    NVIC_SetPriority(DMAC_1_IRQn, (1 << __NVIC_PRIO_BITS) - 1);
+
+    NVIC_DisableIRQ(DMAC_2_IRQn);
+    NVIC_ClearPendingIRQ(DMAC_2_IRQn);
+    NVIC_EnableIRQ(DMAC_2_IRQn);
+    NVIC_SetPriority(DMAC_2_IRQn, (1 << __NVIC_PRIO_BITS) - 1);
+
+    NVIC_DisableIRQ(DMAC_3_IRQn);
+    NVIC_ClearPendingIRQ(DMAC_3_IRQn);
+    NVIC_EnableIRQ(DMAC_3_IRQn);
+    NVIC_SetPriority(DMAC_3_IRQn, (1 << __NVIC_PRIO_BITS) - 1);
+
+    NVIC_DisableIRQ(DMAC_4_IRQn);
+    NVIC_ClearPendingIRQ(DMAC_4_IRQn);
+    NVIC_EnableIRQ(DMAC_4_IRQn);
+    NVIC_SetPriority(DMAC_4_IRQn, (1 << __NVIC_PRIO_BITS) - 1);
+#else
     NVIC_EnableIRQ(DMAC_IRQn);
     NVIC_SetPriority(DMAC_IRQn, (1 << __NVIC_PRIO_BITS) - 1);
+#endif
   }
 
   _beginCount++;
@@ -71,14 +102,27 @@ void DMAClass::end()
 
   if (_beginCount == 0) {
     // disable the interrupt
+#if defined(__SAMD51__)
+      NVIC_DisableIRQ(DMAC_0_IRQn);
+      NVIC_DisableIRQ(DMAC_1_IRQn);
+      NVIC_DisableIRQ(DMAC_2_IRQn);
+      NVIC_DisableIRQ(DMAC_3_IRQn);
+      NVIC_DisableIRQ(DMAC_4_IRQn);
+#else
     NVIC_DisableIRQ(DMAC_IRQn);
+#endif
 
     // disable
     DMAC->CTRL.bit.DMAENABLE = 0;
 
     // disable the DMA interface
-    PM->APBBMASK.bit.DMAC_ = 0;
+#if defined(__SAMD51__)
+    MCLK->AHBMASK.bit.DMAC_ = 0;
+#else
+    // enable the DMA interface
     PM->AHBMASK.bit.DMAC_ = 0;
+    PM->APBBMASK.bit.DMAC_ = 0;
+#endif
   }
 }
 
@@ -96,9 +140,14 @@ int DMAClass::allocateChannel()
       memset((void*)&_descriptors[i], 0x00, sizeof(_descriptors[i]));
 
       // select the channel and reset it
+#if defined(__SAMD51__)
+      DMAC->Channel[i].CHCTRLA.bit.ENABLE = 0;
+      DMAC->Channel[i].CHCTRLA.bit.SWRST = 1;
+#else
       DMAC->CHID.bit.ID = i;
       DMAC->CHCTRLA.bit.ENABLE = 0;
       DMAC->CHCTRLA.bit.SWRST = 1;
+#endif
 
       channel = i;
       break;
@@ -111,8 +160,12 @@ int DMAClass::allocateChannel()
 void DMAClass::freeChannel(int channel)
 {
   // select the channel and disable it
-  DMAC->CHID.bit.ID = channel;
-  DMAC->CHCTRLA.bit.ENABLE = 0;
+#if defined(__SAMD51__)
+      DMAC->Channel[channel].CHCTRLA.bit.ENABLE = 0;
+#else
+      DMAC->CHID.bit.ID = channel;
+      DMAC->CHCTRLA.bit.ENABLE = 0;
+#endif
 
   _channelMask &= ~(1 << channel);
 }
@@ -120,12 +173,21 @@ void DMAClass::freeChannel(int channel)
 void DMAClass::setPriorityLevel(int channel, int level)
 {
   // select the channel and set priority level
-  DMAC->CHID.bit.ID = channel;
-  DMAC->CHCTRLB.bit.LVL = level;
+#if defined(__SAMD51__)
+      
+      DMAC->Channel[channel].CHPRILVL.reg = level;
+#else
+      DMAC->CHID.bit.ID = channel;
+      DMAC->CHCTRLB.bit.LVL = level;
+#endif
 }
 
 void DMAClass::setTriggerSource(int channel, int source)
 {
+#if defined(__SAMD51__)
+  DMAC->Channel[channel].CHCTRLA.bit.TRIGSRC = source;
+  DMAC->Channel[channel].CHCTRLA.bit.TRIGACT = DMAC_CHCTRLA_TRIGACT_BLOCK_Val;
+#else
   // select the channel and set a trigger source
   DMAC->CHID.bit.ID = channel;
   DMAC->CHCTRLB.bit.TRIGSRC = source;
@@ -136,6 +198,7 @@ void DMAClass::setTriggerSource(int channel, int source)
   } else {
     DMAC->CHCTRLB.bit.TRIGACT = DMAC_CHCTRLB_TRIGACT_BLOCK_Val;
   }
+#endif
 }
 
 void DMAClass::setTransferWidth(int channel, int transferWidth)
@@ -178,8 +241,11 @@ int DMAClass::transfer(int channel, void* src, void* dst, uint16_t size)
     return 1;
   }
 
+
+#if !defined(__SAMD51__)
   // select the channel
   DMAC->CHID.bit.ID = channel;
+#endif
 
   // disable event output generation and block actions
   _descriptors[channel].BTCTRL.bit.EVOSEL = DMAC_BTCTRL_EVOSEL_DISABLE_Val;
@@ -223,16 +289,26 @@ int DMAClass::transfer(int channel, void* src, void* dst, uint16_t size)
   // validate the descriptor
   _descriptors[channel].BTCTRL.bit.VALID = 1;
 
+#if defined(__SAMD51__)
+  DMAC->Channel[channel].CHINTENSET.bit.TERR = 1;
+  DMAC->Channel[channel].CHINTENSET.bit.TCMPL = 1;
+  DMAC->Channel[channel].CHCTRLA.bit.ENABLE = 1;
+
+  if (DMAC->Channel[channel].CHCTRLA.bit.TRIGSRC == 0) {
+    // uses software trigger, so trigger it
+    DMAC->SWTRIGCTRL.reg |= (1 << channel);
+  }
+#else
   // enable channel and transfer error + complete interrupts
   DMAC->CHINTENSET.bit.TERR = 1;
   DMAC->CHINTENSET.bit.TCMPL = 1;
   DMAC->CHCTRLA.bit.ENABLE = 1;
 
-
   if (DMAC->CHCTRLB.bit.TRIGSRC == 0) {
     // uses software trigger, so trigger it
     DMAC->SWTRIGCTRL.reg |= (1 << channel);
   }
+#endif
 
   return 0;
 }
@@ -251,11 +327,32 @@ void DMAClass::onService()
 {
   // get the channel and select it
   int channel = DMAC->INTPEND.bit.ID;
+#if !defined(__SAMD51__)
   DMAC->CHID.bit.ID = channel;
+#endif
 
   // invalidate the channel
   _descriptors[channel].BTCTRL.bit.VALID = 0;
 
+#if defined(__SAMD51__)
+  if (DMAC->Channel[channel].CHINTFLAG.bit.TERR) {
+    // clear the error interrupt and call the error callback if there is one
+    DMAC->Channel[channel].CHINTFLAG.bit.TERR = 1;
+
+    if (_transferErrorCallbacks[channel]) {
+      _transferErrorCallbacks[channel](channel);
+    }
+  }
+
+  if (DMAC->Channel[channel].CHINTFLAG.bit.TCMPL) {
+    // clear the complete interrupt and call the callback if there is one
+    DMAC->Channel[channel].CHINTFLAG.bit.TCMPL = 1;
+
+    if (_transferCompleteCallbacks[channel]) {
+      _transferCompleteCallbacks[channel](channel);
+    }
+  }
+#else
   if (DMAC->CHINTFLAG.bit.TERR) {
     // clear the error interrupt and call the error callback if there is one
     DMAC->CHINTFLAG.bit.TERR = 1;
@@ -273,12 +370,55 @@ void DMAClass::onService()
       _transferCompleteCallbacks[channel](channel);
     }
   }
+#endif
 }
 
 extern "C" {
+#if defined(__SAMD51__)
+  static void _dmac_handler(void)
+{
+  DMA.onService();
+}
+/**
+* \brief DMAC interrupt handler
+*/
+void DMAC_0_Handler(void)
+{
+  _dmac_handler();
+}
+/**
+* \brief DMAC interrupt handler
+*/
+void DMAC_1_Handler(void)
+{
+  _dmac_handler();
+}
+/**
+* \brief DMAC interrupt handler
+*/
+void DMAC_2_Handler(void)
+{
+  _dmac_handler();
+}
+/**
+* \brief DMAC interrupt handler
+*/
+void DMAC_3_Handler(void)
+{
+  _dmac_handler();
+}
+/**
+* \brief DMAC interrupt handler
+*/
+void DMAC_4_Handler(void)
+{
+  _dmac_handler();
+}
+#else
   void DMAC_Handler() {
     DMA.onService();
   }
+#endif
 }
 
 DMAClass DMA;
diff --git a/libraries/I2S/src/utility/DMA.h b/libraries/I2S/src/utility/DMA.h
index 19b7b6250..4368eeae1 100644
--- a/libraries/I2S/src/utility/DMA.h
+++ b/libraries/I2S/src/utility/DMA.h
@@ -17,7 +17,11 @@
 */
 #pragma once
 
+#if defined(__SAMD51__)
+#define NUM_DMA_CHANNELS 4
+#else
 #define NUM_DMA_CHANNELS 1
+#endif
 
 /*
   WARNING: The API for this class may change and it's not intended for public use!
diff --git a/libraries/I2S/src/utility/SAMD51_I2SDevice.h b/libraries/I2S/src/utility/SAMD51_I2SDevice.h
new file mode 100644
index 000000000..ba0320afe
--- /dev/null
+++ b/libraries/I2S/src/utility/SAMD51_I2SDevice.h
@@ -0,0 +1,229 @@
+/*
+  Copyright (c) 2016 Arduino LLC. 2017 Adafruit  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#pragma once
+
+#include <Arduino.h>
+
+class I2SDevice_SAMD51 {
+public:
+  I2SDevice_SAMD51(I2s& _i2s) :
+    i2s(_i2s)
+  {
+    // Empty
+  }
+
+  inline void reset() {
+    while(i2s.SYNCBUSY.bit.SWRST);
+    i2s.CTRLA.bit.SWRST = 1;
+  }
+
+  inline void disable() {
+    while(i2s.SYNCBUSY.bit.ENABLE);
+    i2s.CTRLA.bit.ENABLE = 0;
+  }
+
+  inline void enable() {
+    while(i2s.SYNCBUSY.bit.ENABLE);
+    i2s.CTRLA.bit.ENABLE = 1;
+  }
+
+  inline int glckId(int index) {
+    return (index == 0) ? I2S_GCLK_ID_0 : I2S_GCLK_ID_1;
+  }
+
+  inline void setSerialClockSelectMasterClockDiv(int index) {
+    i2s.CLKCTRL[index].bit.SCKSEL = I2S_CLKCTRL_SCKSEL_MCKDIV_Val;
+  }
+
+  inline void setSerialClockSelectPin(int index) {
+    i2s.CLKCTRL[index].bit.SCKSEL = I2S_CLKCTRL_SCKSEL_SCKPIN_Val;
+  }
+
+  inline void setFrameSyncSelectSerialClockDiv(int index) {
+    i2s.CLKCTRL[index].bit.FSSEL = I2S_CLKCTRL_FSSEL_SCKDIV_Val;
+  }
+
+  inline void setFrameSyncSelectPin(int index) {
+    i2s.CLKCTRL[index].bit.FSSEL = I2S_CLKCTRL_FSSEL_FSPIN_Val;
+  }
+
+  inline void set0BitDelay(int index) {
+    i2s.CLKCTRL[index].bit.BITDELAY = I2S_CLKCTRL_BITDELAY_LJ_Val;
+  }
+
+  inline void set1BitDelay(int index) {
+    i2s.CLKCTRL[index].bit.BITDELAY = I2S_CLKCTRL_BITDELAY_I2S_Val;
+  }
+
+  inline void setNumberOfSlots(int index, int nbslots) {
+    i2s.CLKCTRL[index].bit.NBSLOTS = nbslots;
+  }
+
+  inline void setSlotSize(int index, int size) {
+    switch (size) {
+     case 32:
+       i2s.CLKCTRL[index].bit.SLOTSIZE = I2S_CLKCTRL_SLOTSIZE_32_Val;
+       break;
+
+     case 24:
+       i2s.CLKCTRL[index].bit.SLOTSIZE = I2S_CLKCTRL_SLOTSIZE_24_Val;
+       break;
+
+     case 16:
+       i2s.CLKCTRL[index].bit.SLOTSIZE = I2S_CLKCTRL_SLOTSIZE_16_Val;
+       break;
+
+     case 8:
+       i2s.CLKCTRL[index].bit.SLOTSIZE = I2S_CLKCTRL_SLOTSIZE_8_Val;
+       break;
+    }
+  }
+
+  inline void setDataSize(int index, int size) {
+    switch (size) {
+     case 32:
+       i2s.RXCTRL.bit.DATASIZE = I2S_RXCTRL_DATASIZE_32_Val;
+       i2s.TXCTRL.bit.DATASIZE = I2S_TXCTRL_DATASIZE_32_Val;
+       break;
+
+     case 24:
+       i2s.RXCTRL.bit.DATASIZE = I2S_RXCTRL_DATASIZE_24_Val;
+       i2s.TXCTRL.bit.DATASIZE = I2S_TXCTRL_DATASIZE_24_Val;
+       break;
+
+     case 16:
+       i2s.RXCTRL.bit.DATASIZE = I2S_RXCTRL_DATASIZE_16_Val;
+       i2s.TXCTRL.bit.DATASIZE = I2S_TXCTRL_DATASIZE_16_Val;
+       break;
+
+     case 8:
+       i2s.RXCTRL.bit.DATASIZE = I2S_RXCTRL_DATASIZE_8_Val;
+       i2s.TXCTRL.bit.DATASIZE = I2S_TXCTRL_DATASIZE_8_Val;
+       break;
+    }
+  }
+
+  inline void setSlotAdjustedRight(int index) {
+    i2s.RXCTRL.bit.SLOTADJ = I2S_RXCTRL_SLOTADJ_RIGHT_Val;
+    i2s.TXCTRL.bit.SLOTADJ = I2S_TXCTRL_SLOTADJ_RIGHT_Val;
+  }
+
+  inline void setSlotAdjustedLeft(int index) {
+    i2s.RXCTRL.bit.SLOTADJ = I2S_RXCTRL_SLOTADJ_LEFT_Val;
+    i2s.TXCTRL.bit.SLOTADJ = I2S_TXCTRL_SLOTADJ_LEFT_Val;
+  }
+
+  inline void setClockUnit(int index) {
+    i2s.RXCTRL.bit.CLKSEL = (index == 0) ? I2S_RXCTRL_CLKSEL_CLK0_Val : I2S_RXCTRL_CLKSEL_CLK1_Val;
+  }
+
+  inline void setTxMode(int index) {
+    i2s.RXCTRL.bit.SERMODE = 0x01;
+    i2s.TXCTRL.reg &= ~(0x03); //TODO: why is this not in CMSIS...
+    i2s.TXCTRL.reg |= 0x01;
+  }
+
+  inline void setRxMode(int index) {
+    i2s.RXCTRL.bit.SERMODE = 0x00;
+    i2s.TXCTRL.reg &= ~(0x03); //TODO: why is this not in CMSIS...
+    i2s.TXCTRL.reg |= 0x00;
+  }
+
+  inline void enableClockUnit(int index) {
+    if (index == 0) {
+      while(i2s.SYNCBUSY.bit.CKEN0);
+      i2s.CTRLA.bit.CKEN0 = 1;
+    } else {
+      while(i2s.SYNCBUSY.bit.CKEN1);
+      i2s.CTRLA.bit.CKEN1 = 1;
+    }
+  }
+
+  inline void disableClockUnit(int index) {
+    if (index == 0) {
+      while(i2s.SYNCBUSY.bit.CKEN0);
+      i2s.CTRLA.bit.CKEN0 = 0;
+    } else {
+      while(i2s.SYNCBUSY.bit.CKEN1);
+      i2s.CTRLA.bit.CKEN1 = 0;
+    }
+  }
+
+  inline void enableSerializer(int index) {
+    i2s.CTRLA.bit.RXEN = 1;
+    i2s.CTRLA.bit.TXEN = 1;
+  }
+
+  inline void disableSerializer(int index) {
+    i2s.CTRLA.bit.RXEN = 0;
+    i2s.CTRLA.bit.TXEN = 0;
+  }
+
+  inline int dmaTriggerSource(int index) {
+    /*
+    if (i2s.SERCTRL[index].bit.SERMODE == I2S_SERCTRL_SERMODE_TX_Val) {
+      return (index == 0) ? I2S_DMAC_ID_TX_0 : I2S_DMAC_ID_TX_1;
+    } else {
+      return (index == 0) ? I2S_DMAC_ID_RX_0 : I2S_DMAC_ID_RX_1;
+    }
+    */
+  }
+
+  inline int txReady(int index) {
+    return (index == 0) ? i2s.INTFLAG.bit.TXRDY0 :i2s.INTFLAG.bit.TXRDY1;
+  }
+
+  inline void writeData(int index, int32_t value) {
+    while (i2s.SYNCBUSY.bit.TXDATA);
+
+    i2s.TXDATA.bit.DATA = value;
+  }
+
+  inline void clearTxReady(int index) {
+    if (index == 0) {
+     i2s.INTFLAG.bit.TXRDY0 = 1;
+    } else {
+     i2s.INTFLAG.bit.TXRDY1 = 1;
+    }
+  }
+
+  inline int rxReady(int index) {
+    return (index == 0) ? i2s.INTFLAG.bit.RXRDY0 :i2s.INTFLAG.bit.RXRDY1;
+  }
+
+  inline int32_t readData(int index) {
+    while(i2s.SYNCBUSY.bit.RXDATA)
+    return i2s.RXDATA.bit.DATA;
+  }
+
+  inline void clearRxReady(int index) {
+    if (index == 0) {
+     i2s.INTFLAG.bit.RXRDY0 = 1;
+    } else {
+     i2s.INTFLAG.bit.RXRDY1 = 1;
+    }
+  }
+
+  inline void* data(int index) {
+    return (void*)&i2s.RXDATA.reg;
+  }
+
+private:
+  volatile I2s &i2s;
+};
diff --git a/libraries/SAMD_AnalogCorrection/src/SAMD_AnalogCorrection.cpp b/libraries/SAMD_AnalogCorrection/src/SAMD_AnalogCorrection.cpp
index 1681b0a43..a83f7f050 100644
--- a/libraries/SAMD_AnalogCorrection/src/SAMD_AnalogCorrection.cpp
+++ b/libraries/SAMD_AnalogCorrection/src/SAMD_AnalogCorrection.cpp
@@ -1,5 +1,6 @@
 /*
   Copyright (c) 2015 Arduino LLC.  All right reserved.
+  SAMD51 support added by Adafruit - Copyright (c) 2018 Dean Miller for Adafruit Industries
 
   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
@@ -20,12 +21,23 @@
 
 void analogReadCorrection (int offset, uint16_t gain)
 {
+  Adc *adc;
+#if defined (__SAMD51__)
+adc = ADC0;
+#else
+adc = ADC;
+#endif
   // Set correction values
-  ADC->OFFSETCORR.reg = ADC_OFFSETCORR_OFFSETCORR(offset);
-  ADC->GAINCORR.reg = ADC_GAINCORR_GAINCORR(gain);
+  adc->OFFSETCORR.reg = ADC_OFFSETCORR_OFFSETCORR(offset);
+  adc->GAINCORR.reg = ADC_GAINCORR_GAINCORR(gain);
 
   // Enable digital correction logic
-  ADC->CTRLB.bit.CORREN = 1;
-  while(ADC->STATUS.bit.SYNCBUSY);
+  adc->CTRLB.bit.CORREN = 1;
+
+#if defined (__SAMD51__)
+  while(adc->SYNCBUSY.bit.OFFSETCORR || adc->SYNCBUSY.bit.GAINCORR);
+#else
+  while(adc->STATUS.bit.SYNCBUSY);
+#endif
 }
 
diff --git a/libraries/SDU/examples/Usage/.metro_m0.test.only b/libraries/SDU/examples/Usage/.metro_m0.test.only
new file mode 100644
index 000000000..e69de29bb
diff --git a/libraries/SDU/extras/SDUBoot/.metro_m0.test.only b/libraries/SDU/extras/SDUBoot/.metro_m0.test.only
new file mode 100644
index 000000000..e69de29bb
diff --git a/libraries/SPI/SPI.cpp b/libraries/SPI/SPI.cpp
index d154e3671..ba8122815 100644
--- a/libraries/SPI/SPI.cpp
+++ b/libraries/SPI/SPI.cpp
@@ -46,7 +46,16 @@ SPIClass::SPIClass(SERCOM *p_sercom, uint8_t uc_pinMISO, uint8_t uc_pinSCK, uint
 
 void SPIClass::begin()
 {
-  init();
+  if(!initialized) {
+    interruptMode = SPI_IMODE_NONE;
+    interruptSave = 0;
+    interruptMask = 0;
+    initialized = true;
+  }
+
+  if(!use_dma) {
+    dmaAllocate();
+  }
 
   // PIO init
   pinPeripheral(_uc_pinMiso, g_APinDescription[_uc_pinMiso].ulPinType);
@@ -56,16 +65,6 @@ void SPIClass::begin()
   config(DEFAULT_SPI_SETTINGS);
 }
 
-void SPIClass::init()
-{
-  if (initialized)
-    return;
-  interruptMode = SPI_IMODE_NONE;
-  interruptSave = 0;
-  interruptMask = 0;
-  initialized = true;
-}
-
 void SPIClass::config(SPISettings settings)
 {
   _p_sercom->disableSPI();
@@ -80,6 +79,7 @@ void SPIClass::end()
 {
   _p_sercom->resetSPI();
   initialized = false;
+  // Add DMA deallocation here
 }
 
 #ifndef interruptsStatus
@@ -198,7 +198,7 @@ void SPIClass::setDataMode(uint8_t mode)
 
 void SPIClass::setClockDivider(uint8_t div)
 {
-  if (div < SPI_MIN_CLOCK_DIVIDER) {
+  if(div < SPI_MIN_CLOCK_DIVIDER) {
     _p_sercom->setBaudrateSPI(SPI_MIN_CLOCK_DIVIDER);
   } else {
     _p_sercom->setBaudrateSPI(div);
@@ -235,6 +235,243 @@ void SPIClass::transfer(void *buf, size_t count)
   }
 }
 
+// DMA-based SPI transfer() function ---------------------------------------
+
+// IMPORTANT: references to 65535 throughout the DMA code are INTENTIONAL.
+// DO NOT try to 'fix' by changing to 65536, or large transfers will fail!
+// The BTCNT value of a DMA descriptor is an unsigned 16-bit value with a
+// max of 65535. Larger transfers are handled by linked descriptors.
+
+// Pointer to SPIClass object, one per DMA channel. This allows the
+// DMA callback (which has to exist outside the class context) to have
+// a reference back to the originating SPIClass object.
+static SPIClass *spiPtr[DMAC_CH_NUM] = { 0 }; // Legit inits list to NULL
+
+void SPIClass::dmaCallback(Adafruit_ZeroDMA *dma) {
+  // dmaCallback() receives an Adafruit_ZeroDMA object. From this we can get
+  // a channel number (0 to DMAC_CH_NUM-1, always unique per ZeroDMA object),
+  // then locate the originating SPIClass object using array lookup, setting
+  // the dma_busy element 'false' to indicate end of transfer. Doesn't matter
+  // if it's a read or write transfer...both channels get pointers to it.
+  spiPtr[dma->getChannel()]->dma_busy = false;
+}
+
+// For read-only and read+write transfers, a callback is assigned only
+// to the read channel to indicate end-of-transfer, and the write channel's
+// callback is assigned to this nonsense function (for reasons I'm not
+// entirely sure of, setting the callback to NULL doesn't work).
+static void dmaDoNothingCallback(Adafruit_ZeroDMA *dma) { (void)dma; }
+
+// This could've gone in begin(), but for the sake of organization...
+void SPIClass::dmaAllocate(void) {
+  // In order to support fully non-blocking SPI transfers, DMA descriptor
+  // lists must be created for the input and/or output data. Rather than
+  // do this dynamically with every transfer, the lists are allocated once
+  // on SPI init. Maximum list size is finite and knowable -- transfers to
+  // or from RAM or from flash memory will never exceed the corresponding
+  // memory size (if they do, you have bigger problems). Descriptors
+  // aren't large and there's usually only a handful to a dozen, so this
+  // isn't an excessive burden in exchange for big non-blocking transfers.
+  uint32_t maxWriteBytes = FLASH_SIZE; // Writes can't exceed all of flash
+#if defined(__SAMD51__)
+  uint32_t maxReadBytes = HSRAM_SIZE;  // Reads can't exceed all of RAM
+#else
+  uint32_t maxReadBytes = HMCRAMC0_SIZE;
+#endif
+  if(maxReadBytes > maxWriteBytes) { // I don't think any SAMD devices
+    maxWriteBytes = maxReadBytes;    // have RAM > flash, but just in case
+  }
+
+  // VITAL to alloc read channel first, assigns it a higher DMA priority!
+  if(readChannel.allocate() == DMA_STATUS_OK) {
+    if(writeChannel.allocate() == DMA_STATUS_OK) {
+
+      // Both DMA channels (read and write) allocated successfully,
+      // set up transfer triggers and other basics...
+
+      // readChannel callback only needs to be set up once.
+      // Unlike the write callback which may get switched on or off,
+      // read callback stays put. In certain cases the read DMA job
+      // just isn't started and the callback is a non-issue then.
+      readChannel.setTrigger(getDMAC_ID_RX());
+      readChannel.setAction(DMA_TRIGGER_ACTON_BEAT);
+      readChannel.setCallback(dmaCallback);
+      spiPtr[readChannel.getChannel()] = this;
+
+      writeChannel.setTrigger(getDMAC_ID_TX());
+      writeChannel.setAction(DMA_TRIGGER_ACTON_BEAT);
+      spiPtr[writeChannel.getChannel()] = this;
+
+      // One descriptor per channel has already been allocated
+      // in Adafruit_ZeroDMA, this just gets pointers to them...
+      firstReadDescriptor = readChannel.addDescriptor(
+        (void *)getDataRegister(), // Source address (SPI data reg)
+        NULL,                      // Dest address (set later)
+        0,                         // Count (set later)
+        DMA_BEAT_SIZE_BYTE,        // Bytes/hwords/words
+        false,                     // Don't increment source address
+        true);                     // Increment dest address
+      firstWriteDescriptor = writeChannel.addDescriptor(
+        NULL,                      // Source address (set later)
+        (void *)getDataRegister(), // Dest (SPI data register)
+        0,                         // Count (set later)
+        DMA_BEAT_SIZE_BYTE,        // Bytes/hwords/words
+        true,                      // Increment source address
+        false);                    // Don't increment dest address
+      // This is the number of EXTRA descriptors beyond the first.
+      int numReadDescriptors  = ((maxReadBytes  + 65534) / 65535) - 1;
+      int numWriteDescriptors = ((maxWriteBytes + 65534) / 65535) - 1;
+      int totalDescriptors    = numReadDescriptors + numWriteDescriptors;
+
+      if(totalDescriptors <= 0) { // Don't need extra descriptors,
+        use_dma = true;           // channels are allocated, we're good.
+      } else {                    // Else allocate extra descriptor lists...
+        // Although DMA descriptors are technically a linked list, we just
+        // allocate a chunk all at once, and finesse the pointers later.
+        if((extraReadDescriptors = (DmacDescriptor *)malloc(
+          totalDescriptors * sizeof(DmacDescriptor)))) {
+          use_dma = true; // Everything allocated successfully
+          extraWriteDescriptors = &extraReadDescriptors[numReadDescriptors];
+          // Initialize descriptors (copy from first ones)
+          for(int i=0; i<numReadDescriptors; i++) {
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wclass-memaccess"
+            memcpy(&extraReadDescriptors[i], firstReadDescriptor,
+              sizeof(DmacDescriptor));
+#pragma GCC diagnostic pop
+          }
+          for(int i=0; i<numWriteDescriptors; i++) {
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wclass-memaccess"
+            memcpy(&extraWriteDescriptors[i], firstWriteDescriptor,
+              sizeof(DmacDescriptor));
+#pragma GCC diagnostic pop
+          }
+        } // end malloc
+      } // end extra descriptor check
+
+      if(use_dma) { // If everything allocated successfully,
+        return;     // then we're done here.
+      }             // Otherwise clean up interim allocations...
+      writeChannel.free();
+    } // end writeChannel alloc
+    readChannel.free();
+  } // end readChannel alloc
+
+  // NOT FATAL if channel or descriptor allocation fails.
+  // transfer() function will fall back on a manual byte-by-byte loop.
+}
+
+void SPIClass::transfer(const void *txbuf, void *rxbuf, size_t count,
+  bool block) {
+
+  if((!txbuf && !rxbuf) || !count) { // Validate inputs
+    return;
+  }
+  // OK to assume now that txbuf and/or rxbuf are non-NULL, an if/else is
+  // often sufficient, don't need else-ifs for everything buffer related.
+
+  uint8_t *txbuf8 = (uint8_t *)txbuf; // Must cast to byte size
+  uint8_t *rxbuf8 = (uint8_t *)rxbuf; // for pointer math
+
+  if(use_dma) { // DMA-BASED TRANSFER YAY ----------------------------------
+
+    static const uint8_t dum = 0xFF; // Dummy byte for read-only xfers
+
+    // Set up DMA descriptor lists -----------------------------------------
+
+    DmacDescriptor *rDesc = firstReadDescriptor;
+    DmacDescriptor *wDesc = firstWriteDescriptor;
+    int descIdx = 0; // Index into extra descriptor lists
+
+    while(count) { // Counts down to end of transfer
+      uint32_t bytesThisDescriptor = count;
+      if(bytesThisDescriptor > 65535) { // Limit each descriptor
+        bytesThisDescriptor = 65535;    // to 65535 (not 65536) bytes
+      }
+      rDesc->BTCNT.reg = wDesc->BTCNT.reg = bytesThisDescriptor;
+      if(rxbuf) { // Read-only or read+write
+        // Auto-inc addresses in DMA descriptors must point to END of data.
+        // Buf pointers would advance at end of loop anyway, do it now...
+        rxbuf8 += bytesThisDescriptor;
+        rDesc->DSTADDR.reg = (uint32_t)rxbuf8;
+      }
+      if(txbuf) { // Write-only or read+write
+        txbuf8 += bytesThisDescriptor; // Same as above
+        wDesc->SRCADDR.reg       = (uint32_t)txbuf8;
+        wDesc->BTCTRL.bit.SRCINC = 1; // Increment source pointer
+      } else { // Read-only requires dummy write
+        wDesc->SRCADDR.reg       = (uint32_t)&dum;
+        wDesc->BTCTRL.bit.SRCINC = 0; // Don't increment source pointer
+      }
+      count -= bytesThisDescriptor;
+      if(count) { // Still more data?
+        // Link to next descriptors. Extra descriptors are IN ADDITION
+        // to first, so it's safe and correct that descIdx starts at 0.
+        rDesc->DESCADDR.reg = (uint32_t)&extraReadDescriptors[descIdx];
+        wDesc->DESCADDR.reg = (uint32_t)&extraWriteDescriptors[descIdx];
+        rDesc = &extraReadDescriptors[descIdx];  // Update pointers to
+        wDesc = &extraWriteDescriptors[descIdx]; // next descriptors
+        descIdx++;
+        // A write-only transfer doesn't use the read descriptor list, but
+        // it's quicker to build it (full of nonsense) anyway than to check.
+      } else { // No more data, end descriptor linked lists
+        rDesc->DESCADDR.reg = wDesc->DESCADDR.reg = 0;
+      }
+    }
+
+    // Set up DMA transfer job(s) ------------------------------------------
+
+    if(rxbuf) { // Read+write or read-only
+      // End-of-read callback is already set up, disable write CB, start job
+      writeChannel.setCallback(dmaDoNothingCallback);
+      readChannel.startJob();
+    } else { // Write-only, use end-of-write callback
+      writeChannel.setCallback(dmaCallback);
+    }
+
+    // Run DMA jobs, blocking if requested ---------------------------------
+
+    dma_busy = true;
+    writeChannel.startJob(); // All xfers, even read-only, need write job.
+    if(block) {              // If blocking transfer requested,
+      while(dma_busy);       // wait for job to finish
+    }
+
+  } else { // NON-DMA FALLBACK ---------------------------------------------
+
+    if(txbuf8) {
+      if(rxbuf8) { // Write + read simultaneously
+        while(count--) {
+          *rxbuf8++ = _p_sercom->transferDataSPI(*txbuf8++);
+        }
+      } else {     // Write only
+        while(count--) {
+          (void)_p_sercom->transferDataSPI(*txbuf8++);
+        }
+      }
+    } else {       // Read only
+      while(count--) {
+        *rxbuf8++ = _p_sercom->transferDataSPI(0xFF);
+      }
+    }
+
+  } // end non-DMA
+}
+
+// Waits for a prior in-background DMA transfer to complete.
+void SPIClass::waitForTransfer(void) {
+  while(dma_busy);
+}
+
+/* returns the current DMA transfer status to allow non-blocking polling */
+bool SPIClass::isBusy(void) {
+  return dma_busy;
+}
+
+
+// End DMA-based SPI transfer() code ---------------------------------------
+
 void SPIClass::attachInterrupt() {
   // Should be enableInterrupt()
 }
@@ -243,6 +480,61 @@ void SPIClass::detachInterrupt() {
   // Should be disableInterrupt()
 }
 
+// SPI DMA lookup works on both SAMD21 and SAMD51
+
+static const struct {
+  volatile uint32_t *data_reg;
+  int                dmac_id_tx;
+  int                dmac_id_rx;
+} sercomData[] = {
+  { &SERCOM0->SPI.DATA.reg, SERCOM0_DMAC_ID_TX, SERCOM0_DMAC_ID_RX },
+  { &SERCOM1->SPI.DATA.reg, SERCOM1_DMAC_ID_TX, SERCOM1_DMAC_ID_RX },
+  { &SERCOM2->SPI.DATA.reg, SERCOM2_DMAC_ID_TX, SERCOM2_DMAC_ID_RX },
+  { &SERCOM3->SPI.DATA.reg, SERCOM3_DMAC_ID_TX, SERCOM3_DMAC_ID_RX },
+#if defined(SERCOM4)
+  { &SERCOM4->SPI.DATA.reg, SERCOM4_DMAC_ID_TX, SERCOM4_DMAC_ID_RX },
+#endif
+#if defined(SERCOM5)
+  { &SERCOM5->SPI.DATA.reg, SERCOM5_DMAC_ID_TX, SERCOM5_DMAC_ID_RX },
+#endif
+#if defined(SERCOM6)
+  { &SERCOM6->SPI.DATA.reg, SERCOM6_DMAC_ID_TX, SERCOM6_DMAC_ID_RX },
+#endif
+#if defined(SERCOM7)
+  { &SERCOM7->SPI.DATA.reg, SERCOM7_DMAC_ID_TX, SERCOM7_DMAC_ID_RX },
+#endif
+};
+
+volatile uint32_t *SPIClass::getDataRegister(void) {
+  int8_t idx = _p_sercom->getSercomIndex();
+  return (idx >= 0) ? sercomData[idx].data_reg: NULL;
+}
+
+int SPIClass::getDMAC_ID_TX(void) {
+  int8_t idx = _p_sercom->getSercomIndex();
+  return (idx >= 0) ? sercomData[idx].dmac_id_tx : -1;
+}
+
+int SPIClass::getDMAC_ID_RX(void) {
+  int8_t idx = _p_sercom->getSercomIndex();
+  return (idx >= 0) ? sercomData[idx].dmac_id_rx : -1;
+}
+
+#if defined(__SAMD51__)
+
+// Set the SPI device's SERCOM clock CORE and SLOW clock sources.
+// SercomClockSource values are an enumeration in SERCOM.h.
+// This works on SAMD51 only.  On SAMD21, a dummy function is declared
+// in SPI.h which compiles to nothing, so user code doesn't need to check
+// and conditionally compile lines for different architectures.
+void SPIClass::setClockSource(SercomClockSource clk) {
+  int8_t idx = _p_sercom->getSercomIndex();
+  _p_sercom->setClockSource(idx, clk, true);  // true  = set core clock
+  _p_sercom->setClockSource(idx, clk, false); // false = set slow clock
+}
+
+#endif // end __SAMD51__
+
 #if SPI_INTERFACES_COUNT > 0
   /* In case new variant doesn't define these macros,
    * we put here the ones for Arduino Zero.
@@ -275,4 +567,3 @@ void SPIClass::detachInterrupt() {
 #if SPI_INTERFACES_COUNT > 5
   SPIClass SPI5(&PERIPH_SPI5, PIN_SPI5_MISO, PIN_SPI5_SCK, PIN_SPI5_MOSI, PAD_SPI5_TX, PAD_SPI5_RX);
 #endif
-
diff --git a/libraries/SPI/SPI.h b/libraries/SPI/SPI.h
index d4ab2d64a..7c719f695 100644
--- a/libraries/SPI/SPI.h
+++ b/libraries/SPI/SPI.h
@@ -21,6 +21,7 @@
 #define _SPI_H_INCLUDED
 
 #include <Arduino.h>
+#include <Adafruit_ZeroDMA.h>
 
 // SPI_HAS_TRANSACTION means SPI has
 //   - beginTransaction()
@@ -37,12 +38,27 @@
 #define SPI_MODE2 0x03
 #define SPI_MODE3 0x01
 
-#if defined(ARDUINO_ARCH_SAMD)
+#if defined(__SAMD51__)
+  // SAMD51 has configurable MAX_SPI, else use peripheral clock default.
+  // Update: changing MAX_SPI via compiler flags is DEPRECATED, because
+  // this affects ALL SPI peripherals including some that should NOT be
+  // changed (e.g. anything using SD card). Use the setClockSource()
+  // function instead. This is left here for compatibility with interim code.
+  #if !defined(MAX_SPI)
+    #define MAX_SPI 24000000
+  #endif
+  #define SPI_MIN_CLOCK_DIVIDER 1
+#else
   // The datasheet specifies a typical SPI SCK period (tSCK) of 42 ns,
   // see "Table 36-48. SPI Timing Characteristics and Requirements",
   // which translates into a maximum SPI clock of 23.8 MHz.
-  // Conservatively, the divider is set for a 12 MHz maximum SPI clock.
-  #define SPI_MIN_CLOCK_DIVIDER (uint8_t)(1 + ((F_CPU - 1) / 12000000))
+  // We'll permit use of 24 MHz SPI even though this is slightly out
+  // of spec. Given how clock dividers work, the next "sensible"
+  // threshold would be a substantial drop down to 12 MHz.
+  #if !defined(MAX_SPI)
+    #define MAX_SPI 24000000
+  #endif
+  #define SPI_MIN_CLOCK_DIVIDER (uint8_t)(1 + ((F_CPU - 1) / MAX_SPI))
 #endif
 
 class SPISettings {
@@ -64,7 +80,11 @@ class SPISettings {
   }
 
   void init_AlwaysInline(uint32_t clock, BitOrder bitOrder, uint8_t dataMode) __attribute__((__always_inline__)) {
-    this->clockFreq = (clock >= (F_CPU / SPI_MIN_CLOCK_DIVIDER) ? F_CPU / SPI_MIN_CLOCK_DIVIDER : clock);
+#if defined(__SAMD51__)
+    this->clockFreq = clock; // Clipping handled in SERCOM.cpp
+#else
+    this->clockFreq = clock >= MAX_SPI ? MAX_SPI : clock;
+#endif
 
     this->bitOrder = (bitOrder == MSBFIRST ? MSB_FIRST : LSB_FIRST);
 
@@ -94,10 +114,13 @@ class SPIClass {
   public:
   SPIClass(SERCOM *p_sercom, uint8_t uc_pinMISO, uint8_t uc_pinSCK, uint8_t uc_pinMOSI, SercomSpiTXPad, SercomRXPad);
 
-
   byte transfer(uint8_t data);
   uint16_t transfer16(uint16_t data);
   void transfer(void *buf, size_t count);
+  void transfer(const void* txbuf, void* rxbuf, size_t count,
+         bool block = true);
+  void waitForTransfer(void);
+  bool isBusy(void);
 
   // Transaction Functions
   void usingInterrupt(int interruptNumber);
@@ -116,8 +139,21 @@ class SPIClass {
   void setDataMode(uint8_t uc_mode);
   void setClockDivider(uint8_t uc_div);
 
+  // SERCOM lookup functions are available on both SAMD51 and 21.
+  volatile uint32_t *getDataRegister(void);
+  int getDMAC_ID_TX(void);
+  int getDMAC_ID_RX(void);
+  uint8_t getSercomIndex(void) { return _p_sercom->getSercomIndex(); };
+#if defined(__SAMD51__)
+  // SERCOM clock source override is available only on SAMD51.
+  void setClockSource(SercomClockSource clk);
+#else
+  // On SAMD21, this compiles to nothing, so user code doesn't need to
+  // check and conditionally compile lines for different architectures.
+  void setClockSource(SercomClockSource clk) { (void)clk; };
+#endif // end __SAMD51__
+
   private:
-  void init();
   void config(SPISettings settings);
 
   SERCOM *_p_sercom;
@@ -132,6 +168,18 @@ class SPIClass {
   uint8_t interruptMode;
   char interruptSave;
   uint32_t interruptMask;
+
+  // transfer(txbuf, rxbuf, count, block) uses DMA when possible
+  Adafruit_ZeroDMA readChannel;
+  Adafruit_ZeroDMA writeChannel;
+  DmacDescriptor  *firstReadDescriptor   = NULL;  // List entry point
+  DmacDescriptor  *firstWriteDescriptor  = NULL;
+  DmacDescriptor  *extraReadDescriptors  = NULL;  // Add'l descriptors
+  DmacDescriptor  *extraWriteDescriptors = NULL;
+  bool             use_dma               = false; // true on successful alloc
+  volatile bool    dma_busy              = false;
+  void             dmaAllocate(void);
+  static void      dmaCallback(Adafruit_ZeroDMA *dma);
 };
 
 #if SPI_INTERFACES_COUNT > 0
@@ -155,14 +203,12 @@ class SPIClass {
 
 // For compatibility with sketches designed for AVR @ 16 MHz
 // New programs should use SPI.beginTransaction to set the SPI clock
-#if F_CPU == 48000000
-  #define SPI_CLOCK_DIV2   6
-  #define SPI_CLOCK_DIV4   12
-  #define SPI_CLOCK_DIV8   24
-  #define SPI_CLOCK_DIV16  48
-  #define SPI_CLOCK_DIV32  96
-  #define SPI_CLOCK_DIV64  192
-  #define SPI_CLOCK_DIV128 255
-#endif
+#define SPI_CLOCK_DIV2   (MAX_SPI * 2 / 8000000)
+#define SPI_CLOCK_DIV4   (MAX_SPI * 2 / 4000000)
+#define SPI_CLOCK_DIV8   (MAX_SPI * 2 / 2000000)
+#define SPI_CLOCK_DIV16  (MAX_SPI * 2 / 1000000)
+#define SPI_CLOCK_DIV32  (MAX_SPI * 2 / 500000)
+#define SPI_CLOCK_DIV64  (MAX_SPI * 2 / 250000)
+#define SPI_CLOCK_DIV128 (MAX_SPI * 2 / 125000)
 
 #endif
diff --git a/libraries/Servo/README.adoc b/libraries/Servo/README.adoc
new file mode 100644
index 000000000..dd3f0bae3
--- /dev/null
+++ b/libraries/Servo/README.adoc
@@ -0,0 +1,25 @@
+= Servo Library for Arduino =
+
+This library allows an Arduino board to control RC (hobby) servo motors.
+
+For more information about this library please visit us at
+http://www.arduino.cc/en/Reference/Servo
+
+== License ==
+
+Copyright (c) 2013 Arduino LLC. All right reserved.
+Copyright (c) 2009 Michael Margolis.  All right reserved.
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
diff --git a/libraries/Servo/examples/Knob/Knob.ino b/libraries/Servo/examples/Knob/Knob.ino
new file mode 100644
index 000000000..0db8770bd
--- /dev/null
+++ b/libraries/Servo/examples/Knob/Knob.ino
@@ -0,0 +1,27 @@
+/*
+ Controlling a servo position using a potentiometer (variable resistor)
+ by Michal Rinott <http://people.interaction-ivrea.it/m.rinott>
+
+ modified on 8 Nov 2013
+ by Scott Fitzgerald
+ http://www.arduino.cc/en/Tutorial/Knob
+*/
+
+#include <Servo.h>
+
+Servo myservo;  // create servo object to control a servo
+
+int potpin = 0;  // analog pin used to connect the potentiometer
+int val;    // variable to read the value from the analog pin
+
+void setup() {
+  myservo.attach(9);  // attaches the servo on pin 9 to the servo object
+}
+
+void loop() {
+  val = analogRead(potpin);            // reads the value of the potentiometer (value between 0 and 1023)
+  val = map(val, 0, 1023, 0, 180);     // scale it to use it with the servo (value between 0 and 180)
+  myservo.write(val);                  // sets the servo position according to the scaled value
+  delay(15);                           // waits for the servo to get there
+}
+
diff --git a/libraries/Servo/examples/Sweep/Sweep.ino b/libraries/Servo/examples/Sweep/Sweep.ino
new file mode 100644
index 000000000..df904afb1
--- /dev/null
+++ b/libraries/Servo/examples/Sweep/Sweep.ino
@@ -0,0 +1,32 @@
+/* Sweep
+ by BARRAGAN <http://barraganstudio.com>
+ This example code is in the public domain.
+
+ modified 8 Nov 2013
+ by Scott Fitzgerald
+ http://www.arduino.cc/en/Tutorial/Sweep
+*/
+
+#include <Servo.h>
+
+Servo myservo;  // create servo object to control a servo
+// twelve servo objects can be created on most boards
+
+int pos = 0;    // variable to store the servo position
+
+void setup() {
+  myservo.attach(9);  // attaches the servo on pin 9 to the servo object
+}
+
+void loop() {
+  for (pos = 0; pos <= 180; pos += 1) { // goes from 0 degrees to 180 degrees
+    // in steps of 1 degree
+    myservo.write(pos);              // tell servo to go to position in variable 'pos'
+    delay(15);                       // waits 15ms for the servo to reach the position
+  }
+  for (pos = 180; pos >= 0; pos -= 1) { // goes from 180 degrees to 0 degrees
+    myservo.write(pos);              // tell servo to go to position in variable 'pos'
+    delay(15);                       // waits 15ms for the servo to reach the position
+  }
+}
+
diff --git a/libraries/Servo/keywords.txt b/libraries/Servo/keywords.txt
new file mode 100644
index 000000000..0a7ca1e3d
--- /dev/null
+++ b/libraries/Servo/keywords.txt
@@ -0,0 +1,24 @@
+#######################################
+# Syntax Coloring Map Servo
+#######################################
+
+#######################################
+# Datatypes (KEYWORD1)
+#######################################
+
+Servo	KEYWORD1	Servo
+
+#######################################
+# Methods and Functions (KEYWORD2)
+#######################################
+attach	KEYWORD2
+detach	KEYWORD2
+write	KEYWORD2
+read	KEYWORD2
+attached	KEYWORD2
+writeMicroseconds	KEYWORD2
+readMicroseconds	KEYWORD2
+
+#######################################
+# Constants (LITERAL1)
+#######################################
diff --git a/libraries/Servo/library.properties b/libraries/Servo/library.properties
new file mode 100644
index 000000000..8e55e5596
--- /dev/null
+++ b/libraries/Servo/library.properties
@@ -0,0 +1,9 @@
+name=Servo
+version=1.1.4
+author=Michael Margolis, Arduino
+maintainer=Arduino <info@arduino.cc>
+sentence=Allows Arduino/Genuino boards to control a variety of servo motors.
+paragraph=This library can control a great number of servos.<br />It makes careful use of timers: the library can control 12 servos using only 1 timer.<br />On the Arduino Due you can control up to 60 servos.<br />
+category=Device Control
+url=http://www.arduino.cc/en/Reference/Servo
+architectures=avr,megaavr,sam,samd,nrf52,stm32f4
diff --git a/libraries/Servo/src/Servo.h b/libraries/Servo/src/Servo.h
new file mode 100644
index 000000000..a12565800
--- /dev/null
+++ b/libraries/Servo/src/Servo.h
@@ -0,0 +1,121 @@
+/*
+  Servo.h - Interrupt driven Servo library for Arduino using 16 bit timers- Version 2
+  Copyright (c) 2009 Michael Margolis.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* 
+  A servo is activated by creating an instance of the Servo class passing 
+  the desired pin to the attach() method.
+  The servos are pulsed in the background using the value most recently 
+  written using the write() method.
+
+  Note that analogWrite of PWM on pins associated with the timer are 
+  disabled when the first servo is attached.
+  Timers are seized as needed in groups of 12 servos - 24 servos use two 
+  timers, 48 servos will use four.
+  The sequence used to sieze timers is defined in timers.h
+
+  The methods are:
+
+    Servo - Class for manipulating servo motors connected to Arduino pins.
+
+    attach(pin )  - Attaches a servo motor to an i/o pin.
+    attach(pin, min, max  ) - Attaches to a pin setting min and max values in microseconds
+    default min is 544, max is 2400  
+ 
+    write()     - Sets the servo angle in degrees.  (invalid angle that is valid as pulse in microseconds is treated as microseconds)
+    writeMicroseconds() - Sets the servo pulse width in microseconds 
+    read()      - Gets the last written servo pulse width as an angle between 0 and 180. 
+    readMicroseconds()   - Gets the last written servo pulse width in microseconds. (was read_us() in first release)
+    attached()  - Returns true if there is a servo attached. 
+    detach()    - Stops an attached servos from pulsing its i/o pin. 
+ */
+
+#ifndef Servo_h
+#define Servo_h
+
+#include <inttypes.h>
+
+/* 
+ * Defines for 16 bit timers used with  Servo library 
+ *
+ * If _useTimerX is defined then TimerX is a 16 bit timer on the current board
+ * timer16_Sequence_t enumerates the sequence that the timers should be allocated
+ * _Nbr_16timers indicates how many 16 bit timers are available.
+ */
+
+// Architecture specific include
+#if defined(ARDUINO_ARCH_AVR)
+#include "avr/ServoTimers.h"
+#elif defined(ARDUINO_ARCH_SAM)
+#include "sam/ServoTimers.h"
+#elif defined(ARDUINO_ARCH_SAMD)
+#include "samd/ServoTimers.h"
+#elif defined(ARDUINO_ARCH_STM32F4)
+#include "stm32f4/ServoTimers.h"
+#elif defined(ARDUINO_ARCH_NRF52)
+#include "nrf52/ServoTimers.h"
+#elif defined(ARDUINO_ARCH_MEGAAVR)
+#include "megaavr/ServoTimers.h"
+#else
+#error "This library only supports boards with an AVR, SAM, SAMD, NRF52 or STM32F4 processor."
+#endif
+
+#define Servo_VERSION           2     // software version of this library
+
+#define MIN_PULSE_WIDTH       544     // the shortest pulse sent to a servo  
+#define MAX_PULSE_WIDTH      2400     // the longest pulse sent to a servo 
+#define DEFAULT_PULSE_WIDTH  1500     // default pulse width when servo is attached
+#define REFRESH_INTERVAL    20000     // minumim time to refresh servos in microseconds 
+
+#define SERVOS_PER_TIMER       12     // the maximum number of servos controlled by one timer 
+#define MAX_SERVOS   (_Nbr_16timers  * SERVOS_PER_TIMER)
+
+#define INVALID_SERVO         255     // flag indicating an invalid servo index
+
+#if !defined(ARDUINO_ARCH_STM32F4)
+
+typedef struct  {
+  uint8_t nbr        :6 ;             // a pin number from 0 to 63
+  uint8_t isActive   :1 ;             // true if this channel is enabled, pin not pulsed if false 
+} ServoPin_t   ;  
+
+typedef struct {
+  ServoPin_t Pin;
+  volatile unsigned int ticks;
+} servo_t;
+
+class Servo
+{
+public:
+  Servo();
+  uint8_t attach(int pin);           // attach the given pin to the next free channel, sets pinMode, returns channel number or 0 if failure
+  uint8_t attach(int pin, int min, int max); // as above but also sets min and max values for writes. 
+  void detach();
+  void write(int value);             // if value is < 200 its treated as an angle, otherwise as pulse width in microseconds 
+  void writeMicroseconds(int value); // Write pulse width in microseconds 
+  int read();                        // returns current pulse width as an angle between 0 and 180 degrees
+  int readMicroseconds();            // returns current pulse width in microseconds for this servo (was read_us() in first release)
+  bool attached();                   // return true if this servo is attached, otherwise false 
+private:
+   uint8_t servoIndex;               // index into the channel data for this servo
+   int8_t min;                       // minimum is this value times 4 added to MIN_PULSE_WIDTH    
+   int8_t max;                       // maximum is this value times 4 added to MAX_PULSE_WIDTH   
+};
+
+#endif
+#endif
diff --git a/libraries/Servo/src/avr/Servo.cpp b/libraries/Servo/src/avr/Servo.cpp
new file mode 100644
index 000000000..ed7376efc
--- /dev/null
+++ b/libraries/Servo/src/avr/Servo.cpp
@@ -0,0 +1,318 @@
+/*
+ Servo.cpp - Interrupt driven Servo library for Arduino using 16 bit timers- Version 2
+ Copyright (c) 2009 Michael Margolis.  All right reserved.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#if defined(ARDUINO_ARCH_AVR)
+
+#include <avr/interrupt.h>
+#include <Arduino.h>
+
+#include "Servo.h"
+
+#define usToTicks(_us)    (( clockCyclesPerMicrosecond()* _us) / 8)     // converts microseconds to tick (assumes prescale of 8)  // 12 Aug 2009
+#define ticksToUs(_ticks) (( (unsigned)_ticks * 8)/ clockCyclesPerMicrosecond() ) // converts from ticks back to microseconds
+
+
+#define TRIM_DURATION       2                               // compensation ticks to trim adjust for digitalWrite delays // 12 August 2009
+
+//#define NBR_TIMERS        (MAX_SERVOS / SERVOS_PER_TIMER)
+
+static servo_t servos[MAX_SERVOS];                          // static array of servo structures
+static volatile int8_t Channel[_Nbr_16timers ];             // counter for the servo being pulsed for each timer (or -1 if refresh interval)
+
+uint8_t ServoCount = 0;                                     // the total number of attached servos
+
+
+// convenience macros
+#define SERVO_INDEX_TO_TIMER(_servo_nbr) ((timer16_Sequence_t)(_servo_nbr / SERVOS_PER_TIMER)) // returns the timer controlling this servo
+#define SERVO_INDEX_TO_CHANNEL(_servo_nbr) (_servo_nbr % SERVOS_PER_TIMER)       // returns the index of the servo on this timer
+#define SERVO_INDEX(_timer,_channel)  ((_timer*SERVOS_PER_TIMER) + _channel)     // macro to access servo index by timer and channel
+#define SERVO(_timer,_channel)  (servos[SERVO_INDEX(_timer,_channel)])            // macro to access servo class by timer and channel
+
+#define SERVO_MIN() (MIN_PULSE_WIDTH - this->min * 4)  // minimum value in uS for this servo
+#define SERVO_MAX() (MAX_PULSE_WIDTH - this->max * 4)  // maximum value in uS for this servo
+
+/************ static functions common to all instances ***********************/
+
+static inline void handle_interrupts(timer16_Sequence_t timer, volatile uint16_t *TCNTn, volatile uint16_t* OCRnA)
+{
+  if( Channel[timer] < 0 )
+    *TCNTn = 0; // channel set to -1 indicated that refresh interval completed so reset the timer
+  else{
+    if( SERVO_INDEX(timer,Channel[timer]) < ServoCount && SERVO(timer,Channel[timer]).Pin.isActive == true )
+      digitalWrite( SERVO(timer,Channel[timer]).Pin.nbr,LOW); // pulse this channel low if activated
+  }
+
+  Channel[timer]++;    // increment to the next channel
+  if( SERVO_INDEX(timer,Channel[timer]) < ServoCount && Channel[timer] < SERVOS_PER_TIMER) {
+    *OCRnA = *TCNTn + SERVO(timer,Channel[timer]).ticks;
+    if(SERVO(timer,Channel[timer]).Pin.isActive == true)     // check if activated
+      digitalWrite( SERVO(timer,Channel[timer]).Pin.nbr,HIGH); // its an active channel so pulse it high
+  }
+  else {
+    // finished all channels so wait for the refresh period to expire before starting over
+    if( ((unsigned)*TCNTn) + 4 < usToTicks(REFRESH_INTERVAL) )  // allow a few ticks to ensure the next OCR1A not missed
+      *OCRnA = (unsigned int)usToTicks(REFRESH_INTERVAL);
+    else
+      *OCRnA = *TCNTn + 4;  // at least REFRESH_INTERVAL has elapsed
+    Channel[timer] = -1; // this will get incremented at the end of the refresh period to start again at the first channel
+  }
+}
+
+#ifndef WIRING // Wiring pre-defines signal handlers so don't define any if compiling for the Wiring platform
+// Interrupt handlers for Arduino
+#if defined(_useTimer1)
+SIGNAL (TIMER1_COMPA_vect)
+{
+  handle_interrupts(_timer1, &TCNT1, &OCR1A);
+}
+#endif
+
+#if defined(_useTimer3)
+SIGNAL (TIMER3_COMPA_vect)
+{
+  handle_interrupts(_timer3, &TCNT3, &OCR3A);
+}
+#endif
+
+#if defined(_useTimer4)
+SIGNAL (TIMER4_COMPA_vect)
+{
+  handle_interrupts(_timer4, &TCNT4, &OCR4A);
+}
+#endif
+
+#if defined(_useTimer5)
+SIGNAL (TIMER5_COMPA_vect)
+{
+  handle_interrupts(_timer5, &TCNT5, &OCR5A);
+}
+#endif
+
+#elif defined WIRING
+// Interrupt handlers for Wiring
+#if defined(_useTimer1)
+void Timer1Service()
+{
+  handle_interrupts(_timer1, &TCNT1, &OCR1A);
+}
+#endif
+#if defined(_useTimer3)
+void Timer3Service()
+{
+  handle_interrupts(_timer3, &TCNT3, &OCR3A);
+}
+#endif
+#endif
+
+
+static void initISR(timer16_Sequence_t timer)
+{
+#if defined (_useTimer1)
+  if(timer == _timer1) {
+    TCCR1A = 0;             // normal counting mode
+    TCCR1B = _BV(CS11);     // set prescaler of 8
+    TCNT1 = 0;              // clear the timer count
+#if defined(__AVR_ATmega8__)|| defined(__AVR_ATmega128__)
+    TIFR |= _BV(OCF1A);      // clear any pending interrupts;
+    TIMSK |=  _BV(OCIE1A) ;  // enable the output compare interrupt
+#else
+    // here if not ATmega8 or ATmega128
+    TIFR1 |= _BV(OCF1A);     // clear any pending interrupts;
+    TIMSK1 |=  _BV(OCIE1A) ; // enable the output compare interrupt
+#endif
+#if defined(WIRING)
+    timerAttach(TIMER1OUTCOMPAREA_INT, Timer1Service);
+#endif
+  }
+#endif
+
+#if defined (_useTimer3)
+  if(timer == _timer3) {
+    TCCR3A = 0;             // normal counting mode
+    TCCR3B = _BV(CS31);     // set prescaler of 8
+    TCNT3 = 0;              // clear the timer count
+#if defined(__AVR_ATmega128__)
+    TIFR |= _BV(OCF3A);     // clear any pending interrupts;
+	ETIMSK |= _BV(OCIE3A);  // enable the output compare interrupt
+#else
+    TIFR3 = _BV(OCF3A);     // clear any pending interrupts;
+    TIMSK3 =  _BV(OCIE3A) ; // enable the output compare interrupt
+#endif
+#if defined(WIRING)
+    timerAttach(TIMER3OUTCOMPAREA_INT, Timer3Service);  // for Wiring platform only
+#endif
+  }
+#endif
+
+#if defined (_useTimer4)
+  if(timer == _timer4) {
+    TCCR4A = 0;             // normal counting mode
+    TCCR4B = _BV(CS41);     // set prescaler of 8
+    TCNT4 = 0;              // clear the timer count
+    TIFR4 = _BV(OCF4A);     // clear any pending interrupts;
+    TIMSK4 =  _BV(OCIE4A) ; // enable the output compare interrupt
+  }
+#endif
+
+#if defined (_useTimer5)
+  if(timer == _timer5) {
+    TCCR5A = 0;             // normal counting mode
+    TCCR5B = _BV(CS51);     // set prescaler of 8
+    TCNT5 = 0;              // clear the timer count
+    TIFR5 = _BV(OCF5A);     // clear any pending interrupts;
+    TIMSK5 =  _BV(OCIE5A) ; // enable the output compare interrupt
+  }
+#endif
+}
+
+static void finISR(timer16_Sequence_t timer)
+{
+    //disable use of the given timer
+#if defined WIRING   // Wiring
+  if(timer == _timer1) {
+    #if defined(__AVR_ATmega1281__)||defined(__AVR_ATmega2561__)
+    TIMSK1 &=  ~_BV(OCIE1A) ;  // disable timer 1 output compare interrupt
+    #else
+    TIMSK &=  ~_BV(OCIE1A) ;  // disable timer 1 output compare interrupt
+    #endif
+    timerDetach(TIMER1OUTCOMPAREA_INT);
+  }
+  else if(timer == _timer3) {
+    #if defined(__AVR_ATmega1281__)||defined(__AVR_ATmega2561__)
+    TIMSK3 &= ~_BV(OCIE3A);    // disable the timer3 output compare A interrupt
+    #else
+    ETIMSK &= ~_BV(OCIE3A);    // disable the timer3 output compare A interrupt
+    #endif
+    timerDetach(TIMER3OUTCOMPAREA_INT);
+  }
+#else
+  //For arduino - in future: call here to a currently undefined function to reset the timer
+  (void) timer;  // squash "unused parameter 'timer' [-Wunused-parameter]" warning
+#endif
+}
+
+static boolean isTimerActive(timer16_Sequence_t timer)
+{
+  // returns true if any servo is active on this timer
+  for(uint8_t channel=0; channel < SERVOS_PER_TIMER; channel++) {
+    if(SERVO(timer,channel).Pin.isActive == true)
+      return true;
+  }
+  return false;
+}
+
+
+/****************** end of static functions ******************************/
+
+Servo::Servo()
+{
+  if( ServoCount < MAX_SERVOS) {
+    this->servoIndex = ServoCount++;                    // assign a servo index to this instance
+	servos[this->servoIndex].ticks = usToTicks(DEFAULT_PULSE_WIDTH);   // store default values  - 12 Aug 2009
+  }
+  else
+    this->servoIndex = INVALID_SERVO ;  // too many servos
+}
+
+uint8_t Servo::attach(int pin)
+{
+  return this->attach(pin, MIN_PULSE_WIDTH, MAX_PULSE_WIDTH);
+}
+
+uint8_t Servo::attach(int pin, int min, int max)
+{
+  if(this->servoIndex < MAX_SERVOS ) {
+    pinMode( pin, OUTPUT) ;                                   // set servo pin to output
+    servos[this->servoIndex].Pin.nbr = pin;
+    // todo min/max check: abs(min - MIN_PULSE_WIDTH) /4 < 128
+    this->min  = (MIN_PULSE_WIDTH - min)/4; //resolution of min/max is 4 uS
+    this->max  = (MAX_PULSE_WIDTH - max)/4;
+    // initialize the timer if it has not already been initialized
+    timer16_Sequence_t timer = SERVO_INDEX_TO_TIMER(servoIndex);
+    if(isTimerActive(timer) == false)
+      initISR(timer);
+    servos[this->servoIndex].Pin.isActive = true;  // this must be set after the check for isTimerActive
+  }
+  return this->servoIndex ;
+}
+
+void Servo::detach()
+{
+  servos[this->servoIndex].Pin.isActive = false;
+  timer16_Sequence_t timer = SERVO_INDEX_TO_TIMER(servoIndex);
+  if(isTimerActive(timer) == false) {
+    finISR(timer);
+  }
+}
+
+void Servo::write(int value)
+{
+  if(value < MIN_PULSE_WIDTH)
+  {  // treat values less than 544 as angles in degrees (valid values in microseconds are handled as microseconds)
+    if(value < 0) value = 0;
+    if(value > 180) value = 180;
+    value = map(value, 0, 180, SERVO_MIN(),  SERVO_MAX());
+  }
+  this->writeMicroseconds(value);
+}
+
+void Servo::writeMicroseconds(int value)
+{
+  // calculate and store the values for the given channel
+  byte channel = this->servoIndex;
+  if( (channel < MAX_SERVOS) )   // ensure channel is valid
+  {
+    if( value < SERVO_MIN() )          // ensure pulse width is valid
+      value = SERVO_MIN();
+    else if( value > SERVO_MAX() )
+      value = SERVO_MAX();
+
+    value = value - TRIM_DURATION;
+    value = usToTicks(value);  // convert to ticks after compensating for interrupt overhead - 12 Aug 2009
+
+    uint8_t oldSREG = SREG;
+    cli();
+    servos[channel].ticks = value;
+    SREG = oldSREG;
+  }
+}
+
+int Servo::read() // return the value as degrees
+{
+  return  map( this->readMicroseconds()+1, SERVO_MIN(), SERVO_MAX(), 0, 180);
+}
+
+int Servo::readMicroseconds()
+{
+  unsigned int pulsewidth;
+  if( this->servoIndex != INVALID_SERVO )
+    pulsewidth = ticksToUs(servos[this->servoIndex].ticks)  + TRIM_DURATION ;   // 12 aug 2009
+  else
+    pulsewidth  = 0;
+
+  return pulsewidth;
+}
+
+bool Servo::attached()
+{
+  return servos[this->servoIndex].Pin.isActive ;
+}
+
+#endif // ARDUINO_ARCH_AVR
+
diff --git a/libraries/Servo/src/avr/ServoTimers.h b/libraries/Servo/src/avr/ServoTimers.h
new file mode 100644
index 000000000..9794c8ef6
--- /dev/null
+++ b/libraries/Servo/src/avr/ServoTimers.h
@@ -0,0 +1,59 @@
+/*
+  Servo.h - Interrupt driven Servo library for Arduino using 16 bit timers- Version 2
+  Copyright (c) 2009 Michael Margolis.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/*
+ * Defines for 16 bit timers used with  Servo library
+ *
+ * If _useTimerX is defined then TimerX is a 16 bit timer on the current board
+ * timer16_Sequence_t enumerates the sequence that the timers should be allocated
+ * _Nbr_16timers indicates how many 16 bit timers are available.
+ */
+
+/**
+ * AVR Only definitions
+ * --------------------
+ */
+
+// Say which 16 bit timers can be used and in what order
+#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
+#define _useTimer5
+#define _useTimer1
+#define _useTimer3
+#define _useTimer4
+typedef enum { _timer5, _timer1, _timer3, _timer4, _Nbr_16timers } timer16_Sequence_t;
+
+#elif defined(__AVR_ATmega32U4__)
+#define _useTimer1
+typedef enum { _timer1, _Nbr_16timers } timer16_Sequence_t;
+
+#elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
+#define _useTimer3
+#define _useTimer1
+typedef enum { _timer3, _timer1, _Nbr_16timers } timer16_Sequence_t;
+
+#elif defined(__AVR_ATmega128__) || defined(__AVR_ATmega1281__) || defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega2561__)
+#define _useTimer3
+#define _useTimer1
+typedef enum { _timer3, _timer1, _Nbr_16timers } timer16_Sequence_t;
+
+#else  // everything else
+#define _useTimer1
+typedef enum { _timer1, _Nbr_16timers } timer16_Sequence_t;
+#endif
+
diff --git a/libraries/Servo/src/megaavr/Servo.cpp b/libraries/Servo/src/megaavr/Servo.cpp
new file mode 100644
index 000000000..daf7596ee
--- /dev/null
+++ b/libraries/Servo/src/megaavr/Servo.cpp
@@ -0,0 +1,211 @@
+#if defined(ARDUINO_ARCH_MEGAAVR)
+
+#include <Arduino.h>
+#include <Servo.h>
+
+#define usToTicks(_us)    ((clockCyclesPerMicrosecond() / 16 * _us) / 4)                 // converts microseconds to tick
+#define ticksToUs(_ticks) (((unsigned) _ticks * 16) / (clockCyclesPerMicrosecond() / 4))   // converts from ticks back to microseconds
+
+#define TRIM_DURATION  5                                   // compensation ticks to trim adjust for digitalWrite delays
+
+static servo_t servos[MAX_SERVOS];                         // static array of servo structures
+
+uint8_t ServoCount = 0;                                    // the total number of attached servos
+
+static volatile int8_t currentServoIndex[_Nbr_16timers];   // index for the servo being pulsed for each timer (or -1 if refresh interval)
+
+// convenience macros
+#define SERVO_INDEX_TO_TIMER(_servo_nbr) ((timer16_Sequence_t)(_servo_nbr / SERVOS_PER_TIMER))   // returns the timer controlling this servo
+#define SERVO_INDEX_TO_CHANNEL(_servo_nbr) (_servo_nbr % SERVOS_PER_TIMER)                       // returns the index of the servo on this timer
+#define SERVO_INDEX(_timer,_channel)  ((_timer*SERVOS_PER_TIMER) + _channel)                     // macro to access servo index by timer and channel
+#define SERVO(_timer,_channel)  (servos[SERVO_INDEX(_timer,_channel)])                           // macro to access servo class by timer and channel
+
+#define SERVO_MIN() (MIN_PULSE_WIDTH - this->min * 4)   // minimum value in uS for this servo
+#define SERVO_MAX() (MAX_PULSE_WIDTH - this->max * 4)   // maximum value in uS for this servo
+
+void ServoHandler(int timer)
+{
+    if (currentServoIndex[timer] < 0) {
+        // Write compare register
+        _timer->CCMP = 0;
+    } else {
+        if (SERVO_INDEX(timer, currentServoIndex[timer]) < ServoCount && SERVO(timer, currentServoIndex[timer]).Pin.isActive == true) {
+            digitalWrite(SERVO(timer, currentServoIndex[timer]).Pin.nbr, LOW);   // pulse this channel low if activated
+        }
+    }
+
+    // Select the next servo controlled by this timer
+    currentServoIndex[timer]++;
+
+    if (SERVO_INDEX(timer, currentServoIndex[timer]) < ServoCount && currentServoIndex[timer] < SERVOS_PER_TIMER) {
+        if (SERVO(timer, currentServoIndex[timer]).Pin.isActive == true) {   // check if activated
+            digitalWrite(SERVO(timer, currentServoIndex[timer]).Pin.nbr, HIGH);   // it's an active channel so pulse it high
+        }
+
+        // Get the counter value
+        uint16_t tcCounterValue =  0; //_timer->CCMP;
+        _timer->CCMP = (uint16_t) (tcCounterValue + SERVO(timer, currentServoIndex[timer]).ticks);
+    }
+    else {
+        // finished all channels so wait for the refresh period to expire before starting over
+
+        // Get the counter value
+        uint16_t tcCounterValue = _timer->CCMP;
+
+        if (tcCounterValue + 4UL < usToTicks(REFRESH_INTERVAL)) {   // allow a few ticks to ensure the next OCR1A not missed
+            _timer->CCMP = (uint16_t) usToTicks(REFRESH_INTERVAL);
+        }
+        else {
+            _timer->CCMP = (uint16_t) (tcCounterValue + 4UL);   // at least REFRESH_INTERVAL has elapsed
+        }
+
+        currentServoIndex[timer] = -1;   // this will get incremented at the end of the refresh period to start again at the first channel
+    }
+
+    /* Clear flag */
+    _timer->INTFLAGS = TCB_CAPT_bm;
+}
+
+#if defined USE_TIMERB0
+ISR(TCB0_INT_vect)
+#elif defined USE_TIMERB1
+ISR(TCB1_INT_vect)
+#elif defined USE_TIMERB2
+ISR(TCB2_INT_vect)
+#endif
+{
+  ServoHandler(0);
+}
+
+static void initISR(timer16_Sequence_t timer)
+{
+  //TCA0.SINGLE.CTRLA = (TCA_SINGLE_CLKSEL_DIV16_gc) | (TCA_SINGLE_ENABLE_bm);
+
+  _timer->CTRLA = TCB_CLKSEL_CLKTCA_gc;
+  // Timer to Periodic interrupt mode
+  // This write will also disable any active PWM outputs
+  _timer->CTRLB = TCB_CNTMODE_INT_gc;
+  // Enable interrupt
+  _timer->INTCTRL = TCB_CAPTEI_bm;
+  // Enable timer
+  _timer->CTRLA |= TCB_ENABLE_bm;
+}
+
+static void finISR(timer16_Sequence_t timer)
+{
+  // Disable interrupt
+  _timer->INTCTRL = 0;
+}
+
+static boolean isTimerActive(timer16_Sequence_t timer)
+{
+  // returns true if any servo is active on this timer
+  for(uint8_t channel=0; channel < SERVOS_PER_TIMER; channel++) {
+    if(SERVO(timer,channel).Pin.isActive == true)
+      return true;
+  }
+  return false;
+}
+
+/****************** end of static functions ******************************/
+
+Servo::Servo()
+{
+  if (ServoCount < MAX_SERVOS) {
+    this->servoIndex = ServoCount++;                    // assign a servo index to this instance
+    servos[this->servoIndex].ticks = usToTicks(DEFAULT_PULSE_WIDTH);   // store default values
+  } else {
+    this->servoIndex = INVALID_SERVO;  // too many servos
+  }
+}
+
+uint8_t Servo::attach(int pin)
+{
+  return this->attach(pin, MIN_PULSE_WIDTH, MAX_PULSE_WIDTH);
+}
+
+uint8_t Servo::attach(int pin, int min, int max)
+{
+  timer16_Sequence_t timer;
+
+  if (this->servoIndex < MAX_SERVOS) {
+    pinMode(pin, OUTPUT);                                   // set servo pin to output
+    servos[this->servoIndex].Pin.nbr = pin;
+    // todo min/max check: abs(min - MIN_PULSE_WIDTH) /4 < 128
+    this->min  = (MIN_PULSE_WIDTH - min)/4; //resolution of min/max is 4 uS
+    this->max  = (MAX_PULSE_WIDTH - max)/4;
+    // initialize the timer if it has not already been initialized
+    timer = SERVO_INDEX_TO_TIMER(servoIndex);
+    if (isTimerActive(timer) == false) {
+      initISR(timer);
+    }
+    servos[this->servoIndex].Pin.isActive = true;  // this must be set after the check for isTimerActive
+  }
+  return this->servoIndex;
+}
+
+void Servo::detach()
+{
+  timer16_Sequence_t timer;
+
+  servos[this->servoIndex].Pin.isActive = false;
+  timer = SERVO_INDEX_TO_TIMER(servoIndex);
+  if(isTimerActive(timer) == false) {
+    finISR(timer);
+  }
+}
+
+void Servo::write(int value)
+{
+  // treat values less than 544 as angles in degrees (valid values in microseconds are handled as microseconds)
+  if (value < MIN_PULSE_WIDTH)
+  {
+    if (value < 0)
+      value = 0;
+    else if (value > 180)
+      value = 180;
+
+    value = map(value, 0, 180, SERVO_MIN(), SERVO_MAX());
+  }
+  writeMicroseconds(value);
+}
+
+void Servo::writeMicroseconds(int value)
+{
+  // calculate and store the values for the given channel
+  byte channel = this->servoIndex;
+  if( (channel < MAX_SERVOS) )   // ensure channel is valid
+  {
+    if (value < SERVO_MIN())          // ensure pulse width is valid
+      value = SERVO_MIN();
+    else if (value > SERVO_MAX())
+      value = SERVO_MAX();
+
+    value = value - TRIM_DURATION;
+    value = usToTicks(value);  // convert to ticks after compensating for interrupt overhead
+    servos[channel].ticks = value;
+  }
+}
+
+int Servo::read() // return the value as degrees
+{
+  return map(readMicroseconds()+1, SERVO_MIN(), SERVO_MAX(), 0, 180);
+}
+
+int Servo::readMicroseconds()
+{
+  unsigned int pulsewidth;
+  if (this->servoIndex != INVALID_SERVO)
+    pulsewidth = ticksToUs(servos[this->servoIndex].ticks)  + TRIM_DURATION;
+  else
+    pulsewidth  = 0;
+
+  return pulsewidth;
+}
+
+bool Servo::attached()
+{
+  return servos[this->servoIndex].Pin.isActive;
+}
+
+#endif
\ No newline at end of file
diff --git a/libraries/Servo/src/megaavr/ServoTimers.h b/libraries/Servo/src/megaavr/ServoTimers.h
new file mode 100644
index 000000000..62702b4f9
--- /dev/null
+++ b/libraries/Servo/src/megaavr/ServoTimers.h
@@ -0,0 +1,54 @@
+/*
+  Copyright (c) 2018 Arduino LLC. All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+/*
+ * Defines for 16 bit timers used with Servo library
+ *
+ */
+
+#ifndef __SERVO_TIMERS_H__
+#define __SERVO_TIMERS_H__
+
+#include <avr/io.h>
+
+#define USE_TIMERB1        // interferes with PWM on pin 3
+//#define USE_TIMERB2        // interferes with PWM on pin 11
+//#define USE_TIMERB0        // interferes with PWM on pin 6
+
+#if !defined(USE_TIMERB1) && !defined(USE_TIMERB2) && !defined(USE_TIMERB0)
+    # error "No timers allowed for Servo"
+    /* Please uncomment a timer above and rebuild */
+#endif
+
+static volatile TCB_t* _timer =
+#if defined(USE_TIMERB0)
+&TCB0;
+#endif
+#if defined(USE_TIMERB1)
+&TCB1;
+#endif
+#if defined(USE_TIMERB2)
+&TCB2;
+#endif
+
+typedef enum {
+    timer0,
+    _Nbr_16timers } timer16_Sequence_t;
+
+
+#endif  /* __SERVO_TIMERS_H__ */
diff --git a/libraries/Servo/src/nrf52/Servo.cpp b/libraries/Servo/src/nrf52/Servo.cpp
new file mode 100644
index 000000000..a49f09342
--- /dev/null
+++ b/libraries/Servo/src/nrf52/Servo.cpp
@@ -0,0 +1,134 @@
+/*
+  Copyright (c) 2016 Arduino. All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#if defined(ARDUINO_ARCH_NRF52)
+
+#include <Arduino.h>
+#include <Servo.h>
+
+
+static servo_t servos[MAX_SERVOS];                          // static array of servo structures
+
+uint8_t ServoCount = 0;                                     // the total number of attached servos
+
+
+
+uint32_t group_pins[3][NRF_PWM_CHANNEL_COUNT]={{NRF_PWM_PIN_NOT_CONNECTED, NRF_PWM_PIN_NOT_CONNECTED, NRF_PWM_PIN_NOT_CONNECTED, NRF_PWM_PIN_NOT_CONNECTED}, {NRF_PWM_PIN_NOT_CONNECTED, NRF_PWM_PIN_NOT_CONNECTED, NRF_PWM_PIN_NOT_CONNECTED, NRF_PWM_PIN_NOT_CONNECTED}, {NRF_PWM_PIN_NOT_CONNECTED, NRF_PWM_PIN_NOT_CONNECTED, NRF_PWM_PIN_NOT_CONNECTED, NRF_PWM_PIN_NOT_CONNECTED}};
+static uint16_t seq_values[3][NRF_PWM_CHANNEL_COUNT]={{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}};
+
+Servo::Servo()
+{
+  if (ServoCount < MAX_SERVOS) {
+    this->servoIndex = ServoCount++;                    // assign a servo index to this instance
+  } else {                                                 
+    this->servoIndex = INVALID_SERVO;  					// too many servos
+  }
+
+}
+
+uint8_t Servo::attach(int pin)
+{
+	
+	return this->attach(pin, 0, 2500);
+}
+
+
+uint8_t Servo::attach(int pin, int min, int max)
+{
+  int servo_min, servo_max;
+  if (this->servoIndex < MAX_SERVOS) {
+    pinMode(pin, OUTPUT);                                   // set servo pin to output
+    servos[this->servoIndex].Pin.nbr = pin;
+
+	if(min < servo_min) min = servo_min;
+	if (max > servo_max) max = servo_max;
+	this->min  = min;
+    this->max  = max;
+	
+	servos[this->servoIndex].Pin.isActive = true;
+	
+  }
+  return this->servoIndex;
+}
+
+void Servo::detach()
+{
+	servos[this->servoIndex].Pin.isActive = false;
+}
+
+
+void Servo::write(int value)
+{  
+	if (value < 0)
+		value = 0;
+	else if (value > 180)
+		value = 180;
+	value = map(value, 0, 180, MIN_PULSE, MAX_PULSE);
+	
+	writeMicroseconds(value);
+}
+
+
+void Servo::writeMicroseconds(int value)
+{
+	uint8_t channel, instance;
+	uint8_t pin = servos[this->servoIndex].Pin.nbr;
+	//instance of pwm module is MSB - look at VWariant.h
+	instance=(g_APinDescription[pin].ulPWMChannel & 0xF0)/16;
+	//index of pwm channel is LSB - look at VWariant.h
+	channel=g_APinDescription[pin].ulPWMChannel & 0x0F;
+	group_pins[instance][channel]=g_APinDescription[pin].ulPin;
+	NRF_PWM_Type * PWMInstance = instance == 0 ? NRF_PWM0 : (instance == 1 ? NRF_PWM1 : NRF_PWM2);
+	//configure pwm instance and enable it
+	seq_values[instance][channel]= value | 0x8000;
+	nrf_pwm_sequence_t const seq={
+								seq_values[instance],
+								NRF_PWM_VALUES_LENGTH(seq_values),
+								0,
+								0
+    };
+	nrf_pwm_pins_set(PWMInstance, group_pins[instance]);
+	nrf_pwm_enable(PWMInstance);
+	nrf_pwm_configure(PWMInstance, NRF_PWM_CLK_125kHz, NRF_PWM_MODE_UP, 2500);	// 20ms - 50Hz
+	nrf_pwm_decoder_set(PWMInstance, NRF_PWM_LOAD_INDIVIDUAL, NRF_PWM_STEP_AUTO);
+	nrf_pwm_sequence_set(PWMInstance, 0, &seq);
+	nrf_pwm_loop_set(PWMInstance, 0UL);
+	nrf_pwm_task_trigger(PWMInstance, NRF_PWM_TASK_SEQSTART0);
+}
+
+int Servo::read() // return the value as degrees
+{
+	return map(readMicroseconds(), MIN_PULSE, MAX_PULSE, 0, 180);
+}
+
+int Servo::readMicroseconds()
+{	
+	uint8_t channel, instance;
+	uint8_t pin=servos[this->servoIndex].Pin.nbr;
+	instance=(g_APinDescription[pin].ulPWMChannel & 0xF0)/16;
+	channel=g_APinDescription[pin].ulPWMChannel & 0x0F;
+	// remove the 16th bit we added before
+	return seq_values[instance][channel] & 0x7FFF;
+}
+
+bool Servo::attached()
+{
+  return servos[this->servoIndex].Pin.isActive;
+}
+
+#endif // ARDUINO_ARCH_NRF52
\ No newline at end of file
diff --git a/libraries/Servo/src/nrf52/ServoTimers.h b/libraries/Servo/src/nrf52/ServoTimers.h
new file mode 100644
index 000000000..51759beab
--- /dev/null
+++ b/libraries/Servo/src/nrf52/ServoTimers.h
@@ -0,0 +1,38 @@
+/*
+  Copyright (c) 2016 Arduino. All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+/*
+ * NRF52 doesn't use timer, but pwm. This file include definitions to keep
+ * compatibility with the Servo library standards.
+ */
+
+#ifndef __SERVO_TIMERS_H__
+#define __SERVO_TIMERS_H__
+
+/**
+ * NRF52 Only definitions
+ * ---------------------
+ */
+
+#define MIN_PULSE 55
+#define MAX_PULSE 284
+
+// define one timer in order to have MAX_SERVOS = 12
+typedef enum { _timer1, _Nbr_16timers } timer16_Sequence_t;
+
+#endif   // __SERVO_TIMERS_H__
\ No newline at end of file
diff --git a/libraries/Servo/src/sam/Servo.cpp b/libraries/Servo/src/sam/Servo.cpp
new file mode 100644
index 000000000..21f901f0e
--- /dev/null
+++ b/libraries/Servo/src/sam/Servo.cpp
@@ -0,0 +1,283 @@
+/*
+  Copyright (c) 2013 Arduino LLC. All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#if defined(ARDUINO_ARCH_SAM)
+
+#include <Arduino.h>
+#include <Servo.h>
+
+#define usToTicks(_us)    (( clockCyclesPerMicrosecond() * _us) / 32)     // converts microseconds to tick
+#define ticksToUs(_ticks) (( (unsigned)_ticks * 32)/ clockCyclesPerMicrosecond() ) // converts from ticks back to microseconds
+
+#define TRIM_DURATION       2                               // compensation ticks to trim adjust for digitalWrite delays
+
+static servo_t servos[MAX_SERVOS];                          // static array of servo structures
+
+uint8_t ServoCount = 0;                                     // the total number of attached servos
+
+static volatile int8_t Channel[_Nbr_16timers ];             // counter for the servo being pulsed for each timer (or -1 if refresh interval)
+
+// convenience macros
+#define SERVO_INDEX_TO_TIMER(_servo_nbr) ((timer16_Sequence_t)(_servo_nbr / SERVOS_PER_TIMER)) // returns the timer controlling this servo
+#define SERVO_INDEX_TO_CHANNEL(_servo_nbr) (_servo_nbr % SERVOS_PER_TIMER)       // returns the index of the servo on this timer
+#define SERVO_INDEX(_timer,_channel)  ((_timer*SERVOS_PER_TIMER) + _channel)     // macro to access servo index by timer and channel
+#define SERVO(_timer,_channel)  (servos[SERVO_INDEX(_timer,_channel)])            // macro to access servo class by timer and channel
+
+#define SERVO_MIN() (MIN_PULSE_WIDTH - this->min * 4)  // minimum value in uS for this servo
+#define SERVO_MAX() (MAX_PULSE_WIDTH - this->max * 4)  // maximum value in uS for this servo
+
+/************ static functions common to all instances ***********************/
+
+//------------------------------------------------------------------------------
+/// Interrupt handler for the TC0 channel 1.
+//------------------------------------------------------------------------------
+void Servo_Handler(timer16_Sequence_t timer, Tc *pTc, uint8_t channel);
+#if defined (_useTimer1)
+void HANDLER_FOR_TIMER1(void) {
+    Servo_Handler(_timer1, TC_FOR_TIMER1, CHANNEL_FOR_TIMER1);
+}
+#endif
+#if defined (_useTimer2)
+void HANDLER_FOR_TIMER2(void) {
+    Servo_Handler(_timer2, TC_FOR_TIMER2, CHANNEL_FOR_TIMER2);
+}
+#endif
+#if defined (_useTimer3)
+void HANDLER_FOR_TIMER3(void) {
+    Servo_Handler(_timer3, TC_FOR_TIMER3, CHANNEL_FOR_TIMER3);
+}
+#endif
+#if defined (_useTimer4)
+void HANDLER_FOR_TIMER4(void) {
+    Servo_Handler(_timer4, TC_FOR_TIMER4, CHANNEL_FOR_TIMER4);
+}
+#endif
+#if defined (_useTimer5)
+void HANDLER_FOR_TIMER5(void) {
+    Servo_Handler(_timer5, TC_FOR_TIMER5, CHANNEL_FOR_TIMER5);
+}
+#endif
+
+void Servo_Handler(timer16_Sequence_t timer, Tc *tc, uint8_t channel)
+{
+    // clear interrupt
+    tc->TC_CHANNEL[channel].TC_SR;
+    if (Channel[timer] < 0) {
+        tc->TC_CHANNEL[channel].TC_CCR |= TC_CCR_SWTRG; // channel set to -1 indicated that refresh interval completed so reset the timer
+    } else {
+        if (SERVO_INDEX(timer,Channel[timer]) < ServoCount && SERVO(timer,Channel[timer]).Pin.isActive == true) {
+            digitalWrite(SERVO(timer,Channel[timer]).Pin.nbr, LOW); // pulse this channel low if activated
+        }
+    }
+
+    Channel[timer]++;    // increment to the next channel
+    if( SERVO_INDEX(timer,Channel[timer]) < ServoCount && Channel[timer] < SERVOS_PER_TIMER) {
+        tc->TC_CHANNEL[channel].TC_RA = tc->TC_CHANNEL[channel].TC_CV + SERVO(timer,Channel[timer]).ticks;
+        if(SERVO(timer,Channel[timer]).Pin.isActive == true) {    // check if activated
+            digitalWrite( SERVO(timer,Channel[timer]).Pin.nbr,HIGH); // its an active channel so pulse it high
+        }
+    }
+    else {
+        // finished all channels so wait for the refresh period to expire before starting over
+        if( (tc->TC_CHANNEL[channel].TC_CV) + 4 < usToTicks(REFRESH_INTERVAL) ) { // allow a few ticks to ensure the next OCR1A not missed
+            tc->TC_CHANNEL[channel].TC_RA = (unsigned int)usToTicks(REFRESH_INTERVAL);
+        }
+        else {
+            tc->TC_CHANNEL[channel].TC_RA = tc->TC_CHANNEL[channel].TC_CV + 4;  // at least REFRESH_INTERVAL has elapsed
+        }
+        Channel[timer] = -1; // this will get incremented at the end of the refresh period to start again at the first channel
+    }
+}
+
+static void _initISR(Tc *tc, uint32_t channel, uint32_t id, IRQn_Type irqn)
+{
+    pmc_enable_periph_clk(id);
+    TC_Configure(tc, channel,
+   TC_CMR_TCCLKS_TIMER_CLOCK3 | // MCK/32
+            TC_CMR_WAVE |                // Waveform mode
+            TC_CMR_WAVSEL_UP_RC );       // Counter running up and reset when equals to RC
+
+    /* 84MHz, MCK/32, for 1.5ms: 3937 */
+    TC_SetRA(tc, channel, 2625); // 1ms
+
+    /* Configure and enable interrupt */
+    NVIC_EnableIRQ(irqn);
+    // TC_IER_CPAS: RA Compare
+    tc->TC_CHANNEL[channel].TC_IER = TC_IER_CPAS;
+
+    // Enables the timer clock and performs a software reset to start the counting
+    TC_Start(tc, channel);
+}
+
+static void initISR(timer16_Sequence_t timer)
+{
+#if defined (_useTimer1)
+    if (timer == _timer1)
+        _initISR(TC_FOR_TIMER1, CHANNEL_FOR_TIMER1, ID_TC_FOR_TIMER1, IRQn_FOR_TIMER1);
+#endif
+#if defined (_useTimer2)
+    if (timer == _timer2)
+        _initISR(TC_FOR_TIMER2, CHANNEL_FOR_TIMER2, ID_TC_FOR_TIMER2, IRQn_FOR_TIMER2);
+#endif
+#if defined (_useTimer3)
+    if (timer == _timer3)
+        _initISR(TC_FOR_TIMER3, CHANNEL_FOR_TIMER3, ID_TC_FOR_TIMER3, IRQn_FOR_TIMER3);
+#endif
+#if defined (_useTimer4)
+    if (timer == _timer4)
+        _initISR(TC_FOR_TIMER4, CHANNEL_FOR_TIMER4, ID_TC_FOR_TIMER4, IRQn_FOR_TIMER4);
+#endif
+#if defined (_useTimer5)
+    if (timer == _timer5)
+        _initISR(TC_FOR_TIMER5, CHANNEL_FOR_TIMER5, ID_TC_FOR_TIMER5, IRQn_FOR_TIMER5);
+#endif
+}
+
+static void finISR(timer16_Sequence_t timer)
+{
+#if defined (_useTimer1)
+    TC_Stop(TC_FOR_TIMER1, CHANNEL_FOR_TIMER1);
+#endif
+#if defined (_useTimer2)
+    TC_Stop(TC_FOR_TIMER2, CHANNEL_FOR_TIMER2);
+#endif
+#if defined (_useTimer3)
+    TC_Stop(TC_FOR_TIMER3, CHANNEL_FOR_TIMER3);
+#endif
+#if defined (_useTimer4)
+    TC_Stop(TC_FOR_TIMER4, CHANNEL_FOR_TIMER4);
+#endif
+#if defined (_useTimer5)
+    TC_Stop(TC_FOR_TIMER5, CHANNEL_FOR_TIMER5);
+#endif
+}
+
+
+static boolean isTimerActive(timer16_Sequence_t timer)
+{
+  // returns true if any servo is active on this timer
+  for(uint8_t channel=0; channel < SERVOS_PER_TIMER; channel++) {
+    if(SERVO(timer,channel).Pin.isActive == true)
+      return true;
+  }
+  return false;
+}
+
+/****************** end of static functions ******************************/
+
+Servo::Servo()
+{
+  if (ServoCount < MAX_SERVOS) {
+    this->servoIndex = ServoCount++;                    // assign a servo index to this instance
+    servos[this->servoIndex].ticks = usToTicks(DEFAULT_PULSE_WIDTH);   // store default values
+  } else {
+    this->servoIndex = INVALID_SERVO;  // too many servos
+  }
+}
+
+uint8_t Servo::attach(int pin)
+{
+  return this->attach(pin, MIN_PULSE_WIDTH, MAX_PULSE_WIDTH);
+}
+
+uint8_t Servo::attach(int pin, int min, int max)
+{
+  timer16_Sequence_t timer;
+
+  if (this->servoIndex < MAX_SERVOS) {
+    pinMode(pin, OUTPUT);                                   // set servo pin to output
+    servos[this->servoIndex].Pin.nbr = pin;
+    // todo min/max check: abs(min - MIN_PULSE_WIDTH) /4 < 128
+    this->min  = (MIN_PULSE_WIDTH - min)/4; //resolution of min/max is 4 uS
+    this->max  = (MAX_PULSE_WIDTH - max)/4;
+    // initialize the timer if it has not already been initialized
+    timer = SERVO_INDEX_TO_TIMER(servoIndex);
+    if (isTimerActive(timer) == false) {
+      initISR(timer);
+    }
+    servos[this->servoIndex].Pin.isActive = true;  // this must be set after the check for isTimerActive
+  }
+  return this->servoIndex;
+}
+
+void Servo::detach()
+{
+  timer16_Sequence_t timer;
+
+  servos[this->servoIndex].Pin.isActive = false;
+  timer = SERVO_INDEX_TO_TIMER(servoIndex);
+  if(isTimerActive(timer) == false) {
+    finISR(timer);
+  }
+}
+
+void Servo::write(int value)
+{
+  // treat values less than 544 as angles in degrees (valid values in microseconds are handled as microseconds)
+  if (value < MIN_PULSE_WIDTH)
+  {
+    if (value < 0)
+      value = 0;
+    else if (value > 180)
+      value = 180;
+
+    value = map(value, 0, 180, SERVO_MIN(), SERVO_MAX());
+  }
+  writeMicroseconds(value);
+}
+
+void Servo::writeMicroseconds(int value)
+{
+  // calculate and store the values for the given channel
+  byte channel = this->servoIndex;
+  if( (channel < MAX_SERVOS) )   // ensure channel is valid
+  {
+    if (value < SERVO_MIN())          // ensure pulse width is valid
+      value = SERVO_MIN();
+    else if (value > SERVO_MAX())
+      value = SERVO_MAX();
+
+    value = value - TRIM_DURATION;
+    value = usToTicks(value);  // convert to ticks after compensating for interrupt overhead
+    servos[channel].ticks = value;
+  }
+}
+
+int Servo::read() // return the value as degrees
+{
+  return map(readMicroseconds()+1, SERVO_MIN(), SERVO_MAX(), 0, 180);
+}
+
+int Servo::readMicroseconds()
+{
+  unsigned int pulsewidth;
+  if (this->servoIndex != INVALID_SERVO)
+    pulsewidth = ticksToUs(servos[this->servoIndex].ticks)  + TRIM_DURATION;
+  else
+    pulsewidth  = 0;
+
+  return pulsewidth;
+}
+
+bool Servo::attached()
+{
+  return servos[this->servoIndex].Pin.isActive;
+}
+
+#endif // ARDUINO_ARCH_SAM
+
diff --git a/libraries/Servo/src/sam/ServoTimers.h b/libraries/Servo/src/sam/ServoTimers.h
new file mode 100644
index 000000000..13f736a19
--- /dev/null
+++ b/libraries/Servo/src/sam/ServoTimers.h
@@ -0,0 +1,88 @@
+/*
+  Copyright (c) 2013 Arduino LLC. All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+/*
+ * Defines for 16 bit timers used with  Servo library
+ *
+ * If _useTimerX is defined then TimerX is a 16 bit timer on the current board
+ * timer16_Sequence_t enumerates the sequence that the timers should be allocated
+ * _Nbr_16timers indicates how many 16 bit timers are available.
+ */
+
+/**
+ * SAM Only definitions
+ * --------------------
+ */
+
+// For SAM3X:
+#define _useTimer1
+#define _useTimer2
+#define _useTimer3
+#define _useTimer4
+#define _useTimer5
+
+/*
+  TC0, chan 0 => TC0_Handler
+  TC0, chan 1 => TC1_Handler
+  TC0, chan 2 => TC2_Handler
+  TC1, chan 0 => TC3_Handler
+  TC1, chan 1 => TC4_Handler
+  TC1, chan 2 => TC5_Handler
+  TC2, chan 0 => TC6_Handler
+  TC2, chan 1 => TC7_Handler
+  TC2, chan 2 => TC8_Handler
+ */
+
+#if defined (_useTimer1)
+#define TC_FOR_TIMER1       TC1
+#define CHANNEL_FOR_TIMER1  0
+#define ID_TC_FOR_TIMER1    ID_TC3
+#define IRQn_FOR_TIMER1     TC3_IRQn
+#define HANDLER_FOR_TIMER1  TC3_Handler
+#endif
+#if defined (_useTimer2)
+#define TC_FOR_TIMER2       TC1
+#define CHANNEL_FOR_TIMER2  1
+#define ID_TC_FOR_TIMER2    ID_TC4
+#define IRQn_FOR_TIMER2     TC4_IRQn
+#define HANDLER_FOR_TIMER2  TC4_Handler
+#endif
+#if defined (_useTimer3)
+#define TC_FOR_TIMER3       TC1
+#define CHANNEL_FOR_TIMER3  2
+#define ID_TC_FOR_TIMER3    ID_TC5
+#define IRQn_FOR_TIMER3     TC5_IRQn
+#define HANDLER_FOR_TIMER3  TC5_Handler
+#endif
+#if defined (_useTimer4)
+#define TC_FOR_TIMER4       TC0
+#define CHANNEL_FOR_TIMER4  2
+#define ID_TC_FOR_TIMER4    ID_TC2
+#define IRQn_FOR_TIMER4     TC2_IRQn
+#define HANDLER_FOR_TIMER4  TC2_Handler
+#endif
+#if defined (_useTimer5)
+#define TC_FOR_TIMER5       TC0
+#define CHANNEL_FOR_TIMER5  0
+#define ID_TC_FOR_TIMER5    ID_TC0
+#define IRQn_FOR_TIMER5     TC0_IRQn
+#define HANDLER_FOR_TIMER5  TC0_Handler
+#endif
+
+typedef enum { _timer1, _timer2, _timer3, _timer4, _timer5, _Nbr_16timers } timer16_Sequence_t ;
+
diff --git a/libraries/Servo/src/samd/Servo.cpp b/libraries/Servo/src/samd/Servo.cpp
new file mode 100644
index 000000000..9f06e9ec5
--- /dev/null
+++ b/libraries/Servo/src/samd/Servo.cpp
@@ -0,0 +1,391 @@
+/*
+  Copyright (c) 2015 Arduino LLC. All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#if defined(ARDUINO_ARCH_SAMD)
+
+#include <Arduino.h>
+#include <Servo.h>
+
+#if defined(__SAMD51__)
+ // Different prescalers depending on FCPU (avoid overflowing 16-bit counter)
+ #if(F_CPU > 200000000)
+  #define usToTicks(_us)    ((clockCyclesPerMicrosecond() * _us) / 128)
+  #define ticksToUs(_ticks) (((unsigned) _ticks * 128) / clockCyclesPerMicrosecond())
+ #else
+  #define usToTicks(_us)    ((clockCyclesPerMicrosecond() * _us) / 64)
+  #define ticksToUs(_ticks) (((unsigned) _ticks * 64) / clockCyclesPerMicrosecond())
+ #endif
+#else
+ #define usToTicks(_us)    ((clockCyclesPerMicrosecond() * _us) / 16)                 // converts microseconds to tick
+ #define ticksToUs(_ticks) (((unsigned) _ticks * 16) / clockCyclesPerMicrosecond())   // converts from ticks back to microseconds
+#endif
+
+#define TRIM_DURATION  5                                   // compensation ticks to trim adjust for digitalWrite delays
+
+static servo_t servos[MAX_SERVOS];                         // static array of servo structures
+
+uint8_t ServoCount = 0;                                    // the total number of attached servos
+
+static volatile int8_t currentServoIndex[_Nbr_16timers];   // index for the servo being pulsed for each timer (or -1 if refresh interval)
+
+// convenience macros
+#define SERVO_INDEX_TO_TIMER(_servo_nbr) ((timer16_Sequence_t)(_servo_nbr / SERVOS_PER_TIMER))   // returns the timer controlling this servo
+#define SERVO_INDEX_TO_CHANNEL(_servo_nbr) (_servo_nbr % SERVOS_PER_TIMER)                       // returns the index of the servo on this timer
+#define SERVO_INDEX(_timer,_channel)  ((_timer*SERVOS_PER_TIMER) + _channel)                     // macro to access servo index by timer and channel
+#define SERVO(_timer,_channel)  (servos[SERVO_INDEX(_timer,_channel)])                           // macro to access servo class by timer and channel
+
+#define SERVO_MIN() (MIN_PULSE_WIDTH - this->min * 4)   // minimum value in uS for this servo
+#define SERVO_MAX() (MAX_PULSE_WIDTH - this->max * 4)   // maximum value in uS for this servo
+
+// Referenced in SAMD21 code only, no harm in defining regardless
+#define WAIT_TC16_REGS_SYNC(x) while(x->COUNT16.STATUS.bit.SYNCBUSY);
+
+/************ static functions common to all instances ***********************/
+
+void Servo_Handler(timer16_Sequence_t timer, Tc *pTc, uint8_t channel, uint8_t intFlag);
+#if defined (_useTimer1)
+void HANDLER_FOR_TIMER1(void) {
+    Servo_Handler(_timer1, TC_FOR_TIMER1, CHANNEL_FOR_TIMER1, INTFLAG_BIT_FOR_TIMER_1);
+}
+#endif
+#if defined (_useTimer2)
+void HANDLER_FOR_TIMER2(void) {
+    Servo_Handler(_timer2, TC_FOR_TIMER2, CHANNEL_FOR_TIMER2, INTFLAG_BIT_FOR_TIMER_2);
+}
+#endif
+
+void Servo_Handler(timer16_Sequence_t timer, Tc *tc, uint8_t channel, uint8_t intFlag)
+{
+    if (currentServoIndex[timer] < 0) {
+        tc->COUNT16.COUNT.reg = (uint16_t) 0;
+#if defined(__SAMD51__)
+        while(tc->COUNT16.SYNCBUSY.bit.COUNT);
+#else
+        WAIT_TC16_REGS_SYNC(tc)
+#endif
+    } else {
+        if (SERVO_INDEX(timer, currentServoIndex[timer]) < ServoCount && SERVO(timer, currentServoIndex[timer]).Pin.isActive == true) {
+            digitalWrite(SERVO(timer, currentServoIndex[timer]).Pin.nbr, LOW);   // pulse this channel low if activated
+        }
+    }
+
+    // Select the next servo controlled by this timer
+    currentServoIndex[timer]++;
+
+    if (SERVO_INDEX(timer, currentServoIndex[timer]) < ServoCount && currentServoIndex[timer] < SERVOS_PER_TIMER) {
+        if (SERVO(timer, currentServoIndex[timer]).Pin.isActive == true) {   // check if activated
+            digitalWrite(SERVO(timer, currentServoIndex[timer]).Pin.nbr, HIGH);   // it's an active channel so pulse it high
+        }
+
+        // Get the counter value
+#if defined(__SAMD51__)
+        // Note from datasheet: Prior to any read access, this register must be synchronized by user by writing the according TC
+        // Command value to the Control B Set register (CTRLBSET.CMD=READSYNC)
+        while (tc->COUNT16.SYNCBUSY.bit.CTRLB);
+	tc->COUNT16.CTRLBSET.bit.CMD = TC_CTRLBSET_CMD_READSYNC_Val;
+        while (tc->COUNT16.SYNCBUSY.bit.CTRLB);
+#endif
+        uint16_t tcCounterValue = tc->COUNT16.COUNT.reg;
+#if defined(__SAMD51__)
+        while(tc->COUNT16.SYNCBUSY.bit.COUNT);
+#else
+        WAIT_TC16_REGS_SYNC(tc)
+#endif
+
+        tc->COUNT16.CC[channel].reg = (uint16_t) (tcCounterValue + SERVO(timer, currentServoIndex[timer]).ticks);
+#if defined(__SAMD51__)
+        if(channel == 0) {
+            while(tc->COUNT16.SYNCBUSY.bit.CC0);
+        } else if(channel == 1) {
+            while(tc->COUNT16.SYNCBUSY.bit.CC1);
+        }
+#else
+        WAIT_TC16_REGS_SYNC(tc)
+#endif
+    }
+    else {
+        // finished all channels so wait for the refresh period to expire before starting over
+
+        // Get the counter value
+        uint16_t tcCounterValue = tc->COUNT16.COUNT.reg;
+#if defined(__SAMD51__)
+        while(tc->COUNT16.SYNCBUSY.bit.COUNT);
+#else
+        WAIT_TC16_REGS_SYNC(tc)
+#endif
+
+        if (tcCounterValue + 4UL < usToTicks(REFRESH_INTERVAL)) {   // allow a few ticks to ensure the next OCR1A not missed
+            tc->COUNT16.CC[channel].reg = (uint16_t) usToTicks(REFRESH_INTERVAL);
+        }
+        else {
+            tc->COUNT16.CC[channel].reg = (uint16_t) (tcCounterValue + 4UL);   // at least REFRESH_INTERVAL has elapsed
+        }
+#if defined(__SAMD51__)
+        if(channel == 0) {
+            while(tc->COUNT16.SYNCBUSY.bit.CC0);
+        } else if(channel == 1) {
+            while(tc->COUNT16.SYNCBUSY.bit.CC1);
+        }
+#else
+        WAIT_TC16_REGS_SYNC(tc)
+#endif
+
+        currentServoIndex[timer] = -1;   // this will get incremented at the end of the refresh period to start again at the first channel
+    }
+
+    // Clear the interrupt
+    tc->COUNT16.INTFLAG.reg = intFlag;
+}
+
+static inline void resetTC (Tc* TCx)
+{
+    // Disable TCx
+    TCx->COUNT16.CTRLA.reg &= ~TC_CTRLA_ENABLE;
+#if defined(__SAMD51__)
+    while(TCx->COUNT16.SYNCBUSY.bit.ENABLE);
+#else
+    WAIT_TC16_REGS_SYNC(TCx)
+#endif
+
+    // Reset TCx
+    TCx->COUNT16.CTRLA.reg = TC_CTRLA_SWRST;
+#if defined(__SAMD51__)
+    while(TCx->COUNT16.SYNCBUSY.bit.SWRST);
+#else
+    WAIT_TC16_REGS_SYNC(TCx)
+#endif
+    while (TCx->COUNT16.CTRLA.bit.SWRST);
+}
+
+static void _initISR(Tc *tc, uint8_t channel, uint32_t id, IRQn_Type irqn, uint8_t gcmForTimer, uint8_t intEnableBit)
+{
+    (void)id;
+    // Select GCLK0 as timer/counter input clock source
+#if defined(__SAMD51__)
+    int idx = gcmForTimer;           // see datasheet Table 14-9
+    GCLK->PCHCTRL[idx].bit.GEN  = 0; // Select GCLK0 as periph clock source
+    GCLK->PCHCTRL[idx].bit.CHEN = 1; // Enable peripheral
+    while(!GCLK->PCHCTRL[idx].bit.CHEN);
+#else
+    GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID(gcmForTimer));
+    while (GCLK->STATUS.bit.SYNCBUSY);
+#endif
+
+    // Reset the timer
+    // TODO this is not the right thing to do if more than one channel per timer is used by the Servo library
+    resetTC(tc);
+
+    // Set timer counter mode to 16 bits
+    tc->COUNT16.CTRLA.reg |= TC_CTRLA_MODE_COUNT16;
+
+#if defined(__SAMD51__)
+    // Set timer counter mode as normal PWM
+    tc->COUNT16.WAVE.bit.WAVEGEN = TCC_WAVE_WAVEGEN_NPWM_Val;
+
+    // Set the prescaler factor to 64 or 128 depending on FCPU
+    // (avoid overflowing 16-bit clock counter)
+ #if(F_CPU > 200000000)
+    tc->COUNT16.CTRLA.bit.PRESCALER = TCC_CTRLA_PRESCALER_DIV128_Val;
+ #else
+    // At 120-200 MHz GCLK this is 1875-3125 ticks per millisecond
+    tc->COUNT16.CTRLA.bit.PRESCALER = TCC_CTRLA_PRESCALER_DIV64_Val;
+ #endif
+#else
+    // Set timer counter mode as normal PWM
+    tc->COUNT16.CTRLA.reg |= TC_CTRLA_WAVEGEN_NPWM;
+
+    // Set the prescaler factor to GCLK_TC/16.  At nominal 48MHz GCLK_TC this is 3000 ticks per millisecond
+    tc->COUNT16.CTRLA.reg |= TC_CTRLA_PRESCALER_DIV16;
+#endif
+
+    // Count up
+    tc->COUNT16.CTRLBCLR.bit.DIR = 1;
+#if defined(__SAMD51__)
+    while(tc->COUNT16.SYNCBUSY.bit.CTRLB);
+#else
+    WAIT_TC16_REGS_SYNC(tc)
+#endif
+
+    // First interrupt request after 1 ms
+    tc->COUNT16.CC[channel].reg = (uint16_t) usToTicks(1000UL);
+#if defined(__SAMD51__)
+    if(channel == 0) {
+        while(tc->COUNT16.SYNCBUSY.bit.CC0);
+    } else if(channel == 1) {
+        while(tc->COUNT16.SYNCBUSY.bit.CC1);
+    }
+#else
+    WAIT_TC16_REGS_SYNC(tc)
+#endif
+
+    // Configure interrupt request
+    // TODO this should be changed if more than one channel per timer is used by the Servo library
+    NVIC_DisableIRQ(irqn);
+    NVIC_ClearPendingIRQ(irqn);
+    NVIC_SetPriority(irqn, 0);
+    NVIC_EnableIRQ(irqn);
+
+    // Enable the match channel interrupt request
+    tc->COUNT16.INTENSET.reg = intEnableBit;
+
+    // Enable the timer and start it
+    tc->COUNT16.CTRLA.reg |= TC_CTRLA_ENABLE;
+#if defined(__SAMD51__)
+    while(tc->COUNT16.SYNCBUSY.bit.ENABLE);
+#else
+    WAIT_TC16_REGS_SYNC(tc)
+#endif
+}
+
+static void initISR(timer16_Sequence_t timer)
+{
+#if defined (_useTimer1)
+    if (timer == _timer1)
+        _initISR(TC_FOR_TIMER1, CHANNEL_FOR_TIMER1, ID_TC_FOR_TIMER1, IRQn_FOR_TIMER1, GCM_FOR_TIMER_1, INTENSET_BIT_FOR_TIMER_1);
+#endif
+#if defined (_useTimer2)
+    if (timer == _timer2)
+        _initISR(TC_FOR_TIMER2, CHANNEL_FOR_TIMER2, ID_TC_FOR_TIMER2, IRQn_FOR_TIMER2, GCM_FOR_TIMER_2, INTENSET_BIT_FOR_TIMER_2);
+#endif
+}
+
+static void finISR(timer16_Sequence_t timer)
+{
+  (void)timer;
+#if defined (_useTimer1)
+    // Disable the match channel interrupt request
+    TC_FOR_TIMER1->COUNT16.INTENCLR.reg = INTENCLR_BIT_FOR_TIMER_1;
+#endif
+#if defined (_useTimer2)
+    // Disable the match channel interrupt request
+    TC_FOR_TIMER2->COUNT16.INTENCLR.reg = INTENCLR_BIT_FOR_TIMER_2;
+#endif
+}
+
+static boolean isTimerActive(timer16_Sequence_t timer)
+{
+  // returns true if any servo is active on this timer
+  for(uint8_t channel=0; channel < SERVOS_PER_TIMER; channel++) {
+    if(SERVO(timer,channel).Pin.isActive == true)
+      return true;
+  }
+  return false;
+}
+
+/****************** end of static functions ******************************/
+
+Servo::Servo()
+{
+  if (ServoCount < MAX_SERVOS) {
+    this->servoIndex = ServoCount++;                    // assign a servo index to this instance
+    servos[this->servoIndex].ticks = usToTicks(DEFAULT_PULSE_WIDTH);   // store default values
+  } else {
+    this->servoIndex = INVALID_SERVO;  // too many servos
+  }
+}
+
+uint8_t Servo::attach(int pin)
+{
+  return this->attach(pin, MIN_PULSE_WIDTH, MAX_PULSE_WIDTH);
+}
+
+uint8_t Servo::attach(int pin, int min, int max)
+{
+  timer16_Sequence_t timer;
+
+  if (this->servoIndex < MAX_SERVOS) {
+    pinMode(pin, OUTPUT);                                   // set servo pin to output
+    servos[this->servoIndex].Pin.nbr = pin;
+    // todo min/max check: abs(min - MIN_PULSE_WIDTH) /4 < 128
+    this->min  = (MIN_PULSE_WIDTH - min)/4; //resolution of min/max is 4 uS
+    this->max  = (MAX_PULSE_WIDTH - max)/4;
+    // initialize the timer if it has not already been initialized
+    timer = SERVO_INDEX_TO_TIMER(servoIndex);
+    if (isTimerActive(timer) == false) {
+      initISR(timer);
+    }
+    servos[this->servoIndex].Pin.isActive = true;  // this must be set after the check for isTimerActive
+  }
+  return this->servoIndex;
+}
+
+void Servo::detach()
+{
+  timer16_Sequence_t timer;
+
+  servos[this->servoIndex].Pin.isActive = false;
+  timer = SERVO_INDEX_TO_TIMER(servoIndex);
+  if(isTimerActive(timer) == false) {
+    finISR(timer);
+  }
+}
+
+void Servo::write(int value)
+{
+  // treat values less than 544 as angles in degrees (valid values in microseconds are handled as microseconds)
+  if (value < MIN_PULSE_WIDTH)
+  {
+    if (value < 0)
+      value = 0;
+    else if (value > 180)
+      value = 180;
+
+    value = map(value, 0, 180, SERVO_MIN(), SERVO_MAX());
+  }
+  writeMicroseconds(value);
+}
+
+void Servo::writeMicroseconds(int value)
+{
+  // calculate and store the values for the given channel
+  byte channel = this->servoIndex;
+  if( (channel < MAX_SERVOS) )   // ensure channel is valid
+  {
+    if (value < SERVO_MIN())          // ensure pulse width is valid
+      value = SERVO_MIN();
+    else if (value > SERVO_MAX())
+      value = SERVO_MAX();
+
+    value = value - TRIM_DURATION;
+    value = usToTicks(value);  // convert to ticks after compensating for interrupt overhead
+    servos[channel].ticks = value;
+  }
+}
+
+int Servo::read() // return the value as degrees
+{
+  return map(readMicroseconds()+1, SERVO_MIN(), SERVO_MAX(), 0, 180);
+}
+
+int Servo::readMicroseconds()
+{
+  unsigned int pulsewidth;
+  if (this->servoIndex != INVALID_SERVO)
+    pulsewidth = ticksToUs(servos[this->servoIndex].ticks)  + TRIM_DURATION;
+  else
+    pulsewidth  = 0;
+
+  return pulsewidth;
+}
+
+bool Servo::attached()
+{
+  return servos[this->servoIndex].Pin.isActive;
+}
+
+#endif // ARDUINO_ARCH_SAMD
diff --git a/libraries/Servo/src/samd/ServoTimers.h b/libraries/Servo/src/samd/ServoTimers.h
new file mode 100644
index 000000000..c4da50694
--- /dev/null
+++ b/libraries/Servo/src/samd/ServoTimers.h
@@ -0,0 +1,98 @@
+/*
+  Copyright (c) 2015 Arduino LLC. All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+/*
+ * Defines for 16 bit timers used with  Servo library
+ *
+ * If _useTimerX is defined then TimerX is a 16 bit timer on the current board
+ * timer16_Sequence_t enumerates the sequence that the timers should be allocated
+ * _Nbr_16timers indicates how many 16 bit timers are available.
+ */
+
+#ifndef __SERVO_TIMERS_H__
+#define __SERVO_TIMERS_H__
+
+/**
+ * SAMD Only definitions
+ * ---------------------
+ */
+
+// For SAMD:
+#define _useTimer1
+//#define _useTimer2   // <- TODO do not activate until the code in Servo.cpp has been changed in order
+                       //         to manage more than one channel per timer on the SAMD architecture
+
+#if defined(__SAMD51__) 
+  #if defined (_useTimer1)
+    #define TC_FOR_TIMER1             TC1
+    #define CHANNEL_FOR_TIMER1        0
+    #define INTENSET_BIT_FOR_TIMER_1  TC_INTENSET_MC0
+    #define INTENCLR_BIT_FOR_TIMER_1  TC_INTENCLR_MC0
+    #define INTFLAG_BIT_FOR_TIMER_1   TC_INTFLAG_MC0
+    #define ID_TC_FOR_TIMER1          ID_TC1
+    #define IRQn_FOR_TIMER1           TC1_IRQn
+    #define HANDLER_FOR_TIMER1        TC1_Handler
+    #define GCM_FOR_TIMER_1           TC1_GCLK_ID
+  #endif
+
+  #if defined (_useTimer2)
+    #define TC_FOR_TIMER2             TC1
+    #define CHANNEL_FOR_TIMER2        1
+    #define INTENSET_BIT_FOR_TIMER_2  TC_INTENSET_MC1
+    #define INTENCLR_BIT_FOR_TIMER_2  TC_INTENCLR_MC1
+    #define INTFLAG_BIT_FOR_TIMER_2   TC_INTFLAG_MC1
+    #define ID_TC_FOR_TIMER2          ID_TC1
+    #define IRQn_FOR_TIMER2           TC1_IRQn
+    #define HANDLER_FOR_TIMER2        TC1_Handler
+    #define GCM_FOR_TIMER_2           TC1_GCLK_ID
+  #endif
+#else
+  #if defined (_useTimer1)
+    #define TC_FOR_TIMER1             TC4
+    #define CHANNEL_FOR_TIMER1        0
+    #define INTENSET_BIT_FOR_TIMER_1  TC_INTENSET_MC0
+    #define INTENCLR_BIT_FOR_TIMER_1  TC_INTENCLR_MC0
+    #define INTFLAG_BIT_FOR_TIMER_1   TC_INTFLAG_MC0
+    #define ID_TC_FOR_TIMER1          ID_TC4
+    #define IRQn_FOR_TIMER1           TC4_IRQn
+    #define HANDLER_FOR_TIMER1        TC4_Handler
+    #define GCM_FOR_TIMER_1           GCM_TC4_TC5
+  #endif
+
+  #if defined (_useTimer2)
+    #define TC_FOR_TIMER2             TC4
+    #define CHANNEL_FOR_TIMER2        1
+    #define INTENSET_BIT_FOR_TIMER_2  TC_INTENSET_MC1
+    #define INTENCLR_BIT_FOR_TIMER_2  TC_INTENCLR_MC1
+    #define ID_TC_FOR_TIMER2          ID_TC4
+    #define IRQn_FOR_TIMER2           TC4_IRQn
+    #define HANDLER_FOR_TIMER2        TC4_Handler
+    #define GCM_FOR_TIMER_2           GCM_TC4_TC5
+  #endif
+#endif
+
+typedef enum {
+#if defined (_useTimer1)
+    _timer1,
+#endif
+#if defined (_useTimer2)
+    _timer2,
+#endif
+    _Nbr_16timers } timer16_Sequence_t;
+
+#endif   // __SERVO_TIMERS_H__
diff --git a/libraries/Servo/src/stm32f4/Servo.cpp b/libraries/Servo/src/stm32f4/Servo.cpp
new file mode 100644
index 000000000..01d05d98d
--- /dev/null
+++ b/libraries/Servo/src/stm32f4/Servo.cpp
@@ -0,0 +1,194 @@
+/******************************************************************************
+ * The MIT License
+ *
+ * Copyright (c) 2010, LeafLabs, LLC.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *****************************************************************************/
+
+#if defined(ARDUINO_ARCH_STM32F4)
+
+#include "ServoTimers.h"
+
+#include "boards.h"
+#include "io.h"
+#include "pwm.h"
+#include "math.h"
+
+// 20 millisecond period config.  For a 1-based prescaler,
+//
+//    (prescaler * overflow / CYC_MSEC) msec = 1 timer cycle = 20 msec
+// => prescaler * overflow = 20 * CYC_MSEC
+//
+// This picks the smallest prescaler that allows an overflow < 2^16.
+#define MAX_OVERFLOW    ((1 << 16) - 1)
+#define CYC_MSEC        (1000 * CYCLES_PER_MICROSECOND)
+#define TAU_MSEC        20
+#define TAU_USEC        (TAU_MSEC * 1000)
+#define TAU_CYC         (TAU_MSEC * CYC_MSEC)
+#define SERVO_PRESCALER (TAU_CYC / MAX_OVERFLOW + 1)
+#define SERVO_OVERFLOW  ((uint16)round((double)TAU_CYC / SERVO_PRESCALER))
+
+// Unit conversions
+#define US_TO_COMPARE(us) ((uint16)map((us), 0, TAU_USEC, 0, SERVO_OVERFLOW))
+#define COMPARE_TO_US(c)  ((uint32)map((c), 0, SERVO_OVERFLOW, 0, TAU_USEC))
+#define ANGLE_TO_US(a)    ((uint16)(map((a), this->minAngle, this->maxAngle, \
+                                        this->minPW, this->maxPW)))
+#define US_TO_ANGLE(us)   ((int16)(map((us), this->minPW, this->maxPW,  \
+                                       this->minAngle, this->maxAngle)))
+
+Servo::Servo() {
+    this->resetFields();
+}
+
+bool Servo::attach(uint8 pin, uint16 minPW, uint16 maxPW, int16 minAngle, int16 maxAngle)
+{
+    // SerialUSB.begin(115200);
+    // SerialUSB.println(MAX_OVERFLOW);
+
+
+    timer_dev *tdev = PIN_MAP[pin].timer_device;
+
+    analogWriteResolution(16);
+
+    int prescaler = 6;
+    int overflow = 65400;
+    int minPW_correction = 300;
+    int maxPW_correction = 300;
+
+    pinMode(pin, OUTPUT);
+
+
+    if (tdev == NULL) {
+        // don't reset any fields or ASSERT(0), to keep driving any
+        // previously attach()ed servo.
+        return false;
+    }
+
+    if ( (tdev == TIMER1) || (tdev == TIMER8) || (tdev == TIMER10) || (tdev == TIMER11))
+    {
+        prescaler = 54;
+        overflow = 65400;
+        minPW_correction = 40;
+        maxPW_correction = 50;
+    }
+
+    if ( (tdev == TIMER2) || (tdev == TIMER3) || (tdev == TIMER4) || (tdev == TIMER5) )
+    {
+        prescaler = 6;
+        overflow = 64285;
+        minPW_correction = 370;
+        maxPW_correction = 350;
+    }
+
+    if ( (tdev == TIMER6) || (tdev == TIMER7) )
+    {
+        prescaler = 6;
+        overflow = 65400;
+        minPW_correction = 0;
+        maxPW_correction = 0;
+    }
+
+    if ( (tdev == TIMER9) || (tdev == TIMER12) || (tdev == TIMER13) || (tdev == TIMER14) )
+    {
+        prescaler = 6;
+        overflow = 65400;
+        minPW_correction = 30;
+        maxPW_correction = 0;
+    }
+
+    if (this->attached()) {
+        this->detach();
+    }
+
+    this->pin = pin;
+    this->minPW = (minPW + minPW_correction);
+    this->maxPW = (maxPW + maxPW_correction);
+    this->minAngle = minAngle;
+    this->maxAngle = maxAngle;
+
+    timer_pause(tdev);
+    timer_set_prescaler(tdev, prescaler); // prescaler is 1-based
+    timer_set_reload(tdev, overflow);
+    timer_generate_update(tdev);
+    timer_resume(tdev);
+
+    return true;
+}
+
+bool Servo::detach() {
+    if (!this->attached()) {
+        return false;
+    }
+
+    timer_dev *tdev = PIN_MAP[this->pin].timer_device;
+    uint8 tchan = PIN_MAP[this->pin].timer_channel;
+    timer_set_mode(tdev, tchan, TIMER_DISABLED);
+
+    this->resetFields();
+
+    return true;
+}
+
+void Servo::write(int degrees) {
+    degrees = constrain(degrees, this->minAngle, this->maxAngle);
+    this->writeMicroseconds(ANGLE_TO_US(degrees));
+}
+
+int Servo::read() const {
+    int a = US_TO_ANGLE(this->readMicroseconds());
+    // map() round-trips in a weird way we mostly correct for here;
+    // the round-trip is still sometimes off-by-one for write(1) and
+    // write(179).
+    return a == this->minAngle || a == this->maxAngle ? a : a + 1;
+}
+
+void Servo::writeMicroseconds(uint16 pulseWidth) {
+    if (!this->attached()) {
+        ASSERT(0);
+        return;
+    }
+    pulseWidth = constrain(pulseWidth, this->minPW, this->maxPW);
+    analogWrite(this->pin, US_TO_COMPARE(pulseWidth));
+}
+
+uint16 Servo::readMicroseconds() const {
+    if (!this->attached()) {
+        ASSERT(0);
+        return 0;
+    }
+
+    stm32_pin_info pin_info = PIN_MAP[this->pin];
+    uint16 compare = timer_get_compare(pin_info.timer_device,
+                                       pin_info.timer_channel);
+
+    return COMPARE_TO_US(compare);
+}
+
+void Servo::resetFields(void) {
+    this->pin = NOT_ATTACHED;
+    this->minAngle = MIN_ANGLE;
+    this->maxAngle = MAX_ANGLE;
+    this->minPW = MIN_PULSE_WIDTH;
+    this->maxPW = MAX_PULSE_WIDTH;
+}
+
+#endif
diff --git a/libraries/Servo/src/stm32f4/ServoTimers.h b/libraries/Servo/src/stm32f4/ServoTimers.h
new file mode 100644
index 000000000..12d55b730
--- /dev/null
+++ b/libraries/Servo/src/stm32f4/ServoTimers.h
@@ -0,0 +1,207 @@
+/******************************************************************************
+ * The MIT License
+ *
+ * Copyright (c) 2010, LeafLabs, LLC.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *****************************************************************************/
+
+ /*
+ * Arduino srl - www.arduino.org
+ * 2017 Feb 23: Edited by Francesco Alessi (alfran) - francesco@arduino.org
+ */
+#ifndef _SERVO_H_
+#define _SERVO_H_
+
+#include "types.h"
+#include "timer.h"
+
+#include "wiring.h"             /* hack for IDE compile */
+
+/*
+ * Note on Arduino compatibility:
+ *
+ * In the Arduino implementation, PWM is done "by hand" in the sense
+ * that timer channels are hijacked in groups and an ISR is set which
+ * toggles Servo::attach()ed pins using digitalWrite().
+ *
+ * While this scheme allows any pin to drive a servo, it chews up
+ * cycles and complicates the programmer's notion of when a particular
+ * timer channel will be in use.
+ *
+ * This implementation only allows Servo instances to attach() to pins
+ * that already have a timer channel associated with them, and just
+ * uses pwmWrite() to drive the wave.
+ *
+ * This introduces an incompatibility: while the Arduino
+ * implementation of attach() returns the affected channel on success
+ * and 0 on failure, this one returns true on success and false on
+ * failure.
+ *
+ * RC Servos expect a pulse every 20ms.  Since periods are set for
+ * entire timers, rather than individual channels, attach()ing a Servo
+ * to a pin can interfere with other pins associated with the same
+ * timer.  As always, your board's pin map is your friend.
+ */
+
+// Pin number of unattached pins
+#define NOT_ATTACHED                    (-1)
+
+#define _Nbr_16timers 14 // mumber of STM32F469 Timers
+#define SERVOS_PER_TIMER 4 // Number of timer channels
+
+
+// Default min/max pulse widths (in microseconds) and angles (in
+// degrees).  Values chosen for Arduino compatibility.  These values
+// are part of the public API; DO NOT CHANGE THEM.
+#define MIN_ANGLE               0
+#define MAX_ANGLE             180
+
+#define MIN_PULSE_WIDTH       544     // the shortest pulse sent to a servo
+#define MAX_PULSE_WIDTH      2400     // the longest pulse sent to a servo
+
+/** Class for interfacing with RC servomotors. */
+class Servo {
+public:
+    /**
+     * @brief Construct a new Servo instance.
+     *
+     * The new instance will not be attached to any pin.
+     */
+    Servo();
+
+    /**
+     * @brief Associate this instance with a servomotor whose input is
+     *        connected to pin.
+     *
+     * If this instance is already attached to a pin, it will be
+     * detached before being attached to the new pin. This function
+     * doesn't detach any interrupt attached with the pin's timer
+     * channel.
+     *
+     * @param pin Pin connected to the servo pulse wave input. This
+     *            pin must be capable of PWM output.
+     *
+     * @param minPulseWidth Minimum pulse width to write to pin, in
+     *                      microseconds.  This will be associated
+     *                      with a minAngle degree angle.  Defaults to
+     *                      SERVO_DEFAULT_MIN_PW = 544.
+     *
+     * @param maxPulseWidth Maximum pulse width to write to pin, in
+     *                      microseconds.  This will be associated
+     *                      with a maxAngle degree angle. Defaults to
+     *                      SERVO_DEFAULT_MAX_PW = 2400.
+     *
+     * @param minAngle Target angle (in degrees) associated with
+     *                 minPulseWidth.  Defaults to
+     *                 SERVO_DEFAULT_MIN_ANGLE = 0.
+     *
+     * @param maxAngle Target angle (in degrees) associated with
+     *                 maxPulseWidth.  Defaults to
+     *                 SERVO_DEFAULT_MAX_ANGLE = 180.
+     *
+     * @sideeffect May set pinMode(pin, PWM).
+     *
+     * @return true if successful, false when pin doesn't support PWM.
+     */
+
+    bool attach(uint8 pin,
+                uint16 minPulseWidth=MIN_PULSE_WIDTH,
+                uint16 maxPulseWidth=MAX_PULSE_WIDTH,
+                int16 minAngle=MIN_ANGLE,
+                int16 maxAngle=MAX_ANGLE);
+    /**
+     * @brief Stop driving the servo pulse train.
+     *
+     * If not currently attached to a motor, this function has no effect.
+     *
+     * @return true if this call did anything, false otherwise.
+     */
+    bool detach();
+
+    /**
+     * @brief Set the servomotor target angle.
+     *
+     * @param angle Target angle, in degrees.  If the target angle is
+     *              outside the range specified at attach() time, it
+     *              will be clamped to lie in that range.
+     *
+     * @see Servo::attach()
+     */
+    void write(int angle);
+
+    /**
+     * @brief Set the pulse width, in microseconds.
+     *
+     * @param pulseWidth Pulse width to send to the servomotor, in
+     *                   microseconds. If outside of the range
+     *                   specified at attach() time, it is clamped to
+     *                   lie in that range.
+     *
+     * @see Servo::attach()
+     */
+    void writeMicroseconds(uint16 pulseWidth);
+
+    /**
+     * Get the servomotor's target angle, in degrees.  This will
+     * lie inside the range specified at attach() time.
+     *
+     * @see Servo::attach()
+     */
+    int read() const;
+
+    /**
+     * Get the current pulse width, in microseconds.  This will
+     * lie within the range specified at attach() time.
+     *
+     * @see Servo::attach()
+     */
+    uint16 readMicroseconds() const;
+
+
+    /**
+     * @brief Check if this instance is attached to a servo.
+     * @return true if this instance is attached to a servo, false otherwise.
+     * @see Servo::attachedPin()
+     */
+    bool attached() const { return this->pin != NOT_ATTACHED; }
+
+    /**
+     * @brief Get the pin this instance is attached to.
+     * @return Pin number if currently attached to a pin, NOT_ATTACHED
+     *         otherwise.
+     * @see Servo::attach()
+     */
+    int attachedPin() const { return this->pin; }
+
+private:
+    int16 pin;
+    uint16 minPW;
+    uint16 maxPW;
+    int16 minAngle;
+    int16 maxAngle;
+
+    void resetFields(void);
+};
+
+
+
+#endif  /* _SERVO_H_ */
diff --git a/libraries/USBHost/examples/ADKTerminalTest/ADKTerminalTest.ino b/libraries/USBHost/examples/ADKTerminalTest/ADKTerminalTest.ino
index ea7509cbc..21d6ef522 100644
--- a/libraries/USBHost/examples/ADKTerminalTest/ADKTerminalTest.ino
+++ b/libraries/USBHost/examples/ADKTerminalTest/ADKTerminalTest.ino
@@ -37,7 +37,7 @@ void setup(void)
   while (!SERIAL_PORT_MONITOR); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
   SERIAL_PORT_MONITOR.println("\r\nADK demo start");
 
-  if (usb.Init() == -1)
+  if (usb.Init() == (uint32_t)-1)
 	SERIAL_PORT_MONITOR.println("OSC did not start.");
 
   delay(20);
diff --git a/libraries/USBHost/examples/KeyboardController/KeyboardController.ino b/libraries/USBHost/examples/KeyboardController/KeyboardController.ino
index b869ad803..0daf7b02d 100644
--- a/libraries/USBHost/examples/KeyboardController/KeyboardController.ino
+++ b/libraries/USBHost/examples/KeyboardController/KeyboardController.ino
@@ -2,7 +2,7 @@
  Keyboard Controller Example
 
  Shows the output of a USB Keyboard connected to
- the Native USB port on an Arduino Due Board.
+ the Native USB port on an Arduino Zero
 
  created 8 Oct 2012
  by Cristian Maglie
@@ -15,6 +15,13 @@
 // Require keyboard control library
 #include <KeyboardController.h>
 
+
+// on a zero with debug port, use debug port
+//#define SerialDebug Serial
+
+// on a feather or non-debug Zero, use Serial1 (since USB is taken!)
+#define SerialDebug Serial1
+
 // Initialize USB Controller
 USBHost usb;
 
@@ -25,60 +32,61 @@ void printKey();
 
 // This function intercepts key press
 void keyPressed() {
-  SERIAL_PORT_MONITOR.print("Pressed:  ");
+  SerialDebug.print("Pressed:  ");
   printKey();
 }
 
 // This function intercepts key release
 void keyReleased() {
-  SERIAL_PORT_MONITOR.print("Released: ");
+  SerialDebug.print("Released: ");
   printKey();
 }
 
 void printKey() {
   // getOemKey() returns the OEM-code associated with the key
-  SERIAL_PORT_MONITOR.print(" key:");
-  SERIAL_PORT_MONITOR.print(keyboard.getOemKey());
+  SerialDebug.print(" key:");
+  SerialDebug.print(keyboard.getOemKey());
 
   // getModifiers() returns a bits field with the modifiers-keys
   int mod = keyboard.getModifiers();
-  SERIAL_PORT_MONITOR.print(" mod:");
-  SERIAL_PORT_MONITOR.print(mod);
+  SerialDebug.print(" mod:");
+  SerialDebug.print(mod);
 
-  SERIAL_PORT_MONITOR.print(" => ");
+  SerialDebug.print(" => ");
 
   if (mod & LeftCtrl)
-    SERIAL_PORT_MONITOR.print("L-Ctrl ");
+    SerialDebug.print("L-Ctrl ");
   if (mod & LeftShift)
-    SERIAL_PORT_MONITOR.print("L-Shift ");
+    SerialDebug.print("L-Shift ");
   if (mod & Alt)
-    SERIAL_PORT_MONITOR.print("Alt ");
+    SerialDebug.print("Alt ");
   if (mod & LeftCmd)
-    SERIAL_PORT_MONITOR.print("L-Cmd ");
+    SerialDebug.print("L-Cmd ");
   if (mod & RightCtrl)
-    SERIAL_PORT_MONITOR.print("R-Ctrl ");
+    SerialDebug.print("R-Ctrl ");
   if (mod & RightShift)
-    SERIAL_PORT_MONITOR.print("R-Shift ");
+    SerialDebug.print("R-Shift ");
   if (mod & AltGr)
-    SERIAL_PORT_MONITOR.print("AltGr ");
+    SerialDebug.print("AltGr ");
   if (mod & RightCmd)
-    SERIAL_PORT_MONITOR.print("R-Cmd ");
+    SerialDebug.print("R-Cmd ");
 
   // getKey() returns the ASCII translation of OEM key
   // combined with modifiers.
-  SERIAL_PORT_MONITOR.write(keyboard.getKey());
-  SERIAL_PORT_MONITOR.println();
+  SerialDebug.write(keyboard.getKey());
+  SerialDebug.println();
 }
 
+uint32_t lastUSBstate = 0;
+
 void setup()
 {
-  SERIAL_PORT_MONITOR.begin( 115200 );
-  while (!SERIAL_PORT_MONITOR); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
-  SERIAL_PORT_MONITOR.println("Keyboard Controller Program started");
+  SerialDebug.begin( 115200 );
+  SerialDebug.println("USB Host Keyboard Controller Program started");
+  if (usb.Init() == (uint32_t)-1)
+	  SerialDebug.println("USB Host did not start.");
 
-  if (usb.Init() == -1)
-	  SERIAL_PORT_MONITOR.println("OSC did not start.");
-  
+  SerialDebug.println("USB Host started");
   delay( 20 );
 }
 
@@ -86,4 +94,21 @@ void loop()
 {
   // Process USB tasks
   usb.Task();
+
+  uint32_t currentUSBstate = usb.getUsbTaskState();
+  if (lastUSBstate != currentUSBstate) {
+    SerialDebug.print("USB state changed: 0x"); 
+    SerialDebug.print(lastUSBstate, HEX); 
+    SerialDebug.print(" -> 0x"); 
+    SerialDebug.println(currentUSBstate, HEX);
+    switch (currentUSBstate) {
+      case USB_ATTACHED_SUBSTATE_SETTLE: SerialDebug.println("Device Attached"); break;
+      case USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE: SerialDebug.println("Detached, waiting for Device"); break;
+      case USB_ATTACHED_SUBSTATE_RESET_DEVICE: SerialDebug.println("Resetting Device"); break;
+      case USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE: SerialDebug.println("Reset complete"); break;
+      case USB_STATE_CONFIGURING: SerialDebug.println("USB Configuring"); break;
+      case USB_STATE_RUNNING: SerialDebug.println("USB Running"); break;
+    }
+    lastUSBstate = currentUSBstate;
+  }
 }
diff --git a/libraries/USBHost/examples/MouseController/MouseController.ino b/libraries/USBHost/examples/MouseController/MouseController.ino
index ae3a1c046..90e6dce2b 100644
--- a/libraries/USBHost/examples/MouseController/MouseController.ino
+++ b/libraries/USBHost/examples/MouseController/MouseController.ino
@@ -15,6 +15,14 @@
 // Require mouse control library
 #include <MouseController.h>
 
+// on a zero with debug port, use debug port
+//#define SerialDebug Serial
+
+// on a feather or non-debug Zero, use Serial1 (since USB is taken!)
+#define SerialDebug Serial1
+
+uint32_t lastUSBstate = 0;
+
 // Initialize USB Controller
 USBHost usb;
 
@@ -28,65 +36,65 @@ bool rightButton = false;
 
 // This function intercepts mouse movements
 void mouseMoved() {
-  SERIAL_PORT_MONITOR.print("Move: ");
-  SERIAL_PORT_MONITOR.print(mouse.getXChange());
-  SERIAL_PORT_MONITOR.print(", ");
-  SERIAL_PORT_MONITOR.println(mouse.getYChange());
+  SerialDebug.print("Move: ");
+  SerialDebug.print(mouse.getXChange());
+  SerialDebug.print(", ");
+  SerialDebug.println(mouse.getYChange());
 }
 
 // This function intercepts mouse movements while a button is pressed
 void mouseDragged() {
-  SERIAL_PORT_MONITOR.print("DRAG: ");
-  SERIAL_PORT_MONITOR.print(mouse.getXChange());
-  SERIAL_PORT_MONITOR.print(", ");
-  SERIAL_PORT_MONITOR.println(mouse.getYChange());
+  SerialDebug.print("Drag: ");
+  SerialDebug.print(mouse.getXChange());
+  SerialDebug.print(", ");
+  SerialDebug.println(mouse.getYChange());
 }
 
 // This function intercepts mouse button press
 void mousePressed() {
-  SERIAL_PORT_MONITOR.print("Pressed: ");
+  SerialDebug.print("Pressed: ");
   if (mouse.getButton(LEFT_BUTTON)) {
-    SERIAL_PORT_MONITOR.print("L");
+    SerialDebug.print("L");
     leftButton = true;
   }
   if (mouse.getButton(MIDDLE_BUTTON)) {
-    SERIAL_PORT_MONITOR.print("M");
+    SerialDebug.print("M");
     middleButton = true;
   }
   if (mouse.getButton(RIGHT_BUTTON)) {
-    SERIAL_PORT_MONITOR.print("R");
+    SerialDebug.print("R");
     rightButton = true;
   }
-  SERIAL_PORT_MONITOR.println();
+  SerialDebug.println();
 }
 
 // This function intercepts mouse button release
 void mouseReleased() {
-  SERIAL_PORT_MONITOR.print("Released: ");
+  SerialDebug.print("Released: ");
   if (!mouse.getButton(LEFT_BUTTON) && leftButton == true) {
-    SERIAL_PORT_MONITOR.print("L");
+    SerialDebug.print("L");
     leftButton = false;
   }
   if (!mouse.getButton(MIDDLE_BUTTON) && middleButton == true) {
-    SERIAL_PORT_MONITOR.print("M");
+    SerialDebug.print("M");
     middleButton = false;
   }
   if (!mouse.getButton(RIGHT_BUTTON) && rightButton == true) {
-    SERIAL_PORT_MONITOR.print("R");
+    SerialDebug.print("R");
     rightButton = false;
   }
-  SERIAL_PORT_MONITOR.println();
+  SerialDebug.println();
 }
 
 void setup()
 {
-  SERIAL_PORT_MONITOR.begin( 115200 );
-  while (!SERIAL_PORT_MONITOR); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
-  SERIAL_PORT_MONITOR.println("Mouse Controller Program started");
+  SerialDebug.begin( 115200 );
+  SerialDebug.println("USB Host Mouse Controller Program started");
 
-  if (usb.Init() == -1)
-      SERIAL_PORT_MONITOR.println("OSC did not start.");
+  if (usb.Init() == (uint32_t)-1)
+    SerialDebug.println("USB Host did not start.");
 
+  SerialDebug.println("USB Host started");
   delay( 20 );
 }
 
@@ -94,4 +102,21 @@ void loop()
 {
   // Process USB tasks
   usb.Task();
+
+  uint32_t currentUSBstate = usb.getUsbTaskState();
+  if (lastUSBstate != currentUSBstate) {
+    SerialDebug.print("USB state changed: 0x"); 
+    SerialDebug.print(lastUSBstate, HEX); 
+    SerialDebug.print(" -> 0x"); 
+    SerialDebug.println(currentUSBstate, HEX);
+    switch (currentUSBstate) {
+      case USB_ATTACHED_SUBSTATE_SETTLE: SerialDebug.println("Device Attached"); break;
+      case USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE: SerialDebug.println("Detached, waiting for Device"); break;
+      case USB_ATTACHED_SUBSTATE_RESET_DEVICE: SerialDebug.println("Resetting Device"); break;
+      case USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE: SerialDebug.println("Reset complete"); break;
+      case USB_STATE_CONFIGURING: SerialDebug.println("USB Configuring"); break;
+      case USB_STATE_RUNNING: SerialDebug.println("USB Running"); break;
+    }
+    lastUSBstate = currentUSBstate;
+  }
 }
diff --git a/libraries/USBHost/examples/USB_desc/USB_desc.ino b/libraries/USBHost/examples/USB_desc/USB_desc.ino
index a7ede046c..20838ccbe 100644
--- a/libraries/USBHost/examples/USB_desc/USB_desc.ino
+++ b/libraries/USBHost/examples/USB_desc/USB_desc.ino
@@ -1,22 +1,16 @@
-
-
 #include "Arduino.h"
 #include <usbhub.h>
 #include "wiring_constants.h"
 #include "pgmstrings.h"
-// Satisfy IDE, which only needs to see the include statment in the ino.
-#ifdef dobogusinclude
-#include <spi4teensy3.h>
-#endif
+
+
+// on a zero with debug port, use debug port
+//#define SerialDebug Serial
+
+// on a feather or non-debug Zero, use Serial1 (since USB is taken!)
+#define SerialDebug Serial1
 
 USBHost     usb;
-//USBHub  Hub1(&Usb);
-//USBHub  Hub2(&Usb);
-//USBHub  Hub3(&Usb);
-//USBHub  Hub4(&Usb);
-//USBHub  Hub5(&Usb);
-//USBHub  Hub6(&Usb);
-//USBHub  Hub7(&Usb);
 
 uint32_t next_time;
 
@@ -33,39 +27,40 @@ void PrintAllAddresses(UsbDeviceDefinition *pdev)
 {
     UsbDeviceAddress adr;
     adr.devAddress = pdev->address.devAddress;
-    SERIAL_PORT_MONITOR.print("\r\nAddr:");
-    SERIAL_PORT_MONITOR.print(adr.devAddress, HEX);
-    SERIAL_PORT_MONITOR.print("(");
-    SERIAL_PORT_MONITOR.print(adr.bmHub, HEX);
-    SERIAL_PORT_MONITOR.print(".");
-    SERIAL_PORT_MONITOR.print(adr.bmParent, HEX);
-    SERIAL_PORT_MONITOR.print(".");
-    SERIAL_PORT_MONITOR.print(adr.bmAddress, HEX);
-    SERIAL_PORT_MONITOR.println(")");
+    SerialDebug.print("\r\nAddr:");
+    SerialDebug.print(adr.devAddress, HEX);
+    SerialDebug.print("(");
+    SerialDebug.print(adr.bmHub, HEX);
+    SerialDebug.print(".");
+    SerialDebug.print(adr.bmParent, HEX);
+    SerialDebug.print(".");
+    SerialDebug.print(adr.bmAddress, HEX);
+    SerialDebug.println(")");
 }
 
 void PrintAddress(uint8_t addr)
 {
     UsbDeviceAddress adr;
     adr.devAddress = addr;
-    SERIAL_PORT_MONITOR.print("\r\nADDR:\t");
-    SERIAL_PORT_MONITOR.println(adr.devAddress,HEX);
-    SERIAL_PORT_MONITOR.print("DEV:\t");
-    SERIAL_PORT_MONITOR.println(adr.bmAddress,HEX);
-    SERIAL_PORT_MONITOR.print("PRNT:\t");
-    SERIAL_PORT_MONITOR.println(adr.bmParent,HEX);
-    SERIAL_PORT_MONITOR.print("HUB:\t");
-    SERIAL_PORT_MONITOR.println(adr.bmHub,HEX);
+    SerialDebug.print("\r\nADDR:\t");
+    SerialDebug.println(adr.devAddress,HEX);
+    SerialDebug.print("DEV:\t");
+    SerialDebug.println(adr.bmAddress,HEX);
+    SerialDebug.print("PRNT:\t");
+    SerialDebug.println(adr.bmParent,HEX);
+    SerialDebug.print("HUB:\t");
+    SerialDebug.println(adr.bmHub,HEX);
 }
 
 void setup()
 {
-  SERIAL_PORT_MONITOR.begin( 115200 );
-  while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
-  SERIAL_PORT_MONITOR.println("Start USB Desc");
+  Serial.begin(115200);
+  SerialDebug.begin(115200);
+  SerialDebug.println("Starting USB Descriptor test");
 
-  if (usb.Init() == -1)
-      SERIAL_PORT_MONITOR.println("OSC did not start.");
+  SerialDebug.println("Initializing USB");
+  if (usb.Init() == (uint32_t)-1)
+    SerialDebug.println("USBhost did not start.");
 
   delay( 20 );
 
@@ -85,7 +80,7 @@ void PrintDescriptors(uint8_t addr)
       printProgStr(Gen_Error_str);
       print_hex( rcode, 8 );
     }
-    SERIAL_PORT_MONITOR.print("\r\n");
+    SerialDebug.print("\r\n");
 
     for (int i=0; i<num_conf; i++)
     {
@@ -95,15 +90,15 @@ void PrintDescriptors(uint8_t addr)
           printProgStr(Gen_Error_str);
           print_hex(rcode, 8);
         }
-        SERIAL_PORT_MONITOR.println("\r\n");
+        SerialDebug.println("\r\n");
     }
 }
 
 void PrintAllDescriptors(UsbDeviceDefinition *pdev)
 {
-    SERIAL_PORT_MONITOR.println("\r\n");
+    SerialDebug.println("\r\n");
     print_hex(pdev->address.devAddress, 8);
-    SERIAL_PORT_MONITOR.println("\r\n--");
+    SerialDebug.println("\r\n--");
     PrintDescriptors( pdev->address.devAddress );
 }
 
@@ -166,42 +161,43 @@ byte getdevdescr( byte addr, byte &num_conf )
 
 void printhubdescr(uint8_t *descrptr, uint8_t addr)
 {
+    (void)addr;
     HubDescriptor  *pHub = (HubDescriptor*) descrptr;
     uint8_t        len = *((uint8_t*)descrptr);
 
     printProgStr(PSTR("\r\n\r\nHub Descriptor:\r\n"));
     printProgStr(PSTR("bDescLength:\t\t"));
-    SERIAL_PORT_MONITOR.println(pHub->bDescLength, HEX);
+    SerialDebug.println(pHub->bDescLength, HEX);
 
     printProgStr(PSTR("bDescriptorType:\t"));
-    SERIAL_PORT_MONITOR.println(pHub->bDescriptorType, HEX);
+    SerialDebug.println(pHub->bDescriptorType, HEX);
 
     printProgStr(PSTR("bNbrPorts:\t\t"));
-    SERIAL_PORT_MONITOR.println(pHub->bNbrPorts, HEX);
+    SerialDebug.println(pHub->bNbrPorts, HEX);
 
     printProgStr(PSTR("LogPwrSwitchMode:\t"));
-    SERIAL_PORT_MONITOR.println(pHub->LogPwrSwitchMode, BIN);
+    SerialDebug.println(pHub->LogPwrSwitchMode, BIN);
 
     printProgStr(PSTR("CompoundDevice:\t\t"));
-    SERIAL_PORT_MONITOR.println(pHub->CompoundDevice, BIN);
+    SerialDebug.println(pHub->CompoundDevice, BIN);
 
     printProgStr(PSTR("OverCurrentProtectMode:\t"));
-    SERIAL_PORT_MONITOR.println(pHub->OverCurrentProtectMode, BIN);
+    SerialDebug.println(pHub->OverCurrentProtectMode, BIN);
 
     printProgStr(PSTR("TTThinkTime:\t\t"));
-    SERIAL_PORT_MONITOR.println(pHub->TTThinkTime, BIN);
+    SerialDebug.println(pHub->TTThinkTime, BIN);
 
     printProgStr(PSTR("PortIndicatorsSupported:"));
-    SERIAL_PORT_MONITOR.println(pHub->PortIndicatorsSupported, BIN);
+    SerialDebug.println(pHub->PortIndicatorsSupported, BIN);
 
     printProgStr(PSTR("Reserved:\t\t"));
-    SERIAL_PORT_MONITOR.println(pHub->Reserved, HEX);
+    SerialDebug.println(pHub->Reserved, HEX);
 
     printProgStr(PSTR("bPwrOn2PwrGood:\t\t"));
-    SERIAL_PORT_MONITOR.println(pHub->bPwrOn2PwrGood, HEX);
+    SerialDebug.println(pHub->bPwrOn2PwrGood, HEX);
 
     printProgStr(PSTR("bHubContrCurrent:\t"));
-    SERIAL_PORT_MONITOR.println(pHub->bHubContrCurrent, HEX);
+    SerialDebug.println(pHub->bHubContrCurrent, HEX);
 
     for (uint8_t i=7; i<len; i++)
         print_hex(descrptr[i], 8);
@@ -214,10 +210,11 @@ byte getconfdescr( byte addr, byte conf )
 {
   uint8_t buf[ BUFSIZE ];
   uint8_t* buf_ptr = buf;
-  byte rcode;
+  byte rcode; // FIXME -- code does not actually check return code (no error handling!)
   byte descr_length;
   byte descr_type;
   uint16_t total_length;
+  // FIXME -- no check of return code from usb.getConfDescr()
   rcode = usb.getConfDescr( addr, 0, 4, conf, buf );  //get total length
   LOBYTE( total_length ) = buf[ 2 ];
   HIBYTE( total_length ) = buf[ 3 ];
@@ -225,6 +222,7 @@ byte getconfdescr( byte addr, byte conf )
     printProgStr(Conf_Trunc_str);
     total_length = sizeof(buf);
   }
+  // FIXME -- no check of return code from usb.getConfDescr()
   rcode = usb.getConfDescr( addr, 0, total_length, conf, buf ); //get the whole descriptor
   while( buf_ptr < buf + total_length ) {  //parsing descriptors
     descr_length = *( buf_ptr );
@@ -271,7 +269,7 @@ void print_hex(int v, int num_places)
   }
   do {
     digit = ((v >> (num_nibbles-1) * 4)) & 0x0f;
-    SERIAL_PORT_MONITOR.print(digit, HEX);
+    SerialDebug.print(digit, HEX);
   }
   while(--num_nibbles);
 }
@@ -329,7 +327,7 @@ void printHIDdescr( uint8_t* descr_ptr )
     printProgStr(PSTR("\r\nNumb Class Descriptor:\t"));
 	print_hex( ep_ptr->bNumDescriptors, 8 );
     printProgStr(PSTR("\r\nDescriptor Type:\t"));
-	if( ep_ptr->bDescrType == 0x22 ) 
+	if( ep_ptr->bDescrType == 0x22 )
 		printProgStr(PSTR("REPORT DESCRIPTOR"));
 	else
 		print_hex( ep_ptr->bDescrType, 8 );
@@ -386,5 +384,5 @@ void printProgStr(const prog_char str[])
   char c;
   if(!str) return;
   while((c = pgm_read_byte(str++)))
-    SERIAL_PORT_MONITOR.print(c);
+    SerialDebug.print(c);
 }
diff --git a/libraries/USBHost/src/Usb.cpp b/libraries/USBHost/src/Usb.cpp
index 3b3b8b1c6..757d3bb32 100644
--- a/libraries/USBHost/src/Usb.cpp
+++ b/libraries/USBHost/src/Usb.cpp
@@ -429,15 +429,14 @@ uint32_t USBHost::dispatchPkt(uint32_t token, uint32_t epAddr, uint32_t nak_limi
 
 		//case hrNAK:
 		if((USB->HOST.HostPipe[epAddr].PINTFLAG.reg & USB_HOST_PINTFLAG_TRFAIL) ) {
-			USB->HOST.HostPipe[epAddr].PINTFLAG.reg = USB_HOST_PINTFLAG_TRFAIL;
-			nak_count++;
-			if(nak_limit && (nak_count == nak_limit)) {
-				rcode = USB_ERRORFLOW;
-				return (rcode);
-			}
-		}
+	 			USB->HOST.HostPipe[epAddr].PINTFLAG.reg = USB_HOST_PINTFLAG_TRFAIL;
+	 			nak_count++;
+	 			if(nak_limit && (nak_count == nak_limit)) {
+	 				rcode = USB_ERRORFLOW;
+	 				return (rcode);
+	 			}
+	  	}
 
-		//case hrNAK:
 		if( (usb_pipe_table[epAddr].HostDescBank[0].STATUS_BK.reg & USB_ERRORFLOW ) ) {
 			nak_count++;
 			if(nak_limit && (nak_count == nak_limit)) {
diff --git a/libraries/USBHost/src/confdescparser.h b/libraries/USBHost/src/confdescparser.h
index 4b2b41b4f..de69e2ccd 100644
--- a/libraries/USBHost/src/confdescparser.h
+++ b/libraries/USBHost/src/confdescparser.h
@@ -59,15 +59,15 @@ class ConfigDescParser : public USBReadParser {
 	uint32_t				ifaceNumber;		// Interface number
 	uint32_t				ifaceAltSet;		// Interface alternate settings
 
-        bool UseOr;
+	bool UseOr;
 	bool ParseDescriptor(uint8_t **pp, uint32_t *pcntdn);
 	void PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc);
 
 public:
 
-        void SetOR(void) {
-                UseOr = true;
-        }
+	void SetOR(void) {
+			UseOr = true;
+	}
 	ConfigDescParser(UsbConfigXtracter *xtractor);
 	virtual void Parse(const uint32_t len, const uint8_t *pbuf, const uint32_t &offset);
 };
@@ -98,8 +98,19 @@ void ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::Parse(const uin
   compare masks for them. When the match is found, calls EndpointXtract passing buffer containing endpoint descriptor */
 template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
 bool ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::ParseDescriptor(uint8_t **pp, uint32_t *pcntdn) {
-        USB_CONFIGURATION_DESCRIPTOR* ucd = reinterpret_cast<USB_CONFIGURATION_DESCRIPTOR*>(varBuffer);
-        USB_INTERFACE_DESCRIPTOR* uid = reinterpret_cast<USB_INTERFACE_DESCRIPTOR*>(varBuffer);
+	USB_CONFIGURATION_DESCRIPTOR* ucd = reinterpret_cast<USB_CONFIGURATION_DESCRIPTOR*>(varBuffer);
+	USB_INTERFACE_DESCRIPTOR* uid = reinterpret_cast<USB_INTERFACE_DESCRIPTOR*>(varBuffer);
+
+
+#pragma GCC diagnostic push // Available since GCC 4.6.4
+/*
+ * FIXME -- Enabled and review all `-Wimplicit-fallthrough` messages
+ * This code has multiple switch statements that "fall through" to the
+ * next case -- but it's not always clear if this is intentional or not.
+ * Review and commenting of code, and reducing cyclomatic complexity
+ * are highly recommended....
+ */
+#pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
 	switch(stateParseDescr) {
 		case 0:
 			theBuffer.valueSize = 2;
@@ -112,7 +123,7 @@ bool ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::ParseDescriptor
 			dscrType		= *((uint8_t*)theBuffer.pValue + 1);
 			stateParseDescr	= 2;
 		case 2:
-                        // This is a sort of hack. Assuming that two bytes are all ready in the buffer
+			// This is a sort of hack. Assuming that two bytes are all ready in the buffer
 			//	the pointer is positioned two bytes ahead in order for the rest of descriptor
 			//	to be read right after the size and the type fields.
 			// This should be used carefully. varBuffer should be used directly to handle data
@@ -120,14 +131,14 @@ bool ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::ParseDescriptor
 			theBuffer.pValue	= varBuffer + 2;
 			stateParseDescr		= 3;
 		case 3:
-                        switch(dscrType) {
-                                case USB_DESCRIPTOR_INTERFACE:
-                                        isGoodInterface = false;
-                                case USB_DESCRIPTOR_CONFIGURATION:
-                                        theBuffer.valueSize = sizeof (USB_CONFIGURATION_DESCRIPTOR) - 2;
-                                        break;
-                                case USB_DESCRIPTOR_ENDPOINT:
-                                        theBuffer.valueSize = sizeof (USB_ENDPOINT_DESCRIPTOR) - 2;
+			switch(dscrType) {
+				case USB_DESCRIPTOR_INTERFACE:
+					isGoodInterface = false;
+				case USB_DESCRIPTOR_CONFIGURATION:
+					theBuffer.valueSize = sizeof (USB_CONFIGURATION_DESCRIPTOR) - 2;
+					break;
+				case USB_DESCRIPTOR_ENDPOINT:
+					theBuffer.valueSize = sizeof (USB_ENDPOINT_DESCRIPTOR) - 2;
 					break;
 				case HID_DESCRIPTOR_HID:
 					theBuffer.valueSize = dscrLen - 2;
@@ -136,37 +147,37 @@ bool ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::ParseDescriptor
 			valParser.Initialize(&theBuffer);
 			stateParseDescr		= 4;
 		case 4:
-                        switch(dscrType) {
+			switch(dscrType) {
 				case USB_DESCRIPTOR_CONFIGURATION:
-                                        if(!valParser.Parse(pp, pcntdn))
-                                                return false;
-                                        confValue = ucd->bConfigurationValue;
+					if(!valParser.Parse(pp, pcntdn))
+							return false;
+					confValue = ucd->bConfigurationValue;
 					break;
 				case USB_DESCRIPTOR_INTERFACE:
-                                        if(!valParser.Parse(pp, pcntdn))
-                                                return false;
-                                        if((MASK & CP_MASK_COMPARE_CLASS) && uid->bInterfaceClass != CLASS_ID)
-                                                break;
-                                        if((MASK & CP_MASK_COMPARE_SUBCLASS) && uid->bInterfaceSubClass != SUBCLASS_ID)
-                                                break;
-                                        if(UseOr) {
-                                                if((!((MASK & CP_MASK_COMPARE_PROTOCOL) && uid->bInterfaceProtocol)))
-                                                        break;
-                                        } else {
-                                                if((MASK & CP_MASK_COMPARE_PROTOCOL) && uid->bInterfaceProtocol != PROTOCOL_ID)
-                                                        break;
-                                        }
-                                        isGoodInterface = true;
-                                        ifaceNumber = uid->bInterfaceNumber;
-                                        ifaceAltSet = uid->bAlternateSetting;
-                                        protoValue = uid->bInterfaceProtocol;
-                                        break;
-                                case USB_DESCRIPTOR_ENDPOINT:
-                                        if(!valParser.Parse(pp, pcntdn))
-                                                return false;
-                                        if(isGoodInterface)
-                                                if(theXtractor)
-							theXtractor->EndpointXtract(confValue, ifaceNumber, ifaceAltSet, protoValue, (USB_ENDPOINT_DESCRIPTOR*)varBuffer);
+					if(!valParser.Parse(pp, pcntdn))
+							return false;
+					if((MASK & CP_MASK_COMPARE_CLASS) && uid->bInterfaceClass != CLASS_ID)
+							break;
+					if((MASK & CP_MASK_COMPARE_SUBCLASS) && uid->bInterfaceSubClass != SUBCLASS_ID)
+							break;
+					if(UseOr) {
+							if((!((MASK & CP_MASK_COMPARE_PROTOCOL) && uid->bInterfaceProtocol)))
+									break;
+					} else {
+							if((MASK & CP_MASK_COMPARE_PROTOCOL) && uid->bInterfaceProtocol != PROTOCOL_ID)
+									break;
+					}
+					isGoodInterface = true;
+					ifaceNumber = uid->bInterfaceNumber;
+					ifaceAltSet = uid->bAlternateSetting;
+					protoValue = uid->bInterfaceProtocol;
+					break;
+				case USB_DESCRIPTOR_ENDPOINT:
+						if(!valParser.Parse(pp, pcntdn))
+								return false;
+						if(isGoodInterface)
+								if(theXtractor)
+									theXtractor->EndpointXtract(confValue, ifaceNumber, ifaceAltSet, protoValue, (USB_ENDPOINT_DESCRIPTOR*)varBuffer);
 					break;
 				//case HID_DESCRIPTOR_HID:
 				//	if (!valParser.Parse(pp, pcntdn))
@@ -180,44 +191,47 @@ bool ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::ParseDescriptor
 			theBuffer.pValue = varBuffer;
 			stateParseDescr = 0;
 	}
+#pragma GCC diagnostic pop
+
 	return true;
 }
 
 template <const uint8_t CLASS_ID, const uint8_t SUBCLASS_ID, const uint8_t PROTOCOL_ID, const uint8_t MASK>
 void ConfigDescParser<CLASS_ID, SUBCLASS_ID, PROTOCOL_ID, MASK>::PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc) {
-        Notify(PSTR("\r\n\r\nHID Descriptor:\r\n"), 0x80);
-        Notify(PSTR("bDescLength:\t\t"), 0x80);
-        PrintHex<uint8_t > (pDesc->bLength, 0x80);
+	Notify(PSTR("\r\n\r\nHID Descriptor:\r\n"), 0x80);
+	Notify(PSTR("bDescLength:\t\t"), 0x80);
+	PrintHex<uint8_t > (pDesc->bLength, 0x80);
 
-        Notify(PSTR("\r\nbDescriptorType:\t"), 0x80);
-        PrintHex<uint8_t > (pDesc->bDescriptorType, 0x80);
+	Notify(PSTR("\r\nbDescriptorType:\t"), 0x80);
+	PrintHex<uint8_t > (pDesc->bDescriptorType, 0x80);
 
-        Notify(PSTR("\r\nbcdHID:\t\t\t"), 0x80);
-        PrintHex<uint16_t > (pDesc->bcdHID, 0x80);
+	Notify(PSTR("\r\nbcdHID:\t\t\t"), 0x80);
+	PrintHex<uint16_t > (pDesc->bcdHID, 0x80);
 
-        Notify(PSTR("\r\nbCountryCode:\t\t"), 0x80);
-        PrintHex<uint8_t > (pDesc->bCountryCode, 0x80);
+	Notify(PSTR("\r\nbCountryCode:\t\t"), 0x80);
+	PrintHex<uint8_t > (pDesc->bCountryCode, 0x80);
 
-        Notify(PSTR("\r\nbNumDescriptors:\t"), 0x80);
-        PrintHex<uint8_t > (pDesc->bNumDescriptors, 0x80);
+	Notify(PSTR("\r\nbNumDescriptors:\t"), 0x80);
+	PrintHex<uint8_t > (pDesc->bNumDescriptors, 0x80);
 
-        //Notify(PSTR("\r\nbDescrType:\t\t"));
-        //PrintHex<uint8_t>(pDesc->bDescrType);
-        //
-        //Notify(PSTR("\r\nwDescriptorLength:\t"));
-        //PrintHex<uint16_t>(pDesc->wDescriptorLength);
+	//Notify(PSTR("\r\nbDescrType:\t\t"));
+	//PrintHex<uint8_t>(pDesc->bDescrType);
+	//
+	//Notify(PSTR("\r\nwDescriptorLength:\t"));
+	//PrintHex<uint16_t>(pDesc->wDescriptorLength);
 
 	for (uint32_t i = 0; i < pDesc->bNumDescriptors; i++) {
 		HID_CLASS_DESCRIPTOR_LEN_AND_TYPE	*pLT = (HID_CLASS_DESCRIPTOR_LEN_AND_TYPE*)&(pDesc->bDescrType);
 
-                Notify(PSTR("\r\nbDescrType:\t\t"), 0x80);
-                PrintHex<uint8_t > (pLT[i].bDescrType, 0x80);
+		Notify(PSTR("\r\nbDescrType:\t\t"), 0x80);
+		PrintHex<uint8_t > (pLT[i].bDescrType, 0x80);
 
-                Notify(PSTR("\r\nwDescriptorLength:\t"), 0x80);
-                PrintHex<uint16_t > (pLT[i].wDescriptorLength, 0x80);
-        }
-        Notify(PSTR("\r\n"), 0x80);
+		Notify(PSTR("\r\nwDescriptorLength:\t"), 0x80);
+		PrintHex<uint16_t > (pLT[i].wDescriptorLength, 0x80);
+	}
+	Notify(PSTR("\r\n"), 0x80);
 }
 
 
+
 #endif // __CONFDESCPARSER_H__
diff --git a/libraries/USBHost/src/hidescriptorparser.cpp b/libraries/USBHost/src/hidescriptorparser.cpp
index 353874300..b137cb8ab 100644
--- a/libraries/USBHost/src/hidescriptorparser.cpp
+++ b/libraries/USBHost/src/hidescriptorparser.cpp
@@ -994,7 +994,6 @@ void ReportDescParserBase::Parse(const uint32_t len, const uint8_t *pbuf, const
         uint32_t cntdn = (uint32_t)len;
         uint8_t *p = (uint8_t*)pbuf;
 
-
         totalSize = 0;
 
         while(cntdn) {
@@ -1091,6 +1090,17 @@ void ReportDescParserBase::PrintItemTitle(uint8_t prefix) {
 uint8_t ReportDescParserBase::ParseItem(uint8_t **pp, uint32_t *pcntdn) {
         //uint8_t	ret = enErrorSuccess;
         //reinterpret_cast<>(varBuffer);
+
+
+#pragma GCC diagnostic push // Available since GCC 4.6.4
+/*
+ * FIXME -- Enabled and review all `-Wimplicit-fallthrough` messages
+ * This code has multiple switch statements that "fall through" to the
+ * next case -- but it's not always clear if this is intentional or not.
+ * Review and commenting of code, and reducing cyclomatic complexity
+ * are highly recommended....
+ */
+#pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
         switch(itemParseState) {
                 case 0:
                         if(**pp == HID_LONG_ITEM_PREFIX)
@@ -1207,6 +1217,7 @@ uint8_t ReportDescParserBase::ParseItem(uint8_t **pp, uint32_t *pcntdn) {
                         } // switch (**pp & (TYPE_MASK | TAG_MASK))
                 }
         } // switch (itemParseState)
+#pragma GCC diagnostic pop
         itemParseState = 0;
         return enErrorSuccess;
 }
@@ -1236,18 +1247,18 @@ void ReportDescParserBase::SetUsagePage(uint16_t page) {
         if(VALUE_BETWEEN(page, 0x00, 0x11))
                 pfUsage = (usagePageFunctions[page - 1]);
 
-                // Dead code...
-                //
-                //      pfUsage = (UsagePageFunc)pgm_read_pointer(usagePageFunctions[page - 1]);
-                //else if (page > 0x7f && page < 0x84)
-                //      E_Notify(pstrUsagePageMonitor);
-                //else if (page > 0x83 && page < 0x8c)
-                //	E_Notify(pstrUsagePagePower);
-                //else if (page > 0x8b && page < 0x92)
-                //	E_Notify((char*)pgm_read_pointer(&usagePageTitles1[page - 0x8c]));
-                //else if (page > 0xfeff && page <= 0xffff)
-                //	E_Notify(pstrUsagePageVendorDefined);
-                //
+        // Dead code...
+        //
+        //      pfUsage = (UsagePageFunc)pgm_read_pointer(usagePageFunctions[page - 1]);
+        //else if (page > 0x7f && page < 0x84)
+        //      E_Notify(pstrUsagePageMonitor);
+        //else if (page > 0x83 && page < 0x8c)
+        //	E_Notify(pstrUsagePagePower);
+        //else if (page > 0x8b && page < 0x92)
+        //	E_Notify((char*)pgm_read_pointer(&usagePageTitles1[page - 0x8c]));
+        //else if (page > 0xfeff && page <= 0xffff)
+        //	E_Notify(pstrUsagePageVendorDefined);
+        //
         else
                 switch(page) {
                         case 0x14:
@@ -1440,6 +1451,15 @@ void ReportDescParserBase::PrintMedicalInstrumentPageUsage(uint16_t usage) {
 uint8_t ReportDescParser2::ParseItem(uint8_t **pp, uint32_t *pcntdn) {
         //uint8_t	ret = enErrorSuccess;
 
+#pragma GCC diagnostic push // Available since GCC 4.6.4
+/*
+ * FIXME -- Enabled and review all `-Wimplicit-fallthrough` messages
+ * This code has multiple switch statements that "fall through" to the
+ * next case -- but it's not always clear if this is intentional or not.
+ * Review and commenting of code, and reducing cyclomatic complexity
+ * are highly recommended....
+ */
+#pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
         switch(itemParseState) {
                 case 0:
                         if(**pp == HID_LONG_ITEM_PREFIX)
@@ -1519,6 +1539,8 @@ uint8_t ReportDescParser2::ParseItem(uint8_t **pp, uint32_t *pcntdn) {
                         } // switch (**pp & (TYPE_MASK | TAG_MASK))
                 }
         } // switch (itemParseState)
+#pragma GCC diagnostic pop
+
         itemParseState = 0;
         return enErrorSuccess;
 }
@@ -1558,8 +1580,7 @@ void ReportDescParser2::OnInputItem(uint8_t itm) {
                 // bits_to_copy		- number of bits to copy to result buffer
 
                 // for each bit in a field
-                for(uint8_t bits_left = rptSize, bits_to_copy = 0; bits_left;
-                        bits_left -= bits_to_copy) {
+                for(uint8_t bits_left = rptSize, bits_to_copy = 0; bits_left; bits_left -= bits_to_copy) {
                         bits_to_copy = (bits_left > bits_of_byte) ? bits_of_byte : bits_left;
 
                         result.dwResult <<= bits_to_copy; // Result buffer is shifted by the number of bits to be copied into it
diff --git a/libraries/USBHost/src/parsetools.cpp b/libraries/USBHost/src/parsetools.cpp
index 00ca9e642..9867cbc46 100644
--- a/libraries/USBHost/src/parsetools.cpp
+++ b/libraries/USBHost/src/parsetools.cpp
@@ -17,14 +17,14 @@ e-mail   :  support@circuitsathome.com
 #include "Usb.h"
 
 bool MultiByteValueParser::Parse(uint8_t **pp, uint32_t *pcntdn) {
-        if(!pBuf) {
-                Notify(PSTR("Buffer pointer is NULL!\r\n"), 0x80);
+	if(!pBuf) {
+		Notify(PSTR("Buffer pointer is NULL!\r\n"), 0x80);
 		return false;
 	}
 	for (; countDown && (*pcntdn); countDown--, (*pcntdn)--, (*pp)++)
 		pBuf[valueSize - countDown] = (**pp);
 
-        if(countDown)
+	if(countDown)
 		return false;
 
 	countDown = valueSize;
@@ -32,36 +32,48 @@ bool MultiByteValueParser::Parse(uint8_t **pp, uint32_t *pcntdn) {
 }
 
 bool PTPListParser::Parse(uint8_t **pp, uint32_t *pcntdn, PTP_ARRAY_EL_FUNC pf, const void *me) {
-        switch(nStage) {
-	case 0:
-		pBuf->valueSize = lenSize;
-		theParser.Initialize(pBuf);
-		nStage = 1;
 
-	case 1:
-		if(!theParser.Parse(pp, pcntdn))
-			return false;
+#pragma GCC diagnostic push // Available since GCC 4.6.4
+/*
+ * FIXME -- Enabled and review all `-Wimplicit-fallthrough` messages
+ * This code has multiple switch statements that "fall through" to the
+ * next case -- but it's not always clear if this is intentional or not.
+ * Review and commenting of code, and reducing cyclomatic complexity
+ * are highly recommended....
+ */
+#pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
 
-		arLen = 0;
-		arLen = (pBuf->valueSize >= 4) ? *((uint32_t*)pBuf->pValue) : (uint32_t)(*((uint16_t*)pBuf->pValue));
-		arLenCntdn = arLen;
-		nStage = 2;
+	switch(nStage) {
+		case 0:
+			pBuf->valueSize = lenSize;
+			theParser.Initialize(pBuf);
+			nStage = 1;
 
-	case 2:
-		pBuf->valueSize = valSize;
-		theParser.Initialize(pBuf);
-		nStage = 3;
-
-	case 3:
-                for(; arLenCntdn; arLenCntdn--) {
+		case 1:
 			if(!theParser.Parse(pp, pcntdn))
 				return false;
 
+			arLen = 0;
+			arLen = (pBuf->valueSize >= 4) ? *((uint32_t*)pBuf->pValue) : (uint32_t)(*((uint16_t*)pBuf->pValue));
+			arLenCntdn = arLen;
+			nStage = 2;
+
+		case 2:
+			pBuf->valueSize = valSize;
+			theParser.Initialize(pBuf);
+			nStage = 3;
+
+		case 3:
+			for(; arLenCntdn; arLenCntdn--) {
+				if(!theParser.Parse(pp, pcntdn))
+					return false;
+
 			if(pf)
 				pf(pBuf, (arLen - arLenCntdn), me);
 		}
-
 		nStage = 0;
 	}
+#pragma GCC diagnostic pop
+
 	return true;
 }
diff --git a/libraries/USBHost/src/parsetools.h b/libraries/USBHost/src/parsetools.h
index d46335891..947ba02dc 100644
--- a/libraries/USBHost/src/parsetools.h
+++ b/libraries/USBHost/src/parsetools.h
@@ -35,12 +35,12 @@ class MultiByteValueParser {
 
 public:
 
-        MultiByteValueParser() : pBuf(NULL), countDown(0), valueSize(0) {
-        };
+	MultiByteValueParser() : pBuf(NULL), countDown(0), valueSize(0) {
+	};
 
-        const uint8_t* GetBuffer() {
-                return pBuf;
-        };
+	const uint8_t* GetBuffer() {
+		return pBuf;
+	};
 
 	void Initialize(MultiValueBuffer * const pbuf) {
 		pBuf = (uint8_t*)pbuf->pValue;
@@ -58,7 +58,7 @@ class ByteSkipper {
 public:
 
 	ByteSkipper() : pBuf(NULL), nStage(0), countDown(0) {
-        };
+	};
 
 	void Initialize(MultiValueBuffer *pbuf) {
 		pBuf = (uint8_t*)pbuf->pValue;
@@ -66,16 +66,25 @@ class ByteSkipper {
 	};
 
 	bool Skip(uint8_t **pp, uint32_t *pcntdn, uint32_t bytes_to_skip) {
-                switch(nStage) {
-                       case 0:
-                                countDown = bytes_to_skip;
-                                nStage++;
-                        case 1:
-                                for(; countDown && (*pcntdn); countDown--, (*pp)++, (*pcntdn)--);
-
-                                if(!countDown)
-                                        nStage = 0;
+#pragma GCC diagnostic push // Available since GCC 4.6.4
+/*
+ * FIXME -- Enabled and review all `-Wimplicit-fallthrough` messages
+ * This code has multiple switch statements that "fall through" to the
+ * next case -- but it's not always clear if this is intentional or not.
+ * Review and commenting of code, and reducing cyclomatic complexity
+ * are highly recommended....
+ */
+#pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
+		switch(nStage) {
+			case 0:
+				countDown = bytes_to_skip;
+				nStage++;
+			case 1:
+				for(; countDown && (*pcntdn); countDown--, (*pp)++, (*pcntdn)--);
+				if(!countDown)
+					nStage = 0;
 		};
+#pragma GCC diagnostic pop
 		return (!countDown);
 	};
 };
@@ -86,9 +95,9 @@ typedef void (*PTP_ARRAY_EL_FUNC)(const MultiValueBuffer * const p, uint32_t cou
 class PTPListParser {
 public:
 
-        enum ParseMode {
-                modeArray, modeRange/*, modeEnum*/
-        };
+	enum ParseMode {
+			modeArray, modeRange/*, modeEnum*/
+	};
 
 private:
 	uint32_t				nStage;
diff --git a/libraries/Wire/Wire.cpp b/libraries/Wire/Wire.cpp
index b94389b0a..ec3634133 100644
--- a/libraries/Wire/Wire.cpp
+++ b/libraries/Wire/Wire.cpp
@@ -287,6 +287,13 @@ void TwoWire::onService(void)
   void WIRE_IT_HANDLER(void) {
     Wire.onService();
   }
+
+  #if defined(__SAMD51__)
+    void WIRE_IT_HANDLER_0(void) { Wire.onService(); }
+    void WIRE_IT_HANDLER_1(void) { Wire.onService(); }
+    void WIRE_IT_HANDLER_2(void) { Wire.onService(); }
+    void WIRE_IT_HANDLER_3(void) { Wire.onService(); }
+  #endif // __SAMD51__
 #endif
 
 #if WIRE_INTERFACES_COUNT > 1
@@ -295,6 +302,13 @@ void TwoWire::onService(void)
   void WIRE1_IT_HANDLER(void) {
     Wire1.onService();
   }
+
+  #if defined(__SAMD51__)
+    void WIRE1_IT_HANDLER_0(void) { Wire1.onService(); }
+    void WIRE1_IT_HANDLER_1(void) { Wire1.onService(); }
+    void WIRE1_IT_HANDLER_2(void) { Wire1.onService(); }
+    void WIRE1_IT_HANDLER_3(void) { Wire1.onService(); }
+  #endif // __SAMD51__
 #endif
 
 #if WIRE_INTERFACES_COUNT > 2
@@ -303,6 +317,13 @@ void TwoWire::onService(void)
   void WIRE2_IT_HANDLER(void) {
     Wire2.onService();
   }
+
+  #if defined(__SAMD51__)
+    void WIRE2_IT_HANDLER_0(void) { Wire2.onService(); }
+    void WIRE2_IT_HANDLER_1(void) { Wire2.onService(); }
+    void WIRE2_IT_HANDLER_2(void) { Wire2.onService(); }
+    void WIRE2_IT_HANDLER_3(void) { Wire2.onService(); }
+  #endif // __SAMD51__
 #endif
 
 #if WIRE_INTERFACES_COUNT > 3
@@ -311,6 +332,13 @@ void TwoWire::onService(void)
   void WIRE3_IT_HANDLER(void) {
     Wire3.onService();
   }
+
+  #if defined(__SAMD51__)
+    void WIRE3_IT_HANDLER_0(void) { Wire3.onService(); }
+    void WIRE3_IT_HANDLER_1(void) { Wire3.onService(); }
+    void WIRE3_IT_HANDLER_2(void) { Wire3.onService(); }
+    void WIRE3_IT_HANDLER_3(void) { Wire3.onService(); }
+  #endif // __SAMD51__
 #endif
 
 #if WIRE_INTERFACES_COUNT > 4
@@ -319,6 +347,13 @@ void TwoWire::onService(void)
   void WIRE4_IT_HANDLER(void) {
     Wire4.onService();
   }
+
+  #if defined(__SAMD51__)
+    void WIRE4_IT_HANDLER_0(void) { Wire4.onService(); }
+    void WIRE4_IT_HANDLER_1(void) { Wire4.onService(); }
+    void WIRE4_IT_HANDLER_2(void) { Wire4.onService(); }
+    void WIRE4_IT_HANDLER_3(void) { Wire4.onService(); }
+  #endif // __SAMD51__
 #endif
 
 #if WIRE_INTERFACES_COUNT > 5
@@ -327,5 +362,12 @@ void TwoWire::onService(void)
   void WIRE5_IT_HANDLER(void) {
     Wire5.onService();
   }
+
+  #if defined(__SAMD51__)
+    void WIRE5_IT_HANDLER_0(void) { Wire5.onService(); }
+    void WIRE5_IT_HANDLER_1(void) { Wire5.onService(); }
+    void WIRE5_IT_HANDLER_2(void) { Wire5.onService(); }
+    void WIRE5_IT_HANDLER_3(void) { Wire5.onService(); }
+  #endif // __SAMD51__
 #endif
 
diff --git a/libraries/Wire/examples/slave_receiver/slave_receiver.ino b/libraries/Wire/examples/slave_receiver/slave_receiver.ino
index 60dd4bdde..a3103f8b9 100644
--- a/libraries/Wire/examples/slave_receiver/slave_receiver.ino
+++ b/libraries/Wire/examples/slave_receiver/slave_receiver.ino
@@ -28,6 +28,8 @@ void loop()
 // this function is registered as an event, see setup()
 void receiveEvent(int howMany)
 {
+  (void)howMany; // avoid compiler warning about unused parameter
+  
   while(1 < Wire.available()) // loop through all but the last
   {
     char c = Wire.read(); // receive byte as a character
diff --git a/platform.txt b/platform.txt
index 2a2e59cc3..1e71e42af 100644
--- a/platform.txt
+++ b/platform.txt
@@ -19,8 +19,8 @@
 # For more info:
 # https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5---3rd-party-Hardware-specification
 
-name=Arduino SAMD (32-bits ARM Cortex-M0+) Boards
-version=1.6.21
+name=Adafruit SAMD (32-bits ARM Cortex-M0+ and Cortex-M4) Boards
+version=1.6.8
 
 # Compile variables
 # -----------------
@@ -28,18 +28,18 @@ version=1.6.21
 compiler.warning_flags=-w
 compiler.warning_flags.none=-w
 compiler.warning_flags.default=
-compiler.warning_flags.more=-Wall
-compiler.warning_flags.all=-Wall -Wextra
+compiler.warning_flags.more=-Wall -Wno-expansion-to-defined
+compiler.warning_flags.all=-Wall -Wextra -Wno-expansion-to-defined
 
-compiler.path={runtime.tools.arm-none-eabi-gcc-4.8.3-2014q1.path}/bin/
+compiler.path={runtime.tools.arm-none-eabi-gcc.path}/bin/
 compiler.c.cmd=arm-none-eabi-gcc
-compiler.c.flags=-mcpu={build.mcu} -mthumb -c -g -Os {compiler.warning_flags} -std=gnu11 -ffunction-sections -fdata-sections -nostdlib --param max-inline-insns-single=500 -MMD
+compiler.c.flags=-mcpu={build.mcu} -mthumb -c -g -Os {compiler.warning_flags} -std=gnu11 -ffunction-sections -fdata-sections -nostdlib --param max-inline-insns-single=500 -MMD -D__SKETCH_NAME__="""{build.project_name}"""
 compiler.c.elf.cmd=arm-none-eabi-g++
 compiler.c.elf.flags=-Os -Wl,--gc-sections -save-temps
 compiler.S.cmd=arm-none-eabi-gcc
 compiler.S.flags=-c -g -x assembler-with-cpp -MMD
 compiler.cpp.cmd=arm-none-eabi-g++
-compiler.cpp.flags=-mcpu={build.mcu} -mthumb -c -g -Os {compiler.warning_flags} -std=gnu++11 -ffunction-sections -fdata-sections -fno-threadsafe-statics -nostdlib --param max-inline-insns-single=500 -fno-rtti -fno-exceptions -MMD
+compiler.cpp.flags=-mcpu={build.mcu} -mthumb -c -g -Os {compiler.warning_flags} -std=gnu++11 -ffunction-sections -fdata-sections -fno-threadsafe-statics -nostdlib --param max-inline-insns-single=500 -fno-rtti -fno-exceptions -MMD -D__SKETCH_NAME__="""{build.project_name}"""
 compiler.ar.cmd=arm-none-eabi-ar
 compiler.ar.flags=rcs
 compiler.objcopy.cmd=arm-none-eabi-objcopy
@@ -54,6 +54,12 @@ compiler.readelf.cmd=arm-none-eabi-readelf
 
 # this can be overriden in boards.txt
 build.extra_flags=
+build.cache_flags=
+build.flags.optimize=
+build.flags.maxspi=
+build.flags.maxqspi=
+build.flags.usbstack=
+build.flags.debug=
 
 # These can be overridden in platform.local.txt
 compiler.c.extra_flags=
@@ -64,28 +70,34 @@ compiler.S.extra_flags=
 compiler.ar.extra_flags=
 compiler.elf2hex.extra_flags=
 
-compiler.arm.cmsis.c.flags="-I{runtime.tools.CMSIS-4.5.0.path}/CMSIS/Include/" "-I{runtime.tools.CMSIS-Atmel-1.1.0.path}/CMSIS/Device/ATMEL/"
-compiler.arm.cmsis.ldflags="-L{runtime.tools.CMSIS-4.5.0.path}/CMSIS/Lib/GCC/" -larm_cortexM0l_math
+compiler.arm.cmsis.c.flags="-I{runtime.tools.CMSIS-5.4.0.path}/CMSIS/Core/Include/" "-I{runtime.tools.CMSIS-5.4.0.path}/CMSIS/DSP/Include/" "-I{runtime.tools.CMSIS-Atmel-1.2.1.path}/CMSIS/Device/ATMEL/"
+compiler.arm.cmsis.ldflags="-L{runtime.tools.CMSIS-5.4.0.path}/CMSIS/Lib/GCC/" -larm_cortexM0l_math
+
+compiler.libraries.ldflags=
 
 # USB Flags
 # ---------
-build.usb_flags=-DUSB_VID={build.vid} -DUSB_PID={build.pid} -DUSBCON '-DUSB_MANUFACTURER={build.usb_manufacturer}' '-DUSB_PRODUCT={build.usb_product}'
+build.usb_flags=-DUSB_VID={build.vid} -DUSB_PID={build.pid} -DUSBCON -DUSB_CONFIG_POWER={build.usb_power} '-DUSB_MANUFACTURER={build.usb_manufacturer}' '-DUSB_PRODUCT={build.usb_product}' {build.flags.usbstack} {build.flags.debug} "-I{build.core.path}/TinyUSB" "-I{build.core.path}/TinyUSB/Adafruit_TinyUSB_ArduinoCore" "-I{build.core.path}/TinyUSB/Adafruit_TinyUSB_ArduinoCore/tinyusb/src"
+
+# Default advertised device power setting in mA
+build.usb_power=100
 
 # Default usb manufacturer will be replaced at compile time using
 # numeric vendor ID if available or by board's specific value.
 build.usb_manufacturer="Unknown"
 
+
 # Compile patterns
 # ----------------
 
 ## Compile c files
-recipe.c.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.c.flags} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.c.extra_flags} {build.extra_flags} {compiler.arm.cmsis.c.flags} {includes} "{source_file}" -o "{object_file}"
+recipe.c.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.c.flags} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.c.extra_flags} {build.extra_flags} {build.cache_flags}  {build.flags.debug} {build.flags.optimize} {build.flags.maxspi} {build.flags.maxqspi} {compiler.arm.cmsis.c.flags} {includes} "{source_file}" -o "{object_file}"
 
 ## Compile c++ files
-recipe.cpp.o.pattern="{compiler.path}{compiler.cpp.cmd}" {compiler.cpp.flags} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.cpp.extra_flags} {build.extra_flags} {compiler.arm.cmsis.c.flags} {includes} "{source_file}" -o "{object_file}"
+recipe.cpp.o.pattern="{compiler.path}{compiler.cpp.cmd}" {compiler.cpp.flags} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.cpp.extra_flags} {build.extra_flags} {build.cache_flags} {build.flags.debug} {build.flags.optimize} {build.flags.maxspi} {build.flags.maxqspi} {build.extra_flags} {compiler.arm.cmsis.c.flags} {includes} "{source_file}" -o "{object_file}"
 
 ## Compile S files
-recipe.S.o.pattern="{compiler.path}{compiler.S.cmd}" {compiler.S.flags} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.S.extra_flags} {build.extra_flags} {compiler.arm.cmsis.c.flags} {includes} "{source_file}" -o "{object_file}"
+recipe.S.o.pattern="{compiler.path}{compiler.S.cmd}" {compiler.S.flags} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.S.extra_flags} {build.extra_flags} {build.cache_flags} {compiler.arm.cmsis.c.flags} {includes} "{source_file}" -o "{object_file}"
 
 ## Create archives
 # archive_file_path is needed for backwards compatibility with IDE 1.6.5 or older, IDE 1.6.6 or newer overrides this value
@@ -93,7 +105,7 @@ archive_file_path={build.path}/{archive_file}
 recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{archive_file_path}" "{object_file}"
 
 ## Combine gc-sections, archives, and objects
-recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}"  "-L{build.path}" {compiler.c.elf.flags} {compiler.c.elf.extra_flags} "-T{build.variant.path}/{build.ldscript}" "-Wl,-Map,{build.path}/{build.project_name}.map" --specs=nano.specs --specs=nosys.specs {compiler.ldflags} -o "{build.path}/{build.project_name}.elf" {object_files} -Wl,--start-group {compiler.arm.cmsis.ldflags} -lm "{build.path}/{archive_file}" -Wl,--end-group
+recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}"  "-L{build.path}" {compiler.c.elf.flags} {compiler.c.elf.extra_flags} "-T{build.variant.path}/{build.ldscript}" "-Wl,-Map,{build.path}/{build.project_name}.map" --specs=nano.specs --specs=nosys.specs {compiler.ldflags} -o "{build.path}/{build.project_name}.elf" {object_files} {compiler.libraries.ldflags} -Wl,--start-group {compiler.arm.cmsis.ldflags} "-L{build.variant.path}" -lm "{build.path}/{archive_file}" -Wl,--end-group
 
 ## Create output (bin file)
 recipe.objcopy.bin.pattern="{compiler.path}{compiler.elf2hex.cmd}" {compiler.elf2hex.bin.flags} {compiler.elf2hex.extra_flags} "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.bin"
@@ -111,30 +123,10 @@ recipe.output.save_file={build.project_name}.{build.variant}.{build.preferred_ou
 recipe.size.pattern="{compiler.path}{compiler.size.cmd}" -A "{build.path}/{build.project_name}.elf"
 recipe.size.regex=\.text\s+([0-9]+).*
 
-# Uploader tools
-# --------------
-
-#
-# AVRDUDE
-#
-tools.avrdude.path={runtime.tools.avrdude.path}
-tools.avrdude.cmd={path}/bin/avrdude
-tools.avrdude.config.path={path}/etc/avrdude.conf
-
-tools.avrdude.upload.params.verbose=-v -v
-tools.avrdude.upload.params.quiet=-q -q
-tools.avrdude.upload.params.noverify=-V
-tools.avrdude.upload.pattern="{cmd}" "-C{config.path}" {upload.verbose} -p{build.emu.mcu} -c{upload.protocol} -P{serial.port} -b{upload.speed} "-Uflash:w:{build.path}/{build.project_name}.hex:i"
-
-tools.avrdude_remote.upload.pattern="openocd --version 2>&1 | grep 2016 && if opkg update; then opkg upgrade openocd; exit 1; else echo 'Please connect your board to the Internet in order to upgrade tools' >&2; exit 1; fi || /usr/bin/run-avrdude /tmp/sketch.hex"
-
-tools.avrdude.network_cmd={runtime.tools.arduinoOTA.path}/bin/arduinoOTA
-tools.avrdude.upload.network_pattern="{network_cmd}" -address {serial.port} -port 65280 -username arduino -password "{network.password}" -sketch "{build.path}/{build.project_name}.bin" -upload /sketch -b
-
 #
 # BOSSA
 #
-tools.bossac.path={runtime.tools.bossac-1.7.0.path}
+tools.bossac.path={runtime.tools.bossac-1.7.0-arduino3.path}
 tools.bossac.cmd=bossac
 tools.bossac.cmd.windows=bossac.exe
 
@@ -147,17 +139,46 @@ tools.bossac_remote.upload.pattern=/usr/bin/run-bossac {upload.verbose} --port=t
 tools.bossac.network_cmd={runtime.tools.arduinoOTA.path}/bin/arduinoOTA
 tools.bossac.upload.network_pattern="{network_cmd}" -address {serial.port} -port 65280 -username arduino -password "{network.password}" -sketch "{build.path}/{build.project_name}.bin" -upload /sketch -b
 
+# v1.8.0
+
+tools.bossac18.path={runtime.tools.bossac-1.8.0-48-gb176eee.path}
+tools.bossac18.cmd=bossac
+
+tools.bossac18.upload.params.verbose=-i -d
+tools.bossac18.upload.params.quiet=
+tools.bossac18.upload.pattern="{path}/{cmd}" {upload.verbose} --port={serial.port.file} -U -i --offset={upload.offset} -w -v "{build.path}/{build.project_name}.bin" -R
+
+tools.bossac18.network_cmd={runtime.tools.arduinoOTA.path}/bin/arduinoOTA
+tools.bossac18.upload.network_pattern="{network_cmd}" -address {serial.port} -port 65280 -username arduino -password "{network.password}" -sketch "{build.path}/{build.project_name}.bin" -upload /sketch -b
+
+#
+# BOSSA (ignore binary size)
+#
+tools.bossacI.path={runtime.tools.bossac-1.7.0-arduino3.path}
+tools.bossacI.cmd=bossac
+tools.bossacI.cmd.windows=bossac.exe
+
+tools.bossacI.upload.params.verbose=-i -d
+tools.bossacI.upload.params.quiet=
+tools.bossacI.upload.pattern="{path}/{cmd}" {upload.verbose} --port={serial.port.file} -I -U {upload.native_usb} -i -e -w "{build.path}/{build.project_name}.bin" -R
+
+tools.bossacI_remote.upload.pattern=/usr/bin/run-bossac {upload.verbose} --port=ttyATH0 -U {upload.native_usb} -e -w -v /tmp/sketch.bin -R
+
+tools.bossacI.network_cmd={runtime.tools.arduinoOTA.path}/bin/arduinoOTA
+tools.bossacI.upload.network_pattern="{network_cmd}" -address {serial.port} -port 65280 -username arduino -password "{network.password}" -sketch "{build.path}/{build.project_name}.bin" -upload /sketch -b
+
+
 #
 # OpenOCD sketch upload
 #
 
-tools.openocd.path={runtime.tools.openocd-0.9.0-arduino6-static.path}
+tools.openocd.path={runtime.tools.openocd-0.10.0-arduino7.path}
 tools.openocd.cmd=bin/openocd
 tools.openocd.cmd.windows=bin/openocd.exe
 
 tools.openocd.upload.params.verbose=-d2
 tools.openocd.upload.params.quiet=-d0
-tools.openocd.upload.pattern="{path}/{cmd}" {upload.verbose} -s "{path}/share/openocd/scripts/" -f "{runtime.platform.path}/variants/{build.variant}/{build.openocdscript}" -c "telnet_port disabled; program {{{build.path}/{build.project_name}.bin}} verify reset 0x2000; shutdown"
+tools.openocd.upload.pattern="{path}/{cmd}" {upload.verbose} -s "{path}/share/openocd/scripts/" -f "{runtime.platform.path}/variants/{build.variant}/{build.openocdscript}" -c "telnet_port disabled; program {{build.path}/{build.project_name}.bin} verify reset 0x2000; shutdown"
 
 tools.openocd.network_cmd={runtime.tools.arduinoOTA.path}/bin/arduinoOTA
 tools.openocd.upload.network_pattern={network_cmd} -address {serial.port} -port 65280 -username arduino -password "{network.password}" -sketch "{build.path}/{build.project_name}.bin" -upload /sketch -b
@@ -165,7 +186,7 @@ tools.openocd.upload.network_pattern={network_cmd} -address {serial.port} -port
 # Program flashes the binary at 0x0000, so use the linker script without_bootloader
 tools.openocd.program.params.verbose=-d2
 tools.openocd.program.params.quiet=-d0
-tools.openocd.program.pattern="{path}/{cmd}" {program.verbose} -s "{path}/share/openocd/scripts/" -f "{runtime.platform.path}/variants/{build.variant}/{build.openocdscript}" -c "telnet_port disabled; program {{{build.path}/{build.project_name}.elf}} verify reset; shutdown"
+tools.openocd.program.pattern="{path}/{cmd}" {program.verbose} -s "{path}/share/openocd/scripts/" -f "{runtime.platform.path}/variants/{build.variant}/{build.openocdscript}" -c "telnet_port disabled; program {{build.path}/{build.project_name}.elf} verify reset; shutdown"
 
 tools.openocd.erase.params.verbose=-d3
 tools.openocd.erase.params.quiet=-d0
@@ -173,25 +194,25 @@ tools.openocd.erase.pattern=
 
 tools.openocd.bootloader.params.verbose=-d2
 tools.openocd.bootloader.params.quiet=-d0
-tools.openocd.bootloader.pattern="{path}/{cmd}" {bootloader.verbose} -s "{path}/share/openocd/scripts/" -f "{runtime.platform.path}/variants/{build.variant}/{build.openocdscript}" -c "telnet_port disabled; init; halt; at91samd bootloader 0; program {{{runtime.platform.path}/bootloaders/{bootloader.file}}} verify reset; shutdown"
+tools.openocd.bootloader.pattern="{path}/{cmd}" {bootloader.verbose} -s "{path}/share/openocd/scripts/" -f "{runtime.platform.path}/variants/{build.variant}/{build.openocdscript}" -c "telnet_port disabled; init; halt; at91samd bootloader 0; program {{runtime.platform.path}/bootloaders/{bootloader.file}} verify reset; shutdown"
 
 #
 # OpenOCD sketch upload - version with configurable bootloader size
 # FIXME: this programmer is a workaround for default options being overwritten by uploadUsingPreferences
 #
 
-tools.openocd-withbootsize.path={runtime.tools.openocd-0.9.0-arduino6-static.path}
+tools.openocd-withbootsize.path={runtime.tools.openocd-0.10.0-arduino7.path}
 tools.openocd-withbootsize.cmd=bin/openocd
 tools.openocd-withbootsize.cmd.windows=bin/openocd.exe
 
 tools.openocd-withbootsize.upload.params.verbose=-d2
 tools.openocd-withbootsize.upload.params.quiet=-d0
-tools.openocd-withbootsize.upload.pattern="{path}/{cmd}" {upload.verbose} -s "{path}/share/openocd/scripts/" -f "{runtime.platform.path}/variants/{build.variant}/{build.openocdscript}" -c "telnet_port disabled; program {{{build.path}/{build.project_name}.bin}} verify reset {bootloader.size}; shutdown"
+tools.openocd-withbootsize.upload.pattern="{path}/{cmd}" {upload.verbose} -s "{path}/share/openocd/scripts/" -f "{runtime.platform.path}/variants/{build.variant}/{build.openocdscript}" -c "telnet_port disabled; program {{build.path}/{build.project_name}.bin} verify reset {bootloader.size}; shutdown"
 
 # Program flashes the binary at 0x0000, so use the linker script without_bootloader
 tools.openocd-withbootsize.program.params.verbose=-d2
 tools.openocd-withbootsize.program.params.quiet=-d0
-tools.openocd-withbootsize.program.pattern="{path}/{cmd}" {program.verbose} -s "{path}/share/openocd/scripts/" -f "{runtime.platform.path}/variants/{build.variant}/{build.openocdscript}" -c "telnet_port disabled; program {{{build.path}/{build.project_name}.elf}} verify reset; shutdown"
+tools.openocd-withbootsize.program.pattern="{path}/{cmd}" {program.verbose} -s "{path}/share/openocd/scripts/" -f "{runtime.platform.path}/variants/{build.variant}/{build.openocdscript}" -c "telnet_port disabled; program {{build.path}/{build.project_name}.elf} verify reset; shutdown"
 
 tools.openocd-withbootsize.erase.params.verbose=-d3
 tools.openocd-withbootsize.erase.params.quiet=-d0
@@ -199,4 +220,4 @@ tools.openocd-withbootsize.erase.pattern=
 
 tools.openocd-withbootsize.bootloader.params.verbose=-d2
 tools.openocd-withbootsize.bootloader.params.quiet=-d0
-tools.openocd-withbootsize.bootloader.pattern="{path}/{cmd}" {bootloader.verbose} -s "{path}/share/openocd/scripts/" -f "{runtime.platform.path}/variants/{build.variant}/{build.openocdscript}" -c "telnet_port disabled; init; halt; at91samd bootloader 0; program {{{runtime.platform.path}/bootloaders/{bootloader.file}}} verify reset; shutdown"
+tools.openocd-withbootsize.bootloader.pattern="{path}/{cmd}" {bootloader.verbose} -s "{path}/share/openocd/scripts/" -f "{runtime.platform.path}/variants/{build.variant}/{build.openocdscript}" -c "telnet_port disabled; init; halt; at91samd bootloader 0; program {{runtime.platform.path}/bootloaders/{bootloader.file}} verify reset; shutdown"
diff --git a/programmers.txt b/programmers.txt
index fd7471b7d..f1617e4c1 100644
--- a/programmers.txt
+++ b/programmers.txt
@@ -14,23 +14,17 @@
 # License along with this library; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
-edbg.name=Atmel EDBG
-edbg.communication=USB
-edbg.protocol=
-edbg.program.protocol=
-edbg.program.tool=openocd
-edbg.program.extra_params=
+adafruit_jlink.name=J-Link over OpenOCD
+adafruit_jlink.communication=USB
+adafruit_jlink.protocol=jlink
+adafruit_jlink.program.protocol=jlink
+adafruit_jlink.program.tool=openocd
+adafruit_jlink.program.setup_command=interface jlink; transport select swd; reset_config none separate; set WORKAREASIZE 0;
 
-atmel_ice.name=Atmel-ICE
-atmel_ice.communication=USB
-atmel_ice.protocol=
-atmel_ice.program.protocol=
-atmel_ice.program.tool=openocd
-atmel_ice.program.extra_params=
 
-sam_ice.name=Atmel SAM-ICE
-sam_ice.communication=USB
-sam_ice.protocol=
-sam_ice.program.protocol=
-sam_ice.program.tool=openocd
-sam_ice.program.extra_params=
+adafruit_atmel_ice.name=Atmel-ICE over OpenOCD
+adafruit_atmel_ice.communication=USB
+adafruit_atmel_ice.protocol=cmsis-dap
+adafruit_atmel_ice.program.protocol=cmsis-dap
+adafruit_atmel_ice.program.tool=openocd
+adafruit_atmel_ice.program.setup_command=cmsis_dap_vid_pid 0x03eb 0x2141; transport select swd;
\ No newline at end of file
diff --git a/variants/arduino_mzero/variant.h b/variants/arduino_mzero/variant.h
index 4bb8460b8..b48fde2ed 100755
--- a/variants/arduino_mzero/variant.h
+++ b/variants/arduino_mzero/variant.h
@@ -30,7 +30,7 @@
 #define VARIANT_MAINOSC		(32768ul)
 
 /** Master clock frequency */
-#define VARIANT_MCK			  (48000000ul)
+#define VARIANT_MCK	(F_CPU)
 
 /*----------------------------------------------------------------------------
  *        Headers
diff --git a/variants/arduino_zero/variant.cpp b/variants/arduino_zero/variant.cpp
index 90769a984..dfbaf745a 100644
--- a/variants/arduino_zero/variant.cpp
+++ b/variants/arduino_zero/variant.cpp
@@ -131,8 +131,8 @@ const PinDescription g_APinDescription[]=
   { PORTA, 21, PIO_TIMER_ALT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER_ALT), No_ADC_Channel, PWM0_CH7, TCC0_CH7, EXTERNAL_INT_5 }, // TCC0/WO[7]
 
   // Digital High
-  { PORTA,  6, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM1_CH0, TCC1_CH0, EXTERNAL_INT_6 }, // TCC1/WO[0]
-  { PORTA,  7, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM1_CH1, TCC1_CH1, EXTERNAL_INT_7 }, // TCC1/WO[1]
+  { PORTA,  6, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER|PIN_ATTR_ANALOG), ADC_Channel6, PWM1_CH0, TCC1_CH0, EXTERNAL_INT_6 }, // TCC1/WO[0]
+  { PORTA,  7, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER|PIN_ATTR_ANALOG), ADC_Channel7, PWM1_CH1, TCC1_CH1, EXTERNAL_INT_7 }, // TCC1/WO[1]
   { PORTA, 18, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM3_CH0, TC3_CH0, EXTERNAL_INT_2 }, // TC3/WO[0]
   { PORTA, 16, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM2_CH0, TCC2_CH0, EXTERNAL_INT_0 }, // TCC2/WO[0]
   { PORTA, 19, PIO_TIMER_ALT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER_ALT), No_ADC_Channel, PWM0_CH3, TCC0_CH3, EXTERNAL_INT_3 }, // TCC0/WO[3]
@@ -214,7 +214,7 @@ SERCOM sercom4( SERCOM4 ) ;
 SERCOM sercom5( SERCOM5 ) ;
 
 Uart Serial1( &sercom0, PIN_SERIAL1_RX, PIN_SERIAL1_TX, PAD_SERIAL1_RX, PAD_SERIAL1_TX ) ;
-Uart Serial( &sercom5, PIN_SERIAL_RX, PIN_SERIAL_TX, PAD_SERIAL_RX, PAD_SERIAL_TX ) ;
+Uart Serial5( &sercom5, PIN_SERIAL_RX, PIN_SERIAL_TX, PAD_SERIAL_RX, PAD_SERIAL_TX ) ;
 void SERCOM0_Handler()
 {
   Serial1.IrqHandler();
@@ -222,6 +222,6 @@ void SERCOM0_Handler()
 
 void SERCOM5_Handler()
 {
-  Serial.IrqHandler();
+  Serial5.IrqHandler();
 }
 
diff --git a/variants/arduino_zero/variant.h b/variants/arduino_zero/variant.h
index 3856a9838..196ef773b 100644
--- a/variants/arduino_zero/variant.h
+++ b/variants/arduino_zero/variant.h
@@ -30,7 +30,7 @@
 #define VARIANT_MAINOSC		(32768ul)
 
 /** Master clock frequency */
-#define VARIANT_MCK			  (48000000ul)
+#define VARIANT_MCK	(F_CPU)
 
 /*----------------------------------------------------------------------------
  *        Headers
@@ -54,8 +54,8 @@ extern "C"
 
 // Number of pins defined in PinDescription array
 #define PINS_COUNT           (26u)
-#define NUM_DIGITAL_PINS     (20u)
-#define NUM_ANALOG_INPUTS    (6u)
+#define NUM_DIGITAL_PINS     (14u)
+#define NUM_ANALOG_INPUTS    (8u)
 #define NUM_ANALOG_OUTPUTS   (1u)
 #define analogInputToDigitalPin(p)  ((p < 6u) ? (p) + 14u : -1)
 
@@ -94,6 +94,8 @@ extern "C"
 #define PIN_A3               (17ul)
 #define PIN_A4               (18ul)
 #define PIN_A5               (19ul)
+#define PIN_A6               (8ul)
+#define PIN_A7               (9ul)
 #define PIN_DAC0             (14ul)
 
 static const uint8_t A0  = PIN_A0;
@@ -102,6 +104,8 @@ static const uint8_t A2  = PIN_A2;
 static const uint8_t A3  = PIN_A3;
 static const uint8_t A4  = PIN_A4;
 static const uint8_t A5  = PIN_A5;
+static const uint8_t A6  = PIN_A6 ;
+static const uint8_t A7  = PIN_A7 ;
 static const uint8_t DAC0 = PIN_DAC0;
 #define ADC_RESOLUTION		12
 
@@ -193,7 +197,7 @@ extern SERCOM sercom3;
 extern SERCOM sercom4;
 extern SERCOM sercom5;
 
-extern Uart Serial;
+extern Uart Serial5;
 extern Uart Serial1;
 
 #endif
@@ -213,7 +217,7 @@ extern Uart Serial1;
 //
 // SERIAL_PORT_HARDWARE_OPEN  Hardware serial ports which are open for use.  Their RX & TX
 //                            pins are NOT connected to anything by default.
-#define SERIAL_PORT_USBVIRTUAL      SerialUSB
+#define SERIAL_PORT_USBVIRTUAL      Serial
 #define SERIAL_PORT_MONITOR         Serial
 // Serial has no physical pins broken out, so it's not listed as HARDWARE port
 #define SERIAL_PORT_HARDWARE        Serial1
diff --git a/variants/mkrgsm1400/debug_scripts/variant.gdb b/variants/blm_badge/debug_scripts/variant.gdb
similarity index 100%
rename from variants/mkrgsm1400/debug_scripts/variant.gdb
rename to variants/blm_badge/debug_scripts/variant.gdb
diff --git a/variants/blm_badge/linker_scripts/gcc/flash_with_bootloader.ld b/variants/blm_badge/linker_scripts/gcc/flash_with_bootloader.ld
new file mode 100644
index 000000000..4475f9511
--- /dev/null
+++ b/variants/blm_badge/linker_scripts/gcc/flash_with_bootloader.ld
@@ -0,0 +1,211 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* Linker script to configure memory regions.
+ * Need modifying for a specific board.
+ *   FLASH.ORIGIN: starting address of flash
+ *   FLASH.LENGTH: length of flash
+ *   RAM.ORIGIN: starting address of RAM bank 0
+ *   RAM.LENGTH: length of RAM bank 0
+ */
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000+0x2000, LENGTH = 0x00040000-0x2000 /* First 8KB used by bootloader */
+  RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ *   Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ *   __exidx_start
+ *   __exidx_end
+ *   __copy_table_start__
+ *   __copy_table_end__
+ *   __zero_table_start__
+ *   __zero_table_end__
+ *   __etext
+ *   __data_start__
+ *   __preinit_array_start
+ *   __preinit_array_end
+ *   __init_array_start
+ *   __init_array_end
+ *   __fini_array_start
+ *   __fini_array_end
+ *   __data_end__
+ *   __bss_start__
+ *   __bss_end__
+ *   __end__
+ *   end
+ *   __HeapLimit
+ *   __StackLimit
+ *   __StackTop
+ *   __stack
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+	.text :
+	{
+		KEEP(*(.isr_vector))
+		*(.text*)
+
+		KEEP(*(.init))
+		KEEP(*(.fini))
+
+		/* .ctors */
+		*crtbegin.o(.ctors)
+		*crtbegin?.o(.ctors)
+		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+		*(SORT(.ctors.*))
+		*(.ctors)
+
+		/* .dtors */
+ 		*crtbegin.o(.dtors)
+ 		*crtbegin?.o(.dtors)
+ 		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ 		*(SORT(.dtors.*))
+ 		*(.dtors)
+
+		*(.rodata*)
+
+		KEEP(*(.eh_frame*))
+	} > FLASH
+
+	.ARM.extab :
+	{
+		*(.ARM.extab* .gnu.linkonce.armextab.*)
+	} > FLASH
+
+	__exidx_start = .;
+	.ARM.exidx :
+	{
+		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
+	} > FLASH
+	__exidx_end = .;
+
+	/* To copy multiple ROM to RAM sections,
+	 * uncomment .copy.table section and,
+	 * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.copy.table :
+	{
+		. = ALIGN(4);
+		__copy_table_start__ = .;
+		LONG (__etext)
+		LONG (__data_start__)
+		LONG (__data_end__ - __data_start__)
+		LONG (__etext2)
+		LONG (__data2_start__)
+		LONG (__data2_end__ - __data2_start__)
+		__copy_table_end__ = .;
+	} > FLASH
+	*/
+
+	/* To clear multiple BSS sections,
+	 * uncomment .zero.table section and,
+	 * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.zero.table :
+	{
+		. = ALIGN(4);
+		__zero_table_start__ = .;
+		LONG (__bss_start__)
+		LONG (__bss_end__ - __bss_start__)
+		LONG (__bss2_start__)
+		LONG (__bss2_end__ - __bss2_start__)
+		__zero_table_end__ = .;
+	} > FLASH
+	*/
+
+	__etext = .;
+
+	.data : AT (__etext)
+	{
+		__data_start__ = .;
+		*(vtable)
+		*(.data*)
+
+		. = ALIGN(4);
+		/* preinit data */
+		PROVIDE_HIDDEN (__preinit_array_start = .);
+		KEEP(*(.preinit_array))
+		PROVIDE_HIDDEN (__preinit_array_end = .);
+
+		. = ALIGN(4);
+		/* init data */
+		PROVIDE_HIDDEN (__init_array_start = .);
+		KEEP(*(SORT(.init_array.*)))
+		KEEP(*(.init_array))
+		PROVIDE_HIDDEN (__init_array_end = .);
+
+
+		. = ALIGN(4);
+		/* finit data */
+		PROVIDE_HIDDEN (__fini_array_start = .);
+		KEEP(*(SORT(.fini_array.*)))
+		KEEP(*(.fini_array))
+		PROVIDE_HIDDEN (__fini_array_end = .);
+
+		KEEP(*(.jcr*))
+		. = ALIGN(4);
+		/* All data end */
+		__data_end__ = .;
+
+	} > RAM
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start__ = .;
+		*(.bss*)
+		*(COMMON)
+		. = ALIGN(4);
+		__bss_end__ = .;
+	} > RAM
+
+	.heap (COPY):
+	{
+		__end__ = .;
+		PROVIDE(end = .);
+		*(.heap*)
+		__HeapLimit = .;
+	} > RAM
+
+	/* .stack_dummy section doesn't contains any symbols. It is only
+	 * used for linker to calculate size of stack sections, and assign
+	 * values to stack symbols later */
+	.stack_dummy (COPY):
+	{
+		*(.stack*)
+	} > RAM
+
+	/* Set stack top to end of RAM, and stack limit move down by
+	 * size of stack_dummy section */
+	__StackTop = ORIGIN(RAM) + LENGTH(RAM);
+	__StackLimit = __StackTop - SIZEOF(.stack_dummy);
+	PROVIDE(__stack = __StackTop);
+
+	__ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ;
+
+	/* Check if data + heap + stack exceeds RAM limit */
+	ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
+}
diff --git a/variants/blm_badge/linker_scripts/gcc/flash_without_bootloader.ld b/variants/blm_badge/linker_scripts/gcc/flash_without_bootloader.ld
new file mode 100644
index 000000000..0162f0774
--- /dev/null
+++ b/variants/blm_badge/linker_scripts/gcc/flash_without_bootloader.ld
@@ -0,0 +1,212 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* Linker script to configure memory regions.
+ * Need modifying for a specific board.
+ *   FLASH.ORIGIN: starting address of flash
+ *   FLASH.LENGTH: length of flash
+ *   RAM.ORIGIN: starting address of RAM bank 0
+ *   RAM.LENGTH: length of RAM bank 0
+ */
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00040000
+  RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ *   Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ *   __exidx_start
+ *   __exidx_end
+ *   __copy_table_start__
+ *   __copy_table_end__
+ *   __zero_table_start__
+ *   __zero_table_end__
+ *   __etext
+ *   __data_start__
+ *   __preinit_array_start
+ *   __preinit_array_end
+ *   __init_array_start
+ *   __init_array_end
+ *   __fini_array_start
+ *   __fini_array_end
+ *   __data_end__
+ *   __bss_start__
+ *   __bss_end__
+ *   __end__
+ *   end
+ *   __HeapLimit
+ *   __StackLimit
+ *   __StackTop
+ *   __stack
+ *   __ram_end__
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+	.text :
+	{
+		KEEP(*(.isr_vector))
+		*(.text*)
+
+		KEEP(*(.init))
+		KEEP(*(.fini))
+
+		/* .ctors */
+		*crtbegin.o(.ctors)
+		*crtbegin?.o(.ctors)
+		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+		*(SORT(.ctors.*))
+		*(.ctors)
+
+		/* .dtors */
+ 		*crtbegin.o(.dtors)
+ 		*crtbegin?.o(.dtors)
+ 		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ 		*(SORT(.dtors.*))
+ 		*(.dtors)
+
+		*(.rodata*)
+
+		KEEP(*(.eh_frame*))
+	} > FLASH
+
+	.ARM.extab :
+	{
+		*(.ARM.extab* .gnu.linkonce.armextab.*)
+	} > FLASH
+
+	__exidx_start = .;
+	.ARM.exidx :
+	{
+		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
+	} > FLASH
+	__exidx_end = .;
+
+	/* To copy multiple ROM to RAM sections,
+	 * uncomment .copy.table section and,
+	 * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.copy.table :
+	{
+		. = ALIGN(4);
+		__copy_table_start__ = .;
+		LONG (__etext)
+		LONG (__data_start__)
+		LONG (__data_end__ - __data_start__)
+		LONG (__etext2)
+		LONG (__data2_start__)
+		LONG (__data2_end__ - __data2_start__)
+		__copy_table_end__ = .;
+	} > FLASH
+	*/
+
+	/* To clear multiple BSS sections,
+	 * uncomment .zero.table section and,
+	 * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.zero.table :
+	{
+		. = ALIGN(4);
+		__zero_table_start__ = .;
+		LONG (__bss_start__)
+		LONG (__bss_end__ - __bss_start__)
+		LONG (__bss2_start__)
+		LONG (__bss2_end__ - __bss2_start__)
+		__zero_table_end__ = .;
+	} > FLASH
+	*/
+
+	__etext = .;
+
+	.data : AT (__etext)
+	{
+		__data_start__ = .;
+		*(vtable)
+		*(.data*)
+
+		. = ALIGN(4);
+		/* preinit data */
+		PROVIDE_HIDDEN (__preinit_array_start = .);
+		KEEP(*(.preinit_array))
+		PROVIDE_HIDDEN (__preinit_array_end = .);
+
+		. = ALIGN(4);
+		/* init data */
+		PROVIDE_HIDDEN (__init_array_start = .);
+		KEEP(*(SORT(.init_array.*)))
+		KEEP(*(.init_array))
+		PROVIDE_HIDDEN (__init_array_end = .);
+
+
+		. = ALIGN(4);
+		/* finit data */
+		PROVIDE_HIDDEN (__fini_array_start = .);
+		KEEP(*(SORT(.fini_array.*)))
+		KEEP(*(.fini_array))
+		PROVIDE_HIDDEN (__fini_array_end = .);
+
+		KEEP(*(.jcr*))
+		. = ALIGN(4);
+		/* All data end */
+		__data_end__ = .;
+
+	} > RAM
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start__ = .;
+		*(.bss*)
+		*(COMMON)
+		. = ALIGN(4);
+		__bss_end__ = .;
+	} > RAM
+
+	.heap (COPY):
+	{
+		__end__ = .;
+		PROVIDE(end = .);
+		*(.heap*)
+		__HeapLimit = .;
+	} > RAM
+
+	/* .stack_dummy section doesn't contains any symbols. It is only
+	 * used for linker to calculate size of stack sections, and assign
+	 * values to stack symbols later */
+	.stack_dummy (COPY):
+	{
+		*(.stack*)
+	} > RAM
+
+	/* Set stack top to end of RAM, and stack limit move down by
+	 * size of stack_dummy section */
+	__StackTop = ORIGIN(RAM) + LENGTH(RAM) ;
+	__StackLimit = __StackTop - SIZEOF(.stack_dummy);
+	PROVIDE(__stack = __StackTop);
+
+	__ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ;
+
+	/* Check if data + heap + stack exceeds RAM limit */
+	ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
+}
diff --git a/variants/blm_badge/openocd_scripts/gemma_m0.cfg b/variants/blm_badge/openocd_scripts/gemma_m0.cfg
new file mode 100644
index 000000000..93d782d39
--- /dev/null
+++ b/variants/blm_badge/openocd_scripts/gemma_m0.cfg
@@ -0,0 +1,28 @@
+#
+#  Adafruit Gemma M0 OpenOCD script.
+#
+#  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+#
+#  This library is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 2.1 of the License, or (at your option) any later version.
+#
+#  This library is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#  See the GNU Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library; if not, write to the Free Software
+#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#
+
+# chip name
+set CHIPNAME at91samd21g18
+set ENDIAN little
+
+# choose a port here
+set telnet_port 0
+
+source [find target/at91samdXX.cfg]
diff --git a/variants/mkrgsm1400/pins_arduino.h b/variants/blm_badge/pins_arduino.h
similarity index 100%
rename from variants/mkrgsm1400/pins_arduino.h
rename to variants/blm_badge/pins_arduino.h
diff --git a/variants/blm_badge/variant.cpp b/variants/blm_badge/variant.cpp
new file mode 100644
index 000000000..805b6e262
--- /dev/null
+++ b/variants/blm_badge/variant.cpp
@@ -0,0 +1,95 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#include "variant.h"
+
+/*
+ * Pins descriptions
+ */
+const PinDescription g_APinDescription[]=
+{
+  // GPIO 0 - I2S Data
+  { PORTA,  8, PIO_DIGITAL, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER|PIN_ATTR_ANALOG), ADC_Channel16, PWM0_CH0, TCC0_CH0, EXTERNAL_INT_NMI },
+
+  // GPIO 1 - Cap touch 1
+  { PORTA,  2, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel0, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 }, // ADC/AIN[0]
+
+  // GPIO 2 - Cap touch 2
+  { PORTA,  4, PIO_SERCOM_ALT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER|PIN_ATTR_ANALOG), ADC_Channel4, PWM0_CH0, TCC0_CH0, EXTERNAL_INT_4 },  // TCC0/WO[0]
+
+  // GPIO 3 - Cap touch 3
+  { PORTA,  6, PIO_SERCOM_ALT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER|PIN_ATTR_ANALOG), ADC_Channel6, PWM1_CH0, TCC1_CH0, EXTERNAL_INT_6 }, // TCC1/WO[0]
+
+  // GPIO 4 - Cap touch 4
+  { PORTA,  7, PIO_ANALOG, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER|PIN_ATTR_ANALOG), ADC_Channel7, PWM1_CH1, TCC1_CH1, EXTERNAL_INT_7 }, // TCC1/WO[1]
+
+  // GPIO 5 - Stemma I2C SDA
+  { PORTA, 0, PIO_SERCOM_ALT, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_0 }, // SDA
+
+  // GPIO 6 - Stemma I2C SCL
+  { PORTA, 1, PIO_SERCOM_ALT, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_1 }, // SCL
+
+  // GPIO 7 - PDM clock
+  { PORTA, 10, PIO_DIGITAL, (PIN_ATTR_DIGITAL|PIN_ATTR_ANALOG), ADC_Channel18, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_10 },
+
+  // D8/A0 - CT1
+  { PORTA,  2, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel0, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 }, // ADC/AIN[0]
+  // D9/A1 - CT2
+  { PORTA,  4, PIO_ANALOG, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel4, PWM0_CH0, TCC0_CH0, EXTERNAL_INT_4 },  // TCC0/WO[0]
+  // D10/A2 - CT3
+  { PORTA,  6, PIO_ANALOG, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel6, PWM1_CH0, TCC1_CH0, EXTERNAL_INT_6 }, // TCC1/WO[0]
+  // D11/A3 - CT4
+  { PORTA,  7, PIO_ANALOG, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel7, PWM1_CH1, TCC1_CH1, EXTERNAL_INT_7 }, // TCC1/WO[1]
+
+  // D12/A4 - Light
+  { PORTA, 11, PIO_ANALOG, (PIN_ATTR_DIGITAL|PIN_ATTR_ANALOG), ADC_Channel19, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_11 },
+
+  // D13 - LED
+  { PORTA, 3, PIO_DIGITAL, 0, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // LED
+
+  // GPIO 14 - NeoPixel
+  { PORTA,  5, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel5, PWM0_CH1, TCC0_CH1, EXTERNAL_INT_5 },
+
+  // GPIO 15 & 16 (SWCLK & SWDIO)
+  // --------------------------
+  { PORTA, 30, PIO_TIMER, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+  { PORTA, 31, PIO_TIMER, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+
+  // 17..19 - USB
+  // --------------------
+  { PORTA, 28, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB Host enable
+  { PORTA, 24, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB/DM
+  { PORTA, 25, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB/DP
+} ;
+
+const void* g_apTCInstances[TCC_INST_NUM+TC_INST_NUM]={ TCC0, TCC1, TCC2, TC3, TC4, TC5 } ;
+
+// Multi-serial objects instantiation
+SERCOM sercom0( SERCOM0 ) ;
+SERCOM sercom1( SERCOM1 ) ;
+SERCOM sercom2( SERCOM2 ) ;
+SERCOM sercom3( SERCOM3 ) ;
+
+Uart Serial1( &sercom0, PIN_SERIAL1_RX, PIN_SERIAL1_TX, PAD_SERIAL1_RX, PAD_SERIAL1_TX ) ;
+
+void SERCOM0_Handler()
+{
+  Serial1.IrqHandler();
+}
+
diff --git a/variants/blm_badge/variant.h b/variants/blm_badge/variant.h
new file mode 100644
index 000000000..dbee168d1
--- /dev/null
+++ b/variants/blm_badge/variant.h
@@ -0,0 +1,192 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _VARIANT_ADAFRUIT_BLMBADGE_
+#define _VARIANT_ADAFRUIT_BLMBADGE_
+
+// The definitions here needs a SAMD core >=1.6.6
+#define ARDUINO_SAMD_VARIANT_COMPLIANCE 10606
+
+/*----------------------------------------------------------------------------
+ *        Definitions
+ *----------------------------------------------------------------------------*/
+
+/** Frequency of the board main oscillator */
+#define VARIANT_MAINOSC		(32768ul)
+
+/** Master clock frequency */
+#define VARIANT_MCK	(F_CPU)
+
+/*----------------------------------------------------------------------------
+ *        Headers
+ *----------------------------------------------------------------------------*/
+
+#include "WVariant.h"
+
+#ifdef __cplusplus
+#include "SERCOM.h"
+#include "Uart.h"
+#endif // __cplusplus
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif // __cplusplus
+
+/*----------------------------------------------------------------------------
+ *        Pins
+ *----------------------------------------------------------------------------*/
+
+// Number of pins defined in PinDescription array
+#define PINS_COUNT           (20u)
+#define NUM_DIGITAL_PINS     (17u)
+#define NUM_ANALOG_INPUTS    (5u)
+#define NUM_ANALOG_OUTPUTS   (1u)
+#define analogInputToDigitalPin(p)  ((p < 3u) ? (p) + PIN_A0 : -1)
+
+#define digitalPinToPort(P)        ( &(PORT->Group[g_APinDescription[P].ulPort]) )
+#define digitalPinToBitMask(P)     ( 1 << g_APinDescription[P].ulPin )
+//#define analogInPinToBit(P)        ( )
+#define portOutputRegister(port)   ( &(port->OUT.reg) )
+#define portInputRegister(port)    ( &(port->IN.reg) )
+#define portModeRegister(port)     ( &(port->DIR.reg) )
+#define digitalPinHasPWM(P)        ( g_APinDescription[P].ulPWMChannel != NOT_ON_PWM || g_APinDescription[P].ulTCChannel != NOT_ON_TIMER )
+
+/*
+ * digitalPinToTimer(..) is AVR-specific and is not defined for SAMD
+ * architecture. If you need to check if a pin supports PWM you must
+ * use digitalPinHasPWM(..).
+ *
+ * https://github.com/arduino/Arduino/issues/1833
+ */
+// #define digitalPinToTimer(P)
+
+// LEDs
+#define PIN_LED_13           (13u)
+#define PIN_LED_RXL          (13u)
+#define PIN_LED_TXL          (13u)
+#define PIN_LED              PIN_LED_13
+#define PIN_LED2             PIN_LED_RXL
+#define PIN_LED3             PIN_LED_TXL
+#define LED_BUILTIN          PIN_LED_13
+
+// Neopixel LED
+#define PIN_NEOPIXEL   14
+#define NEOPIXEL_NUM   6
+
+/*
+ * Analog pins
+ */
+#define PIN_A0               (8ul)
+#define PIN_A1               (9ul)
+#define PIN_A2               (10ul)
+#define PIN_A3               (11ul)
+#define PIN_A4               (12ul)
+
+#define PIN_DAC0             (PIN_A0)
+
+static const uint8_t A0  = PIN_A0;
+static const uint8_t A1  = PIN_A1;
+static const uint8_t A2  = PIN_A2;
+static const uint8_t A3  = PIN_A3;
+static const uint8_t A4  = PIN_A4;
+static const uint8_t DAC0 = PIN_DAC0;
+
+#define ADC_RESOLUTION		12
+
+/*
+ * Serial interfaces
+ */
+
+// Serial1 (sercom 0)
+#define PIN_SERIAL1_RX       (3ul) // captouch pad
+#define PAD_SERIAL1_RX       (SERCOM_RX_PAD_2)
+#define PIN_SERIAL1_TX       (2ul) // captouch pad
+#define PAD_SERIAL1_TX       (UART_TX_PAD_0)
+
+/*
+ * SPI Interfaces
+ */
+#define SPI_INTERFACES_COUNT 0 // we'll just have SPI CLK and MOSI on sercom 0, no MISO
+
+/*
+ * Wire Interfaces
+ */
+#define WIRE_INTERFACES_COUNT 1
+
+#define PIN_WIRE_SDA         (5u)
+#define PIN_WIRE_SCL         (6u)
+#define PERIPH_WIRE          sercom1
+//#define WIRE_IT_HANDLER    // hack! we call the i2c handler from within the serial handler!
+
+static const uint8_t SDA = PIN_WIRE_SDA;
+static const uint8_t SCL = PIN_WIRE_SCL;
+
+/*
+ * USB
+ */
+#define PIN_USB_HOST_ENABLE (17ul)
+#define PIN_USB_DM          (18ul)
+#define PIN_USB_DP          (19ul)
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+ *        Arduino objects - C++ only
+ *----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+
+/*	=========================
+ *	===== SERCOM DEFINITION
+ *	=========================
+*/
+extern SERCOM sercom0;
+extern SERCOM sercom1;
+extern SERCOM sercom2;
+extern SERCOM sercom3;
+
+extern Uart Serial1;
+
+#endif
+
+// These serial port names are intended to allow libraries and architecture-neutral
+// sketches to automatically default to the correct port name for a particular type
+// of use.  For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN,
+// the first hardware serial port whose RX/TX pins are not dedicated to another use.
+//
+// SERIAL_PORT_MONITOR        Port which normally prints to the Arduino Serial Monitor
+//
+// SERIAL_PORT_USBVIRTUAL     Port which is USB virtual serial
+//
+// SERIAL_PORT_LINUXBRIDGE    Port which connects to a Linux system via Bridge library
+//
+// SERIAL_PORT_HARDWARE       Hardware serial port, physical RX & TX pins.
+//
+// SERIAL_PORT_HARDWARE_OPEN  Hardware serial ports which are open for use.  Their RX & TX
+//                            pins are NOT connected to anything by default.
+#define SERIAL_PORT_USBVIRTUAL      Serial
+#define SERIAL_PORT_MONITOR         Serial
+// Serial has no physical pins broken out, so it's not listed as HARDWARE port
+#define SERIAL_PORT_HARDWARE        Serial1
+#define SERIAL_PORT_HARDWARE_OPEN   Serial1
+
+#endif /* _VARIANT_ADAFRUIT_BLMBADGE_ */
+
diff --git a/variants/circuitplay/openocd_scripts/circuit_play.cfg b/variants/circuitplay/openocd_scripts/circuit_play.cfg
new file mode 100644
index 000000000..e203ef3b0
--- /dev/null
+++ b/variants/circuitplay/openocd_scripts/circuit_play.cfg
@@ -0,0 +1,28 @@
+#
+#  Adafruit Circuit Playground OpenOCD script.
+#
+#  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+#
+#  This library is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 2.1 of the License, or (at your option) any later version.
+#
+#  This library is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#  See the GNU Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library; if not, write to the Free Software
+#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#
+
+# chip name
+set CHIPNAME at91samd21g18
+set ENDIAN little
+
+# choose a port here
+set telnet_port 0
+
+source [find target/at91samdXX.cfg]
diff --git a/variants/circuitplay/variant.cpp b/variants/circuitplay/variant.cpp
index 1aa76015f..0e39cf35e 100644
--- a/variants/circuitplay/variant.cpp
+++ b/variants/circuitplay/variant.cpp
@@ -15,94 +15,6 @@
   License along with this library; if not, write to the Free Software
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */
-/*
- * +------------+------------------+--------+-----------------+--------------------------------------------------------------------------------------------------------
- * + Pin number +  ZERO Board pin  |  PIN   | Label/Name      | Comments (* is for default peripheral in use)
- * +------------+------------------+--------+-----------------+--------------------------------------------------------------------------------------------------------
- * |            | Digital Low      |        |                 |
- * +------------+------------------+--------+-----------------+--------------------------------------------------------------------------------------------------------
- * | 0          | 0 -> RX          |  PA11  |                 | EIC/EXTINT[11] ADC/AIN[19]           PTC/X[3] *SERCOM0/PAD[3]  SERCOM2/PAD[3]  TCC0/WO[3]  TCC1/WO[1]
- * | 1          | 1 <- TX          |  PA10  |                 | EIC/EXTINT[10] ADC/AIN[18]           PTC/X[2] *SERCOM0/PAD[2]                  TCC0/WO[2]  TCC1/WO[0]
- * | 2          | 2                |  PA14  |                 | EIC/EXTINT[14]                                 SERCOM2/PAD[2]  SERCOM4/PAD[2]  TC3/WO[0]   TCC0/WO[4]
- * | 3          | ~3               |  PA09  |                 | EIC/EXTINT[9]  ADC/AIN[17]           PTC/X[1]  SERCOM0/PAD[1]  SERCOM2/PAD[1] *TCC0/WO[1]  TCC1/WO[3]
- * | 4          | ~4               |  PA08  |                 | EIC/NMI        ADC/AIN[16]           PTC/X[0]  SERCOM0/PAD[0]  SERCOM2/PAD[0] *TCC0/WO[0]  TCC1/WO[2]
- * | 5          | ~5               |  PA15  |                 | EIC/EXTINT[15]                                 SERCOM2/PAD[3]  SERCOM4/PAD[3] *TC3/WO[1]   TCC0/WO[5]
- * | 6          | ~6               |  PA20  |                 | EIC/EXTINT[4]                        PTC/X[8]  SERCOM5/PAD[2]  SERCOM3/PAD[2]             *TCC0/WO[6]
- * | 7          | 7                |  PA21  |                 | EIC/EXTINT[5]                        PTC/X[9]  SERCOM5/PAD[3]  SERCOM3/PAD[3]              TCC0/WO[7]
- * +------------+------------------+--------+-----------------+--------------------------------------------------------------------------------------------------------
- * |            | Digital High     |        |                 |
- * +------------+------------------+--------+-----------------+--------------------------------------------------------------------------------------------------------
- * | 8          | ~8               |  PA06  |                 | EIC/EXTINT[6]  ADC/AIN[6]  AC/AIN[2] PTC/Y[4]  SERCOM0/PAD[2]                 *TCC1/WO[0]
- * | 9          | ~9               |  PA07  |                 | EIC/EXTINT[7]  ADC/AIN[7]  AC/AIN[3] PTC/Y[5]  SERCOM0/PAD[3]                 *TCC1/WO[1]
- * | 10         | ~10              |  PA18  |                 | EIC/EXTINT[2]                        PTC/X[6] +SERCOM1/PAD[2]  SERCOM3/PAD[2] *TC3/WO[0]    TCC0/WO[2]
- * | 11         | ~11              |  PA16  |                 | EIC/EXTINT[0]                        PTC/X[4] +SERCOM1/PAD[0]  SERCOM3/PAD[0] *TCC2/WO[0]   TCC0/WO[6]
- * | 12         | ~12              |  PA19  |                 | EIC/EXTINT[3]                        PTC/X[7] +SERCOM1/PAD[3]  SERCOM3/PAD[3]  TC3/WO[1]   *TCC0/WO[3]
- * | 13         | ~13              |  PA17  | LED             | EIC/EXTINT[1]                        PTC/X[5] +SERCOM1/PAD[1]  SERCOM3/PAD[1] *TCC2/WO[1]   TCC0/WO[7]
- * +------------+------------------+--------+-----------------+--------------------------------------------------------------------------------------------------------
- * |            | Analog Connector |        |                 |
- * +------------+------------------+--------+-----------------+--------------------------------------------------------------------------------------------------------
- * | 14         | A0               |  PA02  | A0              | EIC/EXTINT[2] *ADC/AIN[0]  DAC/VOUT  PTC/Y[0]
- * | 15         | A1               |  PB08  | A1              | EIC/EXTINT[8] *ADC/AIN[2]            PTC/Y[14] SERCOM4/PAD[0]                  TC4/WO[0]
- * | 16         | A2               |  PB09  | A2              | EIC/EXTINT[9] *ADC/AIN[3]            PTC/Y[15] SERCOM4/PAD[1]                  TC4/WO[1]
- * | 17         | A3               |  PA04  | A3              | EIC/EXTINT[4] *ADC/AIN[4]  AC/AIN[0] PTC/Y[2]  SERCOM0/PAD[0]                  TCC0/WO[0]
- * | 18         | A4               |  PA05  | A4              | EIC/EXTINT[5] *ADC/AIN[5]  AC/AIN[1] PTC/Y[5]  SERCOM0/PAD[1]                  TCC0/WO[1]
- * | 19         | A5               |  PB02  | A5              | EIC/EXTINT[2] *ADC/AIN[10]           PTC/Y[8]  SERCOM5/PAD[0]
- * +------------+------------------+--------+-----------------+--------------------------------------------------------------------------------------------------------
- * |            | Wire             |        |                 |
- * +------------+------------------+--------+-----------------+--------------------------------------------------------------------------------------------------------
- * | 20         | SDA              |  PA22  | SDA             | EIC/EXTINT[6]                        PTC/X[10] *SERCOM3/PAD[0] SERCOM5/PAD[0] TC4/WO[0] TCC0/WO[4]
- * | 21         | SCL              |  PA23  | SCL             | EIC/EXTINT[7]                        PTC/X[11] *SERCOM3/PAD[1] SERCOM5/PAD[1] TC4/WO[1] TCC0/WO[5]
- * +------------+------------------+--------+-----------------+--------------------------------------------------------------------------------------------------------
- * |            |SPI (Legacy ICSP) |        |                 |
- * +------------+------------------+--------+-----------------+--------------------------------------------------------------------------------------------------------
- * | 22         | 1                |  PA12  | MISO            | EIC/EXTINT[12] SERCOM2/PAD[0] *SERCOM4/PAD[0] TCC2/WO[0] TCC0/WO[6]
- * |            | 2                |        | 5V0             |
- * | 23         | 4                |  PB10  | MOSI            | EIC/EXTINT[10]                *SERCOM4/PAD[2] TC5/WO[0]  TCC0/WO[4]
- * | 24         | 3                |  PB11  | SCK             | EIC/EXTINT[11]                *SERCOM4/PAD[3] TC5/WO[1]  TCC0/WO[5]
- * |            | 5                |        | RESET           |
- * |            | 6                |        | GND             |
- * +------------+------------------+--------+-----------------+--------------------------------------------------------------------------------------------------------
- * |            | LEDs             |        |                 |
- * +------------+------------------+--------+-----------------+--------------------------------------------------------------------------------------------------------
- * | 25         |                  |  PB03  | RX              |
- * | 26         |                  |  PA27  | TX              |
- * +------------+------------------+--------+-----------------+--------------------------------------------------------------------------------------------------------
- * |            | USB              |        |                 |
- * +------------+------------------+--------+-----------------+--------------------------------------------------------------------------------------------------------
- * | 27         |                  |  PA28  | USB_HOST_ENABLE | EIC/EXTINT[8]
- * | 28         |                  |  PA24  | USB_NEGATIVE    | *USB/DM
- * | 29         |                  |  PA25  | USB_POSITIVE    | *USB/DP
- * +------------+------------------+--------+-----------------+--------------------------------------------------------------------------------------------------------
- * |            | EDBG             |        |                 |
- * +------------+------------------+--------+-----------------+--------------------------------------------------------------------------------------------------------
- * | 30         |                  |  PB22  | EDBG_UART TX    | *SERCOM5/PAD[2]
- * | 31         |                  |  PB23  | EDBG_UART RX    | *SERCOM5/PAD[3]
- * +------------+------------------+--------+-----------------+--------------------------------------------------------------------------------------------------------
- * | 32         |                  |  PA22  | EDBG_SDA        | Pin 20 (SDA)
- * | 33         |                  |  PA23  | EDBG_SCL        | Pin 21 (SCL)
- * +------------+------------------+--------+-----------------+--------------------------------------------------------------------------------------------------------
- * | 34         |                  |  PA19  | EDBG_MISO       | EIC/EXTINT[3] *SERCOM1/PAD[3] SERCOM3/PAD[3] TC3/WO[1]  TCC0/WO[3]
- * | 35         |                  |  PA16  | EDBG_MOSI       | EIC/EXTINT[0] *SERCOM1/PAD[0] SERCOM3/PAD[0] TCC2/WO[0] TCC0/WO[6]
- * | 36         |                  |  PA18  | EDBG_SS         | EIC/EXTINT[2] *SERCOM1/PAD[2] SERCOM3/PAD[2] TC3/WO[0]  TCC0/WO[2]
- * | 37         |                  |  PA17  | EDBG_SCK        | EIC/EXTINT[1] *SERCOM1/PAD[1] SERCOM3/PAD[1] TCC2/WO[1] TCC0/WO[7]
- * +------------+------------------+--------+-----------------+--------------------------------------------------------------------------------------------------------
- * | 38         | ATN              |  PA13  | EDBG_GPIO0      | EIC/EXTINT[13] SERCOM2/PAD[1] SERCOM4/PAD[1] *TCC2/WO[1] TCC0/WO[7]
- * | 39         |                  |  PA21  | EDBG_GPIO1      | Pin 7
- * | 40         |                  |  PA06  | EDBG_GPIO2      | Pin 8
- * | 41         |                  |  PA07  | EDBG_GPIO3      | Pin 9
- * +------------+------------------+--------+-----------------+--------------------------------------------------------------------------------------------------------
- * |            |                  |        |                 |
- * +------------+------------------+--------+-----------------+--------------------------------------------------------------------------------------------------------
- * |            | GND              |        |                 |
- * | 42         | AREF             |  PA03  |                 | EIC/EXTINT[3] *[ADC|DAC]/VREFA ADC/AIN[1] PTC/Y[1]
- * +------------+------------------+--------+-----------------+--------------------------------------------------------------------------------------------------------
- * |            |32.768KHz Crystal |        |                 |
- * +------------+------------------+--------+-----------------+--------------------------------------------------------------------------------------------------------
- * |            |                  |  PA00  | XIN32           | EIC/EXTINT[0] SERCOM1/PAD[0] TCC2/WO[0]
- * |            |                  |  PA01  | XOUT32          | EIC/EXTINT[1] SERCOM1/PAD[1] TCC2/WO[1]
- * +------------+------------------+--------+-----------------+--------------------------------------------------------------------------------------------------------
- */
-
 
 #include "variant.h"
 
@@ -121,16 +33,16 @@ const PinDescription g_APinDescription[]=
   // Digital Low
   { PORTB,  2, PIO_SERCOM_ALT, 0, ADC_Channel10, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 },                                    // GPIO D2 / A5 / SDA
   { PORTB,  3, PIO_SERCOM_ALT, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_3 },                    // GPIO D3 / A4 / SCL
-  { PORTA, 28, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },                           // GPIO D4 / Left Button
+  { PORTA, 28, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_8 },                              // GPIO D4 / Left Button
   { PORTA, 14, PIO_DIGITAL, (PIN_ATTR_DIGITAL), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_14 },                    // GPIO D5 / Right button
-  { PORTA,  5, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel5, PWM0_CH1, TCC0_CH1, EXTERNAL_INT_5 },   // GPIO D6 / A1
+  { PORTA,  5, PIO_SERCOM_ALT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel5, PWM0_CH1, TCC0_CH1, EXTERNAL_INT_5 },   // GPIO D6 / A1
   { PORTA, 15, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM3_CH1, TC3_CH1, EXTERNAL_INT_15 }, // GPIO D7 / Slide Switch
 
   // Digital High
-  { PORTB, 23, PIO_DIGITAL, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },                       // GPIO D8 / NeoPixels
-  { PORTA,  6, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel6, PWM1_CH0, TCC1_CH0, EXTERNAL_INT_6 },   // GPIO D9 / A2
-  { PORTA,  7, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel7, PWM1_CH1, TCC1_CH1, EXTERNAL_INT_7 },   // GPIO D10 / A3
-  { PORTA, 30, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },                    // GPIO D11 / Speaker Shutdown
+  { PORTB, 23, PIO_DIGITAL, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_7 },                          // GPIO D8 / NeoPixels
+  { PORTA,  6, PIO_SERCOM_ALT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel6, PWM1_CH0, TCC1_CH0, EXTERNAL_INT_6 },   // GPIO D9 / A2
+  { PORTA,  7, PIO_SERCOM_ALT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel7, PWM1_CH1, TCC1_CH1, EXTERNAL_INT_7 },   // GPIO D10 / A3
+  { PORTA, 30, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_10 },                      // GPIO D11 / Speaker Shutdown
   { PORTA,  2, PIO_DIGITAL, (PIN_ATTR_DIGITAL|PIN_ATTR_ANALOG), ADC_Channel0, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 },       // GPIO D12 / VOut / A0
   // 13 (LED)
   { PORTA, 17, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM2_CH1, TCC2_CH1, EXTERNAL_INT_1 }, // GPIO D13 / Red LED
@@ -141,7 +53,7 @@ const PinDescription g_APinDescription[]=
   { PORTA,  5, PIO_ANALOG, (PIN_ATTR_DIGITAL|PIN_ATTR_ANALOG), ADC_Channel5, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_5 },        // A1 (Same as D6)
   { PORTA,  6, PIO_ANALOG, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER|PIN_ATTR_ANALOG), ADC_Channel6, PWM1_CH0, TCC1_CH0, EXTERNAL_INT_6 },  // A2 (Same as D9)
   { PORTA,  7, PIO_ANALOG, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER|PIN_ATTR_ANALOG), ADC_Channel7, PWM1_CH1, TCC1_CH1, EXTERNAL_INT_7 },  // A3 (Same as D10
-  { PORTB,  3, PIO_ANALOG, (PIN_ATTR_DIGITAL|PIN_ATTR_ANALOG), ADC_Channel11, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },    // A4 (Same as D3)
+  { PORTB,  3, PIO_ANALOG, (PIN_ATTR_DIGITAL|PIN_ATTR_ANALOG), ADC_Channel11, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_3 },       // A4 (Same as D3)
   { PORTB,  2, PIO_ANALOG, (PIN_ATTR_DIGITAL|PIN_ATTR_ANALOG), ADC_Channel10, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 },       // A5 (Same as D2)
   { PORTB,  9, PIO_ANALOG, (PIN_ATTR_DIGITAL|PIN_ATTR_ANALOG|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel3, PWM4_CH1, TC4_CH1, EXTERNAL_INT_9 },   // A6 (Same as D0)
   { PORTB,  8, PIO_ANALOG, (PIN_ATTR_DIGITAL|PIN_ATTR_ANALOG|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel2, PWM4_CH0, TC4_CH0, EXTERNAL_INT_8 },   // A7 (Same as D1)
@@ -159,8 +71,8 @@ const PinDescription g_APinDescription[]=
   { PORTA, 13, PIO_PWM, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM), No_ADC_Channel, PWM0_CH5, NOT_ON_TIMER, EXTERNAL_INT_13 }, // EIC/EXTINT[13] *TCC2/WO[1] TCC0/WO[7]
 
   // GPIO 28 & 29 internal I2C (original xtal pins)
-  { PORTA, 0, PIO_SERCOM_ALT, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // Internal SDA
-  { PORTA, 1, PIO_SERCOM_ALT, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // Internal SCL
+  { PORTA, 0, PIO_SERCOM_ALT, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_0 }, // Internal SDA
+  { PORTA, 1, PIO_SERCOM_ALT, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_1 }, // Internal SCL
 
   // GPIO 30, 31, 32 Internal SPI
   { PORTA, 16, PIO_SERCOM_ALT, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // MISO: SERCOM3/PAD[0]
@@ -182,6 +94,12 @@ const PinDescription g_APinDescription[]=
   { PORTA, 24, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB/DM
   { PORTA, 25, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB/DP
 
+  // 39-42 External SPI
+  { PORTB,  2, PIO_SERCOM_ALT, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 },                    // GPIO D2 / A5 / SDA
+  { PORTB,  3, PIO_SERCOM_ALT, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_3 },                    // GPIO D3 / A4 / SCL
+  { PORTB, 10, PIO_SERCOM_ALT, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_10 },                   // Not available
+  { PORTB, 11, PIO_SERCOM_ALT, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_11 },                   // Not available
+
 } ;
 
 const void* g_apTCInstances[TCC_INST_NUM+TC_INST_NUM]={ TCC0, TCC1, TCC2, TC3, TC4, TC5 } ;
diff --git a/variants/circuitplay/variant.h b/variants/circuitplay/variant.h
index 1697188f1..70deefcf9 100644
--- a/variants/circuitplay/variant.h
+++ b/variants/circuitplay/variant.h
@@ -31,7 +31,7 @@
 #define VARIANT_MAINOSC (32768ul)
 
 // Master clock frequency
-#define VARIANT_MCK     (48000000ul)
+#define VARIANT_MCK     (F_CPU)
 
 // Pins
 // ----
@@ -51,7 +51,10 @@
 #define portInputRegister(port)  (&(port->IN.reg))
 #define portModeRegister(port)   (&(port->DIR.reg))
 #define digitalPinHasPWM(P)      (g_APinDescription[P].ulPWMChannel != NOT_ON_PWM || g_APinDescription[P].ulTCChannel != NOT_ON_TIMER)
-#define digitalPinToInterrupt(P) (g_APinDescription[P].ulExtInt)
+
+#if (ARDUINO_SAMD_VARIANT_COMPLIANCE < 10606)
+  #define digitalPinToInterrupt(P) (g_APinDescription[P].ulExtInt)
+#endif
 
 /*
  * digitalPinToTimer(..) is AVR-specific and is not defined for SAMD
@@ -108,11 +111,18 @@ static const uint8_t DAC0 = PIN_DAC0;
 
 #define ADC_RESOLUTION		12
 
+
+// On-board SPI Flash
+#define EXTERNAL_FLASH_DEVICES  GD25Q16C
+#define EXTERNAL_FLASH_USE_SPI  SPI
+#define EXTERNAL_FLASH_USE_CS   SS
+
 /*
  * SPI Interfaces
  */
-#define SPI_INTERFACES_COUNT 1
+#define SPI_INTERFACES_COUNT 3
 
+// SPI interface for QSPI flash
 #define PIN_SPI_MISO         (30u)
 #define PIN_SPI_SCK          (31u)
 #define PIN_SPI_MOSI         (32u)
@@ -126,6 +136,42 @@ static const uint8_t MISO = PIN_SPI_MISO ;
 static const uint8_t SCK  = PIN_SPI_SCK ;
 
 
+// Extra hardware SPI for Gizmo
+#define PIN_SPI1_SCK          (40u)
+#define PIN_SPI1_MOSI         (39u)
+#define PIN_SPI1_MISO         (41u)
+#define PERIPH_SPI1           sercom5
+#define PAD_SPI1_TX           SPI_PAD_0_SCK_1  // MOSI / SCK
+#define PAD_SPI1_RX           SERCOM_RX_PAD_2  // MISO not avail
+
+static const uint8_t SS1	  = 42 ;
+static const uint8_t MOSI1 = PIN_SPI_MOSI ;
+static const uint8_t MISO1 = PIN_SPI_MISO ;
+static const uint8_t SCK1  = PIN_SPI_SCK ;
+
+
+// Extra hardware for SD card
+#define PIN_SPI2_SCK          (10u)
+#define PIN_SPI2_MOSI         (9u)
+#define PIN_SPI2_MISO         (6u)
+#define PIN_SPI2_SS           (5u)
+#define PERIPH_SPI2           sercom0
+#define PAD_SPI2_TX           SPI_PAD_2_SCK_3  // MOSI / SCK
+#define PAD_SPI2_RX           SERCOM_RX_PAD_1  // MISO not avail
+
+static const uint8_t SS2   = 5 ;
+static const uint8_t MOSI2 = PIN_SPI2_MOSI ;
+static const uint8_t MISO2 = PIN_SPI2_MISO ;
+static const uint8_t SCK2  = PIN_SPI2_SCK ;
+
+
+// Needed for SD library
+#define SDCARD_SPI      SPI2
+#define SDCARD_MISO_PIN PIN_SPI2_MISO
+#define SDCARD_MOSI_PIN PIN_SPI2_MOSI
+#define SDCARD_SCK_PIN  PIN_SPI2_SCK
+#define SDCARD_SS_PIN   PIN_SPI2_SS
+
 /*
  * Wire Interfaces
  */
diff --git a/variants/mkrwan1300/debug_scripts/variant.gdb b/variants/crickit_m0/debug_scripts/variant.gdb
similarity index 100%
rename from variants/mkrwan1300/debug_scripts/variant.gdb
rename to variants/crickit_m0/debug_scripts/variant.gdb
diff --git a/variants/mkrwan1300/linker_scripts/gcc/flash_with_bootloader.ld b/variants/crickit_m0/linker_scripts/gcc/flash_with_bootloader.ld
similarity index 100%
rename from variants/mkrwan1300/linker_scripts/gcc/flash_with_bootloader.ld
rename to variants/crickit_m0/linker_scripts/gcc/flash_with_bootloader.ld
diff --git a/variants/mkrgsm1400/linker_scripts/gcc/flash_without_bootloader.ld b/variants/crickit_m0/linker_scripts/gcc/flash_without_bootloader.ld
similarity index 100%
rename from variants/mkrgsm1400/linker_scripts/gcc/flash_without_bootloader.ld
rename to variants/crickit_m0/linker_scripts/gcc/flash_without_bootloader.ld
diff --git a/variants/crickit_m0/openocd_scripts/cricket_m0.cfg b/variants/crickit_m0/openocd_scripts/cricket_m0.cfg
new file mode 100644
index 000000000..79ded8ec2
--- /dev/null
+++ b/variants/crickit_m0/openocd_scripts/cricket_m0.cfg
@@ -0,0 +1,28 @@
+#
+#  Adafruit Crickit M0 OpenOCD script.
+#
+#  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+#
+#  This library is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 2.1 of the License, or (at your option) any later version.
+#
+#  This library is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#  See the GNU Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library; if not, write to the Free Software
+#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#
+
+# chip name
+set CHIPNAME at91samd21g18
+set ENDIAN little
+
+# choose a port here
+set telnet_port 0
+
+source [find target/at91samdXX.cfg]
diff --git a/variants/mkrwan1300/pins_arduino.h b/variants/crickit_m0/pins_arduino.h
similarity index 100%
rename from variants/mkrwan1300/pins_arduino.h
rename to variants/crickit_m0/pins_arduino.h
diff --git a/variants/crickit_m0/variant.cpp b/variants/crickit_m0/variant.cpp
new file mode 100644
index 000000000..944e731e4
--- /dev/null
+++ b/variants/crickit_m0/variant.cpp
@@ -0,0 +1,112 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "variant.h"
+
+/*
+ * Pins descriptions
+ */
+const PinDescription g_APinDescription[]=
+{
+  // 0..13 - Digital pins
+  // ----------------------
+  // 0/1 - SERCOM/I2C
+  { PORTA, 0, PIO_SERCOM_ALT, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // SDA
+  { PORTA, 1, PIO_SERCOM_ALT, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // SCL
+
+  // D2..D5 - Drive 1 thru 4
+  { PORTA, 13, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM2_CH1, TCC2_CH1, EXTERNAL_INT_13 }, // Drive 1
+  { PORTA, 12, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM2_CH0, TCC2_CH0, EXTERNAL_INT_12 }, // Drive 2
+  { PORTB, 11, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM5_CH1, TC5_CH1, EXTERNAL_INT_11 }, // Drive 3
+  { PORTB, 10, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM5_CH0, TC5_CH0, EXTERNAL_INT_10 }, // Drive 4
+
+  // D6..D9 - Servo 1 thru 4
+  { PORTA, 17, PIO_TIMER_ALT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER_ALT), No_ADC_Channel, PWM0_CH7, TCC0_CH7, EXTERNAL_INT_1 },
+  { PORTA, 16, PIO_TIMER_ALT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER_ALT), No_ADC_Channel, PWM0_CH6, TCC0_CH6, EXTERNAL_INT_0 },
+  { PORTA, 15, PIO_TIMER_ALT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER_ALT), No_ADC_Channel, PWM0_CH5, TCC0_CH5, EXTERNAL_INT_15 },
+  { PORTA, 14, PIO_TIMER_ALT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER_ALT), No_ADC_Channel, PWM0_CH4, TCC0_CH4, EXTERNAL_INT_14 },
+
+  // D10 Internal NeoPixel
+  { PORTA, 27, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_15 },
+
+  // D11 External NeoPixel
+  { PORTA, 20, PIO_TIMER_ALT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER_ALT), No_ADC_Channel, PWM0_CH6, TCC0_CH6, EXTERNAL_INT_4 }, 
+
+  // D12 IRQ
+  { PORTA, 28, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_8 }, 
+
+  // 13 (LED)
+  { PORTB, 22, PIO_SERCOM_ALT, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },  // Yellow LED next to USB  
+
+  // A0-A8 - Analog signal pins
+  // A0 is duplicated since we mark it starting at analog1, so might as well!
+  { PORTA,  2, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel0, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 },        // Analog 0 == 1
+  { PORTA,  2, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel0, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 },        // Analog 1
+  { PORTA,  3, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel1, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },     // Analog 2
+  { PORTB,  8, PIO_ANALOG, (PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel2, PWM4_CH0, TC4_CH0, EXTERNAL_INT_8 }, // Analog 3
+  { PORTB,  9, PIO_ANALOG, (PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel3, PWM4_CH1, TC4_CH1, EXTERNAL_INT_9 }, // Analog 4
+  { PORTA, 11, PIO_ANALOG, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER|PIN_ATTR_ANALOG), ADC_Channel19, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_11 }, // A5
+  { PORTA, 10, PIO_ANALOG, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER|PIN_ATTR_ANALOG), ADC_Channel18, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_10 }, // A6
+  { PORTA,  9, PIO_ANALOG, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER|PIN_ATTR_ANALOG), ADC_Channel17, PWM0_CH1, TCC0_CH1, EXTERNAL_INT_9 },    // A7
+  { PORTA,  8, PIO_ANALOG, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER|PIN_ATTR_ANALOG), ADC_Channel16, PWM0_CH0, TCC0_CH0, EXTERNAL_INT_NMI },  // A8
+
+  // A9-A12 - 4 Captouch pins (also analog!)
+  { PORTA,  4, PIO_ANALOG, 0, ADC_Channel4, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_4 }, // Captouch 1
+  { PORTA,  5, PIO_ANALOG, 0, ADC_Channel5, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_5 }, // Captouch 2
+  { PORTA,  6, PIO_ANALOG, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel6, PWM1_CH0, TCC1_CH0, EXTERNAL_INT_6 }, // Captouch 3
+  { PORTA,  7, PIO_ANALOG, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel7, PWM1_CH1, TCC1_CH1, EXTERNAL_INT_7 }, // Captouch 4
+
+  // A13 - VIN sense pin
+  { PORTB,  3, PIO_ANALOG, 0, ADC_Channel11, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_3 }, // VIN sense divider
+
+  /**************/
+  // 28..31 - 4 Motor PWM pins
+  { PORTA, 22, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM4_CH0, TC4_CH1, EXTERNAL_INT_6 }, // TC4/WO[0]
+  { PORTA, 23, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM4_CH1, TC4_CH1, EXTERNAL_INT_7 }, // TC4/WO[1]
+  { PORTA, 19, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM3_CH1, TC3_CH1, EXTERNAL_INT_3 }, // TC3/WO[1]
+  { PORTA, 18, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM3_CH0, TC3_CH0, EXTERNAL_INT_2 }, // TC3/WO[0]
+
+  // 32..34 - USB
+  // --------------------
+  { PORTA, 28, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB Host enable
+  { PORTA, 24, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB/DM
+  { PORTA, 25, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB/DP
+
+  // 35..36 - fake sercom 5 serial
+  { PORTB,  2, PIO_SERCOM_ALT, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 }, // Sercom 5.0 UART TX
+  { PORTB, 23, PIO_SERCOM_ALT, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_7 }, // Sercom 5.3 UART RX
+
+} ;
+
+const void* g_apTCInstances[TCC_INST_NUM+TC_INST_NUM]={ TCC0, TCC1, TCC2, TC3, TC4, TC5 } ;
+
+// Multi-serial objects instantiation
+SERCOM sercom0( SERCOM0 ) ;
+SERCOM sercom1( SERCOM1 ) ;
+SERCOM sercom2( SERCOM2 ) ;
+SERCOM sercom3( SERCOM3 ) ;
+SERCOM sercom4( SERCOM4 ) ;
+SERCOM sercom5( SERCOM5 ) ;
+
+Uart Serial1( &sercom5, PIN_SERIAL1_RX, PIN_SERIAL1_TX, PAD_SERIAL1_RX, PAD_SERIAL1_TX ) ;
+
+void SERCOM5_Handler()
+{
+  Serial1.IrqHandler();
+}
+
diff --git a/variants/crickit_m0/variant.h b/variants/crickit_m0/variant.h
new file mode 100644
index 000000000..9b7646578
--- /dev/null
+++ b/variants/crickit_m0/variant.h
@@ -0,0 +1,250 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _VARIANT_ITSYBITSY_ZERO_
+#define _VARIANT_ITSYBITSY_ZERO_
+
+// The definitions here needs a SAMD core >=1.6.10
+#define ARDUINO_SAMD_VARIANT_COMPLIANCE 10610
+
+/*----------------------------------------------------------------------------
+ *        Definitions
+ *----------------------------------------------------------------------------*/
+
+/** Frequency of the board main oscillator */
+#define VARIANT_MAINOSC		(32768ul)
+
+/** Master clock frequency */
+#define VARIANT_MCK	(F_CPU)
+
+/*----------------------------------------------------------------------------
+ *        Headers
+ *----------------------------------------------------------------------------*/
+
+#include "WVariant.h"
+
+#ifdef __cplusplus
+#include "SERCOM.h"
+#include "Uart.h"
+#endif // __cplusplus
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif // __cplusplus
+
+/*----------------------------------------------------------------------------
+ *        Pins
+ *----------------------------------------------------------------------------*/
+
+// Number of pins defined in PinDescription array
+#define PINS_COUNT           (26u)
+#define NUM_DIGITAL_PINS     (20u)
+#define NUM_ANALOG_INPUTS    (12u)
+#define NUM_ANALOG_OUTPUTS   (1u)
+#define analogInputToDigitalPin(p)  ((p < 12u) ? (p) + PIN_A0 : -1)
+
+#define digitalPinToPort(P)        ( &(PORT->Group[g_APinDescription[P].ulPort]) )
+#define digitalPinToBitMask(P)     ( 1 << g_APinDescription[P].ulPin )
+//#define analogInPinToBit(P)        ( )
+#define portOutputRegister(port)   ( &(port->OUT.reg) )
+#define portInputRegister(port)    ( &(port->IN.reg) )
+#define portModeRegister(port)     ( &(port->DIR.reg) )
+#define digitalPinHasPWM(P)        ( g_APinDescription[P].ulPWMChannel != NOT_ON_PWM || g_APinDescription[P].ulTCChannel != NOT_ON_TIMER )
+
+/*
+ * digitalPinToTimer(..) is AVR-specific and is not defined for SAMD
+ * architecture. If you need to check if a pin supports PWM you must
+ * use digitalPinHasPWM(..).
+ *
+ * https://github.com/arduino/Arduino/issues/1833
+ */
+// #define digitalPinToTimer(P)
+
+// LEDs
+#define PIN_LED_13           (13u)
+#define PIN_LED              PIN_LED_13
+#define LED_BUILTIN          PIN_LED_13
+
+
+/* CRICKIT pins */
+
+#define CRICKIT_DRIVE_1      (2ul)
+#define CRICKIT_DRIVE_2      (CRICKIT_DRIVE_1 + 1)
+#define CRICKIT_DRIVE_3      (CRICKIT_DRIVE_2 + 1)
+#define CRICKIT_DRIVE_4      (CRICKIT_DRIVE_3 + 1)
+
+#define CRICKIT_SERVO_1      (6ul)
+#define CRICKIT_SERVO_2      (CRICKIT_SERVO_1 + 1)
+#define CRICKIT_SERVO_3      (CRICKIT_SERVO_2 + 1)
+#define CRICKIT_SERVO_4      (CRICKIT_SERVO_3 + 1)
+
+#define CRICKIT_INTERNAL_NEOPIXEL (10ul)
+#define CRICKIT_EXTERNAL_NEOPIXEL (11ul)
+
+#define CRICKIT_IRQ          (12ul)
+
+#define CRICKIT_TOUCH_1      (PIN_A9)
+#define CRICKIT_TOUCH_2      (CRICKIT_TOUCH_1 + 1)
+#define CRICKIT_TOUCH_3      (CRICKIT_TOUCH_2 + 1)
+#define CRICKIT_TOUCH_4      (CRICKIT_TOUCH_3 + 1)
+
+#define CRICKIT_VIN_SENSE    (PIN_A13)
+
+#define CRICKIT_MOTOR_1A     (28ul)
+#define CRICKIT_MOTOR_1B     (29ul)
+#define CRICKIT_MOTOR_2A     (30ul)
+#define CRICKIT_MOTOR_2B     (31ul)
+
+/*
+ * Analog pins
+ */
+#define PIN_A0               (14ul)
+#define PIN_A1               (PIN_A0 + 1)
+#define PIN_A2               (PIN_A0 + 2)
+#define PIN_A3               (PIN_A0 + 3)
+#define PIN_A4               (PIN_A0 + 4)
+#define PIN_A5               (PIN_A0 + 5)
+#define PIN_A6               (PIN_A0 + 6)
+#define PIN_A7               (PIN_A0 + 7)
+#define PIN_A8               (PIN_A0 + 8)
+#define PIN_A9               (PIN_A0 + 9)
+#define PIN_A10              (PIN_A0 + 10)
+#define PIN_A11              (PIN_A0 + 11)
+#define PIN_A12              (PIN_A0 + 12)
+#define PIN_A13              (PIN_A0 + 13)
+#define PIN_DAC0             (14ul)
+
+static const uint8_t A0  = PIN_A0;
+static const uint8_t A1  = PIN_A1;
+static const uint8_t A2  = PIN_A2;
+static const uint8_t A3  = PIN_A3;
+static const uint8_t A4  = PIN_A4;
+static const uint8_t A5  = PIN_A5;
+static const uint8_t A6  = PIN_A6 ;
+static const uint8_t A7  = PIN_A7 ;
+static const uint8_t A8  = PIN_A8 ;
+static const uint8_t A9  = PIN_A9 ;
+static const uint8_t A10 = PIN_A10 ;
+static const uint8_t A11 = PIN_A11 ;
+static const uint8_t A12 = PIN_A12 ;
+static const uint8_t A13 = PIN_A13 ;
+static const uint8_t DAC0 = PIN_DAC0;
+
+#define ADC_RESOLUTION		12
+
+// Other pins
+#define PIN_ATN              (38ul)
+static const uint8_t ATN = PIN_ATN;
+
+/*
+ * Serial interfaces
+ */
+
+// Serial1
+#define PIN_SERIAL1_TX       (35ul)
+#define PIN_SERIAL1_RX       (36ul)
+#define PAD_SERIAL1_TX       (UART_TX_PAD_0)
+#define PAD_SERIAL1_RX       (SERCOM_RX_PAD_3)
+
+/*
+ * SPI Interfaces
+ */
+#define SPI_INTERFACES_COUNT 0
+
+/*
+ * Wire Interfaces
+ */
+#define WIRE_INTERFACES_COUNT 1
+
+#define PIN_WIRE_SDA         (0u)
+#define PIN_WIRE_SCL         (1u)
+#define PERIPH_WIRE          sercom1
+#define WIRE_IT_HANDLER      SERCOM1_Handler
+
+static const uint8_t SDA = PIN_WIRE_SDA;
+static const uint8_t SCL = PIN_WIRE_SCL;
+
+/*
+ * USB
+ */
+#define PIN_USB_HOST_ENABLE (32ul)
+#define PIN_USB_DM          (33ul)
+#define PIN_USB_DP          (34ul)
+/*
+ * I2S Interfaces
+ */
+#define I2S_INTERFACES_COUNT 1
+
+#define I2S_DEVICE          0
+#define I2S_CLOCK_GENERATOR 3
+// PA07 ISD0
+#define PIN_I2S_SD          (CRICKIT_TOUCH_4)
+// PA10 I2SCK
+#define PIN_I2S_SCK         (A6)
+// PA11 IS2FS0
+#define PIN_I2S_FS          (A4)       
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+ *        Arduino objects - C++ only
+ *----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+
+/*	=========================
+ *	===== SERCOM DEFINITION
+ *	=========================
+*/
+extern SERCOM sercom0;
+extern SERCOM sercom1;
+extern SERCOM sercom2;
+extern SERCOM sercom3;
+extern SERCOM sercom4;
+extern SERCOM sercom5;
+
+extern Uart Serial1;
+
+#endif
+
+// These serial port names are intended to allow libraries and architecture-neutral
+// sketches to automatically default to the correct port name for a particular type
+// of use.  For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN,
+// the first hardware serial port whose RX/TX pins are not dedicated to another use.
+//
+// SERIAL_PORT_MONITOR        Port which normally prints to the Arduino Serial Monitor
+//
+// SERIAL_PORT_USBVIRTUAL     Port which is USB virtual serial
+//
+// SERIAL_PORT_LINUXBRIDGE    Port which connects to a Linux system via Bridge library
+//
+// SERIAL_PORT_HARDWARE       Hardware serial port, physical RX & TX pins.
+//
+// SERIAL_PORT_HARDWARE_OPEN  Hardware serial ports which are open for use.  Their RX & TX
+//                            pins are NOT connected to anything by default.
+#define SERIAL_PORT_USBVIRTUAL      Serial
+#define SERIAL_PORT_MONITOR         Serial
+// Serial has no physical pins broken out, so it's not listed as HARDWARE port
+#define SERIAL_PORT_HARDWARE        Serial1
+#define SERIAL_PORT_HARDWARE_OPEN   Serial1
+
+#endif /* _VARIANT_ARDUINO_ZERO_ */
+
diff --git a/variants/mkrwifi1010/debug_scripts/variant.gdb b/variants/feather_m0/debug_scripts/variant.gdb
similarity index 100%
rename from variants/mkrwifi1010/debug_scripts/variant.gdb
rename to variants/feather_m0/debug_scripts/variant.gdb
diff --git a/variants/mkrgsm1400/linker_scripts/gcc/flash_with_bootloader.ld b/variants/feather_m0/linker_scripts/gcc/flash_with_bootloader.ld
similarity index 99%
rename from variants/mkrgsm1400/linker_scripts/gcc/flash_with_bootloader.ld
rename to variants/feather_m0/linker_scripts/gcc/flash_with_bootloader.ld
index 5c0dcb4e0..357946455 100644
--- a/variants/mkrgsm1400/linker_scripts/gcc/flash_with_bootloader.ld
+++ b/variants/feather_m0/linker_scripts/gcc/flash_with_bootloader.ld
@@ -83,7 +83,6 @@ SECTIONS
 		*(SORT(.ctors.*))
 		*(.ctors)
 
-
 		/* .dtors */
  		*crtbegin.o(.dtors)
  		*crtbegin?.o(.dtors)
diff --git a/variants/mkrwan1300/linker_scripts/gcc/flash_without_bootloader.ld b/variants/feather_m0/linker_scripts/gcc/flash_without_bootloader.ld
similarity index 100%
rename from variants/mkrwan1300/linker_scripts/gcc/flash_without_bootloader.ld
rename to variants/feather_m0/linker_scripts/gcc/flash_without_bootloader.ld
diff --git a/variants/feather_m0/openocd_scripts/feather_m0.cfg b/variants/feather_m0/openocd_scripts/feather_m0.cfg
new file mode 100644
index 000000000..1dc08b177
--- /dev/null
+++ b/variants/feather_m0/openocd_scripts/feather_m0.cfg
@@ -0,0 +1,28 @@
+#
+#  Adafruit Feather M0 Express OpenOCD script.
+#
+#  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+#
+#  This library is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 2.1 of the License, or (at your option) any later version.
+#
+#  This library is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#  See the GNU Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library; if not, write to the Free Software
+#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#
+
+# chip name
+set CHIPNAME at91samd21g18
+set ENDIAN little
+
+# choose a port here
+set telnet_port 0
+
+source [find target/at91samdXX.cfg]
diff --git a/variants/mkrwifi1010/pins_arduino.h b/variants/feather_m0/pins_arduino.h
similarity index 100%
rename from variants/mkrwifi1010/pins_arduino.h
rename to variants/feather_m0/pins_arduino.h
diff --git a/variants/feather_m0/variant.cpp b/variants/feather_m0/variant.cpp
new file mode 100644
index 000000000..f9e76061c
--- /dev/null
+++ b/variants/feather_m0/variant.cpp
@@ -0,0 +1,139 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#include "variant.h"
+
+/*
+ * Pins descriptions
+ */
+const PinDescription g_APinDescription[]=
+{
+  // 0..13 - Digital pins
+  // ----------------------
+  // 0/1 - SERCOM/UART (Serial1)
+  { PORTA, 11, PIO_SERCOM, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM1_CH1, TCC1_CH1, EXTERNAL_INT_11 }, // RX: SERCOM0/PAD[3]
+  { PORTA, 10, PIO_SERCOM, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM1_CH0, TCC1_CH0, EXTERNAL_INT_10 }, // TX: SERCOM0/PAD[2]
+
+  // 2..12
+  // Digital Low
+  { PORTA, 14, PIO_DIGITAL, (PIN_ATTR_DIGITAL), No_ADC_Channel, PWM0_CH4, TCC0_CH4, EXTERNAL_INT_14 },
+  { PORTA,  9, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM0_CH1, TCC0_CH1, EXTERNAL_INT_9 }, // TCC0/WO[1]
+  { PORTA,  8, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM0_CH0, TCC0_CH0, EXTERNAL_INT_NMI },  // TCC0/WO[0]
+  { PORTA, 15, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM3_CH1, TC3_CH1, EXTERNAL_INT_15 }, // TC3/WO[1]
+  { PORTA, 20, PIO_TIMER_ALT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER_ALT), No_ADC_Channel, PWM0_CH6, TCC0_CH6, EXTERNAL_INT_4 }, // TCC0/WO[6]
+  { PORTA, 21, PIO_DIGITAL, (PIN_ATTR_DIGITAL), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_5 },
+
+  // Digital High
+  { PORTA,  6, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel6, PWM1_CH0, TCC1_CH0, EXTERNAL_INT_6 }, // TCC1/WO[0]
+  { PORTA,  7, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel7, PWM1_CH1, TCC1_CH1, EXTERNAL_INT_7 }, // TCC1/WO[1]
+  { PORTA, 18, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM3_CH0, TC3_CH0, EXTERNAL_INT_2 }, // TC3/WO[0]
+  { PORTA, 16, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM2_CH0, TCC2_CH0, EXTERNAL_INT_0 }, // TCC2/WO[0]
+  { PORTA, 19, PIO_TIMER_ALT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER_ALT), No_ADC_Channel, PWM0_CH3, TCC0_CH3, EXTERNAL_INT_3 }, // TCC0/WO[3]
+
+  // 13 (LED)
+  { PORTA, 17, PIO_PWM, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM2_CH1, TCC2_CH1, EXTERNAL_INT_1 }, // TCC2/WO[1]
+
+  // 14..19 - Analog pins
+  // --------------------
+  { PORTA,  2, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel0, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 }, // ADC/AIN[0]
+  { PORTB,  8, PIO_ANALOG, (PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel2, PWM4_CH0, TC4_CH0, EXTERNAL_INT_8 }, // ADC/AIN[2]
+  { PORTB,  9, PIO_ANALOG, (PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel3, PWM4_CH1, TC4_CH1, EXTERNAL_INT_9 }, // ADC/AIN[3]
+  { PORTA,  4, PIO_ANALOG, (PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel4, PWM0_CH0, TCC0_CH0, EXTERNAL_INT_4 }, // ADC/AIN[4]
+  { PORTA,  5, PIO_ANALOG, (PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel5, PWM0_CH1, TCC0_CH1, EXTERNAL_INT_5 }, // ADC/AIN[5]
+  { PORTB,  2, PIO_ANALOG, 0, ADC_Channel10, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 }, // ADC/AIN[10]
+
+  // 20..21 I2C pins (SDA/SCL and also EDBG:SDA/SCL)
+  // ----------------------
+  { PORTA, 22, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_6 }, // SDA: SERCOM3/PAD[0]
+  { PORTA, 23, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_7 }, // SCL: SERCOM3/PAD[1]
+
+  // 22..24 - SPI pins (ICSP:MISO,SCK,MOSI)
+  // ----------------------
+  { PORTA, 12, PIO_SERCOM_ALT, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_12 }, // MISO: SERCOM4/PAD[0]
+  { PORTB, 10, PIO_SERCOM_ALT, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_10 }, // MOSI: SERCOM4/PAD[2]
+  { PORTB, 11, PIO_SERCOM_ALT, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_11 }, // SCK: SERCOM4/PAD[3]
+
+  // 25..26 - RX/TX LEDS (PB03/PA27)
+  // --------------------
+  { PORTB,  3, PIO_OUTPUT, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // used as output only
+  { PORTA, 27, PIO_OUTPUT, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // used as output only
+
+  // 27..29 - USB
+  // --------------------
+  { PORTA, 28, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB Host enable
+  { PORTA, 24, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB/DM
+  { PORTA, 25, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB/DP
+
+  // 30..41 - EDBG
+  // ----------------------
+  // 30/31 - EDBG/UART
+  { PORTB, 22, PIO_SERCOM_ALT, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // TX: SERCOM5/PAD[2]
+  { PORTB, 23, PIO_SERCOM_ALT, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // RX: SERCOM5/PAD[3]
+
+  // 32/33 I2C (SDA/SCL and also EDBG:SDA/SCL)
+  { PORTA, 22, PIO_SERCOM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // SDA: SERCOM3/PAD[0]
+  { PORTA, 23, PIO_SERCOM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // SCL: SERCOM3/PAD[1]
+
+  // 34..37 - EDBG/SPI
+  { PORTA, 19, PIO_SERCOM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // MISO: SERCOM1/PAD[3]
+  { PORTA, 16, PIO_SERCOM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // MOSI: SERCOM1/PAD[0]
+  { PORTA, 18, PIO_SERCOM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // SS: SERCOM1/PAD[2]
+  { PORTA, 17, PIO_SERCOM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // SCK: SERCOM1/PAD[1]
+
+  // 38..41 - EDBG/Digital
+  { PORTA, 13, PIO_PWM, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM), No_ADC_Channel, PWM0_CH5, NOT_ON_TIMER, EXTERNAL_INT_13 }, // EIC/EXTINT[13] *TCC2/WO[1] TCC0/WO[7]
+  { PORTA, 21, PIO_PWM_ALT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM), No_ADC_Channel, PWM0_CH7, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // Pin 7
+  { PORTA,  6, PIO_PWM, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM), No_ADC_Channel, PWM1_CH0, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // Pin 8
+  { PORTA,  7, PIO_PWM, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM), No_ADC_Channel, PWM1_CH1, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // Pin 9
+
+  // 42 (AREF)
+  { PORTA, 3, PIO_ANALOG, PIN_ATTR_ANALOG, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // DAC/VREFP
+
+  // ----------------------
+  // 43 - Alternate use of A0 (DAC output)
+  { PORTA,  2, PIO_ANALOG, PIN_ATTR_ANALOG, DAC_Channel0, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 }, // DAC/VOUT
+
+  // 44 & 45 - A6 & A7 (same as D8 and D9
+  { PORTA,  6, PIO_ANALOG, (PIN_ATTR_ANALOG), ADC_Channel6, PWM1_CH0, TCC1_CH0, EXTERNAL_INT_6 }, // TCC1/WO[0]
+  { PORTA,  7, PIO_ANALOG, (PIN_ATTR_ANALOG), ADC_Channel7, PWM1_CH1, TCC1_CH1, EXTERNAL_INT_7 }, // TCC1/WO[1]
+
+} ;
+
+const void* g_apTCInstances[TCC_INST_NUM+TC_INST_NUM]={ TCC0, TCC1, TCC2, TC3, TC4, TC5 } ;
+
+// Multi-serial objects instantiation
+SERCOM sercom0( SERCOM0 ) ;
+SERCOM sercom1( SERCOM1 ) ;
+SERCOM sercom2( SERCOM2 ) ;
+SERCOM sercom3( SERCOM3 ) ;
+SERCOM sercom4( SERCOM4 ) ;
+SERCOM sercom5( SERCOM5 ) ;
+
+Uart Serial1( &sercom0, PIN_SERIAL1_RX, PIN_SERIAL1_TX, PAD_SERIAL1_RX, PAD_SERIAL1_TX ) ;
+Uart Serial5( &sercom5, PIN_SERIAL_RX, PIN_SERIAL_TX, PAD_SERIAL_RX, PAD_SERIAL_TX ) ;
+void SERCOM0_Handler()
+{
+  Serial1.IrqHandler();
+}
+
+void SERCOM5_Handler()
+{
+  Serial5.IrqHandler();
+}
+
diff --git a/variants/feather_m0/variant.h b/variants/feather_m0/variant.h
new file mode 100644
index 000000000..20ecbbbaf
--- /dev/null
+++ b/variants/feather_m0/variant.h
@@ -0,0 +1,228 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _VARIANT_ARDUINO_ZERO_
+#define _VARIANT_ARDUINO_ZERO_
+
+// The definitions here needs a SAMD core >=1.6.10
+#define ARDUINO_SAMD_VARIANT_COMPLIANCE 10610
+
+/*----------------------------------------------------------------------------
+ *        Definitions
+ *----------------------------------------------------------------------------*/
+
+/** Frequency of the board main oscillator */
+#define VARIANT_MAINOSC		(32768ul)
+
+/** Master clock frequency */
+#define VARIANT_MCK	(F_CPU)
+
+/*----------------------------------------------------------------------------
+ *        Headers
+ *----------------------------------------------------------------------------*/
+
+#include "WVariant.h"
+
+#ifdef __cplusplus
+#include "SERCOM.h"
+#include "Uart.h"
+#endif // __cplusplus
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif // __cplusplus
+
+/*----------------------------------------------------------------------------
+ *        Pins
+ *----------------------------------------------------------------------------*/
+
+// Number of pins defined in PinDescription array
+#define PINS_COUNT           (26u)
+#define NUM_DIGITAL_PINS     (20u)
+#define NUM_ANALOG_INPUTS    (8u)
+#define NUM_ANALOG_OUTPUTS   (1u)
+#define analogInputToDigitalPin(p)  ((p < 6u) ? (p) + 14u : -1)
+
+#define digitalPinToPort(P)        ( &(PORT->Group[g_APinDescription[P].ulPort]) )
+#define digitalPinToBitMask(P)     ( 1 << g_APinDescription[P].ulPin )
+//#define analogInPinToBit(P)        ( )
+#define portOutputRegister(port)   ( &(port->OUT.reg) )
+#define portInputRegister(port)    ( &(port->IN.reg) )
+#define portModeRegister(port)     ( &(port->DIR.reg) )
+#define digitalPinHasPWM(P)        ( g_APinDescription[P].ulPWMChannel != NOT_ON_PWM || g_APinDescription[P].ulTCChannel != NOT_ON_TIMER )
+
+/*
+ * digitalPinToTimer(..) is AVR-specific and is not defined for SAMD
+ * architecture. If you need to check if a pin supports PWM you must
+ * use digitalPinHasPWM(..).
+ *
+ * https://github.com/arduino/Arduino/issues/1833
+ */
+// #define digitalPinToTimer(P)
+
+// LEDs
+#define PIN_LED_13           (13u)
+#define PIN_LED_RXL          (25u)
+#define PIN_LED_TXL          (26u)
+#define PIN_LED              PIN_LED_13
+#define PIN_LED2             PIN_LED_RXL
+#define PIN_LED3             PIN_LED_TXL
+#define LED_BUILTIN          PIN_LED_13
+
+/*
+ * Analog pins
+ */
+#define PIN_A0               (14ul)
+#define PIN_A1               (15ul)
+#define PIN_A2               (16ul)
+#define PIN_A3               (17ul)
+#define PIN_A4               (18ul)
+#define PIN_A5               (19ul)
+#define PIN_A6               (44ul)
+#define PIN_A7               (45ul)
+#define PIN_DAC0             (14ul)
+
+static const uint8_t A0  = PIN_A0;
+static const uint8_t A1  = PIN_A1;
+static const uint8_t A2  = PIN_A2;
+static const uint8_t A3  = PIN_A3;
+static const uint8_t A4  = PIN_A4;
+static const uint8_t A5  = PIN_A5;
+static const uint8_t A6  = PIN_A6 ;
+static const uint8_t A7  = PIN_A7 ;
+static const uint8_t DAC0 = PIN_DAC0;
+
+#define ADC_RESOLUTION		12
+
+// Other pins
+#define PIN_ATN              (38ul)
+static const uint8_t ATN = PIN_ATN;
+
+/*
+ * Serial interfaces
+ */
+// Serial (EDBG)
+#define PIN_SERIAL_RX       (31ul)
+#define PIN_SERIAL_TX       (30ul)
+#define PAD_SERIAL_TX       (UART_TX_PAD_2)
+#define PAD_SERIAL_RX       (SERCOM_RX_PAD_3)
+
+// Serial1
+#define PIN_SERIAL1_RX       (0ul)
+#define PIN_SERIAL1_TX       (1ul)
+#define PAD_SERIAL1_TX       (UART_TX_PAD_2)
+#define PAD_SERIAL1_RX       (SERCOM_RX_PAD_3)
+
+/*
+ * SPI Interfaces
+ */
+#define SPI_INTERFACES_COUNT 1
+
+#define PIN_SPI_MISO         (22u)
+#define PIN_SPI_MOSI         (23u)
+#define PIN_SPI_SCK          (24u)
+#define PERIPH_SPI           sercom4
+#define PAD_SPI_TX           SPI_PAD_2_SCK_3
+#define PAD_SPI_RX           SERCOM_RX_PAD_0
+
+static const uint8_t SS	  = PIN_A2 ;	// SERCOM4 last PAD is present on A2 but HW SS isn't used. Set here only for reference.
+static const uint8_t MOSI = PIN_SPI_MOSI ;
+static const uint8_t MISO = PIN_SPI_MISO ;
+static const uint8_t SCK  = PIN_SPI_SCK ;
+
+/*
+ * Wire Interfaces
+ */
+#define WIRE_INTERFACES_COUNT 1
+
+#define PIN_WIRE_SDA         (20u)
+#define PIN_WIRE_SCL         (21u)
+#define PERIPH_WIRE          sercom3
+#define WIRE_IT_HANDLER      SERCOM3_Handler
+
+static const uint8_t SDA = PIN_WIRE_SDA;
+static const uint8_t SCL = PIN_WIRE_SCL;
+
+/*
+ * USB
+ */
+#define PIN_USB_HOST_ENABLE (27ul)
+#define PIN_USB_DM          (28ul)
+#define PIN_USB_DP          (29ul)
+
+/*
+ * I2S Interfaces
+ */
+#define I2S_INTERFACES_COUNT 1
+
+#define I2S_DEVICE          0
+#define I2S_CLOCK_GENERATOR 3
+#define PIN_I2S_SD          (9u)
+#define PIN_I2S_SCK         (1u)
+#define PIN_I2S_FS          (0u)
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+ *        Arduino objects - C++ only
+ *----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+
+/*	=========================
+ *	===== SERCOM DEFINITION
+ *	=========================
+*/
+extern SERCOM sercom0;
+extern SERCOM sercom1;
+extern SERCOM sercom2;
+extern SERCOM sercom3;
+extern SERCOM sercom4;
+extern SERCOM sercom5;
+
+extern Uart Serial5;
+extern Uart Serial1;
+
+#endif
+
+// These serial port names are intended to allow libraries and architecture-neutral
+// sketches to automatically default to the correct port name for a particular type
+// of use.  For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN,
+// the first hardware serial port whose RX/TX pins are not dedicated to another use.
+//
+// SERIAL_PORT_MONITOR        Port which normally prints to the Arduino Serial Monitor
+//
+// SERIAL_PORT_USBVIRTUAL     Port which is USB virtual serial
+//
+// SERIAL_PORT_LINUXBRIDGE    Port which connects to a Linux system via Bridge library
+//
+// SERIAL_PORT_HARDWARE       Hardware serial port, physical RX & TX pins.
+//
+// SERIAL_PORT_HARDWARE_OPEN  Hardware serial ports which are open for use.  Their RX & TX
+//                            pins are NOT connected to anything by default.
+#define SERIAL_PORT_USBVIRTUAL      Serial
+#define SERIAL_PORT_MONITOR         Serial
+// Serial has no physical pins broken out, so it's not listed as HARDWARE port
+#define SERIAL_PORT_HARDWARE        Serial1
+#define SERIAL_PORT_HARDWARE_OPEN   Serial1
+
+#endif /* _VARIANT_ARDUINO_ZERO_ */
+
diff --git a/variants/feather_m0_express/debug_scripts/variant.gdb b/variants/feather_m0_express/debug_scripts/variant.gdb
new file mode 100644
index 000000000..3c37ffde2
--- /dev/null
+++ b/variants/feather_m0_express/debug_scripts/variant.gdb
@@ -0,0 +1,31 @@
+#
+#  Arduino Zero OpenOCD script.
+#
+#  Copyright (c) 2014-2015 Arduino LLC. All right reserved.
+#
+#  This library is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 2.1 of the License, or (at your option) any later version.
+#
+#  This library is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#  See the GNU Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library; if not, write to the Free Software
+#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#
+
+# Define 'reset' command
+define reset
+
+info reg
+
+break main
+
+# End of 'reset' command
+end
+
+target remote | openocd -c "interface cmsis-dap" -c "set CHIPNAME at91samd21g18" -f target/at91samdXX.cfg -c "gdb_port pipe; log_output openocd.log"
diff --git a/variants/feather_m0_express/linker_scripts/gcc/flash_with_bootloader.ld b/variants/feather_m0_express/linker_scripts/gcc/flash_with_bootloader.ld
new file mode 100644
index 000000000..7d75f819d
--- /dev/null
+++ b/variants/feather_m0_express/linker_scripts/gcc/flash_with_bootloader.ld
@@ -0,0 +1,213 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* Linker script to configure memory regions.
+ * Need modifying for a specific board.
+ *   FLASH.ORIGIN: starting address of flash
+ *   FLASH.LENGTH: length of flash
+ *   RAM.ORIGIN: starting address of RAM bank 0
+ *   RAM.LENGTH: length of RAM bank 0
+ */
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000+0x2000, LENGTH = 0x00040000-0x2000 /* First 8KB used by bootloader */
+  RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ *   Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ *   __exidx_start
+ *   __exidx_end
+ *   __copy_table_start__
+ *   __copy_table_end__
+ *   __zero_table_start__
+ *   __zero_table_end__
+ *   __etext
+ *   __data_start__
+ *   __preinit_array_start
+ *   __preinit_array_end
+ *   __init_array_start
+ *   __init_array_end
+ *   __fini_array_start
+ *   __fini_array_end
+ *   __data_end__
+ *   __bss_start__
+ *   __bss_end__
+ *   __end__
+ *   end
+ *   __HeapLimit
+ *   __StackLimit
+ *   __StackTop
+ *   __stack
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+	.text :
+	{
+		__text_start__ = .;
+
+		KEEP(*(.isr_vector))
+		*(.text*)
+
+		KEEP(*(.init))
+		KEEP(*(.fini))
+
+		/* .ctors */
+		*crtbegin.o(.ctors)
+		*crtbegin?.o(.ctors)
+		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+		*(SORT(.ctors.*))
+		*(.ctors)
+
+		/* .dtors */
+ 		*crtbegin.o(.dtors)
+ 		*crtbegin?.o(.dtors)
+ 		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ 		*(SORT(.dtors.*))
+ 		*(.dtors)
+
+		*(.rodata*)
+
+		KEEP(*(.eh_frame*))
+	} > FLASH
+
+	.ARM.extab :
+	{
+		*(.ARM.extab* .gnu.linkonce.armextab.*)
+	} > FLASH
+
+	__exidx_start = .;
+	.ARM.exidx :
+	{
+		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
+	} > FLASH
+	__exidx_end = .;
+
+	/* To copy multiple ROM to RAM sections,
+	 * uncomment .copy.table section and,
+	 * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.copy.table :
+	{
+		. = ALIGN(4);
+		__copy_table_start__ = .;
+		LONG (__etext)
+		LONG (__data_start__)
+		LONG (__data_end__ - __data_start__)
+		LONG (__etext2)
+		LONG (__data2_start__)
+		LONG (__data2_end__ - __data2_start__)
+		__copy_table_end__ = .;
+	} > FLASH
+	*/
+
+	/* To clear multiple BSS sections,
+	 * uncomment .zero.table section and,
+	 * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.zero.table :
+	{
+		. = ALIGN(4);
+		__zero_table_start__ = .;
+		LONG (__bss_start__)
+		LONG (__bss_end__ - __bss_start__)
+		LONG (__bss2_start__)
+		LONG (__bss2_end__ - __bss2_start__)
+		__zero_table_end__ = .;
+	} > FLASH
+	*/
+
+	__etext = .;
+
+	.data : AT (__etext)
+	{
+		__data_start__ = .;
+		*(vtable)
+		*(.data*)
+
+		. = ALIGN(4);
+		/* preinit data */
+		PROVIDE_HIDDEN (__preinit_array_start = .);
+		KEEP(*(.preinit_array))
+		PROVIDE_HIDDEN (__preinit_array_end = .);
+
+		. = ALIGN(4);
+		/* init data */
+		PROVIDE_HIDDEN (__init_array_start = .);
+		KEEP(*(SORT(.init_array.*)))
+		KEEP(*(.init_array))
+		PROVIDE_HIDDEN (__init_array_end = .);
+
+
+		. = ALIGN(4);
+		/* finit data */
+		PROVIDE_HIDDEN (__fini_array_start = .);
+		KEEP(*(SORT(.fini_array.*)))
+		KEEP(*(.fini_array))
+		PROVIDE_HIDDEN (__fini_array_end = .);
+
+		KEEP(*(.jcr*))
+		. = ALIGN(16);
+		/* All data end */
+		__data_end__ = .;
+
+	} > RAM
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start__ = .;
+		*(.bss*)
+		*(COMMON)
+		. = ALIGN(4);
+		__bss_end__ = .;
+	} > RAM
+
+	.heap (COPY):
+	{
+		__end__ = .;
+		PROVIDE(end = .);
+		*(.heap*)
+		__HeapLimit = .;
+	} > RAM
+
+	/* .stack_dummy section doesn't contains any symbols. It is only
+	 * used for linker to calculate size of stack sections, and assign
+	 * values to stack symbols later */
+	.stack_dummy (COPY):
+	{
+		*(.stack*)
+	} > RAM
+
+	/* Set stack top to end of RAM, and stack limit move down by
+	 * size of stack_dummy section */
+	__StackTop = ORIGIN(RAM) + LENGTH(RAM);
+	__StackLimit = __StackTop - SIZEOF(.stack_dummy);
+	PROVIDE(__stack = __StackTop);
+
+	__ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ;
+
+	/* Check if data + heap + stack exceeds RAM limit */
+	ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
+}
diff --git a/variants/mkrwifi1010/linker_scripts/gcc/flash_without_bootloader.ld b/variants/feather_m0_express/linker_scripts/gcc/flash_without_bootloader.ld
similarity index 100%
rename from variants/mkrwifi1010/linker_scripts/gcc/flash_without_bootloader.ld
rename to variants/feather_m0_express/linker_scripts/gcc/flash_without_bootloader.ld
diff --git a/variants/feather_m0_express/openocd_scripts/feather_m0_express.cfg b/variants/feather_m0_express/openocd_scripts/feather_m0_express.cfg
new file mode 100644
index 000000000..9d2a9d3ca
--- /dev/null
+++ b/variants/feather_m0_express/openocd_scripts/feather_m0_express.cfg
@@ -0,0 +1,28 @@
+#
+#  Adafruit Feather M0 OpenOCD script.
+#
+#  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+#
+#  This library is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 2.1 of the License, or (at your option) any later version.
+#
+#  This library is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#  See the GNU Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library; if not, write to the Free Software
+#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#
+
+# chip name
+set CHIPNAME at91samd21g18
+set ENDIAN little
+
+# choose a port here
+set telnet_port 0
+
+source [find target/at91samdXX.cfg]
diff --git a/variants/feather_m0_express/pins_arduino.h b/variants/feather_m0_express/pins_arduino.h
new file mode 100644
index 000000000..db0e40c3d
--- /dev/null
+++ b/variants/feather_m0_express/pins_arduino.h
@@ -0,0 +1,21 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+// API compatibility
+#include "variant.h"
+
diff --git a/variants/feather_m0_express/variant.cpp b/variants/feather_m0_express/variant.cpp
new file mode 100644
index 000000000..a3e87b89e
--- /dev/null
+++ b/variants/feather_m0_express/variant.cpp
@@ -0,0 +1,128 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#include "variant.h"
+
+/*
+ * Pins descriptions
+ */
+const PinDescription g_APinDescription[]=
+{
+  // 0..13 - Digital pins
+  // ----------------------
+  // 0/1 - SERCOM/UART (Serial1)
+  { PORTA, 11, PIO_SERCOM, (PIN_ATTR_DIGITAL), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_11 }, // RX: SERCOM0/PAD[3]
+  { PORTA, 10, PIO_SERCOM, (PIN_ATTR_DIGITAL), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_10 }, // TX: SERCOM0/PAD[2]
+
+  // 2..12
+  // Digital Low
+  { PORTA, 14, PIO_DIGITAL, (PIN_ATTR_DIGITAL), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_14 },
+  { PORTA,  9, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM0_CH1, TCC0_CH1, EXTERNAL_INT_9 }, // TCC0/WO[1]
+  { PORTA,  8, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM0_CH0, TCC0_CH0, EXTERNAL_INT_NMI },  // TCC0/WO[0]
+  { PORTA, 15, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM3_CH1, TC3_CH1, EXTERNAL_INT_15 }, // TC3/WO[1]
+  { PORTA, 20, PIO_TIMER_ALT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER_ALT), No_ADC_Channel, PWM0_CH6, TCC0_CH6, EXTERNAL_INT_4 }, // TCC0/WO[6]
+  { PORTA, 21, PIO_DIGITAL, (PIN_ATTR_DIGITAL), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_5 },
+
+  // Digital High
+  { PORTA,  6, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER|PIN_ATTR_ANALOG), ADC_Channel6, PWM1_CH0, TCC1_CH0, EXTERNAL_INT_6 }, // TCC1/WO[0]
+  { PORTA,  7, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER|PIN_ATTR_ANALOG), ADC_Channel7, PWM1_CH1, TCC1_CH1, EXTERNAL_INT_7 }, // TCC1/WO[1]
+  { PORTA, 18, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM3_CH0, TC3_CH0, EXTERNAL_INT_2 }, // TC3/WO[0]
+  { PORTA, 16, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM2_CH0, TCC2_CH0, EXTERNAL_INT_0 }, // TCC2/WO[0]
+  { PORTA, 19, PIO_TIMER_ALT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER_ALT), No_ADC_Channel, PWM0_CH3, TCC0_CH3, EXTERNAL_INT_3 }, // TCC0/WO[3]
+
+  // 13 (LED)
+  { PORTA, 17, PIO_PWM, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM2_CH1, TCC2_CH1, EXTERNAL_INT_1 }, // TCC2/WO[1]
+
+  // 14..19 - Analog pins
+  // --------------------
+  { PORTA,  2, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel0, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 }, // ADC/AIN[0]
+  { PORTB,  8, PIO_ANALOG, (PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel2, PWM4_CH0, TC4_CH0, EXTERNAL_INT_8 }, // ADC/AIN[2]
+  { PORTB,  9, PIO_ANALOG, (PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel3, PWM4_CH1, TC4_CH1, EXTERNAL_INT_9 }, // ADC/AIN[3]
+  { PORTA,  4, PIO_ANALOG, 0, ADC_Channel4, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_4 }, // ADC/AIN[4]
+  { PORTA,  5, PIO_ANALOG, 0, ADC_Channel5, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_5 }, // ADC/AIN[5]
+  { PORTB,  2, PIO_ANALOG, 0, ADC_Channel10, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 }, // ADC/AIN[10]
+
+
+  // Extra Analog pins! 20..25
+  { PORTA,  6, PIO_ANALOG, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER|PIN_ATTR_ANALOG), ADC_Channel6, PWM1_CH0, TCC1_CH0, EXTERNAL_INT_6 }, // A6 same as D8
+  { PORTA,  7, PIO_ANALOG, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER|PIN_ATTR_ANALOG), ADC_Channel7, PWM1_CH1, TCC1_CH1, EXTERNAL_INT_7 }, // A7 same as D9
+  { PORTA,  8, PIO_ANALOG, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER|PIN_ATTR_ANALOG), ADC_Channel16, PWM0_CH0, TCC0_CH0, EXTERNAL_INT_NMI },  // A8 same as D4
+  { PORTA,  9, PIO_ANALOG, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER|PIN_ATTR_ANALOG), ADC_Channel17, PWM0_CH1, TCC0_CH1, EXTERNAL_INT_9 },    // A9 same as D5
+  { PORTA, 11, PIO_ANALOG, (PIN_ATTR_DIGITAL|PIN_ATTR_ANALOG), ADC_Channel19, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_11 }, // A10 same as D0
+  { PORTA, 10, PIO_ANALOG, (PIN_ATTR_DIGITAL|PIN_ATTR_ANALOG), ADC_Channel18, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_10 }, // A11 same as D1
+
+  // 26..27 I2C pins (SDA/SCL)
+  // ----------------------
+  { PORTA, 22, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_6 }, // SDA: SERCOM3/PAD[0]
+  { PORTA, 23, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_7 }, // SCL: SERCOM3/PAD[1]
+
+  // 28..30 - SPI pins (ICSP:MISO,SCK,MOSI)
+  // ----------------------
+  { PORTA, 12, PIO_SERCOM_ALT, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_12 }, // MISO: SERCOM4/PAD[0]
+  { PORTB, 10, PIO_SERCOM_ALT, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_10 }, // MOSI: SERCOM4/PAD[2]
+  { PORTB, 11, PIO_SERCOM_ALT, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_11 }, // SCK: SERCOM4/PAD[3]
+
+  // 31..32 - RX/TX LEDS (PB03/PA27)  -- unused
+  // --------------------
+  { PORTB,  3, PIO_OUTPUT, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // used as output only
+  { PORTA, 27, PIO_OUTPUT, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // used as output only
+
+  // 33..35 - USB
+  // --------------------
+  { PORTA, 28, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB Host enable
+  { PORTA, 24, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB/DM
+  { PORTA, 25, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB/DP
+
+  // 36..38 - Secondary SPI
+  // ----------------------
+  { PORTA, 14, PIO_SERCOM,     (PIN_ATTR_DIGITAL), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },  // SPI Flash MISO SERCOM2.2
+  { PORTA,  8, PIO_SERCOM_ALT, (PIN_ATTR_DIGITAL), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },  // SPI Flash MOSI SERCOM2.0
+  { PORTA,  9, PIO_SERCOM_ALT, (PIN_ATTR_DIGITAL), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },  // SPI Flash SCK  SERCOM2.1
+
+  // 39 Secondary SPI SS
+  { PORTA, 13, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_13 }, // SPI Flash SS
+
+  // 40 same as #8 - Internal NeoPixel (to match Metro M0)
+  { PORTA,  6, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER|PIN_ATTR_ANALOG), ADC_Channel6, PWM1_CH0, TCC1_CH0, EXTERNAL_INT_6 }, // TCC1/WO[0]
+
+  // 41 (AREF)
+  { PORTA, 3, PIO_ANALOG, PIN_ATTR_ANALOG, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // DAC/VREFP
+
+  // ----------------------
+  // 42 - Alternate use of A0 (DAC output)
+  { PORTA,  2, PIO_ANALOG, PIN_ATTR_ANALOG, DAC_Channel0, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 }, // DAC/VOUT
+} ;
+
+const void* g_apTCInstances[TCC_INST_NUM+TC_INST_NUM]={ TCC0, TCC1, TCC2, TC3, TC4, TC5 } ;
+
+// Multi-serial objects instantiation
+SERCOM sercom0( SERCOM0 ) ;
+SERCOM sercom1( SERCOM1 ) ;
+SERCOM sercom2( SERCOM2 ) ;
+SERCOM sercom3( SERCOM3 ) ;
+SERCOM sercom4( SERCOM4 ) ;
+SERCOM sercom5( SERCOM5 ) ;
+
+Uart Serial1( &sercom0, PIN_SERIAL1_RX, PIN_SERIAL1_TX, PAD_SERIAL1_RX, PAD_SERIAL1_TX ) ;
+
+void SERCOM0_Handler()
+{
+  Serial1.IrqHandler();
+}
+
diff --git a/variants/feather_m0_express/variant.h b/variants/feather_m0_express/variant.h
new file mode 100644
index 000000000..f4d3ae9bf
--- /dev/null
+++ b/variants/feather_m0_express/variant.h
@@ -0,0 +1,255 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _VARIANT_ARDUINO_ZERO_
+#define _VARIANT_ARDUINO_ZERO_
+
+// The definitions here needs a SAMD core >=1.6.10
+#define ARDUINO_SAMD_VARIANT_COMPLIANCE 10610
+
+/*----------------------------------------------------------------------------
+ *        Definitions
+ *----------------------------------------------------------------------------*/
+
+/** Frequency of the board main oscillator */
+#define VARIANT_MAINOSC		(32768ul)
+
+/** Master clock frequency */
+#define VARIANT_MCK	(F_CPU)
+
+/*----------------------------------------------------------------------------
+ *        Headers
+ *----------------------------------------------------------------------------*/
+
+#include "WVariant.h"
+
+#ifdef __cplusplus
+#include "SERCOM.h"
+#include "Uart.h"
+#endif // __cplusplus
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif // __cplusplus
+
+/*----------------------------------------------------------------------------
+ *        Pins
+ *----------------------------------------------------------------------------*/
+
+// Number of pins defined in PinDescription array
+#define PINS_COUNT           (42u)
+#define NUM_DIGITAL_PINS     (42u)
+#define NUM_ANALOG_INPUTS    (12u)
+#define NUM_ANALOG_OUTPUTS   (1u)
+#define analogInputToDigitalPin(p)  ((p < 6u) ? (p) + 14u : -1)
+
+#define digitalPinToPort(P)        ( &(PORT->Group[g_APinDescription[P].ulPort]) )
+#define digitalPinToBitMask(P)     ( 1 << g_APinDescription[P].ulPin )
+//#define analogInPinToBit(P)        ( )
+#define portOutputRegister(port)   ( &(port->OUT.reg) )
+#define portInputRegister(port)    ( &(port->IN.reg) )
+#define portModeRegister(port)     ( &(port->DIR.reg) )
+#define digitalPinHasPWM(P)        ( g_APinDescription[P].ulPWMChannel != NOT_ON_PWM || g_APinDescription[P].ulTCChannel != NOT_ON_TIMER )
+
+/*
+ * digitalPinToTimer(..) is AVR-specific and is not defined for SAMD
+ * architecture. If you need to check if a pin supports PWM you must
+ * use digitalPinHasPWM(..).
+ *
+ * https://github.com/arduino/Arduino/issues/1833
+ */
+// #define digitalPinToTimer(P)
+
+// LEDs
+#define PIN_LED_13           (13u)
+#define PIN_LED_RXL          (31u)
+#define PIN_LED_TXL          (32u)
+#define PIN_LED              PIN_LED_13
+#define PIN_LED2             PIN_LED_RXL
+#define PIN_LED3             PIN_LED_TXL
+#define LED_BUILTIN          PIN_LED_13
+#define NEOPIXEL_BUILTIN     (8u)
+#define PIN_NEOPIXEL		     NEOPIXEL_BUILTIN
+
+/*
+ * Analog pins
+ */
+#define PIN_A0               (14ul)
+#define PIN_A1               (PIN_A0 + 1)
+#define PIN_A2               (PIN_A0 + 2)
+#define PIN_A3               (PIN_A0 + 3)
+#define PIN_A4               (PIN_A0 + 4)
+#define PIN_A5               (PIN_A0 + 5)
+#define PIN_A6               (PIN_A0 + 6)
+#define PIN_A7               (PIN_A0 + 7)
+#define PIN_A8               (PIN_A0 + 8)
+#define PIN_A9               (PIN_A0 + 9)
+#define PIN_A10              (PIN_A0 + 10)
+#define PIN_A11              (PIN_A0 + 11)
+#define PIN_A12              (41ul)  // AREF
+#define PIN_DAC0             (14ul)
+
+static const uint8_t A0  = PIN_A0;
+static const uint8_t A1  = PIN_A1;
+static const uint8_t A2  = PIN_A2;
+static const uint8_t A3  = PIN_A3;
+static const uint8_t A4  = PIN_A4;
+static const uint8_t A5  = PIN_A5;
+static const uint8_t A6  = PIN_A6 ;
+static const uint8_t A7  = PIN_A7 ;
+static const uint8_t A8  = PIN_A8 ;
+static const uint8_t A9  = PIN_A9 ;
+static const uint8_t A10 = PIN_A10 ;
+static const uint8_t A11 = PIN_A11 ;
+static const uint8_t A12 = PIN_A12 ;
+
+static const uint8_t DAC0 = PIN_DAC0;
+
+#define ADC_RESOLUTION		12
+
+// Other pins
+#define PIN_ATN              (38ul)
+static const uint8_t ATN = PIN_ATN;
+
+
+// On-board SPI Flash
+#define EXTERNAL_FLASH_DEVICES  GD25Q16C
+#define EXTERNAL_FLASH_USE_SPI  SPI1
+#define EXTERNAL_FLASH_USE_CS   SS1
+
+/*
+ * Serial interfaces
+ */
+
+// Serial1
+#define PIN_SERIAL1_RX       (0ul)
+#define PIN_SERIAL1_TX       (1ul)
+#define PAD_SERIAL1_TX       (UART_TX_PAD_2)
+#define PAD_SERIAL1_RX       (SERCOM_RX_PAD_3)
+
+/*
+ * SPI Interfaces
+ */
+#define SPI_INTERFACES_COUNT 2
+
+#define PIN_SPI_MISO         (28u)
+#define PIN_SPI_MOSI         (29u)
+#define PIN_SPI_SCK          (30u)
+#define PERIPH_SPI           sercom4
+#define PAD_SPI_TX           SPI_PAD_2_SCK_3
+#define PAD_SPI_RX           SERCOM_RX_PAD_0
+
+static const uint8_t SS	  = PIN_A2 ;	// SERCOM4 last PAD is present on A2 but HW SS isn't used. Set here only for reference.
+static const uint8_t MOSI = PIN_SPI_MOSI ;
+static const uint8_t MISO = PIN_SPI_MISO ;
+static const uint8_t SCK  = PIN_SPI_SCK ;
+
+
+#define PIN_SPI1_MISO         (36u)
+#define PIN_SPI1_MOSI         (37u)
+#define PIN_SPI1_SCK          (38u)
+#define PERIPH_SPI1           sercom2
+#define PAD_SPI1_TX           SPI_PAD_0_SCK_1
+#define PAD_SPI1_RX           SERCOM_RX_PAD_2
+
+static const uint8_t SS1   = 39 ;	// HW SS isn't used. Set here only for reference.
+static const uint8_t MOSI1 = PIN_SPI1_MOSI ;
+static const uint8_t MISO1 = PIN_SPI1_MISO ;
+static const uint8_t SCK1  = PIN_SPI1_SCK ;
+
+
+/*
+ * Wire Interfaces
+ */
+#define WIRE_INTERFACES_COUNT 1
+
+#define PIN_WIRE_SDA         (26u)
+#define PIN_WIRE_SCL         (27u)
+#define PERIPH_WIRE          sercom3
+#define WIRE_IT_HANDLER      SERCOM3_Handler
+
+static const uint8_t SDA = PIN_WIRE_SDA;
+static const uint8_t SCL = PIN_WIRE_SCL;
+
+/*
+ * USB
+ */
+#define PIN_USB_HOST_ENABLE (33ul)
+#define PIN_USB_DM          (34ul)
+#define PIN_USB_DP          (35ul)
+
+/*
+ * I2S Interfaces
+ */
+#define I2S_INTERFACES_COUNT 1
+
+#define I2S_DEVICE          0
+#define I2S_CLOCK_GENERATOR 3
+#define PIN_I2S_SD          (9u)
+#define PIN_I2S_SCK         (1u)
+#define PIN_I2S_FS          (0u)
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+ *        Arduino objects - C++ only
+ *----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+
+/*	=========================
+ *	===== SERCOM DEFINITION
+ *	=========================
+*/
+extern SERCOM sercom0;
+extern SERCOM sercom1;
+extern SERCOM sercom2;
+extern SERCOM sercom3;
+extern SERCOM sercom4;
+extern SERCOM sercom5;
+
+extern Uart Serial1;
+
+#endif
+
+// These serial port names are intended to allow libraries and architecture-neutral
+// sketches to automatically default to the correct port name for a particular type
+// of use.  For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN,
+// the first hardware serial port whose RX/TX pins are not dedicated to another use.
+//
+// SERIAL_PORT_MONITOR        Port which normally prints to the Arduino Serial Monitor
+//
+// SERIAL_PORT_USBVIRTUAL     Port which is USB virtual serial
+//
+// SERIAL_PORT_LINUXBRIDGE    Port which connects to a Linux system via Bridge library
+//
+// SERIAL_PORT_HARDWARE       Hardware serial port, physical RX & TX pins.
+//
+// SERIAL_PORT_HARDWARE_OPEN  Hardware serial ports which are open for use.  Their RX & TX
+//                            pins are NOT connected to anything by default.
+#define SERIAL_PORT_USBVIRTUAL      Serial
+#define SERIAL_PORT_MONITOR         Serial
+// Serial has no physical pins broken out, so it's not listed as HARDWARE port
+#define SERIAL_PORT_HARDWARE        Serial1
+#define SERIAL_PORT_HARDWARE_OPEN   Serial1
+
+#endif /* _VARIANT_ARDUINO_ZERO_ */
+
diff --git a/variants/feather_m4/linker_scripts/gcc/flash_with_bootloader.ld b/variants/feather_m4/linker_scripts/gcc/flash_with_bootloader.ld
new file mode 100644
index 000000000..1bdea69ae
--- /dev/null
+++ b/variants/feather_m4/linker_scripts/gcc/flash_with_bootloader.ld
@@ -0,0 +1,216 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* Linker script to configure memory regions.
+ * Need modifying for a specific board.
+ *   FLASH.ORIGIN: starting address of flash
+ *   FLASH.LENGTH: length of flash
+ *   RAM.ORIGIN: starting address of RAM bank 0
+ *   RAM.LENGTH: length of RAM bank 0
+ */
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000+0x4000, LENGTH = 0x00080000-0x4000 /* First 16KB used by bootloader */
+  RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00030000
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ *   Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ *   __exidx_start
+ *   __exidx_end
+ *   __copy_table_start__
+ *   __copy_table_end__
+ *   __zero_table_start__
+ *   __zero_table_end__
+ *   __etext
+ *   __data_start__
+ *   __preinit_array_start
+ *   __preinit_array_end
+ *   __init_array_start
+ *   __init_array_end
+ *   __fini_array_start
+ *   __fini_array_end
+ *   __data_end__
+ *   __bss_start__
+ *   __bss_end__
+ *   __end__
+ *   end
+ *   __HeapLimit
+ *   __StackLimit
+ *   __StackTop
+ *   __stack
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+	.text :
+	{
+		__text_start__ = .;
+
+		KEEP(*(.sketch_boot))
+
+		. = ALIGN(0x4000);
+		KEEP(*(.isr_vector))
+		*(.text*)
+
+		KEEP(*(.init))
+		KEEP(*(.fini))
+
+		/* .ctors */
+		*crtbegin.o(.ctors)
+		*crtbegin?.o(.ctors)
+		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+		*(SORT(.ctors.*))
+		*(.ctors)
+
+		/* .dtors */
+ 		*crtbegin.o(.dtors)
+ 		*crtbegin?.o(.dtors)
+ 		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ 		*(SORT(.dtors.*))
+ 		*(.dtors)
+
+		*(.rodata*)
+
+		KEEP(*(.eh_frame*))
+	} > FLASH
+
+	.ARM.extab :
+	{
+		*(.ARM.extab* .gnu.linkonce.armextab.*)
+	} > FLASH
+
+	__exidx_start = .;
+	.ARM.exidx :
+	{
+		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
+	} > FLASH
+	__exidx_end = .;
+
+	/* To copy multiple ROM to RAM sections,
+	 * uncomment .copy.table section and,
+	 * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.copy.table :
+	{
+		. = ALIGN(4);
+		__copy_table_start__ = .;
+		LONG (__etext)
+		LONG (__data_start__)
+		LONG (__data_end__ - __data_start__)
+		LONG (__etext2)
+		LONG (__data2_start__)
+		LONG (__data2_end__ - __data2_start__)
+		__copy_table_end__ = .;
+	} > FLASH
+	*/
+
+	/* To clear multiple BSS sections,
+	 * uncomment .zero.table section and,
+	 * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.zero.table :
+	{
+		. = ALIGN(4);
+		__zero_table_start__ = .;
+		LONG (__bss_start__)
+		LONG (__bss_end__ - __bss_start__)
+		LONG (__bss2_start__)
+		LONG (__bss2_end__ - __bss2_start__)
+		__zero_table_end__ = .;
+	} > FLASH
+	*/
+
+	__etext = .;
+
+	.data : AT (__etext)
+	{
+		__data_start__ = .;
+		*(vtable)
+		*(.data*)
+
+		. = ALIGN(4);
+		/* preinit data */
+		PROVIDE_HIDDEN (__preinit_array_start = .);
+		KEEP(*(.preinit_array))
+		PROVIDE_HIDDEN (__preinit_array_end = .);
+
+		. = ALIGN(4);
+		/* init data */
+		PROVIDE_HIDDEN (__init_array_start = .);
+		KEEP(*(SORT(.init_array.*)))
+		KEEP(*(.init_array))
+		PROVIDE_HIDDEN (__init_array_end = .);
+
+
+		. = ALIGN(4);
+		/* finit data */
+		PROVIDE_HIDDEN (__fini_array_start = .);
+		KEEP(*(SORT(.fini_array.*)))
+		KEEP(*(.fini_array))
+		PROVIDE_HIDDEN (__fini_array_end = .);
+
+		KEEP(*(.jcr*))
+		. = ALIGN(16);
+		/* All data end */
+		__data_end__ = .;
+
+	} > RAM
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start__ = .;
+		*(.bss*)
+		*(COMMON)
+		. = ALIGN(4);
+		__bss_end__ = .;
+	} > RAM
+
+	.heap (COPY):
+	{
+		__end__ = .;
+		PROVIDE(end = .);
+		*(.heap*)
+		__HeapLimit = .;
+	} > RAM
+
+	/* .stack_dummy section doesn't contains any symbols. It is only
+	 * used for linker to calculate size of stack sections, and assign
+	 * values to stack symbols later */
+	.stack_dummy (COPY):
+	{
+		*(.stack*)
+	} > RAM
+
+	/* Set stack top to end of RAM, and stack limit move down by
+	 * size of stack_dummy section */
+	__StackTop = ORIGIN(RAM) + LENGTH(RAM);
+	__StackLimit = __StackTop - SIZEOF(.stack_dummy);
+	PROVIDE(__stack = __StackTop);
+
+	__ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ;
+
+	/* Check if data + heap + stack exceeds RAM limit */
+	ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
+}
diff --git a/variants/feather_m4/linker_scripts/gcc/flash_without_bootloader.ld b/variants/feather_m4/linker_scripts/gcc/flash_without_bootloader.ld
new file mode 100644
index 000000000..9c0c4e06d
--- /dev/null
+++ b/variants/feather_m4/linker_scripts/gcc/flash_without_bootloader.ld
@@ -0,0 +1,214 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* Linker script to configure memory regions.
+ * Need modifying for a specific board.
+ *   FLASH.ORIGIN: starting address of flash
+ *   FLASH.LENGTH: length of flash
+ *   RAM.ORIGIN: starting address of RAM bank 0
+ *   RAM.LENGTH: length of RAM bank 0
+ */
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00080000
+  RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00030000
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ *   Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ *   __exidx_start
+ *   __exidx_end
+ *   __copy_table_start__
+ *   __copy_table_end__
+ *   __zero_table_start__
+ *   __zero_table_end__
+ *   __etext
+ *   __data_start__
+ *   __preinit_array_start
+ *   __preinit_array_end
+ *   __init_array_start
+ *   __init_array_end
+ *   __fini_array_start
+ *   __fini_array_end
+ *   __data_end__
+ *   __bss_start__
+ *   __bss_end__
+ *   __end__
+ *   end
+ *   __HeapLimit
+ *   __StackLimit
+ *   __StackTop
+ *   __stack
+ *   __ram_end__
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+	.text :
+	{
+		__text_start__ = .;
+
+		KEEP(*(.isr_vector))
+		*(.text*)
+
+		KEEP(*(.init))
+		KEEP(*(.fini))
+
+		/* .ctors */
+		*crtbegin.o(.ctors)
+		*crtbegin?.o(.ctors)
+		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+		*(SORT(.ctors.*))
+		*(.ctors)
+
+		/* .dtors */
+ 		*crtbegin.o(.dtors)
+ 		*crtbegin?.o(.dtors)
+ 		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ 		*(SORT(.dtors.*))
+ 		*(.dtors)
+
+		*(.rodata*)
+
+		KEEP(*(.eh_frame*))
+	} > FLASH
+
+	.ARM.extab :
+	{
+		*(.ARM.extab* .gnu.linkonce.armextab.*)
+	} > FLASH
+
+	__exidx_start = .;
+	.ARM.exidx :
+	{
+		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
+	} > FLASH
+	__exidx_end = .;
+
+	/* To copy multiple ROM to RAM sections,
+	 * uncomment .copy.table section and,
+	 * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.copy.table :
+	{
+		. = ALIGN(4);
+		__copy_table_start__ = .;
+		LONG (__etext)
+		LONG (__data_start__)
+		LONG (__data_end__ - __data_start__)
+		LONG (__etext2)
+		LONG (__data2_start__)
+		LONG (__data2_end__ - __data2_start__)
+		__copy_table_end__ = .;
+	} > FLASH
+	*/
+
+	/* To clear multiple BSS sections,
+	 * uncomment .zero.table section and,
+	 * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.zero.table :
+	{
+		. = ALIGN(4);
+		__zero_table_start__ = .;
+		LONG (__bss_start__)
+		LONG (__bss_end__ - __bss_start__)
+		LONG (__bss2_start__)
+		LONG (__bss2_end__ - __bss2_start__)
+		__zero_table_end__ = .;
+	} > FLASH
+	*/
+
+	__etext = .;
+
+	.data : AT (__etext)
+	{
+		__data_start__ = .;
+		*(vtable)
+		*(.data*)
+
+		. = ALIGN(4);
+		/* preinit data */
+		PROVIDE_HIDDEN (__preinit_array_start = .);
+		KEEP(*(.preinit_array))
+		PROVIDE_HIDDEN (__preinit_array_end = .);
+
+		. = ALIGN(4);
+		/* init data */
+		PROVIDE_HIDDEN (__init_array_start = .);
+		KEEP(*(SORT(.init_array.*)))
+		KEEP(*(.init_array))
+		PROVIDE_HIDDEN (__init_array_end = .);
+
+
+		. = ALIGN(4);
+		/* finit data */
+		PROVIDE_HIDDEN (__fini_array_start = .);
+		KEEP(*(SORT(.fini_array.*)))
+		KEEP(*(.fini_array))
+		PROVIDE_HIDDEN (__fini_array_end = .);
+
+		KEEP(*(.jcr*))
+		. = ALIGN(16);
+		/* All data end */
+		__data_end__ = .;
+
+	} > RAM
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start__ = .;
+		*(.bss*)
+		*(COMMON)
+		. = ALIGN(4);
+		__bss_end__ = .;
+	} > RAM
+
+	.heap (COPY):
+	{
+		__end__ = .;
+		PROVIDE(end = .);
+		*(.heap*)
+		__HeapLimit = .;
+	} > RAM
+
+	/* .stack_dummy section doesn't contains any symbols. It is only
+	 * used for linker to calculate size of stack sections, and assign
+	 * values to stack symbols later */
+	.stack_dummy (COPY):
+	{
+		*(.stack*)
+	} > RAM
+
+	/* Set stack top to end of RAM, and stack limit move down by
+	 * size of stack_dummy section */
+	__StackTop = ORIGIN(RAM) + LENGTH(RAM) ;
+	__StackLimit = __StackTop - SIZEOF(.stack_dummy);
+	PROVIDE(__stack = __StackTop);
+
+	__ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ;
+
+	/* Check if data + heap + stack exceeds RAM limit */
+	ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
+}
diff --git a/variants/feather_m4/pins_arduino.h b/variants/feather_m4/pins_arduino.h
new file mode 100644
index 000000000..db0e40c3d
--- /dev/null
+++ b/variants/feather_m4/pins_arduino.h
@@ -0,0 +1,21 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+// API compatibility
+#include "variant.h"
+
diff --git a/variants/feather_m4/variant.cpp b/variants/feather_m4/variant.cpp
new file mode 100644
index 000000000..88ba1ff6c
--- /dev/null
+++ b/variants/feather_m4/variant.cpp
@@ -0,0 +1,140 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "variant.h"
+
+/*
+ * Pins descriptions
+ */
+
+//TCC0 IOSET 6
+//TCC1 IOSET 1
+//TC0 IOSET 1
+//TC1 IOSET 1
+//TC2 IOSET 2
+//TC3 IOSET 1
+//TC4 IOSET 1
+const PinDescription g_APinDescription[]=
+{
+  // 0..13 - Digital pins
+  // ----------------------
+  // 0/1 - SERCOM/UART (Serial1)
+  { PORTB, 17, PIO_SERCOM, PIN_ATTR_PWM_G, No_ADC_Channel, TCC0_CH4, NOT_ON_TIMER, EXTERNAL_INT_1 }, // RX: SERCOM5/PAD[1]
+  { PORTB, 16, PIO_SERCOM, PIN_ATTR_PWM_G, No_ADC_Channel, TCC0_CH5, NOT_ON_TIMER, EXTERNAL_INT_0 }, // TX: SERCOM5/PAD[0]
+
+  // 2..12
+  // Digital Low
+  { NOT_A_PORT, 0,  PIO_NOT_A_PIN, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+  { NOT_A_PORT, 0,  PIO_NOT_A_PIN, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+  { PORTA, 14, PIO_DIGITAL, PIN_ATTR_PWM_E, No_ADC_Channel, TC3_CH0, TC3_CH0, EXTERNAL_INT_14 },
+  { PORTA,  16, PIO_TIMER_ALT, PIN_ATTR_PWM_F, No_ADC_Channel, TCC1_CH0, TC2_CH0, EXTERNAL_INT_0  },
+  { PORTA,  18, PIO_TIMER_ALT, PIN_ATTR_PWM_F, No_ADC_Channel, TCC1_CH2, TC3_CH0, EXTERNAL_INT_2 },
+  { NOT_A_PORT, 0, PIO_NOT_A_PIN, PIN_ATTR_TIMER, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+
+  // Digital High
+  { PORTB, 3, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, //neopix
+  { PORTA,  19, PIO_TIMER_ALT, PIN_ATTR_PWM_F, No_ADC_Channel, TCC1_CH3, TC3_CH1, EXTERNAL_INT_3 },
+  { PORTA,  20, PIO_TIMER_ALT, PIN_ATTR_PWM_G, No_ADC_Channel, TCC0_CH0, NOT_ON_TIMER, EXTERNAL_INT_4 },
+  { PORTA, 21, PIO_DIGITAL, PIN_ATTR_PWM_G, No_ADC_Channel, TCC0_CH1, NOT_ON_TIMER, EXTERNAL_INT_5 },
+  { PORTA, 22, PIO_DIGITAL, PIN_ATTR_PWM_G, No_ADC_Channel, TCC0_CH2, NOT_ON_TIMER, EXTERNAL_INT_6 },
+
+  // 13 (LED)
+  { PORTA, 23, PIO_DIGITAL, PIN_ATTR_PWM_G, No_ADC_Channel, TCC0_CH3, TC4_CH1, EXTERNAL_INT_7 }, // TCC2/WO[1]
+
+  // 14..19 - Analog pins
+  // --------------------
+  { PORTA,  2, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel0, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 },
+  { PORTA,  5, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel5, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_5 },
+  { PORTB,  8, PIO_ANALOG, (PIN_ATTR_ANALOG|PIN_ATTR_PWM_E), ADC_Channel2, TC4_CH0, TC4_CH0, EXTERNAL_INT_8 },
+  { PORTB,  9, PIO_ANALOG, (PIN_ATTR_ANALOG|PIN_ATTR_PWM_E), ADC_Channel3, TC4_CH1, TC4_CH1, EXTERNAL_INT_9 },
+  { PORTA,  4, PIO_ANALOG, (PIN_ATTR_ANALOG|PIN_ATTR_PWM_E), ADC_Channel4, TC0_CH0, TC0_CH0, EXTERNAL_INT_4 },
+  { PORTA,  6, PIO_ANALOG, (PIN_ATTR_ANALOG|PIN_ATTR_PWM_E), ADC_Channel6, TC1_CH0, TC1_CH0, EXTERNAL_INT_6 },
+
+  // A6, D20 - VDiv!
+  { PORTB,  1, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel13, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_1 },
+
+
+  // 21..22 I2C pins (SDA/SCL)
+  // ----------------------
+  { PORTA, 12, PIO_SERCOM, PIN_ATTR_PWM_E, No_ADC_Channel, TC2_CH0, TC2_CH0, EXTERNAL_INT_12 }, // SDA: SERCOM2/PAD[0]
+  { PORTA, 13, PIO_SERCOM, PIN_ATTR_PWM_E, No_ADC_Channel, TC2_CH1, TC2_CH1, EXTERNAL_INT_13 }, // SCL: SERCOM2/PAD[1]
+
+  // 23..25 - SPI pins (MISO,MOSI,SCK)
+  // ----------------------
+  { PORTB, 22, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_6 }, // MISO: SERCOM1/PAD[2]
+  { PORTB, 23, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_7 }, // MOSI: SERCOM1/PAD[3]
+  { PORTA, 17, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_1 }, // SCK: SERCOM1/PAD[1]
+
+  // 26..27 - RX/TX LEDS  -- unused
+  // --------------------
+  { NOT_A_PORT, 0, PIO_NOT_A_PIN, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+  { NOT_A_PORT, 0, PIO_NOT_A_PIN, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+
+  // 28..30 - USB
+  // --------------------
+  { NOT_A_PORT, 0, PIO_NOT_A_PIN, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB Host enable DOES NOT EXIST ON THIS BOARD
+  { PORTA, 24, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB/DM
+  { PORTA, 27, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB/DP
+
+  // 31 (AREF)
+  { PORTA, 3, PIO_ANALOG, PIN_ATTR_ANALOG, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // DAC/VREFP
+
+  // ----------------------
+  // 32..33 - Alternate use of A0 (DAC output)
+  { PORTA,  2, PIO_ANALOG, PIN_ATTR_ANALOG, DAC_Channel0, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // DAC/VOUT0
+  { PORTA,  5, PIO_ANALOG, PIN_ATTR_ANALOG, DAC_Channel1, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // DAC/VOUT1
+
+  // ----------------------
+  // 34..39 QSPI (SCK, CS, IO0, IO1, IO2, IO3)
+  { PORTB, 10, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+  { PORTB, 11, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+  { PORTA, 8, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+  { PORTA, 9, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+  { PORTA, 10, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+  { PORTA, 11, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+} ;
+
+const void* g_apTCInstances[TCC_INST_NUM+TC_INST_NUM]={ TCC0, TCC1, TCC2, TCC3, TCC4, TC0, TC1, TC2, TC3, TC4, TC5 } ;
+const uint32_t GCLK_CLKCTRL_IDs[TCC_INST_NUM+TC_INST_NUM] = { TCC0_GCLK_ID, TCC1_GCLK_ID, TCC2_GCLK_ID, TCC3_GCLK_ID, TCC4_GCLK_ID, TC0_GCLK_ID, TC1_GCLK_ID, TC2_GCLK_ID, TC3_GCLK_ID, TC4_GCLK_ID, TC5_GCLK_ID } ;
+
+// Multi-serial objects instantiation
+SERCOM sercom0( SERCOM0 ) ;
+SERCOM sercom1( SERCOM1 ) ;
+SERCOM sercom2( SERCOM2 ) ;
+SERCOM sercom3( SERCOM3 ) ;
+SERCOM sercom4( SERCOM4 ) ;
+SERCOM sercom5( SERCOM5 ) ;
+
+Uart Serial1( &sercom5, PIN_SERIAL1_RX, PIN_SERIAL1_TX, PAD_SERIAL1_RX, PAD_SERIAL1_TX ) ;
+
+void SERCOM5_0_Handler()
+{
+  Serial1.IrqHandler();
+}
+void SERCOM5_1_Handler()
+{
+  Serial1.IrqHandler();
+}
+void SERCOM5_2_Handler()
+{
+  Serial1.IrqHandler();
+}
+void SERCOM5_3_Handler()
+{
+  Serial1.IrqHandler();
+}
diff --git a/variants/feather_m4/variant.h b/variants/feather_m4/variant.h
new file mode 100644
index 000000000..6be35dccb
--- /dev/null
+++ b/variants/feather_m4/variant.h
@@ -0,0 +1,253 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _VARIANT_FEATHER_M4_
+#define _VARIANT_FEATHER_M4_
+
+// The definitions here needs a SAMD core >=1.6.10
+#define ARDUINO_SAMD_VARIANT_COMPLIANCE 10610
+
+/*----------------------------------------------------------------------------
+ *        Definitions
+ *----------------------------------------------------------------------------*/
+
+/** Frequency of the board main oscillator */
+#define VARIANT_MAINOSC		(32768ul)
+
+/** Master clock frequency */
+#define VARIANT_MCK        (F_CPU)
+
+#define VARIANT_GCLK0_FREQ (F_CPU)
+#define VARIANT_GCLK1_FREQ (48000000UL)
+#define VARIANT_GCLK2_FREQ (100000000UL)
+
+/*----------------------------------------------------------------------------
+ *        Headers
+ *----------------------------------------------------------------------------*/
+
+#include "WVariant.h"
+
+#ifdef __cplusplus
+#include "SERCOM.h"
+#include "Uart.h"
+#endif // __cplusplus
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif // __cplusplus
+
+/*----------------------------------------------------------------------------
+ *        Pins
+ *----------------------------------------------------------------------------*/
+
+// Number of pins defined in PinDescription array
+#define PINS_COUNT           (40u)
+#define NUM_DIGITAL_PINS     (20u)
+#define NUM_ANALOG_INPUTS    (6u)
+#define NUM_ANALOG_OUTPUTS   (1u)
+#define analogInputToDigitalPin(p)  ((p < 6u) ? (p) + 14u : -1)
+
+#define digitalPinToPort(P)        ( &(PORT->Group[g_APinDescription[P].ulPort]) )
+#define digitalPinToBitMask(P)     ( 1 << g_APinDescription[P].ulPin )
+//#define analogInPinToBit(P)        ( )
+#define portOutputRegister(port)   ( &(port->OUT.reg) )
+#define portInputRegister(port)    ( &(port->IN.reg) )
+#define portModeRegister(port)     ( &(port->DIR.reg) )
+#define digitalPinHasPWM(P)        ( g_APinDescription[P].ulPWMChannel != NOT_ON_PWM || g_APinDescription[P].ulTCChannel != NOT_ON_TIMER )
+
+/*
+ * digitalPinToTimer(..) is AVR-specific and is not defined for SAMD
+ * architecture. If you need to check if a pin supports PWM you must
+ * use digitalPinHasPWM(..).
+ *
+ * https://github.com/arduino/Arduino/issues/1833
+ */
+// #define digitalPinToTimer(P)
+
+// LEDs
+#define PIN_LED_13           (13u)
+#define PIN_LED_RXL          (25u)
+#define PIN_LED_TXL          (26u)
+#define PIN_LED              PIN_LED_13
+#define PIN_LED2             PIN_LED_RXL
+#define PIN_LED3             PIN_LED_TXL
+#define LED_BUILTIN          PIN_LED_13
+#define PIN_NEOPIXEL         (8)
+
+/*
+ * Analog pins
+ */
+#define PIN_A0               (14ul)
+#define PIN_A1               (PIN_A0 + 1)
+#define PIN_A2               (PIN_A0 + 2)
+#define PIN_A3               (PIN_A0 + 3)
+#define PIN_A4               (PIN_A0 + 4)
+#define PIN_A5               (PIN_A0 + 5)
+#define PIN_A6               (PIN_A0 + 6)
+
+#define PIN_DAC0             (14ul)
+#define PIN_DAC1             PIN_A1
+
+static const uint8_t A0  = PIN_A0;
+static const uint8_t A1  = PIN_A1;
+static const uint8_t A2  = PIN_A2;
+static const uint8_t A3  = PIN_A3;
+static const uint8_t A4  = PIN_A4;
+static const uint8_t A5  = PIN_A5;
+static const uint8_t A6  = PIN_A6 ;
+
+static const uint8_t DAC0 = PIN_DAC0;
+static const uint8_t DAC1 = PIN_DAC1;
+
+#define ADC_RESOLUTION		12
+
+// Other pins
+#define PIN_ATN              (31ul)
+static const uint8_t ATN = PIN_ATN;
+
+/*
+ * Serial interfaces
+ */
+
+// Serial1
+#define PIN_SERIAL1_RX       (0ul)
+#define PIN_SERIAL1_TX       (1ul)
+#define PAD_SERIAL1_RX       (SERCOM_RX_PAD_1)
+#define PAD_SERIAL1_TX       (UART_TX_PAD_0)
+
+/*
+ * SPI Interfaces
+ */
+#define SPI_INTERFACES_COUNT 1
+
+#define PIN_SPI_MISO         (23u)
+#define PIN_SPI_MOSI         (24u)
+#define PIN_SPI_SCK          (25u)
+#define PERIPH_SPI           sercom1
+#define PAD_SPI_TX           SPI_PAD_3_SCK_1
+#define PAD_SPI_RX           SERCOM_RX_PAD_2
+
+static const uint8_t SS	  = 9 ;	// SERCOM1 last PAD is present on d9 but HW SS isn't used. Set here only for reference.
+static const uint8_t MOSI = PIN_SPI_MOSI ;
+static const uint8_t MISO = PIN_SPI_MISO ;
+static const uint8_t SCK  = PIN_SPI_SCK ;
+
+/*
+ * Wire Interfaces
+ */
+#define WIRE_INTERFACES_COUNT 1
+
+#define PIN_WIRE_SDA         (21u)
+#define PIN_WIRE_SCL         (22u)
+#define PERIPH_WIRE          sercom2
+#define WIRE_IT_HANDLER      SERCOM2_Handler
+#define WIRE_IT_HANDLER_0    SERCOM2_0_Handler
+#define WIRE_IT_HANDLER_1    SERCOM2_1_Handler
+#define WIRE_IT_HANDLER_2    SERCOM2_2_Handler
+#define WIRE_IT_HANDLER_3    SERCOM2_3_Handler
+
+static const uint8_t SDA = PIN_WIRE_SDA;
+static const uint8_t SCL = PIN_WIRE_SCL;
+
+/*
+ * USB
+ */
+#define PIN_USB_HOST_ENABLE (28ul)
+#define PIN_USB_DM          (29ul)
+#define PIN_USB_DP          (30ul)
+
+/*
+ * I2S Interfaces
+ */
+#define I2S_INTERFACES_COUNT 1
+
+#define I2S_DEVICE          0
+#define I2S_CLOCK_GENERATOR 3
+
+#define PIN_I2S_SDO          (11u)
+#define PIN_I2S_SDI          (12u)
+#define PIN_I2S_SCK          PIN_SERIAL1_TX
+#define PIN_I2S_FS           (10u)
+#define PIN_I2S_MCK          PIN_SERIAL1_RX
+
+// On-board QSPI Flash
+#define EXTERNAL_FLASH_DEVICES   GD25Q16C
+#define EXTERNAL_FLASH_USE_QSPI
+
+//QSPI Pins
+#define PIN_QSPI_SCK    (34u)
+#define PIN_QSPI_CS     (35u)
+#define PIN_QSPI_IO0    (36u)
+#define PIN_QSPI_IO1    (37u)
+#define PIN_QSPI_IO2    (38u)
+#define PIN_QSPI_IO3    (39u)
+
+#if !defined(VARIANT_QSPI_BAUD_DEFAULT)
+  // TODO: meaningful value for this
+  #define VARIANT_QSPI_BAUD_DEFAULT 5000000
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+ *        Arduino objects - C++ only
+ *----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+
+/*	=========================
+ *	===== SERCOM DEFINITION
+ *	=========================
+*/
+extern SERCOM sercom0;
+extern SERCOM sercom1;
+extern SERCOM sercom2;
+extern SERCOM sercom3;
+extern SERCOM sercom4;
+extern SERCOM sercom5;
+
+extern Uart Serial1;
+
+#endif
+
+// These serial port names are intended to allow libraries and architecture-neutral
+// sketches to automatically default to the correct port name for a particular type
+// of use.  For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN,
+// the first hardware serial port whose RX/TX pins are not dedicated to another use.
+//
+// SERIAL_PORT_MONITOR        Port which normally prints to the Arduino Serial Monitor
+//
+// SERIAL_PORT_USBVIRTUAL     Port which is USB virtual serial
+//
+// SERIAL_PORT_LINUXBRIDGE    Port which connects to a Linux system via Bridge library
+//
+// SERIAL_PORT_HARDWARE       Hardware serial port, physical RX & TX pins.
+//
+// SERIAL_PORT_HARDWARE_OPEN  Hardware serial ports which are open for use.  Their RX & TX
+//                            pins are NOT connected to anything by default.
+#define SERIAL_PORT_USBVIRTUAL      Serial
+#define SERIAL_PORT_MONITOR         Serial
+// Serial has no physical pins broken out, so it's not listed as HARDWARE port
+#define SERIAL_PORT_HARDWARE        Serial1
+#define SERIAL_PORT_HARDWARE_OPEN   Serial1
+
+#endif /* _VARIANT_FEATHER_M4_ */
+
diff --git a/variants/feather_m4_can/linker_scripts/gcc/flash_with_bootloader.ld b/variants/feather_m4_can/linker_scripts/gcc/flash_with_bootloader.ld
new file mode 100644
index 000000000..379e54ed3
--- /dev/null
+++ b/variants/feather_m4_can/linker_scripts/gcc/flash_with_bootloader.ld
@@ -0,0 +1,225 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* Linker script to configure memory regions.
+ * Need modifying for a specific board.
+ *   FLASH.ORIGIN: starting address of flash
+ *   FLASH.LENGTH: length of flash
+ *   RAM.ORIGIN: starting address of RAM bank 0
+ *   RAM.LENGTH: length of RAM bank 0
+ */
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000+0x4000, LENGTH = 0x00080000-0x4000 /* First 16KB used by bootloader */
+  RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00030000
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ *   Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ *   __exidx_start
+ *   __exidx_end
+ *   __copy_table_start__
+ *   __copy_table_end__
+ *   __zero_table_start__
+ *   __zero_table_end__
+ *   __etext
+ *   __data_start__
+ *   __preinit_array_start
+ *   __preinit_array_end
+ *   __init_array_start
+ *   __init_array_end
+ *   __fini_array_start
+ *   __fini_array_end
+ *   __data_end__
+ *   __bss_start__
+ *   __bss_end__
+ *   __end__
+ *   end
+ *   __HeapLimit
+ *   __StackLimit
+ *   __StackTop
+ *   __stack
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+	.text :
+	{
+		__text_start__ = .;
+
+		KEEP(*(.sketch_boot))
+
+		. = ALIGN(0x4000);
+		KEEP(*(.isr_vector))
+		*(.text*)
+
+		KEEP(*(.init))
+		KEEP(*(.fini))
+
+		/* .ctors */
+		*crtbegin.o(.ctors)
+		*crtbegin?.o(.ctors)
+		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+		*(SORT(.ctors.*))
+		*(.ctors)
+
+		/* .dtors */
+ 		*crtbegin.o(.dtors)
+ 		*crtbegin?.o(.dtors)
+ 		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ 		*(SORT(.dtors.*))
+ 		*(.dtors)
+
+		*(.rodata*)
+
+		KEEP(*(.eh_frame*))
+	} > FLASH
+
+	.ARM.extab :
+	{
+		*(.ARM.extab* .gnu.linkonce.armextab.*)
+	} > FLASH
+
+	__exidx_start = .;
+	.ARM.exidx :
+	{
+		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
+	} > FLASH
+	__exidx_end = .;
+
+	/* To copy multiple ROM to RAM sections,
+	 * uncomment .copy.table section and,
+	 * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.copy.table :
+	{
+		. = ALIGN(4);
+		__copy_table_start__ = .;
+		LONG (__etext)
+		LONG (__data_start__)
+		LONG (__data_end__ - __data_start__)
+		LONG (__etext2)
+		LONG (__data2_start__)
+		LONG (__data2_end__ - __data2_start__)
+		__copy_table_end__ = .;
+	} > FLASH
+	*/
+
+	/* To clear multiple BSS sections,
+	 * uncomment .zero.table section and,
+	 * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.zero.table :
+	{
+		. = ALIGN(4);
+		__zero_table_start__ = .;
+		LONG (__bss_start__)
+		LONG (__bss_end__ - __bss_start__)
+		LONG (__bss2_start__)
+		LONG (__bss2_end__ - __bss2_start__)
+		__zero_table_end__ = .;
+	} > FLASH
+	*/
+
+	__etext = .;
+
+	/* Data accessed by the CAN peripheral must be in the first 64kB RAM */
+	/* place it at the very start of RAM, before the .data section */
+	/* *NOTE* it is not expliclty zeroed */
+	.canram (NOLOAD) :
+	{
+	    . = ALIGN(4);
+	    *(.canram)
+	} > RAM
+
+	.data : AT (__etext)
+	{
+		__data_start__ = .;
+		*(vtable)
+		*(.data*)
+
+		. = ALIGN(4);
+		/* preinit data */
+		PROVIDE_HIDDEN (__preinit_array_start = .);
+		KEEP(*(.preinit_array))
+		PROVIDE_HIDDEN (__preinit_array_end = .);
+
+		. = ALIGN(4);
+		/* init data */
+		PROVIDE_HIDDEN (__init_array_start = .);
+		KEEP(*(SORT(.init_array.*)))
+		KEEP(*(.init_array))
+		PROVIDE_HIDDEN (__init_array_end = .);
+
+
+		. = ALIGN(4);
+		/* finit data */
+		PROVIDE_HIDDEN (__fini_array_start = .);
+		KEEP(*(SORT(.fini_array.*)))
+		KEEP(*(.fini_array))
+		PROVIDE_HIDDEN (__fini_array_end = .);
+
+		KEEP(*(.jcr*))
+		. = ALIGN(16);
+		/* All data end */
+		__data_end__ = .;
+
+	} > RAM
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start__ = .;
+		*(.bss*)
+		*(COMMON)
+		. = ALIGN(4);
+		__bss_end__ = .;
+	} > RAM
+
+	.heap (COPY):
+	{
+		__end__ = .;
+		PROVIDE(end = .);
+		*(.heap*)
+		__HeapLimit = .;
+	} > RAM
+
+	/* .stack_dummy section doesn't contains any symbols. It is only
+	 * used for linker to calculate size of stack sections, and assign
+	 * values to stack symbols later */
+	.stack_dummy (COPY):
+	{
+		*(.stack*)
+	} > RAM
+
+	/* Set stack top to end of RAM, and stack limit move down by
+	 * size of stack_dummy section */
+	__StackTop = ORIGIN(RAM) + LENGTH(RAM);
+	__StackLimit = __StackTop - SIZEOF(.stack_dummy);
+	PROVIDE(__stack = __StackTop);
+
+	__ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ;
+
+	/* Check if data + heap + stack exceeds RAM limit */
+	ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
+}
diff --git a/variants/feather_m4_can/linker_scripts/gcc/flash_without_bootloader.ld b/variants/feather_m4_can/linker_scripts/gcc/flash_without_bootloader.ld
new file mode 100644
index 000000000..9e81bbab8
--- /dev/null
+++ b/variants/feather_m4_can/linker_scripts/gcc/flash_without_bootloader.ld
@@ -0,0 +1,223 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* Linker script to configure memory regions.
+ * Need modifying for a specific board.
+ *   FLASH.ORIGIN: starting address of flash
+ *   FLASH.LENGTH: length of flash
+ *   RAM.ORIGIN: starting address of RAM bank 0
+ *   RAM.LENGTH: length of RAM bank 0
+ */
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00080000
+  RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00030000
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ *   Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ *   __exidx_start
+ *   __exidx_end
+ *   __copy_table_start__
+ *   __copy_table_end__
+ *   __zero_table_start__
+ *   __zero_table_end__
+ *   __etext
+ *   __data_start__
+ *   __preinit_array_start
+ *   __preinit_array_end
+ *   __init_array_start
+ *   __init_array_end
+ *   __fini_array_start
+ *   __fini_array_end
+ *   __data_end__
+ *   __bss_start__
+ *   __bss_end__
+ *   __end__
+ *   end
+ *   __HeapLimit
+ *   __StackLimit
+ *   __StackTop
+ *   __stack
+ *   __ram_end__
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+	.text :
+	{
+		__text_start__ = .;
+
+		KEEP(*(.isr_vector))
+		*(.text*)
+
+		KEEP(*(.init))
+		KEEP(*(.fini))
+
+		/* .ctors */
+		*crtbegin.o(.ctors)
+		*crtbegin?.o(.ctors)
+		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+		*(SORT(.ctors.*))
+		*(.ctors)
+
+		/* .dtors */
+ 		*crtbegin.o(.dtors)
+ 		*crtbegin?.o(.dtors)
+ 		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ 		*(SORT(.dtors.*))
+ 		*(.dtors)
+
+		*(.rodata*)
+
+		KEEP(*(.eh_frame*))
+	} > FLASH
+
+	.ARM.extab :
+	{
+		*(.ARM.extab* .gnu.linkonce.armextab.*)
+	} > FLASH
+
+	__exidx_start = .;
+	.ARM.exidx :
+	{
+		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
+	} > FLASH
+	__exidx_end = .;
+
+	/* To copy multiple ROM to RAM sections,
+	 * uncomment .copy.table section and,
+	 * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.copy.table :
+	{
+		. = ALIGN(4);
+		__copy_table_start__ = .;
+		LONG (__etext)
+		LONG (__data_start__)
+		LONG (__data_end__ - __data_start__)
+		LONG (__etext2)
+		LONG (__data2_start__)
+		LONG (__data2_end__ - __data2_start__)
+		__copy_table_end__ = .;
+	} > FLASH
+	*/
+
+	/* To clear multiple BSS sections,
+	 * uncomment .zero.table section and,
+	 * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.zero.table :
+	{
+		. = ALIGN(4);
+		__zero_table_start__ = .;
+		LONG (__bss_start__)
+		LONG (__bss_end__ - __bss_start__)
+		LONG (__bss2_start__)
+		LONG (__bss2_end__ - __bss2_start__)
+		__zero_table_end__ = .;
+	} > FLASH
+	*/
+
+	__etext = .;
+
+	/* Data accessed by the CAN peripheral must be in the first 64kB RAM */
+	/* place it at the very start of RAM, before the .data section */
+	/* *NOTE* it is not expliclty zeroed */
+	.canram (NOLOAD) :
+	{
+	    . = ALIGN(4);
+	    *(.canram)
+	} > RAM
+
+	.data : AT (__etext)
+	{
+		__data_start__ = .;
+		*(vtable)
+		*(.data*)
+
+		. = ALIGN(4);
+		/* preinit data */
+		PROVIDE_HIDDEN (__preinit_array_start = .);
+		KEEP(*(.preinit_array))
+		PROVIDE_HIDDEN (__preinit_array_end = .);
+
+		. = ALIGN(4);
+		/* init data */
+		PROVIDE_HIDDEN (__init_array_start = .);
+		KEEP(*(SORT(.init_array.*)))
+		KEEP(*(.init_array))
+		PROVIDE_HIDDEN (__init_array_end = .);
+
+
+		. = ALIGN(4);
+		/* finit data */
+		PROVIDE_HIDDEN (__fini_array_start = .);
+		KEEP(*(SORT(.fini_array.*)))
+		KEEP(*(.fini_array))
+		PROVIDE_HIDDEN (__fini_array_end = .);
+
+		KEEP(*(.jcr*))
+		. = ALIGN(16);
+		/* All data end */
+		__data_end__ = .;
+
+	} > RAM
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start__ = .;
+		*(.bss*)
+		*(COMMON)
+		. = ALIGN(4);
+		__bss_end__ = .;
+	} > RAM
+
+	.heap (COPY):
+	{
+		__end__ = .;
+		PROVIDE(end = .);
+		*(.heap*)
+		__HeapLimit = .;
+	} > RAM
+
+	/* .stack_dummy section doesn't contains any symbols. It is only
+	 * used for linker to calculate size of stack sections, and assign
+	 * values to stack symbols later */
+	.stack_dummy (COPY):
+	{
+		*(.stack*)
+	} > RAM
+
+	/* Set stack top to end of RAM, and stack limit move down by
+	 * size of stack_dummy section */
+	__StackTop = ORIGIN(RAM) + LENGTH(RAM) ;
+	__StackLimit = __StackTop - SIZEOF(.stack_dummy);
+	PROVIDE(__stack = __StackTop);
+
+	__ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ;
+
+	/* Check if data + heap + stack exceeds RAM limit */
+	ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
+}
diff --git a/variants/feather_m4_can/pins_arduino.h b/variants/feather_m4_can/pins_arduino.h
new file mode 100644
index 000000000..db0e40c3d
--- /dev/null
+++ b/variants/feather_m4_can/pins_arduino.h
@@ -0,0 +1,21 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+// API compatibility
+#include "variant.h"
+
diff --git a/variants/feather_m4_can/variant.cpp b/variants/feather_m4_can/variant.cpp
new file mode 100644
index 000000000..b52e662c4
--- /dev/null
+++ b/variants/feather_m4_can/variant.cpp
@@ -0,0 +1,156 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "variant.h"
+#include "Arduino.h"
+
+/*
+ * Pins descriptions
+ */
+
+//TCC0 IOSET 6
+//TCC1 IOSET 1
+//TC0 IOSET 1
+//TC1 IOSET 1
+//TC2 IOSET 2
+//TC3 IOSET 1
+//TC4 IOSET 1
+const PinDescription g_APinDescription[PINS_COUNT]=
+{
+  // 0..13 - Digital pins
+  // ----------------------
+  // 0/1 - SERCOM/UART (Serial1)
+  { PORTB, 17, PIO_SERCOM, PIN_ATTR_PWM_G, No_ADC_Channel, TCC0_CH4, NOT_ON_TIMER, EXTERNAL_INT_1 }, // RX: SERCOM5/PAD[1]
+  { PORTB, 16, PIO_SERCOM, PIN_ATTR_PWM_G, No_ADC_Channel, TCC0_CH5, NOT_ON_TIMER, EXTERNAL_INT_0 }, // TX: SERCOM5/PAD[0]
+
+  // 2..12
+  // Digital Low
+  { NOT_A_PORT, 0,  PIO_NOT_A_PIN, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+  { NOT_A_PORT, 0,  PIO_NOT_A_PIN, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+  { PORTA, 14, PIO_DIGITAL, PIN_ATTR_PWM_E, No_ADC_Channel, TC3_CH0, TC3_CH0, EXTERNAL_INT_14 },
+  { PORTA, 16, PIO_TIMER_ALT, PIN_ATTR_PWM_F, No_ADC_Channel, TCC1_CH0, TC2_CH0, EXTERNAL_INT_0  },
+  { PORTA, 18, PIO_TIMER_ALT, PIN_ATTR_PWM_F, No_ADC_Channel, TCC1_CH2, TC3_CH0, EXTERNAL_INT_2 },
+  { PORTB,  3, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // 7: neopixel power
+
+  // Digital High
+  { PORTB, 2, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // 8: neopixel
+  { PORTA, 19, PIO_TIMER_ALT, PIN_ATTR_PWM_F, No_ADC_Channel, TCC1_CH3, TC3_CH1, EXTERNAL_INT_3 },
+  { PORTA, 20, PIO_TIMER_ALT, PIN_ATTR_PWM_G, No_ADC_Channel, TCC0_CH0, NOT_ON_TIMER, EXTERNAL_INT_4 },
+  { PORTA, 21, PIO_DIGITAL, PIN_ATTR_PWM_G, No_ADC_Channel, TCC0_CH1, NOT_ON_TIMER, EXTERNAL_INT_5 },
+  { PORTA, 22, PIO_DIGITAL, PIN_ATTR_PWM_G, No_ADC_Channel, TCC0_CH2, NOT_ON_TIMER, EXTERNAL_INT_6 },
+
+  // 13 (LED)
+  { PORTA, 23, PIO_DIGITAL, PIN_ATTR_PWM_G, No_ADC_Channel, TCC0_CH3, TC4_CH1, EXTERNAL_INT_7 },
+
+  // 14..19 - Analog pins
+  // --------------------
+  { PORTA,  2, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel0, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 },
+  { PORTA,  5, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel5, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_5 },
+  { PORTB,  8, PIO_ANALOG, (PIN_ATTR_ANALOG|PIN_ATTR_PWM_E), ADC_Channel2, TC4_CH0, TC4_CH0, EXTERNAL_INT_8 },
+  { PORTB,  9, PIO_ANALOG, (PIN_ATTR_ANALOG|PIN_ATTR_PWM_E), ADC_Channel3, TC4_CH1, TC4_CH1, EXTERNAL_INT_9 },
+  { PORTA,  4, PIO_ANALOG, (PIN_ATTR_ANALOG|PIN_ATTR_PWM_E), ADC_Channel4, TC0_CH0, TC0_CH0, EXTERNAL_INT_4 },
+  { PORTA,  6, PIO_ANALOG, (PIN_ATTR_ANALOG|PIN_ATTR_PWM_E), ADC_Channel6, TC1_CH0, TC1_CH0, EXTERNAL_INT_6 },
+
+  // A6, D20 - VDiv!
+  { PORTB,  1, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel13, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_1 },
+
+
+  // 21..22 I2C pins (SDA/SCL)
+  // ----------------------
+  { PORTA, 12, PIO_SERCOM, PIN_ATTR_PWM_E, No_ADC_Channel, TC2_CH0, TC2_CH0, EXTERNAL_INT_12 }, // SDA: SERCOM2/PAD[0]
+  { PORTA, 13, PIO_SERCOM, PIN_ATTR_PWM_E, No_ADC_Channel, TC2_CH1, TC2_CH1, EXTERNAL_INT_13 }, // SCL: SERCOM2/PAD[1]
+
+  // 23..25 - SPI pins (MISO,MOSI,SCK)
+  // ----------------------
+  { PORTB, 22, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_6 }, // MISO: SERCOM1/PAD[2]
+  { PORTB, 23, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_7 }, // MOSI: SERCOM1/PAD[3]
+  { PORTA, 17, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_1 }, // SCK: SERCOM1/PAD[1]
+
+  // 26..27 - RX/TX LEDS  -- unused
+  // --------------------
+  { NOT_A_PORT, 0, PIO_NOT_A_PIN, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+  { NOT_A_PORT, 0, PIO_NOT_A_PIN, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+
+  // 28..30 - USB
+  // --------------------
+  { NOT_A_PORT, 0, PIO_NOT_A_PIN, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB Host enable DOES NOT EXIST ON THIS BOARD
+  { PORTA, 24, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB/DM
+  { PORTA, 27, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB/DP
+
+  // 31 (AREF)
+  { PORTA, 3, PIO_ANALOG, PIN_ATTR_ANALOG, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // DAC/VREFP
+
+  // ----------------------
+  // 32..33 - Alternate use of A0 (DAC output)
+  { PORTA,  2, PIO_ANALOG, PIN_ATTR_ANALOG, DAC_Channel0, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // DAC/VOUT0
+  { PORTA,  5, PIO_ANALOG, PIN_ATTR_ANALOG, DAC_Channel1, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // DAC/VOUT1
+
+  // ----------------------
+  // 34..39 QSPI (SCK, CS, IO0, IO1, IO2, IO3)
+  { PORTB, 10, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+  { PORTB, 11, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+  { PORTA, 8, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+  { PORTA, 9, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+  { PORTA, 10, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+  { PORTA, 11, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+
+  // ----------------------
+  // 40..43 CAN (STANDBY, BOOST, TX, RX)
+  { PORTB, 12, PIO_DIGITAL, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+  { PORTB, 13, PIO_DIGITAL, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+  { PORTB, 14, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+  { PORTB, 15, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+} ;
+
+const void* g_apTCInstances[TCC_INST_NUM+TC_INST_NUM]={ TCC0, TCC1, TCC2, TCC3, TCC4, TC0, TC1, TC2, TC3, TC4, TC5 } ;
+const uint32_t GCLK_CLKCTRL_IDs[TCC_INST_NUM+TC_INST_NUM] = { TCC0_GCLK_ID, TCC1_GCLK_ID, TCC2_GCLK_ID, TCC3_GCLK_ID, TCC4_GCLK_ID, TC0_GCLK_ID, TC1_GCLK_ID, TC2_GCLK_ID, TC3_GCLK_ID, TC4_GCLK_ID, TC5_GCLK_ID } ;
+
+// Multi-serial objects instantiation
+SERCOM sercom0( SERCOM0 ) ;
+SERCOM sercom1( SERCOM1 ) ;
+SERCOM sercom2( SERCOM2 ) ;
+SERCOM sercom3( SERCOM3 ) ;
+SERCOM sercom4( SERCOM4 ) ;
+SERCOM sercom5( SERCOM5 ) ;
+
+Uart Serial1( &sercom5, PIN_SERIAL1_RX, PIN_SERIAL1_TX, PAD_SERIAL1_RX, PAD_SERIAL1_TX ) ;
+
+void SERCOM5_0_Handler()
+{
+  Serial1.IrqHandler();
+}
+void SERCOM5_1_Handler()
+{
+  Serial1.IrqHandler();
+}
+void SERCOM5_2_Handler()
+{
+  Serial1.IrqHandler();
+}
+void SERCOM5_3_Handler()
+{
+  Serial1.IrqHandler();
+}
+
+void initVariant(void) {
+  // special initialization code just for us
+
+  // turn on neopixel
+  pinMode(7, OUTPUT);
+  digitalWrite(7, HIGH);
+}
diff --git a/variants/feather_m4_can/variant.h b/variants/feather_m4_can/variant.h
new file mode 100644
index 000000000..853086c65
--- /dev/null
+++ b/variants/feather_m4_can/variant.h
@@ -0,0 +1,266 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _VARIANT_FEATHER_M4_
+#define _VARIANT_FEATHER_M4_
+
+// The definitions here needs a SAMD core >=1.6.10
+#define ARDUINO_SAMD_VARIANT_COMPLIANCE 10610
+
+/*----------------------------------------------------------------------------
+ *        Definitions
+ *----------------------------------------------------------------------------*/
+
+/** Frequency of the board main oscillator */
+#define VARIANT_MAINOSC		(32768ul)
+
+/** Master clock frequency */
+#define VARIANT_MCK        (F_CPU)
+
+#define VARIANT_GCLK0_FREQ (F_CPU)
+#define VARIANT_GCLK1_FREQ (48000000UL)
+#define VARIANT_GCLK2_FREQ (100000000UL)
+
+/*----------------------------------------------------------------------------
+ *        Headers
+ *----------------------------------------------------------------------------*/
+
+#include "WVariant.h"
+
+#ifdef __cplusplus
+#include "SERCOM.h"
+#include "Uart.h"
+#endif // __cplusplus
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif // __cplusplus
+
+/*----------------------------------------------------------------------------
+ *        Pins
+ *----------------------------------------------------------------------------*/
+
+// Number of pins defined in PinDescription array
+#define PINS_COUNT           (44u)
+#define NUM_DIGITAL_PINS     (23u)
+#define NUM_ANALOG_INPUTS    (6u)
+#define NUM_ANALOG_OUTPUTS   (1u)
+#define analogInputToDigitalPin(p)  ((p < 6u) ? (p) + 14u : -1)
+
+#define digitalPinToPort(P)        ( &(PORT->Group[g_APinDescription[P].ulPort]) )
+#define digitalPinToBitMask(P)     ( 1 << g_APinDescription[P].ulPin )
+//#define analogInPinToBit(P)        ( )
+#define portOutputRegister(port)   ( &(port->OUT.reg) )
+#define portInputRegister(port)    ( &(port->IN.reg) )
+#define portModeRegister(port)     ( &(port->DIR.reg) )
+#define digitalPinHasPWM(P)        ( g_APinDescription[P].ulPWMChannel != NOT_ON_PWM || g_APinDescription[P].ulTCChannel != NOT_ON_TIMER )
+
+/*
+ * digitalPinToTimer(..) is AVR-specific and is not defined for SAMD
+ * architecture. If you need to check if a pin supports PWM you must
+ * use digitalPinHasPWM(..).
+ *
+ * https://github.com/arduino/Arduino/issues/1833
+ */
+// #define digitalPinToTimer(P)
+
+// LEDs
+#define PIN_LED_13           (13u)
+#define PIN_LED_RXL          (25u)
+#define PIN_LED_TXL          (26u)
+#define PIN_LED              PIN_LED_13
+#define PIN_LED2             PIN_LED_RXL
+#define PIN_LED3             PIN_LED_TXL
+#define LED_BUILTIN          PIN_LED_13
+#define PIN_NEOPIXEL         (8)
+#define PIN_NEOPIXEL_POWER   (7)
+
+/*
+ * Analog pins
+ */
+#define PIN_A0               (14ul)
+#define PIN_A1               (PIN_A0 + 1)
+#define PIN_A2               (PIN_A0 + 2)
+#define PIN_A3               (PIN_A0 + 3)
+#define PIN_A4               (PIN_A0 + 4)
+#define PIN_A5               (PIN_A0 + 5)
+#define PIN_A6               (PIN_A0 + 6)
+
+#define PIN_DAC0             (14ul)
+#define PIN_DAC1             PIN_A1
+
+static const uint8_t A0  = PIN_A0;
+static const uint8_t A1  = PIN_A1;
+static const uint8_t A2  = PIN_A2;
+static const uint8_t A3  = PIN_A3;
+static const uint8_t A4  = PIN_A4;
+static const uint8_t A5  = PIN_A5;
+static const uint8_t A6  = PIN_A6 ;
+
+static const uint8_t DAC0 = PIN_DAC0;
+static const uint8_t DAC1 = PIN_DAC1;
+
+#define ADC_RESOLUTION		12
+
+// Other pins
+#define PIN_ATN              (31ul)
+static const uint8_t ATN = PIN_ATN;
+
+/*
+ * Serial interfaces
+ */
+
+// Serial1
+#define PIN_SERIAL1_RX       (0ul)
+#define PIN_SERIAL1_TX       (1ul)
+#define PAD_SERIAL1_RX       (SERCOM_RX_PAD_1)
+#define PAD_SERIAL1_TX       (UART_TX_PAD_0)
+
+/*
+ * SPI Interfaces
+ */
+#define SPI_INTERFACES_COUNT 1
+
+#define PIN_SPI_MISO         (23u)
+#define PIN_SPI_MOSI         (24u)
+#define PIN_SPI_SCK          (25u)
+#define PERIPH_SPI           sercom1
+#define PAD_SPI_TX           SPI_PAD_3_SCK_1
+#define PAD_SPI_RX           SERCOM_RX_PAD_2
+
+static const uint8_t SS	  = 9 ;	// SERCOM1 last PAD is present on d9 but HW SS isn't used. Set here only for reference.
+static const uint8_t MOSI = PIN_SPI_MOSI ;
+static const uint8_t MISO = PIN_SPI_MISO ;
+static const uint8_t SCK  = PIN_SPI_SCK ;
+
+/*
+ * Wire Interfaces
+ */
+#define WIRE_INTERFACES_COUNT 1
+
+#define PIN_WIRE_SDA         (21u)
+#define PIN_WIRE_SCL         (22u)
+#define PERIPH_WIRE          sercom2
+#define WIRE_IT_HANDLER      SERCOM2_Handler
+#define WIRE_IT_HANDLER_0    SERCOM2_0_Handler
+#define WIRE_IT_HANDLER_1    SERCOM2_1_Handler
+#define WIRE_IT_HANDLER_2    SERCOM2_2_Handler
+#define WIRE_IT_HANDLER_3    SERCOM2_3_Handler
+
+static const uint8_t SDA = PIN_WIRE_SDA;
+static const uint8_t SCL = PIN_WIRE_SCL;
+
+/*
+ * USB
+ */
+#define PIN_USB_HOST_ENABLE (28ul)
+#define PIN_USB_DM          (29ul)
+#define PIN_USB_DP          (30ul)
+
+/*
+ * I2S Interfaces
+ */
+#define I2S_INTERFACES_COUNT 1
+
+#define I2S_DEVICE          0
+#define I2S_CLOCK_GENERATOR 3
+
+#define PIN_I2S_SDO          (11u)
+#define PIN_I2S_SDI          (12u)
+#define PIN_I2S_SCK          PIN_SERIAL1_TX
+#define PIN_I2S_FS           (10u)
+#define PIN_I2S_MCK          PIN_SERIAL1_RX
+
+// On-board QSPI Flash
+#define EXTERNAL_FLASH_DEVICES   GD25Q16C
+#define EXTERNAL_FLASH_USE_QSPI
+
+//QSPI Pins
+#define PIN_QSPI_SCK    (34u)
+#define PIN_QSPI_CS     (35u)
+#define PIN_QSPI_IO0    (36u)
+#define PIN_QSPI_IO1    (37u)
+#define PIN_QSPI_IO2    (38u)
+#define PIN_QSPI_IO3    (39u)
+
+#if !defined(VARIANT_QSPI_BAUD_DEFAULT)
+  // TODO: meaningful value for this
+  #define VARIANT_QSPI_BAUD_DEFAULT 5000000
+#endif
+
+/*
+ * CAN
+ */
+#define PIN_CAN_STANDBY (40)
+#define PIN_CAN_BOOSTEN (41)
+#define PIN_CAN_TX      (42)
+#define PIN_CAN_RX      (43)
+
+#define PIN_CAN1_TX     (12)
+#define PIN_CAN1_RX     (13)
+
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+ *        Arduino objects - C++ only
+ *----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+
+/*	=========================
+ *	===== SERCOM DEFINITION
+ *	=========================
+*/
+extern SERCOM sercom0;
+extern SERCOM sercom1;
+extern SERCOM sercom2;
+extern SERCOM sercom3;
+extern SERCOM sercom4;
+extern SERCOM sercom5;
+
+extern Uart Serial1;
+
+#endif
+
+// These serial port names are intended to allow libraries and architecture-neutral
+// sketches to automatically default to the correct port name for a particular type
+// of use.  For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN,
+// the first hardware serial port whose RX/TX pins are not dedicated to another use.
+//
+// SERIAL_PORT_MONITOR        Port which normally prints to the Arduino Serial Monitor
+//
+// SERIAL_PORT_USBVIRTUAL     Port which is USB virtual serial
+//
+// SERIAL_PORT_LINUXBRIDGE    Port which connects to a Linux system via Bridge library
+//
+// SERIAL_PORT_HARDWARE       Hardware serial port, physical RX & TX pins.
+//
+// SERIAL_PORT_HARDWARE_OPEN  Hardware serial ports which are open for use.  Their RX & TX
+//                            pins are NOT connected to anything by default.
+#define SERIAL_PORT_USBVIRTUAL      Serial
+#define SERIAL_PORT_MONITOR         Serial
+// Serial has no physical pins broken out, so it's not listed as HARDWARE port
+#define SERIAL_PORT_HARDWARE        Serial1
+#define SERIAL_PORT_HARDWARE_OPEN   Serial1
+
+#endif /* _VARIANT_FEATHER_M4_ */
+
diff --git a/variants/gemma_m0/debug_scripts/variant.gdb b/variants/gemma_m0/debug_scripts/variant.gdb
new file mode 100644
index 000000000..3c37ffde2
--- /dev/null
+++ b/variants/gemma_m0/debug_scripts/variant.gdb
@@ -0,0 +1,31 @@
+#
+#  Arduino Zero OpenOCD script.
+#
+#  Copyright (c) 2014-2015 Arduino LLC. All right reserved.
+#
+#  This library is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 2.1 of the License, or (at your option) any later version.
+#
+#  This library is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#  See the GNU Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library; if not, write to the Free Software
+#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#
+
+# Define 'reset' command
+define reset
+
+info reg
+
+break main
+
+# End of 'reset' command
+end
+
+target remote | openocd -c "interface cmsis-dap" -c "set CHIPNAME at91samd21g18" -f target/at91samdXX.cfg -c "gdb_port pipe; log_output openocd.log"
diff --git a/variants/gemma_m0/linker_scripts/gcc/flash_with_bootloader.ld b/variants/gemma_m0/linker_scripts/gcc/flash_with_bootloader.ld
new file mode 100644
index 000000000..4475f9511
--- /dev/null
+++ b/variants/gemma_m0/linker_scripts/gcc/flash_with_bootloader.ld
@@ -0,0 +1,211 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* Linker script to configure memory regions.
+ * Need modifying for a specific board.
+ *   FLASH.ORIGIN: starting address of flash
+ *   FLASH.LENGTH: length of flash
+ *   RAM.ORIGIN: starting address of RAM bank 0
+ *   RAM.LENGTH: length of RAM bank 0
+ */
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000+0x2000, LENGTH = 0x00040000-0x2000 /* First 8KB used by bootloader */
+  RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ *   Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ *   __exidx_start
+ *   __exidx_end
+ *   __copy_table_start__
+ *   __copy_table_end__
+ *   __zero_table_start__
+ *   __zero_table_end__
+ *   __etext
+ *   __data_start__
+ *   __preinit_array_start
+ *   __preinit_array_end
+ *   __init_array_start
+ *   __init_array_end
+ *   __fini_array_start
+ *   __fini_array_end
+ *   __data_end__
+ *   __bss_start__
+ *   __bss_end__
+ *   __end__
+ *   end
+ *   __HeapLimit
+ *   __StackLimit
+ *   __StackTop
+ *   __stack
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+	.text :
+	{
+		KEEP(*(.isr_vector))
+		*(.text*)
+
+		KEEP(*(.init))
+		KEEP(*(.fini))
+
+		/* .ctors */
+		*crtbegin.o(.ctors)
+		*crtbegin?.o(.ctors)
+		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+		*(SORT(.ctors.*))
+		*(.ctors)
+
+		/* .dtors */
+ 		*crtbegin.o(.dtors)
+ 		*crtbegin?.o(.dtors)
+ 		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ 		*(SORT(.dtors.*))
+ 		*(.dtors)
+
+		*(.rodata*)
+
+		KEEP(*(.eh_frame*))
+	} > FLASH
+
+	.ARM.extab :
+	{
+		*(.ARM.extab* .gnu.linkonce.armextab.*)
+	} > FLASH
+
+	__exidx_start = .;
+	.ARM.exidx :
+	{
+		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
+	} > FLASH
+	__exidx_end = .;
+
+	/* To copy multiple ROM to RAM sections,
+	 * uncomment .copy.table section and,
+	 * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.copy.table :
+	{
+		. = ALIGN(4);
+		__copy_table_start__ = .;
+		LONG (__etext)
+		LONG (__data_start__)
+		LONG (__data_end__ - __data_start__)
+		LONG (__etext2)
+		LONG (__data2_start__)
+		LONG (__data2_end__ - __data2_start__)
+		__copy_table_end__ = .;
+	} > FLASH
+	*/
+
+	/* To clear multiple BSS sections,
+	 * uncomment .zero.table section and,
+	 * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.zero.table :
+	{
+		. = ALIGN(4);
+		__zero_table_start__ = .;
+		LONG (__bss_start__)
+		LONG (__bss_end__ - __bss_start__)
+		LONG (__bss2_start__)
+		LONG (__bss2_end__ - __bss2_start__)
+		__zero_table_end__ = .;
+	} > FLASH
+	*/
+
+	__etext = .;
+
+	.data : AT (__etext)
+	{
+		__data_start__ = .;
+		*(vtable)
+		*(.data*)
+
+		. = ALIGN(4);
+		/* preinit data */
+		PROVIDE_HIDDEN (__preinit_array_start = .);
+		KEEP(*(.preinit_array))
+		PROVIDE_HIDDEN (__preinit_array_end = .);
+
+		. = ALIGN(4);
+		/* init data */
+		PROVIDE_HIDDEN (__init_array_start = .);
+		KEEP(*(SORT(.init_array.*)))
+		KEEP(*(.init_array))
+		PROVIDE_HIDDEN (__init_array_end = .);
+
+
+		. = ALIGN(4);
+		/* finit data */
+		PROVIDE_HIDDEN (__fini_array_start = .);
+		KEEP(*(SORT(.fini_array.*)))
+		KEEP(*(.fini_array))
+		PROVIDE_HIDDEN (__fini_array_end = .);
+
+		KEEP(*(.jcr*))
+		. = ALIGN(4);
+		/* All data end */
+		__data_end__ = .;
+
+	} > RAM
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start__ = .;
+		*(.bss*)
+		*(COMMON)
+		. = ALIGN(4);
+		__bss_end__ = .;
+	} > RAM
+
+	.heap (COPY):
+	{
+		__end__ = .;
+		PROVIDE(end = .);
+		*(.heap*)
+		__HeapLimit = .;
+	} > RAM
+
+	/* .stack_dummy section doesn't contains any symbols. It is only
+	 * used for linker to calculate size of stack sections, and assign
+	 * values to stack symbols later */
+	.stack_dummy (COPY):
+	{
+		*(.stack*)
+	} > RAM
+
+	/* Set stack top to end of RAM, and stack limit move down by
+	 * size of stack_dummy section */
+	__StackTop = ORIGIN(RAM) + LENGTH(RAM);
+	__StackLimit = __StackTop - SIZEOF(.stack_dummy);
+	PROVIDE(__stack = __StackTop);
+
+	__ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ;
+
+	/* Check if data + heap + stack exceeds RAM limit */
+	ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
+}
diff --git a/variants/gemma_m0/linker_scripts/gcc/flash_without_bootloader.ld b/variants/gemma_m0/linker_scripts/gcc/flash_without_bootloader.ld
new file mode 100644
index 000000000..0162f0774
--- /dev/null
+++ b/variants/gemma_m0/linker_scripts/gcc/flash_without_bootloader.ld
@@ -0,0 +1,212 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* Linker script to configure memory regions.
+ * Need modifying for a specific board.
+ *   FLASH.ORIGIN: starting address of flash
+ *   FLASH.LENGTH: length of flash
+ *   RAM.ORIGIN: starting address of RAM bank 0
+ *   RAM.LENGTH: length of RAM bank 0
+ */
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00040000
+  RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ *   Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ *   __exidx_start
+ *   __exidx_end
+ *   __copy_table_start__
+ *   __copy_table_end__
+ *   __zero_table_start__
+ *   __zero_table_end__
+ *   __etext
+ *   __data_start__
+ *   __preinit_array_start
+ *   __preinit_array_end
+ *   __init_array_start
+ *   __init_array_end
+ *   __fini_array_start
+ *   __fini_array_end
+ *   __data_end__
+ *   __bss_start__
+ *   __bss_end__
+ *   __end__
+ *   end
+ *   __HeapLimit
+ *   __StackLimit
+ *   __StackTop
+ *   __stack
+ *   __ram_end__
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+	.text :
+	{
+		KEEP(*(.isr_vector))
+		*(.text*)
+
+		KEEP(*(.init))
+		KEEP(*(.fini))
+
+		/* .ctors */
+		*crtbegin.o(.ctors)
+		*crtbegin?.o(.ctors)
+		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+		*(SORT(.ctors.*))
+		*(.ctors)
+
+		/* .dtors */
+ 		*crtbegin.o(.dtors)
+ 		*crtbegin?.o(.dtors)
+ 		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ 		*(SORT(.dtors.*))
+ 		*(.dtors)
+
+		*(.rodata*)
+
+		KEEP(*(.eh_frame*))
+	} > FLASH
+
+	.ARM.extab :
+	{
+		*(.ARM.extab* .gnu.linkonce.armextab.*)
+	} > FLASH
+
+	__exidx_start = .;
+	.ARM.exidx :
+	{
+		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
+	} > FLASH
+	__exidx_end = .;
+
+	/* To copy multiple ROM to RAM sections,
+	 * uncomment .copy.table section and,
+	 * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.copy.table :
+	{
+		. = ALIGN(4);
+		__copy_table_start__ = .;
+		LONG (__etext)
+		LONG (__data_start__)
+		LONG (__data_end__ - __data_start__)
+		LONG (__etext2)
+		LONG (__data2_start__)
+		LONG (__data2_end__ - __data2_start__)
+		__copy_table_end__ = .;
+	} > FLASH
+	*/
+
+	/* To clear multiple BSS sections,
+	 * uncomment .zero.table section and,
+	 * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.zero.table :
+	{
+		. = ALIGN(4);
+		__zero_table_start__ = .;
+		LONG (__bss_start__)
+		LONG (__bss_end__ - __bss_start__)
+		LONG (__bss2_start__)
+		LONG (__bss2_end__ - __bss2_start__)
+		__zero_table_end__ = .;
+	} > FLASH
+	*/
+
+	__etext = .;
+
+	.data : AT (__etext)
+	{
+		__data_start__ = .;
+		*(vtable)
+		*(.data*)
+
+		. = ALIGN(4);
+		/* preinit data */
+		PROVIDE_HIDDEN (__preinit_array_start = .);
+		KEEP(*(.preinit_array))
+		PROVIDE_HIDDEN (__preinit_array_end = .);
+
+		. = ALIGN(4);
+		/* init data */
+		PROVIDE_HIDDEN (__init_array_start = .);
+		KEEP(*(SORT(.init_array.*)))
+		KEEP(*(.init_array))
+		PROVIDE_HIDDEN (__init_array_end = .);
+
+
+		. = ALIGN(4);
+		/* finit data */
+		PROVIDE_HIDDEN (__fini_array_start = .);
+		KEEP(*(SORT(.fini_array.*)))
+		KEEP(*(.fini_array))
+		PROVIDE_HIDDEN (__fini_array_end = .);
+
+		KEEP(*(.jcr*))
+		. = ALIGN(4);
+		/* All data end */
+		__data_end__ = .;
+
+	} > RAM
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start__ = .;
+		*(.bss*)
+		*(COMMON)
+		. = ALIGN(4);
+		__bss_end__ = .;
+	} > RAM
+
+	.heap (COPY):
+	{
+		__end__ = .;
+		PROVIDE(end = .);
+		*(.heap*)
+		__HeapLimit = .;
+	} > RAM
+
+	/* .stack_dummy section doesn't contains any symbols. It is only
+	 * used for linker to calculate size of stack sections, and assign
+	 * values to stack symbols later */
+	.stack_dummy (COPY):
+	{
+		*(.stack*)
+	} > RAM
+
+	/* Set stack top to end of RAM, and stack limit move down by
+	 * size of stack_dummy section */
+	__StackTop = ORIGIN(RAM) + LENGTH(RAM) ;
+	__StackLimit = __StackTop - SIZEOF(.stack_dummy);
+	PROVIDE(__stack = __StackTop);
+
+	__ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ;
+
+	/* Check if data + heap + stack exceeds RAM limit */
+	ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
+}
diff --git a/variants/gemma_m0/openocd_scripts/gemma_m0.cfg b/variants/gemma_m0/openocd_scripts/gemma_m0.cfg
new file mode 100644
index 000000000..93d782d39
--- /dev/null
+++ b/variants/gemma_m0/openocd_scripts/gemma_m0.cfg
@@ -0,0 +1,28 @@
+#
+#  Adafruit Gemma M0 OpenOCD script.
+#
+#  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+#
+#  This library is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 2.1 of the License, or (at your option) any later version.
+#
+#  This library is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#  See the GNU Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library; if not, write to the Free Software
+#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#
+
+# chip name
+set CHIPNAME at91samd21g18
+set ENDIAN little
+
+# choose a port here
+set telnet_port 0
+
+source [find target/at91samdXX.cfg]
diff --git a/variants/gemma_m0/pins_arduino.h b/variants/gemma_m0/pins_arduino.h
new file mode 100644
index 000000000..db0e40c3d
--- /dev/null
+++ b/variants/gemma_m0/pins_arduino.h
@@ -0,0 +1,21 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+// API compatibility
+#include "variant.h"
+
diff --git a/variants/gemma_m0/variant.cpp b/variants/gemma_m0/variant.cpp
new file mode 100644
index 000000000..c0fa9700e
--- /dev/null
+++ b/variants/gemma_m0/variant.cpp
@@ -0,0 +1,97 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#include "variant.h"
+
+/*
+ * Pins descriptions
+ */
+const PinDescription g_APinDescription[]=
+{
+  // GPIO 0, 1, 2 on external pads
+  // 0 - SERCOM0.0 for I2C SDA, UART TX, SPI MOSI, Captouch, IRQ, PWM out TCC0/WO[0], and gen purpose pin
+  { PORTA,  4, PIO_SERCOM_ALT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM0_CH0, TCC0_CH0, EXTERNAL_INT_4 },  // TCC0/WO[0]
+
+  // 1 - ADC, DAC, IRQ, Captouch and general purpose pin - no timer
+  { PORTA,  2, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel0, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 }, // ADC/AIN[0]
+
+  // 2 - SERCOM0 for I2C SCL, UART RX, SPI CLK, Captouch, IRQ, PWM out TCC0/WO[1], and gen purpose pin
+  { PORTA,  5, PIO_SERCOM_ALT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM0_CH1, TCC0_CH1, EXTERNAL_INT_5 }, // TCC0/WO[1]
+
+  // GPIO 3 & 4 - DotStar internal data/clock
+  // ----------------------------------------
+  { PORTA,  0, PIO_DIGITAL, 0, ADC_Channel4, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_0 }, // ADC/AIN[4]
+  { PORTA,  1, PIO_DIGITAL, 0, ADC_Channel5, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_1 }, // ADC/AIN[5]
+
+  // GPIO 5, 6, 7 (USB interface)
+  // ----------------------------
+  { PORTA, 28, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB Host enable - GPIO #5
+  { PORTA, 24, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB/DM - GPIO #6
+  { PORTA, 25, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB/DP - GPIO #7
+
+  // GPIO 8, 9, 10 - analog inputs which are 'clones' of the analog pins
+  // A0 (D8 same as D1)
+  { PORTA,  2, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel0, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 }, // ADC/AIN[0]
+  // A1 (D9 same as D2)
+  { PORTA,  5, PIO_ANALOG, (PIN_ATTR_ANALOG|PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel5, PWM0_CH1, TCC0_CH1, EXTERNAL_INT_5 }, // TCC0/WO[1]
+  // A2 (D10 same as D0)
+  { PORTA,  4, PIO_ANALOG, (PIN_ATTR_ANALOG|PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel4, PWM0_CH0, TCC0_CH0, EXTERNAL_INT_4 },  // TCC0/WO[0]
+
+  // GPIO 11 & 12 (SWCLK & SWDIO)
+  // --------------------------
+  { PORTA, 30, PIO_TIMER, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+  { PORTA, 31, PIO_TIMER, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+
+  // GPIO 13 (LED)
+  { PORTA, 23, PIO_TIMER, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_7 }, // Digital #13
+
+  // Placeholder #14 & 15 for 'txled'
+  { PORTA, 10, PIO_DIGITAL, (PIN_ATTR_DIGITAL), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_10 },
+  { PORTA, 11, PIO_DIGITAL, (PIN_ATTR_DIGITAL), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_11 },
+
+  // Placeholder #16 - extra Sercom/SPI pin that doesnt actually get used
+  { PORTA,  6, PIO_SERCOM_ALT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM1_CH0, TCC1_CH0, EXTERNAL_INT_6 }, // TCC0/WO[1]
+
+  // For unknown reasons we need to have gpio 17-21 so here are extra pins (shrug)
+  { PORTA, 14, PIO_DIGITAL, (PIN_ATTR_DIGITAL), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_14 },
+  { PORTA, 15, PIO_DIGITAL, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM3_CH1, TC3_CH1, EXTERNAL_INT_15 },
+  { PORTA, 16, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM2_CH0, TCC2_CH0, EXTERNAL_INT_0 }, // TCC2/WO[0]
+  { PORTA, 17, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM2_CH1, TCC2_CH1, EXTERNAL_INT_1 }, // TCC2/WO[1]
+} ;
+
+const void* g_apTCInstances[TCC_INST_NUM+TC_INST_NUM]={ TCC0, TCC1, TCC2, TC3, TC4, TC5 } ;
+
+// Multi-serial objects instantiation
+SERCOM sercom0( SERCOM0 ) ;
+SERCOM sercom1( SERCOM1 ) ;
+SERCOM sercom2( SERCOM2 ) ;
+SERCOM sercom3( SERCOM3 ) ;
+
+Uart Serial1( &sercom0, PIN_SERIAL1_RX, PIN_SERIAL1_TX, PAD_SERIAL1_RX, PAD_SERIAL1_TX ) ;
+
+
+// If wire.h isnt included, just do nothing
+void WIRE_IT_HANDLER(void) __attribute__ ((weak));
+
+void SERCOM0_Handler()
+{
+  Serial1.IrqHandler();
+  WIRE_IT_HANDLER();
+}
+
diff --git a/variants/gemma_m0/variant.h b/variants/gemma_m0/variant.h
new file mode 100644
index 000000000..43bdd68a6
--- /dev/null
+++ b/variants/gemma_m0/variant.h
@@ -0,0 +1,199 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _VARIANT_ARDUINO_ZERO_
+#define _VARIANT_ARDUINO_ZERO_
+
+// The definitions here needs a SAMD core >=1.6.6
+#define ARDUINO_SAMD_VARIANT_COMPLIANCE 10606
+
+/*----------------------------------------------------------------------------
+ *        Definitions
+ *----------------------------------------------------------------------------*/
+
+/** Frequency of the board main oscillator */
+#define VARIANT_MAINOSC		(32768ul)
+
+/** Master clock frequency */
+#define VARIANT_MCK	(F_CPU)
+
+/*----------------------------------------------------------------------------
+ *        Headers
+ *----------------------------------------------------------------------------*/
+
+#include "WVariant.h"
+
+#ifdef __cplusplus
+#include "SERCOM.h"
+#include "Uart.h"
+#endif // __cplusplus
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif // __cplusplus
+
+/*----------------------------------------------------------------------------
+ *        Pins
+ *----------------------------------------------------------------------------*/
+
+// Number of pins defined in PinDescription array
+#define PINS_COUNT           (16u)
+#define NUM_DIGITAL_PINS     (16u)
+#define NUM_ANALOG_INPUTS    (3u)
+#define NUM_ANALOG_OUTPUTS   (1u)
+#define analogInputToDigitalPin(p)  ((p < 3u) ? (p) + PIN_A0 : -1)
+
+#define digitalPinToPort(P)        ( &(PORT->Group[g_APinDescription[P].ulPort]) )
+#define digitalPinToBitMask(P)     ( 1 << g_APinDescription[P].ulPin )
+//#define analogInPinToBit(P)        ( )
+#define portOutputRegister(port)   ( &(port->OUT.reg) )
+#define portInputRegister(port)    ( &(port->IN.reg) )
+#define portModeRegister(port)     ( &(port->DIR.reg) )
+#define digitalPinHasPWM(P)        ( g_APinDescription[P].ulPWMChannel != NOT_ON_PWM || g_APinDescription[P].ulTCChannel != NOT_ON_TIMER )
+
+/*
+ * digitalPinToTimer(..) is AVR-specific and is not defined for SAMD
+ * architecture. If you need to check if a pin supports PWM you must
+ * use digitalPinHasPWM(..).
+ *
+ * https://github.com/arduino/Arduino/issues/1833
+ */
+// #define digitalPinToTimer(P)
+
+// LEDs
+#define PIN_LED_13           (13u)
+#define PIN_LED_RXL          (14u)
+#define PIN_LED_TXL          (15u)
+#define PIN_LED              PIN_LED_13
+#define PIN_LED2             PIN_LED_RXL
+#define PIN_LED3             PIN_LED_TXL
+#define LED_BUILTIN          PIN_LED_13
+// DotStar LED
+#define INTERNAL_DS_DATA     3
+#define INTERNAL_DS_CLK      4
+
+/*
+ * Analog pins
+ */
+#define PIN_A0               (8ul)
+#define PIN_A1               (9ul)
+#define PIN_A2               (10ul)
+#define PIN_DAC0             (8ul)
+
+static const uint8_t A0  = PIN_A0;
+static const uint8_t A1  = PIN_A1;
+static const uint8_t A2  = PIN_A2;
+static const uint8_t DAC0 = PIN_DAC0;
+
+#define ADC_RESOLUTION		12
+
+/*
+ * Serial interfaces
+ */
+
+// Serial1 (sercom 0)
+#define PIN_SERIAL1_RX       (2ul) // PA05
+#define PAD_SERIAL1_RX       (SERCOM_RX_PAD_1)
+#define PIN_SERIAL1_TX       (0ul) // PA04
+#define PAD_SERIAL1_TX       (UART_TX_PAD_0)
+
+/*
+ * SPI Interfaces
+ */
+#define SPI_INTERFACES_COUNT 1 // we'll just have SPI CLK and MOSI on sercom 0, no MISO
+
+#define PIN_SPI_MISO         (6u)  // PA06, not actually available
+#define PIN_SPI_MOSI         (0ul) // PA04
+#define PIN_SPI_SCK          (2ul) // PA05
+#define PERIPH_SPI           sercom0
+#define PAD_SPI_TX           SPI_PAD_0_SCK_1
+#define PAD_SPI_RX         SERCOM_RX_PAD_2
+
+static const uint8_t SS	  = 1 ;	// only pin remaining (shrug)
+static const uint8_t MOSI = PIN_SPI_MOSI ;
+static const uint8_t MISO = PIN_SPI_MISO ;
+static const uint8_t SCK  = PIN_SPI_SCK ;
+
+
+/*
+ * Wire Interfaces
+ */
+#define WIRE_INTERFACES_COUNT 1
+
+#define PIN_WIRE_SDA         (0u)
+#define PIN_WIRE_SCL         (2u)
+#define PERIPH_WIRE          sercom0
+//#define WIRE_IT_HANDLER    // hack! we call the i2c handler from within the serial handler!
+
+static const uint8_t SDA = PIN_WIRE_SDA;
+static const uint8_t SCL = PIN_WIRE_SCL;
+
+/*
+ * USB
+ */
+#define PIN_USB_HOST_ENABLE (5ul)
+#define PIN_USB_DM          (6ul)
+#define PIN_USB_DP          (7ul)
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+ *        Arduino objects - C++ only
+ *----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+
+/*	=========================
+ *	===== SERCOM DEFINITION
+ *	=========================
+*/
+extern SERCOM sercom0;
+extern SERCOM sercom1;
+extern SERCOM sercom2;
+extern SERCOM sercom3;
+
+extern Uart Serial1;
+
+#endif
+
+// These serial port names are intended to allow libraries and architecture-neutral
+// sketches to automatically default to the correct port name for a particular type
+// of use.  For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN,
+// the first hardware serial port whose RX/TX pins are not dedicated to another use.
+//
+// SERIAL_PORT_MONITOR        Port which normally prints to the Arduino Serial Monitor
+//
+// SERIAL_PORT_USBVIRTUAL     Port which is USB virtual serial
+//
+// SERIAL_PORT_LINUXBRIDGE    Port which connects to a Linux system via Bridge library
+//
+// SERIAL_PORT_HARDWARE       Hardware serial port, physical RX & TX pins.
+//
+// SERIAL_PORT_HARDWARE_OPEN  Hardware serial ports which are open for use.  Their RX & TX
+//                            pins are NOT connected to anything by default.
+#define SERIAL_PORT_USBVIRTUAL      Serial
+#define SERIAL_PORT_MONITOR         Serial
+// Serial has no physical pins broken out, so it's not listed as HARDWARE port
+#define SERIAL_PORT_HARDWARE        Serial1
+#define SERIAL_PORT_HARDWARE_OPEN   Serial1
+
+#endif /* _VARIANT_ARDUINO_ZERO_ */
+
diff --git a/variants/grand_central_m4/linker_scripts/gcc/flash_with_bootloader.ld b/variants/grand_central_m4/linker_scripts/gcc/flash_with_bootloader.ld
new file mode 100644
index 000000000..39c2a889a
--- /dev/null
+++ b/variants/grand_central_m4/linker_scripts/gcc/flash_with_bootloader.ld
@@ -0,0 +1,216 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* Linker script to configure memory regions.
+ * Need modifying for a specific board.
+ *   FLASH.ORIGIN: starting address of flash
+ *   FLASH.LENGTH: length of flash
+ *   RAM.ORIGIN: starting address of RAM bank 0
+ *   RAM.LENGTH: length of RAM bank 0
+ */
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000+0x4000, LENGTH = 0x100000-0x4000 /* First 16KB used by bootloader */
+  RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x40000
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ *   Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ *   __exidx_start
+ *   __exidx_end
+ *   __copy_table_start__
+ *   __copy_table_end__
+ *   __zero_table_start__
+ *   __zero_table_end__
+ *   __etext
+ *   __data_start__
+ *   __preinit_array_start
+ *   __preinit_array_end
+ *   __init_array_start
+ *   __init_array_end
+ *   __fini_array_start
+ *   __fini_array_end
+ *   __data_end__
+ *   __bss_start__
+ *   __bss_end__
+ *   __end__
+ *   end
+ *   __HeapLimit
+ *   __StackLimit
+ *   __StackTop
+ *   __stack
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+	.text :
+	{
+		__text_start__ = .;
+
+		KEEP(*(.sketch_boot))
+
+		. = ALIGN(0x4000);
+		KEEP(*(.isr_vector))
+		*(.text*)
+
+		KEEP(*(.init))
+		KEEP(*(.fini))
+
+		/* .ctors */
+		*crtbegin.o(.ctors)
+		*crtbegin?.o(.ctors)
+		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+		*(SORT(.ctors.*))
+		*(.ctors)
+
+		/* .dtors */
+ 		*crtbegin.o(.dtors)
+ 		*crtbegin?.o(.dtors)
+ 		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ 		*(SORT(.dtors.*))
+ 		*(.dtors)
+
+		*(.rodata*)
+
+		KEEP(*(.eh_frame*))
+	} > FLASH
+
+	.ARM.extab :
+	{
+		*(.ARM.extab* .gnu.linkonce.armextab.*)
+	} > FLASH
+
+	__exidx_start = .;
+	.ARM.exidx :
+	{
+		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
+	} > FLASH
+	__exidx_end = .;
+
+	/* To copy multiple ROM to RAM sections,
+	 * uncomment .copy.table section and,
+	 * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.copy.table :
+	{
+		. = ALIGN(4);
+		__copy_table_start__ = .;
+		LONG (__etext)
+		LONG (__data_start__)
+		LONG (__data_end__ - __data_start__)
+		LONG (__etext2)
+		LONG (__data2_start__)
+		LONG (__data2_end__ - __data2_start__)
+		__copy_table_end__ = .;
+	} > FLASH
+	*/
+
+	/* To clear multiple BSS sections,
+	 * uncomment .zero.table section and,
+	 * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.zero.table :
+	{
+		. = ALIGN(4);
+		__zero_table_start__ = .;
+		LONG (__bss_start__)
+		LONG (__bss_end__ - __bss_start__)
+		LONG (__bss2_start__)
+		LONG (__bss2_end__ - __bss2_start__)
+		__zero_table_end__ = .;
+	} > FLASH
+	*/
+
+	__etext = .;
+
+	.data : AT (__etext)
+	{
+		__data_start__ = .;
+		*(vtable)
+		*(.data*)
+
+		. = ALIGN(4);
+		/* preinit data */
+		PROVIDE_HIDDEN (__preinit_array_start = .);
+		KEEP(*(.preinit_array))
+		PROVIDE_HIDDEN (__preinit_array_end = .);
+
+		. = ALIGN(4);
+		/* init data */
+		PROVIDE_HIDDEN (__init_array_start = .);
+		KEEP(*(SORT(.init_array.*)))
+		KEEP(*(.init_array))
+		PROVIDE_HIDDEN (__init_array_end = .);
+
+
+		. = ALIGN(4);
+		/* finit data */
+		PROVIDE_HIDDEN (__fini_array_start = .);
+		KEEP(*(SORT(.fini_array.*)))
+		KEEP(*(.fini_array))
+		PROVIDE_HIDDEN (__fini_array_end = .);
+
+		KEEP(*(.jcr*))
+		. = ALIGN(16);
+		/* All data end */
+		__data_end__ = .;
+
+	} > RAM
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start__ = .;
+		*(.bss*)
+		*(COMMON)
+		. = ALIGN(4);
+		__bss_end__ = .;
+	} > RAM
+
+	.heap (COPY):
+	{
+		__end__ = .;
+		PROVIDE(end = .);
+		*(.heap*)
+		__HeapLimit = .;
+	} > RAM
+
+	/* .stack_dummy section doesn't contains any symbols. It is only
+	 * used for linker to calculate size of stack sections, and assign
+	 * values to stack symbols later */
+	.stack_dummy (COPY):
+	{
+		*(.stack*)
+	} > RAM
+
+	/* Set stack top to end of RAM, and stack limit move down by
+	 * size of stack_dummy section */
+	__StackTop = ORIGIN(RAM) + LENGTH(RAM);
+	__StackLimit = __StackTop - SIZEOF(.stack_dummy);
+	PROVIDE(__stack = __StackTop);
+
+	__ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ;
+
+	/* Check if data + heap + stack exceeds RAM limit */
+	ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
+}
diff --git a/variants/grand_central_m4/linker_scripts/gcc/flash_without_bootloader.ld b/variants/grand_central_m4/linker_scripts/gcc/flash_without_bootloader.ld
new file mode 100644
index 000000000..ec0416a03
--- /dev/null
+++ b/variants/grand_central_m4/linker_scripts/gcc/flash_without_bootloader.ld
@@ -0,0 +1,215 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* Linker script to configure memory regions.
+ * Need modifying for a specific board.
+ *   FLASH.ORIGIN: starting address of flash
+ *   FLASH.LENGTH: length of flash
+ *   RAM.ORIGIN: starting address of RAM bank 0
+ *   RAM.LENGTH: length of RAM bank 0
+ */
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x100000
+  RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x40000
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ *   Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ *   __exidx_start
+ *   __exidx_end
+ *   __copy_table_start__
+ *   __copy_table_end__
+ *   __zero_table_start__
+ *   __zero_table_end__
+ *   __etext
+ *   __data_start__
+ *   __preinit_array_start
+ *   __preinit_array_end
+ *   __init_array_start
+ *   __init_array_end
+ *   __fini_array_start
+ *   __fini_array_end
+ *   __data_end__
+ *   __bss_start__
+ *   __bss_end__
+ *   __end__
+ *   end
+ *   __HeapLimit
+ *   __StackLimit
+ *   __StackTop
+ *   __stack
+ *   __ram_end__
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+	.text :
+	{
+		__text_start__ = .;
+
+		. = ALIGN(4);
+		KEEP(*(.isr_vector))
+		*(.text*)
+
+		KEEP(*(.init))
+		KEEP(*(.fini))
+
+		/* .ctors */
+		*crtbegin.o(.ctors)
+		*crtbegin?.o(.ctors)
+		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+		*(SORT(.ctors.*))
+		*(.ctors)
+
+		/* .dtors */
+ 		*crtbegin.o(.dtors)
+ 		*crtbegin?.o(.dtors)
+ 		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ 		*(SORT(.dtors.*))
+ 		*(.dtors)
+
+		*(.rodata*)
+
+		KEEP(*(.eh_frame*))
+	} > FLASH
+
+	.ARM.extab :
+	{
+		*(.ARM.extab* .gnu.linkonce.armextab.*)
+	} > FLASH
+
+	__exidx_start = .;
+	.ARM.exidx :
+	{
+		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
+	} > FLASH
+	__exidx_end = .;
+
+	/* To copy multiple ROM to RAM sections,
+	 * uncomment .copy.table section and,
+	 * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.copy.table :
+	{
+		. = ALIGN(4);
+		__copy_table_start__ = .;
+		LONG (__etext)
+		LONG (__data_start__)
+		LONG (__data_end__ - __data_start__)
+		LONG (__etext2)
+		LONG (__data2_start__)
+		LONG (__data2_end__ - __data2_start__)
+		__copy_table_end__ = .;
+	} > FLASH
+	*/
+
+	/* To clear multiple BSS sections,
+	 * uncomment .zero.table section and,
+	 * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.zero.table :
+	{
+		. = ALIGN(4);
+		__zero_table_start__ = .;
+		LONG (__bss_start__)
+		LONG (__bss_end__ - __bss_start__)
+		LONG (__bss2_start__)
+		LONG (__bss2_end__ - __bss2_start__)
+		__zero_table_end__ = .;
+	} > FLASH
+	*/
+
+	__etext = .;
+
+	.data : AT (__etext)
+	{
+		__data_start__ = .;
+		*(vtable)
+		*(.data*)
+
+		. = ALIGN(4);
+		/* preinit data */
+		PROVIDE_HIDDEN (__preinit_array_start = .);
+		KEEP(*(.preinit_array))
+		PROVIDE_HIDDEN (__preinit_array_end = .);
+
+		. = ALIGN(4);
+		/* init data */
+		PROVIDE_HIDDEN (__init_array_start = .);
+		KEEP(*(SORT(.init_array.*)))
+		KEEP(*(.init_array))
+		PROVIDE_HIDDEN (__init_array_end = .);
+
+
+		. = ALIGN(4);
+		/* finit data */
+		PROVIDE_HIDDEN (__fini_array_start = .);
+		KEEP(*(SORT(.fini_array.*)))
+		KEEP(*(.fini_array))
+		PROVIDE_HIDDEN (__fini_array_end = .);
+
+		KEEP(*(.jcr*))
+		. = ALIGN(16);
+		/* All data end */
+		__data_end__ = .;
+
+	} > RAM
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start__ = .;
+		*(.bss*)
+		*(COMMON)
+		. = ALIGN(4);
+		__bss_end__ = .;
+	} > RAM
+
+	.heap (COPY):
+	{
+		__end__ = .;
+		PROVIDE(end = .);
+		*(.heap*)
+		__HeapLimit = .;
+	} > RAM
+
+	/* .stack_dummy section doesn't contains any symbols. It is only
+	 * used for linker to calculate size of stack sections, and assign
+	 * values to stack symbols later */
+	.stack_dummy (COPY):
+	{
+		*(.stack*)
+	} > RAM
+
+	/* Set stack top to end of RAM, and stack limit move down by
+	 * size of stack_dummy section */
+	__StackTop = ORIGIN(RAM) + LENGTH(RAM) ;
+	__StackLimit = __StackTop - SIZEOF(.stack_dummy);
+	PROVIDE(__stack = __StackTop);
+
+	__ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ;
+
+	/* Check if data + heap + stack exceeds RAM limit */
+	ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
+}
diff --git a/variants/grand_central_m4/pins_arduino.h b/variants/grand_central_m4/pins_arduino.h
new file mode 100644
index 000000000..0595fda01
--- /dev/null
+++ b/variants/grand_central_m4/pins_arduino.h
@@ -0,0 +1,21 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+// API compatibility
+#include "../grand_central_m4/variant.h"
+
diff --git a/variants/grand_central_m4/variant.cpp b/variants/grand_central_m4/variant.cpp
new file mode 100644
index 000000000..78aa1495d
--- /dev/null
+++ b/variants/grand_central_m4/variant.cpp
@@ -0,0 +1,219 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "variant.h"
+
+/*
+ * Pins descriptions
+ * TCC0 IOSET4
+ * TCC1 IOSET2
+ * TCC2 IOSET1
+ * TCC3 IOSET1
+ * TCC4 IOSET1
+ */
+const PinDescription g_APinDescription[]=
+{
+  // 0..13 - Digital pins
+  // ----------------------
+  // 0/1 - SERCOM/UART (Serial1)
+  { PORTB, 25, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_9 },  // RX: SERCOMX/PAD[1]
+  { PORTB, 24, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_8 },  // TX: SERCOMX/PAD[0]
+
+  // 2..12
+  // Digital Low
+  { PORTC, 18, PIO_DIGITAL, PIN_ATTR_PWM_F, No_ADC_Channel, TCC0_CH2, NOT_ON_TIMER, EXTERNAL_INT_2 },
+  { PORTC, 19, PIO_DIGITAL, PIN_ATTR_PWM_F, No_ADC_Channel, TCC0_CH3, NOT_ON_TIMER, EXTERNAL_INT_3 },
+  { PORTC, 20, PIO_DIGITAL, PIN_ATTR_PWM_F, No_ADC_Channel, TCC0_CH4, NOT_ON_TIMER, EXTERNAL_INT_4 },
+  { PORTC, 21, PIO_DIGITAL, PIN_ATTR_PWM_F, No_ADC_Channel, TCC0_CH5, NOT_ON_TIMER, EXTERNAL_INT_5 },
+  { PORTD, 20, PIO_DIGITAL, PIN_ATTR_PWM_F, No_ADC_Channel, TCC1_CH0, NOT_ON_TIMER, EXTERNAL_INT_10 },
+  { PORTD, 21, PIO_DIGITAL, PIN_ATTR_PWM_F, No_ADC_Channel, TCC1_CH1, NOT_ON_TIMER, EXTERNAL_INT_11 },
+
+  // Digital High
+  { PORTB, 18, PIO_DIGITAL, PIN_ATTR_PWM_F, No_ADC_Channel, TCC1_CH0, NOT_ON_TIMER, EXTERNAL_INT_2 },
+  { PORTB, 2, PIO_DIGITAL, PIN_ATTR_PWM_E, No_ADC_Channel, TC6_CH0, TC6_CH0, EXTERNAL_INT_3 },
+  { PORTB, 22, PIO_DIGITAL, PIN_ATTR_PWM_E, No_ADC_Channel, TC7_CH0, TC7_CH0, EXTERNAL_INT_6 },
+  { PORTB, 23, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_7 },
+  { PORTB, 0, PIO_DIGITAL, PIN_ATTR_PWM_E, No_ADC_Channel, TC7_CH0, TC7_CH0, EXTERNAL_INT_0 },
+
+  // 13 (LED)
+  { PORTB, 1, PIO_DIGITAL, PIN_ATTR_PWM_E, No_ADC_Channel, TC7_CH1, TC7_CH1, EXTERNAL_INT_1 },
+
+  // 14..21 - UARTS
+  { PORTB, 16, PIO_SERCOM, PIN_ATTR_PWM_E, No_ADC_Channel, TC6_CH0, TC6_CH0, EXTERNAL_INT_0 },            // UART3_TX
+  { PORTB, 17, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_1 },  // UART3_RX
+  { PORTC, 22, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_6 },  // UART2_TX
+  { PORTC, 23, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_6 },  // UART2_RX
+  { PORTB, 12, PIO_SERCOM, PIN_ATTR_PWM_F, No_ADC_Channel, TCC3_CH0, NOT_ON_TIMER, EXTERNAL_INT_12 },     // UART1_TX
+  { PORTB, 13, PIO_SERCOM, PIN_ATTR_PWM_F, No_ADC_Channel, TCC3_CH1, NOT_ON_TIMER, EXTERNAL_INT_13 },     // UART1_RX
+  { PORTB, 20, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_4 },  //same as SDA
+  { PORTB, 21, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_5 },  //same as SCL
+
+  // 22..53 - Extra Digital Pins
+  // ----------------------
+  // 22..29
+  { PORTD, 12, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_7 },
+  { PORTA, 15, PIO_DIGITAL, PIN_ATTR_PWM_F, No_ADC_Channel, TCC2_CH1, NOT_ON_TIMER, EXTERNAL_INT_15 },
+  { PORTC, 17, PIO_SERCOM, PIN_ATTR_PWM_F, No_ADC_Channel, TCC0_CH1, NOT_ON_TIMER, EXTERNAL_INT_1 },      // SCL_1
+  { PORTC, 16, PIO_SERCOM, PIN_ATTR_PWM_F, No_ADC_Channel, TCC0_CH0, NOT_ON_TIMER, EXTERNAL_INT_0 },      // SDA_1
+  { PORTA, 12, PIO_DIGITAL, PIN_ATTR_PWM_E, No_ADC_Channel, TC2_CH0, TC2_CH0, EXTERNAL_INT_12 },          // DEN1
+  { PORTA, 13, PIO_DIGITAL, PIN_ATTR_PWM_E, No_ADC_Channel, TC2_CH1, TC2_CH1, EXTERNAL_INT_13 },          // DEN2
+  { PORTA, 14, PIO_DIGITAL, PIN_ATTR_PWM_F, No_ADC_Channel, TCC2_CH0, NOT_ON_TIMER, EXTERNAL_INT_14 },    // CLK
+  { PORTB, 19, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_3 }, // XCLK
+
+  // 30..37
+  { PORTA, 23, PIO_DIGITAL, PIN_ATTR_PWM_E, No_ADC_Channel, TC4_CH1, TC4_CH1, EXTERNAL_INT_7 },
+  { PORTA, 22, PIO_DIGITAL, PIN_ATTR_PWM_E, No_ADC_Channel, TC4_CH0, TC4_CH0, EXTERNAL_INT_6 },
+  { PORTA, 21, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_5 },
+  { PORTA, 20, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_4 },
+  { PORTA, 19, PIO_DIGITAL, PIN_ATTR_PWM_E, No_ADC_Channel, TC3_CH1, TC3_CH1, EXTERNAL_INT_3 },
+  { PORTA, 18, PIO_DIGITAL, PIN_ATTR_PWM_E, No_ADC_Channel, TC3_CH0, TC3_CH0, EXTERNAL_INT_2 },
+  { PORTA, 17, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_1 },
+  { PORTA, 16, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_0 },
+
+  // 38..45
+  { PORTB, 15, PIO_DIGITAL, PIN_ATTR_PWM_F, No_ADC_Channel, TCC4_CH1, NOT_ON_TIMER, EXTERNAL_INT_15 },
+  { PORTB, 14, PIO_DIGITAL, PIN_ATTR_PWM_F, No_ADC_Channel, TCC4_CH0, NOT_ON_TIMER, EXTERNAL_INT_14 },
+  { PORTC, 13, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_13 },
+  { PORTC, 12, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_12 },
+  { PORTC, 15, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_15 },
+  { PORTC, 14, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_14 },
+  { PORTC, 11, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_11 },
+  { PORTC, 10, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_10 },
+
+  // 46..53
+  { PORTC, 6, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_6 },
+  { PORTC, 7, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_5 },
+  { PORTC, 4, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_4 },
+  { PORTC, 5, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_5 },
+  { PORTD, 11, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_11 },  //same as MISO
+  { PORTD, 8, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_8 },    //same as MOSI
+  { PORTD, 9, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_9 },    //same as SCK
+  { PORTD, 10, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_10 },  //same as SS
+
+  // 54..61 - Additional ADC
+  { PORTB, 5, PIO_ANALOG, PIN_ATTR_ANALOG_ALT, ADC_Channel7, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_5 },
+  { PORTB, 6, PIO_ANALOG, PIN_ATTR_ANALOG_ALT, ADC_Channel8, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_6 },
+  { PORTB, 7, PIO_ANALOG, PIN_ATTR_ANALOG_ALT, ADC_Channel9, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_7 },
+  { PORTB, 8, PIO_ANALOG, PIN_ATTR_ANALOG_ALT, ADC_Channel0, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_8 },
+  { PORTB, 9, PIO_ANALOG, PIN_ATTR_ANALOG_ALT, ADC_Channel1, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_9 },
+  { PORTA, 4, PIO_ANALOG, (PIN_ATTR_ANALOG|PIN_ATTR_PWM_E), ADC_Channel4, TC0_CH0, TC0_CH0, EXTERNAL_INT_4 },
+  { PORTA, 6, PIO_ANALOG, (PIN_ATTR_ANALOG|PIN_ATTR_PWM_E), ADC_Channel6, TC1_CH0, NOT_ON_TIMER, EXTERNAL_INT_6 },
+  { PORTA, 7, PIO_ANALOG, (PIN_ATTR_ANALOG|PIN_ATTR_PWM_E), ADC_Channel7, TC1_CH1, NOT_ON_TIMER, EXTERNAL_INT_7 },
+
+  // 62..63 - I2C pins (SDA/SCL)
+  // ----------------------
+  { PORTB, 20, PIO_SERCOM, PIN_ATTR_PWM_F, No_ADC_Channel, TCC1_CH2, NOT_ON_TIMER, EXTERNAL_INT_4 },  // SDA
+  { PORTB, 21, PIO_SERCOM, PIN_ATTR_PWM_F, No_ADC_Channel, TCC1_CH3, NOT_ON_TIMER, EXTERNAL_INT_5 },  // SCL
+
+  // 64..66 - SPI pins (ICSP:MISO,SCK,MOSI)
+  // ----------------------
+  { PORTD, 11, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_6 },  // MISO
+  { PORTD, 8, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_3 },   // MOSI
+  { PORTD, 9, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_4 },   // SCK
+
+  // 67..74 - Analog pins
+  // --------------------
+  { PORTA, 2, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel0, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 },
+  { PORTA, 5, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel5, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_5 },
+  { PORTB, 3, PIO_ANALOG, (PIN_ATTR_ANALOG|PIN_ATTR_PWM_E), ADC_Channel15, TC6_CH1, TC6_CH1, EXTERNAL_INT_3 },
+  { PORTC, 0, PIO_ANALOG, PIN_ATTR_ANALOG_ALT, ADC_Channel10, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_0 },
+  { PORTC, 1, PIO_ANALOG, PIN_ATTR_ANALOG_ALT, ADC_Channel11, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_1 },
+  { PORTC, 2, PIO_ANALOG, PIN_ATTR_ANALOG_ALT, ADC_Channel4, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 },
+  { PORTC, 3, PIO_ANALOG, PIN_ATTR_ANALOG_ALT, ADC_Channel5, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_3 },
+  { PORTB, 4, PIO_ANALOG, PIN_ATTR_ANALOG_ALT, ADC_Channel6, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_4 },
+
+  // 75..76 - RX/TX LEDS
+  // --------------------
+  { PORTC, 31, PIO_OUTPUT, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },   // used as output only
+  { PORTC, 30, PIO_OUTPUT, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },   // used as output only
+
+  // 77..79 - USB
+  // --------------------
+  { PORTA, 27, PIO_COM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },  // USB Host enable
+  { PORTA, 24, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_8 },        // USB/DM
+  { PORTA, 25, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_9 },        // USB/DP
+
+  // 80..83 - SD SPI pins (SD:MISO,SCK,MOSI,CS)
+  // ----------------------
+  { PORTB, 29, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+  { PORTB, 27, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+  { PORTB, 26, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+  { PORTB, 28, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+
+  // 84 (AREF)
+  { PORTA, 3, PIO_ANALOG, PIN_ATTR_ANALOG, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_3 },  // DAC/VREFP
+
+  // ----------------------
+  // 85..86 - Alternate use of A0 and A1 (DAC output)
+  { PORTA,  2, PIO_ANALOG, PIN_ATTR_ANALOG, DAC_Channel0, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 },   // DAC/VOUT[0]
+  { PORTA,  5, PIO_ANALOG, PIN_ATTR_ANALOG, DAC_Channel1, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_5 },   // DAC/VOUT[1]
+
+  // 87 - LED #13 duplicate placeholder
+  { PORTB,  1, PIO_DIGITAL, PIN_ATTR_PWM_E, No_ADC_Channel, TC7_CH1, TC7_CH1,  EXTERNAL_INT_1 },
+
+  // 88 - Internal NeoPixel
+  { PORTC,  24, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER,  EXTERNAL_INT_NONE },  // used as output only
+
+  // ----------------------
+  // 89 - 94 QSPI (SCK, CS, IO0, IO1, IO2, IO3)
+  { PORTB, 10, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_10 },
+  { PORTB, 11, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_11 },
+  { PORTA, 8, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NMI },
+  { PORTA, 9, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_9 },
+  { PORTA, 10, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_10 },
+  { PORTA, 11, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_11 },
+
+  // ----------------------
+  // 95 SD detect
+  { PORTB, 31, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_15 },
+  // 96 SWO (on debug header)
+  { PORTB, 30, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_14 },
+} ;
+
+const void* g_apTCInstances[TCC_INST_NUM+TC_INST_NUM]={ TCC0, TCC1, TCC2, TCC3, TCC4, TC0, TC1, TC2, TC3, TC4, TC5, TC6, TC7 } ;
+const uint32_t GCLK_CLKCTRL_IDs[TCC_INST_NUM+TC_INST_NUM] = { TCC0_GCLK_ID, TCC1_GCLK_ID, TCC2_GCLK_ID, TCC3_GCLK_ID, TCC4_GCLK_ID, TC0_GCLK_ID, TC1_GCLK_ID, TC2_GCLK_ID, TC3_GCLK_ID, TC4_GCLK_ID, TC5_GCLK_ID, TC6_GCLK_ID, TC7_GCLK_ID } ;
+
+
+// Multi-serial objects instantiation
+SERCOM sercom0( SERCOM0 ) ;
+SERCOM sercom1( SERCOM1 ) ;
+SERCOM sercom2( SERCOM2 ) ;
+SERCOM sercom3( SERCOM3 ) ;
+SERCOM sercom4( SERCOM4 ) ;
+SERCOM sercom5( SERCOM5 ) ;
+SERCOM sercom6( SERCOM6 ) ;
+SERCOM sercom7( SERCOM7 ) ;
+
+Uart Serial1( &sercom0, PIN_SERIAL1_RX, PIN_SERIAL1_TX, PAD_SERIAL1_RX, PAD_SERIAL1_TX ) ;
+
+void SERCOM0_0_Handler()
+{
+  Serial1.IrqHandler();
+}
+void SERCOM0_1_Handler()
+{
+  Serial1.IrqHandler();
+}
+void SERCOM0_2_Handler()
+{
+  Serial1.IrqHandler();
+}
+void SERCOM0_3_Handler()
+{
+  Serial1.IrqHandler();
+}
diff --git a/variants/grand_central_m4/variant.h b/variants/grand_central_m4/variant.h
new file mode 100644
index 000000000..3092191b1
--- /dev/null
+++ b/variants/grand_central_m4/variant.h
@@ -0,0 +1,346 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _VARIANT_GRAND_CENTRAL_M4_
+#define _VARIANT_GRAND_CENTRAL_M4_
+
+// The definitions here needs a SAMD core >=1.6.10
+#define ARDUINO_SAMD_VARIANT_COMPLIANCE 10610
+
+/*----------------------------------------------------------------------------
+ *        Definitions
+ *----------------------------------------------------------------------------*/
+
+/** Frequency of the board main oscillator */
+#define VARIANT_MAINOSC		(32768ul)
+
+/** Master clock frequency */
+#define VARIANT_MCK        (F_CPU)
+
+#define VARIANT_GCLK0_FREQ (F_CPU)
+#define VARIANT_GCLK1_FREQ (48000000UL)
+#define VARIANT_GCLK2_FREQ (100000000UL)
+
+/*----------------------------------------------------------------------------
+ *        Headers
+ *----------------------------------------------------------------------------*/
+
+#include "WVariant.h"
+
+#ifdef __cplusplus
+#include "SERCOM.h"
+#include "Uart.h"
+#endif // __cplusplus
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif // __cplusplus
+
+/*----------------------------------------------------------------------------
+ *        Pins
+ *----------------------------------------------------------------------------*/
+
+// Number of pins defined in PinDescription array
+#define PINS_COUNT           (96)
+#define NUM_DIGITAL_PINS     (53)
+#define NUM_ANALOG_INPUTS    (19)
+#define NUM_ANALOG_OUTPUTS   (2)
+#define analogInputToDigitalPin(p) ((p < 8) ? 67 + (p) : (p < 16) ? 54 + (p) - 8 : (p < 18) ? 12 + (p) - 16 : (p == 18) ? 9 : -1)
+
+#define digitalPinToPort(P)        ( &(PORT->Group[g_APinDescription[P].ulPort]) )
+#define digitalPinToBitMask(P)     ( 1 << g_APinDescription[P].ulPin )
+//#define analogInPinToBit(P)        ( )
+#define portOutputRegister(port)   ( &(port->OUT.reg) )
+#define portInputRegister(port)    ( &(port->IN.reg) )
+#define portModeRegister(port)     ( &(port->DIR.reg) )
+#define digitalPinHasPWM(P)        ( g_APinDescription[P].ulPWMChannel != NOT_ON_PWM || g_APinDescription[P].ulTCChannel != NOT_ON_TIMER )
+
+/*
+ * digitalPinToTimer(..) is AVR-specific and is not defined for SAMD
+ * architecture. If you need to check if a pin supports PWM you must
+ * use digitalPinHasPWM(..).
+ *
+ * https://github.com/arduino/Arduino/issues/1833
+ */
+// #define digitalPinToTimer(P)
+
+// LEDs
+#define PIN_LED_13          (13)
+#define PIN_LED_RXL         (75)
+#define PIN_LED_TXL         (76)
+#define PIN_LED             PIN_LED_13
+#define PIN_LED2            PIN_LED_RXL
+#define PIN_LED3            PIN_LED_TXL
+#define LED_BUILTIN         PIN_LED_13
+#define PIN_NEOPIXEL		    (88)
+
+/*
+ * Analog pins
+ */
+#define PIN_A0              (67)
+#define PIN_A1              (PIN_A0 + 1)
+#define PIN_A2              (PIN_A0 + 2)
+#define PIN_A3              (PIN_A0 + 3)
+#define PIN_A4              (PIN_A0 + 4)
+#define PIN_A5              (PIN_A0 + 5)
+#define PIN_A6              (PIN_A0 + 6)
+#define PIN_A7              (PIN_A0 + 7)
+
+#define PIN_A8              (54)
+#define PIN_A9              (PIN_A8 + 1)
+#define PIN_A10             (PIN_A8 + 2)
+#define PIN_A11             (PIN_A8 + 3)
+#define PIN_A12             (PIN_A8 + 4)
+#define PIN_A13             (PIN_A8 + 5)
+#define PIN_A14             (PIN_A8 + 6)
+#define PIN_A15             (PIN_A8 + 7)
+
+#define PIN_DAC0            PIN_A0
+#define PIN_DAC1            PIN_A1
+
+static const uint8_t A0   = PIN_A0;
+static const uint8_t A1   = PIN_A1;
+static const uint8_t A2   = PIN_A2;
+static const uint8_t A3   = PIN_A3;
+static const uint8_t A4   = PIN_A4;
+static const uint8_t A5   = PIN_A5;
+static const uint8_t A6   = PIN_A6;
+static const uint8_t A7   = PIN_A7;
+
+static const uint8_t A8   = PIN_A8;
+static const uint8_t A9   = PIN_A9;
+static const uint8_t A10  = PIN_A10;
+static const uint8_t A11  = PIN_A11;
+static const uint8_t A12  = PIN_A12;
+static const uint8_t A13  = PIN_A13;
+static const uint8_t A14  = PIN_A14;
+static const uint8_t A15  = PIN_A15;
+
+static const uint8_t DAC0 = PIN_DAC0;
+static const uint8_t DAC1 = PIN_DAC1;
+
+#define ADC_RESOLUTION		  12
+
+// Other pins
+#define PIN_ATN             (39)
+static const uint8_t ATN = PIN_ATN;
+
+/*
+ * Serial interfaces
+ */
+
+// Serial1
+#define PIN_SERIAL1_RX      (0)
+#define PIN_SERIAL1_TX      (1)
+#define PAD_SERIAL1_TX      (UART_TX_PAD_0)
+#define PAD_SERIAL1_RX      (SERCOM_RX_PAD_1)
+
+// Serial2
+#define PIN_SERIAL2_RX      (19)
+#define PIN_SERIAL2_TX      (18)
+#define PAD_SERIAL2_TX      (UART_TX_PAD_0)
+#define PAD_SERIAL2_RX      (SERCOM_RX_PAD_1)
+#define SERCOM_SERIAL2		  sercom4
+
+// Serial3
+#define PIN_SERIAL3_RX      (17)
+#define PIN_SERIAL3_TX      (16)
+#define PAD_SERIAL3_TX      (UART_TX_PAD_0)
+#define PAD_SERIAL3_RX      (SERCOM_RX_PAD_1)
+#define SERCOM_SERIAL3		  sercom1
+
+// Serial4
+#define PIN_SERIAL4_RX      (15)
+#define PIN_SERIAL4_TX      (14)
+#define PAD_SERIAL4_TX      (UART_TX_PAD_0)
+#define PAD_SERIAL4_RX      (SERCOM_RX_PAD_1)
+#define SERCOM_SERIAL4		  sercom5
+/*
+ * SPI Interfaces
+ */
+#define SPI_INTERFACES_COUNT 2
+
+#define PIN_SPI_MISO        (64)
+#define PIN_SPI_MOSI        (66)
+#define PIN_SPI_SCK         (65)
+#define PERIPH_SPI          sercom7
+#define PAD_SPI_TX          SPI_PAD_0_SCK_1
+#define PAD_SPI_RX          SERCOM_RX_PAD_3
+
+static const uint8_t SS	  = (53);
+static const uint8_t MOSI = PIN_SPI_MOSI;
+static const uint8_t MISO = PIN_SPI_MISO;
+static const uint8_t SCK  = PIN_SPI_SCK;
+
+#define PIN_SPI1_MISO       (80)
+#define PIN_SPI1_MOSI       (82)
+#define PIN_SPI1_SCK        (81)
+#define PIN_SPI1_SS         (83)
+#define PERIPH_SPI1         sercom2
+#define PAD_SPI1_TX         SPI_PAD_0_SCK_1
+#define PAD_SPI1_RX         SERCOM_RX_PAD_3
+
+static const uint8_t SS1	 = PIN_SPI1_SS;
+static const uint8_t MOSI1 = PIN_SPI1_MOSI;
+static const uint8_t MISO1 = PIN_SPI1_MISO;
+static const uint8_t SCK1  = PIN_SPI1_SCK;
+
+// Needed for SD library
+#define SDCARD_SPI          SPI1
+#define SDCARD_MISO_PIN     PIN_SPI1_MISO
+#define SDCARD_MOSI_PIN     PIN_SPI1_MOSI
+#define SDCARD_SCK_PIN      PIN_SPI1_SCK
+#define SDCARD_SS_PIN       PIN_SPI1_SS
+
+/*
+ * Wire Interfaces
+ */
+#define WIRE_INTERFACES_COUNT 2
+
+#define PIN_WIRE_SDA        (62)
+#define PIN_WIRE_SCL        (63)
+#define PERIPH_WIRE         sercom3
+#define WIRE_IT_HANDLER     SERCOM3_Handler
+#define WIRE_IT_HANDLER_0   SERCOM3_0_Handler
+#define WIRE_IT_HANDLER_1   SERCOM3_1_Handler
+#define WIRE_IT_HANDLER_2   SERCOM3_2_Handler
+#define WIRE_IT_HANDLER_3   SERCOM3_3_Handler
+
+static const uint8_t SDA = PIN_WIRE_SDA;
+static const uint8_t SCL = PIN_WIRE_SCL;
+
+#define PIN_WIRE1_SDA       (25)
+#define PIN_WIRE1_SCL       (24)
+#define PERIPH_WIRE1        sercom6
+#define WIRE1_IT_HANDLER    SERCOM6_Handler
+#define WIRE1_IT_HANDLER_0  SERCOM6_0_Handler
+#define WIRE1_IT_HANDLER_1  SERCOM6_1_Handler
+#define WIRE1_IT_HANDLER_2  SERCOM6_2_Handler
+#define WIRE1_IT_HANDLER_3  SERCOM6_3_Handler
+
+static const uint8_t SDA1 = PIN_WIRE1_SDA;
+static const uint8_t SCL1 = PIN_WIRE1_SCL;
+
+/*
+ * USB
+ */
+#define PIN_USB_HOST_ENABLE (77)
+#define PIN_USB_DM          (78)
+#define PIN_USB_DP          (79)
+
+/*
+ * I2S Interfaces
+ */
+#define I2S_INTERFACES_COUNT 1
+
+#define I2S_DEVICE          0
+#define I2S_CLOCK_GENERATOR 3
+
+#define PIN_I2S_SDO         (32)
+#define PIN_I2S_SDI         (31)
+#define PIN_I2S_SCK         PIN_SERIAL4_TX
+#define PIN_I2S_FS          (33)
+#define PIN_I2S_MCK			    PIN_SERIAL4_RX
+
+// On-board QSPI Flash
+#define EXTERNAL_FLASH_DEVICES   GD25Q16C
+#define EXTERNAL_FLASH_USE_QSPI
+
+//QSPI Pins
+#define PIN_QSPI_SCK	      (89)
+#define PIN_QSPI_CS		      (90)
+#define PIN_QSPI_IO0	      (91)
+#define PIN_QSPI_IO1	      (92)
+#define PIN_QSPI_IO2	      (93)
+#define PIN_QSPI_IO3	      (94)
+
+//PCC Pins
+#define PIN_PCC_DEN1        (26)
+#define PIN_PCC_DEN2        (27)
+#define PIN_PCC_CLK         (28)
+#define PIN_PCC_XCLK	      (29)
+#define PIN_PCC_D0          (37)
+#define PIN_PCC_D1          (36)
+#define PIN_PCC_D2          (35)
+#define PIN_PCC_D3          (34)
+#define PIN_PCC_D4          (33)
+#define PIN_PCC_D5          (32)
+#define PIN_PCC_D6          (31)
+#define PIN_PCC_D7          (30)
+#define PIN_PCC_D8          (39)
+#define PIN_PCC_D9          (38)
+#define PIN_PCC_D10         (41)
+#define PIN_PCC_D11         (40)
+#define PIN_PCC_D12         (43)
+#define PIN_PCC_D13         (42)
+
+#if !defined(VARIANT_QSPI_BAUD_DEFAULT)
+  // TODO: meaningful value for this
+  #define VARIANT_QSPI_BAUD_DEFAULT 5000000
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+ *        Arduino objects - C++ only
+ *----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+
+/*	=========================
+ *	===== SERCOM DEFINITION
+ *	=========================
+*/
+extern SERCOM sercom0;
+extern SERCOM sercom1;
+extern SERCOM sercom2;
+extern SERCOM sercom3;
+extern SERCOM sercom4;
+extern SERCOM sercom5;
+extern SERCOM sercom6;
+extern SERCOM sercom7;
+
+extern Uart Serial1;
+
+#endif
+
+// These serial port names are intended to allow libraries and architecture-neutral
+// sketches to automatically default to the correct port name for a particular type
+// of use.  For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN,
+// the first hardware serial port whose RX/TX pins are not dedicated to another use.
+//
+// SERIAL_PORT_MONITOR        Port which normally prints to the Arduino Serial Monitor
+//
+// SERIAL_PORT_USBVIRTUAL     Port which is USB virtual serial
+//
+// SERIAL_PORT_LINUXBRIDGE    Port which connects to a Linux system via Bridge library
+//
+// SERIAL_PORT_HARDWARE       Hardware serial port, physical RX & TX pins.
+//
+// SERIAL_PORT_HARDWARE_OPEN  Hardware serial ports which are open for use.  Their RX & TX
+//                            pins are NOT connected to anything by default.
+#define SERIAL_PORT_USBVIRTUAL      Serial
+#define SERIAL_PORT_MONITOR         Serial
+// Serial has no physical pins broken out, so it's not listed as HARDWARE port
+#define SERIAL_PORT_HARDWARE        Serial1
+#define SERIAL_PORT_HARDWARE_OPEN   Serial1
+
+#endif /* _VARIANT_GRAND_CENTRAL_M4_ */
diff --git a/variants/hallowing_m0_express/debug_scripts/variant.gdb b/variants/hallowing_m0_express/debug_scripts/variant.gdb
new file mode 100644
index 000000000..3c37ffde2
--- /dev/null
+++ b/variants/hallowing_m0_express/debug_scripts/variant.gdb
@@ -0,0 +1,31 @@
+#
+#  Arduino Zero OpenOCD script.
+#
+#  Copyright (c) 2014-2015 Arduino LLC. All right reserved.
+#
+#  This library is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 2.1 of the License, or (at your option) any later version.
+#
+#  This library is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#  See the GNU Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library; if not, write to the Free Software
+#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#
+
+# Define 'reset' command
+define reset
+
+info reg
+
+break main
+
+# End of 'reset' command
+end
+
+target remote | openocd -c "interface cmsis-dap" -c "set CHIPNAME at91samd21g18" -f target/at91samdXX.cfg -c "gdb_port pipe; log_output openocd.log"
diff --git a/variants/hallowing_m0_express/linker_scripts/gcc/flash_with_bootloader.ld b/variants/hallowing_m0_express/linker_scripts/gcc/flash_with_bootloader.ld
new file mode 100644
index 000000000..7d75f819d
--- /dev/null
+++ b/variants/hallowing_m0_express/linker_scripts/gcc/flash_with_bootloader.ld
@@ -0,0 +1,213 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* Linker script to configure memory regions.
+ * Need modifying for a specific board.
+ *   FLASH.ORIGIN: starting address of flash
+ *   FLASH.LENGTH: length of flash
+ *   RAM.ORIGIN: starting address of RAM bank 0
+ *   RAM.LENGTH: length of RAM bank 0
+ */
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000+0x2000, LENGTH = 0x00040000-0x2000 /* First 8KB used by bootloader */
+  RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ *   Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ *   __exidx_start
+ *   __exidx_end
+ *   __copy_table_start__
+ *   __copy_table_end__
+ *   __zero_table_start__
+ *   __zero_table_end__
+ *   __etext
+ *   __data_start__
+ *   __preinit_array_start
+ *   __preinit_array_end
+ *   __init_array_start
+ *   __init_array_end
+ *   __fini_array_start
+ *   __fini_array_end
+ *   __data_end__
+ *   __bss_start__
+ *   __bss_end__
+ *   __end__
+ *   end
+ *   __HeapLimit
+ *   __StackLimit
+ *   __StackTop
+ *   __stack
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+	.text :
+	{
+		__text_start__ = .;
+
+		KEEP(*(.isr_vector))
+		*(.text*)
+
+		KEEP(*(.init))
+		KEEP(*(.fini))
+
+		/* .ctors */
+		*crtbegin.o(.ctors)
+		*crtbegin?.o(.ctors)
+		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+		*(SORT(.ctors.*))
+		*(.ctors)
+
+		/* .dtors */
+ 		*crtbegin.o(.dtors)
+ 		*crtbegin?.o(.dtors)
+ 		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ 		*(SORT(.dtors.*))
+ 		*(.dtors)
+
+		*(.rodata*)
+
+		KEEP(*(.eh_frame*))
+	} > FLASH
+
+	.ARM.extab :
+	{
+		*(.ARM.extab* .gnu.linkonce.armextab.*)
+	} > FLASH
+
+	__exidx_start = .;
+	.ARM.exidx :
+	{
+		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
+	} > FLASH
+	__exidx_end = .;
+
+	/* To copy multiple ROM to RAM sections,
+	 * uncomment .copy.table section and,
+	 * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.copy.table :
+	{
+		. = ALIGN(4);
+		__copy_table_start__ = .;
+		LONG (__etext)
+		LONG (__data_start__)
+		LONG (__data_end__ - __data_start__)
+		LONG (__etext2)
+		LONG (__data2_start__)
+		LONG (__data2_end__ - __data2_start__)
+		__copy_table_end__ = .;
+	} > FLASH
+	*/
+
+	/* To clear multiple BSS sections,
+	 * uncomment .zero.table section and,
+	 * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.zero.table :
+	{
+		. = ALIGN(4);
+		__zero_table_start__ = .;
+		LONG (__bss_start__)
+		LONG (__bss_end__ - __bss_start__)
+		LONG (__bss2_start__)
+		LONG (__bss2_end__ - __bss2_start__)
+		__zero_table_end__ = .;
+	} > FLASH
+	*/
+
+	__etext = .;
+
+	.data : AT (__etext)
+	{
+		__data_start__ = .;
+		*(vtable)
+		*(.data*)
+
+		. = ALIGN(4);
+		/* preinit data */
+		PROVIDE_HIDDEN (__preinit_array_start = .);
+		KEEP(*(.preinit_array))
+		PROVIDE_HIDDEN (__preinit_array_end = .);
+
+		. = ALIGN(4);
+		/* init data */
+		PROVIDE_HIDDEN (__init_array_start = .);
+		KEEP(*(SORT(.init_array.*)))
+		KEEP(*(.init_array))
+		PROVIDE_HIDDEN (__init_array_end = .);
+
+
+		. = ALIGN(4);
+		/* finit data */
+		PROVIDE_HIDDEN (__fini_array_start = .);
+		KEEP(*(SORT(.fini_array.*)))
+		KEEP(*(.fini_array))
+		PROVIDE_HIDDEN (__fini_array_end = .);
+
+		KEEP(*(.jcr*))
+		. = ALIGN(16);
+		/* All data end */
+		__data_end__ = .;
+
+	} > RAM
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start__ = .;
+		*(.bss*)
+		*(COMMON)
+		. = ALIGN(4);
+		__bss_end__ = .;
+	} > RAM
+
+	.heap (COPY):
+	{
+		__end__ = .;
+		PROVIDE(end = .);
+		*(.heap*)
+		__HeapLimit = .;
+	} > RAM
+
+	/* .stack_dummy section doesn't contains any symbols. It is only
+	 * used for linker to calculate size of stack sections, and assign
+	 * values to stack symbols later */
+	.stack_dummy (COPY):
+	{
+		*(.stack*)
+	} > RAM
+
+	/* Set stack top to end of RAM, and stack limit move down by
+	 * size of stack_dummy section */
+	__StackTop = ORIGIN(RAM) + LENGTH(RAM);
+	__StackLimit = __StackTop - SIZEOF(.stack_dummy);
+	PROVIDE(__stack = __StackTop);
+
+	__ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ;
+
+	/* Check if data + heap + stack exceeds RAM limit */
+	ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
+}
diff --git a/variants/hallowing_m0_express/linker_scripts/gcc/flash_without_bootloader.ld b/variants/hallowing_m0_express/linker_scripts/gcc/flash_without_bootloader.ld
new file mode 100644
index 000000000..ebeeee37f
--- /dev/null
+++ b/variants/hallowing_m0_express/linker_scripts/gcc/flash_without_bootloader.ld
@@ -0,0 +1,214 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* Linker script to configure memory regions.
+ * Need modifying for a specific board.
+ *   FLASH.ORIGIN: starting address of flash
+ *   FLASH.LENGTH: length of flash
+ *   RAM.ORIGIN: starting address of RAM bank 0
+ *   RAM.LENGTH: length of RAM bank 0
+ */
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00040000
+  RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ *   Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ *   __exidx_start
+ *   __exidx_end
+ *   __copy_table_start__
+ *   __copy_table_end__
+ *   __zero_table_start__
+ *   __zero_table_end__
+ *   __etext
+ *   __data_start__
+ *   __preinit_array_start
+ *   __preinit_array_end
+ *   __init_array_start
+ *   __init_array_end
+ *   __fini_array_start
+ *   __fini_array_end
+ *   __data_end__
+ *   __bss_start__
+ *   __bss_end__
+ *   __end__
+ *   end
+ *   __HeapLimit
+ *   __StackLimit
+ *   __StackTop
+ *   __stack
+ *   __ram_end__
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+	.text :
+	{
+		__text_start__ = .;
+
+		KEEP(*(.isr_vector))
+		*(.text*)
+
+		KEEP(*(.init))
+		KEEP(*(.fini))
+
+		/* .ctors */
+		*crtbegin.o(.ctors)
+		*crtbegin?.o(.ctors)
+		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+		*(SORT(.ctors.*))
+		*(.ctors)
+
+		/* .dtors */
+ 		*crtbegin.o(.dtors)
+ 		*crtbegin?.o(.dtors)
+ 		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ 		*(SORT(.dtors.*))
+ 		*(.dtors)
+
+		*(.rodata*)
+
+		KEEP(*(.eh_frame*))
+	} > FLASH
+
+	.ARM.extab :
+	{
+		*(.ARM.extab* .gnu.linkonce.armextab.*)
+	} > FLASH
+
+	__exidx_start = .;
+	.ARM.exidx :
+	{
+		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
+	} > FLASH
+	__exidx_end = .;
+
+	/* To copy multiple ROM to RAM sections,
+	 * uncomment .copy.table section and,
+	 * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.copy.table :
+	{
+		. = ALIGN(4);
+		__copy_table_start__ = .;
+		LONG (__etext)
+		LONG (__data_start__)
+		LONG (__data_end__ - __data_start__)
+		LONG (__etext2)
+		LONG (__data2_start__)
+		LONG (__data2_end__ - __data2_start__)
+		__copy_table_end__ = .;
+	} > FLASH
+	*/
+
+	/* To clear multiple BSS sections,
+	 * uncomment .zero.table section and,
+	 * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.zero.table :
+	{
+		. = ALIGN(4);
+		__zero_table_start__ = .;
+		LONG (__bss_start__)
+		LONG (__bss_end__ - __bss_start__)
+		LONG (__bss2_start__)
+		LONG (__bss2_end__ - __bss2_start__)
+		__zero_table_end__ = .;
+	} > FLASH
+	*/
+
+	__etext = .;
+
+	.data : AT (__etext)
+	{
+		__data_start__ = .;
+		*(vtable)
+		*(.data*)
+
+		. = ALIGN(4);
+		/* preinit data */
+		PROVIDE_HIDDEN (__preinit_array_start = .);
+		KEEP(*(.preinit_array))
+		PROVIDE_HIDDEN (__preinit_array_end = .);
+
+		. = ALIGN(4);
+		/* init data */
+		PROVIDE_HIDDEN (__init_array_start = .);
+		KEEP(*(SORT(.init_array.*)))
+		KEEP(*(.init_array))
+		PROVIDE_HIDDEN (__init_array_end = .);
+
+
+		. = ALIGN(4);
+		/* finit data */
+		PROVIDE_HIDDEN (__fini_array_start = .);
+		KEEP(*(SORT(.fini_array.*)))
+		KEEP(*(.fini_array))
+		PROVIDE_HIDDEN (__fini_array_end = .);
+
+		KEEP(*(.jcr*))
+		. = ALIGN(16);
+		/* All data end */
+		__data_end__ = .;
+
+	} > RAM
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start__ = .;
+		*(.bss*)
+		*(COMMON)
+		. = ALIGN(4);
+		__bss_end__ = .;
+	} > RAM
+
+	.heap (COPY):
+	{
+		__end__ = .;
+		PROVIDE(end = .);
+		*(.heap*)
+		__HeapLimit = .;
+	} > RAM
+
+	/* .stack_dummy section doesn't contains any symbols. It is only
+	 * used for linker to calculate size of stack sections, and assign
+	 * values to stack symbols later */
+	.stack_dummy (COPY):
+	{
+		*(.stack*)
+	} > RAM
+
+	/* Set stack top to end of RAM, and stack limit move down by
+	 * size of stack_dummy section */
+	__StackTop = ORIGIN(RAM) + LENGTH(RAM) ;
+	__StackLimit = __StackTop - SIZEOF(.stack_dummy);
+	PROVIDE(__stack = __StackTop);
+
+	__ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ;
+
+	/* Check if data + heap + stack exceeds RAM limit */
+	ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
+}
diff --git a/variants/hallowing_m0_express/openocd_scripts/hallowing_m0_express.cfg b/variants/hallowing_m0_express/openocd_scripts/hallowing_m0_express.cfg
new file mode 100644
index 000000000..251f77aca
--- /dev/null
+++ b/variants/hallowing_m0_express/openocd_scripts/hallowing_m0_express.cfg
@@ -0,0 +1,28 @@
+#
+#  Adafruit Hallowing M0 Express OpenOCD script.
+#
+#  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+#
+#  This library is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 2.1 of the License, or (at your option) any later version.
+#
+#  This library is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#  See the GNU Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library; if not, write to the Free Software
+#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#
+
+# chip name
+set CHIPNAME at91samd21g18
+set ENDIAN little
+
+# choose a port here
+set telnet_port 0
+
+source [find target/at91samdXX.cfg]
diff --git a/variants/hallowing_m0_express/pins_arduino.h b/variants/hallowing_m0_express/pins_arduino.h
new file mode 100644
index 000000000..db0e40c3d
--- /dev/null
+++ b/variants/hallowing_m0_express/pins_arduino.h
@@ -0,0 +1,21 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+// API compatibility
+#include "variant.h"
+
diff --git a/variants/hallowing_m0_express/variant.cpp b/variants/hallowing_m0_express/variant.cpp
new file mode 100644
index 000000000..441e2faee
--- /dev/null
+++ b/variants/hallowing_m0_express/variant.cpp
@@ -0,0 +1,130 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#include "variant.h"
+
+/*
+ * Pins descriptions
+ */
+const PinDescription g_APinDescription[]=
+{
+  // 0..13 - Digital pins
+  // ----------------------
+  // 0/1 - SERCOM/UART (Serial1)
+  { PORTA,  9, PIO_SERCOM_ALT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM0_CH1, TCC0_CH1, EXTERNAL_INT_9 },      // RX: SERCOM2/PAD[1] TCC0/WO[1]
+  { PORTA, 10, PIO_SERCOM_ALT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER_ALT), No_ADC_Channel, PWM0_CH2, TCC0_CH2, EXTERNAL_INT_10 }, // TX: SERCOM2/PAD[3] TCC0/WO[2]
+
+  // 2..12
+  // Digital Low
+  { PORTA, 14, PIO_DIGITAL, (PIN_ATTR_DIGITAL), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_14 },  // D2
+  { PORTA, 11, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER_ALT), No_ADC_Channel, PWM0_CH3, TCC0_CH3, EXTERNAL_INT_11 },     // D3 TCC0/WO[3]
+  { PORTA,  8, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM0_CH0, TCC0_CH0, EXTERNAL_INT_NMI },        // D4 TCC0/WO[0]
+  { PORTA, 15, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM3_CH1, TC3_CH1, EXTERNAL_INT_15 },          // D5 TC3/WO[1]
+  { PORTA, 18, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM3_CH0, TC3_CH0, EXTERNAL_INT_2 },           // D6 TC3/WO[0]
+  { PORTA,  0, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM2_CH0, TCC2_CH0, EXTERNAL_INT_NONE },       // D7 - backlight TCC2/WO[0]
+
+  // Digital High
+  { PORTA, 12, PIO_TIMER, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_12 }, // D8
+  { PORTA, 19, PIO_TIMER_ALT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER_ALT), No_ADC_Channel, PWM0_CH3, TCC0_CH3, EXTERNAL_INT_3 }, // D9   TCC0/WO[3]
+  { PORTA, 20, PIO_TIMER_ALT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER_ALT), No_ADC_Channel, PWM0_CH6, TCC0_CH6, EXTERNAL_INT_4 }, // D10  TCC0/WO[6]
+  { PORTA, 21, PIO_TIMER_ALT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER_ALT), No_ADC_Channel, PWM0_CH7, TCC0_CH7, EXTERNAL_INT_5 }, // D11  TCC0/WO[7]
+  { PORTA, 22, PIO_TIMER_ALT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER_ALT), No_ADC_Channel, PWM0_CH4, TCC0_CH4, EXTERNAL_INT_6 }, // D12  TCC0/WO[4]
+
+  // 13 (LED)
+  { PORTA, 23, PIO_TIMER_ALT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER_ALT), No_ADC_Channel, PWM0_CH5, TCC0_CH5, EXTERNAL_INT_7 }, // D13  TCC0/WO[5]
+
+
+  // 14..19 - Analog pins
+  // --------------------
+  { PORTA,  2, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel0, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 }, // A0 - ADC/AIN[0]
+  { PORTB,  8, PIO_ANALOG, (PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel2, PWM4_CH0, TC4_CH0, EXTERNAL_INT_8 }, // A1 - ADC/AIN[2]
+  { PORTB,  9, PIO_ANALOG, (PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel3, PWM4_CH1, TC4_CH1, EXTERNAL_INT_9 }, // A2 - ADC/AIN[3]
+  { PORTA,  4, PIO_ANALOG, (PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel4, PWM0_CH0, TCC0_CH0, EXTERNAL_INT_4 }, // A3 - ADC/AIN[4]
+  { PORTA,  5, PIO_ANALOG, (PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel5, PWM0_CH1, TCC0_CH1, EXTERNAL_INT_5 }, // A4 - ADC/AIN[5]
+  { PORTA,  6, PIO_ANALOG, (PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel6, PWM1_CH0, TCC1_CH0, EXTERNAL_INT_6 }, // A5 - TCC1/WO[0]
+
+  // Extra Analog pins! 20..25
+  { PORTB,  2, PIO_ANALOG, 0, ADC_Channel10, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 }, // A6 - VBATT - ADC/AIN[10]
+  { PORTB,  3, PIO_ANALOG, (PIN_ATTR_DIGITAL|PIN_ATTR_ANALOG), ADC_Channel11, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // A7 - same as MISO
+  { PORTA,  8, PIO_ANALOG, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER|PIN_ATTR_ANALOG), ADC_Channel16, PWM0_CH0, TCC0_CH0, EXTERNAL_INT_NMI },  // A8 same as D4
+  { PORTA,  9, PIO_ANALOG, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER|PIN_ATTR_ANALOG), ADC_Channel17, PWM0_CH1, TCC0_CH1, EXTERNAL_INT_9 },    // A9 same as RX
+  { PORTA, 10, PIO_ANALOG, (PIN_ATTR_DIGITAL|PIN_ATTR_ANALOG), ADC_Channel18, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_10 }, // A10 same as TX
+  { PORTA, 11, PIO_ANALOG, (PIN_ATTR_DIGITAL|PIN_ATTR_ANALOG), ADC_Channel19, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_11 }, // A11 same as D3
+
+  // 26..27 I2C pins (SDA/SCL)
+  // ----------------------
+  { PORTA, 16, PIO_SERCOM_ALT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM2_CH0, TCC2_CH0, EXTERNAL_INT_0 }, // Sercom 3.0 SDA
+  { PORTA, 17, PIO_SERCOM_ALT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM2_CH1, TCC2_CH1, EXTERNAL_INT_1 }, // Sercom 3.0 SCL
+
+
+  // 28..30 - SPI pins (ICSP:MISO,SCK,MOSI)
+  // ----------------------
+  { PORTB, 03, PIO_SERCOM_ALT, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },  // SPI Flash MISO
+  { PORTB, 22, PIO_SERCOM_ALT, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },  // SPI Flash MOSI
+  { PORTB, 23, PIO_SERCOM_ALT, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },  // SPI Flash SCK
+
+  // 31..32 - USB
+  // --------------------
+  { PORTA, 24, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB/DM
+  { PORTA, 25, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB/DP
+
+  // 33..35 - Secondary SPI
+  // ----------------------
+  { PORTA, 13, PIO_SERCOM_ALT, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_13 }, // MISO: SERCOM4/PAD[1]
+  { PORTB, 10, PIO_SERCOM_ALT, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_10 }, // MOSI: SERCOM4/PAD[2]
+  { PORTB, 11, PIO_SERCOM_ALT, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_11 }, // SCK: SERCOM4/PAD[3]
+  // 36 Secondary SPI SS
+  { PORTA,  7, PIO_DIGITAL, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER|PIN_ATTR_ANALOG), ADC_Channel7, PWM1_CH1, TCC1_CH1, EXTERNAL_INT_7 }, // FlashCS
+
+  // 37 TFT reset
+  { PORTA, 27, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_15 }, // SPI Flash SS
+  // 38 TFT DC
+  { PORTA, 28, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // used as output only
+  // 39 TFT CS
+  { PORTA, 1, PIO_DIGITAL, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // Dotstar Data
+
+  // D40 dup of D8
+  { PORTA, 12, PIO_TIMER, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_12 }, // D8
+
+  // 41 (AREF)
+  { PORTA, 3, PIO_ANALOG, PIN_ATTR_ANALOG, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // DAC/VREFP
+
+  // ----------------------
+  // 42 - Alternate use of A0 (DAC output)
+  { PORTA,  2, PIO_ANALOG, PIN_ATTR_ANALOG, DAC_Channel0, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 }, // DAC/VOUT
+
+} ;
+
+const void* g_apTCInstances[TCC_INST_NUM+TC_INST_NUM]={ TCC0, TCC1, TCC2, TC3, TC4, TC5 } ;
+
+// Multi-serial objects instantiation
+SERCOM sercom0( SERCOM0 ) ;
+SERCOM sercom1( SERCOM1 ) ;
+SERCOM sercom2( SERCOM2 ) ;
+SERCOM sercom3( SERCOM3 ) ;
+SERCOM sercom4( SERCOM4 ) ;
+SERCOM sercom5( SERCOM5 ) ;
+
+Uart Serial1( &sercom2, PIN_SERIAL1_RX, PIN_SERIAL1_TX, PAD_SERIAL1_RX, PAD_SERIAL1_TX ) ;
+
+void SERCOM2_Handler()
+{
+  Serial1.IrqHandler();
+}
+
diff --git a/variants/hallowing_m0_express/variant.h b/variants/hallowing_m0_express/variant.h
new file mode 100644
index 000000000..3dd998c3d
--- /dev/null
+++ b/variants/hallowing_m0_express/variant.h
@@ -0,0 +1,254 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _VARIANT_ARDUINO_ZERO_
+#define _VARIANT_ARDUINO_ZERO_
+
+// The definitions here needs a SAMD core >=1.6.10
+#define ARDUINO_SAMD_VARIANT_COMPLIANCE 10610
+
+/*----------------------------------------------------------------------------
+ *        Definitions
+ *----------------------------------------------------------------------------*/
+
+/** Frequency of the board main oscillator */
+#define VARIANT_MAINOSC		(32768ul)
+
+/** Master clock frequency */
+#define VARIANT_MCK	(F_CPU)
+
+/*----------------------------------------------------------------------------
+ *        Headers
+ *----------------------------------------------------------------------------*/
+
+#include "WVariant.h"
+
+#ifdef __cplusplus
+#include "SERCOM.h"
+#include "Uart.h"
+#endif // __cplusplus
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif // __cplusplus
+
+/*----------------------------------------------------------------------------
+ *        Pins
+ *----------------------------------------------------------------------------*/
+
+// Number of pins defined in PinDescription array
+#define PINS_COUNT           (42u)
+#define NUM_DIGITAL_PINS     (42u)
+#define NUM_ANALOG_INPUTS    (12u)
+#define NUM_ANALOG_OUTPUTS   (1u)
+#define analogInputToDigitalPin(p)  ((p < 6u) ? (p) + 14u : -1)
+
+#define digitalPinToPort(P)        ( &(PORT->Group[g_APinDescription[P].ulPort]) )
+#define digitalPinToBitMask(P)     ( 1 << g_APinDescription[P].ulPin )
+//#define analogInPinToBit(P)        ( )
+#define portOutputRegister(port)   ( &(port->OUT.reg) )
+#define portInputRegister(port)    ( &(port->IN.reg) )
+#define portModeRegister(port)     ( &(port->DIR.reg) )
+#define digitalPinHasPWM(P)        ( g_APinDescription[P].ulPWMChannel != NOT_ON_PWM || g_APinDescription[P].ulTCChannel != NOT_ON_TIMER )
+
+/*
+ * digitalPinToTimer(..) is AVR-specific and is not defined for SAMD
+ * architecture. If you need to check if a pin supports PWM you must
+ * use digitalPinHasPWM(..).
+ *
+ * https://github.com/arduino/Arduino/issues/1833
+ */
+// #define digitalPinToTimer(P)
+
+// LEDs
+#define PIN_LED_13           (13u)
+  //#define PIN_LED_RXL          (31u)
+  //#define PIN_LED_TXL          (32u)
+#define PIN_LED              PIN_LED_13
+//#define PIN_LED2             PIN_LED_RXL
+//#define PIN_LED3             PIN_LED_TXL
+#define LED_BUILTIN          PIN_LED_13
+#define NEOPIXEL_BUILTIN     (8u)
+#define PIN_NEOPIXEL         NEOPIXEL_BUILTIN
+
+/*
+ * Analog pins
+ */
+#define PIN_A0               (14ul)
+#define PIN_A1               (PIN_A0 + 1)
+#define PIN_A2               (PIN_A0 + 2)
+#define PIN_A3               (PIN_A0 + 3)
+#define PIN_A4               (PIN_A0 + 4)
+#define PIN_A5               (PIN_A0 + 5)
+#define PIN_A6               (PIN_A0 + 6)
+#define PIN_A7               (PIN_A0 + 7)
+#define PIN_A8               (PIN_A0 + 8)
+#define PIN_A9               (PIN_A0 + 9)
+#define PIN_A10              (PIN_A0 + 10)
+#define PIN_A11              (PIN_A0 + 11)
+#define PIN_A12              (41ul)
+#define PIN_DAC0             (14ul)
+
+static const uint8_t A0  = PIN_A0;
+static const uint8_t A1  = PIN_A1;
+static const uint8_t A2  = PIN_A2;
+static const uint8_t A3  = PIN_A3;
+static const uint8_t A4  = PIN_A4;
+static const uint8_t A5  = PIN_A5;
+static const uint8_t A6  = PIN_A6 ;
+static const uint8_t A7  = PIN_A7 ;
+static const uint8_t A8  = PIN_A8 ;
+static const uint8_t A9  = PIN_A9 ;
+static const uint8_t A10 = PIN_A10 ;
+static const uint8_t A11 = PIN_A11 ;
+static const uint8_t A12 = PIN_A12 ;
+
+static const uint8_t DAC0 = PIN_DAC0;
+
+#define ADC_RESOLUTION		12
+
+// Other pins
+#define PIN_ATN              (38ul)
+static const uint8_t ATN = PIN_ATN;
+
+// On-board SPI Flash
+#define EXTERNAL_FLASH_DEVICES  GD25Q16C
+#define EXTERNAL_FLASH_USE_SPI  SPI1
+#define EXTERNAL_FLASH_USE_CS   SS1
+
+/*
+ * Serial interfaces
+ */
+
+// Serial1
+#define PIN_SERIAL1_RX       (0ul)
+#define PIN_SERIAL1_TX       (1ul)
+#define PAD_SERIAL1_RX       (SERCOM_RX_PAD_1)
+#define PAD_SERIAL1_TX       (UART_TX_PAD_2)
+
+/*
+ * SPI Interfaces
+ */
+#define SPI_INTERFACES_COUNT 2
+
+#define PIN_SPI_MISO         (28u)
+#define PIN_SPI_MOSI         (29u)
+#define PIN_SPI_SCK          (30u)
+#define PERIPH_SPI           sercom5
+#define PAD_SPI_TX           SPI_PAD_2_SCK_3
+#define PAD_SPI_RX           SERCOM_RX_PAD_1
+
+static const uint8_t SS	  = PIN_A2 ;	// SERCOM4 last PAD is present on A2 but HW SS isn't used. Set here only for reference.
+static const uint8_t MOSI = PIN_SPI_MOSI ;
+static const uint8_t MISO = PIN_SPI_MISO ;
+static const uint8_t SCK  = PIN_SPI_SCK ;
+
+
+#define PIN_SPI1_MISO         (33u)
+#define PIN_SPI1_MOSI         (34u)
+#define PIN_SPI1_SCK          (35u)
+#define PERIPH_SPI1           sercom4
+#define PAD_SPI1_TX           SPI_PAD_2_SCK_3
+#define PAD_SPI1_RX           SERCOM_RX_PAD_1
+
+static const uint8_t SS1   = 36;
+static const uint8_t MOSI1 = PIN_SPI1_MOSI ;
+static const uint8_t MISO1 = PIN_SPI1_MISO ;
+static const uint8_t SCK1  = PIN_SPI1_SCK ;
+
+
+/*
+ * Wire Interfaces
+ */
+#define WIRE_INTERFACES_COUNT 1
+
+#define PIN_WIRE_SDA         (26u)
+#define PIN_WIRE_SCL         (27u)
+#define PERIPH_WIRE          sercom3
+#define WIRE_IT_HANDLER      SERCOM3_Handler
+
+static const uint8_t SDA = PIN_WIRE_SDA;
+static const uint8_t SCL = PIN_WIRE_SCL;
+
+/*
+ * USB
+ */
+#define PIN_USB_HOST_ENABLE (40ul)
+#define PIN_USB_DM          (31ul)
+#define PIN_USB_DP          (32ul)
+
+/*
+ * I2S Interfaces
+ */
+#define I2S_INTERFACES_COUNT 0
+
+#define I2S_DEVICE          0
+#define I2S_CLOCK_GENERATOR 3
+#define PIN_I2S_SD          (9u)
+#define PIN_I2S_SCK         (1u)
+#define PIN_I2S_FS          (0u)
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+ *        Arduino objects - C++ only
+ *----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+
+/*	=========================
+ *	===== SERCOM DEFINITION
+ *	=========================
+*/
+extern SERCOM sercom0;
+extern SERCOM sercom1;
+extern SERCOM sercom2;
+extern SERCOM sercom3;
+extern SERCOM sercom4;
+extern SERCOM sercom5;
+
+extern Uart Serial1;
+
+#endif
+
+// These serial port names are intended to allow libraries and architecture-neutral
+// sketches to automatically default to the correct port name for a particular type
+// of use.  For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN,
+// the first hardware serial port whose RX/TX pins are not dedicated to another use.
+//
+// SERIAL_PORT_MONITOR        Port which normally prints to the Arduino Serial Monitor
+//
+// SERIAL_PORT_USBVIRTUAL     Port which is USB virtual serial
+//
+// SERIAL_PORT_LINUXBRIDGE    Port which connects to a Linux system via Bridge library
+//
+// SERIAL_PORT_HARDWARE       Hardware serial port, physical RX & TX pins.
+//
+// SERIAL_PORT_HARDWARE_OPEN  Hardware serial ports which are open for use.  Their RX & TX
+//                            pins are NOT connected to anything by default.
+#define SERIAL_PORT_USBVIRTUAL      Serial
+#define SERIAL_PORT_MONITOR         Serial
+// Serial has no physical pins broken out, so it's not listed as HARDWARE port
+#define SERIAL_PORT_HARDWARE        Serial1
+#define SERIAL_PORT_HARDWARE_OPEN   Serial1
+
+#endif /* _VARIANT_ARDUINO_ZERO_ */
+
diff --git a/variants/hallowing_m4/debug_scripts/variant.gdb b/variants/hallowing_m4/debug_scripts/variant.gdb
new file mode 100644
index 000000000..3c37ffde2
--- /dev/null
+++ b/variants/hallowing_m4/debug_scripts/variant.gdb
@@ -0,0 +1,31 @@
+#
+#  Arduino Zero OpenOCD script.
+#
+#  Copyright (c) 2014-2015 Arduino LLC. All right reserved.
+#
+#  This library is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 2.1 of the License, or (at your option) any later version.
+#
+#  This library is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#  See the GNU Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library; if not, write to the Free Software
+#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#
+
+# Define 'reset' command
+define reset
+
+info reg
+
+break main
+
+# End of 'reset' command
+end
+
+target remote | openocd -c "interface cmsis-dap" -c "set CHIPNAME at91samd21g18" -f target/at91samdXX.cfg -c "gdb_port pipe; log_output openocd.log"
diff --git a/variants/hallowing_m4/linker_scripts/gcc/flash_with_bootloader.ld b/variants/hallowing_m4/linker_scripts/gcc/flash_with_bootloader.ld
new file mode 100644
index 000000000..1bdea69ae
--- /dev/null
+++ b/variants/hallowing_m4/linker_scripts/gcc/flash_with_bootloader.ld
@@ -0,0 +1,216 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* Linker script to configure memory regions.
+ * Need modifying for a specific board.
+ *   FLASH.ORIGIN: starting address of flash
+ *   FLASH.LENGTH: length of flash
+ *   RAM.ORIGIN: starting address of RAM bank 0
+ *   RAM.LENGTH: length of RAM bank 0
+ */
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000+0x4000, LENGTH = 0x00080000-0x4000 /* First 16KB used by bootloader */
+  RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00030000
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ *   Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ *   __exidx_start
+ *   __exidx_end
+ *   __copy_table_start__
+ *   __copy_table_end__
+ *   __zero_table_start__
+ *   __zero_table_end__
+ *   __etext
+ *   __data_start__
+ *   __preinit_array_start
+ *   __preinit_array_end
+ *   __init_array_start
+ *   __init_array_end
+ *   __fini_array_start
+ *   __fini_array_end
+ *   __data_end__
+ *   __bss_start__
+ *   __bss_end__
+ *   __end__
+ *   end
+ *   __HeapLimit
+ *   __StackLimit
+ *   __StackTop
+ *   __stack
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+	.text :
+	{
+		__text_start__ = .;
+
+		KEEP(*(.sketch_boot))
+
+		. = ALIGN(0x4000);
+		KEEP(*(.isr_vector))
+		*(.text*)
+
+		KEEP(*(.init))
+		KEEP(*(.fini))
+
+		/* .ctors */
+		*crtbegin.o(.ctors)
+		*crtbegin?.o(.ctors)
+		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+		*(SORT(.ctors.*))
+		*(.ctors)
+
+		/* .dtors */
+ 		*crtbegin.o(.dtors)
+ 		*crtbegin?.o(.dtors)
+ 		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ 		*(SORT(.dtors.*))
+ 		*(.dtors)
+
+		*(.rodata*)
+
+		KEEP(*(.eh_frame*))
+	} > FLASH
+
+	.ARM.extab :
+	{
+		*(.ARM.extab* .gnu.linkonce.armextab.*)
+	} > FLASH
+
+	__exidx_start = .;
+	.ARM.exidx :
+	{
+		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
+	} > FLASH
+	__exidx_end = .;
+
+	/* To copy multiple ROM to RAM sections,
+	 * uncomment .copy.table section and,
+	 * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.copy.table :
+	{
+		. = ALIGN(4);
+		__copy_table_start__ = .;
+		LONG (__etext)
+		LONG (__data_start__)
+		LONG (__data_end__ - __data_start__)
+		LONG (__etext2)
+		LONG (__data2_start__)
+		LONG (__data2_end__ - __data2_start__)
+		__copy_table_end__ = .;
+	} > FLASH
+	*/
+
+	/* To clear multiple BSS sections,
+	 * uncomment .zero.table section and,
+	 * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.zero.table :
+	{
+		. = ALIGN(4);
+		__zero_table_start__ = .;
+		LONG (__bss_start__)
+		LONG (__bss_end__ - __bss_start__)
+		LONG (__bss2_start__)
+		LONG (__bss2_end__ - __bss2_start__)
+		__zero_table_end__ = .;
+	} > FLASH
+	*/
+
+	__etext = .;
+
+	.data : AT (__etext)
+	{
+		__data_start__ = .;
+		*(vtable)
+		*(.data*)
+
+		. = ALIGN(4);
+		/* preinit data */
+		PROVIDE_HIDDEN (__preinit_array_start = .);
+		KEEP(*(.preinit_array))
+		PROVIDE_HIDDEN (__preinit_array_end = .);
+
+		. = ALIGN(4);
+		/* init data */
+		PROVIDE_HIDDEN (__init_array_start = .);
+		KEEP(*(SORT(.init_array.*)))
+		KEEP(*(.init_array))
+		PROVIDE_HIDDEN (__init_array_end = .);
+
+
+		. = ALIGN(4);
+		/* finit data */
+		PROVIDE_HIDDEN (__fini_array_start = .);
+		KEEP(*(SORT(.fini_array.*)))
+		KEEP(*(.fini_array))
+		PROVIDE_HIDDEN (__fini_array_end = .);
+
+		KEEP(*(.jcr*))
+		. = ALIGN(16);
+		/* All data end */
+		__data_end__ = .;
+
+	} > RAM
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start__ = .;
+		*(.bss*)
+		*(COMMON)
+		. = ALIGN(4);
+		__bss_end__ = .;
+	} > RAM
+
+	.heap (COPY):
+	{
+		__end__ = .;
+		PROVIDE(end = .);
+		*(.heap*)
+		__HeapLimit = .;
+	} > RAM
+
+	/* .stack_dummy section doesn't contains any symbols. It is only
+	 * used for linker to calculate size of stack sections, and assign
+	 * values to stack symbols later */
+	.stack_dummy (COPY):
+	{
+		*(.stack*)
+	} > RAM
+
+	/* Set stack top to end of RAM, and stack limit move down by
+	 * size of stack_dummy section */
+	__StackTop = ORIGIN(RAM) + LENGTH(RAM);
+	__StackLimit = __StackTop - SIZEOF(.stack_dummy);
+	PROVIDE(__stack = __StackTop);
+
+	__ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ;
+
+	/* Check if data + heap + stack exceeds RAM limit */
+	ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
+}
diff --git a/variants/hallowing_m4/linker_scripts/gcc/flash_without_bootloader.ld b/variants/hallowing_m4/linker_scripts/gcc/flash_without_bootloader.ld
new file mode 100644
index 000000000..9c0c4e06d
--- /dev/null
+++ b/variants/hallowing_m4/linker_scripts/gcc/flash_without_bootloader.ld
@@ -0,0 +1,214 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* Linker script to configure memory regions.
+ * Need modifying for a specific board.
+ *   FLASH.ORIGIN: starting address of flash
+ *   FLASH.LENGTH: length of flash
+ *   RAM.ORIGIN: starting address of RAM bank 0
+ *   RAM.LENGTH: length of RAM bank 0
+ */
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00080000
+  RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00030000
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ *   Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ *   __exidx_start
+ *   __exidx_end
+ *   __copy_table_start__
+ *   __copy_table_end__
+ *   __zero_table_start__
+ *   __zero_table_end__
+ *   __etext
+ *   __data_start__
+ *   __preinit_array_start
+ *   __preinit_array_end
+ *   __init_array_start
+ *   __init_array_end
+ *   __fini_array_start
+ *   __fini_array_end
+ *   __data_end__
+ *   __bss_start__
+ *   __bss_end__
+ *   __end__
+ *   end
+ *   __HeapLimit
+ *   __StackLimit
+ *   __StackTop
+ *   __stack
+ *   __ram_end__
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+	.text :
+	{
+		__text_start__ = .;
+
+		KEEP(*(.isr_vector))
+		*(.text*)
+
+		KEEP(*(.init))
+		KEEP(*(.fini))
+
+		/* .ctors */
+		*crtbegin.o(.ctors)
+		*crtbegin?.o(.ctors)
+		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+		*(SORT(.ctors.*))
+		*(.ctors)
+
+		/* .dtors */
+ 		*crtbegin.o(.dtors)
+ 		*crtbegin?.o(.dtors)
+ 		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ 		*(SORT(.dtors.*))
+ 		*(.dtors)
+
+		*(.rodata*)
+
+		KEEP(*(.eh_frame*))
+	} > FLASH
+
+	.ARM.extab :
+	{
+		*(.ARM.extab* .gnu.linkonce.armextab.*)
+	} > FLASH
+
+	__exidx_start = .;
+	.ARM.exidx :
+	{
+		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
+	} > FLASH
+	__exidx_end = .;
+
+	/* To copy multiple ROM to RAM sections,
+	 * uncomment .copy.table section and,
+	 * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.copy.table :
+	{
+		. = ALIGN(4);
+		__copy_table_start__ = .;
+		LONG (__etext)
+		LONG (__data_start__)
+		LONG (__data_end__ - __data_start__)
+		LONG (__etext2)
+		LONG (__data2_start__)
+		LONG (__data2_end__ - __data2_start__)
+		__copy_table_end__ = .;
+	} > FLASH
+	*/
+
+	/* To clear multiple BSS sections,
+	 * uncomment .zero.table section and,
+	 * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.zero.table :
+	{
+		. = ALIGN(4);
+		__zero_table_start__ = .;
+		LONG (__bss_start__)
+		LONG (__bss_end__ - __bss_start__)
+		LONG (__bss2_start__)
+		LONG (__bss2_end__ - __bss2_start__)
+		__zero_table_end__ = .;
+	} > FLASH
+	*/
+
+	__etext = .;
+
+	.data : AT (__etext)
+	{
+		__data_start__ = .;
+		*(vtable)
+		*(.data*)
+
+		. = ALIGN(4);
+		/* preinit data */
+		PROVIDE_HIDDEN (__preinit_array_start = .);
+		KEEP(*(.preinit_array))
+		PROVIDE_HIDDEN (__preinit_array_end = .);
+
+		. = ALIGN(4);
+		/* init data */
+		PROVIDE_HIDDEN (__init_array_start = .);
+		KEEP(*(SORT(.init_array.*)))
+		KEEP(*(.init_array))
+		PROVIDE_HIDDEN (__init_array_end = .);
+
+
+		. = ALIGN(4);
+		/* finit data */
+		PROVIDE_HIDDEN (__fini_array_start = .);
+		KEEP(*(SORT(.fini_array.*)))
+		KEEP(*(.fini_array))
+		PROVIDE_HIDDEN (__fini_array_end = .);
+
+		KEEP(*(.jcr*))
+		. = ALIGN(16);
+		/* All data end */
+		__data_end__ = .;
+
+	} > RAM
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start__ = .;
+		*(.bss*)
+		*(COMMON)
+		. = ALIGN(4);
+		__bss_end__ = .;
+	} > RAM
+
+	.heap (COPY):
+	{
+		__end__ = .;
+		PROVIDE(end = .);
+		*(.heap*)
+		__HeapLimit = .;
+	} > RAM
+
+	/* .stack_dummy section doesn't contains any symbols. It is only
+	 * used for linker to calculate size of stack sections, and assign
+	 * values to stack symbols later */
+	.stack_dummy (COPY):
+	{
+		*(.stack*)
+	} > RAM
+
+	/* Set stack top to end of RAM, and stack limit move down by
+	 * size of stack_dummy section */
+	__StackTop = ORIGIN(RAM) + LENGTH(RAM) ;
+	__StackLimit = __StackTop - SIZEOF(.stack_dummy);
+	PROVIDE(__stack = __StackTop);
+
+	__ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ;
+
+	/* Check if data + heap + stack exceeds RAM limit */
+	ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
+}
diff --git a/variants/circuitplay/openocd_scripts/arduino_zero.cfg b/variants/hallowing_m4/openocd_scripts/arduino_zero.cfg
similarity index 100%
rename from variants/circuitplay/openocd_scripts/arduino_zero.cfg
rename to variants/hallowing_m4/openocd_scripts/arduino_zero.cfg
diff --git a/variants/hallowing_m4/pins_arduino.h b/variants/hallowing_m4/pins_arduino.h
new file mode 100644
index 000000000..db0e40c3d
--- /dev/null
+++ b/variants/hallowing_m4/pins_arduino.h
@@ -0,0 +1,21 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+// API compatibility
+#include "variant.h"
+
diff --git a/variants/hallowing_m4/variant.cpp b/variants/hallowing_m4/variant.cpp
new file mode 100644
index 000000000..8f9ab0838
--- /dev/null
+++ b/variants/hallowing_m4/variant.cpp
@@ -0,0 +1,148 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "variant.h"
+
+/*
+ * Pins descriptions
+ */
+const PinDescription g_APinDescription[]=
+{
+  // 0..13 - Digital pins
+  // ----------------------
+  // 0/1 - SERCOM/UART (Serial1)
+  { PORTB, 12, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_12 },  // TX SERCOM 4.0
+  { PORTB, 13, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_13 },  // RX SERCOM 4.1
+
+  // 2..12
+  // Digital Low
+  { PORTB,  3, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel15, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_3 }, // D2
+  { PORTB,  2, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel14, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 }, // D3
+  { PORTA,  14, PIO_DIGITAL, PIN_ATTR_PWM_E, No_ADC_Channel, TC3_CH0, TC3_CH0, EXTERNAL_INT_14 }, // D4
+  { PORTA,  16, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_0  }, // D5
+  { PORTA, 17, PIO_DIGITAL, (PIN_ATTR_DIGITAL), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_1 }, // D6 
+  { PORTB,  15, PIO_DIGITAL, PIN_ATTR_PWM_F, No_ADC_Channel, TCC4_CH0, TC5_CH0, EXTERNAL_INT_15 }, // D7 (LISIRQ)
+
+  // Digital High
+
+  { PORTB,  16, PIO_DIGITAL, PIN_ATTR_PWM_G, No_ADC_Channel, TCC0_CH4, NOT_ON_TIMER, EXTERNAL_INT_0 }, // D8 (NEOPIX)
+  { PORTA,  18, PIO_SERCOM, PIO_SERCOM, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2  }, // D9
+  { PORTA,  19, PIO_DIGITAL, PIN_ATTR_PWM_E, No_ADC_Channel, TC3_CH1, TC3_CH1,  EXTERNAL_INT_3 }, // D10
+  { PORTA,  20, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER,  EXTERNAL_INT_4 }, // D11
+  { PORTA,  21, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER,  EXTERNAL_INT_5 }, // D12
+
+  // 13 (LED)
+  { PORTA, 23, PIO_SERCOM, PIN_ATTR_PWM_G, No_ADC_Channel, TCC0_CH3, TC4_CH1, EXTERNAL_INT_7 }, 
+
+
+  // 14..23 - Analog pins
+  // --------------------
+  { PORTA,  2, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel0, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 }, // A0 (DAC0)
+  { PORTA,  5, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel5, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_5 }, // A1 (DAC1)
+  { PORTA,  6, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel6, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_6 }, // A2
+  { PORTB,  9, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel3, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_9 }, // A3
+  { PORTB,  8, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel2, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_8 }, // A4
+  { PORTA,  4, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel4, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_4 }, // A5
+
+  { PORTB,  1, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel13, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_1 },  // A6, D20 - vbatt
+  { PORTB,  4, PIO_ANALOG, PIN_ATTR_ANALOG_ALT, ADC_Channel6, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_4 },  // A7, D21 - Light
+  { PORTB,  3, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel15, NOT_ON_PWM,  NOT_ON_TIMER, EXTERNAL_INT_3 }, // A8 / D2
+  { PORTB,  2, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel14, NOT_ON_PWM,  NOT_ON_TIMER, EXTERNAL_INT_2 }, // A9 / D3
+
+  // 24..25 I2C pins (SDA/SCL)
+  // ----------------------
+  { PORTA,  12, PIO_SERCOM, PIN_ATTR_PWM_E, No_ADC_Channel, TC2_CH0, TC2_CH0,  EXTERNAL_INT_12 }, // SDA
+  { PORTA,  13, PIO_SERCOM, PIN_ATTR_PWM_E, No_ADC_Channel, TC2_CH1, TC2_CH1,  EXTERNAL_INT_13 }, // SCL
+
+
+  // 26..28 - SPI pins (MISO,MOSI,SCK)
+  // ----------------------
+  { PORTB, 22, PIO_SERCOM_ALT, (PIN_ATTR_DIGITAL), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_6 }, // MISO: SERCOM5.2
+  { PORTB, 23, PIO_SERCOM_ALT, (PIN_ATTR_DIGITAL), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_7 }, // MOSI: SERCOM5.3
+  { PORTA, 22, PIO_SERCOM_ALT, PIN_ATTR_PWM_G, No_ADC_Channel, TCC0_CH2, TC4_CH0, EXTERNAL_INT_6 }, // SCK: SERCOM 5.1
+
+  // 29..31 - USB
+  // --------------------
+  { NOT_A_PORT, PIN_NOT_A_PIN, PIO_NOT_A_PIN, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB Host enable DOES NOT EXIST ON THIS BOARD
+  { PORTA, 24, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB/DM
+  { PORTA, 25, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB/DP
+
+  // 32 (AREF)
+  { PORTA, 3, PIO_ANALOG, PIN_ATTR_ANALOG, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // DAC/VREFP
+
+  // ----------------------
+  // 33..34 - Alternate use of A0 (DAC output)
+  { PORTA,  2, PIO_ANALOG, PIN_ATTR_ANALOG, DAC_Channel0, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // DAC/VOUT0
+  { PORTA,  5, PIO_ANALOG, PIN_ATTR_ANALOG, DAC_Channel1, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // DAC/VOUT1
+
+  // ----------------------
+  // 35..40 QSPI (SCK, CS, IO0, IO1, IO2, IO3)
+  { PORTB, 10, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+  { PORTB, 11, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+  { PORTA, 8, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+  { PORTA, 9, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+  { PORTA, 10, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+  { PORTA, 11, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+
+
+  // 41..46 - TFT SPI port + control pins
+  // --------------------
+  { PORTA,  0, PIO_SERCOM_ALT, PIN_ATTR_PWM_E, No_ADC_Channel, TC2_CH0, TC2_CH0, EXTERNAL_INT_0 },         // D41 TFT MOSI (SERCOM1.0)
+  { PORTA,  1, PIO_SERCOM_ALT, PIN_ATTR_PWM_E, No_ADC_Channel, TC2_CH1, TC2_CH1, EXTERNAL_INT_1 },         // D42 TFT SCK (SERCOM1.1)
+  { NOT_A_PORT, PIN_NOT_A_PIN, PIO_NOT_A_PIN, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // D43 TFT MISO (unused)
+  { PORTA, 27, PIO_DIGITAL, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },  // D44 TFT CS
+  { PORTB, 31, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_15 }, // D45 TFT DC
+  { PORTB, 30, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_14 }, // D46 TFT RST
+
+  { PORTB, 14, PIO_DIGITAL, PIN_ATTR_PWM_G, No_ADC_Channel, TCC0_CH2, NOT_ON_TIMER, EXTERNAL_INT_15 },  // D47 Backlight (not connected rev B)
+
+
+  { PORTA, 15, PIO_DIGITAL, PIN_ATTR_PWM_E, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_15  }, // D48 - Cap Pin
+  { PORTB,  5, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_5 },  // D49 Speaker enable
+
+} ;
+
+const void* g_apTCInstances[TCC_INST_NUM+TC_INST_NUM]={ TCC0, TCC1, TCC2, TCC3, TCC4, TC0, TC1, TC2, TC3, TC4, TC5 } ;
+const uint32_t GCLK_CLKCTRL_IDs[TCC_INST_NUM+TC_INST_NUM] = { TCC0_GCLK_ID, TCC1_GCLK_ID, TCC2_GCLK_ID, TCC3_GCLK_ID, TCC4_GCLK_ID, TC0_GCLK_ID, TC1_GCLK_ID, TC2_GCLK_ID, TC3_GCLK_ID, TC4_GCLK_ID, TC5_GCLK_ID } ;
+
+// Multi-serial objects instantiation
+SERCOM sercom0( SERCOM0 ) ;
+SERCOM sercom1( SERCOM1 ) ;
+SERCOM sercom2( SERCOM2 ) ;
+SERCOM sercom3( SERCOM3 ) ;
+SERCOM sercom4( SERCOM4 ) ;
+SERCOM sercom5( SERCOM5 ) ;
+
+Uart Serial1( &sercom4, PIN_SERIAL1_RX, PIN_SERIAL1_TX, PAD_SERIAL1_RX, PAD_SERIAL1_TX ) ;
+
+void SERCOM4_0_Handler()
+{
+  Serial1.IrqHandler();
+}
+void SERCOM4_1_Handler()
+{
+  Serial1.IrqHandler();
+}
+void SERCOM4_2_Handler()
+{
+  Serial1.IrqHandler();
+}
+void SERCOM4_3_Handler()
+{
+  Serial1.IrqHandler();
+}
diff --git a/variants/hallowing_m4/variant.h b/variants/hallowing_m4/variant.h
new file mode 100644
index 000000000..221821d59
--- /dev/null
+++ b/variants/hallowing_m4/variant.h
@@ -0,0 +1,254 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _VARIANT_HALLOWING_M4_
+#define _VARIANT_HALLOWING_M4_
+
+// The definitions here needs a SAMD core >=1.6.10
+#define ARDUINO_SAMD_VARIANT_COMPLIANCE 10610
+
+/*----------------------------------------------------------------------------
+ *        Definitions
+ *----------------------------------------------------------------------------*/
+
+/** Frequency of the board main oscillator */
+#define VARIANT_MAINOSC		(32768ul)
+
+/** Master clock frequency */
+#define VARIANT_MCK	   (F_CPU)
+
+#define VARIANT_GCLK0_FREQ (F_CPU)
+#define VARIANT_GCLK1_FREQ (48000000UL)
+#define VARIANT_GCLK2_FREQ (100000000UL)
+
+/*----------------------------------------------------------------------------
+ *        Headers
+ *----------------------------------------------------------------------------*/
+
+#include "WVariant.h"
+
+#ifdef __cplusplus
+#include "SERCOM.h"
+#include "Uart.h"
+#endif // __cplusplus
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif // __cplusplus
+
+/*----------------------------------------------------------------------------
+ *        Pins
+ *----------------------------------------------------------------------------*/
+
+// Number of pins defined in PinDescription array
+#define PINS_COUNT           (50u)
+#define NUM_DIGITAL_PINS     (50u)
+#define NUM_ANALOG_INPUTS    (10u)
+#define NUM_ANALOG_OUTPUTS   (2u)
+#define analogInputToDigitalPin(p)  ((p < 6u) ? (p) + 14u : -1)
+
+#define digitalPinToPort(P)        ( &(PORT->Group[g_APinDescription[P].ulPort]) )
+#define digitalPinToBitMask(P)     ( 1 << g_APinDescription[P].ulPin )
+//#define analogInPinToBit(P)        ( )
+#define portOutputRegister(port)   ( &(port->OUT.reg) )
+#define portInputRegister(port)    ( &(port->IN.reg) )
+#define portModeRegister(port)     ( &(port->DIR.reg) )
+#define digitalPinHasPWM(P)        ( g_APinDescription[P].ulPWMChannel != NOT_ON_PWM || g_APinDescription[P].ulTCChannel != NOT_ON_TIMER )
+
+/*
+ * digitalPinToTimer(..) is AVR-specific and is not defined for SAMD
+ * architecture. If you need to check if a pin supports PWM you must
+ * use digitalPinHasPWM(..).
+ *
+ * https://github.com/arduino/Arduino/issues/1833
+ */
+// #define digitalPinToTimer(P)
+
+// LEDs
+#define PIN_LED_13           (13u)
+#define PIN_LED              PIN_LED_13
+#define LED_BUILTIN          PIN_LED_13
+
+/*
+ * Analog pins
+ */
+#define PIN_A0               (14ul)
+#define PIN_A1               (PIN_A0 + 1)
+#define PIN_A2               (PIN_A0 + 2)
+#define PIN_A3               (PIN_A0 + 3)
+#define PIN_A4               (PIN_A0 + 4)
+#define PIN_A5               (PIN_A0 + 5)
+#define PIN_A6               (PIN_A0 + 6)
+#define PIN_A7               (PIN_A0 + 7)
+#define PIN_A8               (PIN_A0 + 8)
+#define PIN_A9               (PIN_A0 + 9)
+
+#define PIN_DAC0             PIN_A0
+#define PIN_DAC1             PIN_A1
+
+static const uint8_t A0  = PIN_A0;
+static const uint8_t A1  = PIN_A1;
+static const uint8_t A2  = PIN_A2;
+static const uint8_t A3  = PIN_A3;
+static const uint8_t A4  = PIN_A4;
+static const uint8_t A5  = PIN_A5;
+static const uint8_t A6  = PIN_A6;
+static const uint8_t A7  = PIN_A7;
+static const uint8_t A8  = PIN_A8;
+static const uint8_t A9  = PIN_A9;
+
+static const uint8_t DAC0 = PIN_DAC0;
+static const uint8_t DAC1 = PIN_DAC1;
+
+#define ADC_RESOLUTION		12
+
+/*
+ * Serial interfaces
+ */
+
+// Serial1
+#define PIN_SERIAL1_RX       (0ul)
+#define PIN_SERIAL1_TX       (1ul)
+#define PAD_SERIAL1_RX       (SERCOM_RX_PAD_1)
+#define PAD_SERIAL1_TX       (UART_TX_PAD_0)
+
+/*
+ * SPI Interfaces
+ */
+#define SPI_INTERFACES_COUNT 2
+
+#define PIN_SPI_MISO         (26u)
+#define PIN_SPI_MOSI         (27u)
+#define PIN_SPI_SCK          (28u)
+#define PERIPH_SPI           sercom5
+#define PAD_SPI_TX           SPI_PAD_3_SCK_1
+#define PAD_SPI_RX           SERCOM_RX_PAD_2
+
+static const uint8_t SS	  = 10 ;
+static const uint8_t MOSI = PIN_SPI_MOSI ;
+static const uint8_t MISO = PIN_SPI_MISO ;
+static const uint8_t SCK  = PIN_SPI_SCK ;
+
+  // Internal SPI for TFT
+#define PIN_SPI1_MOSI         (41u)
+#define PIN_SPI1_SCK          (42u)
+#define PIN_SPI1_MISO         (43u)
+#define PERIPH_SPI1           sercom1
+#define PAD_SPI1_TX           SPI_PAD_0_SCK_1
+#define PAD_SPI1_RX           SERCOM_RX_PAD_2
+
+static const uint8_t SS1    = 44 ;
+static const uint8_t MOSI1  = PIN_SPI1_MOSI ;
+static const uint8_t MISO1  = PIN_SPI1_MISO ;
+static const uint8_t SCK1   = PIN_SPI1_SCK ;
+
+/*
+ * Wire Interfaces
+ */
+#define WIRE_INTERFACES_COUNT 1
+
+#define PIN_WIRE_SDA         (24u)
+#define PIN_WIRE_SCL         (25u)
+#define PERIPH_WIRE          sercom2
+#define WIRE_IT_HANDLER      SERCOM2_Handler
+#define WIRE_IT_HANDLER_0    SERCOM2_0_Handler
+#define WIRE_IT_HANDLER_1    SERCOM2_1_Handler
+#define WIRE_IT_HANDLER_2    SERCOM2_2_Handler
+#define WIRE_IT_HANDLER_3    SERCOM2_3_Handler
+
+static const uint8_t SDA = PIN_WIRE_SDA;
+static const uint8_t SCL = PIN_WIRE_SCL;
+
+/*
+ * USB
+ */
+#define PIN_USB_HOST_ENABLE (29ul)
+#define PIN_USB_DM          (30ul)
+#define PIN_USB_DP          (31ul)
+
+/*
+ * I2S Interfaces
+ */
+#define I2S_INTERFACES_COUNT 0
+
+// On-board QSPI Flash
+#define EXTERNAL_FLASH_DEVICES   GD25Q16C
+#define EXTERNAL_FLASH_USE_QSPI
+
+//QSPI Pins
+#define PIN_QSPI_SCK    (35u)
+#define PIN_QSPI_CS     (36u)
+#define PIN_QSPI_IO0    (37u)
+#define PIN_QSPI_IO1    (38u)
+#define PIN_QSPI_IO2    (39u)
+#define PIN_QSPI_IO3    (40u)
+
+#if !defined(VARIANT_QSPI_BAUD_DEFAULT)
+  // TODO: meaningful value for this
+  #define VARIANT_QSPI_BAUD_DEFAULT 5000000
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+ *        Arduino objects - C++ only
+ *----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+
+/*	=========================
+ *	===== SERCOM DEFINITION
+ *	=========================
+*/
+extern SERCOM sercom0;
+extern SERCOM sercom1;
+extern SERCOM sercom2;
+extern SERCOM sercom3;
+extern SERCOM sercom4;
+extern SERCOM sercom5;
+
+extern Uart Serial1;
+
+#endif
+
+// These serial port names are intended to allow libraries and architecture-neutral
+// sketches to automatically default to the correct port name for a particular type
+// of use.  For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN,
+// the first hardware serial port whose RX/TX pins are not dedicated to another use.
+//
+// SERIAL_PORT_MONITOR        Port which normally prints to the Arduino Serial Monitor
+//
+// SERIAL_PORT_USBVIRTUAL     Port which is USB virtual serial
+//
+// SERIAL_PORT_LINUXBRIDGE    Port which connects to a Linux system via Bridge library
+//
+// SERIAL_PORT_HARDWARE       Hardware serial port, physical RX & TX pins.
+//
+// SERIAL_PORT_HARDWARE_OPEN  Hardware serial ports which are open for use.  Their RX & TX
+//                            pins are NOT connected to anything by default.
+#define SERIAL_PORT_USBVIRTUAL      Serial
+#define SERIAL_PORT_MONITOR         Serial
+// Serial has no physical pins broken out, so it's not listed as HARDWARE port
+#define SERIAL_PORT_HARDWARE        Serial1
+#define SERIAL_PORT_HARDWARE_OPEN   Serial1
+
+#endif /* _VARIANT_HALLOWING_M4_ */
+
diff --git a/variants/itsybitsy_m0/debug_scripts/variant.gdb b/variants/itsybitsy_m0/debug_scripts/variant.gdb
new file mode 100644
index 000000000..3c37ffde2
--- /dev/null
+++ b/variants/itsybitsy_m0/debug_scripts/variant.gdb
@@ -0,0 +1,31 @@
+#
+#  Arduino Zero OpenOCD script.
+#
+#  Copyright (c) 2014-2015 Arduino LLC. All right reserved.
+#
+#  This library is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 2.1 of the License, or (at your option) any later version.
+#
+#  This library is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#  See the GNU Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library; if not, write to the Free Software
+#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#
+
+# Define 'reset' command
+define reset
+
+info reg
+
+break main
+
+# End of 'reset' command
+end
+
+target remote | openocd -c "interface cmsis-dap" -c "set CHIPNAME at91samd21g18" -f target/at91samdXX.cfg -c "gdb_port pipe; log_output openocd.log"
diff --git a/variants/mkrwifi1010/linker_scripts/gcc/flash_with_bootloader.ld b/variants/itsybitsy_m0/linker_scripts/gcc/flash_with_bootloader.ld
similarity index 99%
rename from variants/mkrwifi1010/linker_scripts/gcc/flash_with_bootloader.ld
rename to variants/itsybitsy_m0/linker_scripts/gcc/flash_with_bootloader.ld
index 5c0dcb4e0..357946455 100644
--- a/variants/mkrwifi1010/linker_scripts/gcc/flash_with_bootloader.ld
+++ b/variants/itsybitsy_m0/linker_scripts/gcc/flash_with_bootloader.ld
@@ -83,7 +83,6 @@ SECTIONS
 		*(SORT(.ctors.*))
 		*(.ctors)
 
-
 		/* .dtors */
  		*crtbegin.o(.dtors)
  		*crtbegin?.o(.dtors)
diff --git a/variants/itsybitsy_m0/linker_scripts/gcc/flash_without_bootloader.ld b/variants/itsybitsy_m0/linker_scripts/gcc/flash_without_bootloader.ld
new file mode 100644
index 000000000..ebeeee37f
--- /dev/null
+++ b/variants/itsybitsy_m0/linker_scripts/gcc/flash_without_bootloader.ld
@@ -0,0 +1,214 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* Linker script to configure memory regions.
+ * Need modifying for a specific board.
+ *   FLASH.ORIGIN: starting address of flash
+ *   FLASH.LENGTH: length of flash
+ *   RAM.ORIGIN: starting address of RAM bank 0
+ *   RAM.LENGTH: length of RAM bank 0
+ */
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00040000
+  RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ *   Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ *   __exidx_start
+ *   __exidx_end
+ *   __copy_table_start__
+ *   __copy_table_end__
+ *   __zero_table_start__
+ *   __zero_table_end__
+ *   __etext
+ *   __data_start__
+ *   __preinit_array_start
+ *   __preinit_array_end
+ *   __init_array_start
+ *   __init_array_end
+ *   __fini_array_start
+ *   __fini_array_end
+ *   __data_end__
+ *   __bss_start__
+ *   __bss_end__
+ *   __end__
+ *   end
+ *   __HeapLimit
+ *   __StackLimit
+ *   __StackTop
+ *   __stack
+ *   __ram_end__
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+	.text :
+	{
+		__text_start__ = .;
+
+		KEEP(*(.isr_vector))
+		*(.text*)
+
+		KEEP(*(.init))
+		KEEP(*(.fini))
+
+		/* .ctors */
+		*crtbegin.o(.ctors)
+		*crtbegin?.o(.ctors)
+		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+		*(SORT(.ctors.*))
+		*(.ctors)
+
+		/* .dtors */
+ 		*crtbegin.o(.dtors)
+ 		*crtbegin?.o(.dtors)
+ 		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ 		*(SORT(.dtors.*))
+ 		*(.dtors)
+
+		*(.rodata*)
+
+		KEEP(*(.eh_frame*))
+	} > FLASH
+
+	.ARM.extab :
+	{
+		*(.ARM.extab* .gnu.linkonce.armextab.*)
+	} > FLASH
+
+	__exidx_start = .;
+	.ARM.exidx :
+	{
+		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
+	} > FLASH
+	__exidx_end = .;
+
+	/* To copy multiple ROM to RAM sections,
+	 * uncomment .copy.table section and,
+	 * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.copy.table :
+	{
+		. = ALIGN(4);
+		__copy_table_start__ = .;
+		LONG (__etext)
+		LONG (__data_start__)
+		LONG (__data_end__ - __data_start__)
+		LONG (__etext2)
+		LONG (__data2_start__)
+		LONG (__data2_end__ - __data2_start__)
+		__copy_table_end__ = .;
+	} > FLASH
+	*/
+
+	/* To clear multiple BSS sections,
+	 * uncomment .zero.table section and,
+	 * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.zero.table :
+	{
+		. = ALIGN(4);
+		__zero_table_start__ = .;
+		LONG (__bss_start__)
+		LONG (__bss_end__ - __bss_start__)
+		LONG (__bss2_start__)
+		LONG (__bss2_end__ - __bss2_start__)
+		__zero_table_end__ = .;
+	} > FLASH
+	*/
+
+	__etext = .;
+
+	.data : AT (__etext)
+	{
+		__data_start__ = .;
+		*(vtable)
+		*(.data*)
+
+		. = ALIGN(4);
+		/* preinit data */
+		PROVIDE_HIDDEN (__preinit_array_start = .);
+		KEEP(*(.preinit_array))
+		PROVIDE_HIDDEN (__preinit_array_end = .);
+
+		. = ALIGN(4);
+		/* init data */
+		PROVIDE_HIDDEN (__init_array_start = .);
+		KEEP(*(SORT(.init_array.*)))
+		KEEP(*(.init_array))
+		PROVIDE_HIDDEN (__init_array_end = .);
+
+
+		. = ALIGN(4);
+		/* finit data */
+		PROVIDE_HIDDEN (__fini_array_start = .);
+		KEEP(*(SORT(.fini_array.*)))
+		KEEP(*(.fini_array))
+		PROVIDE_HIDDEN (__fini_array_end = .);
+
+		KEEP(*(.jcr*))
+		. = ALIGN(16);
+		/* All data end */
+		__data_end__ = .;
+
+	} > RAM
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start__ = .;
+		*(.bss*)
+		*(COMMON)
+		. = ALIGN(4);
+		__bss_end__ = .;
+	} > RAM
+
+	.heap (COPY):
+	{
+		__end__ = .;
+		PROVIDE(end = .);
+		*(.heap*)
+		__HeapLimit = .;
+	} > RAM
+
+	/* .stack_dummy section doesn't contains any symbols. It is only
+	 * used for linker to calculate size of stack sections, and assign
+	 * values to stack symbols later */
+	.stack_dummy (COPY):
+	{
+		*(.stack*)
+	} > RAM
+
+	/* Set stack top to end of RAM, and stack limit move down by
+	 * size of stack_dummy section */
+	__StackTop = ORIGIN(RAM) + LENGTH(RAM) ;
+	__StackLimit = __StackTop - SIZEOF(.stack_dummy);
+	PROVIDE(__stack = __StackTop);
+
+	__ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ;
+
+	/* Check if data + heap + stack exceeds RAM limit */
+	ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
+}
diff --git a/variants/itsybitsy_m0/openocd_scripts/itsybitsy_m0.cfg b/variants/itsybitsy_m0/openocd_scripts/itsybitsy_m0.cfg
new file mode 100644
index 000000000..bdb6fd94c
--- /dev/null
+++ b/variants/itsybitsy_m0/openocd_scripts/itsybitsy_m0.cfg
@@ -0,0 +1,28 @@
+#
+#  Adafruit ItsyBitsy M0 OpenOCD script.
+#
+#  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+#
+#  This library is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 2.1 of the License, or (at your option) any later version.
+#
+#  This library is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#  See the GNU Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library; if not, write to the Free Software
+#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#
+
+# chip name
+set CHIPNAME at91samd21g18
+set ENDIAN little
+
+# choose a port here
+set telnet_port 0
+
+source [find target/at91samdXX.cfg]
diff --git a/variants/itsybitsy_m0/pins_arduino.h b/variants/itsybitsy_m0/pins_arduino.h
new file mode 100644
index 000000000..db0e40c3d
--- /dev/null
+++ b/variants/itsybitsy_m0/pins_arduino.h
@@ -0,0 +1,21 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+// API compatibility
+#include "variant.h"
+
diff --git a/variants/itsybitsy_m0/variant.cpp b/variants/itsybitsy_m0/variant.cpp
new file mode 100644
index 000000000..fa35301d7
--- /dev/null
+++ b/variants/itsybitsy_m0/variant.cpp
@@ -0,0 +1,126 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "variant.h"
+
+/*
+ * Pins descriptions
+ */
+const PinDescription g_APinDescription[]=
+{
+  // 0..13 - Digital pins
+  // ----------------------
+  // 0/1 - SERCOM/UART (Serial1)
+  { PORTA, 11, PIO_SERCOM, (PIN_ATTR_DIGITAL), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_11 }, // RX: SERCOM0/PAD[3]
+  { PORTA, 10, PIO_SERCOM, (PIN_ATTR_DIGITAL), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_10 }, // TX: SERCOM0/PAD[2]
+
+  // 2..12
+  // Digital Low
+  { PORTA, 14, PIO_DIGITAL, (PIN_ATTR_DIGITAL), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_14 },
+  { PORTA,  9, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM0_CH1, TCC0_CH1, EXTERNAL_INT_9 }, // TCC0/WO[1]
+  { PORTA,  8, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM0_CH0, TCC0_CH0, EXTERNAL_INT_NMI },  // TCC0/WO[0]
+  { PORTA, 15, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM3_CH1, TC3_CH1, EXTERNAL_INT_15 }, // TC3/WO[1]
+  { PORTA, 20, PIO_TIMER_ALT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER_ALT), No_ADC_Channel, PWM0_CH6, TCC0_CH6, EXTERNAL_INT_4 }, // TCC0/WO[6]
+  { PORTA, 21, PIO_DIGITAL, (PIN_ATTR_DIGITAL), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_5 },
+
+  // Digital High
+  { PORTA,  6, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel6, PWM1_CH0, TCC1_CH0, EXTERNAL_INT_6 }, // TCC1/WO[0]
+  { PORTA,  7, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel7, PWM1_CH1, TCC1_CH1, EXTERNAL_INT_7 }, // TCC1/WO[1]
+  { PORTA, 18, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM3_CH0, TC3_CH0, EXTERNAL_INT_2 }, // TC3/WO[0]
+  { PORTA, 16, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM2_CH0, TCC2_CH0, EXTERNAL_INT_0 }, // TCC2/WO[0]
+  { PORTA, 19, PIO_TIMER_ALT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER_ALT), No_ADC_Channel, PWM0_CH3, TCC0_CH3, EXTERNAL_INT_3 }, // TCC0/WO[3]
+
+  // 13 (LED)
+  { PORTA, 17, PIO_PWM, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM2_CH1, TCC2_CH1, EXTERNAL_INT_1 }, // TCC2/WO[1]
+
+  // 14..19 - Analog pins
+  // --------------------
+  { PORTA,  2, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel0, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 }, // ADC/AIN[0]
+  { PORTB,  8, PIO_ANALOG, (PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel2, PWM4_CH0, TC4_CH0, EXTERNAL_INT_8 }, // ADC/AIN[2]
+  { PORTB,  9, PIO_ANALOG, (PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel3, PWM4_CH1, TC4_CH1, EXTERNAL_INT_9 }, // ADC/AIN[3]
+  { PORTA,  4, PIO_ANALOG, 0, ADC_Channel4, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_4 }, // ADC/AIN[4]
+  { PORTA,  5, PIO_ANALOG, 0, ADC_Channel5, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_5 }, // ADC/AIN[5]
+  { PORTB,  2, PIO_ANALOG, 0, ADC_Channel10, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 }, // ADC/AIN[10]
+
+  // Extra Analog pins! 20..25
+  { PORTA, 11, PIO_ANALOG, (PIN_ATTR_DIGITAL|PIN_ATTR_ANALOG), ADC_Channel19, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_11 }, // A6 same as D0
+  { PORTA, 10, PIO_ANALOG, (PIN_ATTR_DIGITAL|PIN_ATTR_ANALOG), ADC_Channel18, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_10 }, // A7 same as D1
+  { PORTA,  8, PIO_ANALOG, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER|PIN_ATTR_ANALOG), ADC_Channel16, PWM0_CH0, TCC0_CH0, EXTERNAL_INT_NMI },  // A8 same as D4
+  { PORTA,  9, PIO_ANALOG, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER|PIN_ATTR_ANALOG), ADC_Channel17, PWM0_CH1, TCC0_CH1, EXTERNAL_INT_9 },    // A9 same as D3
+  { PORTA,  6, PIO_ANALOG, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER|PIN_ATTR_ANALOG), ADC_Channel6, PWM1_CH0, TCC1_CH0, EXTERNAL_INT_6 }, // A10 (unavailable)
+  { PORTA,  7, PIO_ANALOG, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER|PIN_ATTR_ANALOG), ADC_Channel7, PWM1_CH1, TCC1_CH1, EXTERNAL_INT_7 }, // A11 same as D9
+
+  // 26..27 I2C pins (SDA/SCL and also EDBG:SDA/SCL)
+  // ----------------------
+  { PORTA, 22, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_6 }, // SDA: SERCOM3/PAD[0]
+  { PORTA, 23, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_7 }, // SCL: SERCOM3/PAD[1]
+
+  // 28..30 - SPI pins (ICSP:MISO,SCK,MOSI)
+  // ----------------------
+  { PORTA, 12, PIO_SERCOM_ALT, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_12 }, // MISO: SERCOM4/PAD[0]
+  { PORTB, 10, PIO_SERCOM_ALT, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_10 }, // MOSI: SERCOM4/PAD[2]
+  { PORTB, 11, PIO_SERCOM_ALT, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_11 }, // SCK: SERCOM4/PAD[3]
+
+  // 31..32 - RX/TX LEDS (PA31/PA28) (unused)
+  // --------------------
+  { PORTA, 31, PIO_OUTPUT, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // used as output only
+  { PORTA, 28, PIO_OUTPUT, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // used as output only
+
+  // 33..35 - USB
+  // --------------------
+  { PORTA, 28, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB Host enable
+  { PORTA, 24, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB/DM
+  { PORTA, 25, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB/DP
+
+  // 36..38 - Secondary SPI
+  // ----------------------
+  { PORTB, 03, PIO_SERCOM_ALT, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },  // SPI Flash MISO
+  { PORTB, 22, PIO_SERCOM_ALT, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },  // SPI FLash MOSI
+  { PORTB, 23, PIO_SERCOM_ALT, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },  // SPI FLash SCK
+  // 39 Secondary SPI SS
+  { PORTA, 27, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_15 }, // SPI Flash SS
+
+  // 40 & 41 - internal DotStar
+  { PORTA, 0, PIO_DIGITAL, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // Dotstar Clock
+  { PORTA, 1, PIO_DIGITAL, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // Dotstar Data
+
+  // 42 (AREF)
+  { PORTA, 3, PIO_ANALOG, PIN_ATTR_ANALOG, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // DAC/VREFP
+
+  // ----------------------
+  // 43 - Alternate use of A0 (DAC output)
+  { PORTA,  2, PIO_ANALOG, PIN_ATTR_ANALOG, DAC_Channel0, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 }, // DAC/VOUT
+} ;
+
+const void* g_apTCInstances[TCC_INST_NUM+TC_INST_NUM]={ TCC0, TCC1, TCC2, TC3, TC4, TC5 } ;
+
+// Multi-serial objects instantiation
+SERCOM sercom0( SERCOM0 ) ;
+SERCOM sercom1( SERCOM1 ) ;
+SERCOM sercom2( SERCOM2 ) ;
+SERCOM sercom3( SERCOM3 ) ;
+SERCOM sercom4( SERCOM4 ) ;
+SERCOM sercom5( SERCOM5 ) ;
+
+Uart Serial1( &sercom0, PIN_SERIAL1_RX, PIN_SERIAL1_TX, PAD_SERIAL1_RX, PAD_SERIAL1_TX ) ;
+
+void SERCOM0_Handler()
+{
+  Serial1.IrqHandler();
+}
+
diff --git a/variants/itsybitsy_m0/variant.h b/variants/itsybitsy_m0/variant.h
new file mode 100644
index 000000000..8180c919b
--- /dev/null
+++ b/variants/itsybitsy_m0/variant.h
@@ -0,0 +1,245 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _VARIANT_ITSYBITSY_ZERO_
+#define _VARIANT_ITSYBITSY_ZERO_
+
+// The definitions here needs a SAMD core >=1.6.10
+#define ARDUINO_SAMD_VARIANT_COMPLIANCE 10610
+
+/*----------------------------------------------------------------------------
+ *        Definitions
+ *----------------------------------------------------------------------------*/
+
+/** Frequency of the board main oscillator */
+#define VARIANT_MAINOSC		(32768ul)
+
+/** Master clock frequency */
+#define VARIANT_MCK	(F_CPU)
+
+/*----------------------------------------------------------------------------
+ *        Headers
+ *----------------------------------------------------------------------------*/
+
+#include "WVariant.h"
+
+#ifdef __cplusplus
+#include "SERCOM.h"
+#include "Uart.h"
+#endif // __cplusplus
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif // __cplusplus
+
+/*----------------------------------------------------------------------------
+ *        Pins
+ *----------------------------------------------------------------------------*/
+
+// Number of pins defined in PinDescription array
+#define PINS_COUNT           (26u)
+#define NUM_DIGITAL_PINS     (20u)
+#define NUM_ANALOG_INPUTS    (12u)
+#define NUM_ANALOG_OUTPUTS   (1u)
+#define analogInputToDigitalPin(p)  ((p < 12u) ? (p) + PIN_A0 : -1)
+
+#define digitalPinToPort(P)        ( &(PORT->Group[g_APinDescription[P].ulPort]) )
+#define digitalPinToBitMask(P)     ( 1 << g_APinDescription[P].ulPin )
+//#define analogInPinToBit(P)        ( )
+#define portOutputRegister(port)   ( &(port->OUT.reg) )
+#define portInputRegister(port)    ( &(port->IN.reg) )
+#define portModeRegister(port)     ( &(port->DIR.reg) )
+#define digitalPinHasPWM(P)        ( g_APinDescription[P].ulPWMChannel != NOT_ON_PWM || g_APinDescription[P].ulTCChannel != NOT_ON_TIMER )
+
+/*
+ * digitalPinToTimer(..) is AVR-specific and is not defined for SAMD
+ * architecture. If you need to check if a pin supports PWM you must
+ * use digitalPinHasPWM(..).
+ *
+ * https://github.com/arduino/Arduino/issues/1833
+ */
+// #define digitalPinToTimer(P)
+
+// LEDs
+#define PIN_LED_13           (13u)
+#define PIN_LED              PIN_LED_13
+#define LED_BUILTIN          PIN_LED_13
+
+/*
+ * Analog pins
+ */
+#define PIN_A0               (14ul)
+#define PIN_A1               (PIN_A0 + 1)
+#define PIN_A2               (PIN_A0 + 2)
+#define PIN_A3               (PIN_A0 + 3)
+#define PIN_A4               (PIN_A0 + 4)
+#define PIN_A5               (PIN_A0 + 5)
+#define PIN_A6               (PIN_A0 + 6)
+#define PIN_A7               (PIN_A0 + 7)
+#define PIN_A8               (PIN_A0 + 8)
+#define PIN_A9               (PIN_A0 + 9)
+#define PIN_A10              (PIN_A0 + 10)
+#define PIN_A11              (PIN_A0 + 11)
+#define PIN_A12              (42ul)
+#define PIN_DAC0             (14ul)
+
+static const uint8_t A0  = PIN_A0;
+static const uint8_t A1  = PIN_A1;
+static const uint8_t A2  = PIN_A2;
+static const uint8_t A3  = PIN_A3;
+static const uint8_t A4  = PIN_A4;
+static const uint8_t A5  = PIN_A5;
+static const uint8_t A6  = PIN_A6 ;
+static const uint8_t A7  = PIN_A7 ;
+static const uint8_t A8  = PIN_A8 ;
+static const uint8_t A9  = PIN_A9 ;
+static const uint8_t A10 = PIN_A10 ;
+static const uint8_t A11 = PIN_A11 ;
+static const uint8_t A12 = PIN_A12 ;
+static const uint8_t DAC0 = PIN_DAC0;
+
+#define ADC_RESOLUTION		12
+
+// Other pins
+#define PIN_ATN              (38ul)
+static const uint8_t ATN = PIN_ATN;
+
+// On-board SPI Flash
+#define EXTERNAL_FLASH_DEVICES  GD25Q16C
+#define EXTERNAL_FLASH_USE_SPI  SPI1
+#define EXTERNAL_FLASH_USE_CS   SS1
+
+/*
+ * Serial interfaces
+ */
+
+// Serial1
+#define PIN_SERIAL1_RX       (0ul)
+#define PIN_SERIAL1_TX       (1ul)
+#define PAD_SERIAL1_TX       (UART_TX_PAD_2)
+#define PAD_SERIAL1_RX       (SERCOM_RX_PAD_3)
+
+/*
+ * SPI Interfaces
+ */
+#define SPI_INTERFACES_COUNT 2
+
+#define PIN_SPI_MISO         (28u)
+#define PIN_SPI_MOSI         (29u)
+#define PIN_SPI_SCK          (30u)
+#define PERIPH_SPI           sercom4
+#define PAD_SPI_TX           SPI_PAD_2_SCK_3
+#define PAD_SPI_RX           SERCOM_RX_PAD_0
+
+static const uint8_t SS	  = PIN_A2 ;	// SERCOM4 last PAD is present on A2 but HW SS isn't used. Set here only for reference.
+static const uint8_t MOSI = PIN_SPI_MOSI ;
+static const uint8_t MISO = PIN_SPI_MISO ;
+static const uint8_t SCK  = PIN_SPI_SCK ;
+
+
+#define PIN_SPI1_MISO         (36u)
+#define PIN_SPI1_MOSI         (37u)
+#define PIN_SPI1_SCK          (38u)
+#define PERIPH_SPI1           sercom5
+#define PAD_SPI1_TX           SPI_PAD_2_SCK_3
+#define PAD_SPI1_RX           SERCOM_RX_PAD_1
+
+static const uint8_t SS1   = 39 ;	// HW SS isn't used. Set here only for reference.
+static const uint8_t MOSI1 = PIN_SPI_MOSI ;
+static const uint8_t MISO1 = PIN_SPI_MISO ;
+static const uint8_t SCK1  = PIN_SPI_SCK ;
+
+/*
+ * Wire Interfaces
+ */
+#define WIRE_INTERFACES_COUNT 1
+
+#define PIN_WIRE_SDA         (26u)
+#define PIN_WIRE_SCL         (27u)
+#define PERIPH_WIRE          sercom3
+#define WIRE_IT_HANDLER      SERCOM3_Handler
+
+static const uint8_t SDA = PIN_WIRE_SDA;
+static const uint8_t SCL = PIN_WIRE_SCL;
+
+/*
+ * USB
+ */
+#define PIN_USB_HOST_ENABLE (33ul)
+#define PIN_USB_DM          (34ul)
+#define PIN_USB_DP          (35ul)
+/*
+ * I2S Interfaces
+ */
+#define I2S_INTERFACES_COUNT 1
+
+#define I2S_DEVICE          0
+#define I2S_CLOCK_GENERATOR 3
+#define PIN_I2S_SD          (9u)
+#define PIN_I2S_SCK         (1u)
+#define PIN_I2S_FS          (0u)
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+ *        Arduino objects - C++ only
+ *----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+
+/*	=========================
+ *	===== SERCOM DEFINITION
+ *	=========================
+*/
+extern SERCOM sercom0;
+extern SERCOM sercom1;
+extern SERCOM sercom2;
+extern SERCOM sercom3;
+extern SERCOM sercom4;
+extern SERCOM sercom5;
+
+extern Uart Serial1;
+
+#endif
+
+// These serial port names are intended to allow libraries and architecture-neutral
+// sketches to automatically default to the correct port name for a particular type
+// of use.  For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN,
+// the first hardware serial port whose RX/TX pins are not dedicated to another use.
+//
+// SERIAL_PORT_MONITOR        Port which normally prints to the Arduino Serial Monitor
+//
+// SERIAL_PORT_USBVIRTUAL     Port which is USB virtual serial
+//
+// SERIAL_PORT_LINUXBRIDGE    Port which connects to a Linux system via Bridge library
+//
+// SERIAL_PORT_HARDWARE       Hardware serial port, physical RX & TX pins.
+//
+// SERIAL_PORT_HARDWARE_OPEN  Hardware serial ports which are open for use.  Their RX & TX
+//                            pins are NOT connected to anything by default.
+#define SERIAL_PORT_USBVIRTUAL      Serial
+#define SERIAL_PORT_MONITOR         Serial
+// Serial has no physical pins broken out, so it's not listed as HARDWARE port
+#define SERIAL_PORT_HARDWARE        Serial1
+#define SERIAL_PORT_HARDWARE_OPEN   Serial1
+
+#endif /* _VARIANT_ARDUINO_ZERO_ */
+
diff --git a/variants/itsybitsy_m4/linker_scripts/gcc/flash_with_bootloader.ld b/variants/itsybitsy_m4/linker_scripts/gcc/flash_with_bootloader.ld
new file mode 100644
index 000000000..5fe575a0d
--- /dev/null
+++ b/variants/itsybitsy_m4/linker_scripts/gcc/flash_with_bootloader.ld
@@ -0,0 +1,216 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* Linker script to configure memory regions.
+ * Need modifying for a specific board.
+ *   FLASH.ORIGIN: starting address of flash
+ *   FLASH.LENGTH: length of flash
+ *   RAM.ORIGIN: starting address of RAM bank 0
+ *   RAM.LENGTH: length of RAM bank 0
+ */
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000+0x4000, LENGTH = 0x80000-0x4000 /* First 16KB used by bootloader */
+  RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x30000
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ *   Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ *   __exidx_start
+ *   __exidx_end
+ *   __copy_table_start__
+ *   __copy_table_end__
+ *   __zero_table_start__
+ *   __zero_table_end__
+ *   __etext
+ *   __data_start__
+ *   __preinit_array_start
+ *   __preinit_array_end
+ *   __init_array_start
+ *   __init_array_end
+ *   __fini_array_start
+ *   __fini_array_end
+ *   __data_end__
+ *   __bss_start__
+ *   __bss_end__
+ *   __end__
+ *   end
+ *   __HeapLimit
+ *   __StackLimit
+ *   __StackTop
+ *   __stack
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+	.text :
+	{
+		__text_start__ = .;
+
+		KEEP(*(.sketch_boot))
+
+		. = ALIGN(0x4000);
+		KEEP(*(.isr_vector))
+		*(.text*)
+
+		KEEP(*(.init))
+		KEEP(*(.fini))
+
+		/* .ctors */
+		*crtbegin.o(.ctors)
+		*crtbegin?.o(.ctors)
+		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+		*(SORT(.ctors.*))
+		*(.ctors)
+
+		/* .dtors */
+ 		*crtbegin.o(.dtors)
+ 		*crtbegin?.o(.dtors)
+ 		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ 		*(SORT(.dtors.*))
+ 		*(.dtors)
+
+		*(.rodata*)
+
+		KEEP(*(.eh_frame*))
+	} > FLASH
+
+	.ARM.extab :
+	{
+		*(.ARM.extab* .gnu.linkonce.armextab.*)
+	} > FLASH
+
+	__exidx_start = .;
+	.ARM.exidx :
+	{
+		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
+	} > FLASH
+	__exidx_end = .;
+
+	/* To copy multiple ROM to RAM sections,
+	 * uncomment .copy.table section and,
+	 * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.copy.table :
+	{
+		. = ALIGN(4);
+		__copy_table_start__ = .;
+		LONG (__etext)
+		LONG (__data_start__)
+		LONG (__data_end__ - __data_start__)
+		LONG (__etext2)
+		LONG (__data2_start__)
+		LONG (__data2_end__ - __data2_start__)
+		__copy_table_end__ = .;
+	} > FLASH
+	*/
+
+	/* To clear multiple BSS sections,
+	 * uncomment .zero.table section and,
+	 * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.zero.table :
+	{
+		. = ALIGN(4);
+		__zero_table_start__ = .;
+		LONG (__bss_start__)
+		LONG (__bss_end__ - __bss_start__)
+		LONG (__bss2_start__)
+		LONG (__bss2_end__ - __bss2_start__)
+		__zero_table_end__ = .;
+	} > FLASH
+	*/
+
+	__etext = .;
+
+	.data : AT (__etext)
+	{
+		__data_start__ = .;
+		*(vtable)
+		*(.data*)
+
+		. = ALIGN(4);
+		/* preinit data */
+		PROVIDE_HIDDEN (__preinit_array_start = .);
+		KEEP(*(.preinit_array))
+		PROVIDE_HIDDEN (__preinit_array_end = .);
+
+		. = ALIGN(4);
+		/* init data */
+		PROVIDE_HIDDEN (__init_array_start = .);
+		KEEP(*(SORT(.init_array.*)))
+		KEEP(*(.init_array))
+		PROVIDE_HIDDEN (__init_array_end = .);
+
+
+		. = ALIGN(4);
+		/* finit data */
+		PROVIDE_HIDDEN (__fini_array_start = .);
+		KEEP(*(SORT(.fini_array.*)))
+		KEEP(*(.fini_array))
+		PROVIDE_HIDDEN (__fini_array_end = .);
+
+		KEEP(*(.jcr*))
+		. = ALIGN(16);
+		/* All data end */
+		__data_end__ = .;
+
+	} > RAM
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start__ = .;
+		*(.bss*)
+		*(COMMON)
+		. = ALIGN(4);
+		__bss_end__ = .;
+	} > RAM
+
+	.heap (COPY):
+	{
+		__end__ = .;
+		PROVIDE(end = .);
+		*(.heap*)
+		__HeapLimit = .;
+	} > RAM
+
+	/* .stack_dummy section doesn't contains any symbols. It is only
+	 * used for linker to calculate size of stack sections, and assign
+	 * values to stack symbols later */
+	.stack_dummy (COPY):
+	{
+		*(.stack*)
+	} > RAM
+
+	/* Set stack top to end of RAM, and stack limit move down by
+	 * size of stack_dummy section */
+	__StackTop = ORIGIN(RAM) + LENGTH(RAM);
+	__StackLimit = __StackTop - SIZEOF(.stack_dummy);
+	PROVIDE(__stack = __StackTop);
+
+	__ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ;
+
+	/* Check if data + heap + stack exceeds RAM limit */
+	ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
+}
diff --git a/variants/itsybitsy_m4/linker_scripts/gcc/flash_without_bootloader.ld b/variants/itsybitsy_m4/linker_scripts/gcc/flash_without_bootloader.ld
new file mode 100644
index 000000000..0123a0a23
--- /dev/null
+++ b/variants/itsybitsy_m4/linker_scripts/gcc/flash_without_bootloader.ld
@@ -0,0 +1,215 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* Linker script to configure memory regions.
+ * Need modifying for a specific board.
+ *   FLASH.ORIGIN: starting address of flash
+ *   FLASH.LENGTH: length of flash
+ *   RAM.ORIGIN: starting address of RAM bank 0
+ *   RAM.LENGTH: length of RAM bank 0
+ */
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x80000
+  RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x30000
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ *   Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ *   __exidx_start
+ *   __exidx_end
+ *   __copy_table_start__
+ *   __copy_table_end__
+ *   __zero_table_start__
+ *   __zero_table_end__
+ *   __etext
+ *   __data_start__
+ *   __preinit_array_start
+ *   __preinit_array_end
+ *   __init_array_start
+ *   __init_array_end
+ *   __fini_array_start
+ *   __fini_array_end
+ *   __data_end__
+ *   __bss_start__
+ *   __bss_end__
+ *   __end__
+ *   end
+ *   __HeapLimit
+ *   __StackLimit
+ *   __StackTop
+ *   __stack
+ *   __ram_end__
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+	.text :
+	{
+		__text_start__ = .;
+
+		. = ALIGN(4);
+		KEEP(*(.isr_vector))
+		*(.text*)
+
+		KEEP(*(.init))
+		KEEP(*(.fini))
+
+		/* .ctors */
+		*crtbegin.o(.ctors)
+		*crtbegin?.o(.ctors)
+		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+		*(SORT(.ctors.*))
+		*(.ctors)
+
+		/* .dtors */
+ 		*crtbegin.o(.dtors)
+ 		*crtbegin?.o(.dtors)
+ 		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ 		*(SORT(.dtors.*))
+ 		*(.dtors)
+
+		*(.rodata*)
+
+		KEEP(*(.eh_frame*))
+	} > FLASH
+
+	.ARM.extab :
+	{
+		*(.ARM.extab* .gnu.linkonce.armextab.*)
+	} > FLASH
+
+	__exidx_start = .;
+	.ARM.exidx :
+	{
+		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
+	} > FLASH
+	__exidx_end = .;
+
+	/* To copy multiple ROM to RAM sections,
+	 * uncomment .copy.table section and,
+	 * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.copy.table :
+	{
+		. = ALIGN(4);
+		__copy_table_start__ = .;
+		LONG (__etext)
+		LONG (__data_start__)
+		LONG (__data_end__ - __data_start__)
+		LONG (__etext2)
+		LONG (__data2_start__)
+		LONG (__data2_end__ - __data2_start__)
+		__copy_table_end__ = .;
+	} > FLASH
+	*/
+
+	/* To clear multiple BSS sections,
+	 * uncomment .zero.table section and,
+	 * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.zero.table :
+	{
+		. = ALIGN(4);
+		__zero_table_start__ = .;
+		LONG (__bss_start__)
+		LONG (__bss_end__ - __bss_start__)
+		LONG (__bss2_start__)
+		LONG (__bss2_end__ - __bss2_start__)
+		__zero_table_end__ = .;
+	} > FLASH
+	*/
+
+	__etext = .;
+
+	.data : AT (__etext)
+	{
+		__data_start__ = .;
+		*(vtable)
+		*(.data*)
+
+		. = ALIGN(4);
+		/* preinit data */
+		PROVIDE_HIDDEN (__preinit_array_start = .);
+		KEEP(*(.preinit_array))
+		PROVIDE_HIDDEN (__preinit_array_end = .);
+
+		. = ALIGN(4);
+		/* init data */
+		PROVIDE_HIDDEN (__init_array_start = .);
+		KEEP(*(SORT(.init_array.*)))
+		KEEP(*(.init_array))
+		PROVIDE_HIDDEN (__init_array_end = .);
+
+
+		. = ALIGN(4);
+		/* finit data */
+		PROVIDE_HIDDEN (__fini_array_start = .);
+		KEEP(*(SORT(.fini_array.*)))
+		KEEP(*(.fini_array))
+		PROVIDE_HIDDEN (__fini_array_end = .);
+
+		KEEP(*(.jcr*))
+		. = ALIGN(16);
+		/* All data end */
+		__data_end__ = .;
+
+	} > RAM
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start__ = .;
+		*(.bss*)
+		*(COMMON)
+		. = ALIGN(4);
+		__bss_end__ = .;
+	} > RAM
+
+	.heap (COPY):
+	{
+		__end__ = .;
+		PROVIDE(end = .);
+		*(.heap*)
+		__HeapLimit = .;
+	} > RAM
+
+	/* .stack_dummy section doesn't contains any symbols. It is only
+	 * used for linker to calculate size of stack sections, and assign
+	 * values to stack symbols later */
+	.stack_dummy (COPY):
+	{
+		*(.stack*)
+	} > RAM
+
+	/* Set stack top to end of RAM, and stack limit move down by
+	 * size of stack_dummy section */
+	__StackTop = ORIGIN(RAM) + LENGTH(RAM) ;
+	__StackLimit = __StackTop - SIZEOF(.stack_dummy);
+	PROVIDE(__stack = __StackTop);
+
+	__ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ;
+
+	/* Check if data + heap + stack exceeds RAM limit */
+	ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
+}
diff --git a/variants/itsybitsy_m4/pins_arduino.h b/variants/itsybitsy_m4/pins_arduino.h
new file mode 100644
index 000000000..db0e40c3d
--- /dev/null
+++ b/variants/itsybitsy_m4/pins_arduino.h
@@ -0,0 +1,21 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+// API compatibility
+#include "variant.h"
+
diff --git a/variants/itsybitsy_m4/variant.cpp b/variants/itsybitsy_m4/variant.cpp
new file mode 100644
index 000000000..35323cfcd
--- /dev/null
+++ b/variants/itsybitsy_m4/variant.cpp
@@ -0,0 +1,131 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "variant.h"
+
+/*
+ * Pins descriptions
+ */
+
+// TCC0 IOSET6
+// TCC1 IOSET1
+// TCC2 IOSET1
+const PinDescription g_APinDescription[]=
+{
+  // 0..13 - Digital pins
+  // ----------------------
+  // 0/1 - SERCOM/UART (Serial1)
+  { PORTA,  16, PIO_SERCOM_ALT, PIN_ATTR_PWM_F, No_ADC_Channel, TCC1_CH0, TC2_CH0, EXTERNAL_INT_0 }, // SERCOM 3.1
+  { PORTA,  17, PIO_SERCOM_ALT, PIN_ATTR_PWM_F, No_ADC_Channel, TCC1_CH1, TC2_CH1, EXTERNAL_INT_1 }, // SERCOM 3.0
+
+  // 2..12
+  // Digital Low
+  { PORTA,   7, PIO_ANALOG, (PIN_ATTR_ANALOG|PIN_ATTR_PWM_E), ADC_Channel7, TC1_CH1, TC1_CH1, EXTERNAL_INT_7 },  // D2
+  { PORTB,  22, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_6 }, // D3
+  { PORTA,  14, PIO_DIGITAL, PIN_ATTR_PWM_F, No_ADC_Channel, TCC2_CH0, TC3_CH0, EXTERNAL_INT_14 }, // D4
+  { PORTA,  15, PIO_DIGITAL, PIN_ATTR_PWM_F, No_ADC_Channel, TCC2_CH1, TC3_CH1, EXTERNAL_INT_15 }, // D5
+  { PORTB,   2, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel14, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 }, // Dotstar Clock (D6)
+  { PORTA,  18, PIO_DIGITAL, PIN_ATTR_PWM_F, No_ADC_Channel, TCC1_CH2, TC3_CH0, EXTERNAL_INT_2 }, // D7
+
+  // Digital High
+  { PORTB,   3, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel15, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_3 }, // Dotstar Data (D8)
+  { PORTA,  19, PIO_DIGITAL, PIN_ATTR_PWM_F, No_ADC_Channel, TCC1_CH3, TC3_CH1, EXTERNAL_INT_3 }, // D9
+  { PORTA,  20, PIO_DIGITAL, PIN_ATTR_PWM_G, No_ADC_Channel, TCC0_CH0, NOT_ON_TIMER, EXTERNAL_INT_4 }, // D10
+  { PORTA,  21, PIO_DIGITAL, PIN_ATTR_PWM_G, No_ADC_Channel, TCC0_CH1, NOT_ON_TIMER, EXTERNAL_INT_5 }, // D11
+  { PORTA,  23, PIO_DIGITAL, PIN_ATTR_PWM_G, No_ADC_Channel, TCC0_CH3, NOT_ON_TIMER, EXTERNAL_INT_7 }, // D12
+
+  // 13 (LED)
+  { PORTA,  22, PIO_DIGITAL, PIN_ATTR_PWM_G, No_ADC_Channel, TCC0_CH2, NOT_ON_TIMER, EXTERNAL_INT_6 }, // D13
+
+  // 14..19 - Analog pins
+  // --------------------
+  { PORTA,  2, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel0, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 },
+  { PORTA,  5, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel5, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_5 },
+  { PORTB,  8, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel2, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_8 },
+  { PORTB,  9, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel3, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_9 },
+  { PORTA,  4, PIO_ANALOG, (PIN_ATTR_ANALOG|PIN_ATTR_PWM_E), ADC_Channel4, TC0_CH0, TC0_CH0, EXTERNAL_INT_4 },
+  { PORTA,  6, PIO_ANALOG, (PIN_ATTR_ANALOG|PIN_ATTR_PWM_E), ADC_Channel6, TC1_CH0, TC1_CH0, EXTERNAL_INT_6 },
+
+  // Extra Analog pin #20
+  { PORTA,   7, PIO_ANALOG, (PIN_ATTR_ANALOG|PIN_ATTR_PWM_E), ADC_Channel7, TC1_CH1, TC1_CH1, EXTERNAL_INT_7 },  // A6 aka D2
+
+  // 21..22 I2C pins (SDA/SCL)
+  // ----------------------
+  { PORTA,  12, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, TC2_CH0, EXTERNAL_INT_12 }, // SERCOM 2.0
+  { PORTA,  13, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, TC2_CH1, EXTERNAL_INT_13 }, // SERCOM 2.1
+
+  // 23..25 - SPI pins (ICSP:MISO,SCK,MOSI)
+  // ----------------------
+  { PORTB, 23, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_7 },     // MISO SERCOM 1.3
+  { PORTA,  1, PIO_SERCOM_ALT, PIN_ATTR_PWM_E, No_ADC_Channel, TC2_CH1, TC2_CH1, EXTERNAL_INT_1 }, // SCK  SERCOM 1.1
+  { PORTA,  0, PIO_SERCOM_ALT, PIN_ATTR_PWM_E, No_ADC_Channel, TC2_CH0, TC2_CH0, EXTERNAL_INT_0 }, // MOSI SERCOM 1.0
+
+  // 26..28 - USB
+  // --------------------
+  { PORTA, 27, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_11 }, // USB Host enable
+  { PORTA, 24, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_8 }, // USB/DM
+  { PORTA, 25, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_9 }, // USB/DP
+
+  // 29 (AREF)
+  { PORTA, 3, PIO_ANALOG, PIN_ATTR_ANALOG, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_3 }, // DAC/VREFP
+
+  // ----------------------
+  // 30 - 31 Alternate use of A0 and A1 (DAC output)
+  { PORTA,  2, PIO_ANALOG, PIN_ATTR_ANALOG, DAC_Channel0, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 }, // DAC/VOUT[0]
+  { PORTA,  5, PIO_ANALOG, PIN_ATTR_ANALOG, DAC_Channel1, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_5 }, // DAC/VOUT[1]
+
+
+  // ----------------------
+  // 32 - 37 QSPI (SCK, CS, IO0, IO1, IO2, IO3)
+  { PORTB, 10, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_10 },
+  { PORTB, 11, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_11 },
+  { PORTA, 8, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NMI },
+  { PORTA, 9, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_9 },
+  { PORTA, 10, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_10 },
+  { PORTA, 11, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_11 },
+} ;
+
+const void* g_apTCInstances[TCC_INST_NUM+TC_INST_NUM]={ TCC0, TCC1, TCC2, TC0, TC1, TC2, TC3 } ;
+const uint32_t GCLK_CLKCTRL_IDs[TCC_INST_NUM+TC_INST_NUM] = { TCC0_GCLK_ID, TCC1_GCLK_ID, TCC2_GCLK_ID, TC0_GCLK_ID, TC1_GCLK_ID, TC2_GCLK_ID, TC3_GCLK_ID } ;
+
+// Multi-serial objects instantiation
+SERCOM sercom0( SERCOM0 ) ;
+SERCOM sercom1( SERCOM1 ) ;
+SERCOM sercom2( SERCOM2 ) ;
+SERCOM sercom3( SERCOM3 ) ;
+SERCOM sercom4( SERCOM4 ) ;
+SERCOM sercom5( SERCOM5 ) ;
+
+Uart Serial1( &sercom3, PIN_SERIAL1_RX, PIN_SERIAL1_TX, PAD_SERIAL1_RX, PAD_SERIAL1_TX ) ;
+
+void SERCOM3_0_Handler()
+{
+  Serial1.IrqHandler();
+}
+void SERCOM3_1_Handler()
+{
+  Serial1.IrqHandler();
+}
+void SERCOM3_2_Handler()
+{
+  Serial1.IrqHandler();
+}
+void SERCOM3_3_Handler()
+{
+  Serial1.IrqHandler();
+}
diff --git a/variants/itsybitsy_m4/variant.h b/variants/itsybitsy_m4/variant.h
new file mode 100644
index 000000000..e031adc9f
--- /dev/null
+++ b/variants/itsybitsy_m4/variant.h
@@ -0,0 +1,256 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _VARIANT_ITSYBITSY_M4_
+#define _VARIANT_ITSYBITSY_M4_
+
+// The definitions here needs a SAMD core >=1.6.10
+#define ARDUINO_SAMD_VARIANT_COMPLIANCE 10610
+
+/*----------------------------------------------------------------------------
+ *        Definitions
+ *----------------------------------------------------------------------------*/
+
+/** Frequency of the board main oscillator */
+#define VARIANT_MAINOSC		(32768ul)
+
+/** Master clock frequency */
+#define VARIANT_MCK        (F_CPU)
+
+#define VARIANT_GCLK0_FREQ (F_CPU)
+#define VARIANT_GCLK1_FREQ (48000000UL)
+#define VARIANT_GCLK2_FREQ (100000000UL)
+
+/*----------------------------------------------------------------------------
+ *        Headers
+ *----------------------------------------------------------------------------*/
+
+#include "WVariant.h"
+
+#ifdef __cplusplus
+#include "SERCOM.h"
+#include "Uart.h"
+#endif // __cplusplus
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif // __cplusplus
+
+/*----------------------------------------------------------------------------
+ *        Pins
+ *----------------------------------------------------------------------------*/
+
+// Number of pins defined in PinDescription array
+#define PINS_COUNT           (38u)
+#define NUM_DIGITAL_PINS     (26u)
+#define NUM_ANALOG_INPUTS    (7u)
+#define NUM_ANALOG_OUTPUTS   (2u)
+#define analogInputToDigitalPin(p)  ((p < NUM_ANALOG_INPUTS) ? (p) + PIN_A0 : -1)
+
+#define digitalPinToPort(P)        ( &(PORT->Group[g_APinDescription[P].ulPort]) )
+#define digitalPinToBitMask(P)     ( 1 << g_APinDescription[P].ulPin )
+//#define analogInPinToBit(P)        ( )
+#define portOutputRegister(port)   ( &(port->OUT.reg) )
+#define portInputRegister(port)    ( &(port->IN.reg) )
+#define portModeRegister(port)     ( &(port->DIR.reg) )
+#define digitalPinHasPWM(P)        ( g_APinDescription[P].ulPWMChannel != NOT_ON_PWM || g_APinDescription[P].ulTCChannel != NOT_ON_TIMER )
+
+/*
+ * digitalPinToTimer(..) is AVR-specific and is not defined for SAMD
+ * architecture. If you need to check if a pin supports PWM you must
+ * use digitalPinHasPWM(..).
+ *
+ * https://github.com/arduino/Arduino/issues/1833
+ */
+// #define digitalPinToTimer(P)
+
+// LEDs
+#define PIN_LED_13           (13u)
+#define PIN_LED              PIN_LED_13
+#define LED_BUILTIN          PIN_LED_13
+
+/*
+ * Analog pins
+ */
+#define PIN_A0               (14ul)
+#define PIN_A1               (PIN_A0 + 1)
+#define PIN_A2               (PIN_A0 + 2)
+#define PIN_A3               (PIN_A0 + 3)
+#define PIN_A4               (PIN_A0 + 4)
+#define PIN_A5               (PIN_A0 + 5)
+#define PIN_A6               (PIN_A0 + 6)
+#define PIN_DAC0             PIN_A0
+#define PIN_DAC1             PIN_A1
+
+static const uint8_t A0  = PIN_A0;
+static const uint8_t A1  = PIN_A1;
+static const uint8_t A2  = PIN_A2;
+static const uint8_t A3  = PIN_A3;
+static const uint8_t A4  = PIN_A4;
+static const uint8_t A5  = PIN_A5;
+static const uint8_t A6  = PIN_A6 ;
+
+static const uint8_t DAC0 = PIN_DAC0;
+static const uint8_t DAC1 = PIN_DAC1;
+
+#define ADC_RESOLUTION		12
+
+// Other pins
+#define PIN_ATN              (26ul)
+static const uint8_t ATN = PIN_ATN;
+
+/*
+ * Serial interfaces
+ */
+
+// Serial1
+#define PIN_SERIAL1_RX       (0ul)
+#define PIN_SERIAL1_TX       (1ul)
+#define PAD_SERIAL1_RX       (SERCOM_RX_PAD_1)
+#define PAD_SERIAL1_TX       (UART_TX_PAD_0)
+
+/*
+ * SPI Interfaces
+ */
+#define SPI_INTERFACES_COUNT     1
+
+#define PIN_SPI_MISO         (23u)
+#define PIN_SPI_SCK          (24u)
+#define PIN_SPI_MOSI         (25u)
+#define PERIPH_SPI           sercom1
+#define PAD_SPI_TX           SPI_PAD_0_SCK_1
+#define PAD_SPI_RX           SERCOM_RX_PAD_3
+
+static const uint8_t SS	  = PIN_A2 ;	
+static const uint8_t MOSI = PIN_SPI_MOSI ;
+static const uint8_t MISO = PIN_SPI_MISO ;
+static const uint8_t SCK  = PIN_SPI_SCK ;
+
+/*
+ * Wire Interfaces
+ */
+#define WIRE_INTERFACES_COUNT 1
+
+#define PIN_WIRE_SDA         (21u)
+#define PIN_WIRE_SCL         (22u)
+#define PERIPH_WIRE          sercom2
+#define WIRE_IT_HANDLER      SERCOM2_Handler
+#define WIRE_IT_HANDLER_0    SERCOM2_0_Handler
+#define WIRE_IT_HANDLER_1    SERCOM2_1_Handler
+#define WIRE_IT_HANDLER_2    SERCOM2_2_Handler
+#define WIRE_IT_HANDLER_3    SERCOM2_3_Handler
+
+static const uint8_t SDA = PIN_WIRE_SDA;
+static const uint8_t SCL = PIN_WIRE_SCL;
+
+/*
+ * USB
+ */
+#define PIN_USB_HOST_ENABLE (26ul)
+#define PIN_USB_DM          (27ul)
+#define PIN_USB_DP          (28ul)
+
+/*
+ * I2S Interfaces
+ */
+#define I2S_INTERFACES_COUNT 0
+
+#define I2S_DEVICE          0
+// no I2S on G19!
+
+// On-board QSPI Flash
+#define EXTERNAL_FLASH_DEVICES   GD25Q16C
+#define EXTERNAL_FLASH_USE_QSPI
+
+//QSPI Pins
+#define PIN_QSPI_SCK	(32u)
+#define PIN_QSPI_CS	(33u)
+#define PIN_QSPI_IO0	(34u)
+#define PIN_QSPI_IO1	(35u)
+#define PIN_QSPI_IO2	(36u)
+#define PIN_QSPI_IO3	(37u)
+
+//PCC Pins
+#define PIN_PCC_DEN1    (PIN_SPI_MOSI)
+#define PIN_PCC_DEN2    (PIN_SPI_SCK)
+#define PIN_PCC_CLK     (PIN_SPI_MISO)
+#define PIN_PCC_D0      (13u)
+#define PIN_PCC_D1      (12u)
+#define PIN_PCC_D2      (10u)
+#define PIN_PCC_D3      (11u)
+#define PIN_PCC_D4      (9u)
+#define PIN_PCC_D5      (8u)
+#define PIN_PCC_D6      (1u)
+#define PIN_PCC_D7      (0u)
+#define PIN_PCC_D8      (5u)
+#define PIN_PCC_D9      (6u)
+
+#if !defined(VARIANT_QSPI_BAUD_DEFAULT)
+  // TODO: meaningful value for this
+  #define VARIANT_QSPI_BAUD_DEFAULT 5000000
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+ *        Arduino objects - C++ only
+ *----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+
+/*	=========================
+ *	===== SERCOM DEFINITION
+ *	=========================
+*/
+extern SERCOM sercom0;
+extern SERCOM sercom1;
+extern SERCOM sercom2;
+extern SERCOM sercom3;
+extern SERCOM sercom4;
+extern SERCOM sercom5;
+
+extern Uart Serial1;
+
+#endif
+
+// These serial port names are intended to allow libraries and architecture-neutral
+// sketches to automatically default to the correct port name for a particular type
+// of use.  For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN,
+// the first hardware serial port whose RX/TX pins are not dedicated to another use.
+//
+// SERIAL_PORT_MONITOR        Port which normally prints to the Arduino Serial Monitor
+//
+// SERIAL_PORT_USBVIRTUAL     Port which is USB virtual serial
+//
+// SERIAL_PORT_LINUXBRIDGE    Port which connects to a Linux system via Bridge library
+//
+// SERIAL_PORT_HARDWARE       Hardware serial port, physical RX & TX pins.
+//
+// SERIAL_PORT_HARDWARE_OPEN  Hardware serial ports which are open for use.  Their RX & TX
+//                            pins are NOT connected to anything by default.
+#define SERIAL_PORT_USBVIRTUAL      Serial
+#define SERIAL_PORT_MONITOR         Serial
+// Serial has no physical pins broken out, so it's not listed as HARDWARE port
+#define SERIAL_PORT_HARDWARE        Serial1
+#define SERIAL_PORT_HARDWARE_OPEN   Serial1
+
+#endif /* _VARIANT_ITSYBITSY_M4_ */
+
diff --git a/variants/matrixportal_m4/linker_scripts/gcc/flash_with_bootloader.ld b/variants/matrixportal_m4/linker_scripts/gcc/flash_with_bootloader.ld
new file mode 100644
index 000000000..1bdea69ae
--- /dev/null
+++ b/variants/matrixportal_m4/linker_scripts/gcc/flash_with_bootloader.ld
@@ -0,0 +1,216 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* Linker script to configure memory regions.
+ * Need modifying for a specific board.
+ *   FLASH.ORIGIN: starting address of flash
+ *   FLASH.LENGTH: length of flash
+ *   RAM.ORIGIN: starting address of RAM bank 0
+ *   RAM.LENGTH: length of RAM bank 0
+ */
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000+0x4000, LENGTH = 0x00080000-0x4000 /* First 16KB used by bootloader */
+  RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00030000
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ *   Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ *   __exidx_start
+ *   __exidx_end
+ *   __copy_table_start__
+ *   __copy_table_end__
+ *   __zero_table_start__
+ *   __zero_table_end__
+ *   __etext
+ *   __data_start__
+ *   __preinit_array_start
+ *   __preinit_array_end
+ *   __init_array_start
+ *   __init_array_end
+ *   __fini_array_start
+ *   __fini_array_end
+ *   __data_end__
+ *   __bss_start__
+ *   __bss_end__
+ *   __end__
+ *   end
+ *   __HeapLimit
+ *   __StackLimit
+ *   __StackTop
+ *   __stack
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+	.text :
+	{
+		__text_start__ = .;
+
+		KEEP(*(.sketch_boot))
+
+		. = ALIGN(0x4000);
+		KEEP(*(.isr_vector))
+		*(.text*)
+
+		KEEP(*(.init))
+		KEEP(*(.fini))
+
+		/* .ctors */
+		*crtbegin.o(.ctors)
+		*crtbegin?.o(.ctors)
+		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+		*(SORT(.ctors.*))
+		*(.ctors)
+
+		/* .dtors */
+ 		*crtbegin.o(.dtors)
+ 		*crtbegin?.o(.dtors)
+ 		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ 		*(SORT(.dtors.*))
+ 		*(.dtors)
+
+		*(.rodata*)
+
+		KEEP(*(.eh_frame*))
+	} > FLASH
+
+	.ARM.extab :
+	{
+		*(.ARM.extab* .gnu.linkonce.armextab.*)
+	} > FLASH
+
+	__exidx_start = .;
+	.ARM.exidx :
+	{
+		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
+	} > FLASH
+	__exidx_end = .;
+
+	/* To copy multiple ROM to RAM sections,
+	 * uncomment .copy.table section and,
+	 * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.copy.table :
+	{
+		. = ALIGN(4);
+		__copy_table_start__ = .;
+		LONG (__etext)
+		LONG (__data_start__)
+		LONG (__data_end__ - __data_start__)
+		LONG (__etext2)
+		LONG (__data2_start__)
+		LONG (__data2_end__ - __data2_start__)
+		__copy_table_end__ = .;
+	} > FLASH
+	*/
+
+	/* To clear multiple BSS sections,
+	 * uncomment .zero.table section and,
+	 * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.zero.table :
+	{
+		. = ALIGN(4);
+		__zero_table_start__ = .;
+		LONG (__bss_start__)
+		LONG (__bss_end__ - __bss_start__)
+		LONG (__bss2_start__)
+		LONG (__bss2_end__ - __bss2_start__)
+		__zero_table_end__ = .;
+	} > FLASH
+	*/
+
+	__etext = .;
+
+	.data : AT (__etext)
+	{
+		__data_start__ = .;
+		*(vtable)
+		*(.data*)
+
+		. = ALIGN(4);
+		/* preinit data */
+		PROVIDE_HIDDEN (__preinit_array_start = .);
+		KEEP(*(.preinit_array))
+		PROVIDE_HIDDEN (__preinit_array_end = .);
+
+		. = ALIGN(4);
+		/* init data */
+		PROVIDE_HIDDEN (__init_array_start = .);
+		KEEP(*(SORT(.init_array.*)))
+		KEEP(*(.init_array))
+		PROVIDE_HIDDEN (__init_array_end = .);
+
+
+		. = ALIGN(4);
+		/* finit data */
+		PROVIDE_HIDDEN (__fini_array_start = .);
+		KEEP(*(SORT(.fini_array.*)))
+		KEEP(*(.fini_array))
+		PROVIDE_HIDDEN (__fini_array_end = .);
+
+		KEEP(*(.jcr*))
+		. = ALIGN(16);
+		/* All data end */
+		__data_end__ = .;
+
+	} > RAM
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start__ = .;
+		*(.bss*)
+		*(COMMON)
+		. = ALIGN(4);
+		__bss_end__ = .;
+	} > RAM
+
+	.heap (COPY):
+	{
+		__end__ = .;
+		PROVIDE(end = .);
+		*(.heap*)
+		__HeapLimit = .;
+	} > RAM
+
+	/* .stack_dummy section doesn't contains any symbols. It is only
+	 * used for linker to calculate size of stack sections, and assign
+	 * values to stack symbols later */
+	.stack_dummy (COPY):
+	{
+		*(.stack*)
+	} > RAM
+
+	/* Set stack top to end of RAM, and stack limit move down by
+	 * size of stack_dummy section */
+	__StackTop = ORIGIN(RAM) + LENGTH(RAM);
+	__StackLimit = __StackTop - SIZEOF(.stack_dummy);
+	PROVIDE(__stack = __StackTop);
+
+	__ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ;
+
+	/* Check if data + heap + stack exceeds RAM limit */
+	ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
+}
diff --git a/variants/matrixportal_m4/linker_scripts/gcc/flash_without_bootloader.ld b/variants/matrixportal_m4/linker_scripts/gcc/flash_without_bootloader.ld
new file mode 100644
index 000000000..9c0c4e06d
--- /dev/null
+++ b/variants/matrixportal_m4/linker_scripts/gcc/flash_without_bootloader.ld
@@ -0,0 +1,214 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* Linker script to configure memory regions.
+ * Need modifying for a specific board.
+ *   FLASH.ORIGIN: starting address of flash
+ *   FLASH.LENGTH: length of flash
+ *   RAM.ORIGIN: starting address of RAM bank 0
+ *   RAM.LENGTH: length of RAM bank 0
+ */
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00080000
+  RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00030000
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ *   Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ *   __exidx_start
+ *   __exidx_end
+ *   __copy_table_start__
+ *   __copy_table_end__
+ *   __zero_table_start__
+ *   __zero_table_end__
+ *   __etext
+ *   __data_start__
+ *   __preinit_array_start
+ *   __preinit_array_end
+ *   __init_array_start
+ *   __init_array_end
+ *   __fini_array_start
+ *   __fini_array_end
+ *   __data_end__
+ *   __bss_start__
+ *   __bss_end__
+ *   __end__
+ *   end
+ *   __HeapLimit
+ *   __StackLimit
+ *   __StackTop
+ *   __stack
+ *   __ram_end__
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+	.text :
+	{
+		__text_start__ = .;
+
+		KEEP(*(.isr_vector))
+		*(.text*)
+
+		KEEP(*(.init))
+		KEEP(*(.fini))
+
+		/* .ctors */
+		*crtbegin.o(.ctors)
+		*crtbegin?.o(.ctors)
+		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+		*(SORT(.ctors.*))
+		*(.ctors)
+
+		/* .dtors */
+ 		*crtbegin.o(.dtors)
+ 		*crtbegin?.o(.dtors)
+ 		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ 		*(SORT(.dtors.*))
+ 		*(.dtors)
+
+		*(.rodata*)
+
+		KEEP(*(.eh_frame*))
+	} > FLASH
+
+	.ARM.extab :
+	{
+		*(.ARM.extab* .gnu.linkonce.armextab.*)
+	} > FLASH
+
+	__exidx_start = .;
+	.ARM.exidx :
+	{
+		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
+	} > FLASH
+	__exidx_end = .;
+
+	/* To copy multiple ROM to RAM sections,
+	 * uncomment .copy.table section and,
+	 * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.copy.table :
+	{
+		. = ALIGN(4);
+		__copy_table_start__ = .;
+		LONG (__etext)
+		LONG (__data_start__)
+		LONG (__data_end__ - __data_start__)
+		LONG (__etext2)
+		LONG (__data2_start__)
+		LONG (__data2_end__ - __data2_start__)
+		__copy_table_end__ = .;
+	} > FLASH
+	*/
+
+	/* To clear multiple BSS sections,
+	 * uncomment .zero.table section and,
+	 * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.zero.table :
+	{
+		. = ALIGN(4);
+		__zero_table_start__ = .;
+		LONG (__bss_start__)
+		LONG (__bss_end__ - __bss_start__)
+		LONG (__bss2_start__)
+		LONG (__bss2_end__ - __bss2_start__)
+		__zero_table_end__ = .;
+	} > FLASH
+	*/
+
+	__etext = .;
+
+	.data : AT (__etext)
+	{
+		__data_start__ = .;
+		*(vtable)
+		*(.data*)
+
+		. = ALIGN(4);
+		/* preinit data */
+		PROVIDE_HIDDEN (__preinit_array_start = .);
+		KEEP(*(.preinit_array))
+		PROVIDE_HIDDEN (__preinit_array_end = .);
+
+		. = ALIGN(4);
+		/* init data */
+		PROVIDE_HIDDEN (__init_array_start = .);
+		KEEP(*(SORT(.init_array.*)))
+		KEEP(*(.init_array))
+		PROVIDE_HIDDEN (__init_array_end = .);
+
+
+		. = ALIGN(4);
+		/* finit data */
+		PROVIDE_HIDDEN (__fini_array_start = .);
+		KEEP(*(SORT(.fini_array.*)))
+		KEEP(*(.fini_array))
+		PROVIDE_HIDDEN (__fini_array_end = .);
+
+		KEEP(*(.jcr*))
+		. = ALIGN(16);
+		/* All data end */
+		__data_end__ = .;
+
+	} > RAM
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start__ = .;
+		*(.bss*)
+		*(COMMON)
+		. = ALIGN(4);
+		__bss_end__ = .;
+	} > RAM
+
+	.heap (COPY):
+	{
+		__end__ = .;
+		PROVIDE(end = .);
+		*(.heap*)
+		__HeapLimit = .;
+	} > RAM
+
+	/* .stack_dummy section doesn't contains any symbols. It is only
+	 * used for linker to calculate size of stack sections, and assign
+	 * values to stack symbols later */
+	.stack_dummy (COPY):
+	{
+		*(.stack*)
+	} > RAM
+
+	/* Set stack top to end of RAM, and stack limit move down by
+	 * size of stack_dummy section */
+	__StackTop = ORIGIN(RAM) + LENGTH(RAM) ;
+	__StackLimit = __StackTop - SIZEOF(.stack_dummy);
+	PROVIDE(__stack = __StackTop);
+
+	__ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ;
+
+	/* Check if data + heap + stack exceeds RAM limit */
+	ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
+}
diff --git a/variants/matrixportal_m4/pins_arduino.h b/variants/matrixportal_m4/pins_arduino.h
new file mode 100644
index 000000000..db0e40c3d
--- /dev/null
+++ b/variants/matrixportal_m4/pins_arduino.h
@@ -0,0 +1,21 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+// API compatibility
+#include "variant.h"
+
diff --git a/variants/matrixportal_m4/variant.cpp b/variants/matrixportal_m4/variant.cpp
new file mode 100644
index 000000000..df23508fe
--- /dev/null
+++ b/variants/matrixportal_m4/variant.cpp
@@ -0,0 +1,173 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "variant.h"
+
+/*
+ * Pins descriptions
+ */
+
+//TCC0 IOSET 6
+//TCC1 IOSET 1
+//TC0 IOSET 1
+//TC1 IOSET 1
+//TC2 IOSET 2
+//TC3 IOSET 1
+//TC4 IOSET 1
+const PinDescription g_APinDescription[]=
+{
+  // 0..13 - Digital pins
+  // ----------------------
+  // 0/1 - SERCOM/UART (Serial1)
+  { PORTA,  1, PIO_SERCOM_ALT, PIN_ATTR_PWM_E, No_ADC_Channel, TC2_CH1, TC2_CH1, EXTERNAL_INT_1 }, // RX: SERCOM1/PAD[1]
+  { PORTA,  0, PIO_SERCOM_ALT, PIN_ATTR_PWM_E, No_ADC_Channel, TC2_CH0, TC2_CH0, EXTERNAL_INT_0 }, // TX: SERCOM1/PAD[0]
+
+  // 2..3 buttons
+  { PORTB, 22, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_6 }, // Up
+  { PORTB, 23, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_7 }, // Down
+
+  // 4 neopixel
+  { PORTA, 23, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_7 }, // NeoPixel
+
+  // 5..6 I2C
+  { PORTB, 31, PIO_SERCOM_ALT, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_15 }, // SERCOM5.1 SDA
+  { PORTB, 30, PIO_SERCOM_ALT, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_14 }, // SERCOM5.0 SCL
+
+  // 7..12 RGBRGB pins
+  { PORTB,  0, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_0 }, // R1
+  { PORTB,  1, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_1 }, // G1
+  { PORTB,  2, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 }, // B1
+  { PORTB,  3, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_3 }, // R2
+  { PORTB,  4, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_4 }, // G2
+  { PORTB,  5, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_5 }, // B2
+
+  // 13 LED
+  { PORTA, 14, PIO_DIGITAL, PIN_ATTR_PWM_G, No_ADC_Channel, TCC1_CH2, TCC1_CH2, EXTERNAL_INT_14 }, // Red LED
+
+  // 14..21  Control pins
+  { PORTB,  6, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_6 }, // CLK
+  { PORTB, 14, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_14 }, // LAT
+  { PORTB, 12, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_12 }, // OE
+  { PORTB,  7, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_7 }, // ADDR A
+  { PORTB,  8, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_8 }, // ADDR B
+  { PORTB,  9, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_9 }, // ADDR C
+  { PORTB, 15, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_15 }, // ADDR D
+  { PORTB, 13, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_13 }, // ADDR E
+
+  // 22..26 Analog pins
+  // --------------------
+  { PORTA,  2, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel0, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 }, // A0
+  { PORTA,  5, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel5, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_5 }, // A1
+  { PORTA,  4, PIO_ANALOG, (PIN_ATTR_ANALOG|PIN_ATTR_PWM_E), ADC_Channel4, TC0_CH0, TC0_CH0, EXTERNAL_INT_4 }, // A2
+  { PORTA,  6, PIO_ANALOG, (PIN_ATTR_ANALOG|PIN_ATTR_PWM_E), ADC_Channel6, TC1_CH0, TC1_CH0, EXTERNAL_INT_6 }, // A3
+  { PORTA,  7, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel7, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_7 }, // A4
+
+  // 27..28 ESP UART
+  // ----------------------
+  { PORTA, 12, PIO_SERCOM_ALT, PIN_ATTR_PWM_E, No_ADC_Channel, TC2_CH0, TC2_CH0, EXTERNAL_INT_12 }, // RX: SERCOM4/PAD[1]
+  { PORTA, 13, PIO_SERCOM_ALT, PIN_ATTR_PWM_E, No_ADC_Channel, TC2_CH1, TC2_CH1, EXTERNAL_INT_13 }, // TX: SERCOM4/PAD[0]
+
+  // 29..33 ESP control
+  { PORTA, 20, PIO_DIGITAL, PIN_ATTR_PWM_G, No_ADC_Channel, TCC0_CH0, NOT_ON_TIMER, EXTERNAL_INT_4 }, // ESP GPIO0
+  { PORTA, 21, PIO_DIGITAL, PIN_ATTR_PWM_G, No_ADC_Channel, TCC0_CH1, NOT_ON_TIMER, EXTERNAL_INT_5 }, // ESP Reset
+  { PORTA, 22, PIO_DIGITAL, PIN_ATTR_PWM_G, No_ADC_Channel, TCC0_CH2, NOT_ON_TIMER, EXTERNAL_INT_6 }, // ESP Busy
+  { PORTA, 18, PIO_DIGITAL, PIN_ATTR_PWM_F, No_ADC_Channel, TCC1_CH2, NOT_ON_TIMER, EXTERNAL_INT_2 }, // ESP RTS
+  { PORTB, 17, PIO_DIGITAL, PIN_ATTR_PWM_G, No_ADC_Channel, TCC0_CH4, NOT_ON_TIMER, EXTERNAL_INT_1 }, // ESP CS
+
+  // 34..36 ESP SPI
+  { PORTA, 16, PIO_SERCOM_ALT, PIN_ATTR_PWM_F, No_ADC_Channel, TCC1_CH0, TC2_CH0, EXTERNAL_INT_0 }, // SCK: SERCOM3/PAD[1]
+  { PORTA, 17, PIO_SERCOM_ALT, PIN_ATTR_PWM_F, No_ADC_Channel, TCC1_CH1, TC2_CH1, EXTERNAL_INT_1 }, // MISO: SERCOM3/PAD[0]
+  { PORTA, 19, PIO_SERCOM_ALT, PIN_ATTR_PWM_F, No_ADC_Channel, TCC1_CH3, TC3_CH1, EXTERNAL_INT_3 }, // MOSI: SERCOM1/PAD[3]
+
+  // 37..39 - USB
+  // --------------------
+  { NOT_A_PORT, 0, PIO_NOT_A_PIN, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB Host enable DOES NOT EXIST ON THIS BOARD
+  { PORTA, 24, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB/DM
+  { PORTA, 27, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB/DP
+
+  // 40 (AREF)
+  { PORTA, 3, PIO_ANALOG, PIN_ATTR_ANALOG, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // DAC/VREFP
+
+  // ----------------------
+  // 41..46 QSPI (SCK, CS, IO0, IO1, IO2, IO3)
+  { PORTB, 10, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+  { PORTB, 11, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+  { PORTA, 8, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+  { PORTA, 9, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+  { PORTA, 10, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+  { PORTA, 11, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+
+  // 47 LIS IRQ
+  { PORTA, 27, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_11 }, // IRQ
+
+  // 48..50 external SPI #2 on sercom 0
+  { PORTA,  5, PIO_SERCOM_ALT, PIN_ATTR_ANALOG, ADC_Channel5, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_5 }, // SCK SERCOM 0.1
+  { PORTA,  4, PIO_SERCOM_ALT, (PIN_ATTR_ANALOG|PIN_ATTR_PWM_E), ADC_Channel4, TC0_CH0, TC0_CH0, EXTERNAL_INT_4 }, // MOSI SERCOM 0.0
+  { PORTA,  7, PIO_SERCOM_ALT, PIN_ATTR_ANALOG, ADC_Channel7, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_7 }, // MISO SERCOM 0.3
+} ;
+
+const void* g_apTCInstances[TCC_INST_NUM+TC_INST_NUM]={ TCC0, TCC1, TCC2, TCC3, TCC4, TC0, TC1, TC2, TC3, TC4, TC5 } ;
+const uint32_t GCLK_CLKCTRL_IDs[TCC_INST_NUM+TC_INST_NUM] = { TCC0_GCLK_ID, TCC1_GCLK_ID, TCC2_GCLK_ID, TCC3_GCLK_ID, TCC4_GCLK_ID, TC0_GCLK_ID, TC1_GCLK_ID, TC2_GCLK_ID, TC3_GCLK_ID, TC4_GCLK_ID, TC5_GCLK_ID } ;
+
+// Multi-serial objects instantiation
+SERCOM sercom0( SERCOM0 ) ;
+SERCOM sercom1( SERCOM1 ) ;
+SERCOM sercom2( SERCOM2 ) ;
+SERCOM sercom3( SERCOM3 ) ;
+SERCOM sercom4( SERCOM4 ) ;
+SERCOM sercom5( SERCOM5 ) ;
+
+Uart Serial1( &sercom1, PIN_SERIAL1_RX, PIN_SERIAL1_TX, PAD_SERIAL1_RX, PAD_SERIAL1_TX ) ;
+
+void SERCOM1_0_Handler()
+{
+  Serial1.IrqHandler();
+}
+void SERCOM1_1_Handler()
+{
+  Serial1.IrqHandler();
+}
+void SERCOM1_2_Handler()
+{
+  Serial1.IrqHandler();
+}
+void SERCOM1_3_Handler()
+{
+  Serial1.IrqHandler();
+}
+
+
+// sercom for internal ESP32 UART connection
+Uart Serial2( &sercom4, PIN_SERIAL2_RX, PIN_SERIAL2_TX, PAD_SERIAL2_RX, PAD_SERIAL2_TX ) ;
+
+void SERCOM4_0_Handler()
+{
+  Serial2.IrqHandler();
+}
+void SERCOM4_1_Handler()
+{
+  Serial2.IrqHandler();
+}
+void SERCOM4_2_Handler()
+{
+  Serial2.IrqHandler();
+}
+void SERCOM4_3_Handler()
+{
+  Serial2.IrqHandler();
+}
diff --git a/variants/matrixportal_m4/variant.h b/variants/matrixportal_m4/variant.h
new file mode 100644
index 000000000..deedf8502
--- /dev/null
+++ b/variants/matrixportal_m4/variant.h
@@ -0,0 +1,275 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _VARIANT_MATRIXPORTAL_M4_
+#define _VARIANT_MATRIXPORTAL_M4_
+
+// The definitions here needs a SAMD core >=1.6.10
+#define ARDUINO_SAMD_VARIANT_COMPLIANCE 10610
+
+/*----------------------------------------------------------------------------
+ *        Definitions
+ *----------------------------------------------------------------------------*/
+
+/** Frequency of the board main oscillator */
+#define VARIANT_MAINOSC		(32768ul)
+
+/** Master clock frequency */
+#define VARIANT_MCK        (F_CPU)
+
+#define VARIANT_GCLK0_FREQ (F_CPU)
+#define VARIANT_GCLK1_FREQ (48000000UL)
+#define VARIANT_GCLK2_FREQ (100000000UL)
+
+/*----------------------------------------------------------------------------
+ *        Headers
+ *----------------------------------------------------------------------------*/
+
+#include "WVariant.h"
+
+#ifdef __cplusplus
+#include "SERCOM.h"
+#include "Uart.h"
+#endif // __cplusplus
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif // __cplusplus
+
+/*----------------------------------------------------------------------------
+ *        Pins
+ *----------------------------------------------------------------------------*/
+
+// Number of pins defined in PinDescription array
+#define PINS_COUNT           (40u)
+#define NUM_DIGITAL_PINS     (20u)
+#define NUM_ANALOG_INPUTS    (6u)
+#define NUM_ANALOG_OUTPUTS   (1u)
+#define analogInputToDigitalPin(p)  ((p < 6u) ? (p) + 14u : -1)
+
+#define digitalPinToPort(P)        ( &(PORT->Group[g_APinDescription[P].ulPort]) )
+#define digitalPinToBitMask(P)     ( 1 << g_APinDescription[P].ulPin )
+//#define analogInPinToBit(P)        ( )
+#define portOutputRegister(port)   ( &(port->OUT.reg) )
+#define portInputRegister(port)    ( &(port->IN.reg) )
+#define portModeRegister(port)     ( &(port->DIR.reg) )
+#define digitalPinHasPWM(P)        ( g_APinDescription[P].ulPWMChannel != NOT_ON_PWM || g_APinDescription[P].ulTCChannel != NOT_ON_TIMER )
+
+/*
+ * digitalPinToTimer(..) is AVR-specific and is not defined for SAMD
+ * architecture. If you need to check if a pin supports PWM you must
+ * use digitalPinHasPWM(..).
+ *
+ * https://github.com/arduino/Arduino/issues/1833
+ */
+// #define digitalPinToTimer(P)
+
+// LEDs
+#define PIN_LED_13           (13u)
+//#define PIN_LED_RXL          (25u)
+//#define PIN_LED_TXL          (26u)
+#define PIN_LED              PIN_LED_13
+//#define PIN_LED2             PIN_LED_RXL
+//#define PIN_LED3             PIN_LED_TXL
+#define LED_BUILTIN          PIN_LED_13
+#define PIN_NEOPIXEL         (4)
+
+/*
+ * Analog pins
+ */
+#define PIN_A0               (22ul)
+#define PIN_A1               (PIN_A0 + 1)
+#define PIN_A2               (PIN_A0 + 2)
+#define PIN_A3               (PIN_A0 + 3)
+#define PIN_A4               (PIN_A0 + 4)
+
+#define PIN_DAC0             (22ul)
+#define PIN_DAC1             PIN_A1
+
+static const uint8_t A0  = PIN_A0;
+static const uint8_t A1  = PIN_A1;
+static const uint8_t A2  = PIN_A2;
+static const uint8_t A3  = PIN_A3;
+static const uint8_t A4  = PIN_A4;
+
+static const uint8_t DAC0 = PIN_DAC0;
+static const uint8_t DAC1 = PIN_DAC1;
+
+#define ADC_RESOLUTION		12
+
+
+
+/* WiFi interfaces */
+#define SerialESP32     Serial2
+#define SerialNina      SerialESP32
+#define SPIWIFI         SPI
+#define ESP32_GPIO0     29
+#define ESP32_RESETN    30
+#define SPIWIFI_SS      33
+#define SPIWIFI_ACK     31
+#define SPIWIFI_RESET   ESP32_RESETN
+#define NINA_GPIO0      ESP32_GPIO0
+#define NINA_RESETN     ESP32_RESETN
+#define NINA_ACK        SPIWIFI_ACK
+#define NINA_CTS        SPIWIFI_ACK
+#define NINA_RTS        NINA_GPIO0
+
+
+/*
+ * Serial interfaces
+ */
+
+// Serial1
+#define PIN_SERIAL1_RX       (0ul)
+#define PIN_SERIAL1_TX       (1ul)
+#define PAD_SERIAL1_RX       (SERCOM_RX_PAD_1)
+#define PAD_SERIAL1_TX       (UART_TX_PAD_0)
+
+// Serial2
+#define PIN_SERIAL2_RX       (27ul)
+#define PIN_SERIAL2_TX       (28ul)
+#define PAD_SERIAL2_RX       (SERCOM_RX_PAD_1)
+#define PAD_SERIAL2_TX       (UART_TX_PAD_0)
+
+
+/*
+ * SPI Interfaces
+ */
+#define SPI_INTERFACES_COUNT 2
+
+#define PIN_SPI_SCK          (34u)
+#define PIN_SPI_MISO         (35u)
+#define PIN_SPI_MOSI         (36u)
+#define PERIPH_SPI           sercom3
+#define PAD_SPI_TX           SPI_PAD_3_SCK_1
+#define PAD_SPI_RX           SERCOM_RX_PAD_0
+
+static const uint8_t SS	  = 33 ;
+static const uint8_t MOSI = PIN_SPI_MOSI ;
+static const uint8_t MISO = PIN_SPI_MISO ;
+static const uint8_t SCK  = PIN_SPI_SCK ;
+
+
+#define PIN_SPI1_SCK          (48u)
+#define PIN_SPI1_MOSI         (49u)
+#define PIN_SPI1_MISO         (50u)
+#define PERIPH_SPI1           sercom0
+#define PAD_SPI1_TX           SPI_PAD_0_SCK_1
+#define PAD_SPI1_RX           SERCOM_RX_PAD_3
+
+static const uint8_t SS1	 = PIN_A3 ;
+static const uint8_t MOSI1 = PIN_SPI1_MOSI ;
+static const uint8_t MISO1 = PIN_SPI1_MISO ;
+static const uint8_t SCK1  = PIN_SPI1_SCK ;
+
+/*
+ * Wire Interfaces
+ */
+#define WIRE_INTERFACES_COUNT 1
+
+#define PIN_WIRE_SDA         (5u)
+#define PIN_WIRE_SCL         (6u)
+#define PERIPH_WIRE          sercom5
+#define WIRE_IT_HANDLER      SERCOM5_Handler
+#define WIRE_IT_HANDLER_0    SERCOM5_0_Handler
+#define WIRE_IT_HANDLER_1    SERCOM5_1_Handler
+#define WIRE_IT_HANDLER_2    SERCOM5_2_Handler
+#define WIRE_IT_HANDLER_3    SERCOM5_3_Handler
+
+static const uint8_t SDA = PIN_WIRE_SDA;
+static const uint8_t SCL = PIN_WIRE_SCL;
+
+/*
+ * USB
+ */
+#define PIN_USB_HOST_ENABLE (37ul)
+#define PIN_USB_DM          (38ul)
+#define PIN_USB_DP          (39ul)
+
+/*
+ * I2S Interfaces
+ */
+#define I2S_INTERFACES_COUNT 0
+
+// On-board QSPI Flash
+#define EXTERNAL_FLASH_DEVICES   GD25Q16C
+#define EXTERNAL_FLASH_USE_QSPI
+
+//QSPI Pins
+#define PIN_QSPI_SCK    (41u)
+#define PIN_QSPI_CS     (42u)
+#define PIN_QSPI_IO0    (43u)
+#define PIN_QSPI_IO1    (44u)
+#define PIN_QSPI_IO2    (45u)
+#define PIN_QSPI_IO3    (46u)
+
+#if !defined(VARIANT_QSPI_BAUD_DEFAULT)
+  // TODO: meaningful value for this
+  #define VARIANT_QSPI_BAUD_DEFAULT 5000000
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+ *        Arduino objects - C++ only
+ *----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+
+/*	=========================
+ *	===== SERCOM DEFINITION
+ *	=========================
+*/
+extern SERCOM sercom0;
+extern SERCOM sercom1;
+extern SERCOM sercom2;
+extern SERCOM sercom3;
+extern SERCOM sercom4;
+extern SERCOM sercom5;
+
+extern Uart Serial1;
+extern Uart Serial2;
+
+#endif
+
+// These serial port names are intended to allow libraries and architecture-neutral
+// sketches to automatically default to the correct port name for a particular type
+// of use.  For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN,
+// the first hardware serial port whose RX/TX pins are not dedicated to another use.
+//
+// SERIAL_PORT_MONITOR        Port which normally prints to the Arduino Serial Monitor
+//
+// SERIAL_PORT_USBVIRTUAL     Port which is USB virtual serial
+//
+// SERIAL_PORT_LINUXBRIDGE    Port which connects to a Linux system via Bridge library
+//
+// SERIAL_PORT_HARDWARE       Hardware serial port, physical RX & TX pins.
+//
+// SERIAL_PORT_HARDWARE_OPEN  Hardware serial ports which are open for use.  Their RX & TX
+//                            pins are NOT connected to anything by default.
+#define SERIAL_PORT_USBVIRTUAL      Serial
+#define SERIAL_PORT_MONITOR         Serial
+// Serial has no physical pins broken out, so it's not listed as HARDWARE port
+#define SERIAL_PORT_HARDWARE        Serial1
+#define SERIAL_PORT_HARDWARE_OPEN   Serial1
+
+#endif /* _VARIANT_MATRIX_PORTAL_M4_ */
+
diff --git a/variants/metro_m0/debug_scripts/variant.gdb b/variants/metro_m0/debug_scripts/variant.gdb
new file mode 100644
index 000000000..3c37ffde2
--- /dev/null
+++ b/variants/metro_m0/debug_scripts/variant.gdb
@@ -0,0 +1,31 @@
+#
+#  Arduino Zero OpenOCD script.
+#
+#  Copyright (c) 2014-2015 Arduino LLC. All right reserved.
+#
+#  This library is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 2.1 of the License, or (at your option) any later version.
+#
+#  This library is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#  See the GNU Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library; if not, write to the Free Software
+#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#
+
+# Define 'reset' command
+define reset
+
+info reg
+
+break main
+
+# End of 'reset' command
+end
+
+target remote | openocd -c "interface cmsis-dap" -c "set CHIPNAME at91samd21g18" -f target/at91samdXX.cfg -c "gdb_port pipe; log_output openocd.log"
diff --git a/variants/metro_m0/linker_scripts/gcc/flash_with_bootloader.ld b/variants/metro_m0/linker_scripts/gcc/flash_with_bootloader.ld
new file mode 100644
index 000000000..7d75f819d
--- /dev/null
+++ b/variants/metro_m0/linker_scripts/gcc/flash_with_bootloader.ld
@@ -0,0 +1,213 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* Linker script to configure memory regions.
+ * Need modifying for a specific board.
+ *   FLASH.ORIGIN: starting address of flash
+ *   FLASH.LENGTH: length of flash
+ *   RAM.ORIGIN: starting address of RAM bank 0
+ *   RAM.LENGTH: length of RAM bank 0
+ */
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000+0x2000, LENGTH = 0x00040000-0x2000 /* First 8KB used by bootloader */
+  RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ *   Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ *   __exidx_start
+ *   __exidx_end
+ *   __copy_table_start__
+ *   __copy_table_end__
+ *   __zero_table_start__
+ *   __zero_table_end__
+ *   __etext
+ *   __data_start__
+ *   __preinit_array_start
+ *   __preinit_array_end
+ *   __init_array_start
+ *   __init_array_end
+ *   __fini_array_start
+ *   __fini_array_end
+ *   __data_end__
+ *   __bss_start__
+ *   __bss_end__
+ *   __end__
+ *   end
+ *   __HeapLimit
+ *   __StackLimit
+ *   __StackTop
+ *   __stack
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+	.text :
+	{
+		__text_start__ = .;
+
+		KEEP(*(.isr_vector))
+		*(.text*)
+
+		KEEP(*(.init))
+		KEEP(*(.fini))
+
+		/* .ctors */
+		*crtbegin.o(.ctors)
+		*crtbegin?.o(.ctors)
+		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+		*(SORT(.ctors.*))
+		*(.ctors)
+
+		/* .dtors */
+ 		*crtbegin.o(.dtors)
+ 		*crtbegin?.o(.dtors)
+ 		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ 		*(SORT(.dtors.*))
+ 		*(.dtors)
+
+		*(.rodata*)
+
+		KEEP(*(.eh_frame*))
+	} > FLASH
+
+	.ARM.extab :
+	{
+		*(.ARM.extab* .gnu.linkonce.armextab.*)
+	} > FLASH
+
+	__exidx_start = .;
+	.ARM.exidx :
+	{
+		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
+	} > FLASH
+	__exidx_end = .;
+
+	/* To copy multiple ROM to RAM sections,
+	 * uncomment .copy.table section and,
+	 * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.copy.table :
+	{
+		. = ALIGN(4);
+		__copy_table_start__ = .;
+		LONG (__etext)
+		LONG (__data_start__)
+		LONG (__data_end__ - __data_start__)
+		LONG (__etext2)
+		LONG (__data2_start__)
+		LONG (__data2_end__ - __data2_start__)
+		__copy_table_end__ = .;
+	} > FLASH
+	*/
+
+	/* To clear multiple BSS sections,
+	 * uncomment .zero.table section and,
+	 * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.zero.table :
+	{
+		. = ALIGN(4);
+		__zero_table_start__ = .;
+		LONG (__bss_start__)
+		LONG (__bss_end__ - __bss_start__)
+		LONG (__bss2_start__)
+		LONG (__bss2_end__ - __bss2_start__)
+		__zero_table_end__ = .;
+	} > FLASH
+	*/
+
+	__etext = .;
+
+	.data : AT (__etext)
+	{
+		__data_start__ = .;
+		*(vtable)
+		*(.data*)
+
+		. = ALIGN(4);
+		/* preinit data */
+		PROVIDE_HIDDEN (__preinit_array_start = .);
+		KEEP(*(.preinit_array))
+		PROVIDE_HIDDEN (__preinit_array_end = .);
+
+		. = ALIGN(4);
+		/* init data */
+		PROVIDE_HIDDEN (__init_array_start = .);
+		KEEP(*(SORT(.init_array.*)))
+		KEEP(*(.init_array))
+		PROVIDE_HIDDEN (__init_array_end = .);
+
+
+		. = ALIGN(4);
+		/* finit data */
+		PROVIDE_HIDDEN (__fini_array_start = .);
+		KEEP(*(SORT(.fini_array.*)))
+		KEEP(*(.fini_array))
+		PROVIDE_HIDDEN (__fini_array_end = .);
+
+		KEEP(*(.jcr*))
+		. = ALIGN(16);
+		/* All data end */
+		__data_end__ = .;
+
+	} > RAM
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start__ = .;
+		*(.bss*)
+		*(COMMON)
+		. = ALIGN(4);
+		__bss_end__ = .;
+	} > RAM
+
+	.heap (COPY):
+	{
+		__end__ = .;
+		PROVIDE(end = .);
+		*(.heap*)
+		__HeapLimit = .;
+	} > RAM
+
+	/* .stack_dummy section doesn't contains any symbols. It is only
+	 * used for linker to calculate size of stack sections, and assign
+	 * values to stack symbols later */
+	.stack_dummy (COPY):
+	{
+		*(.stack*)
+	} > RAM
+
+	/* Set stack top to end of RAM, and stack limit move down by
+	 * size of stack_dummy section */
+	__StackTop = ORIGIN(RAM) + LENGTH(RAM);
+	__StackLimit = __StackTop - SIZEOF(.stack_dummy);
+	PROVIDE(__stack = __StackTop);
+
+	__ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ;
+
+	/* Check if data + heap + stack exceeds RAM limit */
+	ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
+}
diff --git a/variants/metro_m0/linker_scripts/gcc/flash_without_bootloader.ld b/variants/metro_m0/linker_scripts/gcc/flash_without_bootloader.ld
new file mode 100644
index 000000000..ebeeee37f
--- /dev/null
+++ b/variants/metro_m0/linker_scripts/gcc/flash_without_bootloader.ld
@@ -0,0 +1,214 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* Linker script to configure memory regions.
+ * Need modifying for a specific board.
+ *   FLASH.ORIGIN: starting address of flash
+ *   FLASH.LENGTH: length of flash
+ *   RAM.ORIGIN: starting address of RAM bank 0
+ *   RAM.LENGTH: length of RAM bank 0
+ */
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00040000
+  RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ *   Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ *   __exidx_start
+ *   __exidx_end
+ *   __copy_table_start__
+ *   __copy_table_end__
+ *   __zero_table_start__
+ *   __zero_table_end__
+ *   __etext
+ *   __data_start__
+ *   __preinit_array_start
+ *   __preinit_array_end
+ *   __init_array_start
+ *   __init_array_end
+ *   __fini_array_start
+ *   __fini_array_end
+ *   __data_end__
+ *   __bss_start__
+ *   __bss_end__
+ *   __end__
+ *   end
+ *   __HeapLimit
+ *   __StackLimit
+ *   __StackTop
+ *   __stack
+ *   __ram_end__
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+	.text :
+	{
+		__text_start__ = .;
+
+		KEEP(*(.isr_vector))
+		*(.text*)
+
+		KEEP(*(.init))
+		KEEP(*(.fini))
+
+		/* .ctors */
+		*crtbegin.o(.ctors)
+		*crtbegin?.o(.ctors)
+		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+		*(SORT(.ctors.*))
+		*(.ctors)
+
+		/* .dtors */
+ 		*crtbegin.o(.dtors)
+ 		*crtbegin?.o(.dtors)
+ 		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ 		*(SORT(.dtors.*))
+ 		*(.dtors)
+
+		*(.rodata*)
+
+		KEEP(*(.eh_frame*))
+	} > FLASH
+
+	.ARM.extab :
+	{
+		*(.ARM.extab* .gnu.linkonce.armextab.*)
+	} > FLASH
+
+	__exidx_start = .;
+	.ARM.exidx :
+	{
+		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
+	} > FLASH
+	__exidx_end = .;
+
+	/* To copy multiple ROM to RAM sections,
+	 * uncomment .copy.table section and,
+	 * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.copy.table :
+	{
+		. = ALIGN(4);
+		__copy_table_start__ = .;
+		LONG (__etext)
+		LONG (__data_start__)
+		LONG (__data_end__ - __data_start__)
+		LONG (__etext2)
+		LONG (__data2_start__)
+		LONG (__data2_end__ - __data2_start__)
+		__copy_table_end__ = .;
+	} > FLASH
+	*/
+
+	/* To clear multiple BSS sections,
+	 * uncomment .zero.table section and,
+	 * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.zero.table :
+	{
+		. = ALIGN(4);
+		__zero_table_start__ = .;
+		LONG (__bss_start__)
+		LONG (__bss_end__ - __bss_start__)
+		LONG (__bss2_start__)
+		LONG (__bss2_end__ - __bss2_start__)
+		__zero_table_end__ = .;
+	} > FLASH
+	*/
+
+	__etext = .;
+
+	.data : AT (__etext)
+	{
+		__data_start__ = .;
+		*(vtable)
+		*(.data*)
+
+		. = ALIGN(4);
+		/* preinit data */
+		PROVIDE_HIDDEN (__preinit_array_start = .);
+		KEEP(*(.preinit_array))
+		PROVIDE_HIDDEN (__preinit_array_end = .);
+
+		. = ALIGN(4);
+		/* init data */
+		PROVIDE_HIDDEN (__init_array_start = .);
+		KEEP(*(SORT(.init_array.*)))
+		KEEP(*(.init_array))
+		PROVIDE_HIDDEN (__init_array_end = .);
+
+
+		. = ALIGN(4);
+		/* finit data */
+		PROVIDE_HIDDEN (__fini_array_start = .);
+		KEEP(*(SORT(.fini_array.*)))
+		KEEP(*(.fini_array))
+		PROVIDE_HIDDEN (__fini_array_end = .);
+
+		KEEP(*(.jcr*))
+		. = ALIGN(16);
+		/* All data end */
+		__data_end__ = .;
+
+	} > RAM
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start__ = .;
+		*(.bss*)
+		*(COMMON)
+		. = ALIGN(4);
+		__bss_end__ = .;
+	} > RAM
+
+	.heap (COPY):
+	{
+		__end__ = .;
+		PROVIDE(end = .);
+		*(.heap*)
+		__HeapLimit = .;
+	} > RAM
+
+	/* .stack_dummy section doesn't contains any symbols. It is only
+	 * used for linker to calculate size of stack sections, and assign
+	 * values to stack symbols later */
+	.stack_dummy (COPY):
+	{
+		*(.stack*)
+	} > RAM
+
+	/* Set stack top to end of RAM, and stack limit move down by
+	 * size of stack_dummy section */
+	__StackTop = ORIGIN(RAM) + LENGTH(RAM) ;
+	__StackLimit = __StackTop - SIZEOF(.stack_dummy);
+	PROVIDE(__stack = __StackTop);
+
+	__ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ;
+
+	/* Check if data + heap + stack exceeds RAM limit */
+	ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
+}
diff --git a/variants/metro_m0/openocd_scripts/metro_m0.cfg b/variants/metro_m0/openocd_scripts/metro_m0.cfg
new file mode 100644
index 000000000..06b66f57a
--- /dev/null
+++ b/variants/metro_m0/openocd_scripts/metro_m0.cfg
@@ -0,0 +1,28 @@
+#
+#  Adafruit Metro M0 OpenOCD script.
+#
+#  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+#
+#  This library is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 2.1 of the License, or (at your option) any later version.
+#
+#  This library is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#  See the GNU Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library; if not, write to the Free Software
+#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#
+
+# chip name
+set CHIPNAME at91samd21g18
+set ENDIAN little
+
+# choose a port here
+set telnet_port 0
+
+source [find target/at91samdXX.cfg]
diff --git a/variants/metro_m0/pins_arduino.h b/variants/metro_m0/pins_arduino.h
new file mode 100644
index 000000000..db0e40c3d
--- /dev/null
+++ b/variants/metro_m0/pins_arduino.h
@@ -0,0 +1,21 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+// API compatibility
+#include "variant.h"
+
diff --git a/variants/metro_m0/variant.cpp b/variants/metro_m0/variant.cpp
new file mode 100644
index 000000000..b4836efe8
--- /dev/null
+++ b/variants/metro_m0/variant.cpp
@@ -0,0 +1,127 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#include "variant.h"
+
+/*
+ * Pins descriptions
+ */
+const PinDescription g_APinDescription[]=
+{
+  // 0..13 - Digital pins
+  // ----------------------
+  // 0/1 - SERCOM/UART (Serial1)
+  { PORTA, 11, PIO_SERCOM, (PIN_ATTR_DIGITAL), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_11 }, // RX: SERCOM0/PAD[3]
+  { PORTA, 10, PIO_SERCOM, (PIN_ATTR_DIGITAL), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_10 }, // TX: SERCOM0/PAD[2]
+
+  // 2..12
+  // Digital Low
+  { PORTA, 14, PIO_DIGITAL, (PIN_ATTR_DIGITAL), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_14 },
+  { PORTA,  9, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM0_CH1, TCC0_CH1, EXTERNAL_INT_9 }, // TCC0/WO[1]
+  { PORTA,  8, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM0_CH0, TCC0_CH0, EXTERNAL_INT_NMI },  // TCC0/WO[0]
+  { PORTA, 15, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM3_CH1, TC3_CH1, EXTERNAL_INT_15 }, // TC3/WO[1]
+  { PORTA, 20, PIO_TIMER_ALT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER_ALT), No_ADC_Channel, PWM0_CH6, TCC0_CH6, EXTERNAL_INT_4 }, // TCC0/WO[6]
+  { PORTA, 21, PIO_DIGITAL, (PIN_ATTR_DIGITAL), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_5 },
+
+  // Digital High
+  { PORTA,  6, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel6, PWM1_CH0, TCC1_CH0, EXTERNAL_INT_6 }, // TCC1/WO[0]
+  { PORTA,  7, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel7, PWM1_CH1, TCC1_CH1, EXTERNAL_INT_7 }, // TCC1/WO[1]
+  { PORTA, 18, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM3_CH0, TC3_CH0, EXTERNAL_INT_2 }, // TC3/WO[0]
+  { PORTA, 16, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM2_CH0, TCC2_CH0, EXTERNAL_INT_0 }, // TCC2/WO[0]
+  { PORTA, 19, PIO_TIMER_ALT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER_ALT), No_ADC_Channel, PWM0_CH3, TCC0_CH3, EXTERNAL_INT_3 }, // TCC0/WO[3]
+
+  // 13 (LED)
+  { PORTA, 17, PIO_PWM, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM2_CH1, TCC2_CH1, EXTERNAL_INT_1 }, // TCC2/WO[1]
+
+  // 14..19 - Analog pins
+  // --------------------
+  { PORTA,  2, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel0, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 }, // ADC/AIN[0]
+  { PORTB,  8, PIO_ANALOG, (PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel2, PWM4_CH0, TC4_CH0, EXTERNAL_INT_8 }, // ADC/AIN[2]
+  { PORTB,  9, PIO_ANALOG, (PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel3, PWM4_CH1, TC4_CH1, EXTERNAL_INT_9 }, // ADC/AIN[3]
+  { PORTA,  4, PIO_ANALOG, 0, ADC_Channel4, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_4 }, // ADC/AIN[4]
+  { PORTA,  5, PIO_ANALOG, 0, ADC_Channel5, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_5 }, // ADC/AIN[5]
+  { PORTB,  2, PIO_ANALOG, 0, ADC_Channel10, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 }, // ADC/AIN[10]
+
+
+  // Extra Analog pins! 20..25
+  { PORTA, 11, PIO_ANALOG, (PIN_ATTR_DIGITAL|PIN_ATTR_ANALOG), ADC_Channel19, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_11 }, // A6 same as D0
+  { PORTA, 10, PIO_ANALOG, (PIN_ATTR_DIGITAL|PIN_ATTR_ANALOG), ADC_Channel18, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_10 }, // A7 same as D1
+  { PORTA,  8, PIO_ANALOG, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER|PIN_ATTR_ANALOG), ADC_Channel16, PWM0_CH0, TCC0_CH0, EXTERNAL_INT_NMI },  // A8 same as D4
+  { PORTA,  9, PIO_ANALOG, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER|PIN_ATTR_ANALOG), ADC_Channel17, PWM0_CH1, TCC0_CH1, EXTERNAL_INT_9 },    // A9 same as D5
+  { PORTA,  6, PIO_ANALOG, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER|PIN_ATTR_ANALOG), ADC_Channel6, PWM1_CH0, TCC1_CH0, EXTERNAL_INT_6 }, // A10 same as D8
+  { PORTA,  7, PIO_ANALOG, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER|PIN_ATTR_ANALOG), ADC_Channel7, PWM1_CH1, TCC1_CH1, EXTERNAL_INT_7 }, // A11 same as D9
+
+  // 26..27 I2C pins (SDA/SCL)
+  // ----------------------
+  { PORTA, 22, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_6 }, // SDA: SERCOM3/PAD[0]
+  { PORTA, 23, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_7 }, // SCL: SERCOM3/PAD[1]
+
+  // 28..30 - SPI pins (ICSP:MISO,SCK,MOSI)
+  // ----------------------
+  { PORTA, 12, PIO_SERCOM_ALT, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_12 }, // MISO: SERCOM4/PAD[0]
+  { PORTB, 10, PIO_SERCOM_ALT, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_10 }, // MOSI: SERCOM4/PAD[2]
+  { PORTB, 11, PIO_SERCOM_ALT, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_11 }, // SCK: SERCOM4/PAD[3]
+
+  // 31..32 - RX/TX LEDS (PA31/PA27)
+  // --------------------
+  { PORTA, 31, PIO_OUTPUT, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // used as output only
+  { PORTA, 27, PIO_OUTPUT, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // used as output only
+
+  // 33..35 - USB
+  // --------------------
+  { PORTA, 28, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB Host enable
+  { PORTA, 24, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB/DM
+  { PORTA, 25, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB/DP
+
+  // 36..38 - Secondary SPI
+  // ----------------------
+  { PORTB, 03, PIO_SERCOM_ALT, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },  // SPI Flash MISO
+  { PORTB, 22, PIO_SERCOM_ALT, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },  // SPI FLash MOSI
+  { PORTB, 23, PIO_SERCOM_ALT, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },  // SPI FLash SCK
+  // 39 Secondary SPI SS
+  { PORTA, 13, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_13 }, // SPI Flash SS
+
+  // 40 - Internal NeoPixel
+  { PORTA, 30, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // used as output only
+
+  // 41 (AREF)
+  { PORTA, 3, PIO_ANALOG, PIN_ATTR_ANALOG, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // DAC/VREFP
+
+  // ----------------------
+  // 42 - Alternate use of A0 (DAC output)
+  { PORTA,  2, PIO_ANALOG, PIN_ATTR_ANALOG, DAC_Channel0, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 }, // DAC/VOUT
+} ;
+
+const void* g_apTCInstances[TCC_INST_NUM+TC_INST_NUM]={ TCC0, TCC1, TCC2, TC3, TC4, TC5 } ;
+
+// Multi-serial objects instantiation
+SERCOM sercom0( SERCOM0 ) ;
+SERCOM sercom1( SERCOM1 ) ;
+SERCOM sercom2( SERCOM2 ) ;
+SERCOM sercom3( SERCOM3 ) ;
+SERCOM sercom4( SERCOM4 ) ;
+SERCOM sercom5( SERCOM5 ) ;
+
+Uart Serial1( &sercom0, PIN_SERIAL1_RX, PIN_SERIAL1_TX, PAD_SERIAL1_RX, PAD_SERIAL1_TX ) ;
+
+void SERCOM0_Handler()
+{
+  Serial1.IrqHandler();
+}
+
diff --git a/variants/metro_m0/variant.h b/variants/metro_m0/variant.h
new file mode 100644
index 000000000..5aa2e8525
--- /dev/null
+++ b/variants/metro_m0/variant.h
@@ -0,0 +1,253 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _VARIANT_ARDUINO_ZERO_
+#define _VARIANT_ARDUINO_ZERO_
+
+// The definitions here needs a SAMD core >=1.6.10
+#define ARDUINO_SAMD_VARIANT_COMPLIANCE 10610
+
+/*----------------------------------------------------------------------------
+ *        Definitions
+ *----------------------------------------------------------------------------*/
+
+/** Frequency of the board main oscillator */
+#define VARIANT_MAINOSC		(32768ul)
+
+/** Master clock frequency */
+#define VARIANT_MCK	(F_CPU)
+
+/*----------------------------------------------------------------------------
+ *        Headers
+ *----------------------------------------------------------------------------*/
+
+#include "WVariant.h"
+
+#ifdef __cplusplus
+#include "SERCOM.h"
+#include "Uart.h"
+#endif // __cplusplus
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif // __cplusplus
+
+/*----------------------------------------------------------------------------
+ *        Pins
+ *----------------------------------------------------------------------------*/
+
+// Number of pins defined in PinDescription array
+#define PINS_COUNT           (26u)
+#define NUM_DIGITAL_PINS     (20u)
+#define NUM_ANALOG_INPUTS    (8u)
+#define NUM_ANALOG_OUTPUTS   (1u)
+#define analogInputToDigitalPin(p)  ((p < 6u) ? (p) + 14u : -1)
+
+#define digitalPinToPort(P)        ( &(PORT->Group[g_APinDescription[P].ulPort]) )
+#define digitalPinToBitMask(P)     ( 1 << g_APinDescription[P].ulPin )
+//#define analogInPinToBit(P)        ( )
+#define portOutputRegister(port)   ( &(port->OUT.reg) )
+#define portInputRegister(port)    ( &(port->IN.reg) )
+#define portModeRegister(port)     ( &(port->DIR.reg) )
+#define digitalPinHasPWM(P)        ( g_APinDescription[P].ulPWMChannel != NOT_ON_PWM || g_APinDescription[P].ulTCChannel != NOT_ON_TIMER )
+
+/*
+ * digitalPinToTimer(..) is AVR-specific and is not defined for SAMD
+ * architecture. If you need to check if a pin supports PWM you must
+ * use digitalPinHasPWM(..).
+ *
+ * https://github.com/arduino/Arduino/issues/1833
+ */
+// #define digitalPinToTimer(P)
+
+// LEDs
+#define PIN_LED_13           (13u)
+#define PIN_LED_RXL          (31u)
+#define PIN_LED_TXL          (32u)
+#define PIN_LED              PIN_LED_13
+#define PIN_LED2             PIN_LED_RXL
+#define PIN_LED3             PIN_LED_TXL
+#define LED_BUILTIN          PIN_LED_13
+#define NEOPIXEL_BUILTIN     (40u)
+#define PIN_NEOPIXEL         NEOPIXEL_BUILTIN
+
+/*
+ * Analog pins
+ */
+#define PIN_A0               (14ul)
+#define PIN_A1               (PIN_A0 + 1)
+#define PIN_A2               (PIN_A0 + 2)
+#define PIN_A3               (PIN_A0 + 3)
+#define PIN_A4               (PIN_A0 + 4)
+#define PIN_A5               (PIN_A0 + 5)
+#define PIN_A6               (PIN_A0 + 6)
+#define PIN_A7               (PIN_A0 + 7)
+#define PIN_A8               (PIN_A0 + 8)
+#define PIN_A9               (PIN_A0 + 9)
+#define PIN_A10              (PIN_A0 + 10)
+#define PIN_A11              (PIN_A0 + 11)
+#define PIN_DAC0             (14ul)
+
+static const uint8_t A0  = PIN_A0;
+static const uint8_t A1  = PIN_A1;
+static const uint8_t A2  = PIN_A2;
+static const uint8_t A3  = PIN_A3;
+static const uint8_t A4  = PIN_A4;
+static const uint8_t A5  = PIN_A5;
+static const uint8_t A6  = PIN_A6 ;
+static const uint8_t A7  = PIN_A7 ;
+static const uint8_t A8  = PIN_A8 ;
+static const uint8_t A9  = PIN_A9 ;
+static const uint8_t A10 = PIN_A10 ;
+static const uint8_t A11 = PIN_A11 ;
+
+static const uint8_t DAC0 = PIN_DAC0;
+
+#define ADC_RESOLUTION		12
+
+// Other pins
+#define PIN_ATN              (38ul)
+static const uint8_t ATN = PIN_ATN;
+
+// On-board SPI Flash
+#define EXTERNAL_FLASH_DEVICES  GD25Q16C
+#define EXTERNAL_FLASH_USE_SPI  SPI1
+#define EXTERNAL_FLASH_USE_CS   SS1
+
+/*
+ * Serial interfaces
+ */
+
+// Serial1
+#define PIN_SERIAL1_RX       (0ul)
+#define PIN_SERIAL1_TX       (1ul)
+#define PAD_SERIAL1_TX       (UART_TX_PAD_2)
+#define PAD_SERIAL1_RX       (SERCOM_RX_PAD_3)
+
+/*
+ * SPI Interfaces
+ */
+#define SPI_INTERFACES_COUNT 2
+
+#define PIN_SPI_MISO         (28u)
+#define PIN_SPI_MOSI         (29u)
+#define PIN_SPI_SCK          (30u)
+#define PERIPH_SPI           sercom4
+#define PAD_SPI_TX           SPI_PAD_2_SCK_3
+#define PAD_SPI_RX           SERCOM_RX_PAD_0
+
+static const uint8_t SS	  = PIN_A2 ;	// SERCOM4 last PAD is present on A2 but HW SS isn't used. Set here only for reference.
+static const uint8_t MOSI = PIN_SPI_MOSI ;
+static const uint8_t MISO = PIN_SPI_MISO ;
+static const uint8_t SCK  = PIN_SPI_SCK ;
+
+
+#define PIN_SPI1_MISO         (36u)
+#define PIN_SPI1_MOSI         (37u)
+#define PIN_SPI1_SCK          (38u)
+#define PERIPH_SPI1           sercom5
+#define PAD_SPI1_TX           SPI_PAD_2_SCK_3
+#define PAD_SPI1_RX           SERCOM_RX_PAD_1
+
+static const uint8_t SS1   = 39 ;	// HW SS isn't used. Set here only for reference.
+static const uint8_t MOSI1 = PIN_SPI_MOSI ;
+static const uint8_t MISO1 = PIN_SPI_MISO ;
+static const uint8_t SCK1  = PIN_SPI_SCK ;
+
+
+/*
+ * Wire Interfaces
+ */
+#define WIRE_INTERFACES_COUNT 1
+
+#define PIN_WIRE_SDA         (26u)
+#define PIN_WIRE_SCL         (27u)
+#define PERIPH_WIRE          sercom3
+#define WIRE_IT_HANDLER      SERCOM3_Handler
+
+static const uint8_t SDA = PIN_WIRE_SDA;
+static const uint8_t SCL = PIN_WIRE_SCL;
+
+/*
+ * USB
+ */
+#define PIN_USB_HOST_ENABLE (33ul)
+#define PIN_USB_DM          (34ul)
+#define PIN_USB_DP          (35ul)
+
+/*
+ * I2S Interfaces
+ */
+#define I2S_INTERFACES_COUNT 1
+
+#define I2S_DEVICE          0
+#define I2S_CLOCK_GENERATOR 3
+#define PIN_I2S_SD          (9u)
+#define PIN_I2S_SCK         (1u)
+#define PIN_I2S_FS          (0u)
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+ *        Arduino objects - C++ only
+ *----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+
+/*	=========================
+ *	===== SERCOM DEFINITION
+ *	=========================
+*/
+extern SERCOM sercom0;
+extern SERCOM sercom1;
+extern SERCOM sercom2;
+extern SERCOM sercom3;
+extern SERCOM sercom4;
+extern SERCOM sercom5;
+
+extern Uart Serial5;
+extern Uart Serial1;
+
+#endif
+
+// These serial port names are intended to allow libraries and architecture-neutral
+// sketches to automatically default to the correct port name for a particular type
+// of use.  For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN,
+// the first hardware serial port whose RX/TX pins are not dedicated to another use.
+//
+// SERIAL_PORT_MONITOR        Port which normally prints to the Arduino Serial Monitor
+//
+// SERIAL_PORT_USBVIRTUAL     Port which is USB virtual serial
+//
+// SERIAL_PORT_LINUXBRIDGE    Port which connects to a Linux system via Bridge library
+//
+// SERIAL_PORT_HARDWARE       Hardware serial port, physical RX & TX pins.
+//
+// SERIAL_PORT_HARDWARE_OPEN  Hardware serial ports which are open for use.  Their RX & TX
+//                            pins are NOT connected to anything by default.
+#define SERIAL_PORT_USBVIRTUAL      Serial
+#define SERIAL_PORT_MONITOR         Serial
+// Serial has no physical pins broken out, so it's not listed as HARDWARE port
+#define SERIAL_PORT_HARDWARE        Serial1
+#define SERIAL_PORT_HARDWARE_OPEN   Serial1
+
+#endif /* _VARIANT_ARDUINO_ZERO_ */
+
diff --git a/variants/metro_m4/linker_scripts/gcc/flash_with_bootloader.ld b/variants/metro_m4/linker_scripts/gcc/flash_with_bootloader.ld
new file mode 100644
index 000000000..5fe575a0d
--- /dev/null
+++ b/variants/metro_m4/linker_scripts/gcc/flash_with_bootloader.ld
@@ -0,0 +1,216 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* Linker script to configure memory regions.
+ * Need modifying for a specific board.
+ *   FLASH.ORIGIN: starting address of flash
+ *   FLASH.LENGTH: length of flash
+ *   RAM.ORIGIN: starting address of RAM bank 0
+ *   RAM.LENGTH: length of RAM bank 0
+ */
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000+0x4000, LENGTH = 0x80000-0x4000 /* First 16KB used by bootloader */
+  RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x30000
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ *   Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ *   __exidx_start
+ *   __exidx_end
+ *   __copy_table_start__
+ *   __copy_table_end__
+ *   __zero_table_start__
+ *   __zero_table_end__
+ *   __etext
+ *   __data_start__
+ *   __preinit_array_start
+ *   __preinit_array_end
+ *   __init_array_start
+ *   __init_array_end
+ *   __fini_array_start
+ *   __fini_array_end
+ *   __data_end__
+ *   __bss_start__
+ *   __bss_end__
+ *   __end__
+ *   end
+ *   __HeapLimit
+ *   __StackLimit
+ *   __StackTop
+ *   __stack
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+	.text :
+	{
+		__text_start__ = .;
+
+		KEEP(*(.sketch_boot))
+
+		. = ALIGN(0x4000);
+		KEEP(*(.isr_vector))
+		*(.text*)
+
+		KEEP(*(.init))
+		KEEP(*(.fini))
+
+		/* .ctors */
+		*crtbegin.o(.ctors)
+		*crtbegin?.o(.ctors)
+		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+		*(SORT(.ctors.*))
+		*(.ctors)
+
+		/* .dtors */
+ 		*crtbegin.o(.dtors)
+ 		*crtbegin?.o(.dtors)
+ 		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ 		*(SORT(.dtors.*))
+ 		*(.dtors)
+
+		*(.rodata*)
+
+		KEEP(*(.eh_frame*))
+	} > FLASH
+
+	.ARM.extab :
+	{
+		*(.ARM.extab* .gnu.linkonce.armextab.*)
+	} > FLASH
+
+	__exidx_start = .;
+	.ARM.exidx :
+	{
+		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
+	} > FLASH
+	__exidx_end = .;
+
+	/* To copy multiple ROM to RAM sections,
+	 * uncomment .copy.table section and,
+	 * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.copy.table :
+	{
+		. = ALIGN(4);
+		__copy_table_start__ = .;
+		LONG (__etext)
+		LONG (__data_start__)
+		LONG (__data_end__ - __data_start__)
+		LONG (__etext2)
+		LONG (__data2_start__)
+		LONG (__data2_end__ - __data2_start__)
+		__copy_table_end__ = .;
+	} > FLASH
+	*/
+
+	/* To clear multiple BSS sections,
+	 * uncomment .zero.table section and,
+	 * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.zero.table :
+	{
+		. = ALIGN(4);
+		__zero_table_start__ = .;
+		LONG (__bss_start__)
+		LONG (__bss_end__ - __bss_start__)
+		LONG (__bss2_start__)
+		LONG (__bss2_end__ - __bss2_start__)
+		__zero_table_end__ = .;
+	} > FLASH
+	*/
+
+	__etext = .;
+
+	.data : AT (__etext)
+	{
+		__data_start__ = .;
+		*(vtable)
+		*(.data*)
+
+		. = ALIGN(4);
+		/* preinit data */
+		PROVIDE_HIDDEN (__preinit_array_start = .);
+		KEEP(*(.preinit_array))
+		PROVIDE_HIDDEN (__preinit_array_end = .);
+
+		. = ALIGN(4);
+		/* init data */
+		PROVIDE_HIDDEN (__init_array_start = .);
+		KEEP(*(SORT(.init_array.*)))
+		KEEP(*(.init_array))
+		PROVIDE_HIDDEN (__init_array_end = .);
+
+
+		. = ALIGN(4);
+		/* finit data */
+		PROVIDE_HIDDEN (__fini_array_start = .);
+		KEEP(*(SORT(.fini_array.*)))
+		KEEP(*(.fini_array))
+		PROVIDE_HIDDEN (__fini_array_end = .);
+
+		KEEP(*(.jcr*))
+		. = ALIGN(16);
+		/* All data end */
+		__data_end__ = .;
+
+	} > RAM
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start__ = .;
+		*(.bss*)
+		*(COMMON)
+		. = ALIGN(4);
+		__bss_end__ = .;
+	} > RAM
+
+	.heap (COPY):
+	{
+		__end__ = .;
+		PROVIDE(end = .);
+		*(.heap*)
+		__HeapLimit = .;
+	} > RAM
+
+	/* .stack_dummy section doesn't contains any symbols. It is only
+	 * used for linker to calculate size of stack sections, and assign
+	 * values to stack symbols later */
+	.stack_dummy (COPY):
+	{
+		*(.stack*)
+	} > RAM
+
+	/* Set stack top to end of RAM, and stack limit move down by
+	 * size of stack_dummy section */
+	__StackTop = ORIGIN(RAM) + LENGTH(RAM);
+	__StackLimit = __StackTop - SIZEOF(.stack_dummy);
+	PROVIDE(__stack = __StackTop);
+
+	__ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ;
+
+	/* Check if data + heap + stack exceeds RAM limit */
+	ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
+}
diff --git a/variants/metro_m4/linker_scripts/gcc/flash_without_bootloader.ld b/variants/metro_m4/linker_scripts/gcc/flash_without_bootloader.ld
new file mode 100644
index 000000000..0123a0a23
--- /dev/null
+++ b/variants/metro_m4/linker_scripts/gcc/flash_without_bootloader.ld
@@ -0,0 +1,215 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* Linker script to configure memory regions.
+ * Need modifying for a specific board.
+ *   FLASH.ORIGIN: starting address of flash
+ *   FLASH.LENGTH: length of flash
+ *   RAM.ORIGIN: starting address of RAM bank 0
+ *   RAM.LENGTH: length of RAM bank 0
+ */
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x80000
+  RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x30000
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ *   Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ *   __exidx_start
+ *   __exidx_end
+ *   __copy_table_start__
+ *   __copy_table_end__
+ *   __zero_table_start__
+ *   __zero_table_end__
+ *   __etext
+ *   __data_start__
+ *   __preinit_array_start
+ *   __preinit_array_end
+ *   __init_array_start
+ *   __init_array_end
+ *   __fini_array_start
+ *   __fini_array_end
+ *   __data_end__
+ *   __bss_start__
+ *   __bss_end__
+ *   __end__
+ *   end
+ *   __HeapLimit
+ *   __StackLimit
+ *   __StackTop
+ *   __stack
+ *   __ram_end__
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+	.text :
+	{
+		__text_start__ = .;
+
+		. = ALIGN(4);
+		KEEP(*(.isr_vector))
+		*(.text*)
+
+		KEEP(*(.init))
+		KEEP(*(.fini))
+
+		/* .ctors */
+		*crtbegin.o(.ctors)
+		*crtbegin?.o(.ctors)
+		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+		*(SORT(.ctors.*))
+		*(.ctors)
+
+		/* .dtors */
+ 		*crtbegin.o(.dtors)
+ 		*crtbegin?.o(.dtors)
+ 		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ 		*(SORT(.dtors.*))
+ 		*(.dtors)
+
+		*(.rodata*)
+
+		KEEP(*(.eh_frame*))
+	} > FLASH
+
+	.ARM.extab :
+	{
+		*(.ARM.extab* .gnu.linkonce.armextab.*)
+	} > FLASH
+
+	__exidx_start = .;
+	.ARM.exidx :
+	{
+		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
+	} > FLASH
+	__exidx_end = .;
+
+	/* To copy multiple ROM to RAM sections,
+	 * uncomment .copy.table section and,
+	 * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.copy.table :
+	{
+		. = ALIGN(4);
+		__copy_table_start__ = .;
+		LONG (__etext)
+		LONG (__data_start__)
+		LONG (__data_end__ - __data_start__)
+		LONG (__etext2)
+		LONG (__data2_start__)
+		LONG (__data2_end__ - __data2_start__)
+		__copy_table_end__ = .;
+	} > FLASH
+	*/
+
+	/* To clear multiple BSS sections,
+	 * uncomment .zero.table section and,
+	 * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.zero.table :
+	{
+		. = ALIGN(4);
+		__zero_table_start__ = .;
+		LONG (__bss_start__)
+		LONG (__bss_end__ - __bss_start__)
+		LONG (__bss2_start__)
+		LONG (__bss2_end__ - __bss2_start__)
+		__zero_table_end__ = .;
+	} > FLASH
+	*/
+
+	__etext = .;
+
+	.data : AT (__etext)
+	{
+		__data_start__ = .;
+		*(vtable)
+		*(.data*)
+
+		. = ALIGN(4);
+		/* preinit data */
+		PROVIDE_HIDDEN (__preinit_array_start = .);
+		KEEP(*(.preinit_array))
+		PROVIDE_HIDDEN (__preinit_array_end = .);
+
+		. = ALIGN(4);
+		/* init data */
+		PROVIDE_HIDDEN (__init_array_start = .);
+		KEEP(*(SORT(.init_array.*)))
+		KEEP(*(.init_array))
+		PROVIDE_HIDDEN (__init_array_end = .);
+
+
+		. = ALIGN(4);
+		/* finit data */
+		PROVIDE_HIDDEN (__fini_array_start = .);
+		KEEP(*(SORT(.fini_array.*)))
+		KEEP(*(.fini_array))
+		PROVIDE_HIDDEN (__fini_array_end = .);
+
+		KEEP(*(.jcr*))
+		. = ALIGN(16);
+		/* All data end */
+		__data_end__ = .;
+
+	} > RAM
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start__ = .;
+		*(.bss*)
+		*(COMMON)
+		. = ALIGN(4);
+		__bss_end__ = .;
+	} > RAM
+
+	.heap (COPY):
+	{
+		__end__ = .;
+		PROVIDE(end = .);
+		*(.heap*)
+		__HeapLimit = .;
+	} > RAM
+
+	/* .stack_dummy section doesn't contains any symbols. It is only
+	 * used for linker to calculate size of stack sections, and assign
+	 * values to stack symbols later */
+	.stack_dummy (COPY):
+	{
+		*(.stack*)
+	} > RAM
+
+	/* Set stack top to end of RAM, and stack limit move down by
+	 * size of stack_dummy section */
+	__StackTop = ORIGIN(RAM) + LENGTH(RAM) ;
+	__StackLimit = __StackTop - SIZEOF(.stack_dummy);
+	PROVIDE(__stack = __StackTop);
+
+	__ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ;
+
+	/* Check if data + heap + stack exceeds RAM limit */
+	ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
+}
diff --git a/variants/metro_m4/pins_arduino.h b/variants/metro_m4/pins_arduino.h
new file mode 100644
index 000000000..db0e40c3d
--- /dev/null
+++ b/variants/metro_m4/pins_arduino.h
@@ -0,0 +1,21 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+// API compatibility
+#include "variant.h"
+
diff --git a/variants/metro_m4/variant.cpp b/variants/metro_m4/variant.cpp
new file mode 100644
index 000000000..528a25ce7
--- /dev/null
+++ b/variants/metro_m4/variant.cpp
@@ -0,0 +1,148 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "variant.h"
+
+/*
+ * Pins descriptions
+ */
+const PinDescription g_APinDescription[]=
+{
+  // 0..13 - Digital pins
+  // ----------------------
+  // 0/1 - SERCOM/UART (Serial1)
+  { PORTA, 23, PIO_SERCOM, PIN_ATTR_PWM_G, No_ADC_Channel, TCC0_CH3, TC4_CH1, EXTERNAL_INT_7 }, // RX: SERCOM3/PAD[1]
+  { PORTA, 22, PIO_SERCOM, PIN_ATTR_PWM_G, No_ADC_Channel, TCC0_CH2, TC4_CH0, EXTERNAL_INT_6 }, // TX: SERCOM3/PAD[0]
+
+  // 2..12
+  // Digital Low
+  { PORTB,  17, PIO_DIGITAL, PIN_ATTR_PWM_G, No_ADC_Channel, TCC0_CH5, NOT_ON_TIMER,  EXTERNAL_INT_1 }, // d2
+  { PORTB,  16, PIO_DIGITAL, PIN_ATTR_PWM_G, No_ADC_Channel, TCC0_CH4, NOT_ON_TIMER, EXTERNAL_INT_0 }, // d3
+  { PORTB,  13, PIO_DIGITAL, PIN_ATTR_PWM_F, No_ADC_Channel, TCC3_CH1, TC4_CH1, EXTERNAL_INT_13 }, // d4
+  { PORTB,  14, PIO_DIGITAL, PIN_ATTR_PWM_F, No_ADC_Channel, TCC4_CH0, TC5_CH0, EXTERNAL_INT_14 }, // d5
+  { PORTB,  15, PIO_DIGITAL, PIN_ATTR_PWM_F, No_ADC_Channel, TCC4_CH1, TC5_CH1, EXTERNAL_INT_15 }, // d6
+  { PORTB,  12, PIO_DIGITAL, PIN_ATTR_PWM_F, No_ADC_Channel, TCC3_CH0, TC4_CH0, EXTERNAL_INT_12 }, // d7
+
+  // Digital High
+  { PORTA,  21, PIO_DIGITAL, PIN_ATTR_PWM_G, No_ADC_Channel, TCC0_CH1, NOT_ON_TIMER, EXTERNAL_INT_5 }, // d8
+  { PORTA,  20, PIO_DIGITAL, PIN_ATTR_PWM_G, No_ADC_Channel, TCC0_CH0, NOT_ON_TIMER, EXTERNAL_INT_4 }, // d9
+  { PORTA,  18, PIO_DIGITAL, PIN_ATTR_PWM_F, No_ADC_Channel, TCC1_CH2, TC3_CH0, EXTERNAL_INT_2 }, // d10
+  { PORTA,  19, PIO_DIGITAL, PIN_ATTR_PWM_F, No_ADC_Channel, TCC1_CH3, TC3_CH1, EXTERNAL_INT_3 }, // d11
+  { PORTA,  17, PIO_DIGITAL, PIN_ATTR_PWM_F, No_ADC_Channel, TCC1_CH1, TC2_CH1, EXTERNAL_INT_1 }, // d12
+
+  // 13 (LED)
+  { PORTA,  16, PIO_DIGITAL, PIN_ATTR_PWM_F, No_ADC_Channel, TCC1_CH0, TC2_CH0, EXTERNAL_INT_0  },
+
+  // 14..19 - Analog pins
+  // --------------------
+  { PORTA,  2, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel0, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 },
+  { PORTA,  5, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel5, NOT_ON_PWM, TC0_CH1, EXTERNAL_INT_5 },
+  { PORTA,  6, PIO_ANALOG, (PIN_ATTR_ANALOG|PIN_ATTR_PWM_E), ADC_Channel6, TC1_CH0, TC1_CH0, EXTERNAL_INT_6 },
+  { PORTA,  4, PIO_ANALOG, (PIN_ATTR_ANALOG|PIN_ATTR_PWM_E), ADC_Channel4, TC0_CH0, TC0_CH0, EXTERNAL_INT_4 },
+  { PORTB,  8, PIO_ANALOG, (PIN_ATTR_ANALOG|PIN_ATTR_PWM_E), ADC_Channel2, TC4_CH0, TC4_CH0, EXTERNAL_INT_8 },
+  { PORTB,  9, PIO_ANALOG, (PIN_ATTR_ANALOG|PIN_ATTR_PWM_E), ADC_Channel3, TC4_CH1, TC4_CH1, EXTERNAL_INT_9 },
+
+  // Extra Analog pins! 20..21
+  { PORTB,  2, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel14, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 }, // same as sda
+  { PORTB,  3, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel15, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_3 }, //same as scl
+
+  // 22..23 I2C pins (SDA/SCL)
+  // ----------------------
+  { PORTB,  2, PIO_SERCOM_ALT, PIN_ATTR_PWM_F, No_ADC_Channel, TCC2_CH2, NOT_ON_TIMER, EXTERNAL_INT_2 }, //sda
+  { PORTB,  3, PIO_SERCOM_ALT, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_3 }, //scl
+
+  // 24..26 - SPI pins (ICSP:MISO,SCK,MOSI)
+  // ----------------------
+  { PORTA,  14, PIO_SERCOM, PIN_ATTR_PWM_E, No_ADC_Channel, TC3_CH0, TC3_CH0, EXTERNAL_INT_14 },
+  { PORTA,  13, PIO_SERCOM, PIN_ATTR_PWM_E, No_ADC_Channel, TC2_CH1, TC2_CH1, EXTERNAL_INT_13 },
+  { PORTA,  12, PIO_SERCOM, PIN_ATTR_PWM_E, No_ADC_Channel, TC2_CH0, TC2_CH0, EXTERNAL_INT_12 },
+
+  // 27..28 - RX/TX LEDS (PB06/PA27)
+  // --------------------
+  { PORTB, 6, PIO_OUTPUT, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_6 }, // used as output only
+  { PORTA, 27, PIO_OUTPUT, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_11 }, // used as output only
+
+  // 29..31 - USB
+  // --------------------
+  { PORTB, 7, PIO_COM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_7 }, // USB Host enable
+  { PORTA, 24, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_8 }, // USB/DM
+  { PORTA, 25, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_9 }, // USB/DP
+
+  // 32..34 - Secondary SPI
+  // ----------------------
+  { PORTA,  18, PIO_SERCOM, PIO_SERCOM, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2  }, //same as d10
+  { PORTA,  19, PIO_SERCOM, PIO_SERCOM, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_3  }, //same as d11
+  { PORTA,  17, PIO_SERCOM, PIO_SERCOM, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_1  }, //same as d12
+
+  // 35 - Secondary SPI cs
+  { PORTA,  16, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_0  }, //same as d10
+
+  // 36 (AREF)
+  { PORTA, 3, PIO_ANALOG, PIN_ATTR_ANALOG, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_3 }, // DAC/VREFP
+
+  // ----------------------
+  // 37 - 38 Alternate use of A0 and A1 (DAC output)
+  { PORTA,  2, PIO_ANALOG, PIN_ATTR_ANALOG, DAC_Channel0, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 }, // DAC/VOUT[0]
+  { PORTA,  5, PIO_ANALOG, PIN_ATTR_ANALOG, DAC_Channel1, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_5 }, // DAC/VOUT[1]
+
+  // 39 - LED #13 duplicate placeholder
+  { PORTA,  16, PIO_DIGITAL, PIN_ATTR_PWM_F, No_ADC_Channel, TCC1_CH0, TC2_CH0, EXTERNAL_INT_0  },
+
+  // 40 - Internal NeoPixel
+  { PORTB, 22, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_6 }, // used as output only
+
+  // ----------------------
+  // 41 - 46 QSPI (SCK, CS, IO0, IO1, IO2, IO3)
+  { PORTB, 10, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_10 },
+  { PORTB, 11, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_11 },
+  { PORTA, 8, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NMI },
+  { PORTA, 9, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_9 },
+  { PORTA, 10, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_10 },
+  { PORTA, 11, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_11 },
+} ;
+
+const void* g_apTCInstances[TCC_INST_NUM+TC_INST_NUM]={ TCC0, TCC1, TCC2, TCC3, TCC4, TC0, TC1, TC2, TC3, TC4, TC5 } ;
+const uint32_t GCLK_CLKCTRL_IDs[TCC_INST_NUM+TC_INST_NUM] = { TCC0_GCLK_ID, TCC1_GCLK_ID, TCC2_GCLK_ID, TCC3_GCLK_ID, TCC4_GCLK_ID, TC0_GCLK_ID, TC1_GCLK_ID, TC2_GCLK_ID, TC3_GCLK_ID, TC4_GCLK_ID, TC5_GCLK_ID } ;
+
+
+// Multi-serial objects instantiation
+SERCOM sercom0( SERCOM0 ) ;
+SERCOM sercom1( SERCOM1 ) ;
+SERCOM sercom2( SERCOM2 ) ;
+SERCOM sercom3( SERCOM3 ) ;
+SERCOM sercom4( SERCOM4 ) ;
+SERCOM sercom5( SERCOM5 ) ;
+
+Uart Serial1( &sercom3, PIN_SERIAL1_RX, PIN_SERIAL1_TX, PAD_SERIAL1_RX, PAD_SERIAL1_TX ) ;
+
+void SERCOM3_0_Handler()
+{
+  Serial1.IrqHandler();
+}
+void SERCOM3_1_Handler()
+{
+  Serial1.IrqHandler();
+}
+void SERCOM3_2_Handler()
+{
+  Serial1.IrqHandler();
+}
+void SERCOM3_3_Handler()
+{
+  Serial1.IrqHandler();
+}
diff --git a/variants/metro_m4/variant.h b/variants/metro_m4/variant.h
new file mode 100644
index 000000000..2b510e744
--- /dev/null
+++ b/variants/metro_m4/variant.h
@@ -0,0 +1,270 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _VARIANT_METRO_M4_
+#define _VARIANT_METRO_M4_
+
+// The definitions here needs a SAMD core >=1.6.10
+#define ARDUINO_SAMD_VARIANT_COMPLIANCE 10610
+
+/*----------------------------------------------------------------------------
+ *        Definitions
+ *----------------------------------------------------------------------------*/
+
+/** Frequency of the board main oscillator */
+#define VARIANT_MAINOSC		(32768ul)
+
+/** Master clock frequency */
+#define VARIANT_MCK	(F_CPU)
+
+#define VARIANT_GCLK0_FREQ (F_CPU)
+#define VARIANT_GCLK1_FREQ (48000000UL)
+#define VARIANT_GCLK2_FREQ (100000000UL)
+
+/*----------------------------------------------------------------------------
+ *        Headers
+ *----------------------------------------------------------------------------*/
+
+#include "WVariant.h"
+
+#ifdef __cplusplus
+#include "SERCOM.h"
+#include "Uart.h"
+#endif // __cplusplus
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif // __cplusplus
+
+/*----------------------------------------------------------------------------
+ *        Pins
+ *----------------------------------------------------------------------------*/
+
+// Number of pins defined in PinDescription array
+#define PINS_COUNT           (26u)
+#define NUM_DIGITAL_PINS     (20u)
+#define NUM_ANALOG_INPUTS    (8u)
+#define NUM_ANALOG_OUTPUTS   (2u)
+#define analogInputToDigitalPin(p)  ((p < 6u) ? (p) + 14u : -1)
+
+#define digitalPinToPort(P)        ( &(PORT->Group[g_APinDescription[P].ulPort]) )
+#define digitalPinToBitMask(P)     ( 1 << g_APinDescription[P].ulPin )
+//#define analogInPinToBit(P)        ( )
+#define portOutputRegister(port)   ( &(port->OUT.reg) )
+#define portInputRegister(port)    ( &(port->IN.reg) )
+#define portModeRegister(port)     ( &(port->DIR.reg) )
+#define digitalPinHasPWM(P)        ( g_APinDescription[P].ulPWMChannel != NOT_ON_PWM || g_APinDescription[P].ulTCChannel != NOT_ON_TIMER )
+
+/*
+ * digitalPinToTimer(..) is AVR-specific and is not defined for SAMD
+ * architecture. If you need to check if a pin supports PWM you must
+ * use digitalPinHasPWM(..).
+ *
+ * https://github.com/arduino/Arduino/issues/1833
+ */
+// #define digitalPinToTimer(P)
+
+// LEDs
+#define PIN_LED_13           (13u)
+#define PIN_LED_RXL          (27u)
+#define PIN_LED_TXL          (28u)
+#define PIN_LED              PIN_LED_13
+#define PIN_LED2             PIN_LED_RXL
+#define PIN_LED3             PIN_LED_TXL
+#define LED_BUILTIN          PIN_LED_13
+#define PIN_NEOPIXEL         (40)
+
+/*
+ * Analog pins
+ */
+#define PIN_A0               (14ul)
+#define PIN_A1               (PIN_A0 + 1)
+#define PIN_A2               (PIN_A0 + 2)
+#define PIN_A3               (PIN_A0 + 3)
+#define PIN_A4               (PIN_A0 + 4)
+#define PIN_A5               (PIN_A0 + 5)
+#define PIN_A6               (PIN_A0 + 6)
+#define PIN_A7               (PIN_A0 + 7)
+#define PIN_DAC0             PIN_A0
+#define PIN_DAC1             PIN_A1
+
+static const uint8_t A0  = PIN_A0;
+static const uint8_t A1  = PIN_A1;
+static const uint8_t A2  = PIN_A2;
+static const uint8_t A3  = PIN_A3;
+static const uint8_t A4  = PIN_A4;
+static const uint8_t A5  = PIN_A5;
+static const uint8_t A6  = PIN_A6 ;
+static const uint8_t A7  = PIN_A7 ;
+
+static const uint8_t DAC0 = PIN_DAC0;
+static const uint8_t DAC1 = PIN_DAC1;
+
+#define ADC_RESOLUTION		12
+
+// Other pins
+#define PIN_ATN              (39ul)
+static const uint8_t ATN = PIN_ATN;
+
+/*
+ * Serial interfaces
+ */
+
+// Serial1
+#define PIN_SERIAL1_RX       (0ul)
+#define PIN_SERIAL1_TX       (1ul)
+#define PAD_SERIAL1_TX       (UART_TX_PAD_0)
+#define PAD_SERIAL1_RX       (SERCOM_RX_PAD_1)
+
+/*
+ * SPI Interfaces
+ */
+#define SPI_INTERFACES_COUNT 1
+
+#define PIN_SPI_MISO         (24u)
+#define PIN_SPI_MOSI         (26u)
+#define PIN_SPI_SCK          (25u)
+#define PERIPH_SPI           sercom2
+#define PAD_SPI_TX           SPI_PAD_0_SCK_1
+#define PAD_SPI_RX           SERCOM_RX_PAD_2
+
+static const uint8_t SS	  = PIN_A2 ;	
+static const uint8_t MOSI = PIN_SPI_MOSI ;
+static const uint8_t MISO = PIN_SPI_MISO ;
+static const uint8_t SCK  = PIN_SPI_SCK ;
+
+
+/*
+ * Wire Interfaces
+ */
+#define WIRE_INTERFACES_COUNT 1
+
+#define PIN_WIRE_SDA         (22u)
+#define PIN_WIRE_SCL         (23u)
+#define PERIPH_WIRE          sercom5
+#define WIRE_IT_HANDLER      SERCOM5_Handler
+#define WIRE_IT_HANDLER_0    SERCOM5_0_Handler
+#define WIRE_IT_HANDLER_1    SERCOM5_1_Handler
+#define WIRE_IT_HANDLER_2    SERCOM5_2_Handler
+#define WIRE_IT_HANDLER_3    SERCOM5_3_Handler
+
+static const uint8_t SDA = PIN_WIRE_SDA;
+static const uint8_t SCL = PIN_WIRE_SCL;
+
+/*
+ * USB
+ */
+#define PIN_USB_HOST_ENABLE (29ul)
+#define PIN_USB_DM          (30ul)
+#define PIN_USB_DP          (31ul)
+
+/*
+ * I2S Interfaces
+ */
+#define I2S_INTERFACES_COUNT 1
+
+#define I2S_DEVICE          0
+#define I2S_CLOCK_GENERATOR 3
+
+#define PIN_I2S_SDO          (8u)
+#define PIN_I2S_SDI          (1u)
+#define PIN_I2S_SCK         (3u)
+#define PIN_I2S_FS          (9u)
+#define PIN_I2S_MCK			(2u)
+
+// On-board QSPI Flash
+#define EXTERNAL_FLASH_DEVICES   GD25Q16C
+#define EXTERNAL_FLASH_USE_QSPI
+
+//QSPI Pins
+#define PIN_QSPI_SCK	(41u)
+#define PIN_QSPI_CS	(42u)
+#define PIN_QSPI_IO0	(43u)
+#define PIN_QSPI_IO1	(44u)
+#define PIN_QSPI_IO2	(45u)
+#define PIN_QSPI_IO3	(46u)
+
+//PCC Pins
+#define PIN_PCC_DEN1    (PIN_SPI_MOSI)
+#define PIN_PCC_DEN2    (PIN_SPI_SCK)
+#define PIN_PCC_CLK     (PIN_SPI_MISO)
+#define PIN_PCC_D0      (13u)
+#define PIN_PCC_D1      (12u)
+#define PIN_PCC_D2      (10u)
+#define PIN_PCC_D3      (11u)
+#define PIN_PCC_D4      (9u)
+#define PIN_PCC_D5      (8u)
+#define PIN_PCC_D6      (1u)
+#define PIN_PCC_D7      (0u)
+#define PIN_PCC_D8      (5u)
+#define PIN_PCC_D9      (6u)
+
+#if !defined(VARIANT_QSPI_BAUD_DEFAULT)
+  // TODO: meaningful value for this
+  #define VARIANT_QSPI_BAUD_DEFAULT 5000000
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+ *        Arduino objects - C++ only
+ *----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+
+/*	=========================
+ *	===== SERCOM DEFINITION
+ *	=========================
+*/
+extern SERCOM sercom0;
+extern SERCOM sercom1;
+extern SERCOM sercom2;
+extern SERCOM sercom3;
+extern SERCOM sercom4;
+extern SERCOM sercom5;
+
+extern Uart Serial1;
+
+#endif
+
+// These serial port names are intended to allow libraries and architecture-neutral
+// sketches to automatically default to the correct port name for a particular type
+// of use.  For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN,
+// the first hardware serial port whose RX/TX pins are not dedicated to another use.
+//
+// SERIAL_PORT_MONITOR        Port which normally prints to the Arduino Serial Monitor
+//
+// SERIAL_PORT_USBVIRTUAL     Port which is USB virtual serial
+//
+// SERIAL_PORT_LINUXBRIDGE    Port which connects to a Linux system via Bridge library
+//
+// SERIAL_PORT_HARDWARE       Hardware serial port, physical RX & TX pins.
+//
+// SERIAL_PORT_HARDWARE_OPEN  Hardware serial ports which are open for use.  Their RX & TX
+//                            pins are NOT connected to anything by default.
+#define SERIAL_PORT_USBVIRTUAL      Serial
+#define SERIAL_PORT_MONITOR         Serial
+// Serial has no physical pins broken out, so it's not listed as HARDWARE port
+#define SERIAL_PORT_HARDWARE        Serial1
+#define SERIAL_PORT_HARDWARE_OPEN   Serial1
+
+#endif /* _VARIANT_METRO_M4_ */
+
diff --git a/variants/metro_m4_airlift/linker_scripts/gcc/flash_with_bootloader.ld b/variants/metro_m4_airlift/linker_scripts/gcc/flash_with_bootloader.ld
new file mode 100644
index 000000000..5fe575a0d
--- /dev/null
+++ b/variants/metro_m4_airlift/linker_scripts/gcc/flash_with_bootloader.ld
@@ -0,0 +1,216 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* Linker script to configure memory regions.
+ * Need modifying for a specific board.
+ *   FLASH.ORIGIN: starting address of flash
+ *   FLASH.LENGTH: length of flash
+ *   RAM.ORIGIN: starting address of RAM bank 0
+ *   RAM.LENGTH: length of RAM bank 0
+ */
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000+0x4000, LENGTH = 0x80000-0x4000 /* First 16KB used by bootloader */
+  RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x30000
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ *   Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ *   __exidx_start
+ *   __exidx_end
+ *   __copy_table_start__
+ *   __copy_table_end__
+ *   __zero_table_start__
+ *   __zero_table_end__
+ *   __etext
+ *   __data_start__
+ *   __preinit_array_start
+ *   __preinit_array_end
+ *   __init_array_start
+ *   __init_array_end
+ *   __fini_array_start
+ *   __fini_array_end
+ *   __data_end__
+ *   __bss_start__
+ *   __bss_end__
+ *   __end__
+ *   end
+ *   __HeapLimit
+ *   __StackLimit
+ *   __StackTop
+ *   __stack
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+	.text :
+	{
+		__text_start__ = .;
+
+		KEEP(*(.sketch_boot))
+
+		. = ALIGN(0x4000);
+		KEEP(*(.isr_vector))
+		*(.text*)
+
+		KEEP(*(.init))
+		KEEP(*(.fini))
+
+		/* .ctors */
+		*crtbegin.o(.ctors)
+		*crtbegin?.o(.ctors)
+		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+		*(SORT(.ctors.*))
+		*(.ctors)
+
+		/* .dtors */
+ 		*crtbegin.o(.dtors)
+ 		*crtbegin?.o(.dtors)
+ 		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ 		*(SORT(.dtors.*))
+ 		*(.dtors)
+
+		*(.rodata*)
+
+		KEEP(*(.eh_frame*))
+	} > FLASH
+
+	.ARM.extab :
+	{
+		*(.ARM.extab* .gnu.linkonce.armextab.*)
+	} > FLASH
+
+	__exidx_start = .;
+	.ARM.exidx :
+	{
+		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
+	} > FLASH
+	__exidx_end = .;
+
+	/* To copy multiple ROM to RAM sections,
+	 * uncomment .copy.table section and,
+	 * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.copy.table :
+	{
+		. = ALIGN(4);
+		__copy_table_start__ = .;
+		LONG (__etext)
+		LONG (__data_start__)
+		LONG (__data_end__ - __data_start__)
+		LONG (__etext2)
+		LONG (__data2_start__)
+		LONG (__data2_end__ - __data2_start__)
+		__copy_table_end__ = .;
+	} > FLASH
+	*/
+
+	/* To clear multiple BSS sections,
+	 * uncomment .zero.table section and,
+	 * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.zero.table :
+	{
+		. = ALIGN(4);
+		__zero_table_start__ = .;
+		LONG (__bss_start__)
+		LONG (__bss_end__ - __bss_start__)
+		LONG (__bss2_start__)
+		LONG (__bss2_end__ - __bss2_start__)
+		__zero_table_end__ = .;
+	} > FLASH
+	*/
+
+	__etext = .;
+
+	.data : AT (__etext)
+	{
+		__data_start__ = .;
+		*(vtable)
+		*(.data*)
+
+		. = ALIGN(4);
+		/* preinit data */
+		PROVIDE_HIDDEN (__preinit_array_start = .);
+		KEEP(*(.preinit_array))
+		PROVIDE_HIDDEN (__preinit_array_end = .);
+
+		. = ALIGN(4);
+		/* init data */
+		PROVIDE_HIDDEN (__init_array_start = .);
+		KEEP(*(SORT(.init_array.*)))
+		KEEP(*(.init_array))
+		PROVIDE_HIDDEN (__init_array_end = .);
+
+
+		. = ALIGN(4);
+		/* finit data */
+		PROVIDE_HIDDEN (__fini_array_start = .);
+		KEEP(*(SORT(.fini_array.*)))
+		KEEP(*(.fini_array))
+		PROVIDE_HIDDEN (__fini_array_end = .);
+
+		KEEP(*(.jcr*))
+		. = ALIGN(16);
+		/* All data end */
+		__data_end__ = .;
+
+	} > RAM
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start__ = .;
+		*(.bss*)
+		*(COMMON)
+		. = ALIGN(4);
+		__bss_end__ = .;
+	} > RAM
+
+	.heap (COPY):
+	{
+		__end__ = .;
+		PROVIDE(end = .);
+		*(.heap*)
+		__HeapLimit = .;
+	} > RAM
+
+	/* .stack_dummy section doesn't contains any symbols. It is only
+	 * used for linker to calculate size of stack sections, and assign
+	 * values to stack symbols later */
+	.stack_dummy (COPY):
+	{
+		*(.stack*)
+	} > RAM
+
+	/* Set stack top to end of RAM, and stack limit move down by
+	 * size of stack_dummy section */
+	__StackTop = ORIGIN(RAM) + LENGTH(RAM);
+	__StackLimit = __StackTop - SIZEOF(.stack_dummy);
+	PROVIDE(__stack = __StackTop);
+
+	__ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ;
+
+	/* Check if data + heap + stack exceeds RAM limit */
+	ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
+}
diff --git a/variants/metro_m4_airlift/linker_scripts/gcc/flash_without_bootloader.ld b/variants/metro_m4_airlift/linker_scripts/gcc/flash_without_bootloader.ld
new file mode 100644
index 000000000..0123a0a23
--- /dev/null
+++ b/variants/metro_m4_airlift/linker_scripts/gcc/flash_without_bootloader.ld
@@ -0,0 +1,215 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* Linker script to configure memory regions.
+ * Need modifying for a specific board.
+ *   FLASH.ORIGIN: starting address of flash
+ *   FLASH.LENGTH: length of flash
+ *   RAM.ORIGIN: starting address of RAM bank 0
+ *   RAM.LENGTH: length of RAM bank 0
+ */
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x80000
+  RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x30000
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ *   Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ *   __exidx_start
+ *   __exidx_end
+ *   __copy_table_start__
+ *   __copy_table_end__
+ *   __zero_table_start__
+ *   __zero_table_end__
+ *   __etext
+ *   __data_start__
+ *   __preinit_array_start
+ *   __preinit_array_end
+ *   __init_array_start
+ *   __init_array_end
+ *   __fini_array_start
+ *   __fini_array_end
+ *   __data_end__
+ *   __bss_start__
+ *   __bss_end__
+ *   __end__
+ *   end
+ *   __HeapLimit
+ *   __StackLimit
+ *   __StackTop
+ *   __stack
+ *   __ram_end__
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+	.text :
+	{
+		__text_start__ = .;
+
+		. = ALIGN(4);
+		KEEP(*(.isr_vector))
+		*(.text*)
+
+		KEEP(*(.init))
+		KEEP(*(.fini))
+
+		/* .ctors */
+		*crtbegin.o(.ctors)
+		*crtbegin?.o(.ctors)
+		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+		*(SORT(.ctors.*))
+		*(.ctors)
+
+		/* .dtors */
+ 		*crtbegin.o(.dtors)
+ 		*crtbegin?.o(.dtors)
+ 		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ 		*(SORT(.dtors.*))
+ 		*(.dtors)
+
+		*(.rodata*)
+
+		KEEP(*(.eh_frame*))
+	} > FLASH
+
+	.ARM.extab :
+	{
+		*(.ARM.extab* .gnu.linkonce.armextab.*)
+	} > FLASH
+
+	__exidx_start = .;
+	.ARM.exidx :
+	{
+		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
+	} > FLASH
+	__exidx_end = .;
+
+	/* To copy multiple ROM to RAM sections,
+	 * uncomment .copy.table section and,
+	 * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.copy.table :
+	{
+		. = ALIGN(4);
+		__copy_table_start__ = .;
+		LONG (__etext)
+		LONG (__data_start__)
+		LONG (__data_end__ - __data_start__)
+		LONG (__etext2)
+		LONG (__data2_start__)
+		LONG (__data2_end__ - __data2_start__)
+		__copy_table_end__ = .;
+	} > FLASH
+	*/
+
+	/* To clear multiple BSS sections,
+	 * uncomment .zero.table section and,
+	 * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.zero.table :
+	{
+		. = ALIGN(4);
+		__zero_table_start__ = .;
+		LONG (__bss_start__)
+		LONG (__bss_end__ - __bss_start__)
+		LONG (__bss2_start__)
+		LONG (__bss2_end__ - __bss2_start__)
+		__zero_table_end__ = .;
+	} > FLASH
+	*/
+
+	__etext = .;
+
+	.data : AT (__etext)
+	{
+		__data_start__ = .;
+		*(vtable)
+		*(.data*)
+
+		. = ALIGN(4);
+		/* preinit data */
+		PROVIDE_HIDDEN (__preinit_array_start = .);
+		KEEP(*(.preinit_array))
+		PROVIDE_HIDDEN (__preinit_array_end = .);
+
+		. = ALIGN(4);
+		/* init data */
+		PROVIDE_HIDDEN (__init_array_start = .);
+		KEEP(*(SORT(.init_array.*)))
+		KEEP(*(.init_array))
+		PROVIDE_HIDDEN (__init_array_end = .);
+
+
+		. = ALIGN(4);
+		/* finit data */
+		PROVIDE_HIDDEN (__fini_array_start = .);
+		KEEP(*(SORT(.fini_array.*)))
+		KEEP(*(.fini_array))
+		PROVIDE_HIDDEN (__fini_array_end = .);
+
+		KEEP(*(.jcr*))
+		. = ALIGN(16);
+		/* All data end */
+		__data_end__ = .;
+
+	} > RAM
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start__ = .;
+		*(.bss*)
+		*(COMMON)
+		. = ALIGN(4);
+		__bss_end__ = .;
+	} > RAM
+
+	.heap (COPY):
+	{
+		__end__ = .;
+		PROVIDE(end = .);
+		*(.heap*)
+		__HeapLimit = .;
+	} > RAM
+
+	/* .stack_dummy section doesn't contains any symbols. It is only
+	 * used for linker to calculate size of stack sections, and assign
+	 * values to stack symbols later */
+	.stack_dummy (COPY):
+	{
+		*(.stack*)
+	} > RAM
+
+	/* Set stack top to end of RAM, and stack limit move down by
+	 * size of stack_dummy section */
+	__StackTop = ORIGIN(RAM) + LENGTH(RAM) ;
+	__StackLimit = __StackTop - SIZEOF(.stack_dummy);
+	PROVIDE(__stack = __StackTop);
+
+	__ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ;
+
+	/* Check if data + heap + stack exceeds RAM limit */
+	ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
+}
diff --git a/variants/metro_m4_airlift/pins_arduino.h b/variants/metro_m4_airlift/pins_arduino.h
new file mode 100644
index 000000000..db0e40c3d
--- /dev/null
+++ b/variants/metro_m4_airlift/pins_arduino.h
@@ -0,0 +1,21 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+// API compatibility
+#include "variant.h"
+
diff --git a/variants/metro_m4_airlift/variant.cpp b/variants/metro_m4_airlift/variant.cpp
new file mode 100644
index 000000000..a160346fd
--- /dev/null
+++ b/variants/metro_m4_airlift/variant.cpp
@@ -0,0 +1,172 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "variant.h"
+
+/*
+ * Pins descriptions
+ */
+const PinDescription g_APinDescription[]=
+{
+  // 0..13 - Digital pins
+  // ----------------------
+  // 0/1 - SERCOM/UART (Serial1)
+  { PORTA, 23, PIO_SERCOM, PIN_ATTR_PWM_G, No_ADC_Channel, TCC0_CH3, TC4_CH1, EXTERNAL_INT_7 }, // RX: SERCOM3/PAD[1]
+  { PORTA, 22, PIO_SERCOM, PIN_ATTR_PWM_G, No_ADC_Channel, TCC0_CH2, TC4_CH0, EXTERNAL_INT_6 }, // TX: SERCOM3/PAD[0]
+
+  // 2..12
+  // Digital Low
+  { PORTB,  17, PIO_DIGITAL, PIN_ATTR_PWM_G, No_ADC_Channel, TCC0_CH5, NOT_ON_TIMER,  EXTERNAL_INT_1 },
+  { PORTB,  16, PIO_DIGITAL, PIN_ATTR_PWM_G, No_ADC_Channel, TCC0_CH4, NOT_ON_TIMER, EXTERNAL_INT_0 },
+  { PORTB,  13, PIO_DIGITAL, PIN_ATTR_PWM_F, No_ADC_Channel, TCC3_CH1, TC4_CH1, EXTERNAL_INT_13 },
+  { PORTB,  14, PIO_DIGITAL, PIN_ATTR_PWM_F, No_ADC_Channel, TCC4_CH0, TC5_CH0, EXTERNAL_INT_14 },
+  { PORTB,  15, PIO_DIGITAL, PIN_ATTR_PWM_F, No_ADC_Channel, TCC4_CH1, TC5_CH1, EXTERNAL_INT_15 },
+  { PORTB,  12, PIO_DIGITAL, PIN_ATTR_PWM_F, No_ADC_Channel, TCC3_CH0, TC4_CH0, EXTERNAL_INT_12 },
+
+  // Digital High
+  { PORTA,  21, PIO_DIGITAL, PIN_ATTR_PWM_G, No_ADC_Channel, TCC0_CH1, NOT_ON_TIMER, EXTERNAL_INT_5 },
+  { PORTA,  20, PIO_DIGITAL, PIN_ATTR_PWM_G, No_ADC_Channel, TCC0_CH0, NOT_ON_TIMER, EXTERNAL_INT_4 },
+  { PORTA,  18, PIO_DIGITAL, PIN_ATTR_PWM_F, No_ADC_Channel, TCC1_CH2, TC3_CH0, EXTERNAL_INT_2 },
+  { PORTA,  19, PIO_DIGITAL, PIN_ATTR_PWM_F, No_ADC_Channel, TCC1_CH3, TC3_CH1, EXTERNAL_INT_3 },
+  { PORTA,  17, PIO_DIGITAL, PIN_ATTR_PWM_F, No_ADC_Channel, TCC1_CH1, TC2_CH1, EXTERNAL_INT_1 },
+
+  // 13 (LED)
+  { PORTA,  16, PIO_DIGITAL, PIN_ATTR_PWM_F, No_ADC_Channel, TCC1_CH0, TC2_CH0, EXTERNAL_INT_0  },
+
+  // 14..19 - Analog pins
+  // --------------------
+  { PORTA,  2, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel0, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 },
+  { PORTA,  5, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel5, NOT_ON_PWM, TC0_CH1, EXTERNAL_INT_5 },
+  { PORTA,  6, PIO_ANALOG, (PIN_ATTR_ANALOG|PIN_ATTR_PWM_E), ADC_Channel6, TC1_CH0, TC1_CH0, EXTERNAL_INT_6 },
+  { PORTB,  0, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel12, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_0 }, // NOT SAME AS METRO M4!!
+  { PORTB,  8, PIO_ANALOG, (PIN_ATTR_ANALOG|PIN_ATTR_PWM_E), ADC_Channel2, TC4_CH0, TC4_CH0, EXTERNAL_INT_8 },
+  { PORTB,  9, PIO_ANALOG, (PIN_ATTR_ANALOG|PIN_ATTR_PWM_E), ADC_Channel3, TC4_CH1, TC4_CH1, EXTERNAL_INT_9 },
+
+  // Extra Analog pins! 20..21
+  { PORTB,  2, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel14, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 }, // same as sda
+  { PORTB,  3, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel15, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_3 }, //same as scl
+
+  // 22..23 I2C pins (SDA/SCL)
+  // ----------------------
+  { PORTB,  2, PIO_SERCOM_ALT, PIN_ATTR_PWM_F, No_ADC_Channel, TCC2_CH2, NOT_ON_TIMER, EXTERNAL_INT_2 }, //sda
+  { PORTB,  3, PIO_SERCOM_ALT, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_3 }, //scl
+
+  // 24..26 - SPI pins (ICSP:MISO,SCK,MOSI)
+  // ----------------------
+  { PORTA,  14, PIO_SERCOM, PIN_ATTR_PWM_E, No_ADC_Channel, TC3_CH0, TC3_CH0, EXTERNAL_INT_14 },
+  { PORTA,  13, PIO_SERCOM, PIN_ATTR_PWM_E, No_ADC_Channel, TC2_CH1, TC2_CH1, EXTERNAL_INT_13 },
+  { PORTA,  12, PIO_SERCOM, PIN_ATTR_PWM_E, No_ADC_Channel, TC2_CH0, TC2_CH0, EXTERNAL_INT_12 },
+
+  // 27..28 - RX/TX LEDS (PB06/PB07) NOT SAME AS METRO M4!!!
+  // --------------------
+  { PORTB, 6, PIO_OUTPUT, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_6 }, // used as output only
+  { PORTB, 7, PIO_OUTPUT, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_7 }, // used as output only
+
+  // 29..31 - USB
+  // --------------------
+  { PORTA, 27, PIO_COM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_11 }, // USB Host enable NOT SAME AS METRO M4!!!
+  { PORTA, 24, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_8 }, // USB/DM
+  { PORTA, 25, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_9 }, // USB/DP
+
+  // ESP RX, TX, RTS (32-34)
+  { PORTA,  7, PIO_SERCOM_ALT, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_7 }, // RX: SERCOM0.3
+  { PORTA,  4, PIO_SERCOM_ALT, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_4 }, // TX: SERCOM0.0
+  { PORTB, 23, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_7 },
+
+  // ESP GPIO0, CS, BUSY, RESET (35-38)
+  { PORTB,  1, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_1 },
+  { PORTA, 15, PIO_DIGITAL, PIN_ATTR_PWM_G, No_ADC_Channel, TCC1_CH3, TC3_CH0, EXTERNAL_INT_15 },
+  { PORTB,  4, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_4 },
+  { PORTB,  5, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_5 },
+
+  // 39 - SWO 
+  { PORTB, 30, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_6 }, // used as output only
+
+  // 40 - Internal NeoPixel
+  { PORTB, 22, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_6 }, // used as output only
+
+  // ----------------------
+  // 41 - 46 QSPI (SCK, CS, IO0, IO1, IO2, IO3)
+  { PORTB, 10, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_10 },
+  { PORTB, 11, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_11 },
+  { PORTA, 8, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NMI },
+  { PORTA, 9, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_9 },
+  { PORTA, 10, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_10 },
+  { PORTA, 11, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_11 },
+
+  // 47 (AREF)
+  { PORTA, 3, PIO_ANALOG, PIN_ATTR_ANALOG, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_3 }, // DAC/VREFP
+
+  // ----------------------
+  // 48 - 49 Alternate use of A0 and A1 (DAC output)
+  { PORTA,  2, PIO_ANALOG, PIN_ATTR_ANALOG, DAC_Channel0, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 }, // DAC/VOUT[0]
+  { PORTA,  5, PIO_ANALOG, PIN_ATTR_ANALOG, DAC_Channel1, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_5 }, // DAC/VOUT[1]
+
+} ;
+
+const void* g_apTCInstances[TCC_INST_NUM+TC_INST_NUM]={ TCC0, TCC1, TCC2, TCC3, TCC4, TC0, TC1, TC2, TC3, TC4, TC5 } ;
+const uint32_t GCLK_CLKCTRL_IDs[TCC_INST_NUM+TC_INST_NUM] = { TCC0_GCLK_ID, TCC1_GCLK_ID, TCC2_GCLK_ID, TCC3_GCLK_ID, TCC4_GCLK_ID, TC0_GCLK_ID, TC1_GCLK_ID, TC2_GCLK_ID, TC3_GCLK_ID, TC4_GCLK_ID, TC5_GCLK_ID } ;
+
+
+// Multi-serial objects instantiation
+SERCOM sercom0( SERCOM0 ) ;
+SERCOM sercom1( SERCOM1 ) ;
+SERCOM sercom2( SERCOM2 ) ;
+SERCOM sercom3( SERCOM3 ) ;
+SERCOM sercom4( SERCOM4 ) ;
+SERCOM sercom5( SERCOM5 ) ;
+
+// sercom for pins 0 & 1 UART
+Uart Serial1( &sercom3, PIN_SERIAL1_RX, PIN_SERIAL1_TX, PAD_SERIAL1_RX, PAD_SERIAL1_TX ) ;
+
+void SERCOM3_0_Handler()
+{
+  Serial1.IrqHandler();
+}
+void SERCOM3_1_Handler()
+{
+  Serial1.IrqHandler();
+}
+void SERCOM3_2_Handler()
+{
+  Serial1.IrqHandler();
+}
+void SERCOM3_3_Handler()
+{
+  Serial1.IrqHandler();
+}
+
+// sercom for internal ESP32 UART connection
+Uart Serial2( &sercom0, PIN_SERIAL2_RX, PIN_SERIAL2_TX, PAD_SERIAL2_RX, PAD_SERIAL2_TX ) ;
+
+void SERCOM0_0_Handler()
+{
+  Serial2.IrqHandler();
+}
+void SERCOM0_1_Handler()
+{
+  Serial2.IrqHandler();
+}
+void SERCOM0_2_Handler()
+{
+  Serial2.IrqHandler();
+}
+void SERCOM0_3_Handler()
+{
+  Serial2.IrqHandler();
+}
diff --git a/variants/metro_m4_airlift/variant.h b/variants/metro_m4_airlift/variant.h
new file mode 100644
index 000000000..d078f2099
--- /dev/null
+++ b/variants/metro_m4_airlift/variant.h
@@ -0,0 +1,289 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _VARIANT_METRO_M4_WIFI_
+#define _VARIANT_METRO_M4_WIFI_
+
+// The definitions here needs a SAMD core >=1.6.10
+#define ARDUINO_SAMD_VARIANT_COMPLIANCE 10610
+
+/*----------------------------------------------------------------------------
+ *        Definitions
+ *----------------------------------------------------------------------------*/
+
+/** Frequency of the board main oscillator */
+#define VARIANT_MAINOSC		(32768ul)
+
+/** Master clock frequency */
+#define VARIANT_MCK        (F_CPU)
+
+#define VARIANT_GCLK0_FREQ (F_CPU)
+#define VARIANT_GCLK1_FREQ (48000000UL)
+#define VARIANT_GCLK2_FREQ (100000000UL)
+
+/*----------------------------------------------------------------------------
+ *        Headers
+ *----------------------------------------------------------------------------*/
+
+#include "WVariant.h"
+
+#ifdef __cplusplus
+#include "SERCOM.h"
+#include "Uart.h"
+#endif // __cplusplus
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif // __cplusplus
+
+/*----------------------------------------------------------------------------
+ *        Pins
+ *----------------------------------------------------------------------------*/
+
+// Number of pins defined in PinDescription array
+#define PINS_COUNT           (49u)
+#define NUM_DIGITAL_PINS     (20u)
+#define NUM_ANALOG_INPUTS    (8u)
+#define NUM_ANALOG_OUTPUTS   (2u)
+#define analogInputToDigitalPin(p)  ((p < 6u) ? (p) + 14u : -1)
+
+#define digitalPinToPort(P)        ( &(PORT->Group[g_APinDescription[P].ulPort]) )
+#define digitalPinToBitMask(P)     ( 1 << g_APinDescription[P].ulPin )
+//#define analogInPinToBit(P)        ( )
+#define portOutputRegister(port)   ( &(port->OUT.reg) )
+#define portInputRegister(port)    ( &(port->IN.reg) )
+#define portModeRegister(port)     ( &(port->DIR.reg) )
+#define digitalPinHasPWM(P)        ( g_APinDescription[P].ulPWMChannel != NOT_ON_PWM || g_APinDescription[P].ulTCChannel != NOT_ON_TIMER )
+
+/*
+ * digitalPinToTimer(..) is AVR-specific and is not defined for SAMD
+ * architecture. If you need to check if a pin supports PWM you must
+ * use digitalPinHasPWM(..).
+ *
+ * https://github.com/arduino/Arduino/issues/1833
+ */
+// #define digitalPinToTimer(P)
+
+// LEDs
+#define PIN_LED_13           (13u)
+#define PIN_LED_RXL          (27u)
+#define PIN_LED_TXL          (28u)
+#define PIN_LED              PIN_LED_13
+#define PIN_LED2             PIN_LED_RXL
+#define PIN_LED3             PIN_LED_TXL
+#define LED_BUILTIN          PIN_LED_13
+
+/*
+ * Analog pins
+ */
+#define PIN_A0               (14ul)
+#define PIN_A1               (PIN_A0 + 1)
+#define PIN_A2               (PIN_A0 + 2)
+#define PIN_A3               (PIN_A0 + 3)
+#define PIN_A4               (PIN_A0 + 4)
+#define PIN_A5               (PIN_A0 + 5)
+
+#define PIN_DAC0             PIN_A0
+#define PIN_DAC1             PIN_A1
+
+static const uint8_t A0  = PIN_A0;
+static const uint8_t A1  = PIN_A1;
+static const uint8_t A2  = PIN_A2;
+static const uint8_t A3  = PIN_A3;
+static const uint8_t A4  = PIN_A4;
+static const uint8_t A5  = PIN_A5;
+
+static const uint8_t DAC0 = PIN_DAC0;
+static const uint8_t DAC1 = PIN_DAC1;
+
+#define ADC_RESOLUTION		12
+
+// Other pins
+#define PIN_ATN              (39ul)
+static const uint8_t ATN = PIN_ATN;
+
+
+/* WiFi interfaces */
+#define SerialESP32     Serial2
+#define SerialNina      SerialESP32
+#define SPIWIFI         SPI
+#define ESP32_GPIO0     35
+#define ESP32_RESETN    38
+#define SPIWIFI_SS      36
+#define SPIWIFI_ACK     37
+#define SPIWIFI_RESET   ESP32_RESETN
+#define NINA_GPIO0      ESP32_GPIO0
+#define NINA_RESETN     ESP32_RESETN
+#define NINA_ACK        SPIWIFI_ACK
+#define NINA_CTS        SPIWIFI_ACK
+#define NINA_RTS        NINA_GPIO0
+
+/*
+ * Serial interfaces
+ */
+
+// Serial1
+#define PIN_SERIAL1_RX       (0ul)
+#define PIN_SERIAL1_TX       (1ul)
+#define PAD_SERIAL1_RX       (SERCOM_RX_PAD_1)
+#define PAD_SERIAL1_TX       (UART_TX_PAD_0)
+
+// Serial2
+#define PIN_SERIAL2_RX       (32ul)
+#define PIN_SERIAL2_TX       (33ul)
+#define PAD_SERIAL2_RX       (SERCOM_RX_PAD_3)
+#define PAD_SERIAL2_TX       (UART_TX_PAD_0)
+
+/*
+ * SPI Interfaces
+ */
+#define SPI_INTERFACES_COUNT 1
+
+#define PIN_SPI_MISO         (24u)
+#define PIN_SPI_MOSI         (26u)
+#define PIN_SPI_SCK          (25u)
+#define PERIPH_SPI           sercom2
+#define PAD_SPI_TX           SPI_PAD_0_SCK_1
+#define PAD_SPI_RX           SERCOM_RX_PAD_2
+
+static const uint8_t SS	  = SPIWIFI_SS ;	
+static const uint8_t MOSI = PIN_SPI_MOSI ;
+static const uint8_t MISO = PIN_SPI_MISO ;
+static const uint8_t SCK  = PIN_SPI_SCK ;
+
+
+/*
+ * Wire Interfaces
+ */
+#define WIRE_INTERFACES_COUNT 1
+
+#define PIN_WIRE_SDA         (22u)
+#define PIN_WIRE_SCL         (23u)
+#define PERIPH_WIRE          sercom5
+#define WIRE_IT_HANDLER      SERCOM5_Handler
+#define WIRE_IT_HANDLER_0    SERCOM5_0_Handler
+#define WIRE_IT_HANDLER_1    SERCOM5_1_Handler
+#define WIRE_IT_HANDLER_2    SERCOM5_2_Handler
+#define WIRE_IT_HANDLER_3    SERCOM5_3_Handler
+
+static const uint8_t SDA = PIN_WIRE_SDA;
+static const uint8_t SCL = PIN_WIRE_SCL;
+
+/*
+ * USB
+ */
+#define PIN_USB_HOST_ENABLE (29ul)
+#define PIN_USB_DM          (30ul)
+#define PIN_USB_DP          (31ul)
+
+/*
+ * I2S Interfaces
+ */
+#define I2S_INTERFACES_COUNT 1
+
+#define I2S_DEVICE          0
+#define I2S_CLOCK_GENERATOR 3
+
+#define PIN_I2S_SDO         (8u)
+#define PIN_I2S_SDI         (1u)
+#define PIN_I2S_SCK         (3u)
+#define PIN_I2S_FS          (9u)
+#define PIN_I2S_MCK	    (2u)
+
+// On-board QSPI Flash
+#define EXTERNAL_FLASH_DEVICES   GD25Q16C
+#define EXTERNAL_FLASH_USE_QSPI
+
+//QSPI Pins
+#define PIN_QSPI_SCK	(41u)
+#define PIN_QSPI_CS	(42u)
+#define PIN_QSPI_IO0	(43u)
+#define PIN_QSPI_IO1	(44u)
+#define PIN_QSPI_IO2	(45u)
+#define PIN_QSPI_IO3	(46u)
+
+//PCC Pins
+#define PIN_PCC_DEN1    (PIN_SPI_MOSI)
+#define PIN_PCC_DEN2    (PIN_SPI_SCK)
+#define PIN_PCC_CLK     (PIN_SPI_MISO)
+#define PIN_PCC_D0      (13u)
+#define PIN_PCC_D1      (12u)
+#define PIN_PCC_D2      (10u)
+#define PIN_PCC_D3      (11u)
+#define PIN_PCC_D4      (9u)
+#define PIN_PCC_D5      (8u)
+#define PIN_PCC_D6      (1u)
+#define PIN_PCC_D7      (0u)
+#define PIN_PCC_D8      (5u)
+#define PIN_PCC_D9      (6u)
+
+#if !defined(VARIANT_QSPI_BAUD_DEFAULT)
+  // TODO: meaningful value for this
+  #define VARIANT_QSPI_BAUD_DEFAULT 5000000
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+ *        Arduino objects - C++ only
+ *----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+
+/*	=========================
+ *	===== SERCOM DEFINITION
+ *	=========================
+*/
+extern SERCOM sercom0;
+extern SERCOM sercom1;
+extern SERCOM sercom2;
+extern SERCOM sercom3;
+extern SERCOM sercom4;
+extern SERCOM sercom5;
+
+extern Uart Serial1;
+extern Uart Serial2;
+
+#endif
+
+// These serial port names are intended to allow libraries and architecture-neutral
+// sketches to automatically default to the correct port name for a particular type
+// of use.  For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN,
+// the first hardware serial port whose RX/TX pins are not dedicated to another use.
+//
+// SERIAL_PORT_MONITOR        Port which normally prints to the Arduino Serial Monitor
+//
+// SERIAL_PORT_USBVIRTUAL     Port which is USB virtual serial
+//
+// SERIAL_PORT_LINUXBRIDGE    Port which connects to a Linux system via Bridge library
+//
+// SERIAL_PORT_HARDWARE       Hardware serial port, physical RX & TX pins.
+//
+// SERIAL_PORT_HARDWARE_OPEN  Hardware serial ports which are open for use.  Their RX & TX
+//                            pins are NOT connected to anything by default.
+#define SERIAL_PORT_USBVIRTUAL      Serial
+#define SERIAL_PORT_MONITOR         Serial
+// Serial has no physical pins broken out, so it's not listed as HARDWARE port
+#define SERIAL_PORT_HARDWARE        Serial1
+#define SERIAL_PORT_HARDWARE_OPEN   Serial1
+
+#endif /* _VARIANT_METRO_M4_WIFI_ */
+
diff --git a/variants/mkr1000/variant.h b/variants/mkr1000/variant.h
index 1918dfadd..ce9f6c12c 100644
--- a/variants/mkr1000/variant.h
+++ b/variants/mkr1000/variant.h
@@ -30,7 +30,7 @@
 #define VARIANT_MAINOSC (32768ul)
 
 // Master clock frequency
-#define VARIANT_MCK     (48000000ul)
+#define VARIANT_MCK     (F_CPU)
 
 // Pins
 // ----
diff --git a/variants/mkrfox1200/variant.h b/variants/mkrfox1200/variant.h
index a6d7cad20..ade82e8ba 100644
--- a/variants/mkrfox1200/variant.h
+++ b/variants/mkrfox1200/variant.h
@@ -30,7 +30,7 @@
 #define VARIANT_MAINOSC (32768ul)
 
 // Master clock frequency
-#define VARIANT_MCK     (48000000ul)
+#define VARIANT_MCK     (F_CPU)
 
 // Pins
 // ----
diff --git a/variants/mkrgsm1400/variant.h b/variants/mkrgsm1400/variant.h
index d24aa23c0..f3c2832aa 100644
--- a/variants/mkrgsm1400/variant.h
+++ b/variants/mkrgsm1400/variant.h
@@ -30,7 +30,7 @@
 #define VARIANT_MAINOSC (32768ul)
 
 // Master clock frequency
-#define VARIANT_MCK     (48000000ul)
+#define VARIANT_MCK     (F_CPU)
 
 // Pins
 // ----
@@ -196,4 +196,4 @@ extern Uart Serial2;
 #define SerialGSM                   Serial2
 
 #define ARDUINO_GSM_COMPATIBILITY_WRAPPER
-#define GSM_DEFAULT_STREAM          SerialGSM
\ No newline at end of file
+#define GSM_DEFAULT_STREAM          SerialGSM
diff --git a/variants/mkrnb1500/variant.h b/variants/mkrnb1500/variant.h
index dd3e36742..3482528ce 100644
--- a/variants/mkrnb1500/variant.h
+++ b/variants/mkrnb1500/variant.h
@@ -30,7 +30,7 @@
 #define VARIANT_MAINOSC (32768ul)
 
 // Master clock frequency
-#define VARIANT_MCK     (48000000ul)
+#define VARIANT_MCK     (F_CPU)
 
 // Pins
 // ----
diff --git a/variants/mkrwan1300/variant.h b/variants/mkrwan1300/variant.h
index d398bba2a..7368e02f5 100644
--- a/variants/mkrwan1300/variant.h
+++ b/variants/mkrwan1300/variant.h
@@ -30,7 +30,7 @@
 #define VARIANT_MAINOSC (32768ul)
 
 // Master clock frequency
-#define VARIANT_MCK     (48000000ul)
+#define VARIANT_MCK (F_CPU)
 
 // Pins
 // ----
diff --git a/variants/mkrwifi1010/variant.h b/variants/mkrwifi1010/variant.h
index af7742553..dcd7f7775 100644
--- a/variants/mkrwifi1010/variant.h
+++ b/variants/mkrwifi1010/variant.h
@@ -30,7 +30,7 @@
 #define VARIANT_MAINOSC (32768ul)
 
 // Master clock frequency
-#define VARIANT_MCK     (48000000ul)
+#define VARIANT_MCK     (F_CPU)
 
 // Pins
 // ----
diff --git a/variants/mkrzero/variant.h b/variants/mkrzero/variant.h
index 04a92334d..ca59b5ab2 100644
--- a/variants/mkrzero/variant.h
+++ b/variants/mkrzero/variant.h
@@ -30,7 +30,7 @@
 #define VARIANT_MAINOSC (32768ul)
 
 // Master clock frequency
-#define VARIANT_MCK     (48000000ul)
+#define VARIANT_MCK     (F_CPU)
 
 // Pins
 // ----
diff --git a/variants/monster_m4sk/linker_scripts/gcc/flash_with_bootloader.ld b/variants/monster_m4sk/linker_scripts/gcc/flash_with_bootloader.ld
new file mode 100644
index 000000000..5fe575a0d
--- /dev/null
+++ b/variants/monster_m4sk/linker_scripts/gcc/flash_with_bootloader.ld
@@ -0,0 +1,216 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* Linker script to configure memory regions.
+ * Need modifying for a specific board.
+ *   FLASH.ORIGIN: starting address of flash
+ *   FLASH.LENGTH: length of flash
+ *   RAM.ORIGIN: starting address of RAM bank 0
+ *   RAM.LENGTH: length of RAM bank 0
+ */
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000+0x4000, LENGTH = 0x80000-0x4000 /* First 16KB used by bootloader */
+  RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x30000
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ *   Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ *   __exidx_start
+ *   __exidx_end
+ *   __copy_table_start__
+ *   __copy_table_end__
+ *   __zero_table_start__
+ *   __zero_table_end__
+ *   __etext
+ *   __data_start__
+ *   __preinit_array_start
+ *   __preinit_array_end
+ *   __init_array_start
+ *   __init_array_end
+ *   __fini_array_start
+ *   __fini_array_end
+ *   __data_end__
+ *   __bss_start__
+ *   __bss_end__
+ *   __end__
+ *   end
+ *   __HeapLimit
+ *   __StackLimit
+ *   __StackTop
+ *   __stack
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+	.text :
+	{
+		__text_start__ = .;
+
+		KEEP(*(.sketch_boot))
+
+		. = ALIGN(0x4000);
+		KEEP(*(.isr_vector))
+		*(.text*)
+
+		KEEP(*(.init))
+		KEEP(*(.fini))
+
+		/* .ctors */
+		*crtbegin.o(.ctors)
+		*crtbegin?.o(.ctors)
+		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+		*(SORT(.ctors.*))
+		*(.ctors)
+
+		/* .dtors */
+ 		*crtbegin.o(.dtors)
+ 		*crtbegin?.o(.dtors)
+ 		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ 		*(SORT(.dtors.*))
+ 		*(.dtors)
+
+		*(.rodata*)
+
+		KEEP(*(.eh_frame*))
+	} > FLASH
+
+	.ARM.extab :
+	{
+		*(.ARM.extab* .gnu.linkonce.armextab.*)
+	} > FLASH
+
+	__exidx_start = .;
+	.ARM.exidx :
+	{
+		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
+	} > FLASH
+	__exidx_end = .;
+
+	/* To copy multiple ROM to RAM sections,
+	 * uncomment .copy.table section and,
+	 * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.copy.table :
+	{
+		. = ALIGN(4);
+		__copy_table_start__ = .;
+		LONG (__etext)
+		LONG (__data_start__)
+		LONG (__data_end__ - __data_start__)
+		LONG (__etext2)
+		LONG (__data2_start__)
+		LONG (__data2_end__ - __data2_start__)
+		__copy_table_end__ = .;
+	} > FLASH
+	*/
+
+	/* To clear multiple BSS sections,
+	 * uncomment .zero.table section and,
+	 * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.zero.table :
+	{
+		. = ALIGN(4);
+		__zero_table_start__ = .;
+		LONG (__bss_start__)
+		LONG (__bss_end__ - __bss_start__)
+		LONG (__bss2_start__)
+		LONG (__bss2_end__ - __bss2_start__)
+		__zero_table_end__ = .;
+	} > FLASH
+	*/
+
+	__etext = .;
+
+	.data : AT (__etext)
+	{
+		__data_start__ = .;
+		*(vtable)
+		*(.data*)
+
+		. = ALIGN(4);
+		/* preinit data */
+		PROVIDE_HIDDEN (__preinit_array_start = .);
+		KEEP(*(.preinit_array))
+		PROVIDE_HIDDEN (__preinit_array_end = .);
+
+		. = ALIGN(4);
+		/* init data */
+		PROVIDE_HIDDEN (__init_array_start = .);
+		KEEP(*(SORT(.init_array.*)))
+		KEEP(*(.init_array))
+		PROVIDE_HIDDEN (__init_array_end = .);
+
+
+		. = ALIGN(4);
+		/* finit data */
+		PROVIDE_HIDDEN (__fini_array_start = .);
+		KEEP(*(SORT(.fini_array.*)))
+		KEEP(*(.fini_array))
+		PROVIDE_HIDDEN (__fini_array_end = .);
+
+		KEEP(*(.jcr*))
+		. = ALIGN(16);
+		/* All data end */
+		__data_end__ = .;
+
+	} > RAM
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start__ = .;
+		*(.bss*)
+		*(COMMON)
+		. = ALIGN(4);
+		__bss_end__ = .;
+	} > RAM
+
+	.heap (COPY):
+	{
+		__end__ = .;
+		PROVIDE(end = .);
+		*(.heap*)
+		__HeapLimit = .;
+	} > RAM
+
+	/* .stack_dummy section doesn't contains any symbols. It is only
+	 * used for linker to calculate size of stack sections, and assign
+	 * values to stack symbols later */
+	.stack_dummy (COPY):
+	{
+		*(.stack*)
+	} > RAM
+
+	/* Set stack top to end of RAM, and stack limit move down by
+	 * size of stack_dummy section */
+	__StackTop = ORIGIN(RAM) + LENGTH(RAM);
+	__StackLimit = __StackTop - SIZEOF(.stack_dummy);
+	PROVIDE(__stack = __StackTop);
+
+	__ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ;
+
+	/* Check if data + heap + stack exceeds RAM limit */
+	ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
+}
diff --git a/variants/monster_m4sk/linker_scripts/gcc/flash_without_bootloader.ld b/variants/monster_m4sk/linker_scripts/gcc/flash_without_bootloader.ld
new file mode 100644
index 000000000..0123a0a23
--- /dev/null
+++ b/variants/monster_m4sk/linker_scripts/gcc/flash_without_bootloader.ld
@@ -0,0 +1,215 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* Linker script to configure memory regions.
+ * Need modifying for a specific board.
+ *   FLASH.ORIGIN: starting address of flash
+ *   FLASH.LENGTH: length of flash
+ *   RAM.ORIGIN: starting address of RAM bank 0
+ *   RAM.LENGTH: length of RAM bank 0
+ */
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x80000
+  RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x30000
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ *   Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ *   __exidx_start
+ *   __exidx_end
+ *   __copy_table_start__
+ *   __copy_table_end__
+ *   __zero_table_start__
+ *   __zero_table_end__
+ *   __etext
+ *   __data_start__
+ *   __preinit_array_start
+ *   __preinit_array_end
+ *   __init_array_start
+ *   __init_array_end
+ *   __fini_array_start
+ *   __fini_array_end
+ *   __data_end__
+ *   __bss_start__
+ *   __bss_end__
+ *   __end__
+ *   end
+ *   __HeapLimit
+ *   __StackLimit
+ *   __StackTop
+ *   __stack
+ *   __ram_end__
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+	.text :
+	{
+		__text_start__ = .;
+
+		. = ALIGN(4);
+		KEEP(*(.isr_vector))
+		*(.text*)
+
+		KEEP(*(.init))
+		KEEP(*(.fini))
+
+		/* .ctors */
+		*crtbegin.o(.ctors)
+		*crtbegin?.o(.ctors)
+		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+		*(SORT(.ctors.*))
+		*(.ctors)
+
+		/* .dtors */
+ 		*crtbegin.o(.dtors)
+ 		*crtbegin?.o(.dtors)
+ 		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ 		*(SORT(.dtors.*))
+ 		*(.dtors)
+
+		*(.rodata*)
+
+		KEEP(*(.eh_frame*))
+	} > FLASH
+
+	.ARM.extab :
+	{
+		*(.ARM.extab* .gnu.linkonce.armextab.*)
+	} > FLASH
+
+	__exidx_start = .;
+	.ARM.exidx :
+	{
+		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
+	} > FLASH
+	__exidx_end = .;
+
+	/* To copy multiple ROM to RAM sections,
+	 * uncomment .copy.table section and,
+	 * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.copy.table :
+	{
+		. = ALIGN(4);
+		__copy_table_start__ = .;
+		LONG (__etext)
+		LONG (__data_start__)
+		LONG (__data_end__ - __data_start__)
+		LONG (__etext2)
+		LONG (__data2_start__)
+		LONG (__data2_end__ - __data2_start__)
+		__copy_table_end__ = .;
+	} > FLASH
+	*/
+
+	/* To clear multiple BSS sections,
+	 * uncomment .zero.table section and,
+	 * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.zero.table :
+	{
+		. = ALIGN(4);
+		__zero_table_start__ = .;
+		LONG (__bss_start__)
+		LONG (__bss_end__ - __bss_start__)
+		LONG (__bss2_start__)
+		LONG (__bss2_end__ - __bss2_start__)
+		__zero_table_end__ = .;
+	} > FLASH
+	*/
+
+	__etext = .;
+
+	.data : AT (__etext)
+	{
+		__data_start__ = .;
+		*(vtable)
+		*(.data*)
+
+		. = ALIGN(4);
+		/* preinit data */
+		PROVIDE_HIDDEN (__preinit_array_start = .);
+		KEEP(*(.preinit_array))
+		PROVIDE_HIDDEN (__preinit_array_end = .);
+
+		. = ALIGN(4);
+		/* init data */
+		PROVIDE_HIDDEN (__init_array_start = .);
+		KEEP(*(SORT(.init_array.*)))
+		KEEP(*(.init_array))
+		PROVIDE_HIDDEN (__init_array_end = .);
+
+
+		. = ALIGN(4);
+		/* finit data */
+		PROVIDE_HIDDEN (__fini_array_start = .);
+		KEEP(*(SORT(.fini_array.*)))
+		KEEP(*(.fini_array))
+		PROVIDE_HIDDEN (__fini_array_end = .);
+
+		KEEP(*(.jcr*))
+		. = ALIGN(16);
+		/* All data end */
+		__data_end__ = .;
+
+	} > RAM
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start__ = .;
+		*(.bss*)
+		*(COMMON)
+		. = ALIGN(4);
+		__bss_end__ = .;
+	} > RAM
+
+	.heap (COPY):
+	{
+		__end__ = .;
+		PROVIDE(end = .);
+		*(.heap*)
+		__HeapLimit = .;
+	} > RAM
+
+	/* .stack_dummy section doesn't contains any symbols. It is only
+	 * used for linker to calculate size of stack sections, and assign
+	 * values to stack symbols later */
+	.stack_dummy (COPY):
+	{
+		*(.stack*)
+	} > RAM
+
+	/* Set stack top to end of RAM, and stack limit move down by
+	 * size of stack_dummy section */
+	__StackTop = ORIGIN(RAM) + LENGTH(RAM) ;
+	__StackLimit = __StackTop - SIZEOF(.stack_dummy);
+	PROVIDE(__stack = __StackTop);
+
+	__ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ;
+
+	/* Check if data + heap + stack exceeds RAM limit */
+	ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
+}
diff --git a/variants/monster_m4sk/pins_arduino.h b/variants/monster_m4sk/pins_arduino.h
new file mode 100644
index 000000000..db0e40c3d
--- /dev/null
+++ b/variants/monster_m4sk/pins_arduino.h
@@ -0,0 +1,21 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+// API compatibility
+#include "variant.h"
+
diff --git a/variants/monster_m4sk/variant.cpp b/variants/monster_m4sk/variant.cpp
new file mode 100644
index 000000000..45a5dc0ce
--- /dev/null
+++ b/variants/monster_m4sk/variant.cpp
@@ -0,0 +1,107 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "variant.h"
+
+/*
+ * Pins descriptions
+ */
+
+// TCC0 IOSET6
+// TCC1 IOSET1
+// TCC2 IOSET1
+const PinDescription g_APinDescription[]=
+{
+  // 0..13 - Digital pins
+  // ----------------------
+  // 0/1 - PDM Mic (but could also be used for UART or serial)
+  { PORTA,  16, PIO_SERCOM_ALT, PIN_ATTR_PWM_F, No_ADC_Channel, TCC1_CH0, TC2_CH0, EXTERNAL_INT_0 }, // Uart RX on PDM pins (sercom 3.1/1.0)
+  { PORTA,  17, PIO_SERCOM_ALT, PIN_ATTR_PWM_F, No_ADC_Channel, TCC1_CH1, TC2_CH1, EXTERNAL_INT_1 }, // Uart TX on PDM pins (sercom 3.0/1.1)
+
+  // 2..12
+  // Digital Low
+  { PORTB,  8, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel2, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_8 }, // D2/A2
+  { PORTB,  9, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel3, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_9 }, // D3/A3
+  { PORTA,  4, PIO_DIGITAL, (PIN_ATTR_ANALOG|PIN_ATTR_PWM_E), ADC_Channel4, TC0_CH0, TC0_CH0, EXTERNAL_INT_4 }, // D4 Right TFT Reset
+  { PORTA,  6, PIO_DIGITAL, (PIN_ATTR_ANALOG|PIN_ATTR_PWM_E), ADC_Channel6, TC1_CH0, TC1_CH0, EXTERNAL_INT_6 }, // D5 Right TFT Chip Select
+  { PORTA,   7, PIO_DIGITAL, (PIN_ATTR_ANALOG|PIN_ATTR_PWM_E), ADC_Channel7, TC1_CH1, TC1_CH1, EXTERNAL_INT_7 },  // D6 Right TFT DC
+  { PORTA,  12, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, TC2_CH0, EXTERNAL_INT_12 }, // D7 Right TFT MOSI
+  { PORTA,  13, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, TC2_CH1, EXTERNAL_INT_13 }, // D8 Right TFT SCK
+  { PORTB,  23, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_7 },   // D9 Left TFT Chip Select
+  { PORTB,  22, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_6 }, // D10 Left TFT DC
+  { PORTB,   2, PIO_SERCOM_ALT, PIN_ATTR_ANALOG, ADC_Channel14, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 }, // D11 Left TFT MOSI
+  { PORTB,   3, PIO_SERCOM_ALT, PIN_ATTR_ANALOG, ADC_Channel15, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_3 }, // D12 Left TFT SCK
+
+  { PORTA, 27, PIO_DIGITAL, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // D13 Red LED
+
+  // 14..17 - Analog pins
+  // --------------------
+  { PORTA,  2, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel0, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 },
+  { PORTA,  5, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel5, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_5 },
+  { PORTB,  8, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel2, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_8 },
+  { PORTB,  9, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel3, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_9 },
+
+  // 18..19 I2C pins (SDA/SCL)
+  // ----------------------
+  { PORTA,  0, PIO_SERCOM_ALT, PIN_ATTR_PWM_E, No_ADC_Channel, TC2_CH0, TC2_CH0, EXTERNAL_INT_0 }, // SDA SERCOM 1.0
+  { PORTA,  1, PIO_SERCOM_ALT, PIN_ATTR_PWM_E, No_ADC_Channel, TC2_CH1, TC2_CH1, EXTERNAL_INT_1 }, // SCL SERCOM 1.1
+
+  { PORTA,  14, PIO_DIGITAL, PIN_ATTR_PWM_F, No_ADC_Channel, TCC2_CH0, TC3_CH0, EXTERNAL_INT_14 },   // D20 - Speaker enable
+  { PORTA,  23, PIO_DIGITAL, PIN_ATTR_PWM_G, No_ADC_Channel, TCC0_CH3, NOT_ON_TIMER, EXTERNAL_INT_7 }, // 21 - Backlight
+  { PORTA,  22, PIO_DIGITAL, PIN_ATTR_PWM_G, No_ADC_Channel, TCC0_CH2, NOT_ON_TIMER, EXTERNAL_INT_6 }, // 22 - LISIRQ
+
+  // D23 & D24 - SPI for PDM
+  { PORTA,  16, PIO_SERCOM_ALT, PIN_ATTR_PWM_F, No_ADC_Channel, TCC1_CH0, TC2_CH0, EXTERNAL_INT_0 }, // SPI clock for PDM SERCOM 3.1
+  { PORTA,  17, PIO_SERCOM_ALT, PIN_ATTR_PWM_F, No_ADC_Channel, TCC1_CH1, TC2_CH1, EXTERNAL_INT_1 }, // SPI MISO for PDM SERCOM 3.3
+
+  // 25..27 - USB
+  // --------------------
+  { PORTA, 21, PIO_DIGITAL, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_5 }, // not used
+  { PORTA, 24, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_8 }, // USB/DM
+  { PORTA, 25, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_9 }, // USB/DP
+
+  // 28 (AREF)
+  { PORTA, 3, PIO_ANALOG, PIN_ATTR_ANALOG, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_3 }, // DAC/VREFP
+
+
+  // ----------------------
+  // 29 - 34 QSPI (SCK, CS, IO0, IO1, IO2, IO3)
+  { PORTB, 10, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_10 },
+  { PORTB, 11, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_11 },
+  { PORTA, 8, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NMI },
+  { PORTA, 9, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_9 },
+  { PORTA, 10, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_10 },
+  { PORTA, 11, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_11 },
+
+  // 35 - SWD Clock
+  { PORTA, 30, PIO_DIGITAL, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_14 },
+  // 36- SWD Data
+  { PORTA, 31, PIO_DIGITAL, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_15 },
+
+} ;
+
+const void* g_apTCInstances[TCC_INST_NUM+TC_INST_NUM]={ TCC0, TCC1, TCC2, TC0, TC1, TC2, TC3 } ;
+const uint32_t GCLK_CLKCTRL_IDs[TCC_INST_NUM+TC_INST_NUM] = { TCC0_GCLK_ID, TCC1_GCLK_ID, TCC2_GCLK_ID, TC0_GCLK_ID, TC1_GCLK_ID, TC2_GCLK_ID, TC3_GCLK_ID } ;
+
+// Multi-serial objects instantiation
+SERCOM sercom0( SERCOM0 ) ;
+SERCOM sercom1( SERCOM1 ) ;
+SERCOM sercom2( SERCOM2 ) ;
+SERCOM sercom3( SERCOM3 ) ;
+SERCOM sercom4( SERCOM4 ) ;
+SERCOM sercom5( SERCOM5 ) ;
diff --git a/variants/monster_m4sk/variant.h b/variants/monster_m4sk/variant.h
new file mode 100644
index 000000000..eb3a283fe
--- /dev/null
+++ b/variants/monster_m4sk/variant.h
@@ -0,0 +1,258 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _VARIANT_MONSTER_M4SK_
+#define _VARIANT_MONSTER_M4SK_
+
+// The definitions here needs a SAMD core >=1.6.10
+#define ARDUINO_SAMD_VARIANT_COMPLIANCE 10610
+
+/*----------------------------------------------------------------------------
+ *        Definitions
+ *----------------------------------------------------------------------------*/
+
+/** Frequency of the board main oscillator */
+#define VARIANT_MAINOSC	   (32768ul)
+
+/** Master clock frequency */
+#define VARIANT_MCK        (F_CPU)
+
+#define VARIANT_GCLK0_FREQ (F_CPU)
+#define VARIANT_GCLK1_FREQ (48000000UL)
+#define VARIANT_GCLK2_FREQ (100000000UL)
+
+/*----------------------------------------------------------------------------
+ *        Headers
+ *----------------------------------------------------------------------------*/
+
+#include "WVariant.h"
+
+#ifdef __cplusplus
+#include "SERCOM.h"
+#include "Uart.h"
+#endif // __cplusplus
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif // __cplusplus
+
+/*----------------------------------------------------------------------------
+ *        Pins
+ *----------------------------------------------------------------------------*/
+
+// Number of pins defined in PinDescription array
+#define PINS_COUNT           (37u)
+#define NUM_DIGITAL_PINS     (37u)
+#define NUM_ANALOG_INPUTS    (4u)
+#define NUM_ANALOG_OUTPUTS   (2u)
+#define analogInputToDigitalPin(p)  ((p < NUM_ANALOG_INPUTS) ? (p) + PIN_A0 : -1)
+
+#define digitalPinToPort(P)        ( &(PORT->Group[g_APinDescription[P].ulPort]) )
+#define digitalPinToBitMask(P)     ( 1 << g_APinDescription[P].ulPin )
+//#define analogInPinToBit(P)        ( )
+#define portOutputRegister(port)   ( &(port->OUT.reg) )
+#define portInputRegister(port)    ( &(port->IN.reg) )
+#define portModeRegister(port)     ( &(port->DIR.reg) )
+#define digitalPinHasPWM(P)        ( g_APinDescription[P].ulPWMChannel != NOT_ON_PWM || g_APinDescription[P].ulTCChannel != NOT_ON_TIMER )
+
+/*
+ * digitalPinToTimer(..) is AVR-specific and is not defined for SAMD
+ * architecture. If you need to check if a pin supports PWM you must
+ * use digitalPinHasPWM(..).
+ *
+ * https://github.com/arduino/Arduino/issues/1833
+ */
+// #define digitalPinToTimer(P)
+
+// LEDs
+#define PIN_LED_13           (13u)
+#define PIN_LED              PIN_LED_13
+#define LED_BUILTIN          PIN_LED_13
+
+/*
+ * Analog pins
+ */
+#define PIN_A0               (14ul)
+#define PIN_A1               (PIN_A0 + 1)
+#define PIN_A2               (PIN_A0 + 2)
+#define PIN_A3               (PIN_A0 + 3)
+#define PIN_DAC0              PIN_A0
+#define PIN_DAC1              PIN_A1
+
+static const uint8_t A0  = PIN_A0;
+static const uint8_t A1  = PIN_A1;
+static const uint8_t A2  = PIN_A2;
+static const uint8_t A3  = PIN_A3;
+
+static const uint8_t DAC0 = PIN_DAC0;
+static const uint8_t DAC1 = PIN_DAC1;
+
+#define ADC_RESOLUTION		12
+
+// Other pins
+#define PIN_ATN              (26ul)
+static const uint8_t ATN = PIN_ATN;
+
+/*
+ * Serial interfaces
+ */
+
+// Serial1
+#define PIN_SERIAL1_RX       (0ul)      // sercom3
+#define PIN_SERIAL1_TX       (1ul)      // sercom3
+#define PAD_SERIAL1_RX       (SERCOM_RX_PAD_1)
+#define PAD_SERIAL1_TX       (UART_TX_PAD_0)
+
+/*
+ * SPI Interfaces
+ */
+#define SPI_INTERFACES_COUNT     3
+
+  // Right TFT
+#define PIN_SPI_MISO         (6u) // actually DC pin, ignored
+#define PIN_SPI_SCK          (8u)
+#define PIN_SPI_MOSI         (7u)
+#define PERIPH_SPI           sercom2
+#define PAD_SPI_TX           SPI_PAD_0_SCK_1
+#define PAD_SPI_RX           SERCOM_RX_PAD_3
+
+static const uint8_t SS	  = 5 ;	
+static const uint8_t MOSI = PIN_SPI_MOSI ;
+static const uint8_t MISO = PIN_SPI_MISO ;
+static const uint8_t SCK  = PIN_SPI_SCK ;
+
+  // Left TFT
+#define PIN_SPI1_MISO         (10u) // actually DC pin, ignored
+#define PIN_SPI1_SCK          (12u)
+#define PIN_SPI1_MOSI         (11u)
+#define PERIPH_SPI1           sercom5
+#define PAD_SPI1_TX           SPI_PAD_0_SCK_1
+#define PAD_SPI1_RX           SERCOM_RX_PAD_3
+
+static const uint8_t SS1   = 9 ;	
+static const uint8_t MOSI1 = PIN_SPI_MOSI ;
+static const uint8_t MISO1 = PIN_SPI_MISO ;
+static const uint8_t SCK1  = PIN_SPI_SCK ;
+
+// SPI for PDM
+#define PIN_SPI2_MISO         (23u)
+#define PIN_SPI2_SCK          (24u)
+#define PIN_SPI2_MOSI         (13u)  // actually LED, ignored
+#define PERIPH_SPI2           sercom3
+#define PAD_SPI2_TX           SPI_PAD_3_SCK_1
+#define PAD_SPI2_RX           SERCOM_RX_PAD_0
+
+static const uint8_t SS2   = 13 ;	 // also ignored
+static const uint8_t MOSI2 = PIN_SPI_MOSI ;
+static const uint8_t MISO2 = PIN_SPI_MISO ;
+static const uint8_t SCK2  = PIN_SPI_SCK ;
+
+
+/*
+ * Wire Interfaces
+ */
+#define WIRE_INTERFACES_COUNT 1
+
+#define PIN_WIRE_SDA         (18u)
+#define PIN_WIRE_SCL         (19u)
+#define PERIPH_WIRE          sercom1
+#define WIRE_IT_HANDLER      SERCOM1_Handler
+#define WIRE_IT_HANDLER_0    SERCOM1_0_Handler
+#define WIRE_IT_HANDLER_1    SERCOM1_1_Handler
+#define WIRE_IT_HANDLER_2    SERCOM1_2_Handler
+#define WIRE_IT_HANDLER_3    SERCOM1_3_Handler
+
+static const uint8_t SDA = PIN_WIRE_SDA;
+static const uint8_t SCL = PIN_WIRE_SCL;
+
+/*
+ * USB
+ */
+#define PIN_USB_HOST_ENABLE (25ul)
+#define PIN_USB_DM          (26ul)
+#define PIN_USB_DP          (27ul)
+
+/*
+ * I2S Interfaces
+ */
+#define I2S_INTERFACES_COUNT 0
+
+#define I2S_DEVICE          0
+// no I2S on G19!
+
+// On-board QSPI Flash
+#define EXTERNAL_FLASH_DEVICES   GD25Q64C
+#define EXTERNAL_FLASH_USE_QSPI
+
+//QSPI Pins
+#define PIN_QSPI_SCK	(29u)
+#define PIN_QSPI_CS	(30u)
+#define PIN_QSPI_IO0	(31u)
+#define PIN_QSPI_IO1	(32u)
+#define PIN_QSPI_IO2	(33u)
+#define PIN_QSPI_IO3	(34u)
+
+#if !defined(VARIANT_QSPI_BAUD_DEFAULT)
+  // TODO: meaningful value for this
+  #define VARIANT_QSPI_BAUD_DEFAULT 5000000
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+ *        Arduino objects - C++ only
+ *----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+
+/*	=========================
+ *	===== SERCOM DEFINITION
+ *	=========================
+*/
+extern SERCOM sercom0;
+extern SERCOM sercom1;
+extern SERCOM sercom2;
+extern SERCOM sercom3;
+extern SERCOM sercom4;
+extern SERCOM sercom5;
+
+#endif
+
+// These serial port names are intended to allow libraries and architecture-neutral
+// sketches to automatically default to the correct port name for a particular type
+// of use.  For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN,
+// the first hardware serial port whose RX/TX pins are not dedicated to another use.
+//
+// SERIAL_PORT_MONITOR        Port which normally prints to the Arduino Serial Monitor
+//
+// SERIAL_PORT_USBVIRTUAL     Port which is USB virtual serial
+//
+// SERIAL_PORT_LINUXBRIDGE    Port which connects to a Linux system via Bridge library
+//
+// SERIAL_PORT_HARDWARE       Hardware serial port, physical RX & TX pins.
+//
+// SERIAL_PORT_HARDWARE_OPEN  Hardware serial ports which are open for use.  Their RX & TX
+//                            pins are NOT connected to anything by default.
+#define SERIAL_PORT_USBVIRTUAL      Serial
+#define SERIAL_PORT_MONITOR         Serial
+
+#endif /* _MONSTER_M4SK_ */
+
diff --git a/variants/neokeytrinkey_m0/debug_scripts/variant.gdb b/variants/neokeytrinkey_m0/debug_scripts/variant.gdb
new file mode 100644
index 000000000..13ee2a173
--- /dev/null
+++ b/variants/neokeytrinkey_m0/debug_scripts/variant.gdb
@@ -0,0 +1,31 @@
+#
+#  Arduino Zero OpenOCD script.
+#
+#  Copyright (c) 2014-2015 Arduino LLC. All right reserved.
+#
+#  This library is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 2.1 of the License, or (at your option) any later version.
+#
+#  This library is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#  See the GNU Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library; if not, write to the Free Software
+#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#
+
+# Define 'reset' command
+define reset
+
+info reg
+
+break main
+
+# End of 'reset' command
+end
+
+target remote | openocd -c "interface cmsis-dap" -c "set CHIPNAME at91samd21e18" -f target/at91samdXX.cfg -c "gdb_port pipe; log_output openocd.log"
diff --git a/variants/neokeytrinkey_m0/linker_scripts/gcc/flash_with_bootloader.ld b/variants/neokeytrinkey_m0/linker_scripts/gcc/flash_with_bootloader.ld
new file mode 100644
index 000000000..357946455
--- /dev/null
+++ b/variants/neokeytrinkey_m0/linker_scripts/gcc/flash_with_bootloader.ld
@@ -0,0 +1,216 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* Linker script to configure memory regions.
+ * Need modifying for a specific board.
+ *   FLASH.ORIGIN: starting address of flash
+ *   FLASH.LENGTH: length of flash
+ *   RAM.ORIGIN: starting address of RAM bank 0
+ *   RAM.LENGTH: length of RAM bank 0
+ */
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000+0x2000, LENGTH = 0x00040000-0x2000 /* First 8KB used by bootloader */
+  RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ *   Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ *   __exidx_start
+ *   __exidx_end
+ *   __copy_table_start__
+ *   __copy_table_end__
+ *   __zero_table_start__
+ *   __zero_table_end__
+ *   __etext
+ *   __data_start__
+ *   __preinit_array_start
+ *   __preinit_array_end
+ *   __init_array_start
+ *   __init_array_end
+ *   __fini_array_start
+ *   __fini_array_end
+ *   __data_end__
+ *   __bss_start__
+ *   __bss_end__
+ *   __end__
+ *   end
+ *   __HeapLimit
+ *   __StackLimit
+ *   __StackTop
+ *   __stack
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+	.text :
+	{
+		__text_start__ = .;
+
+		KEEP(*(.sketch_boot))
+
+		. = ALIGN(0x2000);
+		KEEP(*(.isr_vector))
+		*(.text*)
+
+		KEEP(*(.init))
+		KEEP(*(.fini))
+
+		/* .ctors */
+		*crtbegin.o(.ctors)
+		*crtbegin?.o(.ctors)
+		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+		*(SORT(.ctors.*))
+		*(.ctors)
+
+		/* .dtors */
+ 		*crtbegin.o(.dtors)
+ 		*crtbegin?.o(.dtors)
+ 		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ 		*(SORT(.dtors.*))
+ 		*(.dtors)
+
+		*(.rodata*)
+
+		KEEP(*(.eh_frame*))
+	} > FLASH
+
+	.ARM.extab :
+	{
+		*(.ARM.extab* .gnu.linkonce.armextab.*)
+	} > FLASH
+
+	__exidx_start = .;
+	.ARM.exidx :
+	{
+		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
+	} > FLASH
+	__exidx_end = .;
+
+	/* To copy multiple ROM to RAM sections,
+	 * uncomment .copy.table section and,
+	 * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.copy.table :
+	{
+		. = ALIGN(4);
+		__copy_table_start__ = .;
+		LONG (__etext)
+		LONG (__data_start__)
+		LONG (__data_end__ - __data_start__)
+		LONG (__etext2)
+		LONG (__data2_start__)
+		LONG (__data2_end__ - __data2_start__)
+		__copy_table_end__ = .;
+	} > FLASH
+	*/
+
+	/* To clear multiple BSS sections,
+	 * uncomment .zero.table section and,
+	 * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.zero.table :
+	{
+		. = ALIGN(4);
+		__zero_table_start__ = .;
+		LONG (__bss_start__)
+		LONG (__bss_end__ - __bss_start__)
+		LONG (__bss2_start__)
+		LONG (__bss2_end__ - __bss2_start__)
+		__zero_table_end__ = .;
+	} > FLASH
+	*/
+
+	__etext = .;
+
+	.data : AT (__etext)
+	{
+		__data_start__ = .;
+		*(vtable)
+		*(.data*)
+
+		. = ALIGN(4);
+		/* preinit data */
+		PROVIDE_HIDDEN (__preinit_array_start = .);
+		KEEP(*(.preinit_array))
+		PROVIDE_HIDDEN (__preinit_array_end = .);
+
+		. = ALIGN(4);
+		/* init data */
+		PROVIDE_HIDDEN (__init_array_start = .);
+		KEEP(*(SORT(.init_array.*)))
+		KEEP(*(.init_array))
+		PROVIDE_HIDDEN (__init_array_end = .);
+
+
+		. = ALIGN(4);
+		/* finit data */
+		PROVIDE_HIDDEN (__fini_array_start = .);
+		KEEP(*(SORT(.fini_array.*)))
+		KEEP(*(.fini_array))
+		PROVIDE_HIDDEN (__fini_array_end = .);
+
+		KEEP(*(.jcr*))
+		. = ALIGN(16);
+		/* All data end */
+		__data_end__ = .;
+
+	} > RAM
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start__ = .;
+		*(.bss*)
+		*(COMMON)
+		. = ALIGN(4);
+		__bss_end__ = .;
+	} > RAM
+
+	.heap (COPY):
+	{
+		__end__ = .;
+		PROVIDE(end = .);
+		*(.heap*)
+		__HeapLimit = .;
+	} > RAM
+
+	/* .stack_dummy section doesn't contains any symbols. It is only
+	 * used for linker to calculate size of stack sections, and assign
+	 * values to stack symbols later */
+	.stack_dummy (COPY):
+	{
+		*(.stack*)
+	} > RAM
+
+	/* Set stack top to end of RAM, and stack limit move down by
+	 * size of stack_dummy section */
+	__StackTop = ORIGIN(RAM) + LENGTH(RAM);
+	__StackLimit = __StackTop - SIZEOF(.stack_dummy);
+	PROVIDE(__stack = __StackTop);
+
+	__ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ;
+
+	/* Check if data + heap + stack exceeds RAM limit */
+	ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
+}
diff --git a/variants/neokeytrinkey_m0/linker_scripts/gcc/flash_without_bootloader.ld b/variants/neokeytrinkey_m0/linker_scripts/gcc/flash_without_bootloader.ld
new file mode 100644
index 000000000..ebeeee37f
--- /dev/null
+++ b/variants/neokeytrinkey_m0/linker_scripts/gcc/flash_without_bootloader.ld
@@ -0,0 +1,214 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* Linker script to configure memory regions.
+ * Need modifying for a specific board.
+ *   FLASH.ORIGIN: starting address of flash
+ *   FLASH.LENGTH: length of flash
+ *   RAM.ORIGIN: starting address of RAM bank 0
+ *   RAM.LENGTH: length of RAM bank 0
+ */
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00040000
+  RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ *   Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ *   __exidx_start
+ *   __exidx_end
+ *   __copy_table_start__
+ *   __copy_table_end__
+ *   __zero_table_start__
+ *   __zero_table_end__
+ *   __etext
+ *   __data_start__
+ *   __preinit_array_start
+ *   __preinit_array_end
+ *   __init_array_start
+ *   __init_array_end
+ *   __fini_array_start
+ *   __fini_array_end
+ *   __data_end__
+ *   __bss_start__
+ *   __bss_end__
+ *   __end__
+ *   end
+ *   __HeapLimit
+ *   __StackLimit
+ *   __StackTop
+ *   __stack
+ *   __ram_end__
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+	.text :
+	{
+		__text_start__ = .;
+
+		KEEP(*(.isr_vector))
+		*(.text*)
+
+		KEEP(*(.init))
+		KEEP(*(.fini))
+
+		/* .ctors */
+		*crtbegin.o(.ctors)
+		*crtbegin?.o(.ctors)
+		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+		*(SORT(.ctors.*))
+		*(.ctors)
+
+		/* .dtors */
+ 		*crtbegin.o(.dtors)
+ 		*crtbegin?.o(.dtors)
+ 		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ 		*(SORT(.dtors.*))
+ 		*(.dtors)
+
+		*(.rodata*)
+
+		KEEP(*(.eh_frame*))
+	} > FLASH
+
+	.ARM.extab :
+	{
+		*(.ARM.extab* .gnu.linkonce.armextab.*)
+	} > FLASH
+
+	__exidx_start = .;
+	.ARM.exidx :
+	{
+		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
+	} > FLASH
+	__exidx_end = .;
+
+	/* To copy multiple ROM to RAM sections,
+	 * uncomment .copy.table section and,
+	 * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.copy.table :
+	{
+		. = ALIGN(4);
+		__copy_table_start__ = .;
+		LONG (__etext)
+		LONG (__data_start__)
+		LONG (__data_end__ - __data_start__)
+		LONG (__etext2)
+		LONG (__data2_start__)
+		LONG (__data2_end__ - __data2_start__)
+		__copy_table_end__ = .;
+	} > FLASH
+	*/
+
+	/* To clear multiple BSS sections,
+	 * uncomment .zero.table section and,
+	 * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.zero.table :
+	{
+		. = ALIGN(4);
+		__zero_table_start__ = .;
+		LONG (__bss_start__)
+		LONG (__bss_end__ - __bss_start__)
+		LONG (__bss2_start__)
+		LONG (__bss2_end__ - __bss2_start__)
+		__zero_table_end__ = .;
+	} > FLASH
+	*/
+
+	__etext = .;
+
+	.data : AT (__etext)
+	{
+		__data_start__ = .;
+		*(vtable)
+		*(.data*)
+
+		. = ALIGN(4);
+		/* preinit data */
+		PROVIDE_HIDDEN (__preinit_array_start = .);
+		KEEP(*(.preinit_array))
+		PROVIDE_HIDDEN (__preinit_array_end = .);
+
+		. = ALIGN(4);
+		/* init data */
+		PROVIDE_HIDDEN (__init_array_start = .);
+		KEEP(*(SORT(.init_array.*)))
+		KEEP(*(.init_array))
+		PROVIDE_HIDDEN (__init_array_end = .);
+
+
+		. = ALIGN(4);
+		/* finit data */
+		PROVIDE_HIDDEN (__fini_array_start = .);
+		KEEP(*(SORT(.fini_array.*)))
+		KEEP(*(.fini_array))
+		PROVIDE_HIDDEN (__fini_array_end = .);
+
+		KEEP(*(.jcr*))
+		. = ALIGN(16);
+		/* All data end */
+		__data_end__ = .;
+
+	} > RAM
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start__ = .;
+		*(.bss*)
+		*(COMMON)
+		. = ALIGN(4);
+		__bss_end__ = .;
+	} > RAM
+
+	.heap (COPY):
+	{
+		__end__ = .;
+		PROVIDE(end = .);
+		*(.heap*)
+		__HeapLimit = .;
+	} > RAM
+
+	/* .stack_dummy section doesn't contains any symbols. It is only
+	 * used for linker to calculate size of stack sections, and assign
+	 * values to stack symbols later */
+	.stack_dummy (COPY):
+	{
+		*(.stack*)
+	} > RAM
+
+	/* Set stack top to end of RAM, and stack limit move down by
+	 * size of stack_dummy section */
+	__StackTop = ORIGIN(RAM) + LENGTH(RAM) ;
+	__StackLimit = __StackTop - SIZEOF(.stack_dummy);
+	PROVIDE(__stack = __StackTop);
+
+	__ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ;
+
+	/* Check if data + heap + stack exceeds RAM limit */
+	ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
+}
diff --git a/variants/neokeytrinkey_m0/openocd_scripts/neokeytrinkey_m0.cfg b/variants/neokeytrinkey_m0/openocd_scripts/neokeytrinkey_m0.cfg
new file mode 100644
index 000000000..e4c3f81dc
--- /dev/null
+++ b/variants/neokeytrinkey_m0/openocd_scripts/neokeytrinkey_m0.cfg
@@ -0,0 +1,28 @@
+#
+#  Adafruit ItsyBitsy M0 OpenOCD script.
+#
+#  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+#
+#  This library is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 2.1 of the License, or (at your option) any later version.
+#
+#  This library is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#  See the GNU Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library; if not, write to the Free Software
+#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#
+
+# chip name
+set CHIPNAME at91samd21e18
+set ENDIAN little
+
+# choose a port here
+set telnet_port 0
+
+source [find target/at91samdXX.cfg]
diff --git a/variants/neokeytrinkey_m0/pins_arduino.h b/variants/neokeytrinkey_m0/pins_arduino.h
new file mode 100644
index 000000000..db0e40c3d
--- /dev/null
+++ b/variants/neokeytrinkey_m0/pins_arduino.h
@@ -0,0 +1,21 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+// API compatibility
+#include "variant.h"
+
diff --git a/variants/neokeytrinkey_m0/variant.cpp b/variants/neokeytrinkey_m0/variant.cpp
new file mode 100644
index 000000000..e64ad7b21
--- /dev/null
+++ b/variants/neokeytrinkey_m0/variant.cpp
@@ -0,0 +1,51 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "variant.h"
+#include "Arduino.h"
+/*
+ * Pins descriptions
+ */
+const PinDescription g_APinDescription[]=
+{
+  // NeoPixel
+  { PORTA, 15, PIO_DIGITAL, (PIN_ATTR_DIGITAL), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_15 },
+
+  // Mechanical switch
+  { PORTA, 28, PIO_DIGITAL, (PIN_ATTR_DIGITAL), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_8 }, 
+
+  // Touch pad
+  { PORTA,  7, PIO_DIGITAL, (PIN_ATTR_DIGITAL|PIN_ATTR_ANALOG|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel7, PWM1_CH1, TCC1_CH1, EXTERNAL_INT_7 }, 
+
+  
+  // USB pins
+  { PORTA, 28, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB Host enable
+  { PORTA, 24, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB/DM
+  { PORTA, 25, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB/DP
+
+  // Fake DAC pin just so we can compile stuff
+  { PORTA,  2, PIO_ANALOG, (PIN_ATTR_DIGITAL|PIN_ATTR_ANALOG|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel0, PWM2_CH0, TCC2_CH0, EXTERNAL_INT_2 }, // A0 / D0 / DAC  
+} ;
+
+const void* g_apTCInstances[TCC_INST_NUM+TC_INST_NUM]={ TCC0, TCC1, TCC2, TC3, TC4, TC5 } ;
+
+// Multi-serial objects instantiation
+SERCOM sercom0( SERCOM0 ) ;
+SERCOM sercom1( SERCOM1 ) ;
+SERCOM sercom2( SERCOM2 ) ;
+SERCOM sercom3( SERCOM3 ) ;
diff --git a/variants/neokeytrinkey_m0/variant.h b/variants/neokeytrinkey_m0/variant.h
new file mode 100644
index 000000000..e866d8afe
--- /dev/null
+++ b/variants/neokeytrinkey_m0/variant.h
@@ -0,0 +1,171 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _VARIANT_NEOKEYTRINKEY_ZERO_
+#define _VARIANT_NEOKEYTRINKEY_ZERO_
+
+// The definitions here needs a SAMD core >=1.6.10
+#define ARDUINO_SAMD_VARIANT_COMPLIANCE 10610
+
+/*----------------------------------------------------------------------------
+ *        Definitions
+ *----------------------------------------------------------------------------*/
+
+/** Frequency of the board main oscillator */
+#define VARIANT_MAINOSC		(32768ul)
+
+/** Master clock frequency */
+#define VARIANT_MCK	(F_CPU)
+
+/*----------------------------------------------------------------------------
+ *        Headers
+ *----------------------------------------------------------------------------*/
+
+#include "WVariant.h"
+
+#ifdef __cplusplus
+#include "SERCOM.h"
+#include "Uart.h"
+#endif // __cplusplus
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif // __cplusplus
+
+/*----------------------------------------------------------------------------
+ *        Pins
+ *----------------------------------------------------------------------------*/
+
+// Number of pins defined in PinDescription array
+#define PINS_COUNT           (6u)
+#define NUM_DIGITAL_PINS     (6u)
+#define NUM_ANALOG_INPUTS    (1u)
+#define NUM_ANALOG_OUTPUTS   (1u)
+#define analogInputToDigitalPin(p)  (p)
+
+#define digitalPinToPort(P)        ( &(PORT->Group[g_APinDescription[P].ulPort]) )
+#define digitalPinToBitMask(P)     ( 1 << g_APinDescription[P].ulPin )
+//#define analogInPinToBit(P)        ( )
+#define portOutputRegister(port)   ( &(port->OUT.reg) )
+#define portInputRegister(port)    ( &(port->IN.reg) )
+#define portModeRegister(port)     ( &(port->DIR.reg) )
+#define digitalPinHasPWM(P)        ( g_APinDescription[P].ulPWMChannel != NOT_ON_PWM || g_APinDescription[P].ulTCChannel != NOT_ON_TIMER )
+
+/*
+ * digitalPinToTimer(..) is AVR-specific and is not defined for SAMD
+ * architecture. If you need to check if a pin supports PWM you must
+ * use digitalPinHasPWM(..).
+ *
+ * https://github.com/arduino/Arduino/issues/1833
+ */
+// #define digitalPinToTimer(P)
+
+// LEDs
+#define PIN_NEOPIXEL         (0u)
+#define NUM_NEOPIXEL         (1u)
+
+#define PIN_SWITCH           1
+#define PIN_TOUCH            2
+
+/*
+ * Analog pins
+ */
+#define PIN_A0               (6ul)
+#define PIN_A1               (2)
+#define PIN_DAC0             PIN_A0
+
+static const uint8_t A0  = PIN_A0;
+static const uint8_t A1  = PIN_A1;
+
+#define ADC_RESOLUTION		12
+
+
+/*
+ * SPI Interfaces
+ */
+#define SPI_INTERFACES_COUNT 0
+
+/*
+ * Wire Interfaces
+ */
+#define WIRE_INTERFACES_COUNT 0
+
+/*
+ * USB
+ */
+#define PIN_USB_HOST_ENABLE (3ul)
+#define PIN_USB_DM          (4ul)
+#define PIN_USB_DP          (5ul)
+/*
+ * I2S Interfaces
+ */
+#define I2S_INTERFACES_COUNT 0
+
+
+/*
+ * Serial interfaces
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+ *        Arduino objects - C++ only
+ *----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+
+/*	=========================
+ *	===== SERCOM DEFINITION
+ *	=========================
+*/
+extern SERCOM sercom0;
+extern SERCOM sercom1;
+extern SERCOM sercom2;
+extern SERCOM sercom3;
+extern SERCOM sercom4;
+extern SERCOM sercom5;
+
+
+#endif
+
+// These serial port names are intended to allow libraries and architecture-neutral
+// sketches to automatically default to the correct port name for a particular type
+// of use.  For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN,
+// the first hardware serial port whose RX/TX pins are not dedicated to another use.
+//
+// SERIAL_PORT_MONITOR        Port which normally prints to the Arduino Serial Monitor
+//
+// SERIAL_PORT_USBVIRTUAL     Port which is USB virtual serial
+//
+// SERIAL_PORT_LINUXBRIDGE    Port which connects to a Linux system via Bridge library
+//
+// SERIAL_PORT_HARDWARE       Hardware serial port, physical RX & TX pins.
+//
+// SERIAL_PORT_HARDWARE_OPEN  Hardware serial ports which are open for use.  Their RX & TX
+//                            pins are NOT connected to anything by default.
+#define SERIAL_PORT_USBVIRTUAL      Serial
+#define SERIAL_PORT_MONITOR         Serial
+// Serial has no physical pins broken out, so it's not listed as HARDWARE port
+#define SERIAL_PORT_HARDWARE        Serial1
+#define SERIAL_PORT_HARDWARE_OPEN   Serial1
+
+#endif /* _VARIANT_ARDUINO_ZERO_ */
+
diff --git a/variants/neotrinkey_m0/debug_scripts/variant.gdb b/variants/neotrinkey_m0/debug_scripts/variant.gdb
new file mode 100644
index 000000000..13ee2a173
--- /dev/null
+++ b/variants/neotrinkey_m0/debug_scripts/variant.gdb
@@ -0,0 +1,31 @@
+#
+#  Arduino Zero OpenOCD script.
+#
+#  Copyright (c) 2014-2015 Arduino LLC. All right reserved.
+#
+#  This library is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 2.1 of the License, or (at your option) any later version.
+#
+#  This library is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#  See the GNU Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library; if not, write to the Free Software
+#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#
+
+# Define 'reset' command
+define reset
+
+info reg
+
+break main
+
+# End of 'reset' command
+end
+
+target remote | openocd -c "interface cmsis-dap" -c "set CHIPNAME at91samd21e18" -f target/at91samdXX.cfg -c "gdb_port pipe; log_output openocd.log"
diff --git a/variants/neotrinkey_m0/linker_scripts/gcc/flash_with_bootloader.ld b/variants/neotrinkey_m0/linker_scripts/gcc/flash_with_bootloader.ld
new file mode 100644
index 000000000..357946455
--- /dev/null
+++ b/variants/neotrinkey_m0/linker_scripts/gcc/flash_with_bootloader.ld
@@ -0,0 +1,216 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* Linker script to configure memory regions.
+ * Need modifying for a specific board.
+ *   FLASH.ORIGIN: starting address of flash
+ *   FLASH.LENGTH: length of flash
+ *   RAM.ORIGIN: starting address of RAM bank 0
+ *   RAM.LENGTH: length of RAM bank 0
+ */
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000+0x2000, LENGTH = 0x00040000-0x2000 /* First 8KB used by bootloader */
+  RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ *   Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ *   __exidx_start
+ *   __exidx_end
+ *   __copy_table_start__
+ *   __copy_table_end__
+ *   __zero_table_start__
+ *   __zero_table_end__
+ *   __etext
+ *   __data_start__
+ *   __preinit_array_start
+ *   __preinit_array_end
+ *   __init_array_start
+ *   __init_array_end
+ *   __fini_array_start
+ *   __fini_array_end
+ *   __data_end__
+ *   __bss_start__
+ *   __bss_end__
+ *   __end__
+ *   end
+ *   __HeapLimit
+ *   __StackLimit
+ *   __StackTop
+ *   __stack
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+	.text :
+	{
+		__text_start__ = .;
+
+		KEEP(*(.sketch_boot))
+
+		. = ALIGN(0x2000);
+		KEEP(*(.isr_vector))
+		*(.text*)
+
+		KEEP(*(.init))
+		KEEP(*(.fini))
+
+		/* .ctors */
+		*crtbegin.o(.ctors)
+		*crtbegin?.o(.ctors)
+		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+		*(SORT(.ctors.*))
+		*(.ctors)
+
+		/* .dtors */
+ 		*crtbegin.o(.dtors)
+ 		*crtbegin?.o(.dtors)
+ 		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ 		*(SORT(.dtors.*))
+ 		*(.dtors)
+
+		*(.rodata*)
+
+		KEEP(*(.eh_frame*))
+	} > FLASH
+
+	.ARM.extab :
+	{
+		*(.ARM.extab* .gnu.linkonce.armextab.*)
+	} > FLASH
+
+	__exidx_start = .;
+	.ARM.exidx :
+	{
+		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
+	} > FLASH
+	__exidx_end = .;
+
+	/* To copy multiple ROM to RAM sections,
+	 * uncomment .copy.table section and,
+	 * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.copy.table :
+	{
+		. = ALIGN(4);
+		__copy_table_start__ = .;
+		LONG (__etext)
+		LONG (__data_start__)
+		LONG (__data_end__ - __data_start__)
+		LONG (__etext2)
+		LONG (__data2_start__)
+		LONG (__data2_end__ - __data2_start__)
+		__copy_table_end__ = .;
+	} > FLASH
+	*/
+
+	/* To clear multiple BSS sections,
+	 * uncomment .zero.table section and,
+	 * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.zero.table :
+	{
+		. = ALIGN(4);
+		__zero_table_start__ = .;
+		LONG (__bss_start__)
+		LONG (__bss_end__ - __bss_start__)
+		LONG (__bss2_start__)
+		LONG (__bss2_end__ - __bss2_start__)
+		__zero_table_end__ = .;
+	} > FLASH
+	*/
+
+	__etext = .;
+
+	.data : AT (__etext)
+	{
+		__data_start__ = .;
+		*(vtable)
+		*(.data*)
+
+		. = ALIGN(4);
+		/* preinit data */
+		PROVIDE_HIDDEN (__preinit_array_start = .);
+		KEEP(*(.preinit_array))
+		PROVIDE_HIDDEN (__preinit_array_end = .);
+
+		. = ALIGN(4);
+		/* init data */
+		PROVIDE_HIDDEN (__init_array_start = .);
+		KEEP(*(SORT(.init_array.*)))
+		KEEP(*(.init_array))
+		PROVIDE_HIDDEN (__init_array_end = .);
+
+
+		. = ALIGN(4);
+		/* finit data */
+		PROVIDE_HIDDEN (__fini_array_start = .);
+		KEEP(*(SORT(.fini_array.*)))
+		KEEP(*(.fini_array))
+		PROVIDE_HIDDEN (__fini_array_end = .);
+
+		KEEP(*(.jcr*))
+		. = ALIGN(16);
+		/* All data end */
+		__data_end__ = .;
+
+	} > RAM
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start__ = .;
+		*(.bss*)
+		*(COMMON)
+		. = ALIGN(4);
+		__bss_end__ = .;
+	} > RAM
+
+	.heap (COPY):
+	{
+		__end__ = .;
+		PROVIDE(end = .);
+		*(.heap*)
+		__HeapLimit = .;
+	} > RAM
+
+	/* .stack_dummy section doesn't contains any symbols. It is only
+	 * used for linker to calculate size of stack sections, and assign
+	 * values to stack symbols later */
+	.stack_dummy (COPY):
+	{
+		*(.stack*)
+	} > RAM
+
+	/* Set stack top to end of RAM, and stack limit move down by
+	 * size of stack_dummy section */
+	__StackTop = ORIGIN(RAM) + LENGTH(RAM);
+	__StackLimit = __StackTop - SIZEOF(.stack_dummy);
+	PROVIDE(__stack = __StackTop);
+
+	__ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ;
+
+	/* Check if data + heap + stack exceeds RAM limit */
+	ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
+}
diff --git a/variants/neotrinkey_m0/linker_scripts/gcc/flash_without_bootloader.ld b/variants/neotrinkey_m0/linker_scripts/gcc/flash_without_bootloader.ld
new file mode 100644
index 000000000..ebeeee37f
--- /dev/null
+++ b/variants/neotrinkey_m0/linker_scripts/gcc/flash_without_bootloader.ld
@@ -0,0 +1,214 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* Linker script to configure memory regions.
+ * Need modifying for a specific board.
+ *   FLASH.ORIGIN: starting address of flash
+ *   FLASH.LENGTH: length of flash
+ *   RAM.ORIGIN: starting address of RAM bank 0
+ *   RAM.LENGTH: length of RAM bank 0
+ */
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00040000
+  RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ *   Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ *   __exidx_start
+ *   __exidx_end
+ *   __copy_table_start__
+ *   __copy_table_end__
+ *   __zero_table_start__
+ *   __zero_table_end__
+ *   __etext
+ *   __data_start__
+ *   __preinit_array_start
+ *   __preinit_array_end
+ *   __init_array_start
+ *   __init_array_end
+ *   __fini_array_start
+ *   __fini_array_end
+ *   __data_end__
+ *   __bss_start__
+ *   __bss_end__
+ *   __end__
+ *   end
+ *   __HeapLimit
+ *   __StackLimit
+ *   __StackTop
+ *   __stack
+ *   __ram_end__
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+	.text :
+	{
+		__text_start__ = .;
+
+		KEEP(*(.isr_vector))
+		*(.text*)
+
+		KEEP(*(.init))
+		KEEP(*(.fini))
+
+		/* .ctors */
+		*crtbegin.o(.ctors)
+		*crtbegin?.o(.ctors)
+		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+		*(SORT(.ctors.*))
+		*(.ctors)
+
+		/* .dtors */
+ 		*crtbegin.o(.dtors)
+ 		*crtbegin?.o(.dtors)
+ 		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ 		*(SORT(.dtors.*))
+ 		*(.dtors)
+
+		*(.rodata*)
+
+		KEEP(*(.eh_frame*))
+	} > FLASH
+
+	.ARM.extab :
+	{
+		*(.ARM.extab* .gnu.linkonce.armextab.*)
+	} > FLASH
+
+	__exidx_start = .;
+	.ARM.exidx :
+	{
+		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
+	} > FLASH
+	__exidx_end = .;
+
+	/* To copy multiple ROM to RAM sections,
+	 * uncomment .copy.table section and,
+	 * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.copy.table :
+	{
+		. = ALIGN(4);
+		__copy_table_start__ = .;
+		LONG (__etext)
+		LONG (__data_start__)
+		LONG (__data_end__ - __data_start__)
+		LONG (__etext2)
+		LONG (__data2_start__)
+		LONG (__data2_end__ - __data2_start__)
+		__copy_table_end__ = .;
+	} > FLASH
+	*/
+
+	/* To clear multiple BSS sections,
+	 * uncomment .zero.table section and,
+	 * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.zero.table :
+	{
+		. = ALIGN(4);
+		__zero_table_start__ = .;
+		LONG (__bss_start__)
+		LONG (__bss_end__ - __bss_start__)
+		LONG (__bss2_start__)
+		LONG (__bss2_end__ - __bss2_start__)
+		__zero_table_end__ = .;
+	} > FLASH
+	*/
+
+	__etext = .;
+
+	.data : AT (__etext)
+	{
+		__data_start__ = .;
+		*(vtable)
+		*(.data*)
+
+		. = ALIGN(4);
+		/* preinit data */
+		PROVIDE_HIDDEN (__preinit_array_start = .);
+		KEEP(*(.preinit_array))
+		PROVIDE_HIDDEN (__preinit_array_end = .);
+
+		. = ALIGN(4);
+		/* init data */
+		PROVIDE_HIDDEN (__init_array_start = .);
+		KEEP(*(SORT(.init_array.*)))
+		KEEP(*(.init_array))
+		PROVIDE_HIDDEN (__init_array_end = .);
+
+
+		. = ALIGN(4);
+		/* finit data */
+		PROVIDE_HIDDEN (__fini_array_start = .);
+		KEEP(*(SORT(.fini_array.*)))
+		KEEP(*(.fini_array))
+		PROVIDE_HIDDEN (__fini_array_end = .);
+
+		KEEP(*(.jcr*))
+		. = ALIGN(16);
+		/* All data end */
+		__data_end__ = .;
+
+	} > RAM
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start__ = .;
+		*(.bss*)
+		*(COMMON)
+		. = ALIGN(4);
+		__bss_end__ = .;
+	} > RAM
+
+	.heap (COPY):
+	{
+		__end__ = .;
+		PROVIDE(end = .);
+		*(.heap*)
+		__HeapLimit = .;
+	} > RAM
+
+	/* .stack_dummy section doesn't contains any symbols. It is only
+	 * used for linker to calculate size of stack sections, and assign
+	 * values to stack symbols later */
+	.stack_dummy (COPY):
+	{
+		*(.stack*)
+	} > RAM
+
+	/* Set stack top to end of RAM, and stack limit move down by
+	 * size of stack_dummy section */
+	__StackTop = ORIGIN(RAM) + LENGTH(RAM) ;
+	__StackLimit = __StackTop - SIZEOF(.stack_dummy);
+	PROVIDE(__stack = __StackTop);
+
+	__ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ;
+
+	/* Check if data + heap + stack exceeds RAM limit */
+	ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
+}
diff --git a/variants/neotrinkey_m0/openocd_scripts/neotrinkey_m0.cfg b/variants/neotrinkey_m0/openocd_scripts/neotrinkey_m0.cfg
new file mode 100644
index 000000000..e4c3f81dc
--- /dev/null
+++ b/variants/neotrinkey_m0/openocd_scripts/neotrinkey_m0.cfg
@@ -0,0 +1,28 @@
+#
+#  Adafruit ItsyBitsy M0 OpenOCD script.
+#
+#  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+#
+#  This library is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 2.1 of the License, or (at your option) any later version.
+#
+#  This library is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#  See the GNU Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library; if not, write to the Free Software
+#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#
+
+# chip name
+set CHIPNAME at91samd21e18
+set ENDIAN little
+
+# choose a port here
+set telnet_port 0
+
+source [find target/at91samdXX.cfg]
diff --git a/variants/neotrinkey_m0/pins_arduino.h b/variants/neotrinkey_m0/pins_arduino.h
new file mode 100644
index 000000000..db0e40c3d
--- /dev/null
+++ b/variants/neotrinkey_m0/pins_arduino.h
@@ -0,0 +1,21 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+// API compatibility
+#include "variant.h"
+
diff --git a/variants/neotrinkey_m0/variant.cpp b/variants/neotrinkey_m0/variant.cpp
new file mode 100644
index 000000000..150034974
--- /dev/null
+++ b/variants/neotrinkey_m0/variant.cpp
@@ -0,0 +1,50 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "variant.h"
+#include "Arduino.h"
+/*
+ * Pins descriptions
+ */
+const PinDescription g_APinDescription[]=
+{
+  // NeoPixels
+  { PORTA,  5, PIO_ANALOG, (PIN_ATTR_DIGITAL|PIN_ATTR_ANALOG|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel5, PWM0_CH1, TCC0_CH1, EXTERNAL_INT_5 },
+
+  // Touch Pin 1
+  { PORTA,  3, PIO_ANALOG, (PIN_ATTR_DIGITAL|PIN_ATTR_ANALOG), ADC_Channel1, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_3 },
+
+  // Touch Pin 2
+  { PORTA,  7, PIO_ANALOG, (PIN_ATTR_DIGITAL|PIN_ATTR_ANALOG|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel7, PWM1_CH1, TCC1_CH1, EXTERNAL_INT_7 }, 
+
+  // USB pins
+  { PORTA, 28, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB Host enable
+  { PORTA, 24, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB/DM
+  { PORTA, 25, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB/DP
+
+  // Fake DAC pin just so we can compile stuff
+  { PORTA,  2, PIO_ANALOG, (PIN_ATTR_DIGITAL|PIN_ATTR_ANALOG|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel0, PWM2_CH0, TCC2_CH0, EXTERNAL_INT_2 }, // A0 / D0 / DAC  
+} ;
+
+const void* g_apTCInstances[TCC_INST_NUM+TC_INST_NUM]={ TCC0, TCC1, TCC2, TC3, TC4, TC5 } ;
+
+// Multi-serial objects instantiation
+SERCOM sercom0( SERCOM0 ) ;
+SERCOM sercom1( SERCOM1 ) ;
+SERCOM sercom2( SERCOM2 ) ;
+SERCOM sercom3( SERCOM3 ) ;
diff --git a/variants/neotrinkey_m0/variant.h b/variants/neotrinkey_m0/variant.h
new file mode 100644
index 000000000..3da948ce1
--- /dev/null
+++ b/variants/neotrinkey_m0/variant.h
@@ -0,0 +1,166 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _VARIANT_NEOTRINKEY_ZERO_
+#define _VARIANT_NEOTRINKEY_ZERO_
+
+// The definitions here needs a SAMD core >=1.6.10
+#define ARDUINO_SAMD_VARIANT_COMPLIANCE 10610
+
+/*----------------------------------------------------------------------------
+ *        Definitions
+ *----------------------------------------------------------------------------*/
+
+/** Frequency of the board main oscillator */
+#define VARIANT_MAINOSC		(32768ul)
+
+/** Master clock frequency */
+#define VARIANT_MCK	(F_CPU)
+
+/*----------------------------------------------------------------------------
+ *        Headers
+ *----------------------------------------------------------------------------*/
+
+#include "WVariant.h"
+
+#ifdef __cplusplus
+#include "SERCOM.h"
+#include "Uart.h"
+#endif // __cplusplus
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif // __cplusplus
+
+/*----------------------------------------------------------------------------
+ *        Pins
+ *----------------------------------------------------------------------------*/
+
+// Number of pins defined in PinDescription array
+#define PINS_COUNT           (7u)
+#define NUM_DIGITAL_PINS     (7u)
+#define NUM_ANALOG_INPUTS    (3u)
+#define NUM_ANALOG_OUTPUTS   (1u)
+#define analogInputToDigitalPin(p)  (p)
+
+#define digitalPinToPort(P)        ( &(PORT->Group[g_APinDescription[P].ulPort]) )
+#define digitalPinToBitMask(P)     ( 1 << g_APinDescription[P].ulPin )
+//#define analogInPinToBit(P)        ( )
+#define portOutputRegister(port)   ( &(port->OUT.reg) )
+#define portInputRegister(port)    ( &(port->IN.reg) )
+#define portModeRegister(port)     ( &(port->DIR.reg) )
+#define digitalPinHasPWM(P)        ( g_APinDescription[P].ulPWMChannel != NOT_ON_PWM || g_APinDescription[P].ulTCChannel != NOT_ON_TIMER )
+
+/*
+ * digitalPinToTimer(..) is AVR-specific and is not defined for SAMD
+ * architecture. If you need to check if a pin supports PWM you must
+ * use digitalPinHasPWM(..).
+ *
+ * https://github.com/arduino/Arduino/issues/1833
+ */
+// #define digitalPinToTimer(P)
+
+// LEDs
+#define PIN_NEOPIXEL         (0u)
+#define NUM_NEOPIXEL         (4u)
+
+/*
+ * Analog pins
+ */
+#define PIN_A0               (6ul)
+#define PIN_A1               (1)
+#define PIN_A2               (2)
+#define PIN_DAC0             PIN_A0
+
+static const uint8_t A0  = PIN_A0;
+static const uint8_t A1  = PIN_A1;
+static const uint8_t A2  = PIN_A2;
+
+#define ADC_RESOLUTION		12
+
+
+/*
+ * SPI Interfaces
+ */
+#define SPI_INTERFACES_COUNT 0
+
+/*
+ * Wire Interfaces
+ */
+#define WIRE_INTERFACES_COUNT 0
+
+/*
+ * USB
+ */
+#define PIN_USB_HOST_ENABLE (3ul)
+#define PIN_USB_DM          (4ul)
+#define PIN_USB_DP          (5ul)
+/*
+ * I2S Interfaces
+ */
+#define I2S_INTERFACES_COUNT 0
+
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+ *        Arduino objects - C++ only
+ *----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+
+/*	=========================
+ *	===== SERCOM DEFINITION
+ *	=========================
+*/
+extern SERCOM sercom0;
+extern SERCOM sercom1;
+extern SERCOM sercom2;
+extern SERCOM sercom3;
+extern SERCOM sercom4;
+extern SERCOM sercom5;
+
+
+#endif
+
+// These serial port names are intended to allow libraries and architecture-neutral
+// sketches to automatically default to the correct port name for a particular type
+// of use.  For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN,
+// the first hardware serial port whose RX/TX pins are not dedicated to another use.
+//
+// SERIAL_PORT_MONITOR        Port which normally prints to the Arduino Serial Monitor
+//
+// SERIAL_PORT_USBVIRTUAL     Port which is USB virtual serial
+//
+// SERIAL_PORT_LINUXBRIDGE    Port which connects to a Linux system via Bridge library
+//
+// SERIAL_PORT_HARDWARE       Hardware serial port, physical RX & TX pins.
+//
+// SERIAL_PORT_HARDWARE_OPEN  Hardware serial ports which are open for use.  Their RX & TX
+//                            pins are NOT connected to anything by default.
+#define SERIAL_PORT_USBVIRTUAL      Serial
+#define SERIAL_PORT_MONITOR         Serial
+// Serial has no physical pins broken out, so it's not listed as HARDWARE port
+#define SERIAL_PORT_HARDWARE        Serial1
+#define SERIAL_PORT_HARDWARE_OPEN   Serial1
+
+#endif /* _VARIANT_ARDUINO_ZERO_ */
+
diff --git a/variants/pirkey/debug_scripts/variant.gdb b/variants/pirkey/debug_scripts/variant.gdb
new file mode 100644
index 000000000..3c37ffde2
--- /dev/null
+++ b/variants/pirkey/debug_scripts/variant.gdb
@@ -0,0 +1,31 @@
+#
+#  Arduino Zero OpenOCD script.
+#
+#  Copyright (c) 2014-2015 Arduino LLC. All right reserved.
+#
+#  This library is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 2.1 of the License, or (at your option) any later version.
+#
+#  This library is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#  See the GNU Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library; if not, write to the Free Software
+#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#
+
+# Define 'reset' command
+define reset
+
+info reg
+
+break main
+
+# End of 'reset' command
+end
+
+target remote | openocd -c "interface cmsis-dap" -c "set CHIPNAME at91samd21g18" -f target/at91samdXX.cfg -c "gdb_port pipe; log_output openocd.log"
diff --git a/variants/pirkey/linker_scripts/gcc/flash_with_bootloader.ld b/variants/pirkey/linker_scripts/gcc/flash_with_bootloader.ld
new file mode 100644
index 000000000..4475f9511
--- /dev/null
+++ b/variants/pirkey/linker_scripts/gcc/flash_with_bootloader.ld
@@ -0,0 +1,211 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* Linker script to configure memory regions.
+ * Need modifying for a specific board.
+ *   FLASH.ORIGIN: starting address of flash
+ *   FLASH.LENGTH: length of flash
+ *   RAM.ORIGIN: starting address of RAM bank 0
+ *   RAM.LENGTH: length of RAM bank 0
+ */
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000+0x2000, LENGTH = 0x00040000-0x2000 /* First 8KB used by bootloader */
+  RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ *   Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ *   __exidx_start
+ *   __exidx_end
+ *   __copy_table_start__
+ *   __copy_table_end__
+ *   __zero_table_start__
+ *   __zero_table_end__
+ *   __etext
+ *   __data_start__
+ *   __preinit_array_start
+ *   __preinit_array_end
+ *   __init_array_start
+ *   __init_array_end
+ *   __fini_array_start
+ *   __fini_array_end
+ *   __data_end__
+ *   __bss_start__
+ *   __bss_end__
+ *   __end__
+ *   end
+ *   __HeapLimit
+ *   __StackLimit
+ *   __StackTop
+ *   __stack
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+	.text :
+	{
+		KEEP(*(.isr_vector))
+		*(.text*)
+
+		KEEP(*(.init))
+		KEEP(*(.fini))
+
+		/* .ctors */
+		*crtbegin.o(.ctors)
+		*crtbegin?.o(.ctors)
+		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+		*(SORT(.ctors.*))
+		*(.ctors)
+
+		/* .dtors */
+ 		*crtbegin.o(.dtors)
+ 		*crtbegin?.o(.dtors)
+ 		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ 		*(SORT(.dtors.*))
+ 		*(.dtors)
+
+		*(.rodata*)
+
+		KEEP(*(.eh_frame*))
+	} > FLASH
+
+	.ARM.extab :
+	{
+		*(.ARM.extab* .gnu.linkonce.armextab.*)
+	} > FLASH
+
+	__exidx_start = .;
+	.ARM.exidx :
+	{
+		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
+	} > FLASH
+	__exidx_end = .;
+
+	/* To copy multiple ROM to RAM sections,
+	 * uncomment .copy.table section and,
+	 * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.copy.table :
+	{
+		. = ALIGN(4);
+		__copy_table_start__ = .;
+		LONG (__etext)
+		LONG (__data_start__)
+		LONG (__data_end__ - __data_start__)
+		LONG (__etext2)
+		LONG (__data2_start__)
+		LONG (__data2_end__ - __data2_start__)
+		__copy_table_end__ = .;
+	} > FLASH
+	*/
+
+	/* To clear multiple BSS sections,
+	 * uncomment .zero.table section and,
+	 * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.zero.table :
+	{
+		. = ALIGN(4);
+		__zero_table_start__ = .;
+		LONG (__bss_start__)
+		LONG (__bss_end__ - __bss_start__)
+		LONG (__bss2_start__)
+		LONG (__bss2_end__ - __bss2_start__)
+		__zero_table_end__ = .;
+	} > FLASH
+	*/
+
+	__etext = .;
+
+	.data : AT (__etext)
+	{
+		__data_start__ = .;
+		*(vtable)
+		*(.data*)
+
+		. = ALIGN(4);
+		/* preinit data */
+		PROVIDE_HIDDEN (__preinit_array_start = .);
+		KEEP(*(.preinit_array))
+		PROVIDE_HIDDEN (__preinit_array_end = .);
+
+		. = ALIGN(4);
+		/* init data */
+		PROVIDE_HIDDEN (__init_array_start = .);
+		KEEP(*(SORT(.init_array.*)))
+		KEEP(*(.init_array))
+		PROVIDE_HIDDEN (__init_array_end = .);
+
+
+		. = ALIGN(4);
+		/* finit data */
+		PROVIDE_HIDDEN (__fini_array_start = .);
+		KEEP(*(SORT(.fini_array.*)))
+		KEEP(*(.fini_array))
+		PROVIDE_HIDDEN (__fini_array_end = .);
+
+		KEEP(*(.jcr*))
+		. = ALIGN(4);
+		/* All data end */
+		__data_end__ = .;
+
+	} > RAM
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start__ = .;
+		*(.bss*)
+		*(COMMON)
+		. = ALIGN(4);
+		__bss_end__ = .;
+	} > RAM
+
+	.heap (COPY):
+	{
+		__end__ = .;
+		PROVIDE(end = .);
+		*(.heap*)
+		__HeapLimit = .;
+	} > RAM
+
+	/* .stack_dummy section doesn't contains any symbols. It is only
+	 * used for linker to calculate size of stack sections, and assign
+	 * values to stack symbols later */
+	.stack_dummy (COPY):
+	{
+		*(.stack*)
+	} > RAM
+
+	/* Set stack top to end of RAM, and stack limit move down by
+	 * size of stack_dummy section */
+	__StackTop = ORIGIN(RAM) + LENGTH(RAM);
+	__StackLimit = __StackTop - SIZEOF(.stack_dummy);
+	PROVIDE(__stack = __StackTop);
+
+	__ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ;
+
+	/* Check if data + heap + stack exceeds RAM limit */
+	ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
+}
diff --git a/variants/pirkey/linker_scripts/gcc/flash_without_bootloader.ld b/variants/pirkey/linker_scripts/gcc/flash_without_bootloader.ld
new file mode 100644
index 000000000..0162f0774
--- /dev/null
+++ b/variants/pirkey/linker_scripts/gcc/flash_without_bootloader.ld
@@ -0,0 +1,212 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* Linker script to configure memory regions.
+ * Need modifying for a specific board.
+ *   FLASH.ORIGIN: starting address of flash
+ *   FLASH.LENGTH: length of flash
+ *   RAM.ORIGIN: starting address of RAM bank 0
+ *   RAM.LENGTH: length of RAM bank 0
+ */
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00040000
+  RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ *   Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ *   __exidx_start
+ *   __exidx_end
+ *   __copy_table_start__
+ *   __copy_table_end__
+ *   __zero_table_start__
+ *   __zero_table_end__
+ *   __etext
+ *   __data_start__
+ *   __preinit_array_start
+ *   __preinit_array_end
+ *   __init_array_start
+ *   __init_array_end
+ *   __fini_array_start
+ *   __fini_array_end
+ *   __data_end__
+ *   __bss_start__
+ *   __bss_end__
+ *   __end__
+ *   end
+ *   __HeapLimit
+ *   __StackLimit
+ *   __StackTop
+ *   __stack
+ *   __ram_end__
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+	.text :
+	{
+		KEEP(*(.isr_vector))
+		*(.text*)
+
+		KEEP(*(.init))
+		KEEP(*(.fini))
+
+		/* .ctors */
+		*crtbegin.o(.ctors)
+		*crtbegin?.o(.ctors)
+		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+		*(SORT(.ctors.*))
+		*(.ctors)
+
+		/* .dtors */
+ 		*crtbegin.o(.dtors)
+ 		*crtbegin?.o(.dtors)
+ 		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ 		*(SORT(.dtors.*))
+ 		*(.dtors)
+
+		*(.rodata*)
+
+		KEEP(*(.eh_frame*))
+	} > FLASH
+
+	.ARM.extab :
+	{
+		*(.ARM.extab* .gnu.linkonce.armextab.*)
+	} > FLASH
+
+	__exidx_start = .;
+	.ARM.exidx :
+	{
+		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
+	} > FLASH
+	__exidx_end = .;
+
+	/* To copy multiple ROM to RAM sections,
+	 * uncomment .copy.table section and,
+	 * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.copy.table :
+	{
+		. = ALIGN(4);
+		__copy_table_start__ = .;
+		LONG (__etext)
+		LONG (__data_start__)
+		LONG (__data_end__ - __data_start__)
+		LONG (__etext2)
+		LONG (__data2_start__)
+		LONG (__data2_end__ - __data2_start__)
+		__copy_table_end__ = .;
+	} > FLASH
+	*/
+
+	/* To clear multiple BSS sections,
+	 * uncomment .zero.table section and,
+	 * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.zero.table :
+	{
+		. = ALIGN(4);
+		__zero_table_start__ = .;
+		LONG (__bss_start__)
+		LONG (__bss_end__ - __bss_start__)
+		LONG (__bss2_start__)
+		LONG (__bss2_end__ - __bss2_start__)
+		__zero_table_end__ = .;
+	} > FLASH
+	*/
+
+	__etext = .;
+
+	.data : AT (__etext)
+	{
+		__data_start__ = .;
+		*(vtable)
+		*(.data*)
+
+		. = ALIGN(4);
+		/* preinit data */
+		PROVIDE_HIDDEN (__preinit_array_start = .);
+		KEEP(*(.preinit_array))
+		PROVIDE_HIDDEN (__preinit_array_end = .);
+
+		. = ALIGN(4);
+		/* init data */
+		PROVIDE_HIDDEN (__init_array_start = .);
+		KEEP(*(SORT(.init_array.*)))
+		KEEP(*(.init_array))
+		PROVIDE_HIDDEN (__init_array_end = .);
+
+
+		. = ALIGN(4);
+		/* finit data */
+		PROVIDE_HIDDEN (__fini_array_start = .);
+		KEEP(*(SORT(.fini_array.*)))
+		KEEP(*(.fini_array))
+		PROVIDE_HIDDEN (__fini_array_end = .);
+
+		KEEP(*(.jcr*))
+		. = ALIGN(4);
+		/* All data end */
+		__data_end__ = .;
+
+	} > RAM
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start__ = .;
+		*(.bss*)
+		*(COMMON)
+		. = ALIGN(4);
+		__bss_end__ = .;
+	} > RAM
+
+	.heap (COPY):
+	{
+		__end__ = .;
+		PROVIDE(end = .);
+		*(.heap*)
+		__HeapLimit = .;
+	} > RAM
+
+	/* .stack_dummy section doesn't contains any symbols. It is only
+	 * used for linker to calculate size of stack sections, and assign
+	 * values to stack symbols later */
+	.stack_dummy (COPY):
+	{
+		*(.stack*)
+	} > RAM
+
+	/* Set stack top to end of RAM, and stack limit move down by
+	 * size of stack_dummy section */
+	__StackTop = ORIGIN(RAM) + LENGTH(RAM) ;
+	__StackLimit = __StackTop - SIZEOF(.stack_dummy);
+	PROVIDE(__stack = __StackTop);
+
+	__ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ;
+
+	/* Check if data + heap + stack exceeds RAM limit */
+	ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
+}
diff --git a/variants/mkrgsm1400/openocd_scripts/arduino_zero.cfg b/variants/pirkey/openocd_scripts/arduino_zero.cfg
similarity index 100%
rename from variants/mkrgsm1400/openocd_scripts/arduino_zero.cfg
rename to variants/pirkey/openocd_scripts/arduino_zero.cfg
diff --git a/variants/pirkey/pins_arduino.h b/variants/pirkey/pins_arduino.h
new file mode 100644
index 000000000..db0e40c3d
--- /dev/null
+++ b/variants/pirkey/pins_arduino.h
@@ -0,0 +1,21 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+// API compatibility
+#include "variant.h"
+
diff --git a/variants/pirkey/variant.cpp b/variants/pirkey/variant.cpp
new file mode 100644
index 000000000..61734c020
--- /dev/null
+++ b/variants/pirkey/variant.cpp
@@ -0,0 +1,96 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "variant.h"
+
+/*
+ * Pins descriptions
+ */
+const PinDescription g_APinDescription[]=
+{
+  // GPIO 0 & 1 - DotStar internal data/clock
+  // ----------------------------------------
+  { PORTA,  0, PIO_DIGITAL, 0, ADC_Channel4, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_0 }, // ADC/AIN[4]
+  { PORTA,  1, PIO_DIGITAL, 0, ADC_Channel5, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_1 }, // ADC/AIN[5]
+
+  // GPIO 2 - Infrared In
+  { PORTA, 28, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_8 }, // USB Host enable - GPIO #2
+
+  // GPIO 3 & 4 (SWCLK & SWDIO)
+  // --------------------------
+  { PORTA, 30, PIO_SERCOM_ALT, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+  { PORTA, 31, PIO_SERCOM_ALT, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+
+  // Placeholder #5 & 6 for 'txled' and 'rxled'
+  { PORTA, 14, PIO_DIGITAL, (PIN_ATTR_DIGITAL), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_14 },
+  { PORTA, 15, PIO_DIGITAL, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM3_CH1, TC3_CH1, EXTERNAL_INT_15 },
+
+  // GPIO 7, 8, 9 USB Host enable
+  // ----------------------------
+  { PORTA, 27, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB Host enable - GPIO #7
+  { PORTA, 24, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB/DM - GPIO #8
+  { PORTA, 25, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB/DP - GPIO #9
+
+
+  // Digital 10 - 14, Analog A0-A4
+  // A0
+  { PORTA,  2, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel0, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 }, // ADC/AIN[0]
+  // A1
+  { PORTA,  9, PIO_ANALOG, (PIN_ATTR_ANALOG|PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel17, PWM0_CH1, TCC0_CH1, EXTERNAL_INT_9 }, // TCC0/WO[1]
+  // A2
+  { PORTA,  8, PIO_ANALOG, (PIN_ATTR_ANALOG|PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel16, PWM0_CH0, TCC0_CH0, EXTERNAL_INT_NMI },  // TCC0/WO[0]
+  // A3
+  { PORTA,  7, PIO_ANALOG, (PIN_ATTR_ANALOG|PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel7, PWM1_CH1, TCC1_CH1, EXTERNAL_INT_7 }, // TCC1/WO[1]
+  // A4
+  { PORTA,  6, PIO_ANALOG, (PIN_ATTR_ANALOG|PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel6, PWM1_CH0, TCC1_CH0, EXTERNAL_INT_6 }, // TCC1/WO[0]
+
+  { PORTA,  6, PIO_ANALOG, (PIN_ATTR_ANALOG|PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel6, PWM1_CH0, TCC1_CH0, EXTERNAL_INT_6 }, // TCC1/WO[0]
+  { PORTA,  6, PIO_ANALOG, (PIN_ATTR_ANALOG|PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel6, PWM1_CH0, TCC1_CH0, EXTERNAL_INT_6 }, // TCC1/WO[0]
+  { PORTA,  6, PIO_ANALOG, (PIN_ATTR_ANALOG|PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel6, PWM1_CH0, TCC1_CH0, EXTERNAL_INT_6 }, // TCC1/WO[0]
+  { PORTA,  6, PIO_ANALOG, (PIN_ATTR_ANALOG|PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel6, PWM1_CH0, TCC1_CH0, EXTERNAL_INT_6 }, // TCC1/WO[0]
+  { PORTA,  6, PIO_ANALOG, (PIN_ATTR_ANALOG|PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel6, PWM1_CH0, TCC1_CH0, EXTERNAL_INT_6 }, // TCC1/WO[0]
+  { PORTA,  6, PIO_ANALOG, (PIN_ATTR_ANALOG|PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel6, PWM1_CH0, TCC1_CH0, EXTERNAL_INT_6 }, // TCC1/WO[0]
+  { PORTA,  6, PIO_ANALOG, (PIN_ATTR_ANALOG|PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel6, PWM1_CH0, TCC1_CH0, EXTERNAL_INT_6 }, // TCC1/WO[0]
+  { PORTA,  6, PIO_ANALOG, (PIN_ATTR_ANALOG|PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel6, PWM1_CH0, TCC1_CH0, EXTERNAL_INT_6 }, // TCC1/WO[0]
+  { PORTA,  6, PIO_ANALOG, (PIN_ATTR_ANALOG|PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel6, PWM1_CH0, TCC1_CH0, EXTERNAL_INT_6 }, // TCC1/WO[0]
+  { PORTA,  6, PIO_ANALOG, (PIN_ATTR_ANALOG|PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel6, PWM1_CH0, TCC1_CH0, EXTERNAL_INT_6 }, // TCC1/WO[0]
+  { PORTA,  6, PIO_ANALOG, (PIN_ATTR_ANALOG|PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel6, PWM1_CH0, TCC1_CH0, EXTERNAL_INT_6 }, // TCC1/WO[0]
+  { PORTA,  6, PIO_ANALOG, (PIN_ATTR_ANALOG|PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel6, PWM1_CH0, TCC1_CH0, EXTERNAL_INT_6 }, // TCC1/WO[0]
+  { PORTA,  6, PIO_ANALOG, (PIN_ATTR_ANALOG|PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel6, PWM1_CH0, TCC1_CH0, EXTERNAL_INT_6 }, // TCC1/WO[0]
+  { PORTA,  6, PIO_ANALOG, (PIN_ATTR_ANALOG|PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel6, PWM1_CH0, TCC1_CH0, EXTERNAL_INT_6 }, // TCC1/WO[0]
+  { PORTA,  6, PIO_ANALOG, (PIN_ATTR_ANALOG|PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel6, PWM1_CH0, TCC1_CH0, EXTERNAL_INT_6 }, // TCC1/WO[0]
+  { PORTA,  6, PIO_ANALOG, (PIN_ATTR_ANALOG|PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel6, PWM1_CH0, TCC1_CH0, EXTERNAL_INT_6 }, // TCC1/WO[0]
+
+
+} ;
+
+const void* g_apTCInstances[TCC_INST_NUM+TC_INST_NUM]={ TCC0, TCC1, TCC2, TC3, TC4, TC5 } ;
+
+// Multi-serial objects instantiation
+SERCOM sercom0( SERCOM0 ) ;
+SERCOM sercom1( SERCOM1 ) ;
+SERCOM sercom2( SERCOM2 ) ;
+SERCOM sercom3( SERCOM3 ) ;
+
+Uart Serial1( &sercom1, PIN_SERIAL1_RX, PIN_SERIAL1_TX, PAD_SERIAL1_RX, PAD_SERIAL1_TX ) ;
+
+void SERCOM1_Handler()
+{
+  Serial1.IrqHandler();
+}
+
diff --git a/variants/pirkey/variant.h b/variants/pirkey/variant.h
new file mode 100644
index 000000000..e6d0ce74a
--- /dev/null
+++ b/variants/pirkey/variant.h
@@ -0,0 +1,183 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _VARIANT_ARDUINO_ZERO_
+#define _VARIANT_ARDUINO_ZERO_
+
+// The definitions here needs a SAMD core >=1.6.6
+#define ARDUINO_SAMD_VARIANT_COMPLIANCE 10606
+
+/*----------------------------------------------------------------------------
+ *        Definitions
+ *----------------------------------------------------------------------------*/
+
+/** Frequency of the board main oscillator */
+#define VARIANT_MAINOSC		(32768ul)
+
+/** Master clock frequency */
+#define VARIANT_MCK	(F_CPU)
+
+/*----------------------------------------------------------------------------
+ *        Headers
+ *----------------------------------------------------------------------------*/
+
+#include "WVariant.h"
+
+#ifdef __cplusplus
+#include "SERCOM.h"
+#include "Uart.h"
+#endif // __cplusplus
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif // __cplusplus
+
+/*----------------------------------------------------------------------------
+ *        Pins
+ *----------------------------------------------------------------------------*/
+
+// Number of pins defined in PinDescription array
+#define PINS_COUNT           (22u)
+#define NUM_DIGITAL_PINS     (22u)
+#define NUM_ANALOG_INPUTS    (5u)
+#define NUM_ANALOG_OUTPUTS   (1u)
+#define analogInputToDigitalPin(p)  ((p < 5u) ? (p) + PIN_A0 : -1)
+
+#define digitalPinToPort(P)        ( &(PORT->Group[g_APinDescription[P].ulPort]) )
+#define digitalPinToBitMask(P)     ( 1 << g_APinDescription[P].ulPin )
+//#define analogInPinToBit(P)        ( )
+#define portOutputRegister(port)   ( &(port->OUT.reg) )
+#define portInputRegister(port)    ( &(port->IN.reg) )
+#define portModeRegister(port)     ( &(port->DIR.reg) )
+#define digitalPinHasPWM(P)        ( g_APinDescription[P].ulPWMChannel != NOT_ON_PWM || g_APinDescription[P].ulTCChannel != NOT_ON_TIMER )
+
+/*
+ * digitalPinToTimer(..) is AVR-specific and is not defined for SAMD
+ * architecture. If you need to check if a pin supports PWM you must
+ * use digitalPinHasPWM(..).
+ *
+ * https://github.com/arduino/Arduino/issues/1833
+ */
+// #define digitalPinToTimer(P)
+
+// LEDs
+#define PIN_LED_13           (13u)
+#define PIN_LED_RXL          (6u)
+#define PIN_LED_TXL          (5u)
+#define PIN_LED              PIN_LED_13
+#define PIN_LED2             PIN_LED_RXL
+#define PIN_LED3             PIN_LED_TXL
+#define LED_BUILTIN          PIN_LED_13
+// DotStar LED
+#define INTERNAL_DS_DATA     0
+#define INTERNAL_DS_CLK      1
+
+/*
+ * Analog pins
+ */
+#define PIN_A0               (10ul)
+#define PIN_A1               (PIN_A0 + 1)
+#define PIN_A2               (PIN_A0 + 2)
+#define PIN_A3               (PIN_A0 + 3)
+#define PIN_A4               (PIN_A0 + 4)
+#define PIN_DAC0             PIN_A0
+
+static const uint8_t A0  = PIN_A0;
+static const uint8_t A1  = PIN_A1;
+static const uint8_t A2  = PIN_A2;
+static const uint8_t A3  = PIN_A3;
+static const uint8_t A4  = PIN_A4;
+static const uint8_t DAC0 = PIN_DAC0;
+
+
+#define ADC_RESOLUTION		12
+
+/*
+ * Serial interfaces
+ */
+
+// Serial1 (sercom 1)
+#define PIN_SERIAL1_RX       (4ul) // SWDIO PA31
+#define PAD_SERIAL1_RX       (SERCOM_RX_PAD_3)
+#define PIN_SERIAL1_TX       (3ul) // SWCLK PA30
+#define PAD_SERIAL1_TX       (UART_TX_PAD_2)
+
+/*
+ * SPI Interfaces
+ */
+#define SPI_INTERFACES_COUNT 0 // shared with I2C/UART (can't do both)
+
+/*
+ * Wire Interfaces
+ */
+#define WIRE_INTERFACES_COUNT 0
+
+/*
+ * USB
+ */
+#define PIN_USB_HOST_ENABLE (7ul)
+#define PIN_USB_DM          (8ul)
+#define PIN_USB_DP          (9ul)
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+ *        Arduino objects - C++ only
+ *----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+
+/*	=========================
+ *	===== SERCOM DEFINITION
+ *	=========================
+*/
+extern SERCOM sercom0;
+extern SERCOM sercom1;
+extern SERCOM sercom2;
+extern SERCOM sercom3;
+
+extern Uart Serial1;
+
+#endif
+
+// These serial port names are intended to allow libraries and architecture-neutral
+// sketches to automatically default to the correct port name for a particular type
+// of use.  For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN,
+// the first hardware serial port whose RX/TX pins are not dedicated to another use.
+//
+// SERIAL_PORT_MONITOR        Port which normally prints to the Arduino Serial Monitor
+//
+// SERIAL_PORT_USBVIRTUAL     Port which is USB virtual serial
+//
+// SERIAL_PORT_LINUXBRIDGE    Port which connects to a Linux system via Bridge library
+//
+// SERIAL_PORT_HARDWARE       Hardware serial port, physical RX & TX pins.
+//
+// SERIAL_PORT_HARDWARE_OPEN  Hardware serial ports which are open for use.  Their RX & TX
+//                            pins are NOT connected to anything by default.
+#define SERIAL_PORT_USBVIRTUAL      Serial
+#define SERIAL_PORT_MONITOR         Serial
+// Serial has no physical pins broken out, so it's not listed as HARDWARE port
+#define SERIAL_PORT_HARDWARE        Serial1
+#define SERIAL_PORT_HARDWARE_OPEN   Serial1
+
+#endif /* _VARIANT_ARDUINO_ZERO_ */
+
diff --git a/variants/proxlighttrinkey_m0/debug_scripts/variant.gdb b/variants/proxlighttrinkey_m0/debug_scripts/variant.gdb
new file mode 100644
index 000000000..13ee2a173
--- /dev/null
+++ b/variants/proxlighttrinkey_m0/debug_scripts/variant.gdb
@@ -0,0 +1,31 @@
+#
+#  Arduino Zero OpenOCD script.
+#
+#  Copyright (c) 2014-2015 Arduino LLC. All right reserved.
+#
+#  This library is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 2.1 of the License, or (at your option) any later version.
+#
+#  This library is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#  See the GNU Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library; if not, write to the Free Software
+#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#
+
+# Define 'reset' command
+define reset
+
+info reg
+
+break main
+
+# End of 'reset' command
+end
+
+target remote | openocd -c "interface cmsis-dap" -c "set CHIPNAME at91samd21e18" -f target/at91samdXX.cfg -c "gdb_port pipe; log_output openocd.log"
diff --git a/variants/proxlighttrinkey_m0/linker_scripts/gcc/flash_with_bootloader.ld b/variants/proxlighttrinkey_m0/linker_scripts/gcc/flash_with_bootloader.ld
new file mode 100644
index 000000000..357946455
--- /dev/null
+++ b/variants/proxlighttrinkey_m0/linker_scripts/gcc/flash_with_bootloader.ld
@@ -0,0 +1,216 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* Linker script to configure memory regions.
+ * Need modifying for a specific board.
+ *   FLASH.ORIGIN: starting address of flash
+ *   FLASH.LENGTH: length of flash
+ *   RAM.ORIGIN: starting address of RAM bank 0
+ *   RAM.LENGTH: length of RAM bank 0
+ */
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000+0x2000, LENGTH = 0x00040000-0x2000 /* First 8KB used by bootloader */
+  RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ *   Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ *   __exidx_start
+ *   __exidx_end
+ *   __copy_table_start__
+ *   __copy_table_end__
+ *   __zero_table_start__
+ *   __zero_table_end__
+ *   __etext
+ *   __data_start__
+ *   __preinit_array_start
+ *   __preinit_array_end
+ *   __init_array_start
+ *   __init_array_end
+ *   __fini_array_start
+ *   __fini_array_end
+ *   __data_end__
+ *   __bss_start__
+ *   __bss_end__
+ *   __end__
+ *   end
+ *   __HeapLimit
+ *   __StackLimit
+ *   __StackTop
+ *   __stack
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+	.text :
+	{
+		__text_start__ = .;
+
+		KEEP(*(.sketch_boot))
+
+		. = ALIGN(0x2000);
+		KEEP(*(.isr_vector))
+		*(.text*)
+
+		KEEP(*(.init))
+		KEEP(*(.fini))
+
+		/* .ctors */
+		*crtbegin.o(.ctors)
+		*crtbegin?.o(.ctors)
+		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+		*(SORT(.ctors.*))
+		*(.ctors)
+
+		/* .dtors */
+ 		*crtbegin.o(.dtors)
+ 		*crtbegin?.o(.dtors)
+ 		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ 		*(SORT(.dtors.*))
+ 		*(.dtors)
+
+		*(.rodata*)
+
+		KEEP(*(.eh_frame*))
+	} > FLASH
+
+	.ARM.extab :
+	{
+		*(.ARM.extab* .gnu.linkonce.armextab.*)
+	} > FLASH
+
+	__exidx_start = .;
+	.ARM.exidx :
+	{
+		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
+	} > FLASH
+	__exidx_end = .;
+
+	/* To copy multiple ROM to RAM sections,
+	 * uncomment .copy.table section and,
+	 * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.copy.table :
+	{
+		. = ALIGN(4);
+		__copy_table_start__ = .;
+		LONG (__etext)
+		LONG (__data_start__)
+		LONG (__data_end__ - __data_start__)
+		LONG (__etext2)
+		LONG (__data2_start__)
+		LONG (__data2_end__ - __data2_start__)
+		__copy_table_end__ = .;
+	} > FLASH
+	*/
+
+	/* To clear multiple BSS sections,
+	 * uncomment .zero.table section and,
+	 * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.zero.table :
+	{
+		. = ALIGN(4);
+		__zero_table_start__ = .;
+		LONG (__bss_start__)
+		LONG (__bss_end__ - __bss_start__)
+		LONG (__bss2_start__)
+		LONG (__bss2_end__ - __bss2_start__)
+		__zero_table_end__ = .;
+	} > FLASH
+	*/
+
+	__etext = .;
+
+	.data : AT (__etext)
+	{
+		__data_start__ = .;
+		*(vtable)
+		*(.data*)
+
+		. = ALIGN(4);
+		/* preinit data */
+		PROVIDE_HIDDEN (__preinit_array_start = .);
+		KEEP(*(.preinit_array))
+		PROVIDE_HIDDEN (__preinit_array_end = .);
+
+		. = ALIGN(4);
+		/* init data */
+		PROVIDE_HIDDEN (__init_array_start = .);
+		KEEP(*(SORT(.init_array.*)))
+		KEEP(*(.init_array))
+		PROVIDE_HIDDEN (__init_array_end = .);
+
+
+		. = ALIGN(4);
+		/* finit data */
+		PROVIDE_HIDDEN (__fini_array_start = .);
+		KEEP(*(SORT(.fini_array.*)))
+		KEEP(*(.fini_array))
+		PROVIDE_HIDDEN (__fini_array_end = .);
+
+		KEEP(*(.jcr*))
+		. = ALIGN(16);
+		/* All data end */
+		__data_end__ = .;
+
+	} > RAM
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start__ = .;
+		*(.bss*)
+		*(COMMON)
+		. = ALIGN(4);
+		__bss_end__ = .;
+	} > RAM
+
+	.heap (COPY):
+	{
+		__end__ = .;
+		PROVIDE(end = .);
+		*(.heap*)
+		__HeapLimit = .;
+	} > RAM
+
+	/* .stack_dummy section doesn't contains any symbols. It is only
+	 * used for linker to calculate size of stack sections, and assign
+	 * values to stack symbols later */
+	.stack_dummy (COPY):
+	{
+		*(.stack*)
+	} > RAM
+
+	/* Set stack top to end of RAM, and stack limit move down by
+	 * size of stack_dummy section */
+	__StackTop = ORIGIN(RAM) + LENGTH(RAM);
+	__StackLimit = __StackTop - SIZEOF(.stack_dummy);
+	PROVIDE(__stack = __StackTop);
+
+	__ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ;
+
+	/* Check if data + heap + stack exceeds RAM limit */
+	ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
+}
diff --git a/variants/proxlighttrinkey_m0/linker_scripts/gcc/flash_without_bootloader.ld b/variants/proxlighttrinkey_m0/linker_scripts/gcc/flash_without_bootloader.ld
new file mode 100644
index 000000000..ebeeee37f
--- /dev/null
+++ b/variants/proxlighttrinkey_m0/linker_scripts/gcc/flash_without_bootloader.ld
@@ -0,0 +1,214 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* Linker script to configure memory regions.
+ * Need modifying for a specific board.
+ *   FLASH.ORIGIN: starting address of flash
+ *   FLASH.LENGTH: length of flash
+ *   RAM.ORIGIN: starting address of RAM bank 0
+ *   RAM.LENGTH: length of RAM bank 0
+ */
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00040000
+  RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ *   Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ *   __exidx_start
+ *   __exidx_end
+ *   __copy_table_start__
+ *   __copy_table_end__
+ *   __zero_table_start__
+ *   __zero_table_end__
+ *   __etext
+ *   __data_start__
+ *   __preinit_array_start
+ *   __preinit_array_end
+ *   __init_array_start
+ *   __init_array_end
+ *   __fini_array_start
+ *   __fini_array_end
+ *   __data_end__
+ *   __bss_start__
+ *   __bss_end__
+ *   __end__
+ *   end
+ *   __HeapLimit
+ *   __StackLimit
+ *   __StackTop
+ *   __stack
+ *   __ram_end__
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+	.text :
+	{
+		__text_start__ = .;
+
+		KEEP(*(.isr_vector))
+		*(.text*)
+
+		KEEP(*(.init))
+		KEEP(*(.fini))
+
+		/* .ctors */
+		*crtbegin.o(.ctors)
+		*crtbegin?.o(.ctors)
+		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+		*(SORT(.ctors.*))
+		*(.ctors)
+
+		/* .dtors */
+ 		*crtbegin.o(.dtors)
+ 		*crtbegin?.o(.dtors)
+ 		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ 		*(SORT(.dtors.*))
+ 		*(.dtors)
+
+		*(.rodata*)
+
+		KEEP(*(.eh_frame*))
+	} > FLASH
+
+	.ARM.extab :
+	{
+		*(.ARM.extab* .gnu.linkonce.armextab.*)
+	} > FLASH
+
+	__exidx_start = .;
+	.ARM.exidx :
+	{
+		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
+	} > FLASH
+	__exidx_end = .;
+
+	/* To copy multiple ROM to RAM sections,
+	 * uncomment .copy.table section and,
+	 * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.copy.table :
+	{
+		. = ALIGN(4);
+		__copy_table_start__ = .;
+		LONG (__etext)
+		LONG (__data_start__)
+		LONG (__data_end__ - __data_start__)
+		LONG (__etext2)
+		LONG (__data2_start__)
+		LONG (__data2_end__ - __data2_start__)
+		__copy_table_end__ = .;
+	} > FLASH
+	*/
+
+	/* To clear multiple BSS sections,
+	 * uncomment .zero.table section and,
+	 * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.zero.table :
+	{
+		. = ALIGN(4);
+		__zero_table_start__ = .;
+		LONG (__bss_start__)
+		LONG (__bss_end__ - __bss_start__)
+		LONG (__bss2_start__)
+		LONG (__bss2_end__ - __bss2_start__)
+		__zero_table_end__ = .;
+	} > FLASH
+	*/
+
+	__etext = .;
+
+	.data : AT (__etext)
+	{
+		__data_start__ = .;
+		*(vtable)
+		*(.data*)
+
+		. = ALIGN(4);
+		/* preinit data */
+		PROVIDE_HIDDEN (__preinit_array_start = .);
+		KEEP(*(.preinit_array))
+		PROVIDE_HIDDEN (__preinit_array_end = .);
+
+		. = ALIGN(4);
+		/* init data */
+		PROVIDE_HIDDEN (__init_array_start = .);
+		KEEP(*(SORT(.init_array.*)))
+		KEEP(*(.init_array))
+		PROVIDE_HIDDEN (__init_array_end = .);
+
+
+		. = ALIGN(4);
+		/* finit data */
+		PROVIDE_HIDDEN (__fini_array_start = .);
+		KEEP(*(SORT(.fini_array.*)))
+		KEEP(*(.fini_array))
+		PROVIDE_HIDDEN (__fini_array_end = .);
+
+		KEEP(*(.jcr*))
+		. = ALIGN(16);
+		/* All data end */
+		__data_end__ = .;
+
+	} > RAM
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start__ = .;
+		*(.bss*)
+		*(COMMON)
+		. = ALIGN(4);
+		__bss_end__ = .;
+	} > RAM
+
+	.heap (COPY):
+	{
+		__end__ = .;
+		PROVIDE(end = .);
+		*(.heap*)
+		__HeapLimit = .;
+	} > RAM
+
+	/* .stack_dummy section doesn't contains any symbols. It is only
+	 * used for linker to calculate size of stack sections, and assign
+	 * values to stack symbols later */
+	.stack_dummy (COPY):
+	{
+		*(.stack*)
+	} > RAM
+
+	/* Set stack top to end of RAM, and stack limit move down by
+	 * size of stack_dummy section */
+	__StackTop = ORIGIN(RAM) + LENGTH(RAM) ;
+	__StackLimit = __StackTop - SIZEOF(.stack_dummy);
+	PROVIDE(__stack = __StackTop);
+
+	__ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ;
+
+	/* Check if data + heap + stack exceeds RAM limit */
+	ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
+}
diff --git a/variants/proxlighttrinkey_m0/openocd_scripts/proxlighttrinkey_m0.cfg b/variants/proxlighttrinkey_m0/openocd_scripts/proxlighttrinkey_m0.cfg
new file mode 100644
index 000000000..e4c3f81dc
--- /dev/null
+++ b/variants/proxlighttrinkey_m0/openocd_scripts/proxlighttrinkey_m0.cfg
@@ -0,0 +1,28 @@
+#
+#  Adafruit ItsyBitsy M0 OpenOCD script.
+#
+#  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+#
+#  This library is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 2.1 of the License, or (at your option) any later version.
+#
+#  This library is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#  See the GNU Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library; if not, write to the Free Software
+#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#
+
+# chip name
+set CHIPNAME at91samd21e18
+set ENDIAN little
+
+# choose a port here
+set telnet_port 0
+
+source [find target/at91samdXX.cfg]
diff --git a/variants/proxlighttrinkey_m0/pins_arduino.h b/variants/proxlighttrinkey_m0/pins_arduino.h
new file mode 100644
index 000000000..db0e40c3d
--- /dev/null
+++ b/variants/proxlighttrinkey_m0/pins_arduino.h
@@ -0,0 +1,21 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+// API compatibility
+#include "variant.h"
+
diff --git a/variants/proxlighttrinkey_m0/variant.cpp b/variants/proxlighttrinkey_m0/variant.cpp
new file mode 100644
index 000000000..da5bd8d4d
--- /dev/null
+++ b/variants/proxlighttrinkey_m0/variant.cpp
@@ -0,0 +1,57 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "variant.h"
+#include "Arduino.h"
+/*
+ * Pins descriptions
+ */
+const PinDescription g_APinDescription[]=
+{
+  // Fake DAC A0 pin just so we can compile stuff
+  { PORTA,  2, PIO_ANALOG, (PIN_ATTR_DIGITAL|PIN_ATTR_ANALOG|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel0, PWM2_CH0, TCC2_CH0, EXTERNAL_INT_2 }, // A0 / D0 / DAC  
+
+  // touch 1 / A1
+  { PORTA,  7, PIO_ANALOG, (PIN_ATTR_ANALOG|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel7, PWM1_CH1, TCC1_CH1, EXTERNAL_INT_7 }, // TCC1/WO[1]
+  // touch 2 / A2
+  { PORTA,  3, PIO_ANALOG, (PIN_ATTR_ANALOG), ADC_Channel3, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_3 }, // ADC/AIN[3]
+
+  // NeoPixel / D3
+  { PORTA, 15, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM3_CH1, TC3_CH1, EXTERNAL_INT_15 }, // TC3/WO[1]
+
+  // I2C SDA D4 & SCL D5
+  { PORTA, 16, PIO_SERCOM, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER_ALT), No_ADC_Channel, PWM0_CH6, TCC0_CH6, EXTERNAL_INT_0 }, // D4 / SDA / PWM
+  { PORTA, 17, PIO_SERCOM, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER_ALT), No_ADC_Channel, PWM0_CH7, TCC0_CH7, EXTERNAL_INT_1 }, // D5 / SCL / PWM
+
+  // Interrupt D6
+  { PORTA,  0, PIO_DIGITAL, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel,  PWM2_CH0, TCC2_CH0, EXTERNAL_INT_0 },
+  
+  // USB pins
+  { PORTA, 28, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB Host enable
+  { PORTA, 24, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB/DM
+  { PORTA, 25, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB/DP
+
+} ;
+
+const void* g_apTCInstances[TCC_INST_NUM+TC_INST_NUM]={ TCC0, TCC1, TCC2, TC3, TC4, TC5 } ;
+
+// Multi-serial objects instantiation
+SERCOM sercom0( SERCOM0 ) ;
+SERCOM sercom1( SERCOM1 ) ;
+SERCOM sercom2( SERCOM2 ) ;
+SERCOM sercom3( SERCOM3 ) ;
diff --git a/variants/proxlighttrinkey_m0/variant.h b/variants/proxlighttrinkey_m0/variant.h
new file mode 100644
index 000000000..bb9232265
--- /dev/null
+++ b/variants/proxlighttrinkey_m0/variant.h
@@ -0,0 +1,180 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _VARIANT_PROXLIGHTTRINKEY_ZERO_
+#define _VARIANT_PROXLIGHTTRINKEY_ZERO_
+
+// The definitions here needs a SAMD core >=1.6.10
+#define ARDUINO_SAMD_VARIANT_COMPLIANCE 10610
+
+/*----------------------------------------------------------------------------
+ *        Definitions
+ *----------------------------------------------------------------------------*/
+
+/** Frequency of the board main oscillator */
+#define VARIANT_MAINOSC		(32768ul)
+
+/** Master clock frequency */
+#define VARIANT_MCK	(F_CPU)
+
+/*----------------------------------------------------------------------------
+ *        Headers
+ *----------------------------------------------------------------------------*/
+
+#include "WVariant.h"
+
+#ifdef __cplusplus
+#include "SERCOM.h"
+#include "Uart.h"
+#endif // __cplusplus
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif // __cplusplus
+
+/*----------------------------------------------------------------------------
+ *        Pins
+ *----------------------------------------------------------------------------*/
+
+// Number of pins defined in PinDescription array
+#define PINS_COUNT           (10u)
+#define NUM_DIGITAL_PINS     (6u)
+#define NUM_ANALOG_INPUTS    (3u)
+#define NUM_ANALOG_OUTPUTS   (1u)
+#define analogInputToDigitalPin(p)  (p)
+
+#define digitalPinToPort(P)        ( &(PORT->Group[g_APinDescription[P].ulPort]) )
+#define digitalPinToBitMask(P)     ( 1 << g_APinDescription[P].ulPin )
+//#define analogInPinToBit(P)        ( )
+#define portOutputRegister(port)   ( &(port->OUT.reg) )
+#define portInputRegister(port)    ( &(port->IN.reg) )
+#define portModeRegister(port)     ( &(port->DIR.reg) )
+#define digitalPinHasPWM(P)        ( g_APinDescription[P].ulPWMChannel != NOT_ON_PWM || g_APinDescription[P].ulTCChannel != NOT_ON_TIMER )
+
+/*
+ * digitalPinToTimer(..) is AVR-specific and is not defined for SAMD
+ * architecture. If you need to check if a pin supports PWM you must
+ * use digitalPinHasPWM(..).
+ *
+ * https://github.com/arduino/Arduino/issues/1833
+ */
+// #define digitalPinToTimer(P)
+
+// LEDs
+#define PIN_NEOPIXEL         (3u)
+#define NUM_NEOPIXEL         (2u)
+
+// TOUCH PINS
+#define PIN_TOUCH1      1
+#define PIN_TOUCH2      2
+
+#define PIN_INTERRUPT   6
+
+/*
+ * Analog pins
+ */
+#define PIN_A0               (0ul)
+#define PIN_A1               (1)
+#define PIN_A2               (2)
+#define PIN_DAC0             PIN_A0
+
+static const uint8_t A0  = PIN_A0;
+static const uint8_t A1  = PIN_A1;
+static const uint8_t A2  = PIN_A2;
+
+#define ADC_RESOLUTION		12
+
+
+/*
+ * SPI Interfaces
+ */
+#define SPI_INTERFACES_COUNT 0
+
+/*
+ * Wire Interfaces
+ */
+#define WIRE_INTERFACES_COUNT 1
+
+#define PIN_WIRE_SDA         (4u)
+#define PIN_WIRE_SCL         (5u)
+#define PERIPH_WIRE          sercom1
+#define WIRE_IT_HANDLER      SERCOM1_Handler
+
+static const uint8_t SDA = PIN_WIRE_SDA;
+static const uint8_t SCL = PIN_WIRE_SCL;
+
+/*
+ * USB
+ */
+#define PIN_USB_HOST_ENABLE (5ul)
+#define PIN_USB_DM          (6ul)
+#define PIN_USB_DP          (7ul)
+/*
+ * I2S Interfaces
+ */
+#define I2S_INTERFACES_COUNT 0
+
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+ *        Arduino objects - C++ only
+ *----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+
+/*	=========================
+ *	===== SERCOM DEFINITION
+ *	=========================
+*/
+extern SERCOM sercom0;
+extern SERCOM sercom1;
+extern SERCOM sercom2;
+extern SERCOM sercom3;
+extern SERCOM sercom4;
+extern SERCOM sercom5;
+
+
+#endif
+
+// These serial port names are intended to allow libraries and architecture-neutral
+// sketches to automatically default to the correct port name for a particular type
+// of use.  For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN,
+// the first hardware serial port whose RX/TX pins are not dedicated to another use.
+//
+// SERIAL_PORT_MONITOR        Port which normally prints to the Arduino Serial Monitor
+//
+// SERIAL_PORT_USBVIRTUAL     Port which is USB virtual serial
+//
+// SERIAL_PORT_LINUXBRIDGE    Port which connects to a Linux system via Bridge library
+//
+// SERIAL_PORT_HARDWARE       Hardware serial port, physical RX & TX pins.
+//
+// SERIAL_PORT_HARDWARE_OPEN  Hardware serial ports which are open for use.  Their RX & TX
+//                            pins are NOT connected to anything by default.
+#define SERIAL_PORT_USBVIRTUAL      Serial
+#define SERIAL_PORT_MONITOR         Serial
+// Serial has no physical pins broken out, so it's not listed as HARDWARE port
+#define SERIAL_PORT_HARDWARE        Serial1
+#define SERIAL_PORT_HARDWARE_OPEN   Serial1
+
+#endif /* _VARIANT_ARDUINO_ZERO_ */
+
diff --git a/variants/pybadge_airlift_m4/debug_scripts/variant.gdb b/variants/pybadge_airlift_m4/debug_scripts/variant.gdb
new file mode 100644
index 000000000..3c37ffde2
--- /dev/null
+++ b/variants/pybadge_airlift_m4/debug_scripts/variant.gdb
@@ -0,0 +1,31 @@
+#
+#  Arduino Zero OpenOCD script.
+#
+#  Copyright (c) 2014-2015 Arduino LLC. All right reserved.
+#
+#  This library is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 2.1 of the License, or (at your option) any later version.
+#
+#  This library is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#  See the GNU Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library; if not, write to the Free Software
+#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#
+
+# Define 'reset' command
+define reset
+
+info reg
+
+break main
+
+# End of 'reset' command
+end
+
+target remote | openocd -c "interface cmsis-dap" -c "set CHIPNAME at91samd21g18" -f target/at91samdXX.cfg -c "gdb_port pipe; log_output openocd.log"
diff --git a/variants/pybadge_airlift_m4/linker_scripts/gcc/flash_with_bootloader.ld b/variants/pybadge_airlift_m4/linker_scripts/gcc/flash_with_bootloader.ld
new file mode 100644
index 000000000..1bdea69ae
--- /dev/null
+++ b/variants/pybadge_airlift_m4/linker_scripts/gcc/flash_with_bootloader.ld
@@ -0,0 +1,216 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* Linker script to configure memory regions.
+ * Need modifying for a specific board.
+ *   FLASH.ORIGIN: starting address of flash
+ *   FLASH.LENGTH: length of flash
+ *   RAM.ORIGIN: starting address of RAM bank 0
+ *   RAM.LENGTH: length of RAM bank 0
+ */
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000+0x4000, LENGTH = 0x00080000-0x4000 /* First 16KB used by bootloader */
+  RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00030000
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ *   Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ *   __exidx_start
+ *   __exidx_end
+ *   __copy_table_start__
+ *   __copy_table_end__
+ *   __zero_table_start__
+ *   __zero_table_end__
+ *   __etext
+ *   __data_start__
+ *   __preinit_array_start
+ *   __preinit_array_end
+ *   __init_array_start
+ *   __init_array_end
+ *   __fini_array_start
+ *   __fini_array_end
+ *   __data_end__
+ *   __bss_start__
+ *   __bss_end__
+ *   __end__
+ *   end
+ *   __HeapLimit
+ *   __StackLimit
+ *   __StackTop
+ *   __stack
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+	.text :
+	{
+		__text_start__ = .;
+
+		KEEP(*(.sketch_boot))
+
+		. = ALIGN(0x4000);
+		KEEP(*(.isr_vector))
+		*(.text*)
+
+		KEEP(*(.init))
+		KEEP(*(.fini))
+
+		/* .ctors */
+		*crtbegin.o(.ctors)
+		*crtbegin?.o(.ctors)
+		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+		*(SORT(.ctors.*))
+		*(.ctors)
+
+		/* .dtors */
+ 		*crtbegin.o(.dtors)
+ 		*crtbegin?.o(.dtors)
+ 		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ 		*(SORT(.dtors.*))
+ 		*(.dtors)
+
+		*(.rodata*)
+
+		KEEP(*(.eh_frame*))
+	} > FLASH
+
+	.ARM.extab :
+	{
+		*(.ARM.extab* .gnu.linkonce.armextab.*)
+	} > FLASH
+
+	__exidx_start = .;
+	.ARM.exidx :
+	{
+		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
+	} > FLASH
+	__exidx_end = .;
+
+	/* To copy multiple ROM to RAM sections,
+	 * uncomment .copy.table section and,
+	 * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.copy.table :
+	{
+		. = ALIGN(4);
+		__copy_table_start__ = .;
+		LONG (__etext)
+		LONG (__data_start__)
+		LONG (__data_end__ - __data_start__)
+		LONG (__etext2)
+		LONG (__data2_start__)
+		LONG (__data2_end__ - __data2_start__)
+		__copy_table_end__ = .;
+	} > FLASH
+	*/
+
+	/* To clear multiple BSS sections,
+	 * uncomment .zero.table section and,
+	 * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.zero.table :
+	{
+		. = ALIGN(4);
+		__zero_table_start__ = .;
+		LONG (__bss_start__)
+		LONG (__bss_end__ - __bss_start__)
+		LONG (__bss2_start__)
+		LONG (__bss2_end__ - __bss2_start__)
+		__zero_table_end__ = .;
+	} > FLASH
+	*/
+
+	__etext = .;
+
+	.data : AT (__etext)
+	{
+		__data_start__ = .;
+		*(vtable)
+		*(.data*)
+
+		. = ALIGN(4);
+		/* preinit data */
+		PROVIDE_HIDDEN (__preinit_array_start = .);
+		KEEP(*(.preinit_array))
+		PROVIDE_HIDDEN (__preinit_array_end = .);
+
+		. = ALIGN(4);
+		/* init data */
+		PROVIDE_HIDDEN (__init_array_start = .);
+		KEEP(*(SORT(.init_array.*)))
+		KEEP(*(.init_array))
+		PROVIDE_HIDDEN (__init_array_end = .);
+
+
+		. = ALIGN(4);
+		/* finit data */
+		PROVIDE_HIDDEN (__fini_array_start = .);
+		KEEP(*(SORT(.fini_array.*)))
+		KEEP(*(.fini_array))
+		PROVIDE_HIDDEN (__fini_array_end = .);
+
+		KEEP(*(.jcr*))
+		. = ALIGN(16);
+		/* All data end */
+		__data_end__ = .;
+
+	} > RAM
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start__ = .;
+		*(.bss*)
+		*(COMMON)
+		. = ALIGN(4);
+		__bss_end__ = .;
+	} > RAM
+
+	.heap (COPY):
+	{
+		__end__ = .;
+		PROVIDE(end = .);
+		*(.heap*)
+		__HeapLimit = .;
+	} > RAM
+
+	/* .stack_dummy section doesn't contains any symbols. It is only
+	 * used for linker to calculate size of stack sections, and assign
+	 * values to stack symbols later */
+	.stack_dummy (COPY):
+	{
+		*(.stack*)
+	} > RAM
+
+	/* Set stack top to end of RAM, and stack limit move down by
+	 * size of stack_dummy section */
+	__StackTop = ORIGIN(RAM) + LENGTH(RAM);
+	__StackLimit = __StackTop - SIZEOF(.stack_dummy);
+	PROVIDE(__stack = __StackTop);
+
+	__ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ;
+
+	/* Check if data + heap + stack exceeds RAM limit */
+	ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
+}
diff --git a/variants/pybadge_airlift_m4/linker_scripts/gcc/flash_without_bootloader.ld b/variants/pybadge_airlift_m4/linker_scripts/gcc/flash_without_bootloader.ld
new file mode 100644
index 000000000..9c0c4e06d
--- /dev/null
+++ b/variants/pybadge_airlift_m4/linker_scripts/gcc/flash_without_bootloader.ld
@@ -0,0 +1,214 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* Linker script to configure memory regions.
+ * Need modifying for a specific board.
+ *   FLASH.ORIGIN: starting address of flash
+ *   FLASH.LENGTH: length of flash
+ *   RAM.ORIGIN: starting address of RAM bank 0
+ *   RAM.LENGTH: length of RAM bank 0
+ */
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00080000
+  RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00030000
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ *   Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ *   __exidx_start
+ *   __exidx_end
+ *   __copy_table_start__
+ *   __copy_table_end__
+ *   __zero_table_start__
+ *   __zero_table_end__
+ *   __etext
+ *   __data_start__
+ *   __preinit_array_start
+ *   __preinit_array_end
+ *   __init_array_start
+ *   __init_array_end
+ *   __fini_array_start
+ *   __fini_array_end
+ *   __data_end__
+ *   __bss_start__
+ *   __bss_end__
+ *   __end__
+ *   end
+ *   __HeapLimit
+ *   __StackLimit
+ *   __StackTop
+ *   __stack
+ *   __ram_end__
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+	.text :
+	{
+		__text_start__ = .;
+
+		KEEP(*(.isr_vector))
+		*(.text*)
+
+		KEEP(*(.init))
+		KEEP(*(.fini))
+
+		/* .ctors */
+		*crtbegin.o(.ctors)
+		*crtbegin?.o(.ctors)
+		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+		*(SORT(.ctors.*))
+		*(.ctors)
+
+		/* .dtors */
+ 		*crtbegin.o(.dtors)
+ 		*crtbegin?.o(.dtors)
+ 		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ 		*(SORT(.dtors.*))
+ 		*(.dtors)
+
+		*(.rodata*)
+
+		KEEP(*(.eh_frame*))
+	} > FLASH
+
+	.ARM.extab :
+	{
+		*(.ARM.extab* .gnu.linkonce.armextab.*)
+	} > FLASH
+
+	__exidx_start = .;
+	.ARM.exidx :
+	{
+		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
+	} > FLASH
+	__exidx_end = .;
+
+	/* To copy multiple ROM to RAM sections,
+	 * uncomment .copy.table section and,
+	 * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.copy.table :
+	{
+		. = ALIGN(4);
+		__copy_table_start__ = .;
+		LONG (__etext)
+		LONG (__data_start__)
+		LONG (__data_end__ - __data_start__)
+		LONG (__etext2)
+		LONG (__data2_start__)
+		LONG (__data2_end__ - __data2_start__)
+		__copy_table_end__ = .;
+	} > FLASH
+	*/
+
+	/* To clear multiple BSS sections,
+	 * uncomment .zero.table section and,
+	 * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.zero.table :
+	{
+		. = ALIGN(4);
+		__zero_table_start__ = .;
+		LONG (__bss_start__)
+		LONG (__bss_end__ - __bss_start__)
+		LONG (__bss2_start__)
+		LONG (__bss2_end__ - __bss2_start__)
+		__zero_table_end__ = .;
+	} > FLASH
+	*/
+
+	__etext = .;
+
+	.data : AT (__etext)
+	{
+		__data_start__ = .;
+		*(vtable)
+		*(.data*)
+
+		. = ALIGN(4);
+		/* preinit data */
+		PROVIDE_HIDDEN (__preinit_array_start = .);
+		KEEP(*(.preinit_array))
+		PROVIDE_HIDDEN (__preinit_array_end = .);
+
+		. = ALIGN(4);
+		/* init data */
+		PROVIDE_HIDDEN (__init_array_start = .);
+		KEEP(*(SORT(.init_array.*)))
+		KEEP(*(.init_array))
+		PROVIDE_HIDDEN (__init_array_end = .);
+
+
+		. = ALIGN(4);
+		/* finit data */
+		PROVIDE_HIDDEN (__fini_array_start = .);
+		KEEP(*(SORT(.fini_array.*)))
+		KEEP(*(.fini_array))
+		PROVIDE_HIDDEN (__fini_array_end = .);
+
+		KEEP(*(.jcr*))
+		. = ALIGN(16);
+		/* All data end */
+		__data_end__ = .;
+
+	} > RAM
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start__ = .;
+		*(.bss*)
+		*(COMMON)
+		. = ALIGN(4);
+		__bss_end__ = .;
+	} > RAM
+
+	.heap (COPY):
+	{
+		__end__ = .;
+		PROVIDE(end = .);
+		*(.heap*)
+		__HeapLimit = .;
+	} > RAM
+
+	/* .stack_dummy section doesn't contains any symbols. It is only
+	 * used for linker to calculate size of stack sections, and assign
+	 * values to stack symbols later */
+	.stack_dummy (COPY):
+	{
+		*(.stack*)
+	} > RAM
+
+	/* Set stack top to end of RAM, and stack limit move down by
+	 * size of stack_dummy section */
+	__StackTop = ORIGIN(RAM) + LENGTH(RAM) ;
+	__StackLimit = __StackTop - SIZEOF(.stack_dummy);
+	PROVIDE(__stack = __StackTop);
+
+	__ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ;
+
+	/* Check if data + heap + stack exceeds RAM limit */
+	ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
+}
diff --git a/variants/mkrwan1300/openocd_scripts/arduino_zero.cfg b/variants/pybadge_airlift_m4/openocd_scripts/arduino_zero.cfg
similarity index 100%
rename from variants/mkrwan1300/openocd_scripts/arduino_zero.cfg
rename to variants/pybadge_airlift_m4/openocd_scripts/arduino_zero.cfg
diff --git a/variants/pybadge_airlift_m4/pins_arduino.h b/variants/pybadge_airlift_m4/pins_arduino.h
new file mode 100644
index 000000000..db0e40c3d
--- /dev/null
+++ b/variants/pybadge_airlift_m4/pins_arduino.h
@@ -0,0 +1,21 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+// API compatibility
+#include "variant.h"
+
diff --git a/variants/pybadge_airlift_m4/variant.cpp b/variants/pybadge_airlift_m4/variant.cpp
new file mode 100644
index 000000000..ce2304ba1
--- /dev/null
+++ b/variants/pybadge_airlift_m4/variant.cpp
@@ -0,0 +1,154 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "variant.h"
+
+/*
+ * Pins descriptions
+ */
+const PinDescription g_APinDescription[] =
+    {
+        // 0..13 - Digital pins
+        // ----------------------
+        // 0/1 - SERCOM/UART (Serial1)
+        {PORTB, 17, PIO_SERCOM, PIN_ATTR_PWM_G, No_ADC_Channel, TCC0_CH5, NOT_ON_TIMER, EXTERNAL_INT_1},
+        {PORTB, 16, PIO_SERCOM, PIN_ATTR_PWM_G, No_ADC_Channel, TCC0_CH4, NOT_ON_TIMER, EXTERNAL_INT_0},
+
+        // 2..12
+        // Digital Low
+        {PORTB, 3, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel15, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_3},
+        {PORTB, 2, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel14, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2},
+        {PORTA, 14, PIO_SERCOM, PIN_ATTR_PWM_E, No_ADC_Channel, TC3_CH0, TC3_CH0, EXTERNAL_INT_14},
+        {PORTA, 16, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_0},
+        {PORTA, 18, PIO_SERCOM, PIO_SERCOM, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2},
+        {PORTB, 14, PIO_DIGITAL, PIN_ATTR_PWM_F, No_ADC_Channel, TCC4_CH0, TC5_CH0, EXTERNAL_INT_14},
+
+        // Digital High
+        {PORTA, 15, PIO_DIGITAL, PIN_ATTR_PWM_E, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_15}, // D8 - NEOPIXEL
+        {PORTA, 19, PIO_DIGITAL, PIN_ATTR_PWM_E, No_ADC_Channel, TC3_CH1, TC3_CH1, EXTERNAL_INT_3},
+        {PORTA, 20, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_4},
+        {PORTA, 21, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_5},
+        {PORTA, 22, PIO_SERCOM, PIN_ATTR_PWM_G, No_ADC_Channel, TCC0_CH2, TC4_CH0, EXTERNAL_INT_6},
+
+        // 13 (LED)
+        {PORTA, 23, PIO_SERCOM, PIN_ATTR_PWM_G, No_ADC_Channel, TCC0_CH3, TC4_CH1, EXTERNAL_INT_7},
+
+        // 14..23 - Analog pins
+        // --------------------
+        {PORTA, 2, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel0, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2},
+        {PORTA, 5, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel5, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_5},
+        {PORTB, 8, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel2, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_8},
+        {PORTB, 9, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel3, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_9},
+        {PORTA, 4, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel4, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_6},
+        {PORTA, 6, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel6, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_10},
+
+        {PORTB, 1, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel13, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_1},    // A6, D20 - vbatt
+        {PORTB, 4, PIO_ANALOG, PIN_ATTR_ANALOG_ALT, ADC_Channel6, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_4}, // A7, D21 - Light
+        {PORTB, 3, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel15, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2},    // A8 / D2
+        {PORTB, 2, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel14, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2},    // A9 / D3
+
+        // 24..25 I2C pins (SDA/SCL)
+        // ----------------------
+        {PORTA, 12, PIO_SERCOM, PIN_ATTR_PWM_E, No_ADC_Channel, TC2_CH0, TC2_CH0, EXTERNAL_INT_12}, // SDA
+        {PORTA, 13, PIO_SERCOM, PIN_ATTR_PWM_E, No_ADC_Channel, TC2_CH1, TC2_CH1, EXTERNAL_INT_13}, // SCL
+
+        // 26..28 - SPI pins (MISO,MOSI,SCK)
+        // ----------------------
+        {PORTB, 22, PIO_SERCOM, (PIN_ATTR_DIGITAL), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_6}, // MISO: SERCOM1/PAD[2]
+        {PORTB, 23, PIO_SERCOM, (PIN_ATTR_DIGITAL), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_7}, // MOSI: SERCOM1/PAD[3]
+        {PORTA, 17, PIO_SERCOM, (PIN_ATTR_DIGITAL), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_1}, // SCK: SERCOM1/PAD[1]
+
+        // 29..31 - USB
+        // --------------------
+        {NOT_A_PORT, PIN_NOT_A_PIN, PIO_NOT_A_PIN, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE}, // USB Host enable DOES NOT EXIST ON THIS BOARD
+        {PORTA, 24, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE},                       // USB/DM
+        {PORTA, 25, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE},                       // USB/DP
+
+        // 32 (AREF)
+        {PORTA, 3, PIO_ANALOG, PIN_ATTR_ANALOG, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE}, // DAC/VREFP
+
+        // ----------------------
+        // 33..34 - Alternate use of A0 (DAC output)
+        {PORTA, 2, PIO_ANALOG, PIN_ATTR_ANALOG, DAC_Channel0, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE}, // DAC/VOUT0
+        {PORTA, 5, PIO_ANALOG, PIN_ATTR_ANALOG, DAC_Channel1, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE}, // DAC/VOUT1
+
+        // ----------------------
+        // 35..40 QSPI (SCK, CS, IO0, IO1, IO2, IO3)
+        {PORTB, 10, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE},
+        {PORTB, 11, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE},
+        {PORTA, 8, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE},
+        {PORTA, 9, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE},
+        {PORTA, 10, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE},
+        {PORTA, 11, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE},
+
+        // 41..46 - TFT SPI port + control pins
+        // --------------------
+        {PORTB, 15, PIO_SERCOM, PIN_ATTR_PWM_F, No_ADC_Channel, TCC4_CH1, TC5_CH1, EXTERNAL_INT_15},         // SERCOM 4.3 MOSI
+        {PORTB, 13, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_13}, // SERCOM 4.1 SCK
+        {PORTB, 12, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_12}, // SERCOM 4.0 'miso' (NC)
+        {PORTB, 6, PIO_OUTPUT, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_6},   // D44 TFT CS
+        {PORTB, 5, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_5},  // D45 TFT DC
+        {PORTB, 7, PIO_OUTPUT, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_7},   // D46 TFT RST
+
+        // 47 - backlight
+        {PORTA, 1, PIO_DIGITAL, PIN_ATTR_PWM_E, No_ADC_Channel, TC2_CH1, TC2_CH1, EXTERNAL_INT_1}, // D47 TFT BACKLITE
+
+        // 48 - button control
+        {PORTB, 31, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_15}, // D48 button clock
+        {PORTB, 30, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_14}, // D49 button data
+        {PORTB, 0, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_0},   // D50 button latch
+
+        // D51 Speaker enable
+        {PORTA, 27, PIO_DIGITAL, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE},
+
+        // ESP GPIO0, BUSY, RESET (52-54)
+        {PORTA, 31, PIO_DIGITAL, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE}, // D52 ESP32_GPIO0
+        {PORTA, 0, PIO_DIGITAL, PIN_ATTR_PWM_E, No_ADC_Channel, TC2_CH0, TC2_CH0, EXTERNAL_INT_0},            // D53 ESP32_BUSY
+        {PORTB, 12, PIO_DIGITAL, PIN_ATTR_PWM_F, No_ADC_Channel, TCC3_CH0, TC4_CH0, EXTERNAL_INT_12},         // D54 ESP32_RESET 
+
+};
+
+const void* g_apTCInstances[TCC_INST_NUM+TC_INST_NUM]={ TCC0, TCC1, TCC2, TCC3, TCC4, TC0, TC1, TC2, TC3, TC4, TC5 } ;
+const uint32_t GCLK_CLKCTRL_IDs[TCC_INST_NUM+TC_INST_NUM] = { TCC0_GCLK_ID, TCC1_GCLK_ID, TCC2_GCLK_ID, TCC3_GCLK_ID, TCC4_GCLK_ID, TC0_GCLK_ID, TC1_GCLK_ID, TC2_GCLK_ID, TC3_GCLK_ID, TC4_GCLK_ID, TC5_GCLK_ID } ;
+
+// Multi-serial objects instantiation
+SERCOM sercom0( SERCOM0 ) ;
+SERCOM sercom1( SERCOM1 ) ;
+SERCOM sercom2( SERCOM2 ) ;
+SERCOM sercom3( SERCOM3 ) ;
+SERCOM sercom4( SERCOM4 ) ;
+SERCOM sercom5( SERCOM5 ) ;
+
+Uart Serial1( &sercom5, PIN_SERIAL1_RX, PIN_SERIAL1_TX, PAD_SERIAL1_RX, PAD_SERIAL1_TX ) ;
+
+void SERCOM5_0_Handler()
+{
+  Serial1.IrqHandler();
+}
+void SERCOM5_1_Handler()
+{
+  Serial1.IrqHandler();
+}
+void SERCOM5_2_Handler()
+{
+  Serial1.IrqHandler();
+}
+void SERCOM5_3_Handler()
+{
+  Serial1.IrqHandler();
+}
diff --git a/variants/pybadge_airlift_m4/variant.h b/variants/pybadge_airlift_m4/variant.h
new file mode 100644
index 000000000..0887238d5
--- /dev/null
+++ b/variants/pybadge_airlift_m4/variant.h
@@ -0,0 +1,271 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _VARIANT_PYBADGE_AIRLIFT_M4_
+#define _VARIANT_PYBADGE_AIRLIFT_M4_
+
+// The definitions here needs a SAMD core >=1.6.10
+#define ARDUINO_SAMD_VARIANT_COMPLIANCE 10610
+
+/*----------------------------------------------------------------------------
+ *        Definitions
+ *----------------------------------------------------------------------------*/
+
+/** Frequency of the board main oscillator */
+#define VARIANT_MAINOSC		(32768ul)
+
+/** Master clock frequency */
+#define VARIANT_MCK	   (F_CPU)
+
+#define VARIANT_GCLK0_FREQ (F_CPU)
+#define VARIANT_GCLK1_FREQ (48000000UL)
+#define VARIANT_GCLK2_FREQ (100000000UL)
+
+/*----------------------------------------------------------------------------
+ *        Headers
+ *----------------------------------------------------------------------------*/
+
+#include "WVariant.h"
+
+#ifdef __cplusplus
+#include "SERCOM.h"
+#include "Uart.h"
+#endif // __cplusplus
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif // __cplusplus
+
+/*----------------------------------------------------------------------------
+ *        Pins
+ *----------------------------------------------------------------------------*/
+
+// Number of pins defined in PinDescription array
+#define PINS_COUNT           (55u)
+#define NUM_DIGITAL_PINS     (25u)
+#define NUM_ANALOG_INPUTS    (10u)
+#define NUM_ANALOG_OUTPUTS   (2u)
+#define analogInputToDigitalPin(p)  ((p < 6u) ? (p) + 14u : -1)
+
+#define digitalPinToPort(P)        ( &(PORT->Group[g_APinDescription[P].ulPort]) )
+#define digitalPinToBitMask(P)     ( 1 << g_APinDescription[P].ulPin )
+//#define analogInPinToBit(P)        ( )
+#define portOutputRegister(port)   ( &(port->OUT.reg) )
+#define portInputRegister(port)    ( &(port->IN.reg) )
+#define portModeRegister(port)     ( &(port->DIR.reg) )
+#define digitalPinHasPWM(P)        ( g_APinDescription[P].ulPWMChannel != NOT_ON_PWM || g_APinDescription[P].ulTCChannel != NOT_ON_TIMER )
+
+/*
+ * digitalPinToTimer(..) is AVR-specific and is not defined for SAMD
+ * architecture. If you need to check if a pin supports PWM you must
+ * use digitalPinHasPWM(..).
+ *
+ * https://github.com/arduino/Arduino/issues/1833
+ */
+// #define digitalPinToTimer(P)
+
+// LEDs
+#define PIN_LED_13           (13u)
+#define PIN_LED              PIN_LED_13
+#define LED_BUILTIN          PIN_LED_13
+
+/*
+ * Analog pins
+ */
+#define PIN_A0               (14ul)
+#define PIN_A1               (PIN_A0 + 1)
+#define PIN_A2               (PIN_A0 + 2)
+#define PIN_A3               (PIN_A0 + 3)
+#define PIN_A4               (PIN_A0 + 4)
+#define PIN_A5               (PIN_A0 + 5)
+#define PIN_A6               (PIN_A0 + 6)
+#define PIN_A7               (PIN_A0 + 7)
+#define PIN_A8               (PIN_A0 + 8)
+#define PIN_A9               (PIN_A0 + 9)
+
+#define PIN_DAC0             PIN_A0
+#define PIN_DAC1             PIN_A1
+
+static const uint8_t A0  = PIN_A0;
+static const uint8_t A1  = PIN_A1;
+static const uint8_t A2  = PIN_A2;
+static const uint8_t A3  = PIN_A3;
+static const uint8_t A4  = PIN_A4;
+static const uint8_t A5  = PIN_A5;
+static const uint8_t A6  = PIN_A6;
+static const uint8_t A7  = PIN_A7;
+static const uint8_t A8  = PIN_A8;
+static const uint8_t A9  = PIN_A9;
+
+static const uint8_t DAC0 = PIN_DAC0;
+static const uint8_t DAC1 = PIN_DAC1;
+
+#define ADC_RESOLUTION		12
+
+// Other pins
+#define PIN_ATN              (31ul)
+static const uint8_t ATN = PIN_ATN;
+
+/* WiFi interfaces */
+#define SerialESP32 Serial1
+#define SerialNina SerialESP32
+#define SPIWIFI SPI
+#define SPIWIFI_SS 4
+#define SPIWIFI_ACK 53
+#define ESP32_GPIO0 52
+#define ESP32_RESETN 54
+#define SPIWIFI_RESET ESP32_RESETN
+#define NINA_GPIO0 ESP32_GPIO0
+#define NINA_ACK SPIWIFI_ACK
+#define NINA_RESETN ESP32_RESETN
+
+/*
+ * Serial interfaces
+ */
+
+// Serial1
+#define PIN_SERIAL1_RX       (0ul)
+#define PIN_SERIAL1_TX       (1ul)
+#define PAD_SERIAL1_RX       (SERCOM_RX_PAD_1)
+#define PAD_SERIAL1_TX       (UART_TX_PAD_0)
+
+/*
+ * SPI Interfaces
+ */
+#define SPI_INTERFACES_COUNT 2
+
+#define PIN_SPI_MISO         (26u)
+#define PIN_SPI_MOSI         (27u)
+#define PIN_SPI_SCK          (28u)
+#define PERIPH_SPI           sercom1
+#define PAD_SPI_TX           SPI_PAD_3_SCK_1
+#define PAD_SPI_RX           SERCOM_RX_PAD_2
+
+static const uint8_t SS	  = 9 ;	// SERCOM1 last PAD is present on d9 but HW SS isn't used. Set here only for reference.
+static const uint8_t MOSI = PIN_SPI_MOSI ;
+static const uint8_t MISO = PIN_SPI_MISO ;
+static const uint8_t SCK  = PIN_SPI_SCK ;
+
+// Internal SPI for TFT
+#define PIN_SPI1_MOSI         (41u)
+#define PIN_SPI1_SCK          (42u)
+#define PIN_SPI1_MISO         (43u)
+#define PERIPH_SPI1           sercom4
+#define PAD_SPI1_TX           SPI_PAD_3_SCK_1
+#define PAD_SPI1_RX           SERCOM_RX_PAD_0
+
+static const uint8_t SS1	  = 44 ;
+static const uint8_t MOSI1 = PIN_SPI1_MOSI ;
+static const uint8_t MISO1 = PIN_SPI1_MISO ;
+static const uint8_t SCK1 = PIN_SPI1_SCK ;
+
+/*
+ * Wire Interfaces
+ */
+#define WIRE_INTERFACES_COUNT 1
+
+#define PIN_WIRE_SDA         (24u)
+#define PIN_WIRE_SCL         (25u)
+#define PERIPH_WIRE          sercom2
+#define WIRE_IT_HANDLER      SERCOM2_Handler
+#define WIRE_IT_HANDLER_0    SERCOM2_0_Handler
+#define WIRE_IT_HANDLER_1    SERCOM2_1_Handler
+#define WIRE_IT_HANDLER_2    SERCOM2_2_Handler
+#define WIRE_IT_HANDLER_3    SERCOM2_3_Handler
+
+static const uint8_t SDA = PIN_WIRE_SDA;
+static const uint8_t SCL = PIN_WIRE_SCL;
+
+/*
+ * USB
+ */
+#define PIN_USB_HOST_ENABLE (29ul)
+#define PIN_USB_DM          (30ul)
+#define PIN_USB_DP          (31ul)
+
+/*
+ * I2S Interfaces
+ */
+#define I2S_INTERFACES_COUNT 0
+
+// On-board QSPI Flash
+#define EXTERNAL_FLASH_DEVICES   GD25Q16C
+#define EXTERNAL_FLASH_USE_QSPI
+
+//QSPI Pins
+#define PIN_QSPI_SCK    (35u)
+#define PIN_QSPI_CS     (36u)
+#define PIN_QSPI_IO0    (37u)
+#define PIN_QSPI_IO1    (38u)
+#define PIN_QSPI_IO2    (39u)
+#define PIN_QSPI_IO3    (40u)
+
+#if !defined(VARIANT_QSPI_BAUD_DEFAULT)
+  // TODO: meaningful value for this
+  #define VARIANT_QSPI_BAUD_DEFAULT 5000000
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+ *        Arduino objects - C++ only
+ *----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+
+/*	=========================
+ *	===== SERCOM DEFINITION
+ *	=========================
+*/
+extern SERCOM sercom0;
+extern SERCOM sercom1;
+extern SERCOM sercom2;
+extern SERCOM sercom3;
+extern SERCOM sercom4;
+extern SERCOM sercom5;
+
+extern Uart Serial1;
+
+#endif
+
+// These serial port names are intended to allow libraries and architecture-neutral
+// sketches to automatically default to the correct port name for a particular type
+// of use.  For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN,
+// the first hardware serial port whose RX/TX pins are not dedicated to another use.
+//
+// SERIAL_PORT_MONITOR        Port which normally prints to the Arduino Serial Monitor
+//
+// SERIAL_PORT_USBVIRTUAL     Port which is USB virtual serial
+//
+// SERIAL_PORT_LINUXBRIDGE    Port which connects to a Linux system via Bridge library
+//
+// SERIAL_PORT_HARDWARE       Hardware serial port, physical RX & TX pins.
+//
+// SERIAL_PORT_HARDWARE_OPEN  Hardware serial ports which are open for use.  Their RX & TX
+//                            pins are NOT connected to anything by default.
+#define SERIAL_PORT_USBVIRTUAL      Serial
+#define SERIAL_PORT_MONITOR         Serial
+// Serial has no physical pins broken out, so it's not listed as HARDWARE port
+#define SERIAL_PORT_HARDWARE        Serial1
+#define SERIAL_PORT_HARDWARE_OPEN   Serial1
+
+#endif /* _VARIANT_PYBADGE_AIRLIFT_M4_ */
+
diff --git a/variants/pybadge_m4/debug_scripts/variant.gdb b/variants/pybadge_m4/debug_scripts/variant.gdb
new file mode 100644
index 000000000..3c37ffde2
--- /dev/null
+++ b/variants/pybadge_m4/debug_scripts/variant.gdb
@@ -0,0 +1,31 @@
+#
+#  Arduino Zero OpenOCD script.
+#
+#  Copyright (c) 2014-2015 Arduino LLC. All right reserved.
+#
+#  This library is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 2.1 of the License, or (at your option) any later version.
+#
+#  This library is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#  See the GNU Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library; if not, write to the Free Software
+#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#
+
+# Define 'reset' command
+define reset
+
+info reg
+
+break main
+
+# End of 'reset' command
+end
+
+target remote | openocd -c "interface cmsis-dap" -c "set CHIPNAME at91samd21g18" -f target/at91samdXX.cfg -c "gdb_port pipe; log_output openocd.log"
diff --git a/variants/pybadge_m4/linker_scripts/gcc/flash_with_bootloader.ld b/variants/pybadge_m4/linker_scripts/gcc/flash_with_bootloader.ld
new file mode 100644
index 000000000..1bdea69ae
--- /dev/null
+++ b/variants/pybadge_m4/linker_scripts/gcc/flash_with_bootloader.ld
@@ -0,0 +1,216 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* Linker script to configure memory regions.
+ * Need modifying for a specific board.
+ *   FLASH.ORIGIN: starting address of flash
+ *   FLASH.LENGTH: length of flash
+ *   RAM.ORIGIN: starting address of RAM bank 0
+ *   RAM.LENGTH: length of RAM bank 0
+ */
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000+0x4000, LENGTH = 0x00080000-0x4000 /* First 16KB used by bootloader */
+  RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00030000
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ *   Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ *   __exidx_start
+ *   __exidx_end
+ *   __copy_table_start__
+ *   __copy_table_end__
+ *   __zero_table_start__
+ *   __zero_table_end__
+ *   __etext
+ *   __data_start__
+ *   __preinit_array_start
+ *   __preinit_array_end
+ *   __init_array_start
+ *   __init_array_end
+ *   __fini_array_start
+ *   __fini_array_end
+ *   __data_end__
+ *   __bss_start__
+ *   __bss_end__
+ *   __end__
+ *   end
+ *   __HeapLimit
+ *   __StackLimit
+ *   __StackTop
+ *   __stack
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+	.text :
+	{
+		__text_start__ = .;
+
+		KEEP(*(.sketch_boot))
+
+		. = ALIGN(0x4000);
+		KEEP(*(.isr_vector))
+		*(.text*)
+
+		KEEP(*(.init))
+		KEEP(*(.fini))
+
+		/* .ctors */
+		*crtbegin.o(.ctors)
+		*crtbegin?.o(.ctors)
+		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+		*(SORT(.ctors.*))
+		*(.ctors)
+
+		/* .dtors */
+ 		*crtbegin.o(.dtors)
+ 		*crtbegin?.o(.dtors)
+ 		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ 		*(SORT(.dtors.*))
+ 		*(.dtors)
+
+		*(.rodata*)
+
+		KEEP(*(.eh_frame*))
+	} > FLASH
+
+	.ARM.extab :
+	{
+		*(.ARM.extab* .gnu.linkonce.armextab.*)
+	} > FLASH
+
+	__exidx_start = .;
+	.ARM.exidx :
+	{
+		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
+	} > FLASH
+	__exidx_end = .;
+
+	/* To copy multiple ROM to RAM sections,
+	 * uncomment .copy.table section and,
+	 * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.copy.table :
+	{
+		. = ALIGN(4);
+		__copy_table_start__ = .;
+		LONG (__etext)
+		LONG (__data_start__)
+		LONG (__data_end__ - __data_start__)
+		LONG (__etext2)
+		LONG (__data2_start__)
+		LONG (__data2_end__ - __data2_start__)
+		__copy_table_end__ = .;
+	} > FLASH
+	*/
+
+	/* To clear multiple BSS sections,
+	 * uncomment .zero.table section and,
+	 * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.zero.table :
+	{
+		. = ALIGN(4);
+		__zero_table_start__ = .;
+		LONG (__bss_start__)
+		LONG (__bss_end__ - __bss_start__)
+		LONG (__bss2_start__)
+		LONG (__bss2_end__ - __bss2_start__)
+		__zero_table_end__ = .;
+	} > FLASH
+	*/
+
+	__etext = .;
+
+	.data : AT (__etext)
+	{
+		__data_start__ = .;
+		*(vtable)
+		*(.data*)
+
+		. = ALIGN(4);
+		/* preinit data */
+		PROVIDE_HIDDEN (__preinit_array_start = .);
+		KEEP(*(.preinit_array))
+		PROVIDE_HIDDEN (__preinit_array_end = .);
+
+		. = ALIGN(4);
+		/* init data */
+		PROVIDE_HIDDEN (__init_array_start = .);
+		KEEP(*(SORT(.init_array.*)))
+		KEEP(*(.init_array))
+		PROVIDE_HIDDEN (__init_array_end = .);
+
+
+		. = ALIGN(4);
+		/* finit data */
+		PROVIDE_HIDDEN (__fini_array_start = .);
+		KEEP(*(SORT(.fini_array.*)))
+		KEEP(*(.fini_array))
+		PROVIDE_HIDDEN (__fini_array_end = .);
+
+		KEEP(*(.jcr*))
+		. = ALIGN(16);
+		/* All data end */
+		__data_end__ = .;
+
+	} > RAM
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start__ = .;
+		*(.bss*)
+		*(COMMON)
+		. = ALIGN(4);
+		__bss_end__ = .;
+	} > RAM
+
+	.heap (COPY):
+	{
+		__end__ = .;
+		PROVIDE(end = .);
+		*(.heap*)
+		__HeapLimit = .;
+	} > RAM
+
+	/* .stack_dummy section doesn't contains any symbols. It is only
+	 * used for linker to calculate size of stack sections, and assign
+	 * values to stack symbols later */
+	.stack_dummy (COPY):
+	{
+		*(.stack*)
+	} > RAM
+
+	/* Set stack top to end of RAM, and stack limit move down by
+	 * size of stack_dummy section */
+	__StackTop = ORIGIN(RAM) + LENGTH(RAM);
+	__StackLimit = __StackTop - SIZEOF(.stack_dummy);
+	PROVIDE(__stack = __StackTop);
+
+	__ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ;
+
+	/* Check if data + heap + stack exceeds RAM limit */
+	ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
+}
diff --git a/variants/pybadge_m4/linker_scripts/gcc/flash_without_bootloader.ld b/variants/pybadge_m4/linker_scripts/gcc/flash_without_bootloader.ld
new file mode 100644
index 000000000..9c0c4e06d
--- /dev/null
+++ b/variants/pybadge_m4/linker_scripts/gcc/flash_without_bootloader.ld
@@ -0,0 +1,214 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* Linker script to configure memory regions.
+ * Need modifying for a specific board.
+ *   FLASH.ORIGIN: starting address of flash
+ *   FLASH.LENGTH: length of flash
+ *   RAM.ORIGIN: starting address of RAM bank 0
+ *   RAM.LENGTH: length of RAM bank 0
+ */
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00080000
+  RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00030000
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ *   Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ *   __exidx_start
+ *   __exidx_end
+ *   __copy_table_start__
+ *   __copy_table_end__
+ *   __zero_table_start__
+ *   __zero_table_end__
+ *   __etext
+ *   __data_start__
+ *   __preinit_array_start
+ *   __preinit_array_end
+ *   __init_array_start
+ *   __init_array_end
+ *   __fini_array_start
+ *   __fini_array_end
+ *   __data_end__
+ *   __bss_start__
+ *   __bss_end__
+ *   __end__
+ *   end
+ *   __HeapLimit
+ *   __StackLimit
+ *   __StackTop
+ *   __stack
+ *   __ram_end__
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+	.text :
+	{
+		__text_start__ = .;
+
+		KEEP(*(.isr_vector))
+		*(.text*)
+
+		KEEP(*(.init))
+		KEEP(*(.fini))
+
+		/* .ctors */
+		*crtbegin.o(.ctors)
+		*crtbegin?.o(.ctors)
+		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+		*(SORT(.ctors.*))
+		*(.ctors)
+
+		/* .dtors */
+ 		*crtbegin.o(.dtors)
+ 		*crtbegin?.o(.dtors)
+ 		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ 		*(SORT(.dtors.*))
+ 		*(.dtors)
+
+		*(.rodata*)
+
+		KEEP(*(.eh_frame*))
+	} > FLASH
+
+	.ARM.extab :
+	{
+		*(.ARM.extab* .gnu.linkonce.armextab.*)
+	} > FLASH
+
+	__exidx_start = .;
+	.ARM.exidx :
+	{
+		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
+	} > FLASH
+	__exidx_end = .;
+
+	/* To copy multiple ROM to RAM sections,
+	 * uncomment .copy.table section and,
+	 * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.copy.table :
+	{
+		. = ALIGN(4);
+		__copy_table_start__ = .;
+		LONG (__etext)
+		LONG (__data_start__)
+		LONG (__data_end__ - __data_start__)
+		LONG (__etext2)
+		LONG (__data2_start__)
+		LONG (__data2_end__ - __data2_start__)
+		__copy_table_end__ = .;
+	} > FLASH
+	*/
+
+	/* To clear multiple BSS sections,
+	 * uncomment .zero.table section and,
+	 * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.zero.table :
+	{
+		. = ALIGN(4);
+		__zero_table_start__ = .;
+		LONG (__bss_start__)
+		LONG (__bss_end__ - __bss_start__)
+		LONG (__bss2_start__)
+		LONG (__bss2_end__ - __bss2_start__)
+		__zero_table_end__ = .;
+	} > FLASH
+	*/
+
+	__etext = .;
+
+	.data : AT (__etext)
+	{
+		__data_start__ = .;
+		*(vtable)
+		*(.data*)
+
+		. = ALIGN(4);
+		/* preinit data */
+		PROVIDE_HIDDEN (__preinit_array_start = .);
+		KEEP(*(.preinit_array))
+		PROVIDE_HIDDEN (__preinit_array_end = .);
+
+		. = ALIGN(4);
+		/* init data */
+		PROVIDE_HIDDEN (__init_array_start = .);
+		KEEP(*(SORT(.init_array.*)))
+		KEEP(*(.init_array))
+		PROVIDE_HIDDEN (__init_array_end = .);
+
+
+		. = ALIGN(4);
+		/* finit data */
+		PROVIDE_HIDDEN (__fini_array_start = .);
+		KEEP(*(SORT(.fini_array.*)))
+		KEEP(*(.fini_array))
+		PROVIDE_HIDDEN (__fini_array_end = .);
+
+		KEEP(*(.jcr*))
+		. = ALIGN(16);
+		/* All data end */
+		__data_end__ = .;
+
+	} > RAM
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start__ = .;
+		*(.bss*)
+		*(COMMON)
+		. = ALIGN(4);
+		__bss_end__ = .;
+	} > RAM
+
+	.heap (COPY):
+	{
+		__end__ = .;
+		PROVIDE(end = .);
+		*(.heap*)
+		__HeapLimit = .;
+	} > RAM
+
+	/* .stack_dummy section doesn't contains any symbols. It is only
+	 * used for linker to calculate size of stack sections, and assign
+	 * values to stack symbols later */
+	.stack_dummy (COPY):
+	{
+		*(.stack*)
+	} > RAM
+
+	/* Set stack top to end of RAM, and stack limit move down by
+	 * size of stack_dummy section */
+	__StackTop = ORIGIN(RAM) + LENGTH(RAM) ;
+	__StackLimit = __StackTop - SIZEOF(.stack_dummy);
+	PROVIDE(__stack = __StackTop);
+
+	__ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ;
+
+	/* Check if data + heap + stack exceeds RAM limit */
+	ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
+}
diff --git a/variants/mkrwifi1010/openocd_scripts/arduino_zero.cfg b/variants/pybadge_m4/openocd_scripts/arduino_zero.cfg
similarity index 100%
rename from variants/mkrwifi1010/openocd_scripts/arduino_zero.cfg
rename to variants/pybadge_m4/openocd_scripts/arduino_zero.cfg
diff --git a/variants/pybadge_m4/pins_arduino.h b/variants/pybadge_m4/pins_arduino.h
new file mode 100644
index 000000000..db0e40c3d
--- /dev/null
+++ b/variants/pybadge_m4/pins_arduino.h
@@ -0,0 +1,21 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+// API compatibility
+#include "variant.h"
+
diff --git a/variants/pybadge_m4/variant.cpp b/variants/pybadge_m4/variant.cpp
new file mode 100644
index 000000000..ebc2c7f48
--- /dev/null
+++ b/variants/pybadge_m4/variant.cpp
@@ -0,0 +1,152 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "variant.h"
+
+/*
+ * Pins descriptions
+ */
+const PinDescription g_APinDescription[]=
+{
+  // 0..13 - Digital pins
+  // ----------------------
+  // 0/1 - SERCOM/UART (Serial1)
+  { PORTB,  17, PIO_SERCOM, PIN_ATTR_PWM_G, No_ADC_Channel, TCC0_CH5, NOT_ON_TIMER,  EXTERNAL_INT_1 },
+  { PORTB,  16, PIO_SERCOM, PIN_ATTR_PWM_G, No_ADC_Channel, TCC0_CH4, NOT_ON_TIMER, EXTERNAL_INT_0 },
+
+  // 2..12
+  // Digital Low
+  { PORTB,  3, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel15, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_3 },
+  { PORTB,  2, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel14, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 },
+  { PORTA,  14, PIO_SERCOM, PIN_ATTR_PWM_E, No_ADC_Channel, TC3_CH0, TC3_CH0, EXTERNAL_INT_14 },
+  { PORTA,  16, PIO_SERCOM_ALT, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_0  },
+  { PORTA,  18, PIO_SERCOM_ALT, PIO_SERCOM, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2  },
+  { PORTB,  14, PIO_DIGITAL, PIN_ATTR_PWM_F, No_ADC_Channel, TCC4_CH0, TC5_CH0, EXTERNAL_INT_14 },
+
+  // Digital High
+  { PORTA, 15, PIO_DIGITAL, PIN_ATTR_PWM_E, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_15  }, // D8 - NEOPIXEL
+  { PORTA,  19, PIO_SERCOM_ALT, PIN_ATTR_PWM_E, No_ADC_Channel, TC3_CH1, TC3_CH1,  EXTERNAL_INT_3 },
+  { PORTA,  20, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER,  EXTERNAL_INT_4 },
+  { PORTA,  21, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER,  EXTERNAL_INT_5 },
+  { PORTA,  22, PIO_SERCOM, PIN_ATTR_PWM_G, No_ADC_Channel, TCC0_CH2, TC4_CH0, EXTERNAL_INT_6 },
+
+  // 13 (LED)
+  { PORTA, 23, PIO_SERCOM, PIN_ATTR_PWM_G, No_ADC_Channel, TCC0_CH3, TC4_CH1, EXTERNAL_INT_7 }, 
+
+  // 14..23 - Analog pins
+  // --------------------
+  { PORTA,  2, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel0, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 },
+  { PORTA,  5, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel5, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_5 },
+  { PORTB,  8, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel2, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_8 },
+  { PORTB,  9, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel3, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_9 },
+  { PORTA,  4, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel4, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_4 },
+  { PORTA,  6, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel6, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_6 },
+
+  { PORTB,  1, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel13, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_1 },  // A6, D20 - vbatt
+  { PORTB,  4, PIO_ANALOG, PIN_ATTR_ANALOG_ALT, ADC_Channel6, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_4 },   // A7, D21 - Light
+  { PORTB,  3, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel15, NOT_ON_PWM,  NOT_ON_TIMER, EXTERNAL_INT_3 }, // A8 / D2
+  { PORTB,  2, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel14, NOT_ON_PWM,  NOT_ON_TIMER, EXTERNAL_INT_2 }, // A9 / D3
+
+
+  // 24..25 I2C pins (SDA/SCL)
+  // ----------------------
+  { PORTA,  12, PIO_SERCOM, PIN_ATTR_PWM_E, No_ADC_Channel, TC2_CH0, TC2_CH0,  EXTERNAL_INT_12 }, // SDA
+  { PORTA,  13, PIO_SERCOM, PIN_ATTR_PWM_E, No_ADC_Channel, TC2_CH1, TC2_CH1,  EXTERNAL_INT_13 }, // SCL
+
+  // 26..28 - SPI pins (MISO,MOSI,SCK)
+  // ----------------------
+  { PORTB, 22, PIO_SERCOM, (PIN_ATTR_DIGITAL), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_6 }, // MISO: SERCOM1/PAD[2]
+  { PORTB, 23, PIO_SERCOM, (PIN_ATTR_DIGITAL), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_7 }, // MOSI: SERCOM1/PAD[3]
+  { PORTA, 17, PIO_SERCOM, (PIN_ATTR_DIGITAL), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_1 }, // SCK: SERCOM1/PAD[1]
+
+  // 29..31 - USB
+  // --------------------
+  { NOT_A_PORT, PIN_NOT_A_PIN, PIO_NOT_A_PIN, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB Host enable DOES NOT EXIST ON THIS BOARD
+  { PORTA, 24, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB/DM
+  { PORTA, 25, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB/DP
+
+  // 32 (AREF)
+  { PORTA, 3, PIO_ANALOG, PIN_ATTR_ANALOG, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // DAC/VREFP
+
+ // ----------------------
+  // 33..34 - Alternate use of A0 (DAC output)
+  { PORTA,  2, PIO_ANALOG, PIN_ATTR_ANALOG, DAC_Channel0, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // DAC/VOUT0
+  { PORTA,  5, PIO_ANALOG, PIN_ATTR_ANALOG, DAC_Channel1, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // DAC/VOUT1
+
+  // ----------------------
+  // 35..40 QSPI (SCK, CS, IO0, IO1, IO2, IO3)
+  { PORTB, 10, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+  { PORTB, 11, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+  { PORTA, 8, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+  { PORTA, 9, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+  { PORTA, 10, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+  { PORTA, 11, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+
+  // 41..46 - TFT SPI port + control pins
+  // --------------------
+  { PORTB, 15, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_15 },  // SERCOM 4.3 MOSI
+  { PORTB, 13, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_13 },  // SERCOM 4.1 SCK
+  { PORTB, 12, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_12 },  // SERCOM 4.0 'miso' (NC)
+  { PORTB,  7, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_7 },  // D44 TFT CS
+  { PORTB,  5, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_5 },  // D45 TFT DC
+  { PORTA,  0, PIO_DIGITAL, PIN_ATTR_PWM_E, No_ADC_Channel, TC2_CH0, TC2_CH0, EXTERNAL_INT_0 },            // D46 TFT RST
+
+  // 47 - backlight
+  { PORTA,  1, PIO_DIGITAL, PIN_ATTR_PWM_E, No_ADC_Channel, TC2_CH1, TC2_CH1, EXTERNAL_INT_1 }, // D47 TFT BACKLITE
+
+  // 48 - button control
+  { PORTB, 31, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_15 },  // D48 button clock
+  { PORTB, 30, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_14 },  // D49 button data
+  { PORTB,  0, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_0 },  // D50 button latch
+  
+  // D51 Speaker enable
+  { PORTA, 27, PIO_DIGITAL, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+
+  // D52 Bandgap input
+  { NOT_A_PORT, PIN_NOT_A_PIN, PIO_NOT_A_PIN, PIN_ATTR_ANALOG, ADC_Channel_PTAT, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+} ;
+
+const void* g_apTCInstances[TCC_INST_NUM+TC_INST_NUM]={ TCC0, TCC1, TCC2, TCC3, TCC4, TC0, TC1, TC2, TC3, TC4, TC5 } ;
+const uint32_t GCLK_CLKCTRL_IDs[TCC_INST_NUM+TC_INST_NUM] = { TCC0_GCLK_ID, TCC1_GCLK_ID, TCC2_GCLK_ID, TCC3_GCLK_ID, TCC4_GCLK_ID, TC0_GCLK_ID, TC1_GCLK_ID, TC2_GCLK_ID, TC3_GCLK_ID, TC4_GCLK_ID, TC5_GCLK_ID } ;
+
+// Multi-serial objects instantiation
+SERCOM sercom0( SERCOM0 ) ;
+SERCOM sercom1( SERCOM1 ) ;
+SERCOM sercom2( SERCOM2 ) ;
+SERCOM sercom3( SERCOM3 ) ;
+SERCOM sercom4( SERCOM4 ) ;
+SERCOM sercom5( SERCOM5 ) ;
+
+Uart Serial1( &sercom5, PIN_SERIAL1_RX, PIN_SERIAL1_TX, PAD_SERIAL1_RX, PAD_SERIAL1_TX ) ;
+
+void SERCOM5_0_Handler()
+{
+  Serial1.IrqHandler();
+}
+void SERCOM5_1_Handler()
+{
+  Serial1.IrqHandler();
+}
+void SERCOM5_2_Handler()
+{
+  Serial1.IrqHandler();
+}
+void SERCOM5_3_Handler()
+{
+  Serial1.IrqHandler();
+}
diff --git a/variants/pybadge_m4/variant.h b/variants/pybadge_m4/variant.h
new file mode 100644
index 000000000..fbfb6824a
--- /dev/null
+++ b/variants/pybadge_m4/variant.h
@@ -0,0 +1,272 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _VARIANT_PYBADGE_M4_
+#define _VARIANT_PYBADGE_M4_
+
+// The definitions here needs a SAMD core >=1.6.10
+#define ARDUINO_SAMD_VARIANT_COMPLIANCE 10610
+
+/*----------------------------------------------------------------------------
+ *        Definitions
+ *----------------------------------------------------------------------------*/
+
+/** Frequency of the board main oscillator */
+#define VARIANT_MAINOSC		(32768ul)
+
+/** Master clock frequency */
+#define VARIANT_MCK	   (F_CPU)
+
+#define VARIANT_GCLK0_FREQ (F_CPU)
+#define VARIANT_GCLK1_FREQ (48000000UL)
+#define VARIANT_GCLK2_FREQ (100000000UL)
+
+/*----------------------------------------------------------------------------
+ *        Headers
+ *----------------------------------------------------------------------------*/
+
+#include "WVariant.h"
+
+#ifdef __cplusplus
+#include "SERCOM.h"
+#include "Uart.h"
+#endif // __cplusplus
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif // __cplusplus
+
+/*----------------------------------------------------------------------------
+ *        Pins
+ *----------------------------------------------------------------------------*/
+
+// Number of pins defined in PinDescription array
+#define PINS_COUNT           (51u)
+#define NUM_DIGITAL_PINS     (25u)
+#define NUM_ANALOG_INPUTS    (10u)
+#define NUM_ANALOG_OUTPUTS   (2u)
+#define analogInputToDigitalPin(p)  ((p < 6u) ? (p) + 14u : -1)
+
+#define digitalPinToPort(P)        ( &(PORT->Group[g_APinDescription[P].ulPort]) )
+#define digitalPinToBitMask(P)     ( 1 << g_APinDescription[P].ulPin )
+//#define analogInPinToBit(P)        ( )
+#define portOutputRegister(port)   ( &(port->OUT.reg) )
+#define portInputRegister(port)    ( &(port->IN.reg) )
+#define portModeRegister(port)     ( &(port->DIR.reg) )
+#define digitalPinHasPWM(P)        ( g_APinDescription[P].ulPWMChannel != NOT_ON_PWM || g_APinDescription[P].ulTCChannel != NOT_ON_TIMER )
+
+/*
+ * digitalPinToTimer(..) is AVR-specific and is not defined for SAMD
+ * architecture. If you need to check if a pin supports PWM you must
+ * use digitalPinHasPWM(..).
+ *
+ * https://github.com/arduino/Arduino/issues/1833
+ */
+// #define digitalPinToTimer(P)
+
+// LEDs
+#define PIN_LED_13           (13u)
+#define PIN_LED              PIN_LED_13
+#define LED_BUILTIN          PIN_LED_13
+
+/*
+ * Analog pins
+ */
+#define PIN_A0               (14ul)
+#define PIN_A1               (PIN_A0 + 1)
+#define PIN_A2               (PIN_A0 + 2)
+#define PIN_A3               (PIN_A0 + 3)
+#define PIN_A4               (PIN_A0 + 4)
+#define PIN_A5               (PIN_A0 + 5)
+#define PIN_A6               (PIN_A0 + 6)
+#define PIN_A7               (PIN_A0 + 7)
+#define PIN_A8               (PIN_A0 + 8)
+#define PIN_A9               (PIN_A0 + 9)
+#define PIN_BANDGAP_ADC      52
+
+#define PIN_DAC0             PIN_A0
+#define PIN_DAC1             PIN_A1
+
+static const uint8_t A0  = PIN_A0;
+static const uint8_t A1  = PIN_A1;
+static const uint8_t A2  = PIN_A2;
+static const uint8_t A3  = PIN_A3;
+static const uint8_t A4  = PIN_A4;
+static const uint8_t A5  = PIN_A5;
+static const uint8_t A6  = PIN_A6;
+static const uint8_t A7  = PIN_A7;
+static const uint8_t A8  = PIN_A8;
+static const uint8_t A9  = PIN_A9;
+
+static const uint8_t DAC0 = PIN_DAC0;
+static const uint8_t DAC1 = PIN_DAC1;
+
+#define ADC_RESOLUTION		12
+
+// Other pins
+#define PIN_ATN              (31ul)
+static const uint8_t ATN = PIN_ATN;
+
+/*
+ * Serial interfaces
+ */
+
+// Serial1
+#define PIN_SERIAL1_RX       (0ul)
+#define PIN_SERIAL1_TX       (1ul)
+#define PAD_SERIAL1_RX       (SERCOM_RX_PAD_1)
+#define PAD_SERIAL1_TX       (UART_TX_PAD_0)
+
+/*
+ * SPI Interfaces
+ */
+#define SPI_INTERFACES_COUNT 3
+
+#define PIN_SPI_MISO         (26u)
+#define PIN_SPI_MOSI         (27u)
+#define PIN_SPI_SCK          (28u)
+#define PERIPH_SPI           sercom1
+#define PAD_SPI_TX           SPI_PAD_3_SCK_1
+#define PAD_SPI_RX           SERCOM_RX_PAD_2
+
+static const uint8_t SS	  = 9 ;	// SERCOM1 last PAD is present on d9 but HW SS isn't used. Set here only for reference.
+static const uint8_t MOSI = PIN_SPI_MOSI ;
+static const uint8_t MISO = PIN_SPI_MISO ;
+static const uint8_t SCK  = PIN_SPI_SCK ;
+
+// Internal SPI for TFT
+#define PIN_SPI1_MOSI         (41u)
+#define PIN_SPI1_SCK          (42u)
+#define PIN_SPI1_MISO         (43u)
+#define PERIPH_SPI1           sercom4
+#define PAD_SPI1_TX           SPI_PAD_3_SCK_1
+#define PAD_SPI1_RX           SERCOM_RX_PAD_0
+
+static const uint8_t SS1	  = 44 ;
+static const uint8_t MOSI1 = PIN_SPI1_MOSI ;
+static const uint8_t MISO1 = PIN_SPI1_MISO ;
+static const uint8_t SCK1 = PIN_SPI1_SCK ;
+
+// SPI for PDM mic
+#define PIN_SPI2_MOSI         (9u)
+#define PIN_SPI2_SCK          (5u)
+#define PIN_SPI2_MISO         (6u)
+#define PERIPH_SPI2           sercom3
+#define PAD_SPI2_TX           SPI_PAD_3_SCK_1
+#define PAD_SPI2_RX           SERCOM_RX_PAD_2
+
+static const uint8_t SS2	  = 10 ;
+static const uint8_t MOSI2 = PIN_SPI2_MOSI ;
+static const uint8_t MISO2 = PIN_SPI2_MISO ;
+static const uint8_t SCK2 = PIN_SPI2_SCK ;
+
+/*
+ * Wire Interfaces
+ */
+#define WIRE_INTERFACES_COUNT 1
+
+#define PIN_WIRE_SDA         (24u)
+#define PIN_WIRE_SCL         (25u)
+#define PERIPH_WIRE          sercom2
+#define WIRE_IT_HANDLER      SERCOM2_Handler
+#define WIRE_IT_HANDLER_0    SERCOM2_0_Handler
+#define WIRE_IT_HANDLER_1    SERCOM2_1_Handler
+#define WIRE_IT_HANDLER_2    SERCOM2_2_Handler
+#define WIRE_IT_HANDLER_3    SERCOM2_3_Handler
+
+static const uint8_t SDA = PIN_WIRE_SDA;
+static const uint8_t SCL = PIN_WIRE_SCL;
+
+/*
+ * USB
+ */
+#define PIN_USB_HOST_ENABLE (29ul)
+#define PIN_USB_DM          (30ul)
+#define PIN_USB_DP          (31ul)
+
+/*
+ * I2S Interfaces
+ */
+#define I2S_INTERFACES_COUNT 0
+
+// On-board QSPI Flash
+#define EXTERNAL_FLASH_DEVICES   GD25Q16C
+#define EXTERNAL_FLASH_USE_QSPI
+
+//QSPI Pins
+#define PIN_QSPI_SCK    (35u)
+#define PIN_QSPI_CS     (36u)
+#define PIN_QSPI_IO0    (37u)
+#define PIN_QSPI_IO1    (38u)
+#define PIN_QSPI_IO2    (39u)
+#define PIN_QSPI_IO3    (40u)
+
+#if !defined(VARIANT_QSPI_BAUD_DEFAULT)
+  // TODO: meaningful value for this
+  #define VARIANT_QSPI_BAUD_DEFAULT 5000000
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+ *        Arduino objects - C++ only
+ *----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+
+/*	=========================
+ *	===== SERCOM DEFINITION
+ *	=========================
+*/
+extern SERCOM sercom0;
+extern SERCOM sercom1;
+extern SERCOM sercom2;
+extern SERCOM sercom3;
+extern SERCOM sercom4;
+extern SERCOM sercom5;
+
+extern Uart Serial1;
+
+#endif
+
+// These serial port names are intended to allow libraries and architecture-neutral
+// sketches to automatically default to the correct port name for a particular type
+// of use.  For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN,
+// the first hardware serial port whose RX/TX pins are not dedicated to another use.
+//
+// SERIAL_PORT_MONITOR        Port which normally prints to the Arduino Serial Monitor
+//
+// SERIAL_PORT_USBVIRTUAL     Port which is USB virtual serial
+//
+// SERIAL_PORT_LINUXBRIDGE    Port which connects to a Linux system via Bridge library
+//
+// SERIAL_PORT_HARDWARE       Hardware serial port, physical RX & TX pins.
+//
+// SERIAL_PORT_HARDWARE_OPEN  Hardware serial ports which are open for use.  Their RX & TX
+//                            pins are NOT connected to anything by default.
+#define SERIAL_PORT_USBVIRTUAL      Serial
+#define SERIAL_PORT_MONITOR         Serial
+// Serial has no physical pins broken out, so it's not listed as HARDWARE port
+#define SERIAL_PORT_HARDWARE        Serial1
+#define SERIAL_PORT_HARDWARE_OPEN   Serial1
+
+#endif /* _VARIANT_PYBADGE_M4_ */
+
diff --git a/variants/pygamer_advance_m4/debug_scripts/variant.gdb b/variants/pygamer_advance_m4/debug_scripts/variant.gdb
new file mode 100644
index 000000000..3c37ffde2
--- /dev/null
+++ b/variants/pygamer_advance_m4/debug_scripts/variant.gdb
@@ -0,0 +1,31 @@
+#
+#  Arduino Zero OpenOCD script.
+#
+#  Copyright (c) 2014-2015 Arduino LLC. All right reserved.
+#
+#  This library is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 2.1 of the License, or (at your option) any later version.
+#
+#  This library is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#  See the GNU Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library; if not, write to the Free Software
+#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#
+
+# Define 'reset' command
+define reset
+
+info reg
+
+break main
+
+# End of 'reset' command
+end
+
+target remote | openocd -c "interface cmsis-dap" -c "set CHIPNAME at91samd21g18" -f target/at91samdXX.cfg -c "gdb_port pipe; log_output openocd.log"
diff --git a/variants/pygamer_advance_m4/linker_scripts/gcc/flash_with_bootloader.ld b/variants/pygamer_advance_m4/linker_scripts/gcc/flash_with_bootloader.ld
new file mode 100644
index 000000000..1bdea69ae
--- /dev/null
+++ b/variants/pygamer_advance_m4/linker_scripts/gcc/flash_with_bootloader.ld
@@ -0,0 +1,216 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* Linker script to configure memory regions.
+ * Need modifying for a specific board.
+ *   FLASH.ORIGIN: starting address of flash
+ *   FLASH.LENGTH: length of flash
+ *   RAM.ORIGIN: starting address of RAM bank 0
+ *   RAM.LENGTH: length of RAM bank 0
+ */
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000+0x4000, LENGTH = 0x00080000-0x4000 /* First 16KB used by bootloader */
+  RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00030000
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ *   Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ *   __exidx_start
+ *   __exidx_end
+ *   __copy_table_start__
+ *   __copy_table_end__
+ *   __zero_table_start__
+ *   __zero_table_end__
+ *   __etext
+ *   __data_start__
+ *   __preinit_array_start
+ *   __preinit_array_end
+ *   __init_array_start
+ *   __init_array_end
+ *   __fini_array_start
+ *   __fini_array_end
+ *   __data_end__
+ *   __bss_start__
+ *   __bss_end__
+ *   __end__
+ *   end
+ *   __HeapLimit
+ *   __StackLimit
+ *   __StackTop
+ *   __stack
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+	.text :
+	{
+		__text_start__ = .;
+
+		KEEP(*(.sketch_boot))
+
+		. = ALIGN(0x4000);
+		KEEP(*(.isr_vector))
+		*(.text*)
+
+		KEEP(*(.init))
+		KEEP(*(.fini))
+
+		/* .ctors */
+		*crtbegin.o(.ctors)
+		*crtbegin?.o(.ctors)
+		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+		*(SORT(.ctors.*))
+		*(.ctors)
+
+		/* .dtors */
+ 		*crtbegin.o(.dtors)
+ 		*crtbegin?.o(.dtors)
+ 		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ 		*(SORT(.dtors.*))
+ 		*(.dtors)
+
+		*(.rodata*)
+
+		KEEP(*(.eh_frame*))
+	} > FLASH
+
+	.ARM.extab :
+	{
+		*(.ARM.extab* .gnu.linkonce.armextab.*)
+	} > FLASH
+
+	__exidx_start = .;
+	.ARM.exidx :
+	{
+		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
+	} > FLASH
+	__exidx_end = .;
+
+	/* To copy multiple ROM to RAM sections,
+	 * uncomment .copy.table section and,
+	 * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.copy.table :
+	{
+		. = ALIGN(4);
+		__copy_table_start__ = .;
+		LONG (__etext)
+		LONG (__data_start__)
+		LONG (__data_end__ - __data_start__)
+		LONG (__etext2)
+		LONG (__data2_start__)
+		LONG (__data2_end__ - __data2_start__)
+		__copy_table_end__ = .;
+	} > FLASH
+	*/
+
+	/* To clear multiple BSS sections,
+	 * uncomment .zero.table section and,
+	 * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.zero.table :
+	{
+		. = ALIGN(4);
+		__zero_table_start__ = .;
+		LONG (__bss_start__)
+		LONG (__bss_end__ - __bss_start__)
+		LONG (__bss2_start__)
+		LONG (__bss2_end__ - __bss2_start__)
+		__zero_table_end__ = .;
+	} > FLASH
+	*/
+
+	__etext = .;
+
+	.data : AT (__etext)
+	{
+		__data_start__ = .;
+		*(vtable)
+		*(.data*)
+
+		. = ALIGN(4);
+		/* preinit data */
+		PROVIDE_HIDDEN (__preinit_array_start = .);
+		KEEP(*(.preinit_array))
+		PROVIDE_HIDDEN (__preinit_array_end = .);
+
+		. = ALIGN(4);
+		/* init data */
+		PROVIDE_HIDDEN (__init_array_start = .);
+		KEEP(*(SORT(.init_array.*)))
+		KEEP(*(.init_array))
+		PROVIDE_HIDDEN (__init_array_end = .);
+
+
+		. = ALIGN(4);
+		/* finit data */
+		PROVIDE_HIDDEN (__fini_array_start = .);
+		KEEP(*(SORT(.fini_array.*)))
+		KEEP(*(.fini_array))
+		PROVIDE_HIDDEN (__fini_array_end = .);
+
+		KEEP(*(.jcr*))
+		. = ALIGN(16);
+		/* All data end */
+		__data_end__ = .;
+
+	} > RAM
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start__ = .;
+		*(.bss*)
+		*(COMMON)
+		. = ALIGN(4);
+		__bss_end__ = .;
+	} > RAM
+
+	.heap (COPY):
+	{
+		__end__ = .;
+		PROVIDE(end = .);
+		*(.heap*)
+		__HeapLimit = .;
+	} > RAM
+
+	/* .stack_dummy section doesn't contains any symbols. It is only
+	 * used for linker to calculate size of stack sections, and assign
+	 * values to stack symbols later */
+	.stack_dummy (COPY):
+	{
+		*(.stack*)
+	} > RAM
+
+	/* Set stack top to end of RAM, and stack limit move down by
+	 * size of stack_dummy section */
+	__StackTop = ORIGIN(RAM) + LENGTH(RAM);
+	__StackLimit = __StackTop - SIZEOF(.stack_dummy);
+	PROVIDE(__stack = __StackTop);
+
+	__ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ;
+
+	/* Check if data + heap + stack exceeds RAM limit */
+	ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
+}
diff --git a/variants/pygamer_advance_m4/linker_scripts/gcc/flash_without_bootloader.ld b/variants/pygamer_advance_m4/linker_scripts/gcc/flash_without_bootloader.ld
new file mode 100644
index 000000000..9c0c4e06d
--- /dev/null
+++ b/variants/pygamer_advance_m4/linker_scripts/gcc/flash_without_bootloader.ld
@@ -0,0 +1,214 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* Linker script to configure memory regions.
+ * Need modifying for a specific board.
+ *   FLASH.ORIGIN: starting address of flash
+ *   FLASH.LENGTH: length of flash
+ *   RAM.ORIGIN: starting address of RAM bank 0
+ *   RAM.LENGTH: length of RAM bank 0
+ */
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00080000
+  RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00030000
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ *   Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ *   __exidx_start
+ *   __exidx_end
+ *   __copy_table_start__
+ *   __copy_table_end__
+ *   __zero_table_start__
+ *   __zero_table_end__
+ *   __etext
+ *   __data_start__
+ *   __preinit_array_start
+ *   __preinit_array_end
+ *   __init_array_start
+ *   __init_array_end
+ *   __fini_array_start
+ *   __fini_array_end
+ *   __data_end__
+ *   __bss_start__
+ *   __bss_end__
+ *   __end__
+ *   end
+ *   __HeapLimit
+ *   __StackLimit
+ *   __StackTop
+ *   __stack
+ *   __ram_end__
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+	.text :
+	{
+		__text_start__ = .;
+
+		KEEP(*(.isr_vector))
+		*(.text*)
+
+		KEEP(*(.init))
+		KEEP(*(.fini))
+
+		/* .ctors */
+		*crtbegin.o(.ctors)
+		*crtbegin?.o(.ctors)
+		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+		*(SORT(.ctors.*))
+		*(.ctors)
+
+		/* .dtors */
+ 		*crtbegin.o(.dtors)
+ 		*crtbegin?.o(.dtors)
+ 		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ 		*(SORT(.dtors.*))
+ 		*(.dtors)
+
+		*(.rodata*)
+
+		KEEP(*(.eh_frame*))
+	} > FLASH
+
+	.ARM.extab :
+	{
+		*(.ARM.extab* .gnu.linkonce.armextab.*)
+	} > FLASH
+
+	__exidx_start = .;
+	.ARM.exidx :
+	{
+		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
+	} > FLASH
+	__exidx_end = .;
+
+	/* To copy multiple ROM to RAM sections,
+	 * uncomment .copy.table section and,
+	 * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.copy.table :
+	{
+		. = ALIGN(4);
+		__copy_table_start__ = .;
+		LONG (__etext)
+		LONG (__data_start__)
+		LONG (__data_end__ - __data_start__)
+		LONG (__etext2)
+		LONG (__data2_start__)
+		LONG (__data2_end__ - __data2_start__)
+		__copy_table_end__ = .;
+	} > FLASH
+	*/
+
+	/* To clear multiple BSS sections,
+	 * uncomment .zero.table section and,
+	 * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.zero.table :
+	{
+		. = ALIGN(4);
+		__zero_table_start__ = .;
+		LONG (__bss_start__)
+		LONG (__bss_end__ - __bss_start__)
+		LONG (__bss2_start__)
+		LONG (__bss2_end__ - __bss2_start__)
+		__zero_table_end__ = .;
+	} > FLASH
+	*/
+
+	__etext = .;
+
+	.data : AT (__etext)
+	{
+		__data_start__ = .;
+		*(vtable)
+		*(.data*)
+
+		. = ALIGN(4);
+		/* preinit data */
+		PROVIDE_HIDDEN (__preinit_array_start = .);
+		KEEP(*(.preinit_array))
+		PROVIDE_HIDDEN (__preinit_array_end = .);
+
+		. = ALIGN(4);
+		/* init data */
+		PROVIDE_HIDDEN (__init_array_start = .);
+		KEEP(*(SORT(.init_array.*)))
+		KEEP(*(.init_array))
+		PROVIDE_HIDDEN (__init_array_end = .);
+
+
+		. = ALIGN(4);
+		/* finit data */
+		PROVIDE_HIDDEN (__fini_array_start = .);
+		KEEP(*(SORT(.fini_array.*)))
+		KEEP(*(.fini_array))
+		PROVIDE_HIDDEN (__fini_array_end = .);
+
+		KEEP(*(.jcr*))
+		. = ALIGN(16);
+		/* All data end */
+		__data_end__ = .;
+
+	} > RAM
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start__ = .;
+		*(.bss*)
+		*(COMMON)
+		. = ALIGN(4);
+		__bss_end__ = .;
+	} > RAM
+
+	.heap (COPY):
+	{
+		__end__ = .;
+		PROVIDE(end = .);
+		*(.heap*)
+		__HeapLimit = .;
+	} > RAM
+
+	/* .stack_dummy section doesn't contains any symbols. It is only
+	 * used for linker to calculate size of stack sections, and assign
+	 * values to stack symbols later */
+	.stack_dummy (COPY):
+	{
+		*(.stack*)
+	} > RAM
+
+	/* Set stack top to end of RAM, and stack limit move down by
+	 * size of stack_dummy section */
+	__StackTop = ORIGIN(RAM) + LENGTH(RAM) ;
+	__StackLimit = __StackTop - SIZEOF(.stack_dummy);
+	PROVIDE(__stack = __StackTop);
+
+	__ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ;
+
+	/* Check if data + heap + stack exceeds RAM limit */
+	ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
+}
diff --git a/variants/pygamer_advance_m4/openocd_scripts/arduino_zero.cfg b/variants/pygamer_advance_m4/openocd_scripts/arduino_zero.cfg
new file mode 100644
index 000000000..36c65c32d
--- /dev/null
+++ b/variants/pygamer_advance_m4/openocd_scripts/arduino_zero.cfg
@@ -0,0 +1,30 @@
+#
+#  Arduino Zero OpenOCD script.
+#
+#  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+#
+#  This library is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 2.1 of the License, or (at your option) any later version.
+#
+#  This library is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#  See the GNU Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library; if not, write to the Free Software
+#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#
+
+source [find interface/cmsis-dap.cfg]
+
+# chip name
+set CHIPNAME at91samd21g18
+set ENDIAN little
+
+# choose a port here
+set telnet_port 0
+
+source [find target/at91samdXX.cfg]
diff --git a/variants/pygamer_advance_m4/pins_arduino.h b/variants/pygamer_advance_m4/pins_arduino.h
new file mode 100644
index 000000000..db0e40c3d
--- /dev/null
+++ b/variants/pygamer_advance_m4/pins_arduino.h
@@ -0,0 +1,21 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+// API compatibility
+#include "variant.h"
+
diff --git a/variants/pygamer_advance_m4/variant.cpp b/variants/pygamer_advance_m4/variant.cpp
new file mode 100644
index 000000000..34f7e9831
--- /dev/null
+++ b/variants/pygamer_advance_m4/variant.cpp
@@ -0,0 +1,151 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "variant.h"
+
+/*
+ * Pins descriptions
+ */
+const PinDescription g_APinDescription[]=
+{
+  // 0..13 - Digital pins
+  // ----------------------
+  // 0/1 - SERCOM/UART (Serial1)
+  { PORTB,  17, PIO_SERCOM, PIN_ATTR_PWM_G, No_ADC_Channel, TCC0_CH5, NOT_ON_TIMER,  EXTERNAL_INT_1 },
+  { PORTB,  16, PIO_SERCOM, PIN_ATTR_PWM_G, No_ADC_Channel, TCC0_CH4, NOT_ON_TIMER, EXTERNAL_INT_0 },
+
+  // 2..12
+  // Digital Low
+  { PORTB,  3, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel15, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_3 },
+  { PORTB,  2, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel14, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 },
+  { PORTA,  14, PIO_SERCOM, PIN_ATTR_PWM_E, No_ADC_Channel, TC3_CH0, TC3_CH0, EXTERNAL_INT_14 },
+  { PORTA,  16, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_0  },
+  { PORTA,  18, PIO_SERCOM, PIO_SERCOM, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2  },
+  { PORTB,  14, PIO_DIGITAL, PIN_ATTR_PWM_F, No_ADC_Channel, TCC4_CH0, TC5_CH0, EXTERNAL_INT_14 },
+
+  // Digital High
+  { PORTA, 15, PIO_DIGITAL, PIN_ATTR_PWM_E, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_15  }, // D8 - NEOPIXEL
+  { PORTA,  19, PIO_DIGITAL, PIN_ATTR_PWM_E, No_ADC_Channel, TC3_CH1, TC3_CH1,  EXTERNAL_INT_3 },
+  { PORTA,  20, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER,  EXTERNAL_INT_4 },
+  { PORTA,  21, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER,  EXTERNAL_INT_5 },
+  { PORTA,  22, PIO_SERCOM, PIN_ATTR_PWM_G, No_ADC_Channel, TCC0_CH2, TC4_CH0, EXTERNAL_INT_6 },
+
+  // 13 (LED)
+  { PORTA, 23, PIO_SERCOM, PIN_ATTR_PWM_G, No_ADC_Channel, TCC0_CH3, TC4_CH1, EXTERNAL_INT_7 }, 
+
+  // 14..25 - Analog pins
+  // --------------------
+  { PORTA,  2, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel0, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 },
+  { PORTA,  5, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel5, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_5 },
+  { PORTB,  8, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel2, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_8 },
+  { PORTB,  9, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel3, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_9 },
+  { PORTA,  4, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel4, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_4 },
+  { PORTA,  6, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel6, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_6 },
+
+  { PORTB,  1, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel13, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_1 },  // A6, D20 - vbatt
+  { PORTB,  4, PIO_ANALOG, PIN_ATTR_ANALOG_ALT, ADC_Channel6, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_4 },   // A7, D21 - Light
+  { PORTB,  3, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel15, NOT_ON_PWM,  NOT_ON_TIMER, EXTERNAL_INT_3 }, // A8 / D2
+  { PORTB,  2, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel14, NOT_ON_PWM,  NOT_ON_TIMER, EXTERNAL_INT_2 }, // A9 / D3
+  { PORTB,  6, PIO_ANALOG, PIN_ATTR_ANALOG_ALT, ADC_Channel8, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_6 },   // A10 / JOYY
+  { PORTB,  7, PIO_ANALOG, PIN_ATTR_ANALOG_ALT, ADC_Channel9, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_7 },   // A11 / JOYX
+
+  // 26..27 I2C pins (SDA/SCL)
+  // ----------------------
+  { PORTA,  12, PIO_SERCOM, PIN_ATTR_PWM_E, No_ADC_Channel, TC2_CH0, TC2_CH0,  EXTERNAL_INT_12 }, // SDA
+  { PORTA,  13, PIO_SERCOM, PIN_ATTR_PWM_E, No_ADC_Channel, TC2_CH1, TC2_CH1,  EXTERNAL_INT_13 }, // SCL
+
+  // 28..30 - SPI pins (MISO,MOSI,SCK)
+  // ----------------------
+  { PORTB, 22, PIO_SERCOM, (PIN_ATTR_DIGITAL), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_6 }, // MISO: SERCOM1/PAD[2]
+  { PORTB, 23, PIO_SERCOM, (PIN_ATTR_DIGITAL), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_7 }, // MOSI: SERCOM1/PAD[3]
+  { PORTA, 17, PIO_SERCOM, (PIN_ATTR_DIGITAL), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_1 }, // SCK: SERCOM1/PAD[1]
+
+  // 31..33 - USB
+  // --------------------
+  { NOT_A_PORT, PIN_NOT_A_PIN, PIO_NOT_A_PIN, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB Host enable DOES NOT EXIST ON THIS BOARD
+  { PORTA, 24, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB/DM
+  { PORTA, 25, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB/DP
+
+  // 34 (AREF)
+  { PORTA, 3, PIO_ANALOG, PIN_ATTR_ANALOG, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // DAC/VREFP
+
+  // ----------------------
+  // 35..40 QSPI (SCK, CS, IO0, IO1, IO2, IO3)
+  { PORTB, 10, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+  { PORTB, 11, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+  { PORTA, 8, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+  { PORTA, 9, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+  { PORTA, 10, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+  { PORTA, 11, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+
+  // 41..46 - TFT SPI port + control pins
+  // --------------------
+  { PORTB, 12, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_12 }, // SERCOM 4.0 MOSI   
+  { PORTB, 13, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_13 },  // SERCOM 4.1 SCK
+  { PORTB, 15, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_15 },  // SERCOM 4.3 'miso' (NC)
+  { PORTB, 15, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_15 },  // D44 TFT CS
+  { PORTA,  0, PIO_DIGITAL, PIN_ATTR_PWM_E, No_ADC_Channel, TC2_CH0, TC2_CH0, EXTERNAL_INT_0 },            // D45 TFT DC
+  { PORTB,  5, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_5 },  // D46 TFT RST
+
+  // 47 - backlight
+  { PORTA,  1, PIO_DIGITAL, PIN_ATTR_PWM_E, No_ADC_Channel, TC2_CH1, TC2_CH1, EXTERNAL_INT_1 }, // D47 TFT BACKLITE
+
+  // 48 - button control
+  { PORTB, 31, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_15 },  // D48 button clock
+  { PORTB, 30, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_14 },  // D49 button data
+  { PORTB,  0, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_0 },  // D50 button latch
+  
+  // D51 Speaker enable
+  { PORTA, 27, PIO_DIGITAL, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+
+  // ----------------------
+  // D52..D53 - Alternate use of A0 (DAC outputs)
+  { PORTA,  2, PIO_ANALOG, PIN_ATTR_ANALOG, DAC_Channel0, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // DAC/VOUT0
+  { PORTA,  5, PIO_ANALOG, PIN_ATTR_ANALOG, DAC_Channel1, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // DAC/VOUT1
+
+} ;
+
+const void* g_apTCInstances[TCC_INST_NUM+TC_INST_NUM]={ TCC0, TCC1, TCC2, TCC3, TCC4, TC0, TC1, TC2, TC3, TC4, TC5 } ;
+const uint32_t GCLK_CLKCTRL_IDs[TCC_INST_NUM+TC_INST_NUM] = { TCC0_GCLK_ID, TCC1_GCLK_ID, TCC2_GCLK_ID, TCC3_GCLK_ID, TCC4_GCLK_ID, TC0_GCLK_ID, TC1_GCLK_ID, TC2_GCLK_ID, TC3_GCLK_ID, TC4_GCLK_ID, TC5_GCLK_ID } ;
+
+// Multi-serial objects instantiation
+SERCOM sercom0( SERCOM0 ) ;
+SERCOM sercom1( SERCOM1 ) ;
+SERCOM sercom2( SERCOM2 ) ;
+SERCOM sercom3( SERCOM3 ) ;
+SERCOM sercom4( SERCOM4 ) ;
+SERCOM sercom5( SERCOM5 ) ;
+
+Uart Serial1( &sercom5, PIN_SERIAL1_RX, PIN_SERIAL1_TX, PAD_SERIAL1_RX, PAD_SERIAL1_TX ) ;
+
+void SERCOM5_0_Handler()
+{
+  Serial1.IrqHandler();
+}
+void SERCOM5_1_Handler()
+{
+  Serial1.IrqHandler();
+}
+void SERCOM5_2_Handler()
+{
+  Serial1.IrqHandler();
+}
+void SERCOM5_3_Handler()
+{
+  Serial1.IrqHandler();
+}
diff --git a/variants/pygamer_advance_m4/variant.h b/variants/pygamer_advance_m4/variant.h
new file mode 100644
index 000000000..cd5e271dd
--- /dev/null
+++ b/variants/pygamer_advance_m4/variant.h
@@ -0,0 +1,263 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _VARIANT_PYGAMER_ADVANCE_M4_
+#define _VARIANT_PYGAMER_ADVANCE_M4_
+
+// The definitions here needs a SAMD core >=1.6.10
+#define ARDUINO_SAMD_VARIANT_COMPLIANCE 10610
+
+/*----------------------------------------------------------------------------
+ *        Definitions
+ *----------------------------------------------------------------------------*/
+
+/** Frequency of the board main oscillator */
+#define VARIANT_MAINOSC		(32768ul)
+
+/** Master clock frequency */
+#define VARIANT_MCK	   (F_CPU)
+
+#define VARIANT_GCLK0_FREQ (F_CPU)
+#define VARIANT_GCLK1_FREQ (48000000UL)
+#define VARIANT_GCLK2_FREQ (100000000UL)
+
+/*----------------------------------------------------------------------------
+ *        Headers
+ *----------------------------------------------------------------------------*/
+
+#include "WVariant.h"
+
+#ifdef __cplusplus
+#include "SERCOM.h"
+#include "Uart.h"
+#endif // __cplusplus
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif // __cplusplus
+
+/*----------------------------------------------------------------------------
+ *        Pins
+ *----------------------------------------------------------------------------*/
+
+// Number of pins defined in PinDescription array
+#define PINS_COUNT           (54u)
+#define NUM_DIGITAL_PINS     (25u)
+#define NUM_ANALOG_INPUTS    (12u)
+#define NUM_ANALOG_OUTPUTS   (2u)
+#define analogInputToDigitalPin(p)  ((p < 6u) ? (p) + 14u : -1)
+
+#define digitalPinToPort(P)        ( &(PORT->Group[g_APinDescription[P].ulPort]) )
+#define digitalPinToBitMask(P)     ( 1 << g_APinDescription[P].ulPin )
+//#define analogInPinToBit(P)        ( )
+#define portOutputRegister(port)   ( &(port->OUT.reg) )
+#define portInputRegister(port)    ( &(port->IN.reg) )
+#define portModeRegister(port)     ( &(port->DIR.reg) )
+#define digitalPinHasPWM(P)        ( g_APinDescription[P].ulPWMChannel != NOT_ON_PWM || g_APinDescription[P].ulTCChannel != NOT_ON_TIMER )
+
+/*
+ * digitalPinToTimer(..) is AVR-specific and is not defined for SAMD
+ * architecture. If you need to check if a pin supports PWM you must
+ * use digitalPinHasPWM(..).
+ *
+ * https://github.com/arduino/Arduino/issues/1833
+ */
+// #define digitalPinToTimer(P)
+
+// LEDs
+#define PIN_LED_13           (13u)
+#define PIN_LED              PIN_LED_13
+#define LED_BUILTIN          PIN_LED_13
+
+/*
+ * Analog pins
+ */
+#define PIN_A0               (14ul)
+#define PIN_A1               (PIN_A0 + 1)
+#define PIN_A2               (PIN_A0 + 2)
+#define PIN_A3               (PIN_A0 + 3)
+#define PIN_A4               (PIN_A0 + 4)
+#define PIN_A5               (PIN_A0 + 5)
+#define PIN_A6               (PIN_A0 + 6)
+#define PIN_A7               (PIN_A0 + 7)
+#define PIN_A8               (PIN_A0 + 8)
+#define PIN_A9               (PIN_A0 + 9)
+#define PIN_A10              (PIN_A0 + 10)
+#define PIN_A11              (PIN_A0 + 11)
+
+#define PIN_DAC0             PIN_A0
+#define PIN_DAC1             PIN_A1
+
+static const uint8_t A0  = PIN_A0;
+static const uint8_t A1  = PIN_A1;
+static const uint8_t A2  = PIN_A2;
+static const uint8_t A3  = PIN_A3;
+static const uint8_t A4  = PIN_A4;
+static const uint8_t A5  = PIN_A5;
+static const uint8_t A6  = PIN_A6;
+static const uint8_t A7  = PIN_A7;
+static const uint8_t A8  = PIN_A8;
+static const uint8_t A9  = PIN_A9;
+static const uint8_t A10 = PIN_A10;
+static const uint8_t A11 = PIN_A11;
+
+static const uint8_t DAC0 = PIN_DAC0;
+static const uint8_t DAC1 = PIN_DAC1;
+
+#define ADC_RESOLUTION		12
+
+// Other pins
+#define PIN_ATN              (31ul)
+static const uint8_t ATN = PIN_ATN;
+
+
+/*
+ * Serial interfaces
+ */
+
+// Serial1
+#define PIN_SERIAL1_RX       (0ul)
+#define PIN_SERIAL1_TX       (1ul)
+#define PAD_SERIAL1_RX       (SERCOM_RX_PAD_1)
+#define PAD_SERIAL1_TX       (UART_TX_PAD_0)
+
+/*
+ * SPI Interfaces
+ */
+#define SPI_INTERFACES_COUNT 2
+
+#define PIN_SPI_MISO         (28u)
+#define PIN_SPI_MOSI         (29u)
+#define PIN_SPI_SCK          (30u)
+#define PERIPH_SPI           sercom1
+#define PAD_SPI_TX           SPI_PAD_3_SCK_1
+#define PAD_SPI_RX           SERCOM_RX_PAD_2
+
+static const uint8_t SS	  = 4 ;	// SD card CS
+static const uint8_t MOSI = PIN_SPI_MOSI ;
+static const uint8_t MISO = PIN_SPI_MISO ;
+static const uint8_t SCK  = PIN_SPI_SCK ;
+
+  // Internal SPI for TFT
+#define PIN_SPI1_MOSI         (41u)
+#define PIN_SPI1_SCK          (42u)
+#define PIN_SPI1_MISO         (0u)
+#define PERIPH_SPI1           sercom4
+#define PAD_SPI1_TX           SPI_PAD_0_SCK_1
+#define PAD_SPI1_RX           SERCOM_RX_PAD_3
+
+static const uint8_t SS1	  = 44 ;
+static const uint8_t MOSI1 = PIN_SPI1_MOSI ;
+static const uint8_t MISO1 = PIN_SPI1_MISO ;
+static const uint8_t SCK1 = PIN_SPI1_SCK ;
+
+/*
+ * Wire Interfaces
+ */
+#define WIRE_INTERFACES_COUNT 1
+
+#define PIN_WIRE_SDA         (26u)
+#define PIN_WIRE_SCL         (27u)
+#define PERIPH_WIRE          sercom2
+#define WIRE_IT_HANDLER      SERCOM2_Handler
+#define WIRE_IT_HANDLER_0    SERCOM2_0_Handler
+#define WIRE_IT_HANDLER_1    SERCOM2_1_Handler
+#define WIRE_IT_HANDLER_2    SERCOM2_2_Handler
+#define WIRE_IT_HANDLER_3    SERCOM2_3_Handler
+
+static const uint8_t SDA = PIN_WIRE_SDA;
+static const uint8_t SCL = PIN_WIRE_SCL;
+
+/*
+ * USB
+ */
+#define PIN_USB_HOST_ENABLE (31ul)
+#define PIN_USB_DM          (32ul)
+#define PIN_USB_DP          (33ul)
+
+/*
+ * I2S Interfaces
+ */
+#define I2S_INTERFACES_COUNT 0
+
+// On-board QSPI Flash
+#define EXTERNAL_FLASH_DEVICES   GD25Q16C
+#define EXTERNAL_FLASH_USE_QSPI
+
+//QSPI Pins
+#define PIN_QSPI_SCK    (35u)
+#define PIN_QSPI_CS     (36u)
+#define PIN_QSPI_IO0    (37u)
+#define PIN_QSPI_IO1    (38u)
+#define PIN_QSPI_IO2    (39u)
+#define PIN_QSPI_IO3    (40u)
+
+#if !defined(VARIANT_QSPI_BAUD_DEFAULT)
+  // TODO: meaningful value for this
+  #define VARIANT_QSPI_BAUD_DEFAULT 5000000
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+ *        Arduino objects - C++ only
+ *----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+
+/*	=========================
+ *	===== SERCOM DEFINITION
+ *	=========================
+*/
+extern SERCOM sercom0;
+extern SERCOM sercom1;
+extern SERCOM sercom2;
+extern SERCOM sercom3;
+extern SERCOM sercom4;
+extern SERCOM sercom5;
+
+extern Uart Serial1;
+
+#endif
+
+// These serial port names are intended to allow libraries and architecture-neutral
+// sketches to automatically default to the correct port name for a particular type
+// of use.  For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN,
+// the first hardware serial port whose RX/TX pins are not dedicated to another use.
+//
+// SERIAL_PORT_MONITOR        Port which normally prints to the Arduino Serial Monitor
+//
+// SERIAL_PORT_USBVIRTUAL     Port which is USB virtual serial
+//
+// SERIAL_PORT_LINUXBRIDGE    Port which connects to a Linux system via Bridge library
+//
+// SERIAL_PORT_HARDWARE       Hardware serial port, physical RX & TX pins.
+//
+// SERIAL_PORT_HARDWARE_OPEN  Hardware serial ports which are open for use.  Their RX & TX
+//                            pins are NOT connected to anything by default.
+#define SERIAL_PORT_USBVIRTUAL      Serial
+#define SERIAL_PORT_MONITOR         Serial
+// Serial has no physical pins broken out, so it's not listed as HARDWARE port
+#define SERIAL_PORT_HARDWARE        Serial1
+#define SERIAL_PORT_HARDWARE_OPEN   Serial1
+
+#endif /* _VARIANT_PYGAMER_ADVANCE_M4_ */
+
diff --git a/variants/pygamer_m4/debug_scripts/variant.gdb b/variants/pygamer_m4/debug_scripts/variant.gdb
new file mode 100644
index 000000000..3c37ffde2
--- /dev/null
+++ b/variants/pygamer_m4/debug_scripts/variant.gdb
@@ -0,0 +1,31 @@
+#
+#  Arduino Zero OpenOCD script.
+#
+#  Copyright (c) 2014-2015 Arduino LLC. All right reserved.
+#
+#  This library is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 2.1 of the License, or (at your option) any later version.
+#
+#  This library is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#  See the GNU Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library; if not, write to the Free Software
+#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#
+
+# Define 'reset' command
+define reset
+
+info reg
+
+break main
+
+# End of 'reset' command
+end
+
+target remote | openocd -c "interface cmsis-dap" -c "set CHIPNAME at91samd21g18" -f target/at91samdXX.cfg -c "gdb_port pipe; log_output openocd.log"
diff --git a/variants/pygamer_m4/linker_scripts/gcc/flash_with_bootloader.ld b/variants/pygamer_m4/linker_scripts/gcc/flash_with_bootloader.ld
new file mode 100644
index 000000000..1bdea69ae
--- /dev/null
+++ b/variants/pygamer_m4/linker_scripts/gcc/flash_with_bootloader.ld
@@ -0,0 +1,216 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* Linker script to configure memory regions.
+ * Need modifying for a specific board.
+ *   FLASH.ORIGIN: starting address of flash
+ *   FLASH.LENGTH: length of flash
+ *   RAM.ORIGIN: starting address of RAM bank 0
+ *   RAM.LENGTH: length of RAM bank 0
+ */
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000+0x4000, LENGTH = 0x00080000-0x4000 /* First 16KB used by bootloader */
+  RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00030000
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ *   Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ *   __exidx_start
+ *   __exidx_end
+ *   __copy_table_start__
+ *   __copy_table_end__
+ *   __zero_table_start__
+ *   __zero_table_end__
+ *   __etext
+ *   __data_start__
+ *   __preinit_array_start
+ *   __preinit_array_end
+ *   __init_array_start
+ *   __init_array_end
+ *   __fini_array_start
+ *   __fini_array_end
+ *   __data_end__
+ *   __bss_start__
+ *   __bss_end__
+ *   __end__
+ *   end
+ *   __HeapLimit
+ *   __StackLimit
+ *   __StackTop
+ *   __stack
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+	.text :
+	{
+		__text_start__ = .;
+
+		KEEP(*(.sketch_boot))
+
+		. = ALIGN(0x4000);
+		KEEP(*(.isr_vector))
+		*(.text*)
+
+		KEEP(*(.init))
+		KEEP(*(.fini))
+
+		/* .ctors */
+		*crtbegin.o(.ctors)
+		*crtbegin?.o(.ctors)
+		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+		*(SORT(.ctors.*))
+		*(.ctors)
+
+		/* .dtors */
+ 		*crtbegin.o(.dtors)
+ 		*crtbegin?.o(.dtors)
+ 		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ 		*(SORT(.dtors.*))
+ 		*(.dtors)
+
+		*(.rodata*)
+
+		KEEP(*(.eh_frame*))
+	} > FLASH
+
+	.ARM.extab :
+	{
+		*(.ARM.extab* .gnu.linkonce.armextab.*)
+	} > FLASH
+
+	__exidx_start = .;
+	.ARM.exidx :
+	{
+		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
+	} > FLASH
+	__exidx_end = .;
+
+	/* To copy multiple ROM to RAM sections,
+	 * uncomment .copy.table section and,
+	 * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.copy.table :
+	{
+		. = ALIGN(4);
+		__copy_table_start__ = .;
+		LONG (__etext)
+		LONG (__data_start__)
+		LONG (__data_end__ - __data_start__)
+		LONG (__etext2)
+		LONG (__data2_start__)
+		LONG (__data2_end__ - __data2_start__)
+		__copy_table_end__ = .;
+	} > FLASH
+	*/
+
+	/* To clear multiple BSS sections,
+	 * uncomment .zero.table section and,
+	 * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.zero.table :
+	{
+		. = ALIGN(4);
+		__zero_table_start__ = .;
+		LONG (__bss_start__)
+		LONG (__bss_end__ - __bss_start__)
+		LONG (__bss2_start__)
+		LONG (__bss2_end__ - __bss2_start__)
+		__zero_table_end__ = .;
+	} > FLASH
+	*/
+
+	__etext = .;
+
+	.data : AT (__etext)
+	{
+		__data_start__ = .;
+		*(vtable)
+		*(.data*)
+
+		. = ALIGN(4);
+		/* preinit data */
+		PROVIDE_HIDDEN (__preinit_array_start = .);
+		KEEP(*(.preinit_array))
+		PROVIDE_HIDDEN (__preinit_array_end = .);
+
+		. = ALIGN(4);
+		/* init data */
+		PROVIDE_HIDDEN (__init_array_start = .);
+		KEEP(*(SORT(.init_array.*)))
+		KEEP(*(.init_array))
+		PROVIDE_HIDDEN (__init_array_end = .);
+
+
+		. = ALIGN(4);
+		/* finit data */
+		PROVIDE_HIDDEN (__fini_array_start = .);
+		KEEP(*(SORT(.fini_array.*)))
+		KEEP(*(.fini_array))
+		PROVIDE_HIDDEN (__fini_array_end = .);
+
+		KEEP(*(.jcr*))
+		. = ALIGN(16);
+		/* All data end */
+		__data_end__ = .;
+
+	} > RAM
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start__ = .;
+		*(.bss*)
+		*(COMMON)
+		. = ALIGN(4);
+		__bss_end__ = .;
+	} > RAM
+
+	.heap (COPY):
+	{
+		__end__ = .;
+		PROVIDE(end = .);
+		*(.heap*)
+		__HeapLimit = .;
+	} > RAM
+
+	/* .stack_dummy section doesn't contains any symbols. It is only
+	 * used for linker to calculate size of stack sections, and assign
+	 * values to stack symbols later */
+	.stack_dummy (COPY):
+	{
+		*(.stack*)
+	} > RAM
+
+	/* Set stack top to end of RAM, and stack limit move down by
+	 * size of stack_dummy section */
+	__StackTop = ORIGIN(RAM) + LENGTH(RAM);
+	__StackLimit = __StackTop - SIZEOF(.stack_dummy);
+	PROVIDE(__stack = __StackTop);
+
+	__ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ;
+
+	/* Check if data + heap + stack exceeds RAM limit */
+	ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
+}
diff --git a/variants/pygamer_m4/linker_scripts/gcc/flash_without_bootloader.ld b/variants/pygamer_m4/linker_scripts/gcc/flash_without_bootloader.ld
new file mode 100644
index 000000000..9c0c4e06d
--- /dev/null
+++ b/variants/pygamer_m4/linker_scripts/gcc/flash_without_bootloader.ld
@@ -0,0 +1,214 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* Linker script to configure memory regions.
+ * Need modifying for a specific board.
+ *   FLASH.ORIGIN: starting address of flash
+ *   FLASH.LENGTH: length of flash
+ *   RAM.ORIGIN: starting address of RAM bank 0
+ *   RAM.LENGTH: length of RAM bank 0
+ */
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00080000
+  RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00030000
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ *   Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ *   __exidx_start
+ *   __exidx_end
+ *   __copy_table_start__
+ *   __copy_table_end__
+ *   __zero_table_start__
+ *   __zero_table_end__
+ *   __etext
+ *   __data_start__
+ *   __preinit_array_start
+ *   __preinit_array_end
+ *   __init_array_start
+ *   __init_array_end
+ *   __fini_array_start
+ *   __fini_array_end
+ *   __data_end__
+ *   __bss_start__
+ *   __bss_end__
+ *   __end__
+ *   end
+ *   __HeapLimit
+ *   __StackLimit
+ *   __StackTop
+ *   __stack
+ *   __ram_end__
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+	.text :
+	{
+		__text_start__ = .;
+
+		KEEP(*(.isr_vector))
+		*(.text*)
+
+		KEEP(*(.init))
+		KEEP(*(.fini))
+
+		/* .ctors */
+		*crtbegin.o(.ctors)
+		*crtbegin?.o(.ctors)
+		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+		*(SORT(.ctors.*))
+		*(.ctors)
+
+		/* .dtors */
+ 		*crtbegin.o(.dtors)
+ 		*crtbegin?.o(.dtors)
+ 		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ 		*(SORT(.dtors.*))
+ 		*(.dtors)
+
+		*(.rodata*)
+
+		KEEP(*(.eh_frame*))
+	} > FLASH
+
+	.ARM.extab :
+	{
+		*(.ARM.extab* .gnu.linkonce.armextab.*)
+	} > FLASH
+
+	__exidx_start = .;
+	.ARM.exidx :
+	{
+		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
+	} > FLASH
+	__exidx_end = .;
+
+	/* To copy multiple ROM to RAM sections,
+	 * uncomment .copy.table section and,
+	 * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.copy.table :
+	{
+		. = ALIGN(4);
+		__copy_table_start__ = .;
+		LONG (__etext)
+		LONG (__data_start__)
+		LONG (__data_end__ - __data_start__)
+		LONG (__etext2)
+		LONG (__data2_start__)
+		LONG (__data2_end__ - __data2_start__)
+		__copy_table_end__ = .;
+	} > FLASH
+	*/
+
+	/* To clear multiple BSS sections,
+	 * uncomment .zero.table section and,
+	 * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.zero.table :
+	{
+		. = ALIGN(4);
+		__zero_table_start__ = .;
+		LONG (__bss_start__)
+		LONG (__bss_end__ - __bss_start__)
+		LONG (__bss2_start__)
+		LONG (__bss2_end__ - __bss2_start__)
+		__zero_table_end__ = .;
+	} > FLASH
+	*/
+
+	__etext = .;
+
+	.data : AT (__etext)
+	{
+		__data_start__ = .;
+		*(vtable)
+		*(.data*)
+
+		. = ALIGN(4);
+		/* preinit data */
+		PROVIDE_HIDDEN (__preinit_array_start = .);
+		KEEP(*(.preinit_array))
+		PROVIDE_HIDDEN (__preinit_array_end = .);
+
+		. = ALIGN(4);
+		/* init data */
+		PROVIDE_HIDDEN (__init_array_start = .);
+		KEEP(*(SORT(.init_array.*)))
+		KEEP(*(.init_array))
+		PROVIDE_HIDDEN (__init_array_end = .);
+
+
+		. = ALIGN(4);
+		/* finit data */
+		PROVIDE_HIDDEN (__fini_array_start = .);
+		KEEP(*(SORT(.fini_array.*)))
+		KEEP(*(.fini_array))
+		PROVIDE_HIDDEN (__fini_array_end = .);
+
+		KEEP(*(.jcr*))
+		. = ALIGN(16);
+		/* All data end */
+		__data_end__ = .;
+
+	} > RAM
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start__ = .;
+		*(.bss*)
+		*(COMMON)
+		. = ALIGN(4);
+		__bss_end__ = .;
+	} > RAM
+
+	.heap (COPY):
+	{
+		__end__ = .;
+		PROVIDE(end = .);
+		*(.heap*)
+		__HeapLimit = .;
+	} > RAM
+
+	/* .stack_dummy section doesn't contains any symbols. It is only
+	 * used for linker to calculate size of stack sections, and assign
+	 * values to stack symbols later */
+	.stack_dummy (COPY):
+	{
+		*(.stack*)
+	} > RAM
+
+	/* Set stack top to end of RAM, and stack limit move down by
+	 * size of stack_dummy section */
+	__StackTop = ORIGIN(RAM) + LENGTH(RAM) ;
+	__StackLimit = __StackTop - SIZEOF(.stack_dummy);
+	PROVIDE(__stack = __StackTop);
+
+	__ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ;
+
+	/* Check if data + heap + stack exceeds RAM limit */
+	ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
+}
diff --git a/variants/pygamer_m4/openocd_scripts/arduino_zero.cfg b/variants/pygamer_m4/openocd_scripts/arduino_zero.cfg
new file mode 100644
index 000000000..36c65c32d
--- /dev/null
+++ b/variants/pygamer_m4/openocd_scripts/arduino_zero.cfg
@@ -0,0 +1,30 @@
+#
+#  Arduino Zero OpenOCD script.
+#
+#  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+#
+#  This library is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 2.1 of the License, or (at your option) any later version.
+#
+#  This library is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#  See the GNU Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library; if not, write to the Free Software
+#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#
+
+source [find interface/cmsis-dap.cfg]
+
+# chip name
+set CHIPNAME at91samd21g18
+set ENDIAN little
+
+# choose a port here
+set telnet_port 0
+
+source [find target/at91samdXX.cfg]
diff --git a/variants/pygamer_m4/pins_arduino.h b/variants/pygamer_m4/pins_arduino.h
new file mode 100644
index 000000000..db0e40c3d
--- /dev/null
+++ b/variants/pygamer_m4/pins_arduino.h
@@ -0,0 +1,21 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+// API compatibility
+#include "variant.h"
+
diff --git a/variants/pygamer_m4/variant.cpp b/variants/pygamer_m4/variant.cpp
new file mode 100644
index 000000000..ffbccefe8
--- /dev/null
+++ b/variants/pygamer_m4/variant.cpp
@@ -0,0 +1,151 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "variant.h"
+
+/*
+ * Pins descriptions
+ */
+const PinDescription g_APinDescription[]=
+{
+  // 0..13 - Digital pins
+  // ----------------------
+  // 0/1 - SERCOM/UART (Serial1)
+  { PORTB,  17, PIO_SERCOM, PIN_ATTR_PWM_G, No_ADC_Channel, TCC0_CH5, NOT_ON_TIMER,  EXTERNAL_INT_1 },
+  { PORTB,  16, PIO_SERCOM, PIN_ATTR_PWM_G, No_ADC_Channel, TCC0_CH4, NOT_ON_TIMER, EXTERNAL_INT_0 },
+
+  // 2..12
+  // Digital Low
+  { PORTB,  3, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel15, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_3 },
+  { PORTB,  2, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel14, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 },
+  { PORTA,  14, PIO_SERCOM, PIN_ATTR_PWM_E, No_ADC_Channel, TC3_CH0, TC3_CH0, EXTERNAL_INT_14 },
+  { PORTA,  16, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_0  },
+  { PORTA,  18, PIO_SERCOM, PIO_SERCOM, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2  },
+  { PORTB,  14, PIO_DIGITAL, PIN_ATTR_PWM_F, No_ADC_Channel, TCC4_CH0, TC5_CH0, EXTERNAL_INT_14 },
+
+  // Digital High
+  { PORTA, 15, PIO_DIGITAL, PIN_ATTR_PWM_E, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_15  }, // D8 - NEOPIXEL
+  { PORTA,  19, PIO_DIGITAL, PIN_ATTR_PWM_E, No_ADC_Channel, TC3_CH1, TC3_CH1,  EXTERNAL_INT_3 },
+  { PORTA,  20, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER,  EXTERNAL_INT_4 },
+  { PORTA,  21, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER,  EXTERNAL_INT_5 },
+  { PORTA,  22, PIO_SERCOM, PIN_ATTR_PWM_G, No_ADC_Channel, TCC0_CH2, TC4_CH0, EXTERNAL_INT_6 },
+
+  // 13 (LED)
+  { PORTA, 23, PIO_SERCOM, PIN_ATTR_PWM_G, No_ADC_Channel, TCC0_CH3, TC4_CH1, EXTERNAL_INT_7 }, 
+
+  // 14..25 - Analog pins
+  // --------------------
+  { PORTA,  2, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel0, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 },
+  { PORTA,  5, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel5, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_5 },
+  { PORTB,  8, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel2, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_8 },
+  { PORTB,  9, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel3, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_9 },
+  { PORTA,  4, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel4, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_4 },
+  { PORTA,  6, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel6, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_6 },
+
+  { PORTB,  1, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel13, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_1 },  // A6, D20 - vbatt
+  { PORTB,  4, PIO_ANALOG, PIN_ATTR_ANALOG_ALT, ADC_Channel6, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_4 },   // A7, D21 - Light
+  { PORTB,  3, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel15, NOT_ON_PWM,  NOT_ON_TIMER, EXTERNAL_INT_3 }, // A8 / D2
+  { PORTB,  2, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel14, NOT_ON_PWM,  NOT_ON_TIMER, EXTERNAL_INT_2 }, // A9 / D3
+  { PORTB,  6, PIO_ANALOG, PIN_ATTR_ANALOG_ALT, ADC_Channel8, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_6 },   // A10 / JOYY
+  { PORTB,  7, PIO_ANALOG, PIN_ATTR_ANALOG_ALT, ADC_Channel9, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_7 },   // A11 / JOYX
+
+  // 26..27 I2C pins (SDA/SCL)
+  // ----------------------
+  { PORTA,  12, PIO_SERCOM, PIN_ATTR_PWM_E, No_ADC_Channel, TC2_CH0, TC2_CH0,  EXTERNAL_INT_12 }, // SDA
+  { PORTA,  13, PIO_SERCOM, PIN_ATTR_PWM_E, No_ADC_Channel, TC2_CH1, TC2_CH1,  EXTERNAL_INT_13 }, // SCL
+
+  // 28..30 - SPI pins (MISO,MOSI,SCK)
+  // ----------------------
+  { PORTB, 22, PIO_SERCOM, (PIN_ATTR_DIGITAL), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_6 }, // MISO: SERCOM1/PAD[2]
+  { PORTB, 23, PIO_SERCOM, (PIN_ATTR_DIGITAL), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_7 }, // MOSI: SERCOM1/PAD[3]
+  { PORTA, 17, PIO_SERCOM, (PIN_ATTR_DIGITAL), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_1 }, // SCK: SERCOM1/PAD[1]
+
+  // 31..33 - USB
+  // --------------------
+  { NOT_A_PORT, PIN_NOT_A_PIN, PIO_NOT_A_PIN, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB Host enable DOES NOT EXIST ON THIS BOARD
+  { PORTA, 24, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB/DM
+  { PORTA, 25, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB/DP
+
+  // 34 (AREF)
+  { PORTA, 3, PIO_ANALOG, PIN_ATTR_ANALOG, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // DAC/VREFP
+
+  // ----------------------
+  // 35..40 QSPI (SCK, CS, IO0, IO1, IO2, IO3)
+  { PORTB, 10, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+  { PORTB, 11, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+  { PORTA, 8, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+  { PORTA, 9, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+  { PORTA, 10, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+  { PORTA, 11, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+
+  // 41..46 - TFT SPI port + control pins
+  // --------------------
+  { PORTB, 15, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_15 },  // SERCOM 4.3 MOSI
+  { PORTB, 13, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_13 },  // SERCOM 4.1 SCK
+  { PORTB, 12, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_12 },  // SERCOM 4.0 'miso' (NC)
+  { PORTB, 12, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_12 },  // D44 TFT CS
+  { PORTB,  5, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_5 },  // D45 TFT DC
+  { PORTA,  0, PIO_DIGITAL, PIN_ATTR_PWM_E, No_ADC_Channel, TC2_CH0, TC2_CH0, EXTERNAL_INT_0 },            // D46 TFT RST
+
+  // 47 - backlight
+  { PORTA,  1, PIO_DIGITAL, PIN_ATTR_PWM_E, No_ADC_Channel, TC2_CH1, TC2_CH1, EXTERNAL_INT_1 }, // D47 TFT BACKLITE
+
+  // 48 - button control
+  { PORTB, 31, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_15 },  // D48 button clock
+  { PORTB, 30, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_14 },  // D49 button data
+  { PORTB,  0, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_0 },  // D50 button latch
+  
+  // D51 Speaker enable
+  { PORTA, 27, PIO_DIGITAL, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+
+  // ----------------------
+  // D52..D53 - Alternate use of A0 (DAC outputs)
+  { PORTA,  2, PIO_ANALOG, PIN_ATTR_ANALOG, DAC_Channel0, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // DAC/VOUT0
+  { PORTA,  5, PIO_ANALOG, PIN_ATTR_ANALOG, DAC_Channel1, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // DAC/VOUT1
+
+} ;
+
+const void* g_apTCInstances[TCC_INST_NUM+TC_INST_NUM]={ TCC0, TCC1, TCC2, TCC3, TCC4, TC0, TC1, TC2, TC3, TC4, TC5 } ;
+const uint32_t GCLK_CLKCTRL_IDs[TCC_INST_NUM+TC_INST_NUM] = { TCC0_GCLK_ID, TCC1_GCLK_ID, TCC2_GCLK_ID, TCC3_GCLK_ID, TCC4_GCLK_ID, TC0_GCLK_ID, TC1_GCLK_ID, TC2_GCLK_ID, TC3_GCLK_ID, TC4_GCLK_ID, TC5_GCLK_ID } ;
+
+// Multi-serial objects instantiation
+SERCOM sercom0( SERCOM0 ) ;
+SERCOM sercom1( SERCOM1 ) ;
+SERCOM sercom2( SERCOM2 ) ;
+SERCOM sercom3( SERCOM3 ) ;
+SERCOM sercom4( SERCOM4 ) ;
+SERCOM sercom5( SERCOM5 ) ;
+
+Uart Serial1( &sercom5, PIN_SERIAL1_RX, PIN_SERIAL1_TX, PAD_SERIAL1_RX, PAD_SERIAL1_TX ) ;
+
+void SERCOM5_0_Handler()
+{
+  Serial1.IrqHandler();
+}
+void SERCOM5_1_Handler()
+{
+  Serial1.IrqHandler();
+}
+void SERCOM5_2_Handler()
+{
+  Serial1.IrqHandler();
+}
+void SERCOM5_3_Handler()
+{
+  Serial1.IrqHandler();
+}
diff --git a/variants/pygamer_m4/variant.h b/variants/pygamer_m4/variant.h
new file mode 100644
index 000000000..12c5b4ffb
--- /dev/null
+++ b/variants/pygamer_m4/variant.h
@@ -0,0 +1,264 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _VARIANT_PYGAMER_M4_
+#define _VARIANT_PYGAMER_M4_
+
+// The definitions here needs a SAMD core >=1.6.10
+#define ARDUINO_SAMD_VARIANT_COMPLIANCE 10610
+
+/*----------------------------------------------------------------------------
+ *        Definitions
+ *----------------------------------------------------------------------------*/
+
+/** Frequency of the board main oscillator */
+#define VARIANT_MAINOSC		(32768ul)
+
+/** Master clock frequency */
+#define VARIANT_MCK	   (F_CPU)
+
+#define VARIANT_GCLK0_FREQ (F_CPU)
+#define VARIANT_GCLK1_FREQ (48000000UL)
+#define VARIANT_GCLK2_FREQ (100000000UL)
+
+/*----------------------------------------------------------------------------
+ *        Headers
+ *----------------------------------------------------------------------------*/
+
+#include "WVariant.h"
+
+#ifdef __cplusplus
+#include "SERCOM.h"
+#include "Uart.h"
+#endif // __cplusplus
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif // __cplusplus
+
+/*----------------------------------------------------------------------------
+ *        Pins
+ *----------------------------------------------------------------------------*/
+
+// Number of pins defined in PinDescription array
+#define PINS_COUNT           (54u)
+#define NUM_DIGITAL_PINS     (25u)
+#define NUM_ANALOG_INPUTS    (12u)
+#define NUM_ANALOG_OUTPUTS   (2u)
+#define analogInputToDigitalPin(p)  ((p < 6u) ? (p) + 14u : -1)
+
+#define digitalPinToPort(P)        ( &(PORT->Group[g_APinDescription[P].ulPort]) )
+#define digitalPinToBitMask(P)     ( 1 << g_APinDescription[P].ulPin )
+//#define analogInPinToBit(P)        ( )
+#define portOutputRegister(port)   ( &(port->OUT.reg) )
+#define portInputRegister(port)    ( &(port->IN.reg) )
+#define portModeRegister(port)     ( &(port->DIR.reg) )
+#define digitalPinHasPWM(P)        ( g_APinDescription[P].ulPWMChannel != NOT_ON_PWM || g_APinDescription[P].ulTCChannel != NOT_ON_TIMER )
+
+/*
+ * digitalPinToTimer(..) is AVR-specific and is not defined for SAMD
+ * architecture. If you need to check if a pin supports PWM you must
+ * use digitalPinHasPWM(..).
+ *
+ * https://github.com/arduino/Arduino/issues/1833
+ */
+// #define digitalPinToTimer(P)
+
+// LEDs
+#define PIN_LED_13           (13u)
+#define PIN_LED              PIN_LED_13
+#define LED_BUILTIN          PIN_LED_13
+
+/*
+ * Analog pins
+ */
+#define PIN_A0               (14ul)
+#define PIN_A1               (PIN_A0 + 1)
+#define PIN_A2               (PIN_A0 + 2)
+#define PIN_A3               (PIN_A0 + 3)
+#define PIN_A4               (PIN_A0 + 4)
+#define PIN_A5               (PIN_A0 + 5)
+#define PIN_A6               (PIN_A0 + 6)
+#define PIN_A7               (PIN_A0 + 7)
+#define PIN_A8               (PIN_A0 + 8)
+#define PIN_A9               (PIN_A0 + 9)
+#define PIN_A10              (PIN_A0 + 10)
+#define PIN_A11              (PIN_A0 + 11)
+
+#define PIN_DAC0             PIN_A0
+#define PIN_DAC1             PIN_A1
+
+static const uint8_t A0  = PIN_A0;
+static const uint8_t A1  = PIN_A1;
+static const uint8_t A2  = PIN_A2;
+static const uint8_t A3  = PIN_A3;
+static const uint8_t A4  = PIN_A4;
+static const uint8_t A5  = PIN_A5;
+static const uint8_t A6  = PIN_A6;
+static const uint8_t A7  = PIN_A7;
+static const uint8_t A8  = PIN_A8;
+static const uint8_t A9  = PIN_A9;
+static const uint8_t A10 = PIN_A10;
+static const uint8_t A11 = PIN_A11;
+
+static const uint8_t DAC0 = PIN_DAC0;
+static const uint8_t DAC1 = PIN_DAC1;
+
+#define ADC_RESOLUTION		12
+
+// Other pins
+#define PIN_ATN              (31ul)
+static const uint8_t ATN = PIN_ATN;
+
+
+/*
+ * Serial interfaces
+ */
+
+// Serial1
+#define PIN_SERIAL1_RX       (0ul)
+#define PIN_SERIAL1_TX       (1ul)
+#define PAD_SERIAL1_RX       (SERCOM_RX_PAD_1)
+#define PAD_SERIAL1_TX       (UART_TX_PAD_0)
+
+/*
+ * SPI Interfaces
+ */
+#define SPI_INTERFACES_COUNT 2
+
+#define PIN_SPI_MISO         (28u)
+#define PIN_SPI_MOSI         (29u)
+#define PIN_SPI_SCK          (30u)
+#define PERIPH_SPI           sercom1
+#define PAD_SPI_TX           SPI_PAD_3_SCK_1
+#define PAD_SPI_RX           SERCOM_RX_PAD_2
+
+static const uint8_t SS	  = 4 ;	// SD card CS
+static const uint8_t MOSI = PIN_SPI_MOSI ;
+static const uint8_t MISO = PIN_SPI_MISO ;
+static const uint8_t SCK  = PIN_SPI_SCK ;
+
+  // Internal SPI for TFT
+#define PIN_SPI1_MOSI         (41u)
+#define PIN_SPI1_SCK          (42u)
+#define PIN_SPI1_MISO         (0u)
+#define PERIPH_SPI1           sercom4
+#define PAD_SPI1_TX           SPI_PAD_3_SCK_1
+#define PAD_SPI1_RX           SERCOM_RX_PAD_0
+
+static const uint8_t SS1	  = 44 ;
+static const uint8_t MOSI1 = PIN_SPI1_MOSI ;
+static const uint8_t MISO1 = PIN_SPI1_MISO ;
+static const uint8_t SCK1 = PIN_SPI1_SCK ;
+
+/*
+ * Wire Interfaces
+ */
+#define WIRE_INTERFACES_COUNT 1
+
+#define PIN_WIRE_SDA         (26u)
+#define PIN_WIRE_SCL         (27u)
+#define PERIPH_WIRE          sercom2
+#define WIRE_IT_HANDLER      SERCOM2_Handler
+#define WIRE_IT_HANDLER_0    SERCOM2_0_Handler
+#define WIRE_IT_HANDLER_1    SERCOM2_1_Handler
+#define WIRE_IT_HANDLER_2    SERCOM2_2_Handler
+#define WIRE_IT_HANDLER_3    SERCOM2_3_Handler
+
+static const uint8_t SDA = PIN_WIRE_SDA;
+static const uint8_t SCL = PIN_WIRE_SCL;
+
+/*
+ * USB
+ */
+#define PIN_USB_HOST_ENABLE (31ul)
+#define PIN_USB_DM          (32ul)
+#define PIN_USB_DP          (33ul)
+
+/*
+ * I2S Interfaces
+ */
+#define I2S_INTERFACES_COUNT 0
+
+
+// On-board QSPI Flash
+#define EXTERNAL_FLASH_DEVICES   GD25Q64C
+#define EXTERNAL_FLASH_USE_QSPI
+
+//QSPI Pins
+#define PIN_QSPI_SCK    (35u)
+#define PIN_QSPI_CS     (36u)
+#define PIN_QSPI_IO0    (37u)
+#define PIN_QSPI_IO1    (38u)
+#define PIN_QSPI_IO2    (39u)
+#define PIN_QSPI_IO3    (40u)
+
+#if !defined(VARIANT_QSPI_BAUD_DEFAULT)
+  // TODO: meaningful value for this
+  #define VARIANT_QSPI_BAUD_DEFAULT 5000000
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+ *        Arduino objects - C++ only
+ *----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+
+/*	=========================
+ *	===== SERCOM DEFINITION
+ *	=========================
+*/
+extern SERCOM sercom0;
+extern SERCOM sercom1;
+extern SERCOM sercom2;
+extern SERCOM sercom3;
+extern SERCOM sercom4;
+extern SERCOM sercom5;
+
+extern Uart Serial1;
+
+#endif
+
+// These serial port names are intended to allow libraries and architecture-neutral
+// sketches to automatically default to the correct port name for a particular type
+// of use.  For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN,
+// the first hardware serial port whose RX/TX pins are not dedicated to another use.
+//
+// SERIAL_PORT_MONITOR        Port which normally prints to the Arduino Serial Monitor
+//
+// SERIAL_PORT_USBVIRTUAL     Port which is USB virtual serial
+//
+// SERIAL_PORT_LINUXBRIDGE    Port which connects to a Linux system via Bridge library
+//
+// SERIAL_PORT_HARDWARE       Hardware serial port, physical RX & TX pins.
+//
+// SERIAL_PORT_HARDWARE_OPEN  Hardware serial ports which are open for use.  Their RX & TX
+//                            pins are NOT connected to anything by default.
+#define SERIAL_PORT_USBVIRTUAL      Serial
+#define SERIAL_PORT_MONITOR         Serial
+// Serial has no physical pins broken out, so it's not listed as HARDWARE port
+#define SERIAL_PORT_HARDWARE        Serial1
+#define SERIAL_PORT_HARDWARE_OPEN   Serial1
+
+#endif /* _VARIANT_PYGAMER_M4_ */
+
diff --git a/variants/pyportal_m4/linker_scripts/gcc/flash_with_bootloader.ld b/variants/pyportal_m4/linker_scripts/gcc/flash_with_bootloader.ld
new file mode 100644
index 000000000..5fe575a0d
--- /dev/null
+++ b/variants/pyportal_m4/linker_scripts/gcc/flash_with_bootloader.ld
@@ -0,0 +1,216 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* Linker script to configure memory regions.
+ * Need modifying for a specific board.
+ *   FLASH.ORIGIN: starting address of flash
+ *   FLASH.LENGTH: length of flash
+ *   RAM.ORIGIN: starting address of RAM bank 0
+ *   RAM.LENGTH: length of RAM bank 0
+ */
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000+0x4000, LENGTH = 0x80000-0x4000 /* First 16KB used by bootloader */
+  RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x30000
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ *   Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ *   __exidx_start
+ *   __exidx_end
+ *   __copy_table_start__
+ *   __copy_table_end__
+ *   __zero_table_start__
+ *   __zero_table_end__
+ *   __etext
+ *   __data_start__
+ *   __preinit_array_start
+ *   __preinit_array_end
+ *   __init_array_start
+ *   __init_array_end
+ *   __fini_array_start
+ *   __fini_array_end
+ *   __data_end__
+ *   __bss_start__
+ *   __bss_end__
+ *   __end__
+ *   end
+ *   __HeapLimit
+ *   __StackLimit
+ *   __StackTop
+ *   __stack
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+	.text :
+	{
+		__text_start__ = .;
+
+		KEEP(*(.sketch_boot))
+
+		. = ALIGN(0x4000);
+		KEEP(*(.isr_vector))
+		*(.text*)
+
+		KEEP(*(.init))
+		KEEP(*(.fini))
+
+		/* .ctors */
+		*crtbegin.o(.ctors)
+		*crtbegin?.o(.ctors)
+		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+		*(SORT(.ctors.*))
+		*(.ctors)
+
+		/* .dtors */
+ 		*crtbegin.o(.dtors)
+ 		*crtbegin?.o(.dtors)
+ 		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ 		*(SORT(.dtors.*))
+ 		*(.dtors)
+
+		*(.rodata*)
+
+		KEEP(*(.eh_frame*))
+	} > FLASH
+
+	.ARM.extab :
+	{
+		*(.ARM.extab* .gnu.linkonce.armextab.*)
+	} > FLASH
+
+	__exidx_start = .;
+	.ARM.exidx :
+	{
+		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
+	} > FLASH
+	__exidx_end = .;
+
+	/* To copy multiple ROM to RAM sections,
+	 * uncomment .copy.table section and,
+	 * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.copy.table :
+	{
+		. = ALIGN(4);
+		__copy_table_start__ = .;
+		LONG (__etext)
+		LONG (__data_start__)
+		LONG (__data_end__ - __data_start__)
+		LONG (__etext2)
+		LONG (__data2_start__)
+		LONG (__data2_end__ - __data2_start__)
+		__copy_table_end__ = .;
+	} > FLASH
+	*/
+
+	/* To clear multiple BSS sections,
+	 * uncomment .zero.table section and,
+	 * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.zero.table :
+	{
+		. = ALIGN(4);
+		__zero_table_start__ = .;
+		LONG (__bss_start__)
+		LONG (__bss_end__ - __bss_start__)
+		LONG (__bss2_start__)
+		LONG (__bss2_end__ - __bss2_start__)
+		__zero_table_end__ = .;
+	} > FLASH
+	*/
+
+	__etext = .;
+
+	.data : AT (__etext)
+	{
+		__data_start__ = .;
+		*(vtable)
+		*(.data*)
+
+		. = ALIGN(4);
+		/* preinit data */
+		PROVIDE_HIDDEN (__preinit_array_start = .);
+		KEEP(*(.preinit_array))
+		PROVIDE_HIDDEN (__preinit_array_end = .);
+
+		. = ALIGN(4);
+		/* init data */
+		PROVIDE_HIDDEN (__init_array_start = .);
+		KEEP(*(SORT(.init_array.*)))
+		KEEP(*(.init_array))
+		PROVIDE_HIDDEN (__init_array_end = .);
+
+
+		. = ALIGN(4);
+		/* finit data */
+		PROVIDE_HIDDEN (__fini_array_start = .);
+		KEEP(*(SORT(.fini_array.*)))
+		KEEP(*(.fini_array))
+		PROVIDE_HIDDEN (__fini_array_end = .);
+
+		KEEP(*(.jcr*))
+		. = ALIGN(16);
+		/* All data end */
+		__data_end__ = .;
+
+	} > RAM
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start__ = .;
+		*(.bss*)
+		*(COMMON)
+		. = ALIGN(4);
+		__bss_end__ = .;
+	} > RAM
+
+	.heap (COPY):
+	{
+		__end__ = .;
+		PROVIDE(end = .);
+		*(.heap*)
+		__HeapLimit = .;
+	} > RAM
+
+	/* .stack_dummy section doesn't contains any symbols. It is only
+	 * used for linker to calculate size of stack sections, and assign
+	 * values to stack symbols later */
+	.stack_dummy (COPY):
+	{
+		*(.stack*)
+	} > RAM
+
+	/* Set stack top to end of RAM, and stack limit move down by
+	 * size of stack_dummy section */
+	__StackTop = ORIGIN(RAM) + LENGTH(RAM);
+	__StackLimit = __StackTop - SIZEOF(.stack_dummy);
+	PROVIDE(__stack = __StackTop);
+
+	__ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ;
+
+	/* Check if data + heap + stack exceeds RAM limit */
+	ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
+}
diff --git a/variants/pyportal_m4/linker_scripts/gcc/flash_without_bootloader.ld b/variants/pyportal_m4/linker_scripts/gcc/flash_without_bootloader.ld
new file mode 100644
index 000000000..0123a0a23
--- /dev/null
+++ b/variants/pyportal_m4/linker_scripts/gcc/flash_without_bootloader.ld
@@ -0,0 +1,215 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* Linker script to configure memory regions.
+ * Need modifying for a specific board.
+ *   FLASH.ORIGIN: starting address of flash
+ *   FLASH.LENGTH: length of flash
+ *   RAM.ORIGIN: starting address of RAM bank 0
+ *   RAM.LENGTH: length of RAM bank 0
+ */
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x80000
+  RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x30000
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ *   Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ *   __exidx_start
+ *   __exidx_end
+ *   __copy_table_start__
+ *   __copy_table_end__
+ *   __zero_table_start__
+ *   __zero_table_end__
+ *   __etext
+ *   __data_start__
+ *   __preinit_array_start
+ *   __preinit_array_end
+ *   __init_array_start
+ *   __init_array_end
+ *   __fini_array_start
+ *   __fini_array_end
+ *   __data_end__
+ *   __bss_start__
+ *   __bss_end__
+ *   __end__
+ *   end
+ *   __HeapLimit
+ *   __StackLimit
+ *   __StackTop
+ *   __stack
+ *   __ram_end__
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+	.text :
+	{
+		__text_start__ = .;
+
+		. = ALIGN(4);
+		KEEP(*(.isr_vector))
+		*(.text*)
+
+		KEEP(*(.init))
+		KEEP(*(.fini))
+
+		/* .ctors */
+		*crtbegin.o(.ctors)
+		*crtbegin?.o(.ctors)
+		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+		*(SORT(.ctors.*))
+		*(.ctors)
+
+		/* .dtors */
+ 		*crtbegin.o(.dtors)
+ 		*crtbegin?.o(.dtors)
+ 		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ 		*(SORT(.dtors.*))
+ 		*(.dtors)
+
+		*(.rodata*)
+
+		KEEP(*(.eh_frame*))
+	} > FLASH
+
+	.ARM.extab :
+	{
+		*(.ARM.extab* .gnu.linkonce.armextab.*)
+	} > FLASH
+
+	__exidx_start = .;
+	.ARM.exidx :
+	{
+		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
+	} > FLASH
+	__exidx_end = .;
+
+	/* To copy multiple ROM to RAM sections,
+	 * uncomment .copy.table section and,
+	 * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.copy.table :
+	{
+		. = ALIGN(4);
+		__copy_table_start__ = .;
+		LONG (__etext)
+		LONG (__data_start__)
+		LONG (__data_end__ - __data_start__)
+		LONG (__etext2)
+		LONG (__data2_start__)
+		LONG (__data2_end__ - __data2_start__)
+		__copy_table_end__ = .;
+	} > FLASH
+	*/
+
+	/* To clear multiple BSS sections,
+	 * uncomment .zero.table section and,
+	 * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.zero.table :
+	{
+		. = ALIGN(4);
+		__zero_table_start__ = .;
+		LONG (__bss_start__)
+		LONG (__bss_end__ - __bss_start__)
+		LONG (__bss2_start__)
+		LONG (__bss2_end__ - __bss2_start__)
+		__zero_table_end__ = .;
+	} > FLASH
+	*/
+
+	__etext = .;
+
+	.data : AT (__etext)
+	{
+		__data_start__ = .;
+		*(vtable)
+		*(.data*)
+
+		. = ALIGN(4);
+		/* preinit data */
+		PROVIDE_HIDDEN (__preinit_array_start = .);
+		KEEP(*(.preinit_array))
+		PROVIDE_HIDDEN (__preinit_array_end = .);
+
+		. = ALIGN(4);
+		/* init data */
+		PROVIDE_HIDDEN (__init_array_start = .);
+		KEEP(*(SORT(.init_array.*)))
+		KEEP(*(.init_array))
+		PROVIDE_HIDDEN (__init_array_end = .);
+
+
+		. = ALIGN(4);
+		/* finit data */
+		PROVIDE_HIDDEN (__fini_array_start = .);
+		KEEP(*(SORT(.fini_array.*)))
+		KEEP(*(.fini_array))
+		PROVIDE_HIDDEN (__fini_array_end = .);
+
+		KEEP(*(.jcr*))
+		. = ALIGN(16);
+		/* All data end */
+		__data_end__ = .;
+
+	} > RAM
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start__ = .;
+		*(.bss*)
+		*(COMMON)
+		. = ALIGN(4);
+		__bss_end__ = .;
+	} > RAM
+
+	.heap (COPY):
+	{
+		__end__ = .;
+		PROVIDE(end = .);
+		*(.heap*)
+		__HeapLimit = .;
+	} > RAM
+
+	/* .stack_dummy section doesn't contains any symbols. It is only
+	 * used for linker to calculate size of stack sections, and assign
+	 * values to stack symbols later */
+	.stack_dummy (COPY):
+	{
+		*(.stack*)
+	} > RAM
+
+	/* Set stack top to end of RAM, and stack limit move down by
+	 * size of stack_dummy section */
+	__StackTop = ORIGIN(RAM) + LENGTH(RAM) ;
+	__StackLimit = __StackTop - SIZEOF(.stack_dummy);
+	PROVIDE(__stack = __StackTop);
+
+	__ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ;
+
+	/* Check if data + heap + stack exceeds RAM limit */
+	ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
+}
diff --git a/variants/pyportal_m4/pins_arduino.h b/variants/pyportal_m4/pins_arduino.h
new file mode 100644
index 000000000..db0e40c3d
--- /dev/null
+++ b/variants/pyportal_m4/pins_arduino.h
@@ -0,0 +1,21 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+// API compatibility
+#include "variant.h"
+
diff --git a/variants/pyportal_m4/variant.cpp b/variants/pyportal_m4/variant.cpp
new file mode 100644
index 000000000..a74da78f6
--- /dev/null
+++ b/variants/pyportal_m4/variant.cpp
@@ -0,0 +1,151 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "variant.h"
+
+// PyPortal uses ATSAMD51J20 (64-pin), Metro & Feather M4 use J19, Trellis uses 51G
+// NOT SURE ABOUT PIN_ATTR_PWM_n VALUES, defaulting all to "E" for now, update as required
+// Also setting PWM and TIMER pins to same value to start, update as required
+// Is LIGHT pin connected/routed anywhere?
+
+/* NEW PIN DEFS IN PROGRESS:
+
+  { PORTA,  3, PIO_ANALOG    , PIN_ATTR_ANALOG                 , ADC_Channel1  , NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_3    }, // AREF - NOT USED
+  { PORTA, 30, PIO_DIGITAL   , PIN_ATTR_PWM_E                  , No_ADC_Channel, TC6_CH0   , TC6_CH0     , EXTERNAL_INT_14   }, // SWCLK - not used?
+  { PORTA, 31, PIO_DIGITAL   , PIN_ATTR_PWM_E                  , No_ADC_Channel, TC6_CH1   , TC6_CH1     , EXTERNAL_INT_15   }, // SWDIO - not used?
+
+*/
+
+
+/*
+ * Pins descriptions
+ */
+const PinDescription g_APinDescription[]=
+{
+  // 0..13 - Digital pins
+  // ----------------------
+  // 0/1 - SERCOM/UART (Serial1)
+  { PORTB, 13, PIO_SERCOM    , PIN_ATTR_NONE                   , No_ADC_Channel, TC4_CH1   , TCC3_CH1    , EXTERNAL_INT_13   }, // RXD (pin 0, to ESP32), SERCOM4/PAD[1]
+  { PORTB, 12, PIO_SERCOM    , PIN_ATTR_NONE                   , No_ADC_Channel, TC4_CH0   , TCC3_CH0    , EXTERNAL_INT_12   }, // TXD (pin 1, to ESP32), SERCOM4/PAD[0]
+
+  // 2..4
+  { PORTB, 22, PIO_DIGITAL   , PIN_ATTR_PWM_E                  , No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_6    }, // NEOPIX
+  { PORTA,  4, PIO_SERCOM_ALT, (PIN_ATTR_ANALOG|PIN_ATTR_PWM_E), ADC_Channel4  , TC0_CH0   , TC0_CH0     , EXTERNAL_INT_4    }, // D3 (SENSE JST)
+  { PORTA,  5, PIO_SERCOM_ALT, (PIN_ATTR_ANALOG|PIN_ATTR_PWM_E), ADC_Channel5  , TC0_CH1   , TC0_CH1     , EXTERNAL_INT_5    }, // D4 (NEOPIX JST)
+
+  // 5..12  ESP32 and TFT control lines
+  { PORTB, 16, PIO_DIGITAL   , PIN_ATTR_PWM_E                  , No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_0    }, // ESP_BUSY
+  { PORTB, 15, PIO_DIGITAL   , PIN_ATTR_PWM_E                  , No_ADC_Channel, TC5_CH1   , TC5_CH1     , EXTERNAL_INT_15   }, // ESP_GPIO0
+  { PORTB, 17, PIO_DIGITAL   , PIN_ATTR_PWM_E                  , No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_1    }, // ESP RESET
+  { PORTB, 14, PIO_DIGITAL   , PIN_ATTR_PWM_E                  , No_ADC_Channel, TC5_CH0   , TC5_CH0     , EXTERNAL_INT_14   }, // ESP_CS
+  { PORTB,  4, PIO_DIGITAL   , PIN_ATTR_NONE                   , No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_4    }, // TFT_RD
+  { PORTB,  5, PIO_DIGITAL   , PIN_ATTR_NONE                   , No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_5    }, // TFT_RS
+  { PORTB,  6, PIO_DIGITAL   , PIN_ATTR_NONE                   , No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_6    }, // TFT_CS
+  { PORTB,  7, PIO_DIGITAL   , PIN_ATTR_NONE                   , No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_7    }, // TFT_TE
+
+  // 13 (LED)
+  { PORTB, 23, PIO_DIGITAL   , PIN_ATTR_PWM_E                  , No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_7    }, // D13 (LED)
+
+  // 14..23  Analog pins
+  { PORTA,  2, PIO_ANALOG    , PIN_ATTR_ANALOG                 , DAC_Channel0  , NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2    }, // AUDIO_OUT (A0)
+  { PORTA,  4, PIO_ANALOG    , (PIN_ATTR_ANALOG|PIN_ATTR_PWM_E), ADC_Channel4  , TC0_CH0   , TC0_CH0     , EXTERNAL_INT_4    }, // D3 (SENSE JST)
+  { PORTA,  7, PIO_DIGITAL   , (PIN_ATTR_ANALOG|PIN_ATTR_PWM_E), ADC_Channel7  , TC1_CH1   , TC1_CH1     , EXTERNAL_INT_7    }, // Light sensor (A2)
+  { PORTA,  5, PIO_ANALOG    , (PIN_ATTR_ANALOG|PIN_ATTR_PWM_E), ADC_Channel5  , TC0_CH1   , TC0_CH1     , EXTERNAL_INT_5    }, // D4 (NEOPIX JST)
+  { PORTB,  0, PIO_ANALOG    , (PIN_ATTR_ANALOG|PIN_ATTR_PWM_E), ADC_Channel12 , NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_0    }, // TOUCH_YD
+  { PORTB,  1, PIO_ANALOG    , (PIN_ATTR_ANALOG|PIN_ATTR_PWM_E), ADC_Channel13 , NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_1    }, // TOUCH_XL
+  { PORTA,  6, PIO_ANALOG    , (PIN_ATTR_ANALOG|PIN_ATTR_PWM_E), ADC_Channel6  , TC1_CH0   , TC1_CH0     , EXTERNAL_INT_6    }, // TOUCH_YU
+  { PORTB,  8, PIO_ANALOG    , (PIN_ATTR_ANALOG|PIN_ATTR_PWM_E), ADC_Channel2  , TC4_CH0   , TC4_CH0     , EXTERNAL_INT_8    }, // TOUCH_XR
+  { PORTB,  2, PIO_SERCOM_ALT, (PIN_ATTR_ANALOG|PIN_ATTR_PWM_E), ADC_Channel14 , NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2    }, // SDA (JST), SERCOM5/PAD[0] - analog copy
+  { PORTB,  3, PIO_SERCOM_ALT, (PIN_ATTR_ANALOG|PIN_ATTR_PWM_E), ADC_Channel15 , NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_3    }, // SCL (JST), SERCOM5/PAD[1] - analog copy
+
+  // 24..26 more TFT control lines
+  { PORTA,  0, PIO_DIGITAL   , PIN_ATTR_PWM_E                  , No_ADC_Channel, TC2_CH0   , TC2_CH0     , EXTERNAL_INT_0    }, // TFT_RESET
+  { PORTB, 31, PIO_DIGITAL   , PIN_ATTR_PWM_F                  , No_ADC_Channel, TCC4_CH1  , TCC4_CH1    , EXTERNAL_INT_15   }, // TFT_BACKLITE
+  { PORTB,  9, PIO_DIGITAL   , (PIN_ATTR_ANALOG|PIN_ATTR_PWM_E), ADC_Channel3  , TC4_CH1   , TC4_CH1     , EXTERNAL_INT_9    }, // TFT_WR, CCL/OUT[2]
+
+  // 27..28  I2C pins
+  { PORTB,  2, PIO_SERCOM_ALT, (PIN_ATTR_ANALOG|PIN_ATTR_PWM_E), ADC_Channel14 , NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2    }, // SDA (JST), SERCOM5/PAD[0]
+  { PORTB,  3, PIO_SERCOM_ALT, (PIN_ATTR_ANALOG|PIN_ATTR_PWM_E), ADC_Channel15 , NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_3    }, // SCL (JST), SERCOM5/PAD[1]
+
+  // 29..31  SPI pins
+  { PORTA, 12, PIO_SERCOM    , PIN_ATTR_PWM_E                  , No_ADC_Channel, TC2_CH0   , TC2_CH0     , EXTERNAL_INT_12   }, // MOSI, SERCOM2/PAD[0]
+  { PORTA, 13, PIO_SERCOM    , PIN_ATTR_PWM_E                  , No_ADC_Channel, TC2_CH1   , TC2_CH1     , EXTERNAL_INT_13   }, // SCK,  SERCOM2/PAD[1]
+  { PORTA, 14, PIO_SERCOM    , PIN_ATTR_PWM_E                  , No_ADC_Channel, TC3_CH0   , TC3_CH0     , EXTERNAL_INT_14   }, // MISO, SERCOM2/PAD[2]
+
+  // 32..33  Some SD card control
+  { PORTB, 30, PIO_DIGITAL   , PIN_ATTR_PWM_E                  , No_ADC_Channel, TC0_CH0   , TC0_CH0     , EXTERNAL_INT_14   }, // SD_CS
+  { PORTA,  1, PIO_DIGITAL   , PIN_ATTR_PWM_E                  , No_ADC_Channel, TC2_CH1   , TC2_CH1     , EXTERNAL_INT_1    }, // CARDDET
+
+  // 34..41  LCD data
+  { PORTA, 16, PIO_DIGITAL   , PIN_ATTR_PWM_E                  , No_ADC_Channel, TC2_CH0   , TC2_CH0     , EXTERNAL_INT_0    }, // LCD_DATA0
+  { PORTA, 17, PIO_DIGITAL   , PIN_ATTR_PWM_F                  , No_ADC_Channel, TCC1_CH1  , TC2_CH1     , EXTERNAL_INT_1    }, // LCD_DATA1
+  { PORTA, 18, PIO_DIGITAL   , PIN_ATTR_PWM_F                  , No_ADC_Channel, TCC1_CH2  , TC3_CH0     , EXTERNAL_INT_2    }, // LCD_DATA2
+  { PORTA, 19, PIO_DIGITAL   , PIN_ATTR_PWM_F                  , No_ADC_Channel, TCC1_CH3  , TC3_CH1     , EXTERNAL_INT_3    }, // LCD_DATA3
+  { PORTA, 20, PIO_DIGITAL   , PIN_ATTR_PWM_G                  , No_ADC_Channel, TCC0_CH0  , TC0_CH0     , EXTERNAL_INT_4    }, // LCD_DATA4
+  { PORTA, 21, PIO_DIGITAL   , PIN_ATTR_PWM_G                  , No_ADC_Channel, TCC0_CH0  , TC0_CH1     , EXTERNAL_INT_5    }, // LCD_DATA5
+  { PORTA, 22, PIO_DIGITAL   , PIN_ATTR_PWM_G                  , No_ADC_Channel, TCC0_CH2  , TC4_CH0     , EXTERNAL_INT_6    }, // LCD_DATA6
+  { PORTA, 23, PIO_DIGITAL   , PIN_ATTR_PWM_G                  , No_ADC_Channel, TCC0_CH3  , TC4_CH1     , EXTERNAL_INT_7    }, // LCD_DATA7
+
+  // 42..47  QSPI
+  { PORTB, 10, PIO_COM       , PIN_ATTR_NONE                   , No_ADC_Channel, TC5_CH0   , TC5_CH0     , EXTERNAL_INT_10   }, // QSPI_SCK
+  { PORTB, 11, PIO_COM       , PIN_ATTR_NONE                   , No_ADC_Channel, TC5_CH1   , TC5_CH1     , EXTERNAL_INT_11   }, // QSPI_CS
+  { PORTA,  8, PIO_COM       , PIN_ATTR_NONE                   , No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NMI  }, // QSPI_DATA0
+  { PORTA,  9, PIO_COM       , PIN_ATTR_NONE                   , No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_9    }, // QSPI_DATA1
+  { PORTA, 10, PIO_COM       , PIN_ATTR_NONE                   , No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_10   }, // QSPI_DATA2
+  { PORTA, 11, PIO_COM       , PIN_ATTR_NONE                   , No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_11   }, // QSPI_DATA3
+
+  // 48..49  USB
+  { PORTA, 24, PIO_COM       , PIN_ATTR_NONE                   , No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB D-
+  { PORTA, 25, PIO_COM       , PIN_ATTR_NONE                   , No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB D+
+
+  // 50..51
+  { PORTA, 27, PIO_DIGITAL   , PIN_ATTR_NONE                   , No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_11   }, // Speaker shutdown
+  { PORTA, 15, PIO_DIGITAL   , PIN_ATTR_PWM_E                  , No_ADC_Channel, TC3_CH1   , TC3_CH1     , EXTERNAL_INT_15   }, // ESP_RTS
+
+} ;
+
+const void* g_apTCInstances[TCC_INST_NUM+TC_INST_NUM]={ TCC0, TCC1, TCC2, TCC3, TCC4, TC0, TC1, TC2, TC3, TC4, TC5 } ;
+const uint32_t GCLK_CLKCTRL_IDs[TCC_INST_NUM+TC_INST_NUM] = { TCC0_GCLK_ID, TCC1_GCLK_ID, TCC2_GCLK_ID, TCC3_GCLK_ID, TCC4_GCLK_ID, TC0_GCLK_ID, TC1_GCLK_ID, TC2_GCLK_ID, TC3_GCLK_ID, TC4_GCLK_ID, TC5_GCLK_ID } ;
+
+
+// Multi-serial objects instantiation
+SERCOM sercom0( SERCOM0 ) ;
+SERCOM sercom1( SERCOM1 ) ;
+SERCOM sercom2( SERCOM2 ) ;
+SERCOM sercom3( SERCOM3 ) ;
+SERCOM sercom4( SERCOM4 ) ;
+SERCOM sercom5( SERCOM5 ) ;
+
+Uart Serial1( &sercom4, PIN_SERIAL1_RX, PIN_SERIAL1_TX, PAD_SERIAL1_RX, PAD_SERIAL1_TX ) ;
+
+void SERCOM4_0_Handler()
+{
+  Serial1.IrqHandler();
+}
+void SERCOM4_1_Handler()
+{
+  Serial1.IrqHandler();
+}
+void SERCOM4_2_Handler()
+{
+  Serial1.IrqHandler();
+}
+void SERCOM4_3_Handler()
+{
+  Serial1.IrqHandler();
+}
diff --git a/variants/pyportal_m4/variant.h b/variants/pyportal_m4/variant.h
new file mode 100644
index 000000000..b159bd7e3
--- /dev/null
+++ b/variants/pyportal_m4/variant.h
@@ -0,0 +1,258 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _VARIANT_PYPORTAL_M4_
+#define _VARIANT_PYPORTAL_M4_
+
+// The definitions here needs a SAMD core >=1.6.10
+#define ARDUINO_SAMD_VARIANT_COMPLIANCE 10610
+
+/*----------------------------------------------------------------------------
+ *        Definitions
+ *----------------------------------------------------------------------------*/
+
+/** Frequency of the board main oscillator */
+#define VARIANT_MAINOSC		(32768ul)
+
+/** Master clock frequency */
+#define VARIANT_MCK        (F_CPU)
+
+#define VARIANT_GCLK0_FREQ (F_CPU)
+#define VARIANT_GCLK1_FREQ (48000000UL)
+#define VARIANT_GCLK2_FREQ (100000000UL)
+
+/*----------------------------------------------------------------------------
+ *        Headers
+ *----------------------------------------------------------------------------*/
+
+#include "WVariant.h"
+
+#ifdef __cplusplus
+#include "SERCOM.h"
+#include "Uart.h"
+#endif // __cplusplus
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif // __cplusplus
+
+/*----------------------------------------------------------------------------
+ *        Pins
+ *----------------------------------------------------------------------------*/
+
+// Number of pins defined in PinDescription array
+#define PINS_COUNT           (52u)
+#define NUM_DIGITAL_PINS     (42u)
+#define NUM_ANALOG_INPUTS    (9u)
+#define NUM_ANALOG_OUTPUTS   (1u)
+#define analogInputToDigitalPin(p)  ((p < 10u) ? (p) + 14u : -1)
+
+#define digitalPinToPort(P)        ( &(PORT->Group[g_APinDescription[P].ulPort]) )
+#define digitalPinToBitMask(P)     ( 1 << g_APinDescription[P].ulPin )
+//#define analogInPinToBit(P)        ( )
+#define portOutputRegister(port)   ( &(port->OUT.reg) )
+#define portInputRegister(port)    ( &(port->IN.reg) )
+#define portModeRegister(port)     ( &(port->DIR.reg) )
+#define digitalPinHasPWM(P)        ( g_APinDescription[P].ulPWMChannel != NOT_ON_PWM || g_APinDescription[P].ulTCChannel != NOT_ON_TIMER )
+
+/*
+ * digitalPinToTimer(..) is AVR-specific and is not defined for SAMD
+ * architecture. If you need to check if a pin supports PWM you must
+ * use digitalPinHasPWM(..).
+ *
+ * https://github.com/arduino/Arduino/issues/1833
+ */
+// #define digitalPinToTimer(P)
+
+// LEDs
+#define PIN_LED_13           (13u)
+//#define PIN_LED_RXL          (27u)
+//#define PIN_LED_TXL          (28u)
+#define PIN_LED              PIN_LED_13
+//#define PIN_LED2             PIN_LED_RXL
+//#define PIN_LED3             PIN_LED_TXL
+#define LED_BUILTIN          PIN_LED_13
+
+/*
+ * Analog pins
+ */
+#define PIN_A0               (14ul)
+#define PIN_A1               (PIN_A0 + 1)
+#define PIN_A2               (PIN_A0 + 2)
+#define PIN_A3               (PIN_A0 + 3)
+#define PIN_A4               (PIN_A0 + 4)
+#define PIN_A5               (PIN_A0 + 5)
+#define PIN_A6               (PIN_A0 + 6)
+#define PIN_A7               (PIN_A0 + 7)
+#define PIN_A8               (PIN_A0 + 8)
+#define PIN_A9               (PIN_A0 + 9)
+#define PIN_DAC0             PIN_A0
+#define PIN_DAC1             PIN_A1
+
+static const uint8_t A0  = PIN_A0;
+static const uint8_t A1  = PIN_A1;
+static const uint8_t A2  = PIN_A2;
+static const uint8_t A3  = PIN_A3;
+static const uint8_t A4  = PIN_A4;
+static const uint8_t A5  = PIN_A5;
+static const uint8_t A6  = PIN_A6;
+static const uint8_t A7  = PIN_A7;
+static const uint8_t A8  = PIN_A8;
+static const uint8_t A9  = PIN_A9;
+
+static const uint8_t DAC0 = PIN_DAC0;
+
+#define ADC_RESOLUTION		12
+
+// Other pins
+#define PIN_ATN              (39ul)  // ???
+static const uint8_t ATN = PIN_ATN;
+
+/* WiFi interfaces */
+#define SerialNina      Serial1
+#define SPIWIFI         SPI
+#define ESP32_GPIO0     6
+#define ESP32_RESETN    7
+#define SPIWIFI_SS      8
+#define SPIWIFI_ACK     5
+#define SPIWIFI_RESET   7
+#define NINA_GPIO0      ESP32_GPIO0
+#define NINA_RESETN     ESP32_RESETN
+#define NINA_ACK        SPIWIFI_ACK
+#define SerialESP32     Serial1
+
+/*
+ * Serial interfaces
+ */
+
+// Serial1
+#define PIN_SERIAL1_RX       (0ul)
+#define PIN_SERIAL1_TX       (1ul)
+#define PAD_SERIAL1_RX       (SERCOM_RX_PAD_1)
+#define PAD_SERIAL1_TX       (UART_TX_PAD_0)
+
+
+/*
+ * SPI Interfaces
+ */
+#define SPI_INTERFACES_COUNT 1
+
+#define PIN_SPI_MISO         (31u)
+#define PIN_SPI_MOSI         (29u)
+#define PIN_SPI_SCK          (30u)
+#define PERIPH_SPI           sercom2
+#define PAD_SPI_TX           SPI_PAD_0_SCK_1
+#define PAD_SPI_RX           SERCOM_RX_PAD_2
+
+static const uint8_t SS	  = PIN_A2;       // ???
+static const uint8_t MOSI = PIN_SPI_MOSI;
+static const uint8_t MISO = PIN_SPI_MISO;
+static const uint8_t SCK  = PIN_SPI_SCK;
+
+
+/*
+ * Wire Interfaces
+ */
+#define WIRE_INTERFACES_COUNT 1
+
+#define PIN_WIRE_SDA         (27u)
+#define PIN_WIRE_SCL         (28u)
+#define PERIPH_WIRE          sercom5
+#define WIRE_IT_HANDLER      SERCOM5_Handler
+#define WIRE_IT_HANDLER_0    SERCOM5_0_Handler
+#define WIRE_IT_HANDLER_1    SERCOM5_1_Handler
+#define WIRE_IT_HANDLER_2    SERCOM5_2_Handler
+#define WIRE_IT_HANDLER_3    SERCOM5_3_Handler
+
+
+static const uint8_t SDA = PIN_WIRE_SDA;
+static const uint8_t SCL = PIN_WIRE_SCL;
+
+/*
+ * USB
+ */
+#define PIN_USB_HOST_ENABLE (29ul) // ???
+#define PIN_USB_DM          (48ul)
+#define PIN_USB_DP          (49ul)
+
+// On-board QSPI Flash
+#define EXTERNAL_FLASH_DEVICES   GD25Q64C
+#define EXTERNAL_FLASH_USE_QSPI
+
+//QSPI Pins
+#define PIN_QSPI_SCK	(42u)
+#define PIN_QSPI_CS	(43u)
+#define PIN_QSPI_IO0	(44u)
+#define PIN_QSPI_IO1	(45u)
+#define PIN_QSPI_IO2	(46u)
+#define PIN_QSPI_IO3	(47u)
+
+#if !defined(VARIANT_QSPI_BAUD_DEFAULT)
+  // TODO: meaningful value for this
+  #define VARIANT_QSPI_BAUD_DEFAULT 5000000
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+ *        Arduino objects - C++ only
+ *----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+
+/*	=========================
+ *	===== SERCOM DEFINITION
+ *	=========================
+*/
+extern SERCOM sercom0;
+extern SERCOM sercom1;
+extern SERCOM sercom2;
+extern SERCOM sercom3;
+extern SERCOM sercom4;
+extern SERCOM sercom5;
+
+extern Uart Serial1;
+
+#endif
+
+// These serial port names are intended to allow libraries and architecture-neutral
+// sketches to automatically default to the correct port name for a particular type
+// of use.  For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN,
+// the first hardware serial port whose RX/TX pins are not dedicated to another use.
+//
+// SERIAL_PORT_MONITOR        Port which normally prints to the Arduino Serial Monitor
+//
+// SERIAL_PORT_USBVIRTUAL     Port which is USB virtual serial
+//
+// SERIAL_PORT_LINUXBRIDGE    Port which connects to a Linux system via Bridge library
+//
+// SERIAL_PORT_HARDWARE       Hardware serial port, physical RX & TX pins.
+//
+// SERIAL_PORT_HARDWARE_OPEN  Hardware serial ports which are open for use.  Their RX & TX
+//                            pins are NOT connected to anything by default.
+#define SERIAL_PORT_USBVIRTUAL      Serial
+#define SERIAL_PORT_MONITOR         Serial
+// Serial has no physical pins broken out, so it's not listed as HARDWARE port
+#define SERIAL_PORT_HARDWARE        Serial1
+#define SERIAL_PORT_HARDWARE_OPEN   Serial1
+
+#endif /* _VARIANT_PYPORTAL_M4_ */
+
diff --git a/variants/pyportal_m4_titano/linker_scripts/gcc/flash_with_bootloader.ld b/variants/pyportal_m4_titano/linker_scripts/gcc/flash_with_bootloader.ld
new file mode 100644
index 000000000..5fe575a0d
--- /dev/null
+++ b/variants/pyportal_m4_titano/linker_scripts/gcc/flash_with_bootloader.ld
@@ -0,0 +1,216 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* Linker script to configure memory regions.
+ * Need modifying for a specific board.
+ *   FLASH.ORIGIN: starting address of flash
+ *   FLASH.LENGTH: length of flash
+ *   RAM.ORIGIN: starting address of RAM bank 0
+ *   RAM.LENGTH: length of RAM bank 0
+ */
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000+0x4000, LENGTH = 0x80000-0x4000 /* First 16KB used by bootloader */
+  RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x30000
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ *   Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ *   __exidx_start
+ *   __exidx_end
+ *   __copy_table_start__
+ *   __copy_table_end__
+ *   __zero_table_start__
+ *   __zero_table_end__
+ *   __etext
+ *   __data_start__
+ *   __preinit_array_start
+ *   __preinit_array_end
+ *   __init_array_start
+ *   __init_array_end
+ *   __fini_array_start
+ *   __fini_array_end
+ *   __data_end__
+ *   __bss_start__
+ *   __bss_end__
+ *   __end__
+ *   end
+ *   __HeapLimit
+ *   __StackLimit
+ *   __StackTop
+ *   __stack
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+	.text :
+	{
+		__text_start__ = .;
+
+		KEEP(*(.sketch_boot))
+
+		. = ALIGN(0x4000);
+		KEEP(*(.isr_vector))
+		*(.text*)
+
+		KEEP(*(.init))
+		KEEP(*(.fini))
+
+		/* .ctors */
+		*crtbegin.o(.ctors)
+		*crtbegin?.o(.ctors)
+		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+		*(SORT(.ctors.*))
+		*(.ctors)
+
+		/* .dtors */
+ 		*crtbegin.o(.dtors)
+ 		*crtbegin?.o(.dtors)
+ 		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ 		*(SORT(.dtors.*))
+ 		*(.dtors)
+
+		*(.rodata*)
+
+		KEEP(*(.eh_frame*))
+	} > FLASH
+
+	.ARM.extab :
+	{
+		*(.ARM.extab* .gnu.linkonce.armextab.*)
+	} > FLASH
+
+	__exidx_start = .;
+	.ARM.exidx :
+	{
+		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
+	} > FLASH
+	__exidx_end = .;
+
+	/* To copy multiple ROM to RAM sections,
+	 * uncomment .copy.table section and,
+	 * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.copy.table :
+	{
+		. = ALIGN(4);
+		__copy_table_start__ = .;
+		LONG (__etext)
+		LONG (__data_start__)
+		LONG (__data_end__ - __data_start__)
+		LONG (__etext2)
+		LONG (__data2_start__)
+		LONG (__data2_end__ - __data2_start__)
+		__copy_table_end__ = .;
+	} > FLASH
+	*/
+
+	/* To clear multiple BSS sections,
+	 * uncomment .zero.table section and,
+	 * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.zero.table :
+	{
+		. = ALIGN(4);
+		__zero_table_start__ = .;
+		LONG (__bss_start__)
+		LONG (__bss_end__ - __bss_start__)
+		LONG (__bss2_start__)
+		LONG (__bss2_end__ - __bss2_start__)
+		__zero_table_end__ = .;
+	} > FLASH
+	*/
+
+	__etext = .;
+
+	.data : AT (__etext)
+	{
+		__data_start__ = .;
+		*(vtable)
+		*(.data*)
+
+		. = ALIGN(4);
+		/* preinit data */
+		PROVIDE_HIDDEN (__preinit_array_start = .);
+		KEEP(*(.preinit_array))
+		PROVIDE_HIDDEN (__preinit_array_end = .);
+
+		. = ALIGN(4);
+		/* init data */
+		PROVIDE_HIDDEN (__init_array_start = .);
+		KEEP(*(SORT(.init_array.*)))
+		KEEP(*(.init_array))
+		PROVIDE_HIDDEN (__init_array_end = .);
+
+
+		. = ALIGN(4);
+		/* finit data */
+		PROVIDE_HIDDEN (__fini_array_start = .);
+		KEEP(*(SORT(.fini_array.*)))
+		KEEP(*(.fini_array))
+		PROVIDE_HIDDEN (__fini_array_end = .);
+
+		KEEP(*(.jcr*))
+		. = ALIGN(16);
+		/* All data end */
+		__data_end__ = .;
+
+	} > RAM
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start__ = .;
+		*(.bss*)
+		*(COMMON)
+		. = ALIGN(4);
+		__bss_end__ = .;
+	} > RAM
+
+	.heap (COPY):
+	{
+		__end__ = .;
+		PROVIDE(end = .);
+		*(.heap*)
+		__HeapLimit = .;
+	} > RAM
+
+	/* .stack_dummy section doesn't contains any symbols. It is only
+	 * used for linker to calculate size of stack sections, and assign
+	 * values to stack symbols later */
+	.stack_dummy (COPY):
+	{
+		*(.stack*)
+	} > RAM
+
+	/* Set stack top to end of RAM, and stack limit move down by
+	 * size of stack_dummy section */
+	__StackTop = ORIGIN(RAM) + LENGTH(RAM);
+	__StackLimit = __StackTop - SIZEOF(.stack_dummy);
+	PROVIDE(__stack = __StackTop);
+
+	__ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ;
+
+	/* Check if data + heap + stack exceeds RAM limit */
+	ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
+}
diff --git a/variants/pyportal_m4_titano/linker_scripts/gcc/flash_without_bootloader.ld b/variants/pyportal_m4_titano/linker_scripts/gcc/flash_without_bootloader.ld
new file mode 100644
index 000000000..0123a0a23
--- /dev/null
+++ b/variants/pyportal_m4_titano/linker_scripts/gcc/flash_without_bootloader.ld
@@ -0,0 +1,215 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* Linker script to configure memory regions.
+ * Need modifying for a specific board.
+ *   FLASH.ORIGIN: starting address of flash
+ *   FLASH.LENGTH: length of flash
+ *   RAM.ORIGIN: starting address of RAM bank 0
+ *   RAM.LENGTH: length of RAM bank 0
+ */
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x80000
+  RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x30000
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ *   Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ *   __exidx_start
+ *   __exidx_end
+ *   __copy_table_start__
+ *   __copy_table_end__
+ *   __zero_table_start__
+ *   __zero_table_end__
+ *   __etext
+ *   __data_start__
+ *   __preinit_array_start
+ *   __preinit_array_end
+ *   __init_array_start
+ *   __init_array_end
+ *   __fini_array_start
+ *   __fini_array_end
+ *   __data_end__
+ *   __bss_start__
+ *   __bss_end__
+ *   __end__
+ *   end
+ *   __HeapLimit
+ *   __StackLimit
+ *   __StackTop
+ *   __stack
+ *   __ram_end__
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+	.text :
+	{
+		__text_start__ = .;
+
+		. = ALIGN(4);
+		KEEP(*(.isr_vector))
+		*(.text*)
+
+		KEEP(*(.init))
+		KEEP(*(.fini))
+
+		/* .ctors */
+		*crtbegin.o(.ctors)
+		*crtbegin?.o(.ctors)
+		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+		*(SORT(.ctors.*))
+		*(.ctors)
+
+		/* .dtors */
+ 		*crtbegin.o(.dtors)
+ 		*crtbegin?.o(.dtors)
+ 		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ 		*(SORT(.dtors.*))
+ 		*(.dtors)
+
+		*(.rodata*)
+
+		KEEP(*(.eh_frame*))
+	} > FLASH
+
+	.ARM.extab :
+	{
+		*(.ARM.extab* .gnu.linkonce.armextab.*)
+	} > FLASH
+
+	__exidx_start = .;
+	.ARM.exidx :
+	{
+		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
+	} > FLASH
+	__exidx_end = .;
+
+	/* To copy multiple ROM to RAM sections,
+	 * uncomment .copy.table section and,
+	 * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.copy.table :
+	{
+		. = ALIGN(4);
+		__copy_table_start__ = .;
+		LONG (__etext)
+		LONG (__data_start__)
+		LONG (__data_end__ - __data_start__)
+		LONG (__etext2)
+		LONG (__data2_start__)
+		LONG (__data2_end__ - __data2_start__)
+		__copy_table_end__ = .;
+	} > FLASH
+	*/
+
+	/* To clear multiple BSS sections,
+	 * uncomment .zero.table section and,
+	 * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.zero.table :
+	{
+		. = ALIGN(4);
+		__zero_table_start__ = .;
+		LONG (__bss_start__)
+		LONG (__bss_end__ - __bss_start__)
+		LONG (__bss2_start__)
+		LONG (__bss2_end__ - __bss2_start__)
+		__zero_table_end__ = .;
+	} > FLASH
+	*/
+
+	__etext = .;
+
+	.data : AT (__etext)
+	{
+		__data_start__ = .;
+		*(vtable)
+		*(.data*)
+
+		. = ALIGN(4);
+		/* preinit data */
+		PROVIDE_HIDDEN (__preinit_array_start = .);
+		KEEP(*(.preinit_array))
+		PROVIDE_HIDDEN (__preinit_array_end = .);
+
+		. = ALIGN(4);
+		/* init data */
+		PROVIDE_HIDDEN (__init_array_start = .);
+		KEEP(*(SORT(.init_array.*)))
+		KEEP(*(.init_array))
+		PROVIDE_HIDDEN (__init_array_end = .);
+
+
+		. = ALIGN(4);
+		/* finit data */
+		PROVIDE_HIDDEN (__fini_array_start = .);
+		KEEP(*(SORT(.fini_array.*)))
+		KEEP(*(.fini_array))
+		PROVIDE_HIDDEN (__fini_array_end = .);
+
+		KEEP(*(.jcr*))
+		. = ALIGN(16);
+		/* All data end */
+		__data_end__ = .;
+
+	} > RAM
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start__ = .;
+		*(.bss*)
+		*(COMMON)
+		. = ALIGN(4);
+		__bss_end__ = .;
+	} > RAM
+
+	.heap (COPY):
+	{
+		__end__ = .;
+		PROVIDE(end = .);
+		*(.heap*)
+		__HeapLimit = .;
+	} > RAM
+
+	/* .stack_dummy section doesn't contains any symbols. It is only
+	 * used for linker to calculate size of stack sections, and assign
+	 * values to stack symbols later */
+	.stack_dummy (COPY):
+	{
+		*(.stack*)
+	} > RAM
+
+	/* Set stack top to end of RAM, and stack limit move down by
+	 * size of stack_dummy section */
+	__StackTop = ORIGIN(RAM) + LENGTH(RAM) ;
+	__StackLimit = __StackTop - SIZEOF(.stack_dummy);
+	PROVIDE(__stack = __StackTop);
+
+	__ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ;
+
+	/* Check if data + heap + stack exceeds RAM limit */
+	ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
+}
diff --git a/variants/pyportal_m4_titano/pins_arduino.h b/variants/pyportal_m4_titano/pins_arduino.h
new file mode 100644
index 000000000..db0e40c3d
--- /dev/null
+++ b/variants/pyportal_m4_titano/pins_arduino.h
@@ -0,0 +1,21 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+// API compatibility
+#include "variant.h"
+
diff --git a/variants/pyportal_m4_titano/variant.cpp b/variants/pyportal_m4_titano/variant.cpp
new file mode 100644
index 000000000..53cfdaca5
--- /dev/null
+++ b/variants/pyportal_m4_titano/variant.cpp
@@ -0,0 +1,151 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "variant.h"
+
+// PyPortal uses ATSAMD51J20 (64-pin), Metro & Feather M4 use J19, Trellis uses 51G
+// NOT SURE ABOUT PIN_ATTR_PWM_n VALUES, defaulting all to "E" for now, update as required
+// Also setting PWM and TIMER pins to same value to start, update as required
+// Is LIGHT pin connected/routed anywhere?
+
+/* NEW PIN DEFS IN PROGRESS:
+
+  { PORTA,  3, PIO_ANALOG    , PIN_ATTR_ANALOG                 , ADC_Channel1  , NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_3    }, // AREF - NOT USED
+  { PORTA, 30, PIO_DIGITAL   , PIN_ATTR_PWM_E                  , No_ADC_Channel, TC6_CH0   , TC6_CH0     , EXTERNAL_INT_14   }, // SWCLK - not used?
+  { PORTA, 31, PIO_DIGITAL   , PIN_ATTR_PWM_E                  , No_ADC_Channel, TC6_CH1   , TC6_CH1     , EXTERNAL_INT_15   }, // SWDIO - not used?
+
+*/
+
+
+/*
+ * Pins descriptions
+ */
+const PinDescription g_APinDescription[]=
+{
+  // 0..13 - Digital pins
+  // ----------------------
+  // 0/1 - SERCOM/UART (Serial1)
+  { PORTB, 13, PIO_SERCOM    , PIN_ATTR_NONE                   , No_ADC_Channel, TC4_CH1   , TCC3_CH1    , EXTERNAL_INT_13   }, // RXD (pin 0, to ESP32), SERCOM4/PAD[1]
+  { PORTB, 12, PIO_SERCOM    , PIN_ATTR_NONE                   , No_ADC_Channel, TC4_CH0   , TCC3_CH0    , EXTERNAL_INT_12   }, // TXD (pin 1, to ESP32), SERCOM4/PAD[0]
+
+  // 2..4
+  { PORTB, 22, PIO_DIGITAL   , PIN_ATTR_PWM_E                  , No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_6    }, // NEOPIX
+  { PORTA,  4, PIO_SERCOM_ALT, (PIN_ATTR_ANALOG|PIN_ATTR_PWM_E), ADC_Channel4  , TC0_CH0   , TC0_CH0     , EXTERNAL_INT_4    }, // D3 (SENSE JST)
+  { PORTA,  5, PIO_SERCOM_ALT, (PIN_ATTR_ANALOG|PIN_ATTR_PWM_E), ADC_Channel5  , TC0_CH1   , TC0_CH1     , EXTERNAL_INT_5    }, // D4 (NEOPIX JST)
+
+  // 5..12  ESP32 and TFT control lines
+  { PORTB, 16, PIO_DIGITAL   , PIN_ATTR_PWM_E                  , No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_0    }, // ESP_BUSY
+  { PORTB, 15, PIO_DIGITAL   , PIN_ATTR_PWM_E                  , No_ADC_Channel, TC5_CH1   , TC5_CH1     , EXTERNAL_INT_15   }, // ESP_GPIO0
+  { PORTB, 17, PIO_DIGITAL   , PIN_ATTR_PWM_E                  , No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_1    }, // ESP RESET
+  { PORTB, 14, PIO_DIGITAL   , PIN_ATTR_PWM_E                  , No_ADC_Channel, TC5_CH0   , TC5_CH0     , EXTERNAL_INT_14   }, // ESP_CS
+  { PORTB,  4, PIO_DIGITAL   , PIN_ATTR_NONE                   , No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_4    }, // TFT_RD
+  { PORTB,  5, PIO_DIGITAL   , PIN_ATTR_NONE                   , No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_5    }, // TFT_RS
+  { PORTB,  6, PIO_DIGITAL   , PIN_ATTR_NONE                   , No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_6    }, // TFT_CS
+  { PORTB,  7, PIO_DIGITAL   , PIN_ATTR_NONE                   , No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_7    }, // TFT_TE
+
+  // 13 (LED)
+  { PORTB, 23, PIO_DIGITAL   , PIN_ATTR_PWM_E                  , No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_7    }, // D13 (LED)
+
+  // 14..23  Analog pins
+  { PORTA,  2, PIO_ANALOG    , PIN_ATTR_ANALOG                 , DAC_Channel0  , NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2    }, // AUDIO_OUT (A0)
+  { PORTA,  4, PIO_ANALOG    , (PIN_ATTR_ANALOG|PIN_ATTR_PWM_E), ADC_Channel4  , TC0_CH0   , TC0_CH0     , EXTERNAL_INT_4    }, // D3 (SENSE JST)
+  { PORTA,  7, PIO_DIGITAL   , (PIN_ATTR_ANALOG|PIN_ATTR_PWM_E), ADC_Channel7  , TC1_CH1   , TC1_CH1     , EXTERNAL_INT_7    }, // Light sensor (A2)
+  { PORTA,  5, PIO_ANALOG    , (PIN_ATTR_ANALOG|PIN_ATTR_PWM_E), ADC_Channel5  , TC0_CH1   , TC0_CH1     , EXTERNAL_INT_5    }, // D4 (NEOPIX JST)
+  { PORTB,  0, PIO_ANALOG    , (PIN_ATTR_ANALOG|PIN_ATTR_PWM_E), ADC_Channel12 , NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_0    }, // TOUCH_YD
+  { PORTB,  1, PIO_ANALOG    , (PIN_ATTR_ANALOG|PIN_ATTR_PWM_E), ADC_Channel13 , NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_1    }, // TOUCH_XL
+  { PORTA,  6, PIO_ANALOG    , (PIN_ATTR_ANALOG|PIN_ATTR_PWM_E), ADC_Channel6  , TC1_CH0   , TC1_CH0     , EXTERNAL_INT_6    }, // TOUCH_YU
+  { PORTB,  8, PIO_ANALOG    , (PIN_ATTR_ANALOG|PIN_ATTR_PWM_E), ADC_Channel2  , TC4_CH0   , TC4_CH0     , EXTERNAL_INT_8    }, // TOUCH_XR
+  { PORTB,  2, PIO_SERCOM_ALT, (PIN_ATTR_ANALOG|PIN_ATTR_PWM_E), ADC_Channel14 , NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2    }, // SDA (JST), SERCOM5/PAD[0] - analog copy
+  { PORTB,  3, PIO_SERCOM_ALT, (PIN_ATTR_ANALOG|PIN_ATTR_PWM_E), ADC_Channel15 , NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_3    }, // SCL (JST), SERCOM5/PAD[1] - analog copy
+
+  // 24..26 more TFT control lines
+  { PORTA,  0, PIO_DIGITAL   , PIN_ATTR_PWM_E                  , No_ADC_Channel, TC2_CH0   , TC2_CH0     , EXTERNAL_INT_0    }, // TFT_RESET
+  { PORTB, 31, PIO_DIGITAL   , PIN_ATTR_PWM_E                  , No_ADC_Channel, TC0_CH1   , TC0_CH1     , EXTERNAL_INT_15   }, // TFT_BACKLITE
+  { PORTB,  9, PIO_DIGITAL   , (PIN_ATTR_ANALOG|PIN_ATTR_PWM_E), ADC_Channel3  , TC4_CH1   , TC4_CH1     , EXTERNAL_INT_9    }, // TFT_WR, CCL/OUT[2]
+
+  // 27..28  I2C pins
+  { PORTB,  2, PIO_SERCOM_ALT, (PIN_ATTR_ANALOG|PIN_ATTR_PWM_E), ADC_Channel14 , NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2    }, // SDA (JST), SERCOM5/PAD[0]
+  { PORTB,  3, PIO_SERCOM_ALT, (PIN_ATTR_ANALOG|PIN_ATTR_PWM_E), ADC_Channel15 , NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_3    }, // SCL (JST), SERCOM5/PAD[1]
+
+  // 29..31  SPI pins
+  { PORTA, 12, PIO_SERCOM    , PIN_ATTR_PWM_E                  , No_ADC_Channel, TC2_CH0   , TC2_CH0     , EXTERNAL_INT_12   }, // MOSI, SERCOM2/PAD[0]
+  { PORTA, 13, PIO_SERCOM    , PIN_ATTR_PWM_E                  , No_ADC_Channel, TC2_CH1   , TC2_CH1     , EXTERNAL_INT_13   }, // SCK,  SERCOM2/PAD[1]
+  { PORTA, 14, PIO_SERCOM    , PIN_ATTR_PWM_E                  , No_ADC_Channel, TC3_CH0   , TC3_CH0     , EXTERNAL_INT_14   }, // MISO, SERCOM2/PAD[2]
+
+  // 32..33  Some SD card control
+  { PORTB, 30, PIO_DIGITAL   , PIN_ATTR_PWM_E                  , No_ADC_Channel, TC0_CH0   , TC0_CH0     , EXTERNAL_INT_14   }, // SD_CS
+  { PORTA,  1, PIO_DIGITAL   , PIN_ATTR_PWM_E                  , No_ADC_Channel, TC2_CH1   , TC2_CH1     , EXTERNAL_INT_1    }, // CARDDET
+
+  // 34..41  LCD data
+  { PORTA, 16, PIO_DIGITAL   , PIN_ATTR_PWM_E                  , No_ADC_Channel, TC2_CH0   , TC2_CH0     , EXTERNAL_INT_0    }, // LCD_DATA0
+  { PORTA, 17, PIO_DIGITAL   , PIN_ATTR_PWM_F                  , No_ADC_Channel, TCC1_CH1  , TC2_CH1     , EXTERNAL_INT_1    }, // LCD_DATA1
+  { PORTA, 18, PIO_DIGITAL   , PIN_ATTR_PWM_F                  , No_ADC_Channel, TCC1_CH2  , TC3_CH0     , EXTERNAL_INT_2    }, // LCD_DATA2
+  { PORTA, 19, PIO_DIGITAL   , PIN_ATTR_PWM_F                  , No_ADC_Channel, TCC1_CH3  , TC3_CH1     , EXTERNAL_INT_3    }, // LCD_DATA3
+  { PORTA, 20, PIO_DIGITAL   , PIN_ATTR_PWM_G                  , No_ADC_Channel, TCC0_CH0  , TC0_CH0     , EXTERNAL_INT_4    }, // LCD_DATA4
+  { PORTA, 21, PIO_DIGITAL   , PIN_ATTR_PWM_G                  , No_ADC_Channel, TCC0_CH0  , TC0_CH1     , EXTERNAL_INT_5    }, // LCD_DATA5
+  { PORTA, 22, PIO_DIGITAL   , PIN_ATTR_PWM_G                  , No_ADC_Channel, TCC0_CH2  , TC4_CH0     , EXTERNAL_INT_6    }, // LCD_DATA6
+  { PORTA, 23, PIO_DIGITAL   , PIN_ATTR_PWM_G                  , No_ADC_Channel, TCC0_CH3  , TC4_CH1     , EXTERNAL_INT_7    }, // LCD_DATA7
+
+  // 42..47  QSPI
+  { PORTB, 10, PIO_COM       , PIN_ATTR_NONE                   , No_ADC_Channel, TC5_CH0   , TC5_CH0     , EXTERNAL_INT_10   }, // QSPI_SCK
+  { PORTB, 11, PIO_COM       , PIN_ATTR_NONE                   , No_ADC_Channel, TC5_CH1   , TC5_CH1     , EXTERNAL_INT_11   }, // QSPI_CS
+  { PORTA,  8, PIO_COM       , PIN_ATTR_NONE                   , No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NMI  }, // QSPI_DATA0
+  { PORTA,  9, PIO_COM       , PIN_ATTR_NONE                   , No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_9    }, // QSPI_DATA1
+  { PORTA, 10, PIO_COM       , PIN_ATTR_NONE                   , No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_10   }, // QSPI_DATA2
+  { PORTA, 11, PIO_COM       , PIN_ATTR_NONE                   , No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_11   }, // QSPI_DATA3
+
+  // 48..49  USB
+  { PORTA, 24, PIO_COM       , PIN_ATTR_NONE                   , No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB D-
+  { PORTA, 25, PIO_COM       , PIN_ATTR_NONE                   , No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB D+
+
+  // 50..51
+  { PORTA, 27, PIO_DIGITAL   , PIN_ATTR_NONE                   , No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_11   }, // Speaker shutdown
+  { PORTA, 15, PIO_DIGITAL   , PIN_ATTR_PWM_E                  , No_ADC_Channel, TC3_CH1   , TC3_CH1     , EXTERNAL_INT_15   }, // ESP_RTS
+
+} ;
+
+const void* g_apTCInstances[TCC_INST_NUM+TC_INST_NUM]={ TCC0, TCC1, TCC2, TCC3, TCC4, TC0, TC1, TC2, TC3, TC4, TC5 } ;
+const uint32_t GCLK_CLKCTRL_IDs[TCC_INST_NUM+TC_INST_NUM] = { TCC0_GCLK_ID, TCC1_GCLK_ID, TCC2_GCLK_ID, TCC3_GCLK_ID, TCC4_GCLK_ID, TC0_GCLK_ID, TC1_GCLK_ID, TC2_GCLK_ID, TC3_GCLK_ID, TC4_GCLK_ID, TC5_GCLK_ID } ;
+
+
+// Multi-serial objects instantiation
+SERCOM sercom0( SERCOM0 ) ;
+SERCOM sercom1( SERCOM1 ) ;
+SERCOM sercom2( SERCOM2 ) ;
+SERCOM sercom3( SERCOM3 ) ;
+SERCOM sercom4( SERCOM4 ) ;
+SERCOM sercom5( SERCOM5 ) ;
+
+Uart Serial1( &sercom4, PIN_SERIAL1_RX, PIN_SERIAL1_TX, PAD_SERIAL1_RX, PAD_SERIAL1_TX ) ;
+
+void SERCOM4_0_Handler()
+{
+  Serial1.IrqHandler();
+}
+void SERCOM4_1_Handler()
+{
+  Serial1.IrqHandler();
+}
+void SERCOM4_2_Handler()
+{
+  Serial1.IrqHandler();
+}
+void SERCOM4_3_Handler()
+{
+  Serial1.IrqHandler();
+}
diff --git a/variants/pyportal_m4_titano/variant.h b/variants/pyportal_m4_titano/variant.h
new file mode 100644
index 000000000..3072826fa
--- /dev/null
+++ b/variants/pyportal_m4_titano/variant.h
@@ -0,0 +1,257 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _VARIANT_PYPORTAL_M4_TITANO_
+#define _VARIANT_PYPORTAL_M4_TITANO_
+
+// The definitions here needs a SAMD core >=1.6.10
+#define ARDUINO_SAMD_VARIANT_COMPLIANCE 10610
+
+/*----------------------------------------------------------------------------
+ *        Definitions
+ *----------------------------------------------------------------------------*/
+
+/** Frequency of the board main oscillator */
+#define VARIANT_MAINOSC		(32768ul)
+
+/** Master clock frequency */
+#define VARIANT_MCK        (F_CPU)
+
+#define VARIANT_GCLK0_FREQ (F_CPU)
+#define VARIANT_GCLK1_FREQ (48000000UL)
+#define VARIANT_GCLK2_FREQ (100000000UL)
+
+/*----------------------------------------------------------------------------
+ *        Headers
+ *----------------------------------------------------------------------------*/
+
+#include "WVariant.h"
+
+#ifdef __cplusplus
+#include "SERCOM.h"
+#include "Uart.h"
+#endif // __cplusplus
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif // __cplusplus
+
+/*----------------------------------------------------------------------------
+ *        Pins
+ *----------------------------------------------------------------------------*/
+
+// Number of pins defined in PinDescription array
+#define PINS_COUNT           (52u)
+#define NUM_DIGITAL_PINS     (42u)
+#define NUM_ANALOG_INPUTS    (9u)
+#define NUM_ANALOG_OUTPUTS   (1u)
+#define analogInputToDigitalPin(p)  ((p < 10u) ? (p) + 14u : -1)
+
+#define digitalPinToPort(P)        ( &(PORT->Group[g_APinDescription[P].ulPort]) )
+#define digitalPinToBitMask(P)     ( 1 << g_APinDescription[P].ulPin )
+//#define analogInPinToBit(P)        ( )
+#define portOutputRegister(port)   ( &(port->OUT.reg) )
+#define portInputRegister(port)    ( &(port->IN.reg) )
+#define portModeRegister(port)     ( &(port->DIR.reg) )
+#define digitalPinHasPWM(P)        ( g_APinDescription[P].ulPWMChannel != NOT_ON_PWM || g_APinDescription[P].ulTCChannel != NOT_ON_TIMER )
+
+/*
+ * digitalPinToTimer(..) is AVR-specific and is not defined for SAMD
+ * architecture. If you need to check if a pin supports PWM you must
+ * use digitalPinHasPWM(..).
+ *
+ * https://github.com/arduino/Arduino/issues/1833
+ */
+// #define digitalPinToTimer(P)
+
+// LEDs
+#define PIN_LED_13           (13u)
+//#define PIN_LED_RXL          (27u)
+//#define PIN_LED_TXL          (28u)
+#define PIN_LED              PIN_LED_13
+//#define PIN_LED2             PIN_LED_RXL
+//#define PIN_LED3             PIN_LED_TXL
+#define LED_BUILTIN          PIN_LED_13
+
+/*
+ * Analog pins
+ */
+#define PIN_A0               (14ul)
+#define PIN_A1               (PIN_A0 + 1)
+#define PIN_A2               (PIN_A0 + 2)
+#define PIN_A3               (PIN_A0 + 3)
+#define PIN_A4               (PIN_A0 + 4)
+#define PIN_A5               (PIN_A0 + 5)
+#define PIN_A6               (PIN_A0 + 6)
+#define PIN_A7               (PIN_A0 + 7)
+#define PIN_A8               (PIN_A0 + 8)
+#define PIN_A9               (PIN_A0 + 9)
+#define PIN_DAC0             PIN_A0
+#define PIN_DAC1             PIN_A1
+
+static const uint8_t A0  = PIN_A0;
+static const uint8_t A1  = PIN_A1;
+static const uint8_t A2  = PIN_A2;
+static const uint8_t A3  = PIN_A3;
+static const uint8_t A4  = PIN_A4;
+static const uint8_t A5  = PIN_A5;
+static const uint8_t A6  = PIN_A6;
+static const uint8_t A7  = PIN_A7;
+static const uint8_t A8  = PIN_A8;
+static const uint8_t A9  = PIN_A9;
+
+static const uint8_t DAC0 = PIN_DAC0;
+
+#define ADC_RESOLUTION		12
+
+// Other pins
+#define PIN_ATN              (39ul)  // ???
+static const uint8_t ATN = PIN_ATN;
+
+/* WiFi interfaces */
+#define SerialNina      Serial1
+#define SPIWIFI         SPI
+#define ESP32_GPIO0     6
+#define ESP32_RESETN    7
+#define SPIWIFI_SS      8
+#define SPIWIFI_ACK     5
+#define SPIWIFI_RESET   7
+#define NINA_GPIO0      ESP32_GPIO0
+#define NINA_RESETN     ESP32_RESETN
+#define NINA_ACK        SPIWIFI_ACK
+#define SerialESP32     Serial1
+
+/*
+ * Serial interfaces
+ */
+
+// Serial1
+#define PIN_SERIAL1_RX       (0ul)
+#define PIN_SERIAL1_TX       (1ul)
+#define PAD_SERIAL1_RX       (SERCOM_RX_PAD_1)
+#define PAD_SERIAL1_TX       (UART_TX_PAD_0)
+
+
+/*
+ * SPI Interfaces
+ */
+#define SPI_INTERFACES_COUNT 1
+
+#define PIN_SPI_MISO         (31u)
+#define PIN_SPI_MOSI         (29u)
+#define PIN_SPI_SCK          (30u)
+#define PERIPH_SPI           sercom2
+#define PAD_SPI_TX           SPI_PAD_0_SCK_1
+#define PAD_SPI_RX           SERCOM_RX_PAD_2
+
+static const uint8_t SS	  = PIN_A2;       // ???
+static const uint8_t MOSI = PIN_SPI_MOSI;
+static const uint8_t MISO = PIN_SPI_MISO;
+static const uint8_t SCK  = PIN_SPI_SCK;
+
+
+/*
+ * Wire Interfaces
+ */
+#define WIRE_INTERFACES_COUNT 1
+
+#define PIN_WIRE_SDA         (27u)
+#define PIN_WIRE_SCL         (28u)
+#define PERIPH_WIRE          sercom5
+#define WIRE_IT_HANDLER      SERCOM5_Handler
+#define WIRE_IT_HANDLER_0    SERCOM5_0_Handler
+#define WIRE_IT_HANDLER_1    SERCOM5_1_Handler
+#define WIRE_IT_HANDLER_2    SERCOM5_2_Handler
+#define WIRE_IT_HANDLER_3    SERCOM5_3_Handler
+
+static const uint8_t SDA = PIN_WIRE_SDA;
+static const uint8_t SCL = PIN_WIRE_SCL;
+
+/*
+ * USB
+ */
+#define PIN_USB_HOST_ENABLE (29ul) // ???
+#define PIN_USB_DM          (48ul)
+#define PIN_USB_DP          (49ul)
+
+// On-board QSPI Flash
+#define EXTERNAL_FLASH_DEVICES   GD25Q64C
+#define EXTERNAL_FLASH_USE_QSPI
+
+//QSPI Pins
+#define PIN_QSPI_SCK	(42u)
+#define PIN_QSPI_CS	(43u)
+#define PIN_QSPI_IO0	(44u)
+#define PIN_QSPI_IO1	(45u)
+#define PIN_QSPI_IO2	(46u)
+#define PIN_QSPI_IO3	(47u)
+
+#if !defined(VARIANT_QSPI_BAUD_DEFAULT)
+  // TODO: meaningful value for this
+  #define VARIANT_QSPI_BAUD_DEFAULT 5000000
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+ *        Arduino objects - C++ only
+ *----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+
+/*	=========================
+ *	===== SERCOM DEFINITION
+ *	=========================
+*/
+extern SERCOM sercom0;
+extern SERCOM sercom1;
+extern SERCOM sercom2;
+extern SERCOM sercom3;
+extern SERCOM sercom4;
+extern SERCOM sercom5;
+
+extern Uart Serial1;
+
+#endif
+
+// These serial port names are intended to allow libraries and architecture-neutral
+// sketches to automatically default to the correct port name for a particular type
+// of use.  For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN,
+// the first hardware serial port whose RX/TX pins are not dedicated to another use.
+//
+// SERIAL_PORT_MONITOR        Port which normally prints to the Arduino Serial Monitor
+//
+// SERIAL_PORT_USBVIRTUAL     Port which is USB virtual serial
+//
+// SERIAL_PORT_LINUXBRIDGE    Port which connects to a Linux system via Bridge library
+//
+// SERIAL_PORT_HARDWARE       Hardware serial port, physical RX & TX pins.
+//
+// SERIAL_PORT_HARDWARE_OPEN  Hardware serial ports which are open for use.  Their RX & TX
+//                            pins are NOT connected to anything by default.
+#define SERIAL_PORT_USBVIRTUAL      Serial
+#define SERIAL_PORT_MONITOR         Serial
+// Serial has no physical pins broken out, so it's not listed as HARDWARE port
+#define SERIAL_PORT_HARDWARE        Serial1
+#define SERIAL_PORT_HARDWARE_OPEN   Serial1
+
+#endif /* _VARIANT_PYPORTAL_M4_TITANO_ */
+
diff --git a/variants/qtpy_m0/debug_scripts/variant.gdb b/variants/qtpy_m0/debug_scripts/variant.gdb
new file mode 100644
index 000000000..13ee2a173
--- /dev/null
+++ b/variants/qtpy_m0/debug_scripts/variant.gdb
@@ -0,0 +1,31 @@
+#
+#  Arduino Zero OpenOCD script.
+#
+#  Copyright (c) 2014-2015 Arduino LLC. All right reserved.
+#
+#  This library is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 2.1 of the License, or (at your option) any later version.
+#
+#  This library is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#  See the GNU Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library; if not, write to the Free Software
+#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#
+
+# Define 'reset' command
+define reset
+
+info reg
+
+break main
+
+# End of 'reset' command
+end
+
+target remote | openocd -c "interface cmsis-dap" -c "set CHIPNAME at91samd21e18" -f target/at91samdXX.cfg -c "gdb_port pipe; log_output openocd.log"
diff --git a/variants/qtpy_m0/linker_scripts/gcc/flash_with_bootloader.ld b/variants/qtpy_m0/linker_scripts/gcc/flash_with_bootloader.ld
new file mode 100644
index 000000000..357946455
--- /dev/null
+++ b/variants/qtpy_m0/linker_scripts/gcc/flash_with_bootloader.ld
@@ -0,0 +1,216 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* Linker script to configure memory regions.
+ * Need modifying for a specific board.
+ *   FLASH.ORIGIN: starting address of flash
+ *   FLASH.LENGTH: length of flash
+ *   RAM.ORIGIN: starting address of RAM bank 0
+ *   RAM.LENGTH: length of RAM bank 0
+ */
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000+0x2000, LENGTH = 0x00040000-0x2000 /* First 8KB used by bootloader */
+  RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ *   Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ *   __exidx_start
+ *   __exidx_end
+ *   __copy_table_start__
+ *   __copy_table_end__
+ *   __zero_table_start__
+ *   __zero_table_end__
+ *   __etext
+ *   __data_start__
+ *   __preinit_array_start
+ *   __preinit_array_end
+ *   __init_array_start
+ *   __init_array_end
+ *   __fini_array_start
+ *   __fini_array_end
+ *   __data_end__
+ *   __bss_start__
+ *   __bss_end__
+ *   __end__
+ *   end
+ *   __HeapLimit
+ *   __StackLimit
+ *   __StackTop
+ *   __stack
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+	.text :
+	{
+		__text_start__ = .;
+
+		KEEP(*(.sketch_boot))
+
+		. = ALIGN(0x2000);
+		KEEP(*(.isr_vector))
+		*(.text*)
+
+		KEEP(*(.init))
+		KEEP(*(.fini))
+
+		/* .ctors */
+		*crtbegin.o(.ctors)
+		*crtbegin?.o(.ctors)
+		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+		*(SORT(.ctors.*))
+		*(.ctors)
+
+		/* .dtors */
+ 		*crtbegin.o(.dtors)
+ 		*crtbegin?.o(.dtors)
+ 		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ 		*(SORT(.dtors.*))
+ 		*(.dtors)
+
+		*(.rodata*)
+
+		KEEP(*(.eh_frame*))
+	} > FLASH
+
+	.ARM.extab :
+	{
+		*(.ARM.extab* .gnu.linkonce.armextab.*)
+	} > FLASH
+
+	__exidx_start = .;
+	.ARM.exidx :
+	{
+		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
+	} > FLASH
+	__exidx_end = .;
+
+	/* To copy multiple ROM to RAM sections,
+	 * uncomment .copy.table section and,
+	 * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.copy.table :
+	{
+		. = ALIGN(4);
+		__copy_table_start__ = .;
+		LONG (__etext)
+		LONG (__data_start__)
+		LONG (__data_end__ - __data_start__)
+		LONG (__etext2)
+		LONG (__data2_start__)
+		LONG (__data2_end__ - __data2_start__)
+		__copy_table_end__ = .;
+	} > FLASH
+	*/
+
+	/* To clear multiple BSS sections,
+	 * uncomment .zero.table section and,
+	 * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.zero.table :
+	{
+		. = ALIGN(4);
+		__zero_table_start__ = .;
+		LONG (__bss_start__)
+		LONG (__bss_end__ - __bss_start__)
+		LONG (__bss2_start__)
+		LONG (__bss2_end__ - __bss2_start__)
+		__zero_table_end__ = .;
+	} > FLASH
+	*/
+
+	__etext = .;
+
+	.data : AT (__etext)
+	{
+		__data_start__ = .;
+		*(vtable)
+		*(.data*)
+
+		. = ALIGN(4);
+		/* preinit data */
+		PROVIDE_HIDDEN (__preinit_array_start = .);
+		KEEP(*(.preinit_array))
+		PROVIDE_HIDDEN (__preinit_array_end = .);
+
+		. = ALIGN(4);
+		/* init data */
+		PROVIDE_HIDDEN (__init_array_start = .);
+		KEEP(*(SORT(.init_array.*)))
+		KEEP(*(.init_array))
+		PROVIDE_HIDDEN (__init_array_end = .);
+
+
+		. = ALIGN(4);
+		/* finit data */
+		PROVIDE_HIDDEN (__fini_array_start = .);
+		KEEP(*(SORT(.fini_array.*)))
+		KEEP(*(.fini_array))
+		PROVIDE_HIDDEN (__fini_array_end = .);
+
+		KEEP(*(.jcr*))
+		. = ALIGN(16);
+		/* All data end */
+		__data_end__ = .;
+
+	} > RAM
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start__ = .;
+		*(.bss*)
+		*(COMMON)
+		. = ALIGN(4);
+		__bss_end__ = .;
+	} > RAM
+
+	.heap (COPY):
+	{
+		__end__ = .;
+		PROVIDE(end = .);
+		*(.heap*)
+		__HeapLimit = .;
+	} > RAM
+
+	/* .stack_dummy section doesn't contains any symbols. It is only
+	 * used for linker to calculate size of stack sections, and assign
+	 * values to stack symbols later */
+	.stack_dummy (COPY):
+	{
+		*(.stack*)
+	} > RAM
+
+	/* Set stack top to end of RAM, and stack limit move down by
+	 * size of stack_dummy section */
+	__StackTop = ORIGIN(RAM) + LENGTH(RAM);
+	__StackLimit = __StackTop - SIZEOF(.stack_dummy);
+	PROVIDE(__stack = __StackTop);
+
+	__ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ;
+
+	/* Check if data + heap + stack exceeds RAM limit */
+	ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
+}
diff --git a/variants/qtpy_m0/linker_scripts/gcc/flash_without_bootloader.ld b/variants/qtpy_m0/linker_scripts/gcc/flash_without_bootloader.ld
new file mode 100644
index 000000000..ebeeee37f
--- /dev/null
+++ b/variants/qtpy_m0/linker_scripts/gcc/flash_without_bootloader.ld
@@ -0,0 +1,214 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* Linker script to configure memory regions.
+ * Need modifying for a specific board.
+ *   FLASH.ORIGIN: starting address of flash
+ *   FLASH.LENGTH: length of flash
+ *   RAM.ORIGIN: starting address of RAM bank 0
+ *   RAM.LENGTH: length of RAM bank 0
+ */
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00040000
+  RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ *   Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ *   __exidx_start
+ *   __exidx_end
+ *   __copy_table_start__
+ *   __copy_table_end__
+ *   __zero_table_start__
+ *   __zero_table_end__
+ *   __etext
+ *   __data_start__
+ *   __preinit_array_start
+ *   __preinit_array_end
+ *   __init_array_start
+ *   __init_array_end
+ *   __fini_array_start
+ *   __fini_array_end
+ *   __data_end__
+ *   __bss_start__
+ *   __bss_end__
+ *   __end__
+ *   end
+ *   __HeapLimit
+ *   __StackLimit
+ *   __StackTop
+ *   __stack
+ *   __ram_end__
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+	.text :
+	{
+		__text_start__ = .;
+
+		KEEP(*(.isr_vector))
+		*(.text*)
+
+		KEEP(*(.init))
+		KEEP(*(.fini))
+
+		/* .ctors */
+		*crtbegin.o(.ctors)
+		*crtbegin?.o(.ctors)
+		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+		*(SORT(.ctors.*))
+		*(.ctors)
+
+		/* .dtors */
+ 		*crtbegin.o(.dtors)
+ 		*crtbegin?.o(.dtors)
+ 		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ 		*(SORT(.dtors.*))
+ 		*(.dtors)
+
+		*(.rodata*)
+
+		KEEP(*(.eh_frame*))
+	} > FLASH
+
+	.ARM.extab :
+	{
+		*(.ARM.extab* .gnu.linkonce.armextab.*)
+	} > FLASH
+
+	__exidx_start = .;
+	.ARM.exidx :
+	{
+		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
+	} > FLASH
+	__exidx_end = .;
+
+	/* To copy multiple ROM to RAM sections,
+	 * uncomment .copy.table section and,
+	 * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.copy.table :
+	{
+		. = ALIGN(4);
+		__copy_table_start__ = .;
+		LONG (__etext)
+		LONG (__data_start__)
+		LONG (__data_end__ - __data_start__)
+		LONG (__etext2)
+		LONG (__data2_start__)
+		LONG (__data2_end__ - __data2_start__)
+		__copy_table_end__ = .;
+	} > FLASH
+	*/
+
+	/* To clear multiple BSS sections,
+	 * uncomment .zero.table section and,
+	 * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.zero.table :
+	{
+		. = ALIGN(4);
+		__zero_table_start__ = .;
+		LONG (__bss_start__)
+		LONG (__bss_end__ - __bss_start__)
+		LONG (__bss2_start__)
+		LONG (__bss2_end__ - __bss2_start__)
+		__zero_table_end__ = .;
+	} > FLASH
+	*/
+
+	__etext = .;
+
+	.data : AT (__etext)
+	{
+		__data_start__ = .;
+		*(vtable)
+		*(.data*)
+
+		. = ALIGN(4);
+		/* preinit data */
+		PROVIDE_HIDDEN (__preinit_array_start = .);
+		KEEP(*(.preinit_array))
+		PROVIDE_HIDDEN (__preinit_array_end = .);
+
+		. = ALIGN(4);
+		/* init data */
+		PROVIDE_HIDDEN (__init_array_start = .);
+		KEEP(*(SORT(.init_array.*)))
+		KEEP(*(.init_array))
+		PROVIDE_HIDDEN (__init_array_end = .);
+
+
+		. = ALIGN(4);
+		/* finit data */
+		PROVIDE_HIDDEN (__fini_array_start = .);
+		KEEP(*(SORT(.fini_array.*)))
+		KEEP(*(.fini_array))
+		PROVIDE_HIDDEN (__fini_array_end = .);
+
+		KEEP(*(.jcr*))
+		. = ALIGN(16);
+		/* All data end */
+		__data_end__ = .;
+
+	} > RAM
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start__ = .;
+		*(.bss*)
+		*(COMMON)
+		. = ALIGN(4);
+		__bss_end__ = .;
+	} > RAM
+
+	.heap (COPY):
+	{
+		__end__ = .;
+		PROVIDE(end = .);
+		*(.heap*)
+		__HeapLimit = .;
+	} > RAM
+
+	/* .stack_dummy section doesn't contains any symbols. It is only
+	 * used for linker to calculate size of stack sections, and assign
+	 * values to stack symbols later */
+	.stack_dummy (COPY):
+	{
+		*(.stack*)
+	} > RAM
+
+	/* Set stack top to end of RAM, and stack limit move down by
+	 * size of stack_dummy section */
+	__StackTop = ORIGIN(RAM) + LENGTH(RAM) ;
+	__StackLimit = __StackTop - SIZEOF(.stack_dummy);
+	PROVIDE(__stack = __StackTop);
+
+	__ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ;
+
+	/* Check if data + heap + stack exceeds RAM limit */
+	ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
+}
diff --git a/variants/qtpy_m0/openocd_scripts/qtpy_m0.cfg b/variants/qtpy_m0/openocd_scripts/qtpy_m0.cfg
new file mode 100644
index 000000000..e4c3f81dc
--- /dev/null
+++ b/variants/qtpy_m0/openocd_scripts/qtpy_m0.cfg
@@ -0,0 +1,28 @@
+#
+#  Adafruit ItsyBitsy M0 OpenOCD script.
+#
+#  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+#
+#  This library is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 2.1 of the License, or (at your option) any later version.
+#
+#  This library is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#  See the GNU Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library; if not, write to the Free Software
+#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#
+
+# chip name
+set CHIPNAME at91samd21e18
+set ENDIAN little
+
+# choose a port here
+set telnet_port 0
+
+source [find target/at91samdXX.cfg]
diff --git a/variants/qtpy_m0/pins_arduino.h b/variants/qtpy_m0/pins_arduino.h
new file mode 100644
index 000000000..db0e40c3d
--- /dev/null
+++ b/variants/qtpy_m0/pins_arduino.h
@@ -0,0 +1,21 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+// API compatibility
+#include "variant.h"
+
diff --git a/variants/qtpy_m0/variant.cpp b/variants/qtpy_m0/variant.cpp
new file mode 100644
index 000000000..af5996a28
--- /dev/null
+++ b/variants/qtpy_m0/variant.cpp
@@ -0,0 +1,86 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "variant.h"
+#include "Arduino.h"
+/*
+ * Pins descriptions
+ */
+const PinDescription g_APinDescription[]=
+{
+  { PORTA,  2, PIO_ANALOG, (PIN_ATTR_DIGITAL|PIN_ATTR_ANALOG|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel0, PWM2_CH0, TCC2_CH0, EXTERNAL_INT_2 }, // A0 / D0 / DAC
+  { PORTA,  3, PIO_ANALOG, (PIN_ATTR_DIGITAL|PIN_ATTR_ANALOG), ADC_Channel1, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_3 }, // A1 / D1 / AREF
+  { PORTA,  4, PIO_ANALOG, (PIN_ATTR_DIGITAL|PIN_ATTR_ANALOG|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel4, PWM0_CH0, TCC0_CH0, EXTERNAL_INT_4 }, // A2 / D2 / PWM
+  { PORTA,  5, PIO_ANALOG, (PIN_ATTR_DIGITAL|PIN_ATTR_ANALOG|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel5, PWM0_CH1, TCC0_CH1, EXTERNAL_INT_5 }, // A3 / D3 / PWM
+
+  // I2C SDA & SCL
+  { PORTA, 16, PIO_SERCOM, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER_ALT), No_ADC_Channel, PWM0_CH6, TCC0_CH6, EXTERNAL_INT_0 }, // D4 / SDA / PWM
+  { PORTA, 17, PIO_SERCOM, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER_ALT), No_ADC_Channel, PWM0_CH7, TCC0_CH7, EXTERNAL_INT_1 }, // D5 / SCL / PWM
+
+  // UART TX & RX
+  { PORTA,  6, PIO_SERCOM_ALT, (PIN_ATTR_DIGITAL|PIN_ATTR_ANALOG|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel6, PWM1_CH0, TCC1_CH0, EXTERNAL_INT_6 }, // A6 / D6 / TX / PWM
+  { PORTA,  7, PIO_SERCOM_ALT, (PIN_ATTR_DIGITAL|PIN_ATTR_ANALOG|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel7, PWM1_CH1, TCC1_CH1, EXTERNAL_INT_7 }, // A7 / D7 / RX / PWM
+
+  // SPI SCK, MISO, MOSI
+  { PORTA, 11, PIO_SERCOM_ALT, (PIN_ATTR_DIGITAL|PIN_ATTR_ANALOG|PIN_ATTR_PWM|PIN_ATTR_TIMER_ALT), ADC_Channel19, PWM0_CH3, TCC0_CH3, EXTERNAL_INT_11 }, // A8 / D8 / SCK / PWM
+  { PORTA,  9, PIO_SERCOM_ALT, (PIN_ATTR_DIGITAL|PIN_ATTR_ANALOG|PIN_ATTR_PWM|PIN_ATTR_TIMER_ALT), ADC_Channel17, PWM1_CH3, TCC1_CH3, EXTERNAL_INT_9 },  // A9 / D9 / MISO / PWM 
+  { PORTA, 10, PIO_SERCOM_ALT, (PIN_ATTR_DIGITAL|PIN_ATTR_ANALOG|PIN_ATTR_PWM|PIN_ATTR_TIMER_ALT), ADC_Channel18, PWM0_CH2, TCC0_CH2, EXTERNAL_INT_10 }, // A10 / D10 / MOSI / PWM
+
+  { PORTA, 18, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 }, // D11 Neopix
+  { PORTA, 15, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_15 }, // D12 Neopix power 
+
+  // D13 fake pin
+  { PORTA, 27, PIO_OUTPUT, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // used as fake output only
+
+  // SPI1 SCK, MISO, MOSI
+  { PORTA, 23, PIO_SERCOM, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER_ALT), No_ADC_Channel, PWM0_CH5, TCC0_CH5, EXTERNAL_INT_7 }, // D14 / SCK1
+  { PORTA, 19, PIO_SERCOM_ALT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM3_CH1, TC3_CH1, EXTERNAL_INT_3 }, // D15 / MISO1
+  { PORTA, 22, PIO_SERCOM, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER_ALT), No_ADC_Channel, PWM0_CH4, TCC0_CH4, EXTERNAL_INT_6 },   // D16 / MOSI1
+  // SPI1 CS
+  { PORTA,  8, PIO_SERCOM_ALT, (PIN_ATTR_DIGITAL|PIN_ATTR_ANALOG|PIN_ATTR_PWM|PIN_ATTR_TIMER_ALT), ADC_Channel16, PWM1_CH2, TCC1_CH2, EXTERNAL_INT_NMI },   // D17 / CS
+
+  // USB pins
+  { PORTA, 28, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB Host enable
+  { PORTA, 24, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB/DM
+  { PORTA, 25, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB/DP
+
+
+} ;
+
+const void* g_apTCInstances[TCC_INST_NUM+TC_INST_NUM]={ TCC0, TCC1, TCC2, TC3, TC4, TC5 } ;
+
+// Multi-serial objects instantiation
+SERCOM sercom0( SERCOM0 ) ;
+SERCOM sercom1( SERCOM1 ) ;
+SERCOM sercom2( SERCOM2 ) ;
+SERCOM sercom3( SERCOM3 ) ;
+
+Uart Serial1( &sercom0, PIN_SERIAL1_RX, PIN_SERIAL1_TX, PAD_SERIAL1_RX, PAD_SERIAL1_TX ) ;
+
+void SERCOM0_Handler()
+{
+  Serial1.IrqHandler();
+}
+
+void initVariant(void) {
+  // special initialization code just for us
+
+  // turn on neopixel
+  pinMode(12, OUTPUT);
+  digitalWrite(12, HIGH);
+}
diff --git a/variants/qtpy_m0/variant.h b/variants/qtpy_m0/variant.h
new file mode 100644
index 000000000..1e4c4e0e1
--- /dev/null
+++ b/variants/qtpy_m0/variant.h
@@ -0,0 +1,234 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _VARIANT_QTPY_ZERO_
+#define _VARIANT_QTPY_ZERO_
+
+// The definitions here needs a SAMD core >=1.6.10
+#define ARDUINO_SAMD_VARIANT_COMPLIANCE 10610
+
+/*----------------------------------------------------------------------------
+ *        Definitions
+ *----------------------------------------------------------------------------*/
+
+/** Frequency of the board main oscillator */
+#define VARIANT_MAINOSC		(32768ul)
+
+/** Master clock frequency */
+#define VARIANT_MCK	(F_CPU)
+
+/*----------------------------------------------------------------------------
+ *        Headers
+ *----------------------------------------------------------------------------*/
+
+#include "WVariant.h"
+
+#ifdef __cplusplus
+#include "SERCOM.h"
+#include "Uart.h"
+#endif // __cplusplus
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif // __cplusplus
+
+/*----------------------------------------------------------------------------
+ *        Pins
+ *----------------------------------------------------------------------------*/
+
+// Number of pins defined in PinDescription array
+#define PINS_COUNT           (21u)
+#define NUM_DIGITAL_PINS     (21u)
+#define NUM_ANALOG_INPUTS    (9u)
+#define NUM_ANALOG_OUTPUTS   (1u)
+#define analogInputToDigitalPin(p)  (p)
+
+#define digitalPinToPort(P)        ( &(PORT->Group[g_APinDescription[P].ulPort]) )
+#define digitalPinToBitMask(P)     ( 1 << g_APinDescription[P].ulPin )
+//#define analogInPinToBit(P)        ( )
+#define portOutputRegister(port)   ( &(port->OUT.reg) )
+#define portInputRegister(port)    ( &(port->IN.reg) )
+#define portModeRegister(port)     ( &(port->DIR.reg) )
+#define digitalPinHasPWM(P)        ( g_APinDescription[P].ulPWMChannel != NOT_ON_PWM || g_APinDescription[P].ulTCChannel != NOT_ON_TIMER )
+
+/*
+ * digitalPinToTimer(..) is AVR-specific and is not defined for SAMD
+ * architecture. If you need to check if a pin supports PWM you must
+ * use digitalPinHasPWM(..).
+ *
+ * https://github.com/arduino/Arduino/issues/1833
+ */
+// #define digitalPinToTimer(P)
+
+// LEDs
+#define PIN_LED_13           (13u)
+#define PIN_LED              PIN_LED_13
+#define LED_BUILTIN          PIN_LED_13
+#define PIN_NEOPIXEL         (11u)
+
+/*
+ * Analog pins
+ */
+#define PIN_A0               (0ul)
+#define PIN_A1               (PIN_A0 + 1)
+#define PIN_A2               (PIN_A0 + 2)
+#define PIN_A3               (PIN_A0 + 3)
+#define PIN_A6               (PIN_A0 + 6)
+#define PIN_A7               (PIN_A0 + 7)
+#define PIN_A8               (PIN_A0 + 8)
+#define PIN_A9               (PIN_A0 + 9)
+#define PIN_A10              (PIN_A0 + 10)
+#define PIN_DAC0             (00ul)
+
+static const uint8_t A0  = PIN_A0;
+static const uint8_t A1  = PIN_A1;
+static const uint8_t A2  = PIN_A2;
+static const uint8_t A3  = PIN_A3;
+static const uint8_t A6  = PIN_A6 ;
+static const uint8_t A7  = PIN_A7 ;
+static const uint8_t A8  = PIN_A8 ;
+static const uint8_t A9  = PIN_A9 ;
+static const uint8_t A10 = PIN_A10 ;
+static const uint8_t DAC0 = PIN_DAC0;
+
+#define ADC_RESOLUTION		12
+
+// On-board SPI Flash
+#define EXTERNAL_FLASH_DEVICES  GD25Q16C
+#define EXTERNAL_FLASH_USE_SPI  SPI1
+#define EXTERNAL_FLASH_USE_CS   SS1
+
+/*
+ * Serial interfaces
+ */
+
+// Serial1
+#define PIN_SERIAL1_TX       (6ul)
+#define PIN_SERIAL1_RX       (7ul)
+#define PAD_SERIAL1_TX       (UART_TX_PAD_2)
+#define PAD_SERIAL1_RX       (SERCOM_RX_PAD_3)
+
+/*
+ * SPI Interfaces
+ */
+#define SPI_INTERFACES_COUNT 2
+
+#define PIN_SPI_SCK          (8u)
+#define PIN_SPI_MISO         (9u)
+#define PIN_SPI_MOSI         (10u)
+#define PERIPH_SPI           sercom2
+#define PAD_SPI_TX           SPI_PAD_2_SCK_3
+#define PAD_SPI_RX           SERCOM_RX_PAD_1
+
+static const uint8_t SS	  = PIN_A0 ;	// unused, just for reference
+static const uint8_t MOSI = PIN_SPI_MOSI ;
+static const uint8_t MISO = PIN_SPI_MISO ;
+static const uint8_t SCK  = PIN_SPI_SCK ;
+
+
+#define PIN_SPI1_SCK          (14u)
+#define PIN_SPI1_MISO         (15u)
+#define PIN_SPI1_MOSI         (16u)
+#define PERIPH_SPI1           sercom3
+#define PAD_SPI1_TX           SPI_PAD_0_SCK_1
+#define PAD_SPI1_RX           SERCOM_RX_PAD_3
+
+static const uint8_t SS1   = 17;
+static const uint8_t MOSI1 = PIN_SPI1_MOSI ;
+static const uint8_t MISO1 = PIN_SPI1_MISO ;
+static const uint8_t SCK1  = PIN_SPI1_SCK ;
+
+/*
+ * Wire Interfaces
+ */
+#define WIRE_INTERFACES_COUNT 1
+
+#define PIN_WIRE_SDA         (4u)
+#define PIN_WIRE_SCL         (5u)
+#define PERIPH_WIRE          sercom1
+#define WIRE_IT_HANDLER      SERCOM1_Handler
+
+static const uint8_t SDA = PIN_WIRE_SDA;
+static const uint8_t SCL = PIN_WIRE_SCL;
+
+/*
+ * USB
+ */
+#define PIN_USB_HOST_ENABLE (18ul)
+#define PIN_USB_DM          (19ul)
+#define PIN_USB_DP          (20ul)
+/*
+ * I2S Interfaces
+ */
+#define I2S_INTERFACES_COUNT 1
+
+#define I2S_DEVICE          0
+#define I2S_CLOCK_GENERATOR 3
+#define PIN_I2S_SD          (A7)
+#define PIN_I2S_SCK         (MOSI)
+#define PIN_I2S_FS          (SCK)
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+ *        Arduino objects - C++ only
+ *----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+
+/*	=========================
+ *	===== SERCOM DEFINITION
+ *	=========================
+*/
+extern SERCOM sercom0;
+extern SERCOM sercom1;
+extern SERCOM sercom2;
+extern SERCOM sercom3;
+extern SERCOM sercom4;
+extern SERCOM sercom5;
+
+extern Uart Serial1;
+
+#endif
+
+// These serial port names are intended to allow libraries and architecture-neutral
+// sketches to automatically default to the correct port name for a particular type
+// of use.  For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN,
+// the first hardware serial port whose RX/TX pins are not dedicated to another use.
+//
+// SERIAL_PORT_MONITOR        Port which normally prints to the Arduino Serial Monitor
+//
+// SERIAL_PORT_USBVIRTUAL     Port which is USB virtual serial
+//
+// SERIAL_PORT_LINUXBRIDGE    Port which connects to a Linux system via Bridge library
+//
+// SERIAL_PORT_HARDWARE       Hardware serial port, physical RX & TX pins.
+//
+// SERIAL_PORT_HARDWARE_OPEN  Hardware serial ports which are open for use.  Their RX & TX
+//                            pins are NOT connected to anything by default.
+#define SERIAL_PORT_USBVIRTUAL      Serial
+#define SERIAL_PORT_MONITOR         Serial
+// Serial has no physical pins broken out, so it's not listed as HARDWARE port
+#define SERIAL_PORT_HARDWARE        Serial1
+#define SERIAL_PORT_HARDWARE_OPEN   Serial1
+
+#endif /* _VARIANT_ARDUINO_ZERO_ */
+
diff --git a/variants/rotarytrinkey_m0/debug_scripts/variant.gdb b/variants/rotarytrinkey_m0/debug_scripts/variant.gdb
new file mode 100644
index 000000000..13ee2a173
--- /dev/null
+++ b/variants/rotarytrinkey_m0/debug_scripts/variant.gdb
@@ -0,0 +1,31 @@
+#
+#  Arduino Zero OpenOCD script.
+#
+#  Copyright (c) 2014-2015 Arduino LLC. All right reserved.
+#
+#  This library is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 2.1 of the License, or (at your option) any later version.
+#
+#  This library is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#  See the GNU Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library; if not, write to the Free Software
+#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#
+
+# Define 'reset' command
+define reset
+
+info reg
+
+break main
+
+# End of 'reset' command
+end
+
+target remote | openocd -c "interface cmsis-dap" -c "set CHIPNAME at91samd21e18" -f target/at91samdXX.cfg -c "gdb_port pipe; log_output openocd.log"
diff --git a/variants/rotarytrinkey_m0/linker_scripts/gcc/flash_with_bootloader.ld b/variants/rotarytrinkey_m0/linker_scripts/gcc/flash_with_bootloader.ld
new file mode 100644
index 000000000..357946455
--- /dev/null
+++ b/variants/rotarytrinkey_m0/linker_scripts/gcc/flash_with_bootloader.ld
@@ -0,0 +1,216 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* Linker script to configure memory regions.
+ * Need modifying for a specific board.
+ *   FLASH.ORIGIN: starting address of flash
+ *   FLASH.LENGTH: length of flash
+ *   RAM.ORIGIN: starting address of RAM bank 0
+ *   RAM.LENGTH: length of RAM bank 0
+ */
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000+0x2000, LENGTH = 0x00040000-0x2000 /* First 8KB used by bootloader */
+  RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ *   Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ *   __exidx_start
+ *   __exidx_end
+ *   __copy_table_start__
+ *   __copy_table_end__
+ *   __zero_table_start__
+ *   __zero_table_end__
+ *   __etext
+ *   __data_start__
+ *   __preinit_array_start
+ *   __preinit_array_end
+ *   __init_array_start
+ *   __init_array_end
+ *   __fini_array_start
+ *   __fini_array_end
+ *   __data_end__
+ *   __bss_start__
+ *   __bss_end__
+ *   __end__
+ *   end
+ *   __HeapLimit
+ *   __StackLimit
+ *   __StackTop
+ *   __stack
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+	.text :
+	{
+		__text_start__ = .;
+
+		KEEP(*(.sketch_boot))
+
+		. = ALIGN(0x2000);
+		KEEP(*(.isr_vector))
+		*(.text*)
+
+		KEEP(*(.init))
+		KEEP(*(.fini))
+
+		/* .ctors */
+		*crtbegin.o(.ctors)
+		*crtbegin?.o(.ctors)
+		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+		*(SORT(.ctors.*))
+		*(.ctors)
+
+		/* .dtors */
+ 		*crtbegin.o(.dtors)
+ 		*crtbegin?.o(.dtors)
+ 		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ 		*(SORT(.dtors.*))
+ 		*(.dtors)
+
+		*(.rodata*)
+
+		KEEP(*(.eh_frame*))
+	} > FLASH
+
+	.ARM.extab :
+	{
+		*(.ARM.extab* .gnu.linkonce.armextab.*)
+	} > FLASH
+
+	__exidx_start = .;
+	.ARM.exidx :
+	{
+		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
+	} > FLASH
+	__exidx_end = .;
+
+	/* To copy multiple ROM to RAM sections,
+	 * uncomment .copy.table section and,
+	 * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.copy.table :
+	{
+		. = ALIGN(4);
+		__copy_table_start__ = .;
+		LONG (__etext)
+		LONG (__data_start__)
+		LONG (__data_end__ - __data_start__)
+		LONG (__etext2)
+		LONG (__data2_start__)
+		LONG (__data2_end__ - __data2_start__)
+		__copy_table_end__ = .;
+	} > FLASH
+	*/
+
+	/* To clear multiple BSS sections,
+	 * uncomment .zero.table section and,
+	 * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.zero.table :
+	{
+		. = ALIGN(4);
+		__zero_table_start__ = .;
+		LONG (__bss_start__)
+		LONG (__bss_end__ - __bss_start__)
+		LONG (__bss2_start__)
+		LONG (__bss2_end__ - __bss2_start__)
+		__zero_table_end__ = .;
+	} > FLASH
+	*/
+
+	__etext = .;
+
+	.data : AT (__etext)
+	{
+		__data_start__ = .;
+		*(vtable)
+		*(.data*)
+
+		. = ALIGN(4);
+		/* preinit data */
+		PROVIDE_HIDDEN (__preinit_array_start = .);
+		KEEP(*(.preinit_array))
+		PROVIDE_HIDDEN (__preinit_array_end = .);
+
+		. = ALIGN(4);
+		/* init data */
+		PROVIDE_HIDDEN (__init_array_start = .);
+		KEEP(*(SORT(.init_array.*)))
+		KEEP(*(.init_array))
+		PROVIDE_HIDDEN (__init_array_end = .);
+
+
+		. = ALIGN(4);
+		/* finit data */
+		PROVIDE_HIDDEN (__fini_array_start = .);
+		KEEP(*(SORT(.fini_array.*)))
+		KEEP(*(.fini_array))
+		PROVIDE_HIDDEN (__fini_array_end = .);
+
+		KEEP(*(.jcr*))
+		. = ALIGN(16);
+		/* All data end */
+		__data_end__ = .;
+
+	} > RAM
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start__ = .;
+		*(.bss*)
+		*(COMMON)
+		. = ALIGN(4);
+		__bss_end__ = .;
+	} > RAM
+
+	.heap (COPY):
+	{
+		__end__ = .;
+		PROVIDE(end = .);
+		*(.heap*)
+		__HeapLimit = .;
+	} > RAM
+
+	/* .stack_dummy section doesn't contains any symbols. It is only
+	 * used for linker to calculate size of stack sections, and assign
+	 * values to stack symbols later */
+	.stack_dummy (COPY):
+	{
+		*(.stack*)
+	} > RAM
+
+	/* Set stack top to end of RAM, and stack limit move down by
+	 * size of stack_dummy section */
+	__StackTop = ORIGIN(RAM) + LENGTH(RAM);
+	__StackLimit = __StackTop - SIZEOF(.stack_dummy);
+	PROVIDE(__stack = __StackTop);
+
+	__ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ;
+
+	/* Check if data + heap + stack exceeds RAM limit */
+	ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
+}
diff --git a/variants/rotarytrinkey_m0/linker_scripts/gcc/flash_without_bootloader.ld b/variants/rotarytrinkey_m0/linker_scripts/gcc/flash_without_bootloader.ld
new file mode 100644
index 000000000..ebeeee37f
--- /dev/null
+++ b/variants/rotarytrinkey_m0/linker_scripts/gcc/flash_without_bootloader.ld
@@ -0,0 +1,214 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* Linker script to configure memory regions.
+ * Need modifying for a specific board.
+ *   FLASH.ORIGIN: starting address of flash
+ *   FLASH.LENGTH: length of flash
+ *   RAM.ORIGIN: starting address of RAM bank 0
+ *   RAM.LENGTH: length of RAM bank 0
+ */
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00040000
+  RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ *   Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ *   __exidx_start
+ *   __exidx_end
+ *   __copy_table_start__
+ *   __copy_table_end__
+ *   __zero_table_start__
+ *   __zero_table_end__
+ *   __etext
+ *   __data_start__
+ *   __preinit_array_start
+ *   __preinit_array_end
+ *   __init_array_start
+ *   __init_array_end
+ *   __fini_array_start
+ *   __fini_array_end
+ *   __data_end__
+ *   __bss_start__
+ *   __bss_end__
+ *   __end__
+ *   end
+ *   __HeapLimit
+ *   __StackLimit
+ *   __StackTop
+ *   __stack
+ *   __ram_end__
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+	.text :
+	{
+		__text_start__ = .;
+
+		KEEP(*(.isr_vector))
+		*(.text*)
+
+		KEEP(*(.init))
+		KEEP(*(.fini))
+
+		/* .ctors */
+		*crtbegin.o(.ctors)
+		*crtbegin?.o(.ctors)
+		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+		*(SORT(.ctors.*))
+		*(.ctors)
+
+		/* .dtors */
+ 		*crtbegin.o(.dtors)
+ 		*crtbegin?.o(.dtors)
+ 		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ 		*(SORT(.dtors.*))
+ 		*(.dtors)
+
+		*(.rodata*)
+
+		KEEP(*(.eh_frame*))
+	} > FLASH
+
+	.ARM.extab :
+	{
+		*(.ARM.extab* .gnu.linkonce.armextab.*)
+	} > FLASH
+
+	__exidx_start = .;
+	.ARM.exidx :
+	{
+		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
+	} > FLASH
+	__exidx_end = .;
+
+	/* To copy multiple ROM to RAM sections,
+	 * uncomment .copy.table section and,
+	 * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.copy.table :
+	{
+		. = ALIGN(4);
+		__copy_table_start__ = .;
+		LONG (__etext)
+		LONG (__data_start__)
+		LONG (__data_end__ - __data_start__)
+		LONG (__etext2)
+		LONG (__data2_start__)
+		LONG (__data2_end__ - __data2_start__)
+		__copy_table_end__ = .;
+	} > FLASH
+	*/
+
+	/* To clear multiple BSS sections,
+	 * uncomment .zero.table section and,
+	 * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.zero.table :
+	{
+		. = ALIGN(4);
+		__zero_table_start__ = .;
+		LONG (__bss_start__)
+		LONG (__bss_end__ - __bss_start__)
+		LONG (__bss2_start__)
+		LONG (__bss2_end__ - __bss2_start__)
+		__zero_table_end__ = .;
+	} > FLASH
+	*/
+
+	__etext = .;
+
+	.data : AT (__etext)
+	{
+		__data_start__ = .;
+		*(vtable)
+		*(.data*)
+
+		. = ALIGN(4);
+		/* preinit data */
+		PROVIDE_HIDDEN (__preinit_array_start = .);
+		KEEP(*(.preinit_array))
+		PROVIDE_HIDDEN (__preinit_array_end = .);
+
+		. = ALIGN(4);
+		/* init data */
+		PROVIDE_HIDDEN (__init_array_start = .);
+		KEEP(*(SORT(.init_array.*)))
+		KEEP(*(.init_array))
+		PROVIDE_HIDDEN (__init_array_end = .);
+
+
+		. = ALIGN(4);
+		/* finit data */
+		PROVIDE_HIDDEN (__fini_array_start = .);
+		KEEP(*(SORT(.fini_array.*)))
+		KEEP(*(.fini_array))
+		PROVIDE_HIDDEN (__fini_array_end = .);
+
+		KEEP(*(.jcr*))
+		. = ALIGN(16);
+		/* All data end */
+		__data_end__ = .;
+
+	} > RAM
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start__ = .;
+		*(.bss*)
+		*(COMMON)
+		. = ALIGN(4);
+		__bss_end__ = .;
+	} > RAM
+
+	.heap (COPY):
+	{
+		__end__ = .;
+		PROVIDE(end = .);
+		*(.heap*)
+		__HeapLimit = .;
+	} > RAM
+
+	/* .stack_dummy section doesn't contains any symbols. It is only
+	 * used for linker to calculate size of stack sections, and assign
+	 * values to stack symbols later */
+	.stack_dummy (COPY):
+	{
+		*(.stack*)
+	} > RAM
+
+	/* Set stack top to end of RAM, and stack limit move down by
+	 * size of stack_dummy section */
+	__StackTop = ORIGIN(RAM) + LENGTH(RAM) ;
+	__StackLimit = __StackTop - SIZEOF(.stack_dummy);
+	PROVIDE(__stack = __StackTop);
+
+	__ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ;
+
+	/* Check if data + heap + stack exceeds RAM limit */
+	ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
+}
diff --git a/variants/rotarytrinkey_m0/openocd_scripts/rotarytrinkey_m0.cfg b/variants/rotarytrinkey_m0/openocd_scripts/rotarytrinkey_m0.cfg
new file mode 100644
index 000000000..e4c3f81dc
--- /dev/null
+++ b/variants/rotarytrinkey_m0/openocd_scripts/rotarytrinkey_m0.cfg
@@ -0,0 +1,28 @@
+#
+#  Adafruit ItsyBitsy M0 OpenOCD script.
+#
+#  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+#
+#  This library is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 2.1 of the License, or (at your option) any later version.
+#
+#  This library is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#  See the GNU Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library; if not, write to the Free Software
+#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#
+
+# chip name
+set CHIPNAME at91samd21e18
+set ENDIAN little
+
+# choose a port here
+set telnet_port 0
+
+source [find target/at91samdXX.cfg]
diff --git a/variants/rotarytrinkey_m0/pins_arduino.h b/variants/rotarytrinkey_m0/pins_arduino.h
new file mode 100644
index 000000000..db0e40c3d
--- /dev/null
+++ b/variants/rotarytrinkey_m0/pins_arduino.h
@@ -0,0 +1,21 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+// API compatibility
+#include "variant.h"
+
diff --git a/variants/rotarytrinkey_m0/variant.cpp b/variants/rotarytrinkey_m0/variant.cpp
new file mode 100644
index 000000000..e3c824ff5
--- /dev/null
+++ b/variants/rotarytrinkey_m0/variant.cpp
@@ -0,0 +1,68 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "variant.h"
+#include "Arduino.h"
+/*
+ * Pins descriptions
+ */
+const PinDescription g_APinDescription[]=
+{
+  // NeoPixel
+  { PORTA,  1, PIO_DIGITAL, (PIN_ATTR_DIGITAL), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_1 },
+
+  // Encoder pin 1
+  { PORTA,  0, PIO_DIGITAL, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel,  PWM2_CH0, TCC2_CH0, EXTERNAL_INT_0 },
+
+  // Encoder pin 2
+  { PORTA,  4, PIO_DIGITAL, (PIN_ATTR_DIGITAL|PIN_ATTR_ANALOG|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel4, PWM0_CH0, TCC0_CH0, EXTERNAL_INT_4 }, 
+
+  // Encoder switch
+  { PORTA, 27, PIO_DIGITAL, (PIN_ATTR_DIGITAL), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_15 }, 
+
+  // Touch pad
+  { PORTA,  6, PIO_DIGITAL, (PIN_ATTR_DIGITAL|PIN_ATTR_ANALOG|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel6, PWM1_CH0, TCC1_CH0, EXTERNAL_INT_6 }, 
+
+  
+  // USB pins
+  { PORTA, 28, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB Host enable
+  { PORTA, 24, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB/DM
+  { PORTA, 25, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB/DP
+
+  // Fake DAC pin just so we can compile stuff
+  { PORTA,  2, PIO_ANALOG, (PIN_ATTR_DIGITAL|PIN_ATTR_ANALOG|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel0, PWM2_CH0, TCC2_CH0, EXTERNAL_INT_2 }, // A0 / D0 / DAC  
+} ;
+
+const void* g_apTCInstances[TCC_INST_NUM+TC_INST_NUM]={ TCC0, TCC1, TCC2, TC3, TC4, TC5 } ;
+
+// Multi-serial objects instantiation
+SERCOM sercom0( SERCOM0 ) ;
+SERCOM sercom1( SERCOM1 ) ;
+SERCOM sercom2( SERCOM2 ) ;
+SERCOM sercom3( SERCOM3 ) ;
+
+/*
+ * Serial interfaces
+
+
+// Serial1
+#define PIN_SERIAL1_TX       (6ul)
+#define PIN_SERIAL1_RX       (7ul)
+#define PAD_SERIAL1_TX       (UART_TX_PAD_2)
+#define PAD_SERIAL1_RX       (SERCOM_RX_PAD_3)
+ */
diff --git a/variants/rotarytrinkey_m0/variant.h b/variants/rotarytrinkey_m0/variant.h
new file mode 100644
index 000000000..8490ee360
--- /dev/null
+++ b/variants/rotarytrinkey_m0/variant.h
@@ -0,0 +1,184 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _VARIANT_ROTARYTRINKEY_ZERO_
+#define _VARIANT_ROTARYTRINKEY_ZERO_
+
+// The definitions here needs a SAMD core >=1.6.10
+#define ARDUINO_SAMD_VARIANT_COMPLIANCE 10610
+
+/*----------------------------------------------------------------------------
+ *        Definitions
+ *----------------------------------------------------------------------------*/
+
+/** Frequency of the board main oscillator */
+#define VARIANT_MAINOSC		(32768ul)
+
+/** Master clock frequency */
+#define VARIANT_MCK	(F_CPU)
+
+/*----------------------------------------------------------------------------
+ *        Headers
+ *----------------------------------------------------------------------------*/
+
+#include "WVariant.h"
+
+#ifdef __cplusplus
+#include "SERCOM.h"
+#include "Uart.h"
+#endif // __cplusplus
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif // __cplusplus
+
+/*----------------------------------------------------------------------------
+ *        Pins
+ *----------------------------------------------------------------------------*/
+
+// Number of pins defined in PinDescription array
+#define PINS_COUNT           (9u)
+#define NUM_DIGITAL_PINS     (5u)
+#define NUM_ANALOG_INPUTS    (2u)
+#define NUM_ANALOG_OUTPUTS   (1u)
+#define analogInputToDigitalPin(p)  (p)
+
+#define digitalPinToPort(P)        ( &(PORT->Group[g_APinDescription[P].ulPort]) )
+#define digitalPinToBitMask(P)     ( 1 << g_APinDescription[P].ulPin )
+//#define analogInPinToBit(P)        ( )
+#define portOutputRegister(port)   ( &(port->OUT.reg) )
+#define portInputRegister(port)    ( &(port->IN.reg) )
+#define portModeRegister(port)     ( &(port->DIR.reg) )
+#define digitalPinHasPWM(P)        ( g_APinDescription[P].ulPWMChannel != NOT_ON_PWM || g_APinDescription[P].ulTCChannel != NOT_ON_TIMER )
+
+/*
+ * digitalPinToTimer(..) is AVR-specific and is not defined for SAMD
+ * architecture. If you need to check if a pin supports PWM you must
+ * use digitalPinHasPWM(..).
+ *
+ * https://github.com/arduino/Arduino/issues/1833
+ */
+// #define digitalPinToTimer(P)
+
+// LEDs
+#define PIN_NEOPIXEL         (0u)
+#define NUM_NEOPIXEL         (1u)
+
+// ENCODER
+#define PIN_ENCODER_A        1
+#define PIN_ENCODER_B        2
+#define PIN_ENCODER_SWITCH   3
+
+#define PIN_TOUCH            4
+
+/*
+ * Analog pins
+ */
+#define PIN_A0               (8ul)
+#define PIN_A1               (2)
+#define PIN_A2               (4)
+#define PIN_DAC0             PIN_A0
+
+static const uint8_t A0  = PIN_A0;
+static const uint8_t A1  = PIN_A1;
+static const uint8_t A2  = PIN_A2;
+
+#define ADC_RESOLUTION		12
+
+
+/*
+ * SPI Interfaces
+ */
+#define SPI_INTERFACES_COUNT 0
+
+/*
+ * Wire Interfaces
+ */
+#define WIRE_INTERFACES_COUNT 0
+
+/*
+ * USB
+ */
+#define PIN_USB_HOST_ENABLE (5ul)
+#define PIN_USB_DM          (6ul)
+#define PIN_USB_DP          (7ul)
+/*
+ * I2S Interfaces
+ */
+#define I2S_INTERFACES_COUNT 0
+
+
+/*
+ * Serial interfaces
+ */
+
+// Serial1
+#define PIN_SERIAL1_TX       (2ul)  // D2 / PA04 / SERCOM 0.0
+#define PIN_SERIAL1_RX       (4ul)  // D2 / PA06 / SERCOM 0.2
+#define PAD_SERIAL1_TX       (UART_TX_PAD_0)
+#define PAD_SERIAL1_RX       (SERCOM_RX_PAD_2)
+
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+ *        Arduino objects - C++ only
+ *----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+
+/*	=========================
+ *	===== SERCOM DEFINITION
+ *	=========================
+*/
+extern SERCOM sercom0;
+extern SERCOM sercom1;
+extern SERCOM sercom2;
+extern SERCOM sercom3;
+extern SERCOM sercom4;
+extern SERCOM sercom5;
+
+
+#endif
+
+// These serial port names are intended to allow libraries and architecture-neutral
+// sketches to automatically default to the correct port name for a particular type
+// of use.  For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN,
+// the first hardware serial port whose RX/TX pins are not dedicated to another use.
+//
+// SERIAL_PORT_MONITOR        Port which normally prints to the Arduino Serial Monitor
+//
+// SERIAL_PORT_USBVIRTUAL     Port which is USB virtual serial
+//
+// SERIAL_PORT_LINUXBRIDGE    Port which connects to a Linux system via Bridge library
+//
+// SERIAL_PORT_HARDWARE       Hardware serial port, physical RX & TX pins.
+//
+// SERIAL_PORT_HARDWARE_OPEN  Hardware serial ports which are open for use.  Their RX & TX
+//                            pins are NOT connected to anything by default.
+#define SERIAL_PORT_USBVIRTUAL      Serial
+#define SERIAL_PORT_MONITOR         Serial
+// Serial has no physical pins broken out, so it's not listed as HARDWARE port
+#define SERIAL_PORT_HARDWARE        Serial1
+#define SERIAL_PORT_HARDWARE_OPEN   Serial1
+
+#endif /* _VARIANT_ARDUINO_ZERO_ */
+
diff --git a/variants/slidetrinkey_m0/debug_scripts/variant.gdb b/variants/slidetrinkey_m0/debug_scripts/variant.gdb
new file mode 100644
index 000000000..13ee2a173
--- /dev/null
+++ b/variants/slidetrinkey_m0/debug_scripts/variant.gdb
@@ -0,0 +1,31 @@
+#
+#  Arduino Zero OpenOCD script.
+#
+#  Copyright (c) 2014-2015 Arduino LLC. All right reserved.
+#
+#  This library is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 2.1 of the License, or (at your option) any later version.
+#
+#  This library is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#  See the GNU Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library; if not, write to the Free Software
+#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#
+
+# Define 'reset' command
+define reset
+
+info reg
+
+break main
+
+# End of 'reset' command
+end
+
+target remote | openocd -c "interface cmsis-dap" -c "set CHIPNAME at91samd21e18" -f target/at91samdXX.cfg -c "gdb_port pipe; log_output openocd.log"
diff --git a/variants/slidetrinkey_m0/linker_scripts/gcc/flash_with_bootloader.ld b/variants/slidetrinkey_m0/linker_scripts/gcc/flash_with_bootloader.ld
new file mode 100644
index 000000000..357946455
--- /dev/null
+++ b/variants/slidetrinkey_m0/linker_scripts/gcc/flash_with_bootloader.ld
@@ -0,0 +1,216 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* Linker script to configure memory regions.
+ * Need modifying for a specific board.
+ *   FLASH.ORIGIN: starting address of flash
+ *   FLASH.LENGTH: length of flash
+ *   RAM.ORIGIN: starting address of RAM bank 0
+ *   RAM.LENGTH: length of RAM bank 0
+ */
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000+0x2000, LENGTH = 0x00040000-0x2000 /* First 8KB used by bootloader */
+  RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ *   Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ *   __exidx_start
+ *   __exidx_end
+ *   __copy_table_start__
+ *   __copy_table_end__
+ *   __zero_table_start__
+ *   __zero_table_end__
+ *   __etext
+ *   __data_start__
+ *   __preinit_array_start
+ *   __preinit_array_end
+ *   __init_array_start
+ *   __init_array_end
+ *   __fini_array_start
+ *   __fini_array_end
+ *   __data_end__
+ *   __bss_start__
+ *   __bss_end__
+ *   __end__
+ *   end
+ *   __HeapLimit
+ *   __StackLimit
+ *   __StackTop
+ *   __stack
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+	.text :
+	{
+		__text_start__ = .;
+
+		KEEP(*(.sketch_boot))
+
+		. = ALIGN(0x2000);
+		KEEP(*(.isr_vector))
+		*(.text*)
+
+		KEEP(*(.init))
+		KEEP(*(.fini))
+
+		/* .ctors */
+		*crtbegin.o(.ctors)
+		*crtbegin?.o(.ctors)
+		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+		*(SORT(.ctors.*))
+		*(.ctors)
+
+		/* .dtors */
+ 		*crtbegin.o(.dtors)
+ 		*crtbegin?.o(.dtors)
+ 		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ 		*(SORT(.dtors.*))
+ 		*(.dtors)
+
+		*(.rodata*)
+
+		KEEP(*(.eh_frame*))
+	} > FLASH
+
+	.ARM.extab :
+	{
+		*(.ARM.extab* .gnu.linkonce.armextab.*)
+	} > FLASH
+
+	__exidx_start = .;
+	.ARM.exidx :
+	{
+		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
+	} > FLASH
+	__exidx_end = .;
+
+	/* To copy multiple ROM to RAM sections,
+	 * uncomment .copy.table section and,
+	 * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.copy.table :
+	{
+		. = ALIGN(4);
+		__copy_table_start__ = .;
+		LONG (__etext)
+		LONG (__data_start__)
+		LONG (__data_end__ - __data_start__)
+		LONG (__etext2)
+		LONG (__data2_start__)
+		LONG (__data2_end__ - __data2_start__)
+		__copy_table_end__ = .;
+	} > FLASH
+	*/
+
+	/* To clear multiple BSS sections,
+	 * uncomment .zero.table section and,
+	 * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.zero.table :
+	{
+		. = ALIGN(4);
+		__zero_table_start__ = .;
+		LONG (__bss_start__)
+		LONG (__bss_end__ - __bss_start__)
+		LONG (__bss2_start__)
+		LONG (__bss2_end__ - __bss2_start__)
+		__zero_table_end__ = .;
+	} > FLASH
+	*/
+
+	__etext = .;
+
+	.data : AT (__etext)
+	{
+		__data_start__ = .;
+		*(vtable)
+		*(.data*)
+
+		. = ALIGN(4);
+		/* preinit data */
+		PROVIDE_HIDDEN (__preinit_array_start = .);
+		KEEP(*(.preinit_array))
+		PROVIDE_HIDDEN (__preinit_array_end = .);
+
+		. = ALIGN(4);
+		/* init data */
+		PROVIDE_HIDDEN (__init_array_start = .);
+		KEEP(*(SORT(.init_array.*)))
+		KEEP(*(.init_array))
+		PROVIDE_HIDDEN (__init_array_end = .);
+
+
+		. = ALIGN(4);
+		/* finit data */
+		PROVIDE_HIDDEN (__fini_array_start = .);
+		KEEP(*(SORT(.fini_array.*)))
+		KEEP(*(.fini_array))
+		PROVIDE_HIDDEN (__fini_array_end = .);
+
+		KEEP(*(.jcr*))
+		. = ALIGN(16);
+		/* All data end */
+		__data_end__ = .;
+
+	} > RAM
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start__ = .;
+		*(.bss*)
+		*(COMMON)
+		. = ALIGN(4);
+		__bss_end__ = .;
+	} > RAM
+
+	.heap (COPY):
+	{
+		__end__ = .;
+		PROVIDE(end = .);
+		*(.heap*)
+		__HeapLimit = .;
+	} > RAM
+
+	/* .stack_dummy section doesn't contains any symbols. It is only
+	 * used for linker to calculate size of stack sections, and assign
+	 * values to stack symbols later */
+	.stack_dummy (COPY):
+	{
+		*(.stack*)
+	} > RAM
+
+	/* Set stack top to end of RAM, and stack limit move down by
+	 * size of stack_dummy section */
+	__StackTop = ORIGIN(RAM) + LENGTH(RAM);
+	__StackLimit = __StackTop - SIZEOF(.stack_dummy);
+	PROVIDE(__stack = __StackTop);
+
+	__ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ;
+
+	/* Check if data + heap + stack exceeds RAM limit */
+	ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
+}
diff --git a/variants/slidetrinkey_m0/linker_scripts/gcc/flash_without_bootloader.ld b/variants/slidetrinkey_m0/linker_scripts/gcc/flash_without_bootloader.ld
new file mode 100644
index 000000000..ebeeee37f
--- /dev/null
+++ b/variants/slidetrinkey_m0/linker_scripts/gcc/flash_without_bootloader.ld
@@ -0,0 +1,214 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* Linker script to configure memory regions.
+ * Need modifying for a specific board.
+ *   FLASH.ORIGIN: starting address of flash
+ *   FLASH.LENGTH: length of flash
+ *   RAM.ORIGIN: starting address of RAM bank 0
+ *   RAM.LENGTH: length of RAM bank 0
+ */
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00040000
+  RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ *   Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ *   __exidx_start
+ *   __exidx_end
+ *   __copy_table_start__
+ *   __copy_table_end__
+ *   __zero_table_start__
+ *   __zero_table_end__
+ *   __etext
+ *   __data_start__
+ *   __preinit_array_start
+ *   __preinit_array_end
+ *   __init_array_start
+ *   __init_array_end
+ *   __fini_array_start
+ *   __fini_array_end
+ *   __data_end__
+ *   __bss_start__
+ *   __bss_end__
+ *   __end__
+ *   end
+ *   __HeapLimit
+ *   __StackLimit
+ *   __StackTop
+ *   __stack
+ *   __ram_end__
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+	.text :
+	{
+		__text_start__ = .;
+
+		KEEP(*(.isr_vector))
+		*(.text*)
+
+		KEEP(*(.init))
+		KEEP(*(.fini))
+
+		/* .ctors */
+		*crtbegin.o(.ctors)
+		*crtbegin?.o(.ctors)
+		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+		*(SORT(.ctors.*))
+		*(.ctors)
+
+		/* .dtors */
+ 		*crtbegin.o(.dtors)
+ 		*crtbegin?.o(.dtors)
+ 		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ 		*(SORT(.dtors.*))
+ 		*(.dtors)
+
+		*(.rodata*)
+
+		KEEP(*(.eh_frame*))
+	} > FLASH
+
+	.ARM.extab :
+	{
+		*(.ARM.extab* .gnu.linkonce.armextab.*)
+	} > FLASH
+
+	__exidx_start = .;
+	.ARM.exidx :
+	{
+		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
+	} > FLASH
+	__exidx_end = .;
+
+	/* To copy multiple ROM to RAM sections,
+	 * uncomment .copy.table section and,
+	 * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.copy.table :
+	{
+		. = ALIGN(4);
+		__copy_table_start__ = .;
+		LONG (__etext)
+		LONG (__data_start__)
+		LONG (__data_end__ - __data_start__)
+		LONG (__etext2)
+		LONG (__data2_start__)
+		LONG (__data2_end__ - __data2_start__)
+		__copy_table_end__ = .;
+	} > FLASH
+	*/
+
+	/* To clear multiple BSS sections,
+	 * uncomment .zero.table section and,
+	 * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.zero.table :
+	{
+		. = ALIGN(4);
+		__zero_table_start__ = .;
+		LONG (__bss_start__)
+		LONG (__bss_end__ - __bss_start__)
+		LONG (__bss2_start__)
+		LONG (__bss2_end__ - __bss2_start__)
+		__zero_table_end__ = .;
+	} > FLASH
+	*/
+
+	__etext = .;
+
+	.data : AT (__etext)
+	{
+		__data_start__ = .;
+		*(vtable)
+		*(.data*)
+
+		. = ALIGN(4);
+		/* preinit data */
+		PROVIDE_HIDDEN (__preinit_array_start = .);
+		KEEP(*(.preinit_array))
+		PROVIDE_HIDDEN (__preinit_array_end = .);
+
+		. = ALIGN(4);
+		/* init data */
+		PROVIDE_HIDDEN (__init_array_start = .);
+		KEEP(*(SORT(.init_array.*)))
+		KEEP(*(.init_array))
+		PROVIDE_HIDDEN (__init_array_end = .);
+
+
+		. = ALIGN(4);
+		/* finit data */
+		PROVIDE_HIDDEN (__fini_array_start = .);
+		KEEP(*(SORT(.fini_array.*)))
+		KEEP(*(.fini_array))
+		PROVIDE_HIDDEN (__fini_array_end = .);
+
+		KEEP(*(.jcr*))
+		. = ALIGN(16);
+		/* All data end */
+		__data_end__ = .;
+
+	} > RAM
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start__ = .;
+		*(.bss*)
+		*(COMMON)
+		. = ALIGN(4);
+		__bss_end__ = .;
+	} > RAM
+
+	.heap (COPY):
+	{
+		__end__ = .;
+		PROVIDE(end = .);
+		*(.heap*)
+		__HeapLimit = .;
+	} > RAM
+
+	/* .stack_dummy section doesn't contains any symbols. It is only
+	 * used for linker to calculate size of stack sections, and assign
+	 * values to stack symbols later */
+	.stack_dummy (COPY):
+	{
+		*(.stack*)
+	} > RAM
+
+	/* Set stack top to end of RAM, and stack limit move down by
+	 * size of stack_dummy section */
+	__StackTop = ORIGIN(RAM) + LENGTH(RAM) ;
+	__StackLimit = __StackTop - SIZEOF(.stack_dummy);
+	PROVIDE(__stack = __StackTop);
+
+	__ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ;
+
+	/* Check if data + heap + stack exceeds RAM limit */
+	ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
+}
diff --git a/variants/slidetrinkey_m0/openocd_scripts/slidetrinkey_m0.cfg b/variants/slidetrinkey_m0/openocd_scripts/slidetrinkey_m0.cfg
new file mode 100644
index 000000000..e4c3f81dc
--- /dev/null
+++ b/variants/slidetrinkey_m0/openocd_scripts/slidetrinkey_m0.cfg
@@ -0,0 +1,28 @@
+#
+#  Adafruit ItsyBitsy M0 OpenOCD script.
+#
+#  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+#
+#  This library is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 2.1 of the License, or (at your option) any later version.
+#
+#  This library is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#  See the GNU Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library; if not, write to the Free Software
+#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#
+
+# chip name
+set CHIPNAME at91samd21e18
+set ENDIAN little
+
+# choose a port here
+set telnet_port 0
+
+source [find target/at91samdXX.cfg]
diff --git a/variants/slidetrinkey_m0/pins_arduino.h b/variants/slidetrinkey_m0/pins_arduino.h
new file mode 100644
index 000000000..db0e40c3d
--- /dev/null
+++ b/variants/slidetrinkey_m0/pins_arduino.h
@@ -0,0 +1,21 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+// API compatibility
+#include "variant.h"
+
diff --git a/variants/slidetrinkey_m0/variant.cpp b/variants/slidetrinkey_m0/variant.cpp
new file mode 100644
index 000000000..88a348db7
--- /dev/null
+++ b/variants/slidetrinkey_m0/variant.cpp
@@ -0,0 +1,48 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "variant.h"
+#include "Arduino.h"
+/*
+ * Pins descriptions
+ */
+const PinDescription g_APinDescription[]=
+{
+  // Potentiometer
+  { PORTA,  2, PIO_ANALOG, (PIN_ATTR_DIGITAL|PIN_ATTR_ANALOG|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel0, PWM2_CH0, TCC2_CH0, EXTERNAL_INT_2 },
+
+  // Touch pad
+  { PORTA,  7, PIO_ANALOG, (PIN_ATTR_DIGITAL|PIN_ATTR_ANALOG|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel7, PWM1_CH1, TCC1_CH1, EXTERNAL_INT_7 },
+
+  // NeoPixel
+  { PORTA,  4, PIO_DIGITAL, (PIN_ATTR_DIGITAL|PIN_ATTR_ANALOG|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel4, PWM0_CH0, TCC0_CH0, EXTERNAL_INT_4 }, 
+
+  // USB pins
+  { PORTA, 28, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB Host enable
+  { PORTA, 24, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB/DM
+  { PORTA, 25, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB/DP
+
+} ;
+
+const void* g_apTCInstances[TCC_INST_NUM+TC_INST_NUM]={ TCC0, TCC1, TCC2, TC3, TC4, TC5 } ;
+
+// Multi-serial objects instantiation
+SERCOM sercom0( SERCOM0 ) ;
+SERCOM sercom1( SERCOM1 ) ;
+SERCOM sercom2( SERCOM2 ) ;
+SERCOM sercom3( SERCOM3 ) ;
diff --git a/variants/slidetrinkey_m0/variant.h b/variants/slidetrinkey_m0/variant.h
new file mode 100644
index 000000000..88b4876f1
--- /dev/null
+++ b/variants/slidetrinkey_m0/variant.h
@@ -0,0 +1,175 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _VARIANT_SLIDETRINKEY_ZERO_
+#define _VARIANT_SLIDETRINKEY_ZERO_
+
+// The definitions here needs a SAMD core >=1.6.10
+#define ARDUINO_SAMD_VARIANT_COMPLIANCE 10610
+
+/*----------------------------------------------------------------------------
+ *        Definitions
+ *----------------------------------------------------------------------------*/
+
+/** Frequency of the board main oscillator */
+#define VARIANT_MAINOSC		(32768ul)
+
+/** Master clock frequency */
+#define VARIANT_MCK	(F_CPU)
+
+/*----------------------------------------------------------------------------
+ *        Headers
+ *----------------------------------------------------------------------------*/
+
+#include "WVariant.h"
+
+#ifdef __cplusplus
+#include "SERCOM.h"
+#include "Uart.h"
+#endif // __cplusplus
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif // __cplusplus
+
+/*----------------------------------------------------------------------------
+ *        Pins
+ *----------------------------------------------------------------------------*/
+
+// Number of pins defined in PinDescription array
+#define PINS_COUNT           (6u)
+#define NUM_DIGITAL_PINS     (3u)
+#define NUM_ANALOG_INPUTS    (3u)
+#define NUM_ANALOG_OUTPUTS   (1u)
+#define analogInputToDigitalPin(p)  (p)
+
+#define digitalPinToPort(P)        ( &(PORT->Group[g_APinDescription[P].ulPort]) )
+#define digitalPinToBitMask(P)     ( 1 << g_APinDescription[P].ulPin )
+//#define analogInPinToBit(P)        ( )
+#define portOutputRegister(port)   ( &(port->OUT.reg) )
+#define portInputRegister(port)    ( &(port->IN.reg) )
+#define portModeRegister(port)     ( &(port->DIR.reg) )
+#define digitalPinHasPWM(P)        ( g_APinDescription[P].ulPWMChannel != NOT_ON_PWM || g_APinDescription[P].ulTCChannel != NOT_ON_TIMER )
+
+/*
+ * digitalPinToTimer(..) is AVR-specific and is not defined for SAMD
+ * architecture. If you need to check if a pin supports PWM you must
+ * use digitalPinHasPWM(..).
+ *
+ * https://github.com/arduino/Arduino/issues/1833
+ */
+// #define digitalPinToTimer(P)
+
+// LEDs
+#define PIN_NEOPIXEL         (2u)
+#define NUM_NEOPIXEL         (2u)
+
+// POT
+#define PIN_POTENTIOMETER    (0u)
+#define PIN_TOUCH            (1u)
+
+/*
+ * Analog pins
+ */
+#define PIN_A0               (0ul)
+#define PIN_A1               (1ul)
+#define PIN_A2               (2ul)
+#define PIN_DAC0             PIN_A0
+
+static const uint8_t A0  = PIN_A0;
+static const uint8_t A1  = PIN_A1;
+static const uint8_t A2  = PIN_A2;
+
+#define ADC_RESOLUTION		12
+
+
+/*
+ * SPI Interfaces
+ */
+#define SPI_INTERFACES_COUNT 0
+
+/*
+ * Wire Interfaces
+ */
+#define WIRE_INTERFACES_COUNT 0
+
+/*
+ * USB
+ */
+#define PIN_USB_HOST_ENABLE (3ul)
+#define PIN_USB_DM          (4ul)
+#define PIN_USB_DP          (5ul)
+/*
+ * I2S Interfaces
+ */
+#define I2S_INTERFACES_COUNT 0
+
+
+/*
+ * Serial interfaces
+ */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+ *        Arduino objects - C++ only
+ *----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+
+/*	=========================
+ *	===== SERCOM DEFINITION
+ *	=========================
+*/
+extern SERCOM sercom0;
+extern SERCOM sercom1;
+extern SERCOM sercom2;
+extern SERCOM sercom3;
+extern SERCOM sercom4;
+extern SERCOM sercom5;
+
+
+#endif
+
+// These serial port names are intended to allow libraries and architecture-neutral
+// sketches to automatically default to the correct port name for a particular type
+// of use.  For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN,
+// the first hardware serial port whose RX/TX pins are not dedicated to another use.
+//
+// SERIAL_PORT_MONITOR        Port which normally prints to the Arduino Serial Monitor
+//
+// SERIAL_PORT_USBVIRTUAL     Port which is USB virtual serial
+//
+// SERIAL_PORT_LINUXBRIDGE    Port which connects to a Linux system via Bridge library
+//
+// SERIAL_PORT_HARDWARE       Hardware serial port, physical RX & TX pins.
+//
+// SERIAL_PORT_HARDWARE_OPEN  Hardware serial ports which are open for use.  Their RX & TX
+//                            pins are NOT connected to anything by default.
+#define SERIAL_PORT_USBVIRTUAL      Serial
+#define SERIAL_PORT_MONITOR         Serial
+// Serial has no physical pins broken out, so it's not listed as HARDWARE port
+#define SERIAL_PORT_HARDWARE        Serial1
+#define SERIAL_PORT_HARDWARE_OPEN   Serial1
+
+#endif /* _VARIANT_ARDUINO_ZERO_ */
+
diff --git a/variants/trellis_m4/linker_scripts/gcc/flash_with_bootloader.ld b/variants/trellis_m4/linker_scripts/gcc/flash_with_bootloader.ld
new file mode 100644
index 000000000..5fe575a0d
--- /dev/null
+++ b/variants/trellis_m4/linker_scripts/gcc/flash_with_bootloader.ld
@@ -0,0 +1,216 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* Linker script to configure memory regions.
+ * Need modifying for a specific board.
+ *   FLASH.ORIGIN: starting address of flash
+ *   FLASH.LENGTH: length of flash
+ *   RAM.ORIGIN: starting address of RAM bank 0
+ *   RAM.LENGTH: length of RAM bank 0
+ */
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000+0x4000, LENGTH = 0x80000-0x4000 /* First 16KB used by bootloader */
+  RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x30000
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ *   Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ *   __exidx_start
+ *   __exidx_end
+ *   __copy_table_start__
+ *   __copy_table_end__
+ *   __zero_table_start__
+ *   __zero_table_end__
+ *   __etext
+ *   __data_start__
+ *   __preinit_array_start
+ *   __preinit_array_end
+ *   __init_array_start
+ *   __init_array_end
+ *   __fini_array_start
+ *   __fini_array_end
+ *   __data_end__
+ *   __bss_start__
+ *   __bss_end__
+ *   __end__
+ *   end
+ *   __HeapLimit
+ *   __StackLimit
+ *   __StackTop
+ *   __stack
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+	.text :
+	{
+		__text_start__ = .;
+
+		KEEP(*(.sketch_boot))
+
+		. = ALIGN(0x4000);
+		KEEP(*(.isr_vector))
+		*(.text*)
+
+		KEEP(*(.init))
+		KEEP(*(.fini))
+
+		/* .ctors */
+		*crtbegin.o(.ctors)
+		*crtbegin?.o(.ctors)
+		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+		*(SORT(.ctors.*))
+		*(.ctors)
+
+		/* .dtors */
+ 		*crtbegin.o(.dtors)
+ 		*crtbegin?.o(.dtors)
+ 		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ 		*(SORT(.dtors.*))
+ 		*(.dtors)
+
+		*(.rodata*)
+
+		KEEP(*(.eh_frame*))
+	} > FLASH
+
+	.ARM.extab :
+	{
+		*(.ARM.extab* .gnu.linkonce.armextab.*)
+	} > FLASH
+
+	__exidx_start = .;
+	.ARM.exidx :
+	{
+		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
+	} > FLASH
+	__exidx_end = .;
+
+	/* To copy multiple ROM to RAM sections,
+	 * uncomment .copy.table section and,
+	 * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.copy.table :
+	{
+		. = ALIGN(4);
+		__copy_table_start__ = .;
+		LONG (__etext)
+		LONG (__data_start__)
+		LONG (__data_end__ - __data_start__)
+		LONG (__etext2)
+		LONG (__data2_start__)
+		LONG (__data2_end__ - __data2_start__)
+		__copy_table_end__ = .;
+	} > FLASH
+	*/
+
+	/* To clear multiple BSS sections,
+	 * uncomment .zero.table section and,
+	 * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.zero.table :
+	{
+		. = ALIGN(4);
+		__zero_table_start__ = .;
+		LONG (__bss_start__)
+		LONG (__bss_end__ - __bss_start__)
+		LONG (__bss2_start__)
+		LONG (__bss2_end__ - __bss2_start__)
+		__zero_table_end__ = .;
+	} > FLASH
+	*/
+
+	__etext = .;
+
+	.data : AT (__etext)
+	{
+		__data_start__ = .;
+		*(vtable)
+		*(.data*)
+
+		. = ALIGN(4);
+		/* preinit data */
+		PROVIDE_HIDDEN (__preinit_array_start = .);
+		KEEP(*(.preinit_array))
+		PROVIDE_HIDDEN (__preinit_array_end = .);
+
+		. = ALIGN(4);
+		/* init data */
+		PROVIDE_HIDDEN (__init_array_start = .);
+		KEEP(*(SORT(.init_array.*)))
+		KEEP(*(.init_array))
+		PROVIDE_HIDDEN (__init_array_end = .);
+
+
+		. = ALIGN(4);
+		/* finit data */
+		PROVIDE_HIDDEN (__fini_array_start = .);
+		KEEP(*(SORT(.fini_array.*)))
+		KEEP(*(.fini_array))
+		PROVIDE_HIDDEN (__fini_array_end = .);
+
+		KEEP(*(.jcr*))
+		. = ALIGN(16);
+		/* All data end */
+		__data_end__ = .;
+
+	} > RAM
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start__ = .;
+		*(.bss*)
+		*(COMMON)
+		. = ALIGN(4);
+		__bss_end__ = .;
+	} > RAM
+
+	.heap (COPY):
+	{
+		__end__ = .;
+		PROVIDE(end = .);
+		*(.heap*)
+		__HeapLimit = .;
+	} > RAM
+
+	/* .stack_dummy section doesn't contains any symbols. It is only
+	 * used for linker to calculate size of stack sections, and assign
+	 * values to stack symbols later */
+	.stack_dummy (COPY):
+	{
+		*(.stack*)
+	} > RAM
+
+	/* Set stack top to end of RAM, and stack limit move down by
+	 * size of stack_dummy section */
+	__StackTop = ORIGIN(RAM) + LENGTH(RAM);
+	__StackLimit = __StackTop - SIZEOF(.stack_dummy);
+	PROVIDE(__stack = __StackTop);
+
+	__ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ;
+
+	/* Check if data + heap + stack exceeds RAM limit */
+	ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
+}
diff --git a/variants/trellis_m4/linker_scripts/gcc/flash_without_bootloader.ld b/variants/trellis_m4/linker_scripts/gcc/flash_without_bootloader.ld
new file mode 100644
index 000000000..0123a0a23
--- /dev/null
+++ b/variants/trellis_m4/linker_scripts/gcc/flash_without_bootloader.ld
@@ -0,0 +1,215 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* Linker script to configure memory regions.
+ * Need modifying for a specific board.
+ *   FLASH.ORIGIN: starting address of flash
+ *   FLASH.LENGTH: length of flash
+ *   RAM.ORIGIN: starting address of RAM bank 0
+ *   RAM.LENGTH: length of RAM bank 0
+ */
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x80000
+  RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x30000
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ *   Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ *   __exidx_start
+ *   __exidx_end
+ *   __copy_table_start__
+ *   __copy_table_end__
+ *   __zero_table_start__
+ *   __zero_table_end__
+ *   __etext
+ *   __data_start__
+ *   __preinit_array_start
+ *   __preinit_array_end
+ *   __init_array_start
+ *   __init_array_end
+ *   __fini_array_start
+ *   __fini_array_end
+ *   __data_end__
+ *   __bss_start__
+ *   __bss_end__
+ *   __end__
+ *   end
+ *   __HeapLimit
+ *   __StackLimit
+ *   __StackTop
+ *   __stack
+ *   __ram_end__
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+	.text :
+	{
+		__text_start__ = .;
+
+		. = ALIGN(4);
+		KEEP(*(.isr_vector))
+		*(.text*)
+
+		KEEP(*(.init))
+		KEEP(*(.fini))
+
+		/* .ctors */
+		*crtbegin.o(.ctors)
+		*crtbegin?.o(.ctors)
+		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+		*(SORT(.ctors.*))
+		*(.ctors)
+
+		/* .dtors */
+ 		*crtbegin.o(.dtors)
+ 		*crtbegin?.o(.dtors)
+ 		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ 		*(SORT(.dtors.*))
+ 		*(.dtors)
+
+		*(.rodata*)
+
+		KEEP(*(.eh_frame*))
+	} > FLASH
+
+	.ARM.extab :
+	{
+		*(.ARM.extab* .gnu.linkonce.armextab.*)
+	} > FLASH
+
+	__exidx_start = .;
+	.ARM.exidx :
+	{
+		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
+	} > FLASH
+	__exidx_end = .;
+
+	/* To copy multiple ROM to RAM sections,
+	 * uncomment .copy.table section and,
+	 * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.copy.table :
+	{
+		. = ALIGN(4);
+		__copy_table_start__ = .;
+		LONG (__etext)
+		LONG (__data_start__)
+		LONG (__data_end__ - __data_start__)
+		LONG (__etext2)
+		LONG (__data2_start__)
+		LONG (__data2_end__ - __data2_start__)
+		__copy_table_end__ = .;
+	} > FLASH
+	*/
+
+	/* To clear multiple BSS sections,
+	 * uncomment .zero.table section and,
+	 * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.zero.table :
+	{
+		. = ALIGN(4);
+		__zero_table_start__ = .;
+		LONG (__bss_start__)
+		LONG (__bss_end__ - __bss_start__)
+		LONG (__bss2_start__)
+		LONG (__bss2_end__ - __bss2_start__)
+		__zero_table_end__ = .;
+	} > FLASH
+	*/
+
+	__etext = .;
+
+	.data : AT (__etext)
+	{
+		__data_start__ = .;
+		*(vtable)
+		*(.data*)
+
+		. = ALIGN(4);
+		/* preinit data */
+		PROVIDE_HIDDEN (__preinit_array_start = .);
+		KEEP(*(.preinit_array))
+		PROVIDE_HIDDEN (__preinit_array_end = .);
+
+		. = ALIGN(4);
+		/* init data */
+		PROVIDE_HIDDEN (__init_array_start = .);
+		KEEP(*(SORT(.init_array.*)))
+		KEEP(*(.init_array))
+		PROVIDE_HIDDEN (__init_array_end = .);
+
+
+		. = ALIGN(4);
+		/* finit data */
+		PROVIDE_HIDDEN (__fini_array_start = .);
+		KEEP(*(SORT(.fini_array.*)))
+		KEEP(*(.fini_array))
+		PROVIDE_HIDDEN (__fini_array_end = .);
+
+		KEEP(*(.jcr*))
+		. = ALIGN(16);
+		/* All data end */
+		__data_end__ = .;
+
+	} > RAM
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start__ = .;
+		*(.bss*)
+		*(COMMON)
+		. = ALIGN(4);
+		__bss_end__ = .;
+	} > RAM
+
+	.heap (COPY):
+	{
+		__end__ = .;
+		PROVIDE(end = .);
+		*(.heap*)
+		__HeapLimit = .;
+	} > RAM
+
+	/* .stack_dummy section doesn't contains any symbols. It is only
+	 * used for linker to calculate size of stack sections, and assign
+	 * values to stack symbols later */
+	.stack_dummy (COPY):
+	{
+		*(.stack*)
+	} > RAM
+
+	/* Set stack top to end of RAM, and stack limit move down by
+	 * size of stack_dummy section */
+	__StackTop = ORIGIN(RAM) + LENGTH(RAM) ;
+	__StackLimit = __StackTop - SIZEOF(.stack_dummy);
+	PROVIDE(__stack = __StackTop);
+
+	__ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ;
+
+	/* Check if data + heap + stack exceeds RAM limit */
+	ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
+}
diff --git a/variants/trellis_m4/pins_arduino.h b/variants/trellis_m4/pins_arduino.h
new file mode 100644
index 000000000..db0e40c3d
--- /dev/null
+++ b/variants/trellis_m4/pins_arduino.h
@@ -0,0 +1,21 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+// API compatibility
+#include "variant.h"
+
diff --git a/variants/trellis_m4/variant.cpp b/variants/trellis_m4/variant.cpp
new file mode 100644
index 000000000..cbe7be633
--- /dev/null
+++ b/variants/trellis_m4/variant.cpp
@@ -0,0 +1,130 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "variant.h"
+
+/*
+ * Pins descriptions
+ */
+const PinDescription g_APinDescription[]=
+{
+  // 0..13 - Digital pins
+  // ----------------------
+  // 0/1 - SERCOM/UART (Serial1)
+  { PORTA,  12, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_12 }, // SERCOM 2.0
+  { PORTA,  13, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_13 }, // SERCOM 2.1
+
+  // 2..9 - columns
+  { PORTA,  14, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_14 },    // D2 COL0
+  { PORTA,  15, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_15 },    // D3 COL1
+  { PORTA,  16, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_0 }, // D4 COL2
+  { PORTA,  17, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_1 }, // D5 COL3
+  { PORTA,  20, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_4 }, // D6 COL4
+  { PORTA,  21, PIO_SERCOM_ALT, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_5 }, // D7 COL5
+  { PORTA,  22, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_6 }, // D8 COL6
+  { PORTA,  23, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_7 }, // D9 COL7
+
+  // NeoPixel #10
+  { PORTA,   27, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_7 },  // D10
+
+  // 11 & 12 - dotstar clock + data
+  { PORTA,  0, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_0 }, // MOSI SERCOM 1.0
+  { PORTA,  1, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_1 }, // SCK  SERCOM 1.1
+
+  // 13 (LED)
+  { PORTB, 02, PIO_DIGITAL, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_11 }, // unconnected
+
+  // 14..17 - rows
+  { PORTA,  18, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 },
+  { PORTA,  19, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_3 },
+  { PORTB,  22, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_6 },
+  { PORTB,  23, PIO_DIGITAL, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_7 },     // MISO SERCOM 1.3
+
+  // 18 - IRQ
+  { PORTA,  4, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel4, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_4 },
+
+  // 19..20 - USB
+  // --------------------
+  { PORTA, 24, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_8 }, // USB/DM
+  { PORTA, 25, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_9 }, // USB/DP
+
+  // 21..22 I2C pins (SDA/SCL) or Serial1 Pins
+  // ----------------------
+  { PORTB,  8, PIO_SERCOM_ALT, PIN_ATTR_ANALOG, ADC_Channel2, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_8 }, // SERCOM 4.0
+  { PORTB,  9, PIO_SERCOM_ALT, PIN_ATTR_ANALOG_ALT, ADC_Channel1, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_9 }, // SERCOM 4.1
+
+  // ----------------------
+  // 23 - 28 QSPI (SCK, CS, IO0, IO1, IO2, IO3)
+  { PORTB, 10, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_10 },
+  { PORTB, 11, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_11 },
+  { PORTA, 8, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NMI },
+  { PORTA, 9, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_9 },
+  { PORTA, 10, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_10 },
+  { PORTA, 11, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_11 },
+
+  // 29..34 - Analog pins
+  // --------------------
+  { PORTA,  2, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel0, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 }, // A0
+  { PORTA,  5, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel5, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_5 }, // A1
+  { PORTA,  6, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel6, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_6 }, // Amp'd Mic
+  { PORTA,  7, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel7, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_7 }, // Raw Mic
+  { PORTB,  8, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel2, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_8 }, // SDA
+  { PORTB,  9, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel3, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_9 }, // SCL
+
+  // 35 - SWCLK
+  { PORTA, 30, PIO_SERCOM_ALT, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_14 },
+  // 36 - SWDIO
+  { PORTA, 31, PIO_SERCOM_ALT, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_15 },
+
+  // Unused
+  { PORTB,  2, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel14, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 },
+  { PORTB,  3, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel15, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_3 }, 
+
+  // AREF tied to 3.3V
+  { PORTA, 3, PIO_ANALOG, PIN_ATTR_ANALOG, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_3 }, // DAC/VREFP
+} ;
+
+const void* g_apTCInstances[TCC_INST_NUM+TC_INST_NUM]={ TCC0, TCC1, TCC2, TC0, TC1, TC2, TC3 } ;
+const uint32_t GCLK_CLKCTRL_IDs[TCC_INST_NUM+TC_INST_NUM] = { TCC0_GCLK_ID, TCC1_GCLK_ID, TCC2_GCLK_ID, TC0_GCLK_ID, TC1_GCLK_ID, TC2_GCLK_ID, TC3_GCLK_ID } ;
+
+// Multi-serial objects instantiation
+SERCOM sercom0( SERCOM0 ) ;
+SERCOM sercom1( SERCOM1 ) ;
+SERCOM sercom2( SERCOM2 ) ;
+SERCOM sercom3( SERCOM3 ) ;
+SERCOM sercom4( SERCOM4 ) ;
+SERCOM sercom5( SERCOM5 ) ;
+
+Uart Serial1( &sercom4, PIN_SERIAL1_RX, PIN_SERIAL1_TX, PAD_SERIAL1_RX, PAD_SERIAL1_TX ) ;
+
+void SERCOM4_0_Handler()
+{
+  Serial1.IrqHandler();
+}
+void SERCOM4_1_Handler()
+{
+  Serial1.IrqHandler();
+}
+void SERCOM4_2_Handler()
+{
+  Serial1.IrqHandler();
+}
+void SERCOM4_3_Handler()
+{
+  Serial1.IrqHandler();
+}
diff --git a/variants/trellis_m4/variant.h b/variants/trellis_m4/variant.h
new file mode 100644
index 000000000..46e66b754
--- /dev/null
+++ b/variants/trellis_m4/variant.h
@@ -0,0 +1,261 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _VARIANT_TRELLIS_M4_
+#define _VARIANT_TRELLIS_M4_
+
+// The definitions here needs a SAMD core >=1.6.10
+#define ARDUINO_SAMD_VARIANT_COMPLIANCE 10610
+
+/*----------------------------------------------------------------------------
+ *        Definitions
+ *----------------------------------------------------------------------------*/
+
+/** Frequency of the board main oscillator */
+#define VARIANT_MAINOSC		(32768ul)
+
+/** Master clock frequency */
+#define VARIANT_MCK        (F_CPU)
+
+#define VARIANT_GCLK0_FREQ (F_CPU)
+#define VARIANT_GCLK1_FREQ (48000000UL)
+#define VARIANT_GCLK2_FREQ (100000000UL)
+
+/*----------------------------------------------------------------------------
+ *        Headers
+ *----------------------------------------------------------------------------*/
+
+#include "WVariant.h"
+
+#ifdef __cplusplus
+#include "SERCOM.h"
+#include "Uart.h"
+#endif // __cplusplus
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif // __cplusplus
+
+/*----------------------------------------------------------------------------
+ *        Pins
+ *----------------------------------------------------------------------------*/
+
+// Number of pins defined in PinDescription array
+#define PINS_COUNT           (32u)
+#define NUM_DIGITAL_PINS     (30u)
+#define NUM_ANALOG_INPUTS    (3u)
+#define NUM_ANALOG_OUTPUTS   (2u)
+#define analogInputToDigitalPin(p)  ((p < NUM_ANALOG_INPUTS) ? (p) + PIN_A0 : -1)
+
+#define digitalPinToPort(P)        ( &(PORT->Group[g_APinDescription[P].ulPort]) )
+#define digitalPinToBitMask(P)     ( 1 << g_APinDescription[P].ulPin )
+//#define analogInPinToBit(P)        ( )
+#define portOutputRegister(port)   ( &(port->OUT.reg) )
+#define portInputRegister(port)    ( &(port->IN.reg) )
+#define portModeRegister(port)     ( &(port->DIR.reg) )
+#define digitalPinHasPWM(P)        ( g_APinDescription[P].ulPWMChannel != NOT_ON_PWM || g_APinDescription[P].ulTCChannel != NOT_ON_TIMER )
+
+/*
+ * digitalPinToTimer(..) is AVR-specific and is not defined for SAMD
+ * architecture. If you need to check if a pin supports PWM you must
+ * use digitalPinHasPWM(..).
+ *
+ * https://github.com/arduino/Arduino/issues/1833
+ */
+// #define digitalPinToTimer(P)
+
+// LEDs
+#define PIN_LED_13           (13u)
+#define PIN_LED              PIN_LED_13
+#define LED_BUILTIN          PIN_LED_13
+
+/*
+ * Analog pins
+ */
+#define PIN_A0               (29ul)
+#define PIN_A1               (PIN_A0 + 1)
+#define PIN_A2               (PIN_A0 + 2)
+#define PIN_A3               (PIN_A0 + 3)
+#define PIN_A4               (PIN_A0 + 4)
+#define PIN_A5               (PIN_A0 + 5)
+
+#define PIN_DAC0             PIN_A0
+#define PIN_DAC1             PIN_A1
+#define PIN_MIC              PIN_A2
+#define PIN_MIC_RAW          PIN_A3
+#define PIN_LINE_LEFT        (21ul)
+#define PIN_LINE_RIGHT       (22ul)
+
+static const uint8_t A0  = PIN_A0;
+static const uint8_t A1  = PIN_A1;
+static const uint8_t A2  = PIN_A2;
+static const uint8_t A3  = PIN_A3;
+static const uint8_t A4  = PIN_A4;
+static const uint8_t A5  = PIN_A5;
+
+static const uint8_t DAC0 = PIN_DAC0;
+static const uint8_t DAC1 = PIN_DAC1;
+
+static const uint8_t MIC_RAW = PIN_MIC_RAW;
+static const uint8_t MIC = PIN_MIC;
+static const uint8_t LINE_LEFT = PIN_LINE_LEFT;
+static const uint8_t LINE_RIGHT = PIN_LINE_RIGHT;
+
+#define ADC_RESOLUTION		12
+
+/*
+ * Serial interfaces
+ */
+
+// Serial1
+#define PIN_SERIAL1_RX       (22ul)
+#define PIN_SERIAL1_TX       (21ul)
+#define PAD_SERIAL1_RX       (SERCOM_RX_PAD_1)
+#define PAD_SERIAL1_TX       (UART_TX_PAD_0)
+
+/*
+ * SPI Interfaces
+ */
+#define SPI_INTERFACES_COUNT     1
+
+#define PIN_SPI_SCK          (9u)   // COL7
+#define PIN_SPI_MOSI         (8u)   // COL6 
+#define PIN_SPI_MISO         (7u)   // COL5
+#define PERIPH_SPI           sercom3
+#define PAD_SPI_TX           SPI_PAD_0_SCK_1
+#define PAD_SPI_RX           SERCOM_RX_PAD_3
+
+static const uint8_t SS	  = PIN_A2 ;	
+static const uint8_t MOSI = PIN_SPI_MOSI ;
+static const uint8_t MISO = PIN_SPI_MISO ;
+static const uint8_t SCK  = PIN_SPI_SCK ;
+
+
+/*
+ * Wire Interfaces
+ */
+#define WIRE_INTERFACES_COUNT 2
+
+#define PIN_WIRE_SDA         (21u)
+#define PIN_WIRE_SCL         (22u)
+#define PERIPH_WIRE          sercom4
+#define WIRE_IT_HANDLER      SERCOM4_Handler
+
+// Sercom interrupt handlers for I2C slave not set; they are used by Serial1
+// #define WIRE_IT_HANDLER_0    SERCOM4_0_Handler
+// #define WIRE_IT_HANDLER_1    SERCOM4_1_Handler
+// #define WIRE_IT_HANDLER_2    SERCOM4_2_Handler
+// #define WIRE_IT_HANDLER_3    SERCOM4_3_Handler
+
+static const uint8_t SDA = PIN_WIRE_SDA;
+static const uint8_t SCL = PIN_WIRE_SCL;
+
+
+#define PIN_WIRE1_SDA         (0u)
+#define PIN_WIRE1_SCL         (1u)
+#define PERIPH_WIRE1          sercom2
+#define WIRE1_IT_HANDLER      SERCOM2_Handler
+#define WIRE1_IT_HANDLER_0    SERCOM2_0_Handler
+#define WIRE1_IT_HANDLER_1    SERCOM2_1_Handler
+#define WIRE1_IT_HANDLER_2    SERCOM2_2_Handler
+#define WIRE1_IT_HANDLER_3    SERCOM2_3_Handler
+
+static const uint8_t SDA1 = PIN_WIRE_SDA;
+static const uint8_t SCL1 = PIN_WIRE_SCL;
+
+/*
+ * USB
+ */
+#define PIN_USB_HOST_ENABLE (13ul)
+#define PIN_USB_DM          (19ul)
+#define PIN_USB_DP          (20ul)
+
+/*
+ * I2S Interfaces
+ */
+#define I2S_INTERFACES_COUNT 0
+
+#define I2S_DEVICE          0
+// no I2S on G19!
+
+// On-board QSPI Flash
+#define EXTERNAL_FLASH_DEVICES   GD25Q64C
+#define EXTERNAL_FLASH_USE_QSPI
+
+//QSPI Pins
+#define PIN_QSPI_SCK	(23u)
+#define PIN_QSPI_CS	(24u)
+#define PIN_QSPI_IO0	(25u)
+#define PIN_QSPI_IO1	(26u)
+#define PIN_QSPI_IO2	(27u)
+#define PIN_QSPI_IO3	(28u)
+
+#if !defined(VARIANT_QSPI_BAUD_DEFAULT)
+  // TODO: meaningful value for this
+  #define VARIANT_QSPI_BAUD_DEFAULT 5000000
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+ *        Arduino objects - C++ only
+ *----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+
+/*	=========================
+ *	===== SERCOM DEFINITION
+ *	=========================
+*/
+extern SERCOM sercom0;
+extern SERCOM sercom1;
+extern SERCOM sercom2;
+extern SERCOM sercom3;
+extern SERCOM sercom4;
+extern SERCOM sercom5;
+
+extern Uart Serial1;
+
+#endif
+
+// These serial port names are intended to allow libraries and architecture-neutral
+// sketches to automatically default to the correct port name for a particular type
+// of use.  For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN,
+// the first hardware serial port whose RX/TX pins are not dedicated to another use.
+//
+// SERIAL_PORT_MONITOR        Port which normally prints to the Arduino Serial Monitor
+//
+// SERIAL_PORT_USBVIRTUAL     Port which is USB virtual serial
+//
+// SERIAL_PORT_LINUXBRIDGE    Port which connects to a Linux system via Bridge library
+//
+// SERIAL_PORT_HARDWARE       Hardware serial port, physical RX & TX pins.
+//
+// SERIAL_PORT_HARDWARE_OPEN  Hardware serial ports which are open for use.  Their RX & TX
+//                            pins are NOT connected to anything by default.
+#define SERIAL_PORT_USBVIRTUAL      Serial
+#define SERIAL_PORT_MONITOR         Serial
+#define SERIAL_PORT_HARDWARE        Serial1
+#define SERIAL_PORT_HARDWARE_OPEN   Serial1
+
+
+#endif /* _VARIANT_TRELLIS_M4_ */
+
diff --git a/variants/trinket_m0/debug_scripts/variant.gdb b/variants/trinket_m0/debug_scripts/variant.gdb
new file mode 100644
index 000000000..3c37ffde2
--- /dev/null
+++ b/variants/trinket_m0/debug_scripts/variant.gdb
@@ -0,0 +1,31 @@
+#
+#  Arduino Zero OpenOCD script.
+#
+#  Copyright (c) 2014-2015 Arduino LLC. All right reserved.
+#
+#  This library is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 2.1 of the License, or (at your option) any later version.
+#
+#  This library is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#  See the GNU Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library; if not, write to the Free Software
+#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#
+
+# Define 'reset' command
+define reset
+
+info reg
+
+break main
+
+# End of 'reset' command
+end
+
+target remote | openocd -c "interface cmsis-dap" -c "set CHIPNAME at91samd21g18" -f target/at91samdXX.cfg -c "gdb_port pipe; log_output openocd.log"
diff --git a/variants/trinket_m0/linker_scripts/gcc/flash_with_bootloader.ld b/variants/trinket_m0/linker_scripts/gcc/flash_with_bootloader.ld
new file mode 100644
index 000000000..4475f9511
--- /dev/null
+++ b/variants/trinket_m0/linker_scripts/gcc/flash_with_bootloader.ld
@@ -0,0 +1,211 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* Linker script to configure memory regions.
+ * Need modifying for a specific board.
+ *   FLASH.ORIGIN: starting address of flash
+ *   FLASH.LENGTH: length of flash
+ *   RAM.ORIGIN: starting address of RAM bank 0
+ *   RAM.LENGTH: length of RAM bank 0
+ */
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000+0x2000, LENGTH = 0x00040000-0x2000 /* First 8KB used by bootloader */
+  RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ *   Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ *   __exidx_start
+ *   __exidx_end
+ *   __copy_table_start__
+ *   __copy_table_end__
+ *   __zero_table_start__
+ *   __zero_table_end__
+ *   __etext
+ *   __data_start__
+ *   __preinit_array_start
+ *   __preinit_array_end
+ *   __init_array_start
+ *   __init_array_end
+ *   __fini_array_start
+ *   __fini_array_end
+ *   __data_end__
+ *   __bss_start__
+ *   __bss_end__
+ *   __end__
+ *   end
+ *   __HeapLimit
+ *   __StackLimit
+ *   __StackTop
+ *   __stack
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+	.text :
+	{
+		KEEP(*(.isr_vector))
+		*(.text*)
+
+		KEEP(*(.init))
+		KEEP(*(.fini))
+
+		/* .ctors */
+		*crtbegin.o(.ctors)
+		*crtbegin?.o(.ctors)
+		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+		*(SORT(.ctors.*))
+		*(.ctors)
+
+		/* .dtors */
+ 		*crtbegin.o(.dtors)
+ 		*crtbegin?.o(.dtors)
+ 		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ 		*(SORT(.dtors.*))
+ 		*(.dtors)
+
+		*(.rodata*)
+
+		KEEP(*(.eh_frame*))
+	} > FLASH
+
+	.ARM.extab :
+	{
+		*(.ARM.extab* .gnu.linkonce.armextab.*)
+	} > FLASH
+
+	__exidx_start = .;
+	.ARM.exidx :
+	{
+		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
+	} > FLASH
+	__exidx_end = .;
+
+	/* To copy multiple ROM to RAM sections,
+	 * uncomment .copy.table section and,
+	 * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.copy.table :
+	{
+		. = ALIGN(4);
+		__copy_table_start__ = .;
+		LONG (__etext)
+		LONG (__data_start__)
+		LONG (__data_end__ - __data_start__)
+		LONG (__etext2)
+		LONG (__data2_start__)
+		LONG (__data2_end__ - __data2_start__)
+		__copy_table_end__ = .;
+	} > FLASH
+	*/
+
+	/* To clear multiple BSS sections,
+	 * uncomment .zero.table section and,
+	 * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.zero.table :
+	{
+		. = ALIGN(4);
+		__zero_table_start__ = .;
+		LONG (__bss_start__)
+		LONG (__bss_end__ - __bss_start__)
+		LONG (__bss2_start__)
+		LONG (__bss2_end__ - __bss2_start__)
+		__zero_table_end__ = .;
+	} > FLASH
+	*/
+
+	__etext = .;
+
+	.data : AT (__etext)
+	{
+		__data_start__ = .;
+		*(vtable)
+		*(.data*)
+
+		. = ALIGN(4);
+		/* preinit data */
+		PROVIDE_HIDDEN (__preinit_array_start = .);
+		KEEP(*(.preinit_array))
+		PROVIDE_HIDDEN (__preinit_array_end = .);
+
+		. = ALIGN(4);
+		/* init data */
+		PROVIDE_HIDDEN (__init_array_start = .);
+		KEEP(*(SORT(.init_array.*)))
+		KEEP(*(.init_array))
+		PROVIDE_HIDDEN (__init_array_end = .);
+
+
+		. = ALIGN(4);
+		/* finit data */
+		PROVIDE_HIDDEN (__fini_array_start = .);
+		KEEP(*(SORT(.fini_array.*)))
+		KEEP(*(.fini_array))
+		PROVIDE_HIDDEN (__fini_array_end = .);
+
+		KEEP(*(.jcr*))
+		. = ALIGN(4);
+		/* All data end */
+		__data_end__ = .;
+
+	} > RAM
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start__ = .;
+		*(.bss*)
+		*(COMMON)
+		. = ALIGN(4);
+		__bss_end__ = .;
+	} > RAM
+
+	.heap (COPY):
+	{
+		__end__ = .;
+		PROVIDE(end = .);
+		*(.heap*)
+		__HeapLimit = .;
+	} > RAM
+
+	/* .stack_dummy section doesn't contains any symbols. It is only
+	 * used for linker to calculate size of stack sections, and assign
+	 * values to stack symbols later */
+	.stack_dummy (COPY):
+	{
+		*(.stack*)
+	} > RAM
+
+	/* Set stack top to end of RAM, and stack limit move down by
+	 * size of stack_dummy section */
+	__StackTop = ORIGIN(RAM) + LENGTH(RAM);
+	__StackLimit = __StackTop - SIZEOF(.stack_dummy);
+	PROVIDE(__stack = __StackTop);
+
+	__ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ;
+
+	/* Check if data + heap + stack exceeds RAM limit */
+	ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
+}
diff --git a/variants/trinket_m0/linker_scripts/gcc/flash_without_bootloader.ld b/variants/trinket_m0/linker_scripts/gcc/flash_without_bootloader.ld
new file mode 100644
index 000000000..0162f0774
--- /dev/null
+++ b/variants/trinket_m0/linker_scripts/gcc/flash_without_bootloader.ld
@@ -0,0 +1,212 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* Linker script to configure memory regions.
+ * Need modifying for a specific board.
+ *   FLASH.ORIGIN: starting address of flash
+ *   FLASH.LENGTH: length of flash
+ *   RAM.ORIGIN: starting address of RAM bank 0
+ *   RAM.LENGTH: length of RAM bank 0
+ */
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00040000
+  RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ *   Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ *   __exidx_start
+ *   __exidx_end
+ *   __copy_table_start__
+ *   __copy_table_end__
+ *   __zero_table_start__
+ *   __zero_table_end__
+ *   __etext
+ *   __data_start__
+ *   __preinit_array_start
+ *   __preinit_array_end
+ *   __init_array_start
+ *   __init_array_end
+ *   __fini_array_start
+ *   __fini_array_end
+ *   __data_end__
+ *   __bss_start__
+ *   __bss_end__
+ *   __end__
+ *   end
+ *   __HeapLimit
+ *   __StackLimit
+ *   __StackTop
+ *   __stack
+ *   __ram_end__
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+	.text :
+	{
+		KEEP(*(.isr_vector))
+		*(.text*)
+
+		KEEP(*(.init))
+		KEEP(*(.fini))
+
+		/* .ctors */
+		*crtbegin.o(.ctors)
+		*crtbegin?.o(.ctors)
+		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+		*(SORT(.ctors.*))
+		*(.ctors)
+
+		/* .dtors */
+ 		*crtbegin.o(.dtors)
+ 		*crtbegin?.o(.dtors)
+ 		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ 		*(SORT(.dtors.*))
+ 		*(.dtors)
+
+		*(.rodata*)
+
+		KEEP(*(.eh_frame*))
+	} > FLASH
+
+	.ARM.extab :
+	{
+		*(.ARM.extab* .gnu.linkonce.armextab.*)
+	} > FLASH
+
+	__exidx_start = .;
+	.ARM.exidx :
+	{
+		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
+	} > FLASH
+	__exidx_end = .;
+
+	/* To copy multiple ROM to RAM sections,
+	 * uncomment .copy.table section and,
+	 * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.copy.table :
+	{
+		. = ALIGN(4);
+		__copy_table_start__ = .;
+		LONG (__etext)
+		LONG (__data_start__)
+		LONG (__data_end__ - __data_start__)
+		LONG (__etext2)
+		LONG (__data2_start__)
+		LONG (__data2_end__ - __data2_start__)
+		__copy_table_end__ = .;
+	} > FLASH
+	*/
+
+	/* To clear multiple BSS sections,
+	 * uncomment .zero.table section and,
+	 * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.zero.table :
+	{
+		. = ALIGN(4);
+		__zero_table_start__ = .;
+		LONG (__bss_start__)
+		LONG (__bss_end__ - __bss_start__)
+		LONG (__bss2_start__)
+		LONG (__bss2_end__ - __bss2_start__)
+		__zero_table_end__ = .;
+	} > FLASH
+	*/
+
+	__etext = .;
+
+	.data : AT (__etext)
+	{
+		__data_start__ = .;
+		*(vtable)
+		*(.data*)
+
+		. = ALIGN(4);
+		/* preinit data */
+		PROVIDE_HIDDEN (__preinit_array_start = .);
+		KEEP(*(.preinit_array))
+		PROVIDE_HIDDEN (__preinit_array_end = .);
+
+		. = ALIGN(4);
+		/* init data */
+		PROVIDE_HIDDEN (__init_array_start = .);
+		KEEP(*(SORT(.init_array.*)))
+		KEEP(*(.init_array))
+		PROVIDE_HIDDEN (__init_array_end = .);
+
+
+		. = ALIGN(4);
+		/* finit data */
+		PROVIDE_HIDDEN (__fini_array_start = .);
+		KEEP(*(SORT(.fini_array.*)))
+		KEEP(*(.fini_array))
+		PROVIDE_HIDDEN (__fini_array_end = .);
+
+		KEEP(*(.jcr*))
+		. = ALIGN(4);
+		/* All data end */
+		__data_end__ = .;
+
+	} > RAM
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start__ = .;
+		*(.bss*)
+		*(COMMON)
+		. = ALIGN(4);
+		__bss_end__ = .;
+	} > RAM
+
+	.heap (COPY):
+	{
+		__end__ = .;
+		PROVIDE(end = .);
+		*(.heap*)
+		__HeapLimit = .;
+	} > RAM
+
+	/* .stack_dummy section doesn't contains any symbols. It is only
+	 * used for linker to calculate size of stack sections, and assign
+	 * values to stack symbols later */
+	.stack_dummy (COPY):
+	{
+		*(.stack*)
+	} > RAM
+
+	/* Set stack top to end of RAM, and stack limit move down by
+	 * size of stack_dummy section */
+	__StackTop = ORIGIN(RAM) + LENGTH(RAM) ;
+	__StackLimit = __StackTop - SIZEOF(.stack_dummy);
+	PROVIDE(__stack = __StackTop);
+
+	__ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ;
+
+	/* Check if data + heap + stack exceeds RAM limit */
+	ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
+}
diff --git a/variants/trinket_m0/openocd_scripts/trinket_m0.cfg b/variants/trinket_m0/openocd_scripts/trinket_m0.cfg
new file mode 100644
index 000000000..f26f25f37
--- /dev/null
+++ b/variants/trinket_m0/openocd_scripts/trinket_m0.cfg
@@ -0,0 +1,28 @@
+#
+#  Adafruit Trinket M0 OpenOCD script.
+#
+#  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+#
+#  This library is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 2.1 of the License, or (at your option) any later version.
+#
+#  This library is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#  See the GNU Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library; if not, write to the Free Software
+#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#
+
+# chip name
+set CHIPNAME at91samd21g18
+set ENDIAN little
+
+# choose a port here
+set telnet_port 0
+
+source [find target/at91samdXX.cfg]
diff --git a/variants/trinket_m0/pins_arduino.h b/variants/trinket_m0/pins_arduino.h
new file mode 100644
index 000000000..db0e40c3d
--- /dev/null
+++ b/variants/trinket_m0/pins_arduino.h
@@ -0,0 +1,21 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+// API compatibility
+#include "variant.h"
+
diff --git a/variants/trinket_m0/variant.cpp b/variants/trinket_m0/variant.cpp
new file mode 100644
index 000000000..5363f8daf
--- /dev/null
+++ b/variants/trinket_m0/variant.cpp
@@ -0,0 +1,103 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "variant.h"
+
+/*
+ * Pins descriptions
+ */
+const PinDescription g_APinDescription[]=
+{
+  // GPIO 0-4 on external pads
+  // D0, ADC, PWM, IRQ, and I2C SDA on sercom2 - no captouch
+  { PORTA,  8, PIO_SERCOM_ALT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel16, PWM0_CH0, TCC0_CH0, EXTERNAL_INT_NMI },  // TCC0/WO[0]
+
+  // D1, ADC, DAC, IRQ, Captouch and general purpose pin - no timer
+  { PORTA,  2, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel0, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 }, // ADC/AIN[0]
+
+  // D2, ADC, PWM, IRQ, and I2C SCL on sercom2 - no captouch
+  { PORTA,  9, PIO_SERCOM_ALT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel17, PWM0_CH1, TCC0_CH1, EXTERNAL_INT_9 }, // TCC0/WO[1]
+
+  // D3, ADC, PWM, IRQ, UART RX, Captouch and general purpose pin
+  { PORTA,  7, PIO_SERCOM_ALT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel7, PWM1_CH1, TCC1_CH1, EXTERNAL_INT_7 }, // TCC1/WO[1]
+
+  // D4, ADC, PWM, IRQ, UART TX, Captouch and general purpose pin
+  { PORTA,  6, PIO_SERCOM_ALT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel6, PWM1_CH0, TCC1_CH0, EXTERNAL_INT_6 }, // TCC1/WO[0]
+
+  // D5, same as D0 but on sercom2 (for SPI sercommin')
+  { PORTA,  8, PIO_SERCOM, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel16, PWM0_CH0, TCC0_CH0, EXTERNAL_INT_NMI },  // TCC0/WO[0]
+  // D6, same as D2 but on sercom2 (for SPI sercommin')
+  { PORTA,  9, PIO_SERCOM, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel17, PWM0_CH1, TCC0_CH1, EXTERNAL_INT_9 }, // TCC0/WO[1]
+
+  // GPIO 7 & 8 - DotStar internal data/clock
+  // ----------------------------------------
+  { PORTA,  0, PIO_DIGITAL, 0, ADC_Channel4, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_0 }, // ADC/AIN[4]
+  { PORTA,  1, PIO_DIGITAL, 0, ADC_Channel5, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_1 }, // ADC/AIN[5]
+
+  // GPIO 9, 10, 11 USB Host enable
+  // ----------------------------
+  { PORTA, 28, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB Host enable - GPIO #5
+  { PORTA, 24, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB/DM - GPIO #6
+  { PORTA, 25, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB/DP - GPIO #7
+
+  // GPIO 12 is a placeholder, same as D13
+  { PORTA, 10, PIO_DIGITAL, (PIN_ATTR_DIGITAL), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_10 }, // TX: SERCOM0/PAD[2]
+
+  // GPIO 13 (LED)
+  { PORTA, 10, PIO_DIGITAL, (PIN_ATTR_DIGITAL), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_10 }, // TX: SERCOM0/PAD[2]
+
+
+  // Digital 14 - 18, Analog A0-A4
+  // A0 same as D1
+  { PORTA,  2, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel0, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 }, // ADC/AIN[0]
+  // A1, same as D2
+  { PORTA,  9, PIO_ANALOG, (PIN_ATTR_ANALOG|PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel17, PWM0_CH1, TCC0_CH1, EXTERNAL_INT_9 }, // TCC0/WO[1]
+  // A2, same as D0
+  { PORTA,  8, PIO_ANALOG, (PIN_ATTR_ANALOG|PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel16, PWM0_CH0, TCC0_CH0, EXTERNAL_INT_NMI },  // TCC0/WO[0]
+  // A3, same as D3
+  { PORTA,  7, PIO_ANALOG, (PIN_ATTR_ANALOG|PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel7, PWM1_CH1, TCC1_CH1, EXTERNAL_INT_7 }, // TCC1/WO[1]
+  // A4, same as D4
+  { PORTA,  6, PIO_ANALOG, (PIN_ATTR_ANALOG|PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel6, PWM1_CH0, TCC1_CH0, EXTERNAL_INT_6 }, // TCC1/WO[0]
+
+
+  // GPIO 19 & 20 (SWCLK & SWDIO)
+  // --------------------------
+  { PORTA, 30, PIO_TIMER, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+  { PORTA, 31, PIO_TIMER, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE },
+
+
+  // Placeholder #21 & 22 for 'txled' and 'rxled'
+  { PORTA, 14, PIO_DIGITAL, (PIN_ATTR_DIGITAL), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_14 },
+  { PORTA, 15, PIO_DIGITAL, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM3_CH1, TC3_CH1, EXTERNAL_INT_15 },
+} ;
+
+const void* g_apTCInstances[TCC_INST_NUM+TC_INST_NUM]={ TCC0, TCC1, TCC2, TC3, TC4, TC5 } ;
+
+// Multi-serial objects instantiation
+SERCOM sercom0( SERCOM0 ) ;
+SERCOM sercom1( SERCOM1 ) ;
+SERCOM sercom2( SERCOM2 ) ;
+SERCOM sercom3( SERCOM3 ) ;
+
+Uart Serial1( &sercom0, PIN_SERIAL1_RX, PIN_SERIAL1_TX, PAD_SERIAL1_RX, PAD_SERIAL1_TX ) ;
+
+void SERCOM0_Handler()
+{
+  Serial1.IrqHandler();
+}
+
diff --git a/variants/trinket_m0/variant.h b/variants/trinket_m0/variant.h
new file mode 100644
index 000000000..f11b1ef09
--- /dev/null
+++ b/variants/trinket_m0/variant.h
@@ -0,0 +1,202 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _VARIANT_ARDUINO_ZERO_
+#define _VARIANT_ARDUINO_ZERO_
+
+// The definitions here needs a SAMD core >=1.6.6
+#define ARDUINO_SAMD_VARIANT_COMPLIANCE 10606
+
+/*----------------------------------------------------------------------------
+ *        Definitions
+ *----------------------------------------------------------------------------*/
+
+/** Frequency of the board main oscillator */
+#define VARIANT_MAINOSC		(32768ul)
+
+/** Master clock frequency */
+#define VARIANT_MCK	(F_CPU)
+
+/*----------------------------------------------------------------------------
+ *        Headers
+ *----------------------------------------------------------------------------*/
+
+#include "WVariant.h"
+
+#ifdef __cplusplus
+#include "SERCOM.h"
+#include "Uart.h"
+#endif // __cplusplus
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif // __cplusplus
+
+/*----------------------------------------------------------------------------
+ *        Pins
+ *----------------------------------------------------------------------------*/
+
+// Number of pins defined in PinDescription array
+#define PINS_COUNT           (22u)
+#define NUM_DIGITAL_PINS     (22u)
+#define NUM_ANALOG_INPUTS    (5u)
+#define NUM_ANALOG_OUTPUTS   (1u)
+#define analogInputToDigitalPin(p)  ((p < 5u) ? (p) + PIN_A0 : -1)
+
+#define digitalPinToPort(P)        ( &(PORT->Group[g_APinDescription[P].ulPort]) )
+#define digitalPinToBitMask(P)     ( 1 << g_APinDescription[P].ulPin )
+//#define analogInPinToBit(P)        ( )
+#define portOutputRegister(port)   ( &(port->OUT.reg) )
+#define portInputRegister(port)    ( &(port->IN.reg) )
+#define portModeRegister(port)     ( &(port->DIR.reg) )
+#define digitalPinHasPWM(P)        ( g_APinDescription[P].ulPWMChannel != NOT_ON_PWM || g_APinDescription[P].ulTCChannel != NOT_ON_TIMER )
+
+/*
+ * digitalPinToTimer(..) is AVR-specific and is not defined for SAMD
+ * architecture. If you need to check if a pin supports PWM you must
+ * use digitalPinHasPWM(..).
+ *
+ * https://github.com/arduino/Arduino/issues/1833
+ */
+// #define digitalPinToTimer(P)
+
+// LEDs
+#define PIN_LED_13           (13u)
+#define PIN_LED_RXL          (21u)
+#define PIN_LED_TXL          (22u)
+#define PIN_LED              PIN_LED_13
+#define PIN_LED2             PIN_LED_RXL
+#define PIN_LED3             PIN_LED_TXL
+#define LED_BUILTIN          PIN_LED_13
+// DotStar LED
+#define INTERNAL_DS_DATA     7
+#define INTERNAL_DS_CLK      8
+
+/*
+ * Analog pins
+ */
+#define PIN_A0               (14ul)
+#define PIN_A1               (PIN_A0 + 1)
+#define PIN_A2               (PIN_A0 + 2)
+#define PIN_A3               (PIN_A0 + 3)
+#define PIN_A4               (PIN_A0 + 4)
+#define PIN_DAC0             PIN_A0
+
+static const uint8_t A0  = PIN_A0;
+static const uint8_t A1  = PIN_A1;
+static const uint8_t A2  = PIN_A2;
+static const uint8_t A3  = PIN_A3;
+static const uint8_t A4  = PIN_A4;
+static const uint8_t DAC0 = PIN_DAC0;
+
+#define ADC_RESOLUTION		12
+
+/*
+ * Serial interfaces
+ */
+
+// Serial1 (sercom 0)
+#define PIN_SERIAL1_RX       (3ul) // PA07
+#define PAD_SERIAL1_RX       (SERCOM_RX_PAD_3)
+#define PIN_SERIAL1_TX       (4ul) // PA06
+#define PAD_SERIAL1_TX       (UART_TX_PAD_2)
+
+/*
+ * SPI Interfaces
+ */
+#define SPI_INTERFACES_COUNT 1 // shared with I2C/UART (can't do both)
+
+#define PIN_SPI_MISO         (6u)  // PA09 same as D2
+#define PIN_SPI_MOSI         (4u)
+#define PIN_SPI_SCK          (3u)
+#define PERIPH_SPI           sercom0
+#define PAD_SPI_TX           SPI_PAD_2_SCK_3
+#define PAD_SPI_RX           SERCOM_RX_PAD_1
+
+static const uint8_t SS	  = 5 ;	// SERCOM0 last PAD is present on 5 but HW SS isn't used. Set here only for reference.
+static const uint8_t MOSI = PIN_SPI_MOSI ;
+static const uint8_t MISO = PIN_SPI_MISO ;
+static const uint8_t SCK  = PIN_SPI_SCK ;
+
+/*
+ * Wire Interfaces
+ */
+#define WIRE_INTERFACES_COUNT 1
+
+#define PIN_WIRE_SDA         (0u)
+#define PIN_WIRE_SCL         (2u)
+#define PERIPH_WIRE          sercom2
+#define WIRE_IT_HANDLER      SERCOM2_Handler
+
+static const uint8_t SDA = PIN_WIRE_SDA;
+static const uint8_t SCL = PIN_WIRE_SCL;
+
+/*
+ * USB
+ */
+#define PIN_USB_HOST_ENABLE (9ul)
+#define PIN_USB_DM          (10ul)
+#define PIN_USB_DP          (11ul)
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+ *        Arduino objects - C++ only
+ *----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+
+/*	=========================
+ *	===== SERCOM DEFINITION
+ *	=========================
+*/
+extern SERCOM sercom0;
+extern SERCOM sercom1;
+extern SERCOM sercom2;
+extern SERCOM sercom3;
+
+extern Uart Serial1;
+
+#endif
+
+// These serial port names are intended to allow libraries and architecture-neutral
+// sketches to automatically default to the correct port name for a particular type
+// of use.  For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN,
+// the first hardware serial port whose RX/TX pins are not dedicated to another use.
+//
+// SERIAL_PORT_MONITOR        Port which normally prints to the Arduino Serial Monitor
+//
+// SERIAL_PORT_USBVIRTUAL     Port which is USB virtual serial
+//
+// SERIAL_PORT_LINUXBRIDGE    Port which connects to a Linux system via Bridge library
+//
+// SERIAL_PORT_HARDWARE       Hardware serial port, physical RX & TX pins.
+//
+// SERIAL_PORT_HARDWARE_OPEN  Hardware serial ports which are open for use.  Their RX & TX
+//                            pins are NOT connected to anything by default.
+#define SERIAL_PORT_USBVIRTUAL      Serial
+#define SERIAL_PORT_MONITOR         Serial
+// Serial has no physical pins broken out, so it's not listed as HARDWARE port
+#define SERIAL_PORT_HARDWARE        Serial1
+#define SERIAL_PORT_HARDWARE_OPEN   Serial1
+
+#endif /* _VARIANT_ARDUINO_ZERO_ */
+
diff --git a/variants/zero_radio/debug_scripts/variant.gdb b/variants/zero_radio/debug_scripts/variant.gdb
new file mode 100644
index 000000000..3c37ffde2
--- /dev/null
+++ b/variants/zero_radio/debug_scripts/variant.gdb
@@ -0,0 +1,31 @@
+#
+#  Arduino Zero OpenOCD script.
+#
+#  Copyright (c) 2014-2015 Arduino LLC. All right reserved.
+#
+#  This library is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 2.1 of the License, or (at your option) any later version.
+#
+#  This library is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#  See the GNU Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library; if not, write to the Free Software
+#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#
+
+# Define 'reset' command
+define reset
+
+info reg
+
+break main
+
+# End of 'reset' command
+end
+
+target remote | openocd -c "interface cmsis-dap" -c "set CHIPNAME at91samd21g18" -f target/at91samdXX.cfg -c "gdb_port pipe; log_output openocd.log"
diff --git a/variants/zero_radio/linker_scripts/gcc/flash_with_bootloader.ld b/variants/zero_radio/linker_scripts/gcc/flash_with_bootloader.ld
new file mode 100644
index 000000000..4475f9511
--- /dev/null
+++ b/variants/zero_radio/linker_scripts/gcc/flash_with_bootloader.ld
@@ -0,0 +1,211 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* Linker script to configure memory regions.
+ * Need modifying for a specific board.
+ *   FLASH.ORIGIN: starting address of flash
+ *   FLASH.LENGTH: length of flash
+ *   RAM.ORIGIN: starting address of RAM bank 0
+ *   RAM.LENGTH: length of RAM bank 0
+ */
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000+0x2000, LENGTH = 0x00040000-0x2000 /* First 8KB used by bootloader */
+  RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ *   Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ *   __exidx_start
+ *   __exidx_end
+ *   __copy_table_start__
+ *   __copy_table_end__
+ *   __zero_table_start__
+ *   __zero_table_end__
+ *   __etext
+ *   __data_start__
+ *   __preinit_array_start
+ *   __preinit_array_end
+ *   __init_array_start
+ *   __init_array_end
+ *   __fini_array_start
+ *   __fini_array_end
+ *   __data_end__
+ *   __bss_start__
+ *   __bss_end__
+ *   __end__
+ *   end
+ *   __HeapLimit
+ *   __StackLimit
+ *   __StackTop
+ *   __stack
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+	.text :
+	{
+		KEEP(*(.isr_vector))
+		*(.text*)
+
+		KEEP(*(.init))
+		KEEP(*(.fini))
+
+		/* .ctors */
+		*crtbegin.o(.ctors)
+		*crtbegin?.o(.ctors)
+		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+		*(SORT(.ctors.*))
+		*(.ctors)
+
+		/* .dtors */
+ 		*crtbegin.o(.dtors)
+ 		*crtbegin?.o(.dtors)
+ 		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ 		*(SORT(.dtors.*))
+ 		*(.dtors)
+
+		*(.rodata*)
+
+		KEEP(*(.eh_frame*))
+	} > FLASH
+
+	.ARM.extab :
+	{
+		*(.ARM.extab* .gnu.linkonce.armextab.*)
+	} > FLASH
+
+	__exidx_start = .;
+	.ARM.exidx :
+	{
+		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
+	} > FLASH
+	__exidx_end = .;
+
+	/* To copy multiple ROM to RAM sections,
+	 * uncomment .copy.table section and,
+	 * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.copy.table :
+	{
+		. = ALIGN(4);
+		__copy_table_start__ = .;
+		LONG (__etext)
+		LONG (__data_start__)
+		LONG (__data_end__ - __data_start__)
+		LONG (__etext2)
+		LONG (__data2_start__)
+		LONG (__data2_end__ - __data2_start__)
+		__copy_table_end__ = .;
+	} > FLASH
+	*/
+
+	/* To clear multiple BSS sections,
+	 * uncomment .zero.table section and,
+	 * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.zero.table :
+	{
+		. = ALIGN(4);
+		__zero_table_start__ = .;
+		LONG (__bss_start__)
+		LONG (__bss_end__ - __bss_start__)
+		LONG (__bss2_start__)
+		LONG (__bss2_end__ - __bss2_start__)
+		__zero_table_end__ = .;
+	} > FLASH
+	*/
+
+	__etext = .;
+
+	.data : AT (__etext)
+	{
+		__data_start__ = .;
+		*(vtable)
+		*(.data*)
+
+		. = ALIGN(4);
+		/* preinit data */
+		PROVIDE_HIDDEN (__preinit_array_start = .);
+		KEEP(*(.preinit_array))
+		PROVIDE_HIDDEN (__preinit_array_end = .);
+
+		. = ALIGN(4);
+		/* init data */
+		PROVIDE_HIDDEN (__init_array_start = .);
+		KEEP(*(SORT(.init_array.*)))
+		KEEP(*(.init_array))
+		PROVIDE_HIDDEN (__init_array_end = .);
+
+
+		. = ALIGN(4);
+		/* finit data */
+		PROVIDE_HIDDEN (__fini_array_start = .);
+		KEEP(*(SORT(.fini_array.*)))
+		KEEP(*(.fini_array))
+		PROVIDE_HIDDEN (__fini_array_end = .);
+
+		KEEP(*(.jcr*))
+		. = ALIGN(4);
+		/* All data end */
+		__data_end__ = .;
+
+	} > RAM
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start__ = .;
+		*(.bss*)
+		*(COMMON)
+		. = ALIGN(4);
+		__bss_end__ = .;
+	} > RAM
+
+	.heap (COPY):
+	{
+		__end__ = .;
+		PROVIDE(end = .);
+		*(.heap*)
+		__HeapLimit = .;
+	} > RAM
+
+	/* .stack_dummy section doesn't contains any symbols. It is only
+	 * used for linker to calculate size of stack sections, and assign
+	 * values to stack symbols later */
+	.stack_dummy (COPY):
+	{
+		*(.stack*)
+	} > RAM
+
+	/* Set stack top to end of RAM, and stack limit move down by
+	 * size of stack_dummy section */
+	__StackTop = ORIGIN(RAM) + LENGTH(RAM);
+	__StackLimit = __StackTop - SIZEOF(.stack_dummy);
+	PROVIDE(__stack = __StackTop);
+
+	__ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ;
+
+	/* Check if data + heap + stack exceeds RAM limit */
+	ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
+}
diff --git a/variants/zero_radio/linker_scripts/gcc/flash_without_bootloader.ld b/variants/zero_radio/linker_scripts/gcc/flash_without_bootloader.ld
new file mode 100644
index 000000000..0162f0774
--- /dev/null
+++ b/variants/zero_radio/linker_scripts/gcc/flash_without_bootloader.ld
@@ -0,0 +1,212 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* Linker script to configure memory regions.
+ * Need modifying for a specific board.
+ *   FLASH.ORIGIN: starting address of flash
+ *   FLASH.LENGTH: length of flash
+ *   RAM.ORIGIN: starting address of RAM bank 0
+ *   RAM.LENGTH: length of RAM bank 0
+ */
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00040000
+  RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ *   Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ *   __exidx_start
+ *   __exidx_end
+ *   __copy_table_start__
+ *   __copy_table_end__
+ *   __zero_table_start__
+ *   __zero_table_end__
+ *   __etext
+ *   __data_start__
+ *   __preinit_array_start
+ *   __preinit_array_end
+ *   __init_array_start
+ *   __init_array_end
+ *   __fini_array_start
+ *   __fini_array_end
+ *   __data_end__
+ *   __bss_start__
+ *   __bss_end__
+ *   __end__
+ *   end
+ *   __HeapLimit
+ *   __StackLimit
+ *   __StackTop
+ *   __stack
+ *   __ram_end__
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+	.text :
+	{
+		KEEP(*(.isr_vector))
+		*(.text*)
+
+		KEEP(*(.init))
+		KEEP(*(.fini))
+
+		/* .ctors */
+		*crtbegin.o(.ctors)
+		*crtbegin?.o(.ctors)
+		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+		*(SORT(.ctors.*))
+		*(.ctors)
+
+		/* .dtors */
+ 		*crtbegin.o(.dtors)
+ 		*crtbegin?.o(.dtors)
+ 		*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+ 		*(SORT(.dtors.*))
+ 		*(.dtors)
+
+		*(.rodata*)
+
+		KEEP(*(.eh_frame*))
+	} > FLASH
+
+	.ARM.extab :
+	{
+		*(.ARM.extab* .gnu.linkonce.armextab.*)
+	} > FLASH
+
+	__exidx_start = .;
+	.ARM.exidx :
+	{
+		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
+	} > FLASH
+	__exidx_end = .;
+
+	/* To copy multiple ROM to RAM sections,
+	 * uncomment .copy.table section and,
+	 * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.copy.table :
+	{
+		. = ALIGN(4);
+		__copy_table_start__ = .;
+		LONG (__etext)
+		LONG (__data_start__)
+		LONG (__data_end__ - __data_start__)
+		LONG (__etext2)
+		LONG (__data2_start__)
+		LONG (__data2_end__ - __data2_start__)
+		__copy_table_end__ = .;
+	} > FLASH
+	*/
+
+	/* To clear multiple BSS sections,
+	 * uncomment .zero.table section and,
+	 * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
+	/*
+	.zero.table :
+	{
+		. = ALIGN(4);
+		__zero_table_start__ = .;
+		LONG (__bss_start__)
+		LONG (__bss_end__ - __bss_start__)
+		LONG (__bss2_start__)
+		LONG (__bss2_end__ - __bss2_start__)
+		__zero_table_end__ = .;
+	} > FLASH
+	*/
+
+	__etext = .;
+
+	.data : AT (__etext)
+	{
+		__data_start__ = .;
+		*(vtable)
+		*(.data*)
+
+		. = ALIGN(4);
+		/* preinit data */
+		PROVIDE_HIDDEN (__preinit_array_start = .);
+		KEEP(*(.preinit_array))
+		PROVIDE_HIDDEN (__preinit_array_end = .);
+
+		. = ALIGN(4);
+		/* init data */
+		PROVIDE_HIDDEN (__init_array_start = .);
+		KEEP(*(SORT(.init_array.*)))
+		KEEP(*(.init_array))
+		PROVIDE_HIDDEN (__init_array_end = .);
+
+
+		. = ALIGN(4);
+		/* finit data */
+		PROVIDE_HIDDEN (__fini_array_start = .);
+		KEEP(*(SORT(.fini_array.*)))
+		KEEP(*(.fini_array))
+		PROVIDE_HIDDEN (__fini_array_end = .);
+
+		KEEP(*(.jcr*))
+		. = ALIGN(4);
+		/* All data end */
+		__data_end__ = .;
+
+	} > RAM
+
+	.bss :
+	{
+		. = ALIGN(4);
+		__bss_start__ = .;
+		*(.bss*)
+		*(COMMON)
+		. = ALIGN(4);
+		__bss_end__ = .;
+	} > RAM
+
+	.heap (COPY):
+	{
+		__end__ = .;
+		PROVIDE(end = .);
+		*(.heap*)
+		__HeapLimit = .;
+	} > RAM
+
+	/* .stack_dummy section doesn't contains any symbols. It is only
+	 * used for linker to calculate size of stack sections, and assign
+	 * values to stack symbols later */
+	.stack_dummy (COPY):
+	{
+		*(.stack*)
+	} > RAM
+
+	/* Set stack top to end of RAM, and stack limit move down by
+	 * size of stack_dummy section */
+	__StackTop = ORIGIN(RAM) + LENGTH(RAM) ;
+	__StackLimit = __StackTop - SIZEOF(.stack_dummy);
+	PROVIDE(__stack = __StackTop);
+
+	__ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ;
+
+	/* Check if data + heap + stack exceeds RAM limit */
+	ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
+}
diff --git a/variants/zero_radio/openocd_scripts/zero_radio.cfg b/variants/zero_radio/openocd_scripts/zero_radio.cfg
new file mode 100644
index 000000000..6960702ab
--- /dev/null
+++ b/variants/zero_radio/openocd_scripts/zero_radio.cfg
@@ -0,0 +1,28 @@
+#
+#  Adafruit Feather M0 Radio OpenOCD script.
+#
+#  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+#
+#  This library is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU Lesser General Public
+#  License as published by the Free Software Foundation; either
+#  version 2.1 of the License, or (at your option) any later version.
+#
+#  This library is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+#  See the GNU Lesser General Public License for more details.
+#
+#  You should have received a copy of the GNU Lesser General Public
+#  License along with this library; if not, write to the Free Software
+#  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+#
+
+# chip name
+set CHIPNAME at91samd21g18
+set ENDIAN little
+
+# choose a port here
+set telnet_port 0
+
+source [find target/at91samdXX.cfg]
diff --git a/variants/zero_radio/pins_arduino.h b/variants/zero_radio/pins_arduino.h
new file mode 100644
index 000000000..db0e40c3d
--- /dev/null
+++ b/variants/zero_radio/pins_arduino.h
@@ -0,0 +1,21 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+// API compatibility
+#include "variant.h"
+
diff --git a/variants/zero_radio/variant.cpp b/variants/zero_radio/variant.cpp
new file mode 100644
index 000000000..8e3150122
--- /dev/null
+++ b/variants/zero_radio/variant.cpp
@@ -0,0 +1,225 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+/*
+ * +------------+------------------+--------+-----------------+--------------------------------------------------------------------------------------------------------
+ * + Pin number +  ZERO Board pin  |  PIN   | Label/Name      | Comments (* is for default peripheral in use)
+ * +------------+------------------+--------+-----------------+--------------------------------------------------------------------------------------------------------
+ * |            | Digital Low      |        |                 |
+ * +------------+------------------+--------+-----------------+--------------------------------------------------------------------------------------------------------
+ * | 0          | 0                |  PA11  | AT86RF233_DIG4  | EIC/EXTINT[11] ADC/AIN[19]           PTC/X[3]  SERCOM0/PAD[3]  SERCOM2/PAD[3]  TCC0/WO[3]  TCC1/WO[1]
+ * | 1          | 1                |  PA10  | AT86RF233_DIG3  | EIC/EXTINT[10] ADC/AIN[18]           PTC/X[2]  SERCOM0/PAD[2]                  TCC0/WO[2]  TCC1/WO[0]
+ * | 2          | 2                |  PA14  | MISO            | EIC/EXTINT[14]                                 SERCOM2/PAD[2]  SERCOM4/PAD[2]  TC3/WO[0]   TCC0/WO[4]
+ * | 3          | ~3               |  PA09  |                 | EIC/EXTINT[9]  ADC/AIN[17]           PTC/X[1]  SERCOM0/PAD[1]  SERCOM2/PAD[1] *TCC0/WO[1]  TCC1/WO[3]
+ * | 4          | ~4               |  PA08  |                 | EIC/NMI        ADC/AIN[16]           PTC/X[0]  SERCOM0/PAD[0]  SERCOM2/PAD[0] *TCC0/WO[0]  TCC1/WO[2]
+ * | 5          | ~5               |  PA15  |                 | EIC/EXTINT[15]                                 SERCOM2/PAD[3]  SERCOM4/PAD[3] *TC3/WO[1]   TCC0/WO[5]
+ * | 6          | ~6               |  PA20  |                 | EIC/EXTINT[4]                        PTC/X[8]  SERCOM5/PAD[2]  SERCOM3/PAD[2]             *TCC0/WO[6]
+ * | 7          | 7                |  PA21  |                 | EIC/EXTINT[5]                        PTC/X[9]  SERCOM5/PAD[3]  SERCOM3/PAD[3]              TCC0/WO[7]
+ * +------------+------------------+--------+-----------------+--------------------------------------------------------------------------------------------------------
+ * |            | Digital High     |        |                 |
+ * +------------+------------------+--------+-----------------+--------------------------------------------------------------------------------------------------------
+ * | 8          | ~8               |  PA06  |                 | EIC/EXTINT[6]  ADC/AIN[6]  AC/AIN[2] PTC/Y[4]  SERCOM0/PAD[2]                 *TCC1/WO[0]
+ * | 9          | ~9               |  PA07  |                 | EIC/EXTINT[7]  ADC/AIN[7]  AC/AIN[3] PTC/Y[5]  SERCOM0/PAD[3]                 *TCC1/WO[1]
+ * | 10         | ~10              |  PA18  |                 | EIC/EXTINT[2]                        PTC/X[6] +SERCOM1/PAD[2]  SERCOM3/PAD[2] *TC3/WO[0]    TCC0/WO[2]
+ * | 11         | ~11              |  PA16  |                 | EIC/EXTINT[0]                        PTC/X[4] +SERCOM1/PAD[0]  SERCOM3/PAD[0] *TCC2/WO[0]   TCC0/WO[6]
+ * | 12         | ~12              |  PA19  |                 | EIC/EXTINT[3]                        PTC/X[7] +SERCOM1/PAD[3]  SERCOM3/PAD[3]  TC3/WO[1]   *TCC0/WO[3]
+ * | 13         | ~13              |  PA17  | LED             | EIC/EXTINT[1]                        PTC/X[5] +SERCOM1/PAD[1]  SERCOM3/PAD[1] *TCC2/WO[1]   TCC0/WO[7]
+ * +------------+------------------+--------+-----------------+--------------------------------------------------------------------------------------------------------
+ * |            | Analog Connector |        |                 |
+ * +------------+------------------+--------+-----------------+--------------------------------------------------------------------------------------------------------
+ * | 14         | A0               |  PA02  | A0              | EIC/EXTINT[2] *ADC/AIN[0]  DAC/VOUT  PTC/Y[0]
+ * | 15         | A1               |  PB08  | A1              | EIC/EXTINT[8] *ADC/AIN[2]            PTC/Y[14] SERCOM4/PAD[0]                  TC4/WO[0]
+ * | 16         | A2               |  PB09  | A2              | EIC/EXTINT[9] *ADC/AIN[3]            PTC/Y[15] SERCOM4/PAD[1]                  TC4/WO[1]
+ * | 17         | A3               |  PA04  | A3              | EIC/EXTINT[4] *ADC/AIN[4]  AC/AIN[0] PTC/Y[2]  SERCOM0/PAD[0]                  TCC0/WO[0]
+ * | 18         | A4               |  PA05  | A4              | EIC/EXTINT[5] *ADC/AIN[5]  AC/AIN[1] PTC/Y[5]  SERCOM0/PAD[1]                  TCC0/WO[1]
+ * | 19         | A5               |  PB02  | A5              | EIC/EXTINT[2] *ADC/AIN[10]           PTC/Y[8]  SERCOM5/PAD[0]
+ * +------------+------------------+--------+-----------------+--------------------------------------------------------------------------------------------------------
+ * |            | Wire             |        |                 |
+ * +------------+------------------+--------+-----------------+--------------------------------------------------------------------------------------------------------
+ * | 20         | SDA              |  PA22  | SDA             | EIC/EXTINT[6]                        PTC/X[10] *SERCOM3/PAD[0] SERCOM5/PAD[0] TC4/WO[0] TCC0/WO[4]
+ * | 21         | SCL              |  PA23  | SCL             | EIC/EXTINT[7]                        PTC/X[11] *SERCOM3/PAD[1] SERCOM5/PAD[1] TC4/WO[1] TCC0/WO[5]
+ * +------------+------------------+--------+-----------------+--------------------------------------------------------------------------------------------------------
+ * |            |SPI (Legacy ICSP) |        |                 |
+ * +------------+------------------+--------+-----------------+--------------------------------------------------------------------------------------------------------
+ * | 22         | 1                |  PA12  | MISO            | EIC/EXTINT[12] SERCOM2/PAD[0] *SERCOM4/PAD[0] TCC2/WO[0] TCC0/WO[6]
+ * |            | 2                |        | 5V0             |
+ * | 23         | 4                |  PB10  | MOSI            | EIC/EXTINT[10]                *SERCOM4/PAD[2] TC5/WO[0]  TCC0/WO[4]
+ * | 24         | 3                |  PB11  | SCK             | EIC/EXTINT[11]                *SERCOM4/PAD[3] TC5/WO[1]  TCC0/WO[5]
+ * |            | 5                |        | RESET           |
+ * |            | 6                |        | GND             |
+ * +------------+------------------+--------+-----------------+--------------------------------------------------------------------------------------------------------
+ * |            | LEDs             |        |                 |
+ * +------------+------------------+--------+-----------------+--------------------------------------------------------------------------------------------------------
+ * | 25         |                  |  PB03  | RX              |
+ * | 26         |                  |  PA27  | TX              |
+ * +------------+------------------+--------+-----------------+--------------------------------------------------------------------------------------------------------
+ * |            | USB              |        |                 |
+ * +------------+------------------+--------+-----------------+--------------------------------------------------------------------------------------------------------
+ * | 27         |                  |  PA28  | USB_HOST_ENABLE | EIC/EXTINT[8]
+ * | 28         |                  |  PA24  | USB_NEGATIVE    | *USB/DM
+ * | 29         |                  |  PA25  | USB_POSITIVE    | *USB/DP
+ * +------------+------------------+--------+-----------------+--------------------------------------------------------------------------------------------------------
+ * |            | EDBG             |        |                 |
+ * +------------+------------------+--------+-----------------+--------------------------------------------------------------------------------------------------------
+ * | 30         |                  |  PB22  | EDBG_UART TX    | *SERCOM5/PAD[2]
+ * | 31         |                  |  PB23  | EDBG_UART RX    | *SERCOM5/PAD[3]
+ * +------------+------------------+--------+-----------------+--------------------------------------------------------------------------------------------------------
+ * | 32         |                  |  PA22  | EDBG_SDA        | Pin 20 (SDA)
+ * | 33         |                  |  PA23  | EDBG_SCL        | Pin 21 (SCL)
+ * +------------+------------------+--------+-----------------+--------------------------------------------------------------------------------------------------------
+ * | 34         |                  |  PA19  | EDBG_MISO       | EIC/EXTINT[3] *SERCOM1/PAD[3] SERCOM3/PAD[3] TC3/WO[1]  TCC0/WO[3]
+ * | 35         |                  |  PA16  | EDBG_MOSI       | EIC/EXTINT[0] *SERCOM1/PAD[0] SERCOM3/PAD[0] TCC2/WO[0] TCC0/WO[6]
+ * | 36         |                  |  PA18  | EDBG_SS         | EIC/EXTINT[2] *SERCOM1/PAD[2] SERCOM3/PAD[2] TC3/WO[0]  TCC0/WO[2]
+ * | 37         |                  |  PA17  | EDBG_SCK        | EIC/EXTINT[1] *SERCOM1/PAD[1] SERCOM3/PAD[1] TCC2/WO[1] TCC0/WO[7]
+ * +------------+------------------+--------+-----------------+--------------------------------------------------------------------------------------------------------
+ * | 38         | ATN              |  PA13  | EDBG_GPIO0      | EIC/EXTINT[13] SERCOM2/PAD[1] SERCOM4/PAD[1] *TCC2/WO[1] TCC0/WO[7]
+ * | 39         |                  |  PA21  | EDBG_GPIO1      | Pin 7
+ * | 40         |                  |  PA06  | EDBG_GPIO2      | Pin 8
+ * | 41         |                  |  PA07  | EDBG_GPIO3      | Pin 9
+ * +------------+------------------+--------+-----------------+--------------------------------------------------------------------------------------------------------
+ * |            |                  |        |                 |
+ * +------------+------------------+--------+-----------------+--------------------------------------------------------------------------------------------------------
+ * |            | GND              |        |                 |
+ * | 42         | AREF             |  PA03  |                 | EIC/EXTINT[3] *[ADC|DAC]/VREFA ADC/AIN[1] PTC/Y[1]
+ * +------------+------------------+--------+-----------------+--------------------------------------------------------------------------------------------------------
+ * |            |32.768KHz Crystal |        |                 |
+ * +------------+------------------+--------+-----------------+--------------------------------------------------------------------------------------------------------
+ * |            |                  |  PA00  | XIN32           | EIC/EXTINT[0] SERCOM1/PAD[0] TCC2/WO[0]
+ * |            |                  |  PA01  | XOUT32          | EIC/EXTINT[1] SERCOM1/PAD[1] TCC2/WO[1]
+ * +------------+------------------+--------+-----------------+--------------------------------------------------------------------------------------------------------
+ */
+
+
+#include "variant.h"
+
+/*
+ * Pins descriptions
+ */
+const PinDescription g_APinDescription[]=
+{
+  // 0..13 - Digital pins
+  // ----------------------
+  // 0/1 - AT86RF233 internal pins
+  { PORTA, 11, PIO_SERCOM, (PIN_ATTR_DIGITAL), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_11 }, // AT86RF233 DIG4
+  { PORTA, 10, PIO_SERCOM, (PIN_ATTR_DIGITAL), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_10 }, // AT86RF233 DIG3
+
+  // 2..12
+  // Digital Low
+  { PORTA, 14, PIO_SERCOM, (PIN_ATTR_DIGITAL), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_14 },  // SPI MISO SERCOM 2.2
+  { PORTA,  9, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel17, PWM0_CH1, TCC0_CH1, EXTERNAL_INT_9 }, // TCC0/WO[1]
+  { PORTA,  8, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), ADC_Channel16, PWM0_CH0, TCC0_CH0, EXTERNAL_INT_NMI },  // TCC0/WO[0]
+  { PORTA, 15, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM3_CH1, TC3_CH1, EXTERNAL_INT_15 }, // TC3/WO[1]
+  { PORTA, 20, PIO_TIMER_ALT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER_ALT), No_ADC_Channel, PWM0_CH6, TCC0_CH6, EXTERNAL_INT_4 }, // used for AT86RF SLP_TR
+  { }, // PA21 not available on SAMR
+
+  // Digital High
+  { PORTA,  6, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER|PIN_ATTR_ANALOG), ADC_Channel6, PWM1_CH0, TCC1_CH0, EXTERNAL_INT_6 }, // TCC1/WO[0]
+  { PORTA,  7, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER|PIN_ATTR_ANALOG), ADC_Channel7, PWM1_CH1, TCC1_CH1, EXTERNAL_INT_7 }, // TCC1/WO[1]
+  { PORTA, 18, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM3_CH0, TC3_CH0, EXTERNAL_INT_2 }, // TC3/WO[0]
+  { PORTA, 16, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM2_CH0, TCC2_CH0, EXTERNAL_INT_0 }, // TCC2/WO[0]
+  { PORTA, 19, PIO_TIMER_ALT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER_ALT), No_ADC_Channel, PWM0_CH3, TCC0_CH3, EXTERNAL_INT_3 }, // TCC0/WO[3]
+
+  // 13 (LED)
+  { PORTA, 17, PIO_PWM, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM), No_ADC_Channel, PWM2_CH1, NOT_ON_TIMER, EXTERNAL_INT_1 }, // TCC2/WO[1]
+
+  // 14..19 - Analog pins
+  // --------------------
+  { }, // PA02 not available on SAMR
+  { },  // PB08 not available on SAMR
+  { },  // PB09 not available on SAMR
+  { PORTA,  4, PIO_ANALOG, 0, ADC_Channel4, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_4 }, // ADC/AIN[4]
+  { PORTA,  5, PIO_ANALOG, 0, ADC_Channel5, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_5 }, // ADC/AIN[5]
+  { PORTB,  2, PIO_ANALOG, 0, ADC_Channel10, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 }, // ADC/AIN[10]
+
+  // 20..21 I2C pins (SDA/SCL and also EDBG:SDA/SCL)
+  // ----------------------
+  { PORTA, 22, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_6 }, // SDA: SERCOM3/PAD[0]
+  { PORTA, 23, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_7 }, // SCL: SERCOM3/PAD[1]
+
+  // 22..24 - SPI pins (ICSP:MISO,SCK,MOSI)
+  // ----------------------
+  { PORTA, 12, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_12 }, // MOSI: SERCOM2/PAD[0]
+  { }, // PB10 Not available
+  { }, // PB11 Not available
+
+  // 25..26 - IO & TX LED (PB03/PA27)
+  // --------------------
+  { PORTB,  3, PIO_ANALOG, 0, ADC_Channel11, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // used as analog11
+  { PORTA, 27, PIO_OUTPUT, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // used as output only
+
+  // 27..29 - USB
+  // --------------------
+  { PORTA, 28, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB Host enable
+  { PORTA, 24, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB/DM
+  { PORTA, 25, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB/DP
+
+  // 30..41 - Serial1 UART
+  // ----------------------
+  // 30/31 - Serial1 UART
+  { PORTB, 22, PIO_SERCOM_ALT, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // TX: SERCOM5/PAD[2]
+  { PORTB, 23, PIO_SERCOM_ALT, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // RX: SERCOM5/PAD[3]
+
+  // 32/33 I2C (SDA/SCL and also EDBG:SDA/SCL)
+  { PORTA, 22, PIO_SERCOM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // SDA: SERCOM3/PAD[0]
+  { PORTA, 23, PIO_SERCOM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // SCL: SERCOM3/PAD[1]
+
+  // 34..37 - EDBG/SPI
+  { PORTA, 19, PIO_SERCOM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // MISO: SERCOM1/PAD[3]
+  { PORTA, 16, PIO_SERCOM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // MOSI: SERCOM1/PAD[0]
+  { PORTA, 18, PIO_SERCOM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // SS: SERCOM1/PAD[2]
+  { PORTA, 17, PIO_SERCOM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // SCK: SERCOM1/PAD[1]
+
+  // 38..41 - EDBG/Digital
+  { PORTA, 13, PIO_SERCOM, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM), No_ADC_Channel, PWM0_CH5, NOT_ON_TIMER, EXTERNAL_INT_13 }, // SCK: SERCOM2.1
+  {  }, // PA21 Not available
+  { PORTA,  6, PIO_PWM, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM), No_ADC_Channel, PWM1_CH0, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // Pin 8
+  { PORTA,  7, PIO_PWM, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM), No_ADC_Channel, PWM1_CH1, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // Pin 9
+
+  // 42 (AREF)
+  {  }, // DAC/VREFP
+
+  // ----------------------
+  // 43 - Alternate use of A0 (DAC output)
+  {  }, // DAC/VOUT
+
+
+  // ----- Special SAMR pins! ------
+  { PORTB, 15, PIO_TIMER, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // #44 PB15 == AT86_RESETN
+  { PORTC, 16, PIO_TIMER, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // #45 PC16 == AT86_CLKM
+  { PORTC, 18, PIO_TIMER_ALT, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // #46 PC18 == AT86_SCLK sercom4.3
+  { PORTC, 19, PIO_TIMER_ALT, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // #47 PC19 == AT86_MISO sercom4.0
+  { PORTB, 30, PIO_TIMER_ALT, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // #48 PB30 == AT86_MOSI sercom4.2
+  { PORTB, 31, PIO_TIMER_ALT, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // #49 PB31 == AT86_SEL sercom4.1
+  { PORTB, 00, PIO_TIMER, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_0 }, // #50 PB00 = AT86_IRQ
+} ;
+
+const void* g_apTCInstances[TCC_INST_NUM+TC_INST_NUM]={ TCC0, TCC1, TCC2, TC3, TC4, TC5 } ;
+
+// Multi-serial objects instantiation
+SERCOM sercom0( SERCOM0 ) ;
+SERCOM sercom1( SERCOM1 ) ;
+SERCOM sercom2( SERCOM2 ) ;
+SERCOM sercom3( SERCOM3 ) ;
+SERCOM sercom4( SERCOM4 ) ;
+SERCOM sercom5( SERCOM5 ) ;
+
+// We'll use sercom5 for Serial1 hardware serial since pins 0 and 1 are not external
+Uart Serial1( &sercom5, PIN_SERIAL1_RX, PIN_SERIAL1_TX, PAD_SERIAL1_RX, PAD_SERIAL1_TX ) ;
+void SERCOM5_Handler()
+{
+  Serial1.IrqHandler();
+}
diff --git a/variants/zero_radio/variant.h b/variants/zero_radio/variant.h
new file mode 100644
index 000000000..dfc5b93d7
--- /dev/null
+++ b/variants/zero_radio/variant.h
@@ -0,0 +1,242 @@
+/*
+  Copyright (c) 2014-2015 Arduino LLC.  All right reserved.
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+  See the GNU Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _VARIANT_ARDUINO_ZERO_
+#define _VARIANT_ARDUINO_ZERO_
+
+// The definitions here needs a SAMD core >=1.6.6
+#define ARDUINO_SAMD_VARIANT_COMPLIANCE 10606
+
+/*----------------------------------------------------------------------------
+ *        Definitions
+ *----------------------------------------------------------------------------*/
+
+/** Frequency of the board main oscillator */
+#define VARIANT_MAINOSC		(32768ul)
+
+/** Master clock frequency */
+#define VARIANT_MCK	(F_CPU)
+
+/*----------------------------------------------------------------------------
+ *        Headers
+ *----------------------------------------------------------------------------*/
+
+#include "WVariant.h"
+
+#ifdef __cplusplus
+#include "SERCOM.h"
+#include "Uart.h"
+#endif // __cplusplus
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif // __cplusplus
+
+/*----------------------------------------------------------------------------
+ *        Pins
+ *----------------------------------------------------------------------------*/
+
+// Number of pins defined in PinDescription array
+#define PINS_COUNT           (51u)
+#define NUM_DIGITAL_PINS     (51u)
+
+#define NUM_ANALOG_INPUTS    (8u)
+#define NUM_ANALOG_OUTPUTS   (0u)
+#define analogInputToDigitalPin(p)  ((p < 6u) ? (p) + 14u : -1)
+
+#define digitalPinToPort(P)        ( &(PORT->Group[g_APinDescription[P].ulPort]) )
+#define digitalPinToBitMask(P)     ( 1 << g_APinDescription[P].ulPin )
+//#define analogInPinToBit(P)        ( )
+#define portOutputRegister(port)   ( &(port->OUT.reg) )
+#define portInputRegister(port)    ( &(port->IN.reg) )
+#define portModeRegister(port)     ( &(port->DIR.reg) )
+#define digitalPinHasPWM(P)        ( g_APinDescription[P].ulPWMChannel != NOT_ON_PWM || g_APinDescription[P].ulTCChannel != NOT_ON_TIMER )
+
+/*
+ * digitalPinToTimer(..) is AVR-specific and is not defined for SAMD
+ * architecture. If you need to check if a pin supports PWM you must
+ * use digitalPinHasPWM(..).
+ *
+ * https://github.com/arduino/Arduino/issues/1833
+ */
+// #define digitalPinToTimer(P)
+
+// LEDs
+#define PIN_LED_13           (13u)
+#define PIN_LED_RXL          (25u)
+#define PIN_LED_TXL          (26u)
+#define PIN_LED              PIN_LED_13
+#define PIN_LED2             PIN_LED_RXL
+#define PIN_LED3             PIN_LED_TXL
+#define LED_BUILTIN          PIN_LED_13
+
+/*
+ * Analog pins
+ */
+#define PIN_A0               (14ul)
+#define PIN_A1               (15ul)
+#define PIN_A2               (16ul)
+#define PIN_A3               (17ul)
+#define PIN_A4               (18ul)
+#define PIN_A5               (19ul)
+#define PIN_A6               (8ul)
+#define PIN_A7               (9ul)
+#define PIN_A11              (25ul)
+#define PIN_A16              (4ul)
+#define PIN_A17              (3ul)
+
+static const uint8_t A0  = PIN_A0 ;
+static const uint8_t A1  = PIN_A1 ;
+static const uint8_t A2  = PIN_A2 ;
+static const uint8_t A3  = PIN_A3 ;
+static const uint8_t A4  = PIN_A4 ;
+static const uint8_t A5  = PIN_A5 ;
+static const uint8_t A6  = PIN_A6 ;
+static const uint8_t A7  = PIN_A7 ;
+static const uint8_t A11  = PIN_A11 ;
+static const uint8_t A16  = PIN_A16 ;
+static const uint8_t A17  = PIN_A17 ;
+
+#define ADC_RESOLUTION		12
+
+// Other pins
+#define PIN_ATN              (38ul)
+static const uint8_t ATN = PIN_ATN;
+
+
+// Other pins
+#define PIN_ATRF_RESETN   44
+#define PIN_ATRF_CLKM     45
+#define PIN_ATRF_SLPTR    6
+#define PIN_ATRF_SCLK         (46u)
+#define PIN_ATRF_MISO         (47u)
+#define PIN_ATRF_MOSI         (48u)
+#define PIN_ATRF_SEL          (49u)
+#define PIN_ATRF_IRQ          (50u)
+
+/*
+ * Serial interfaces
+ */
+
+// Serial1 on SERCOM5
+#define PIN_SERIAL1_RX       (31ul)
+#define PIN_SERIAL1_TX       (30ul)
+#define PAD_SERIAL1_TX       (UART_TX_PAD_2)
+#define PAD_SERIAL1_RX       (SERCOM_RX_PAD_3)
+
+/*
+ * SPI Interfaces
+ */
+#define SPI_INTERFACES_COUNT 2
+
+  // "external" SPI, used for sensors, displays, available to user
+#define PIN_SPI_MISO         (2u)
+#define PIN_SPI_MOSI         (22u)
+#define PIN_SPI_SCK          (38u)
+#define PERIPH_SPI           sercom2
+#define PAD_SPI_TX           SPI_PAD_0_SCK_1
+#define PAD_SPI_RX           SERCOM_RX_PAD_2
+
+static const uint8_t SS	  = PIN_A2 ;	// SERCOM4 last PAD is present on A2 but HW SS isn't used. Set here only for reference.
+static const uint8_t MOSI = PIN_SPI_MOSI ;
+static const uint8_t MISO = PIN_SPI_MISO ;
+static const uint8_t SCK  = PIN_SPI_SCK ;
+
+  // "internal" SPI, used for AT86RF233 only!
+#define PIN_SPI1_MISO         (47u)
+#define PIN_SPI1_MOSI         (48u)
+#define PIN_SPI1_SCK          (46u)
+#define PIN_SPI1_SEL          (49u)
+#define PERIPH_SPI1           sercom4
+#define PAD_SPI1_TX           SPI_PAD_2_SCK_3
+#define PAD_SPI1_RX           SERCOM_RX_PAD_0
+
+static const uint8_t SS1   = PIN_SPI1_SEL ;
+static const uint8_t MOSI1 = PIN_SPI_MOSI ;
+static const uint8_t MISO1 = PIN_SPI_MISO ;
+static const uint8_t SCK1  = PIN_SPI_SCK ;
+
+/*
+ * Wire Interfaces
+ */
+#define WIRE_INTERFACES_COUNT 1
+
+#define PIN_WIRE_SDA         (20u)
+#define PIN_WIRE_SCL         (21u)
+#define PERIPH_WIRE          sercom3
+#define WIRE_IT_HANDLER      SERCOM3_Handler
+
+static const uint8_t SDA = PIN_WIRE_SDA;
+static const uint8_t SCL = PIN_WIRE_SCL;
+
+/*
+ * USB
+ */
+#define PIN_USB_HOST_ENABLE (27ul)
+#define PIN_USB_DM          (28ul)
+#define PIN_USB_DP          (29ul)
+
+#ifdef __cplusplus
+}
+#endif
+
+/*----------------------------------------------------------------------------
+ *        Arduino objects - C++ only
+ *----------------------------------------------------------------------------*/
+
+#ifdef __cplusplus
+
+/*	=========================
+ *	===== SERCOM DEFINITION
+ *	=========================
+*/
+extern SERCOM sercom0;
+extern SERCOM sercom1;
+extern SERCOM sercom2;
+extern SERCOM sercom3;
+extern SERCOM sercom4;
+extern SERCOM sercom5;
+
+extern Uart Serial1;
+
+#endif
+
+// These serial port names are intended to allow libraries and architecture-neutral
+// sketches to automatically default to the correct port name for a particular type
+// of use.  For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN,
+// the first hardware serial port whose RX/TX pins are not dedicated to another use.
+//
+// SERIAL_PORT_MONITOR        Port which normally prints to the Arduino Serial Monitor
+//
+// SERIAL_PORT_USBVIRTUAL     Port which is USB virtual serial
+//
+// SERIAL_PORT_LINUXBRIDGE    Port which connects to a Linux system via Bridge library
+//
+// SERIAL_PORT_HARDWARE       Hardware serial port, physical RX & TX pins.
+//
+// SERIAL_PORT_HARDWARE_OPEN  Hardware serial ports which are open for use.  Their RX & TX
+//                            pins are NOT connected to anything by default.
+#define SERIAL_PORT_USBVIRTUAL      Serial
+#define SERIAL_PORT_MONITOR         Serial
+// Serial has no physical pins broken out, so it's not listed as HARDWARE port
+#define SERIAL_PORT_HARDWARE        Serial1
+#define SERIAL_PORT_HARDWARE_OPEN   Serial1
+
+#endif /* _VARIANT_ARDUINO_ZERO_ */
+