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 +#include "board_definitions.h" + +inline void LED_init(void) { PORT->Group[BOARD_LED_PORT].DIRSET.reg = (1<Group[BOARD_LED_PORT].OUTSET.reg = (1<Group[BOARD_LED_PORT].OUTCLR.reg = (1<Group[BOARD_LED_PORT].OUTTGL.reg = (1<Group[BOARD_LEDRX_PORT].DIRSET.reg = (1<Group[BOARD_LEDRX_PORT].OUTSET.reg = (1<Group[BOARD_LEDRX_PORT].OUTCLR.reg = (1<Group[BOARD_LEDRX_PORT].OUTTGL.reg = (1<Group[BOARD_LEDTX_PORT].DIRSET.reg = (1<Group[BOARD_LEDTX_PORT].OUTSET.reg = (1<Group[BOARD_LEDTX_PORT].OUTCLR.reg = (1<Group[BOARD_LEDTX_PORT].OUTTGL.reg = (1<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 +#include +#include + +#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 +#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 +#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 + +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 +#include +#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 +#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 +#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(jgetdata_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*) ¤t_number, 2); + } + else if (command == 'w') + { + current_number = *((uint32_t *) ptr_data); + sam_ba_putdata_term((uint8_t*) ¤t_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) && iADDR.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; iputdata("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 +#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 +#include + + +/* 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 +#include +#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 +#include + +#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 @@ + + + + 2.0 + 7.0 + com.Atmel.ARMGCC.C + dce6c7e3-ee26-4d79-826b-08594b9ad897 + ATSAMD21G18A + none + Executable + C + $(MSBuildProjectName) + .elf + $(MSBuildProjectDirectory)\$(Configuration) + samd21_sam_ba + samd21_sam_ba + samd21_sam_ba + Native + true + false + true + true + 0x20000000 + + true + exception_table + 2 + 0 + + + + + + + + + + + + + + com.atmel.avrdbg.tool.atmelice + J41800001895 + 0x10010000 + SWD + + + + 2000000 + + SWD + + com.atmel.avrdbg.tool.atmelice + J41800001895 + Atmel-ICE + + 2000000 + + + + + SWD + + com.atmel.avrdbg.tool.edbg + ATML2320040200000259 + EDBG + + + + + + True + True + True + True + True + + + NDEBUG + + + Optimize for size (-Os) + True + True + + + libm + + + True + -Tsamd21j18a_flash.ld + + + + + + + True + True + True + True + True + + + DEBUG + + + Optimize (-O1) + True + Maximum (-g3) + True + + + libm + + + True + -Tsamd21j18a_flash.ld + Default (-g) + Default (-Wa,-g) + + + True + + DEBUG=1 all + clean + Makefile + + + + compile + board_definitions.h + + + compile + board_driver_led.c + + + compile + board_driver_led.h + + + compile + board_driver_serial.c + + + compile + board_driver_serial.h + + + compile + board_driver_usb.c + + + compile + board_driver_usb.h + + + compile + board_init.c + + + compile + board_startup.c + + + compile + main.c + + + compile + sam_ba_cdc.c + + + compile + sam_ba_cdc.h + + + compile + sam_ba_monitor.c + + + compile + sam_ba_monitor.h + + + compile + sam_ba_serial.c + + + compile + sam_ba_serial.h + + + compile + sam_ba_usb.c + + + compile + sam_ba_usb.h + + + + + compile + Makefile + + + compile + README.md + + + compile + bootloader_samd21x18.ld + + + + \ 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 +#include "board_definitions.h" + +#if defined(BOARD_LED_PORT) +inline void LED_init(void) { PORT->Group[BOARD_LED_PORT].DIRSET.reg = (1<Group[BOARD_LED_PORT].OUTSET.reg = (1<Group[BOARD_LED_PORT].OUTCLR.reg = (1<Group[BOARD_LED_PORT].OUTTGL.reg = (1<Group[BOARD_LEDRX_PORT].DIRSET.reg = (1<Group[BOARD_LEDRX_PORT].OUTCLR.reg = (1<Group[BOARD_LEDRX_PORT].OUTSET.reg = (1<Group[BOARD_LEDRX_PORT].OUTTGL.reg = (1<Group[BOARD_LEDTX_PORT].DIRSET.reg = (1<Group[BOARD_LEDTX_PORT].OUTCLR.reg = (1<Group[BOARD_LEDTX_PORT].OUTSET.reg = (1<Group[BOARD_LEDTX_PORT].OUTTGL.reg = (1<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 +#include +#include + +#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 +#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 +#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 + +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 +#include +#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 +#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 +#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(jput_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) && iADDR.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", 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 +#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 +#include + + +/* 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 +#include +#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>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 +#include + +#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 @@ + + + + \ 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 @@ + + + + 2.0 + 7.0 + com.Atmel.ARMGCC.C + dce6c7e3-ee26-4d79-826b-08594b9ad897 + ATSAMD51J19A + none + Executable + C + $(MSBuildProjectName) + .elf + $(MSBuildProjectDirectory)\$(Configuration) + samd21_sam_ba + samd51_sam_ba + samd21_sam_ba + Native + true + false + true + true + 0x20000000 + + true + exception_table + 2 + 0 + + + + + + + + + + + + + + com.atmel.avrdbg.tool.edbg + 00000000EZE000006352 + 0x60060005 + SWD + + + + 0 + + SWD + + com.atmel.avrdbg.tool.atmelice + J41800001895 + Atmel-ICE + + 2000000 + + + + 2000000 + + SWD + + com.atmel.avrdbg.tool.edbg + 00000000EZE000006352 + EDBG + + True + + + + + True + True + True + True + True + + + NDEBUG + + + Optimize for size (-Os) + True + True + + + libm + + + True + -Tsamd21j18a_flash.ld + + + + + + + True + True + True + True + True + + + DEBUG + + + Optimize (-O1) + True + Maximum (-g3) + True + + + libm + + + True + -Tsamd21j18a_flash.ld + Default (-g) + Default (-Wa,-g) + + + True + + DEBUG=1 all + clean + Makefile + + + + + True + True + True + True + True + + + DEBUG + + + Optimize (-O1) + True + Maximum (-g3) + True + + + libm + + + True + -Tsamd21j18a_flash.ld + Default (-g) + Default (-Wa,-g) + + + True + + DEBUG=1 all BOARD_ID=FEATHER_M4 BOARD_CHIP=__SAMD51G19A__ + clean BOARD_ID=FEATHER_M4 + Makefile + bin\featherm4\ + + + + + True + True + True + True + True + + + DEBUG + + + Optimize (-O1) + True + Maximum (-g3) + True + + + libm + + + True + -Tsamd21j18a_flash.ld + Default (-g) + Default (-Wa,-g) + + + True + + DEBUG=0 all BOARD_ID=METRO_M4 BOARD_CHIP=__SAMD51J19A__ + clean BOARD_ID=METRO_M4 + Makefile + bin\metrom4\ + METRO_M4_sam_ba + .elf + + + + compile + board_definitions.h + + + compile + + + compile + + + compile + board_driver_led.c + + + compile + board_driver_led.h + + + compile + board_driver_serial.c + + + compile + board_driver_serial.h + + + compile + board_driver_usb.c + + + compile + board_driver_usb.h + + + compile + board_init.c + + + compile + board_startup.c + + + compile + main.c + + + compile + sam_ba_cdc.c + + + compile + sam_ba_cdc.h + + + compile + sam_ba_monitor.c + + + compile + sam_ba_monitor.h + + + compile + sam_ba_serial.c + + + compile + sam_ba_serial.h + + + compile + sam_ba_usb.c + + + compile + sam_ba_usb.h + + + + + compile + + + compile + + + compile + Makefile + + + compile + README.md + + + + \ 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 #include "board_definitions.h" -#if defined(BOARD_LED_PORT) inline void LED_init(void) { PORT->Group[BOARD_LED_PORT].DIRSET.reg = (1<Group[BOARD_LED_PORT].OUTSET.reg = (1<Group[BOARD_LED_PORT].OUTCLR.reg = (1<Group[BOARD_LED_PORT].OUTTGL.reg = (1<Group[BOARD_LEDRX_PORT].DIRSET.reg = (1<Group[BOARD_LEDRX_PORT].OUTCLR.reg = (1<Group[BOARD_LEDRX_PORT].OUTSET.reg = (1<Group[BOARD_LEDRX_PORT].OUTSET.reg = (1<Group[BOARD_LEDRX_PORT].OUTCLR.reg = (1<Group[BOARD_LEDRX_PORT].OUTTGL.reg = (1<Group[BOARD_LEDTX_PORT].DIRSET.reg = (1<Group[BOARD_LEDTX_PORT].OUTCLR.reg = (1<Group[BOARD_LEDTX_PORT].OUTSET.reg = (1<Group[BOARD_LEDTX_PORT].OUTSET.reg = (1<Group[BOARD_LEDTX_PORT].OUTCLR.reg = (1<Group[BOARD_LEDTX_PORT].OUTTGL.reg = (1< #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(jgetdata_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 #include -#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>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 + auto min(const T& a, const L& b) -> decltype((b < a) ? b : a) + { + return (b < a) ? b : a; + } + + template + 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 #include // for size_t +#include // 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 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 // 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 #include // 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 + +#include +#include +#include + +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 -#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 @@ -28,7 +35,12 @@ #include #include +#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 #include @@ -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 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 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; currentINTFLAG.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 #include "sam.h" +#include #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 + +/* ---------------------------------------------------------------------- +* 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 -/** - * \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<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<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<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<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<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<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 +#include // 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; iChannel[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 & 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 +#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 +#include +#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 +#include +#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 +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 Atmel Support + */ +#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_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 #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 + +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 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 +#include // 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 + + modified on 8 Nov 2013 + by Scott Fitzgerald + http://www.arduino.cc/en/Tutorial/Knob +*/ + +#include + +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 + This example code is in the public domain. + + modified 8 Nov 2013 + by Scott Fitzgerald + http://www.arduino.cc/en/Tutorial/Sweep +*/ + +#include + +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 +sentence=Allows Arduino/Genuino boards to control a variety of servo motors. +paragraph=This library can control a great number of servos.
It makes careful use of timers: the library can control 12 servos using only 1 timer.
On the Arduino Due you can control up to 60 servos.
+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 + +/* + * 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 +#include + +#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 +#include + +#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 + +#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 +#include + + +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 +#include + +#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 +#include + +#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 + +// 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 +// 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 #include "wiring_constants.h" #include "pgmstrings.h" -// Satisfy IDE, which only needs to see the include statment in the ino. -#ifdef dobogusinclude -#include -#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; iaddress.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> (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::Parse(const uin compare masks for them. When the match is found, calls EndpointXtract passing buffer containing endpoint descriptor */ template bool ConfigDescParser::ParseDescriptor(uint8_t **pp, uint32_t *pcntdn) { - USB_CONFIGURATION_DESCRIPTOR* ucd = reinterpret_cast(varBuffer); - USB_INTERFACE_DESCRIPTOR* uid = reinterpret_cast(varBuffer); + USB_CONFIGURATION_DESCRIPTOR* ucd = reinterpret_cast(varBuffer); + USB_INTERFACE_DESCRIPTOR* uid = 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(stateParseDescr) { case 0: theBuffer.valueSize = 2; @@ -112,7 +123,7 @@ bool ConfigDescParser::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::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::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::ParseDescriptor theBuffer.pValue = varBuffer; stateParseDescr = 0; } +#pragma GCC diagnostic pop + return true; } template void ConfigDescParser::PrintHidDescriptor(const USB_HID_DESCRIPTOR *pDesc) { - Notify(PSTR("\r\n\r\nHID Descriptor:\r\n"), 0x80); - Notify(PSTR("bDescLength:\t\t"), 0x80); - PrintHex (pDesc->bLength, 0x80); + Notify(PSTR("\r\n\r\nHID Descriptor:\r\n"), 0x80); + Notify(PSTR("bDescLength:\t\t"), 0x80); + PrintHex (pDesc->bLength, 0x80); - Notify(PSTR("\r\nbDescriptorType:\t"), 0x80); - PrintHex (pDesc->bDescriptorType, 0x80); + Notify(PSTR("\r\nbDescriptorType:\t"), 0x80); + PrintHex (pDesc->bDescriptorType, 0x80); - Notify(PSTR("\r\nbcdHID:\t\t\t"), 0x80); - PrintHex (pDesc->bcdHID, 0x80); + Notify(PSTR("\r\nbcdHID:\t\t\t"), 0x80); + PrintHex (pDesc->bcdHID, 0x80); - Notify(PSTR("\r\nbCountryCode:\t\t"), 0x80); - PrintHex (pDesc->bCountryCode, 0x80); + Notify(PSTR("\r\nbCountryCode:\t\t"), 0x80); + PrintHex (pDesc->bCountryCode, 0x80); - Notify(PSTR("\r\nbNumDescriptors:\t"), 0x80); - PrintHex (pDesc->bNumDescriptors, 0x80); + Notify(PSTR("\r\nbNumDescriptors:\t"), 0x80); + PrintHex (pDesc->bNumDescriptors, 0x80); - //Notify(PSTR("\r\nbDescrType:\t\t")); - //PrintHex(pDesc->bDescrType); - // - //Notify(PSTR("\r\nwDescriptorLength:\t")); - //PrintHex(pDesc->wDescriptorLength); + //Notify(PSTR("\r\nbDescrType:\t\t")); + //PrintHex(pDesc->bDescrType); + // + //Notify(PSTR("\r\nwDescriptorLength:\t")); + //PrintHex(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 (pLT[i].bDescrType, 0x80); + Notify(PSTR("\r\nbDescrType:\t\t"), 0x80); + PrintHex (pLT[i].bDescrType, 0x80); - Notify(PSTR("\r\nwDescriptorLength:\t"), 0x80); - PrintHex (pLT[i].wDescriptorLength, 0x80); - } - Notify(PSTR("\r\n"), 0x80); + Notify(PSTR("\r\nwDescriptorLength:\t"), 0x80); + PrintHex (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_ */ +