diff --git a/IDE_Board_Manager/package_sparkfun_index.json b/IDE_Board_Manager/package_sparkfun_index.json index 2634fe36..5b0d7105 100644 --- a/IDE_Board_Manager/package_sparkfun_index.json +++ b/IDE_Board_Manager/package_sparkfun_index.json @@ -174,6 +174,26 @@ { "name":"SparkFun 9DoF Razor IMU M0" } ], "toolsDependencies":[] + }, + { + "name":"SparkFun SAMD Boards (dependency: Arduino SAMD Boards 1.6.11)", + "architecture":"samd", + "version":"1.3.3", + "category":"Contributed", + "url":"https://github.com/sparkfun/Arduino_Boards/raw/spectacle/IDE_Board_Manager/sparkfun-samd-1.3.3.tar.bz2", + "archiveFileName":"sparkfun-samd-1.3.3.tar.bz2", + "checksum":"SHA-256:344c33368532736dfd5b40fb41fc67fa7e26bc8a66e289f4859b52b9d0f6825d", + "size":"207911", + "help":{ + "online":"https://forums.sparkfun.com" + }, + "boards":[ + { "name":"SparkFun SAMD21 Mini Breakout" }, + { "name":"SparkFun SAMD21 Dev Breakout" }, + { "name":"SparkFun 9DoF Razor IMU M0" }, + { "name":"SparkFun Spectacle Director" } + ], + "toolsDependencies":[] } ], "tools":[] diff --git a/IDE_Board_Manager/sparkfun-samd-1.3.3.tar.bz2 b/IDE_Board_Manager/sparkfun-samd-1.3.3.tar.bz2 new file mode 100644 index 00000000..b91faf5b Binary files /dev/null and b/IDE_Board_Manager/sparkfun-samd-1.3.3.tar.bz2 differ diff --git a/sparkfun/samd/boards.txt b/sparkfun/samd/boards.txt index 0b86f291..c6b7860d 100644 --- a/sparkfun/samd/boards.txt +++ b/sparkfun/samd/boards.txt @@ -97,4 +97,32 @@ samd21_9dof.build.extra_combine_flags= samd21_9dof.build.vid=0x1B4F samd21_9dof.build.pid=0x9D0F samd21_9dof.bootloader.tool=openocd -samd21_9dof.bootloader.file=zero/SparkFun_9DoF_Razor_M0.bin \ No newline at end of file +samd21_9dof.bootloader.file=zero/SparkFun_9DoF_Razor_M0.bin + +spectacle.name=SparkFun Spectacle Director +spectacle.vid.0=0x1B4F +spectacle.pid.0=0x8888 +spectacle.vid.1=0x1B4F +spectacle.pid.1=0x0888 +spectacle.upload.tool=bossac +spectacle.upload.protocol=sam-ba +spectacle.upload.maximum_size=262144 +spectacle.upload.use_1200bps_touch=true +spectacle.upload.wait_for_upload_port=true +spectacle.upload.native_usb=true +spectacle.build.mcu=cortex-m0plus +spectacle.build.f_cpu=48000000L +spectacle.build.usb_product="Spectacle" +spectacle.build.usb_manufacturer="SparkFun" +spectacle.build.board=SAMD_ZERO +spectacle.build.core=arduino +spectacle.build.extra_flags=-D__SAMD21G18A__ {build.usb_flags} +spectacle.build.ldscript=linker_scripts/gcc/flash_with_bootloader.ld +spectacle.build.openocdscript=openocd_scripts/arduino_zero.cfg +spectacle.build.variant=SparkFun_Spectacle_Director +spectacle.build.variant_system_lib= +spectacle.build.extra_combine_flags= +spectacle.build.vid=0x1B4F +spectacle.build.pid=0x8D21 +spectacle.bootloader.tool=openocd +spectacle.bootloader.file=zero/SparkFun_spectacle.bin \ No newline at end of file diff --git a/sparkfun/samd/bootloaders/spectacle/Makefile b/sparkfun/samd/bootloaders/spectacle/Makefile new file mode 100644 index 00000000..59797703 --- /dev/null +++ b/sparkfun/samd/bootloaders/spectacle/Makefile @@ -0,0 +1,170 @@ +# 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 + +# ----------------------------------------------------------------------------- +# Boards definitions +NAME?=sparkfun_spectacle +BOARD_ID?=sparkfun_spectacle + +# ----------------------------------------------------------------------------- +# 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 +else + CFLAGS+=-Os -DDEBUG=0 +endif + +ELF=$(NAME).elf +BIN=$(NAME).bin +HEX=$(NAME).hex + + +INCLUDES=-I"$(MODULE_PATH)/tools/CMSIS/4.5.0/CMSIS/Include/" -I"$(MODULE_PATH)/tools/CMSIS-Atmel/1.0.0/CMSIS/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)) + +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/sparkfun/samd/bootloaders/spectacle/README.md b/sparkfun/samd/bootloaders/spectacle/README.md new file mode 100644 index 00000000..b0d939db --- /dev/null +++ b/sparkfun/samd/bootloaders/spectacle/README.md @@ -0,0 +1,95 @@ +# 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. + +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 +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. + +## 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/sparkfun/samd/bootloaders/spectacle/board_definitions.h b/sparkfun/samd/bootloaders/spectacle/board_definitions.h new file mode 100644 index 00000000..72db49a1 --- /dev/null +++ b/sparkfun/samd/bootloaders/spectacle/board_definitions.h @@ -0,0 +1,40 @@ +/* + 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_arduino_zero) + #include "board_definitions_arduino_zero.h" +#elif defined(BOARD_ID_genuino_zero) + #include "board_definitions_genuino_zero.h" +#elif defined(BOARD_ID_arduino_mkr1000) + #include "board_definitions_arduino_mkr1000.h" +#elif defined(BOARD_ID_genuino_mkr1000) + #include "board_definitions_genuino_mkr1000.h" +#elif defined(BOARD_ID_arduino_mkrzero) + #include "board_definitions_arduino_mkrzero.h" +#elif defined(BOARD_ID_sparkfun_spectacle) + #include "board_definitions_sparkfun_spectacle.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/sparkfun/samd/bootloaders/spectacle/board_definitions_arduino_mkr1000.h b/sparkfun/samd/bootloaders/spectacle/board_definitions_arduino_mkr1000.h new file mode 100644 index 00000000..4e71e4d5 --- /dev/null +++ b/sparkfun/samd/bootloaders/spectacle/board_definitions_arduino_mkr1000.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 "Arduino MKR1000" +#define USB_VID_HIGH 0x23 +#define USB_VID_LOW 0x41 +#define USB_PID_HIGH 0x00 +#define USB_PID_LOW 0x4E + +/* + * 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_USART_MODULE SERCOM0 +#define BOOT_USART_BUS_CLOCK_INDEX PM_APBCMASK_SERCOM0 +#define BOOT_USART_PER_CLOCK_INDEX GCLK_CLKCTRL_ID_SERCOM0_CORE_Val +#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 + +/* 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) + +/* + * LEDs definitions + */ +// PA20 (digital pin 6) +#define BOARD_LED_PORT (0) +#define BOARD_LED_PIN (20) + +// No RX/TX led +//#define BOARD_LEDRX_PORT +//#define BOARD_LEDRX_PIN + +//#define BOARD_LEDTX_PORT +//#define BOARD_LEDTX_PIN + +#endif // _BOARD_DEFINITIONS_H_ diff --git a/sparkfun/samd/bootloaders/spectacle/board_definitions_arduino_mkrzero.h b/sparkfun/samd/bootloaders/spectacle/board_definitions_arduino_mkrzero.h new file mode 100644 index 00000000..0adfeb67 --- /dev/null +++ b/sparkfun/samd/bootloaders/spectacle/board_definitions_arduino_mkrzero.h @@ -0,0 +1,81 @@ +/* + Copyright (c) 2016 Arduino LLC. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + 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 "Arduino MKRZero" +#define USB_VID_HIGH 0x23 +#define USB_VID_LOW 0x41 +#define USB_PID_HIGH 0x00 +#define USB_PID_LOW 0x4F + +/* + * 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 +//#define BOOT_LOAD_PIN PIN_PA15 + +#define BOOT_USART_MODULE SERCOM5 +#define BOOT_USART_BUS_CLOCK_INDEX PM_APBCMASK_SERCOM5 +#define BOOT_USART_PER_CLOCK_INDEX GCLK_CLKCTRL_ID_SERCOM5_CORE_Val +#define BOOT_USART_PAD_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_PAD1 PINMUX_UNUSED +#define BOOT_USART_PAD0 PINMUX_UNUSED + +/* 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) + +/* + * LEDs definitions + */ +// PB08 (digital pin 32) +#define BOARD_LED_PORT (1) +#define BOARD_LED_PIN (8) + +// No RX/TX led +//#define BOARD_LEDRX_PORT +//#define BOARD_LEDRX_PIN + +//#define BOARD_LEDTX_PORT +//#define BOARD_LEDTX_PIN + +#endif // _BOARD_DEFINITIONS_H_ diff --git a/sparkfun/samd/bootloaders/spectacle/board_definitions_arduino_zero.h b/sparkfun/samd/bootloaders/spectacle/board_definitions_arduino_zero.h new file mode 100644 index 00000000..eac27b73 --- /dev/null +++ b/sparkfun/samd/bootloaders/spectacle/board_definitions_arduino_zero.h @@ -0,0 +1,81 @@ +/* + 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 "Arduino Zero" +#define USB_VID_HIGH 0x23 +#define USB_VID_LOW 0x41 +#define USB_PID_HIGH 0x00 +#define USB_PID_LOW 0x4D + +/* + * 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_USART_MODULE SERCOM0 +#define BOOT_USART_BUS_CLOCK_INDEX PM_APBCMASK_SERCOM0 +#define BOOT_USART_PER_CLOCK_INDEX GCLK_CLKCTRL_ID_SERCOM0_CORE_Val +#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 + + +/* 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) + +/* + * 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/sparkfun/samd/bootloaders/spectacle/board_definitions_genuino_mkr1000.h b/sparkfun/samd/bootloaders/spectacle/board_definitions_genuino_mkr1000.h new file mode 100644 index 00000000..d97163d4 --- /dev/null +++ b/sparkfun/samd/bootloaders/spectacle/board_definitions_genuino_mkr1000.h @@ -0,0 +1,83 @@ +/* + 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 "Genuino MKR1000" +#define USB_VID_HIGH 0x23 +#define USB_VID_LOW 0x41 +#define USB_PID_HIGH 0x02 +#define USB_PID_LOW 0x4E + +/* + * 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_USART_MODULE SERCOM0 +#define BOOT_USART_BUS_CLOCK_INDEX PM_APBCMASK_SERCOM0 +#define BOOT_USART_PER_CLOCK_INDEX GCLK_CLKCTRL_ID_SERCOM0_CORE_Val +#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 + + +/* 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) + +/* + * LEDs definitions + */ +// PA20 (digital pin 6) +#define BOARD_LED_PORT (0) +#define BOARD_LED_PIN (20) + +// No RX/TX led +//#define BOARD_LEDRX_PORT +//#define BOARD_LEDRX_PIN + +//#define BOARD_LEDTX_PORT +//#define BOARD_LEDTX_PIN + +#endif // _BOARD_DEFINITIONS_H_ diff --git a/sparkfun/samd/bootloaders/spectacle/board_definitions_genuino_zero.h b/sparkfun/samd/bootloaders/spectacle/board_definitions_genuino_zero.h new file mode 100644 index 00000000..a4e27d83 --- /dev/null +++ b/sparkfun/samd/bootloaders/spectacle/board_definitions_genuino_zero.h @@ -0,0 +1,81 @@ +/* + 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 "Genuino Zero" +#define USB_VID_HIGH 0x23 +#define USB_VID_LOW 0x41 +#define USB_PID_HIGH 0x02 +#define USB_PID_LOW 0x4D + +/* + * 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_USART_MODULE SERCOM0 +#define BOOT_USART_BUS_CLOCK_INDEX PM_APBCMASK_SERCOM0 +#define BOOT_USART_PER_CLOCK_INDEX GCLK_CLKCTRL_ID_SERCOM0_CORE_Val +#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 + + +/* 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) + +/* + * 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/sparkfun/samd/bootloaders/spectacle/board_definitions_sparkfun_spectacle.h b/sparkfun/samd/bootloaders/spectacle/board_definitions_sparkfun_spectacle.h new file mode 100644 index 00000000..aa62309a --- /dev/null +++ b/sparkfun/samd/bootloaders/spectacle/board_definitions_sparkfun_spectacle.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_ + +#define CRYSTALLESS // The Spectacle does not have an external 32kHz oscillator +/* + * USB device definitions + */ +#define STRING_PRODUCT "SparkFun Spectacle Director" +#define USB_VID_HIGH 0x1B +#define USB_VID_LOW 0x4F +#define USB_PID_HIGH 0x88 +#define USB_PID_LOW 0x88 + +/* + * 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_USART_MODULE SERCOM0 +#define BOOT_USART_BUS_CLOCK_INDEX PM_APBCMASK_SERCOM0 +#define BOOT_USART_PER_CLOCK_INDEX GCLK_CLKCTRL_ID_SERCOM0_CORE_Val +#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 + + +/* 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) + +/* + * 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/sparkfun/samd/bootloaders/spectacle/board_driver_led.c b/sparkfun/samd/bootloaders/spectacle/board_driver_led.c new file mode 100644 index 00000000..ffa6c478 --- /dev/null +++ b/sparkfun/samd/bootloaders/spectacle/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/sparkfun/samd/bootloaders/spectacle/board_driver_led.h b/sparkfun/samd/bootloaders/spectacle/board_driver_led.h new file mode 100644 index 00000000..d7d47cad --- /dev/null +++ b/sparkfun/samd/bootloaders/spectacle/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/sparkfun/samd/bootloaders/spectacle/board_driver_serial.h b/sparkfun/samd/bootloaders/spectacle/board_driver_serial.h new file mode 100644 index 00000000..809f7ec0 --- /dev/null +++ b/sparkfun/samd/bootloaders/spectacle/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/sparkfun/samd/bootloaders/spectacle/board_driver_usb.c b/sparkfun/samd/bootloaders/spectacle/board_driver_usb.c new file mode 100644 index 00000000..f1c83f44 --- /dev/null +++ b/sparkfun/samd/bootloaders/spectacle/board_driver_usb.c @@ -0,0 +1,361 @@ +/* + 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 */ + 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/sparkfun/samd/bootloaders/spectacle/board_driver_usb.h b/sparkfun/samd/bootloaders/spectacle/board_driver_usb.h new file mode 100644 index 00000000..4e71b8c1 --- /dev/null +++ b/sparkfun/samd/bootloaders/spectacle/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/sparkfun/samd/bootloaders/spectacle/board_init.c b/sparkfun/samd/bootloaders/spectacle/board_init.c new file mode 100644 index 00000000..6c3f44d7 --- /dev/null +++ b/sparkfun/samd/bootloaders/spectacle/board_init.c @@ -0,0 +1,266 @@ +/* + 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_OSC32K (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; + +#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 + + /* ---------------------------------------------------------------------------------------------- + * 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.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 */ + } + +#if defined(CRYSTALLESS) + + // 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; + } + uint32_t fine =( *((uint32_t *)(NVMCTRL_OTP4) + (NVM_SW_CALIB_DFLL48M_FINE_VAL / 32)) >> (NVM_SW_CALIB_DFLL48M_FINE_VAL % 32) ) + & ((1 << 10) - 1); + if (fine == 0x3ff) { + fine = 0x1ff; + } + + SYSCTRL->DFLLVAL.reg = SYSCTRL_DFLLVAL_COARSE(coarse) | SYSCTRL_DFLLVAL_FINE(fine); + /* Write full configuration to DFLL control register */ + SYSCTRL->DFLLCTRL.reg = SYSCTRL_DFLLCTRL_USBCRM | /* USB correction */ + SYSCTRL_DFLLCTRL_CCDIS | + 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 ; + +#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 */ + } + +#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/sparkfun/samd/bootloaders/spectacle/board_startup.c b/sparkfun/samd/bootloaders/spectacle/board_startup.c new file mode 100644 index 00000000..593d93b6 --- /dev/null +++ b/sparkfun/samd/bootloaders/spectacle/board_startup.c @@ -0,0 +1,141 @@ +/* + 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); +} diff --git a/sparkfun/samd/bootloaders/spectacle/bootloader_samd21x18.ld b/sparkfun/samd/bootloaders/spectacle/bootloader_samd21x18.ld new file mode 100644 index 00000000..2a8b056d --- /dev/null +++ b/sparkfun/samd/bootloaders/spectacle/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/sparkfun/samd/bootloaders/spectacle/build_all_bootloaders.sh b/sparkfun/samd/bootloaders/spectacle/build_all_bootloaders.sh new file mode 100644 index 00000000..e837f7bf --- /dev/null +++ b/sparkfun/samd/bootloaders/spectacle/build_all_bootloaders.sh @@ -0,0 +1,17 @@ +#!/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/ + +echo Done building bootloaders! + diff --git a/sparkfun/samd/bootloaders/spectacle/main.c b/sparkfun/samd/bootloaders/spectacle/main.c new file mode 100644 index 00000000..8d5c52b2 --- /dev/null +++ b/sparkfun/samd/bootloaders/spectacle/main.c @@ -0,0 +1,233 @@ +/* + 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 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(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; + + /* 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/sparkfun/samd/bootloaders/spectacle/sam_ba_cdc.c b/sparkfun/samd/bootloaders/spectacle/sam_ba_cdc.c new file mode 100644 index 00000000..37734092 --- /dev/null +++ b/sparkfun/samd/bootloaders/spectacle/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/sparkfun/samd/bootloaders/spectacle/sam_ba_cdc.h b/sparkfun/samd/bootloaders/spectacle/sam_ba_cdc.h new file mode 100644 index 00000000..49b7643c --- /dev/null +++ b/sparkfun/samd/bootloaders/spectacle/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/sparkfun/samd/bootloaders/spectacle/sam_ba_monitor.c b/sparkfun/samd/bootloaders/spectacle/sam_ba_monitor.c new file mode 100644 index 00000000..8b31b947 --- /dev/null +++ b/sparkfun/samd/bootloaders/spectacle/sam_ba_monitor.c @@ -0,0 +1,553 @@ +/* + 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. + + // 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 + 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->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 + 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/sparkfun/samd/bootloaders/spectacle/sam_ba_monitor.h b/sparkfun/samd/bootloaders/spectacle/sam_ba_monitor.h new file mode 100644 index 00000000..19575ec7 --- /dev/null +++ b/sparkfun/samd/bootloaders/spectacle/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_USBCDC_ONLY //SAM_BA_BOTH_INTERFACES +#endif + +/* Selects USB as the communication interface of the monitor */ +#define SAM_BA_INTERFACE_USBCDC 1 +/* Selects USART as the communication interface of the monitor */ +#define SAM_BA_INTERFACE_USART 0 + +/* 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/sparkfun/samd/bootloaders/spectacle/sam_ba_serial.c b/sparkfun/samd/bootloaders/spectacle/sam_ba_serial.c new file mode 100644 index 00000000..09607ecf --- /dev/null +++ b/sparkfun/samd/bootloaders/spectacle/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/sparkfun/samd/bootloaders/spectacle/sam_ba_serial.h b/sparkfun/samd/bootloaders/spectacle/sam_ba_serial.h new file mode 100644 index 00000000..cb69f459 --- /dev/null +++ b/sparkfun/samd/bootloaders/spectacle/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/sparkfun/samd/bootloaders/spectacle/sam_ba_usb.c b/sparkfun/samd/bootloaders/spectacle/sam_ba_usb.c new file mode 100644 index 00000000..068b81d8 --- /dev/null +++ b/sparkfun/samd/bootloaders/spectacle/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/sparkfun/samd/bootloaders/spectacle/sam_ba_usb.h b/sparkfun/samd/bootloaders/spectacle/sam_ba_usb.h new file mode 100644 index 00000000..457fdbc0 --- /dev/null +++ b/sparkfun/samd/bootloaders/spectacle/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/sparkfun/samd/bootloaders/spectacle/sparkfun_spectacle.atsln b/sparkfun/samd/bootloaders/spectacle/sparkfun_spectacle.atsln new file mode 100644 index 00000000..0641335d --- /dev/null +++ b/sparkfun/samd/bootloaders/spectacle/sparkfun_spectacle.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}") = "sparkfun_spectacle", "sparkfun_spectacle.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/sparkfun/samd/bootloaders/spectacle/sparkfun_spectacle.bin b/sparkfun/samd/bootloaders/spectacle/sparkfun_spectacle.bin new file mode 100644 index 00000000..7aed3449 Binary files /dev/null and b/sparkfun/samd/bootloaders/spectacle/sparkfun_spectacle.bin differ diff --git a/sparkfun/samd/bootloaders/spectacle/sparkfun_spectacle.componentinfo.xml b/sparkfun/samd/bootloaders/spectacle/sparkfun_spectacle.componentinfo.xml new file mode 100644 index 00000000..e2757552 --- /dev/null +++ b/sparkfun/samd/bootloaders/spectacle/sparkfun_spectacle.componentinfo.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/sparkfun/samd/bootloaders/spectacle/sparkfun_spectacle.cproj b/sparkfun/samd/bootloaders/spectacle/sparkfun_spectacle.cproj new file mode 100644 index 00000000..3894f194 --- /dev/null +++ b/sparkfun/samd/bootloaders/spectacle/sparkfun_spectacle.cproj @@ -0,0 +1,229 @@ + + + + 2.0 + 7.0 + com.Atmel.ARMGCC.C + dce6c7e3-ee26-4d79-826b-08594b9ad897 + ATSAMD21G18A + none + Executable + C + $(MSBuildProjectName) + .elf + $(MSBuildProjectDirectory)\$(Configuration) + sparkfun_spectacle + sparkfun_spectacle + sparkfun_spectacle + Native + true + false + true + true + 0x20000000 + + true + exception_table + 2 + 0 + + + + + + + + + + + + + + com.atmel.avrdbg.tool.jtagice3plus + J30200029917 + 0x10010005 + SWD + + + + 0 + + SWD + + com.atmel.avrdbg.tool.atmelice + J41800001895 + Atmel-ICE + + 2000000 + + + + + SWD + + com.atmel.avrdbg.tool.edbg + ATML2320040200000259 + EDBG + + + + + 2000000 + + SWD + + com.atmel.avrdbg.tool.jtagice3plus + J30200029917 + JTAGICE3 + + + + + + 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/sparkfun/samd/bootloaders/spectacle/sparkfun_spectacle.hex b/sparkfun/samd/bootloaders/spectacle/sparkfun_spectacle.hex new file mode 100644 index 00000000..4866cedb --- /dev/null +++ b/sparkfun/samd/bootloaders/spectacle/sparkfun_spectacle.hex @@ -0,0 +1,340 @@ +:10000000FC7F00209D0500008D050000910500008B +:1000100000000000000000000000000000000000E0 +:100020000000000000000000000000009505000036 +:10003000000000000000000099050000CD0600004F +:1000400010B5064C2378002B07D1054B002B02D0AE +:10005000044800E000BF0123237010BD5C000020B5 +:1000600000000000BC14000008B5084B002B03D0B2 +:100070000748084900E000BF07480368002B03D089 +:10008000064B002B00D0984708BDC046000000007A +:10009000BC14000060000020580000200000000098 +:1000A000154A164B1178002909D115491878097895 +:1000B0004118C9B21970802012498002C8611178B4 +:1000C0000131C9B211701978F02902D819780929BB +:1000D00009D80B4908784042C0B2087018780978EE +:1000E0004118C9B2197012781B789A4203D1802244 +:1000F000044B9202DA617047780000200100002072 +:10010000000000200044004170B50368041C988B77 +:100110001A1C0821FF32084226D080209983987249 +:10012000112353704021144B917150715E68134D2F +:10013000C0202E40800506435E605E69354028433E +:1001400058610F4818600F4818615D680E482840D4 +:100150008025AD02284358605868800B80035860A2 +:1001600000235171237105E0137ADA0602D5201CB1 +:1001700000F0E6FA207970BD98010020FFFFFF8FA4 +:100180009800002018010020FF3F00F000230371B9 +:100190004371044B016083600B78022213430B70A0 +:1001A0007047C0460901000038B5364B2021DA6996 +:1001B00001200A43DA61344B06241A7802431A708C +:1001C000324B0F2219789143197019782143197015 +:1001D0002F490C782043087019780A401A701A7851 +:1001E00060210A431A702B4B2B4A5A805A7852B21C +:1001F000002AFBDB294B01211A780A431A709A78EE +:10020000D107FCD426480268510B1F2211409142AD +:1002100000D1052111408C011D8D22492940214327 +:1002200019850468A10C0A401F2A00D11D221C8DCB +:100230001F210A408C4322431A8502680721D20DF0 +:100240000A408A4200D103220A40188D1103164A3F +:1002500002400A431A8519787F220A401A701A78D8 +:10026000042112480A431A7058621A890C218A43E1 +:100270001A811A8901218A431A810021802200F003 +:10028000A4FF38BD00040040584400413C440041F4 +:1002900059440041000C004006400000005000415D +:1002A000246080003FF8FFFFFF8FFFFF98010020D0 +:1002B000F7B5141C1F4A5F0101971D1CD319061CBA +:1002C0005869271C4000400F03301033C74006D048 +:1002D0000F1C8022596812060A435A6009E02F1C3D +:1002E0007B1E9F41144BBF01FF18381C221C00F0DD +:1002F00063FF01990F48083542181761131C5269B2 +:10030000A104920B890C92030A435A6159690B4A62 +:100310000A405A616B01F3180222DA71597980227E +:1003200052420A435A716B01F318DB799A07FAD5E6 +:10033000201CFEBD9801002018010020FF3F00F0A6 +:10034000F8B51A4E051C3378141C002B12D1184B2B +:10035000184A1A645A6C920B92035A64586C164AE3 +:1003600002405A64A2235B00EA5C40200243EA5444 +:10037000012333704827FF37EA5D0123134012D071 +:100380000B4B5A6C9204920CA24202D25C6CA404F5 +:10039000A40C081C221C074900F00EFF0123EB559A +:1003A0000023337000E01C1C201CF8BD79000020E5 +:1003B00098010020D8000020FF3F00F0FF30837933 +:1003C0002022002900D110221343837170470000BE +:1003D000084BFF305A69920B92035A610223037251 +:1003E000827980235B4213438371037A9A07FCD599 +:1003F0007047C0469801002080235B421943C9B270 +:100400008172704770B5A02303225B00C254134B66 +:10041000134A5C6CC021144089050C4346255C647A +:10042000FF35402444550F4D30261D6490256D0046 +:1004300046555D6B15402943922559636D00802117 +:100440004155094D1D63B0256D0044555C6F224038 +:100450005A67B2235B00C15470BDC04698010020AA +:10046000FFFFFF8FD80000205801002030B53B4B24 +:100470001E215A688A4302210A4339495A608B690E +:1004800008221343374A8B611368D804400E364B59 +:1004900000041843354B9861101CDA685407FCD5EA +:1004A000334A012414701478E50704D5304C64787D +:1004B00064B2002CF7DB01249460547864B2002C01 +:1004C000FBDB2C4D2A4C6560547864B2002CFBDBBE +:1004D0008225274CED016580547864B2002CFBDB4B +:1004E0009C8C8025AC439C84DC68E506FCD5224DC1 +:1004F0001E4CE562DC68E506FCD50468A40E3F2CC2 +:1005000000D11F241D481E4D00688005800DA842A3 +:1005100000D11C48A40220439862B22000019884B4 +:10052000DC681248E506FBD5848C02252C438484C4 +:10053000D868C406FCD50023936053785BB2002BC7 +:10054000FBDB11480A4B586053785BB2002BFBDB96 +:1005500000230B724B728B72CB7230BD0040004196 +:1005600000040040246080000606000000080040EF +:10057000000C004001040100B805FF7D28608000E8 +:10058000FF030000FF010000000703000EBEFEE7AE +:100590000DBEFEE705BEFEE702BEFEE70E4A0F48AF +:1005A00038B5824204D10E4A0E4B93420ED10AE076 +:1005B0000D4C9442F7D00023D1188842F3D9E55866 +:1005C00004330D60F8E700F011F804E09342FAD22A +:1005D000002102C3FAE7FEE7000000205C000020D3 +:1005E000980200205C000020C01400002B4A38B59F +:1005F0001368141C01331ED0D1B200291BD1284B23 +:10060000187801231840274B0AD11D6826498D42CE +:1006100001D118600FE01960244901390029FCD18B +:100620001960236883F30888FF239A43204B9A605C +:100630001A4B5B681847FFF719FF62B600F04CF8D9 +:100640001C4B802292021C499A6008220A601B49B6 +:10065000041C0A60802212059A609A61184B194A9C +:10066000C0215A60124A0906106A0002000A0143BA +:10067000116200229A6007221A60A368201C984722 +:10068000114B002801D001221A701B78002BF4D0E6 +:10069000012000F085FA00F0FFFAFCE700200000DE +:1006A00038040040FC7F00203581730748E80100D2 +:1006B00000ED00E0004400418844004198440041BE +:1006C00010E000E0E70300007A00002008B5FFF723 +:1006D000E7FC00F0BDFA08BD10B5054B054C2360E2 +:1006E000FFF762FD201C2168FFF750FD201C10BDA4 +:1006F000005000411802002070B5051CC0B0081C55 +:10070000161C0C1C00F069FD40006A4603230230F1 +:100710005370107076080123E218013A11785A00DC +:10072000002906D1281C69460023FFF7C1FD40B00F +:1007300070BDB342F6DA684681520133ECE700003F +:10074000F7B5BA4A04681378B949271CFF37051C66 +:10075000102038720B705378B648B74E03709378F8 +:100760003380D178338809020B4333801179B34B3E +:100770001980517918880902084318809079B04986 +:100780000880D2790888120202430A8040227A71D6 +:10079000A84F3A78A64F120238780F1C0243A94896 +:1007A0008446181C624500D1C2E020DC802149004B +:1007B0008A4200D16EE109DC812A00D192E0822ACE +:1007C00000D195E0802A00D064E18BE081235B00BA +:1007D0009A4200D1CFE000DA58E1C0239B009A4250 +:1007E00000D157E1984B9A4200D14FE152E190235A +:1007F0001B019A4269D015DCD023DB009A4222D03B +:1008000088231B019A4269D0A023DB009A4200D0C2 +:1008100040E1201CFFF7DCFD3188286889B2FFF732 +:10082000EBFD3BE1894B9A4200D12FE100DC31E145 +:10083000874B9A4200D11DE1864B9A4200D029E1B4 +:1008400033886B7122E133881B0A012B08D10B8896 +:1008500012222868934201D80A8892B27E4911E197 +:1008600033881B0A022B08D10B8843222868934245 +:1008700001D80A8892B2794904E133881B0A032B14 +:1008800000D007E13388DBB2012B17D0002B07D053 +:10089000022B00D0FEE00A882868D2B2704911E02D +:1008A000042201A86F4900F087FC3B8804222868D5 +:1008B000934201D83A8892B201A9E3E00A882868F5 +:1008C0006949D2B2FFF718FFE8E03388201C2B718A +:1008D000FFF77EFD201CFFF795FDDFE0291C01C915 +:1008E0000122CFE0614900230B8028680222CAE080 +:1008F0005E4900220A801888502210405C4A10701D +:100900001E880F20304018801888032800D9C1E0C5 +:1009100012781B8808335B01E418A379002A01D000 +:100920009B0600E0DB06DB0F0B8028680222A9E0B3 +:1009300019887F2291434E4AC9B2117018880F213D +:10094000014019803188002900D0A3E019880029CE +:1009500000D19FE01988032900D99BE012781B88F9 +:1009600008335B01E318002A02D020225A718DE07F +:10097000102159718AE002887F239A433C4BD2B2FE +:100980001A7001880F220A4002803288002A00D0A3 +:1009900080E00288002A00D17CE00288032A00D986 +:1009A00078E01B78002B1FD0038808335B01E31825 +:1009B0009B799A066AD50388202208335B01E318E5 +:1009C0001A71038808335B01E318DB795F065DD594 +:1009D0000388402208335B01E318DA71038802229E +:1009E00008335B01E3181EE0038808335B01E3185A +:1009F0009B79D9064AD50388102208335B01E31896 +:100A00001A71038808335B01E318DB799A063DD538 +:100A10000388202208335B01E318DA71038801227E +:100A200008335B01E3181A7130E0C04698000020DB +:100A30007C0000208200002084000020860000202E +:100A400080000020020300000103000021200000BC +:100A5000A1210000212200002C120000040000202F +:100A60001012000000120000041200007E0000209E +:100A70007B0000200B8808222868934201D80A884E +:100A800092B207490023FFF713FC07E0201CFFF791 +:100A90009FFC03E0201C0121FFF790FCF7BDC0463E +:100AA0004800002007B5054B0122019001A91868F4 +:100AB000131CFFF7FDFB01200EBDC04618020020ED +:100AC00013B5054B6C4607341868211C0122FFF74B +:100AD00037FC207816BDC0461802002010B5074C20 +:100AE000201CFFF711FB031C0020834205D0226865 +:100AF0004823FF33D05C0123184010BD18020020AA +:100B000010B5054A0C1C031C191C10680123221C7B +:100B1000FFF7CEFB201C10BD1802002070B5084C5A +:100B2000061C201C0D1CFFF7EFFA0023984205D08D +:100B30002068311C2A1CFFF703FC031C181C70BD25 +:100B400018020020F8B50C4C051C201C0E1CFFF7E9 +:100B5000DBFA0023271C341C98420AD0002C07D053 +:100B6000291C221C3868FFF7EBFB241A2D18F5E727 +:100B7000331C181CF8BDC0461802002008B5031C21 +:100B8000081C111C9847044B802212055A61034B24 +:100B900064221A8008BDC046004400418C00002039 +:100BA000012802D1014A024B1A60704790120000DE +:100BB0008802002030B50A1C1C4985B00978031C46 +:100BC00000292AD0042A01D1006804E0022A01D1B8 +:100BD000008800E00078520004A98B180B3B9C1A97 +:100BE000A3420BD00F210140092902D83025294307 +:100BF00000E0373119700009013BF1E701A930230A +:100C00000B7078234B700A208B1898700D20D870C9 +:100C1000074B04321B68D86803E005490968C868B7 +:100C2000191CFFF7ABFF05B030BDC046880000209F +:100C30008802002072B6EFF30883044A1360036849 +:100C400083F30888436818477047C0468C02002029 +:100C50000D4B1A88002A09D01A88013A92B21A80DC +:100C6000002A03D18022094B12059A61084B1A8889 +:100C7000002A08D01A88013A92B21A80002A02D1BA +:100C8000044B08221A6070478C0000200044004189 +:100C90008A00002098440041F0B591B008A9CE4ADE +:100CA0000B1C31CA31C351CA51C360CA60C3CB4B9C +:100CB000CB489A687A255203520F92005258C9497C +:100CC00002609C68A4B262430C60C74900240A60B9 +:100CD000C64A1460C64C2570C64CC74D2368281CF4 +:100CE0001B6940219847002805D0C44B08221A6090 +:100CF000C34B64221A80C34B00221860C24B1D6094 +:100D0000C24BC24DBF4F1A602A683B689A42E3D279 +:100D1000BD4B1B681A78FF2A00D120E2232A00D09D +:100D2000F7E1BB4E3378002B06D0B24BB9491B68B4 +:100D30000222D868FFF722FFAD4B1B78532B3FD11F +:100D40003B682A6893421ED9AF4801322A609A1A3A +:100D5000B14B01681B6801310160B04E9A4201D26B +:100D6000326000E03360A14832680068049000F00F +:100D700023FA336829685A182A60A34A1668F118BA +:100D80001160A74A13702B68013B2B609E4B1A68B9 +:100D9000013A1A60A24BA04A1B7811688B420DD20F +:100DA00022689248C91A006892699047002805D0C5 +:100DB000924B08221A60924B64221A80C04696E138 +:100DC000522B0ED18948944A2368006811685B69E8 +:100DD00003909847934B802212055A616422924BEC +:100DE0000DE04F2B05D1814B8B4A1B6812681A709E +:100DF0007DE1482B05D17D4B874A1B6812681A801C +:100E000075E1572B05D1794B834A1B6812681A602C +:100E10006DE16F2B03D1754B0121186807E0682B3A +:100E200008D1724B7C481B6802211B880360FFF7C6 +:100E3000C1FE5CE1772B06D16C4B77481B6804211F +:100E40001B680360F3E7472B13D1734B1868FFF758 +:100E5000F1FE764B1B6883F3088862B6744B1B78EF +:100E6000002B00D143E1634B06201B681B689847A9 +:100E70003DE1542B04D1012333705E4B1B6864E0C9 +:100E80004E2B0CD13378002B06D15A4B61491B688D +:100E90000222D868FFF772FE0023337027E1562B39 +:100EA00057D123686349D8680122FFF767FE23689A +:100EB0006149D8680322FFF761FE604D2368291C51 +:100EC000D8680122FFF75AFE23685D49D8680D22D1 +:100ED000FFF754FE2368291CD8680122FFF74EFE55 +:100EE000494F4A4D5749002339602B603A1C281C52 +:100EF00013685E1C16601B780593002B03D00368F3 +:100F000001330360F4E73B4E2A683368D868FFF783 +:100F100035FE33684949D8680122FFF72FFE05994D +:100F2000296049493960384A1368581C10601B7899 +:100F3000002B04D0354B1A6801321A60F3E733688E +:100F40002A68D868FFF71AFE3368D8683149022248 +:100F5000CBE0314A582B17D1214E234D3668136808 +:100F60002A68B10093420AD21C4D5808E8613748FC +:100F700028801A4D287DC607FBD55B18F2E71D4B6C +:100F800033491B68D868AFE0592B00D07DE0126868 +:100F9000164B3049002A02D11B680B6070E00F4DE0 +:100FA000086819686B680D4E8025AB439208736022 +:100FB000002A65D0284B094D2B80084E337DDD0774 +:100FC000FBD50023064D2D680195AD08AB4247D3F4 +:100FD000224D024E35804AE04012000000400041A0 +:100FE0004002002038020020340200208402002049 +:100FF0003002002088020020440200209444004176 +:101000008A000020280200202C0200203C02002040 +:10101000880000208412000090020020940200202A +:1010200024020020004400418C0000208C0200209B +:10103000940000206012000089120000621200007B +:10104000AC120000641200007012000002A5FFFF45 +:10105000791200009000002044A5FFFF04A5FFFFC7 +:101060009342B5D09D00465901334E51AAE7404EF8 +:10107000357DEE07FBD59D0049194019D21A97E737 +:101080003C4B3D491B68D8682EE05A2B2FD13B4B77 +:1010900017681D680026EF19BD4206D02878311C5C +:1010A00000F07EF80135061CF6E7324B34491B6828 +:1010B0000122D868FFF762FD07230F223240111C7E +:1010C00036093031092A00DD07311820C0186A4678 +:1010D0008154013BF1D2236806A9D8680822FFF7A2 +:1010E0004DFD23682749D8680322FFF747FD264BAB +:1010F0007A221A70254B00221A60254B1B789342E6 +:101100002DD01C4B23491B680122D868FFF736FD00 +:1011100025E0111C3039C8B21C4B092804D81D68C1 +:101120002A01114319601AE0111C4139052903D81D +:101130001E68373A310106E0111C6139052904D8CF +:101140001868573A01010A4308E02C2A03D10B4AD8 +:101150001968116001E00C490A7000221A600E4BF8 +:101160001A6801321A600D4B1A680132C9E5C0468F +:1011700000400041880200207D120000840200200F +:101180008112000083120000300200209002002033 +:1011900088000020871200003C0200202C02002062 +:1011A0000B0A5840034B4000C05A0902484080B225 +:1011B0007047C046BA12000010B50023934203D016 +:1011C000CC5CC4540133F9E710BD031C8218934270 +:1011D00002D019700133FAE770470023C25C013373 +:1011E000002AFBD1581E7047F8B5C046F8BC08BCB1 +:1011F0009E467047F8B5C046F8BC08BC9E4670478E +:101200000403090441726475696E6F204C4C4300FD +:10121000537061726B46756E2053706563746163C1 +:101220006C65204469726563746F7200120100027C +:10123000020000404F1B88880002010200010000EC +:101240000800000010000000200000004000000026 +:101250008000000000010000000200000004000007 +:10126000760020004A616E20313120323031370063 +:1012700031343A33333A343100580A0D00590A0DEB +:10128000005A00230A0D003E00322E3000000000FC +:10129000A50A0000C10A0000DD0A0000010B0000E1 +:1012A0001D0B0000010B0000450B00005B41726448 +:1012B00075696E6F3A58595A5D000000211042203E +:1012C00063308440A550C660E770088129914AA127 +:1012D0006BB18CC1ADD1CEE1EFF13112100273329E +:1012E0005222B5529442F772D662399318837BB377 +:1012F0005AA3BDD39CC3FFF3DEE36224433420042E +:101300000114E664C774A44485546AA54BB52885C6 +:101310000995EEE5CFF5ACC58DD55336722611167D +:101320003006D776F6669556B4465BB77AA7199716 +:101330003887DFF7FEE79DD7BCC7C448E558866805 +:10134000A7784008611802282338CCC9EDD98EE966 +:10135000AFF9488969990AA92BB9F55AD44AB77ADD +:10136000966A711A500A333A122AFDDBDCCBBFFBB6 +:101370009EEB799B588B3BBB1AABA66C877CE44CED +:10138000C55C222C033C600C411CAEED8FFDECCD06 +:10139000CDDD2AAD0BBD688D499D977EB66ED55EBD +:1013A000F44E133E322E511E700E9FFFBEEFDDDF56 +:1013B000FCCF1BBF3AAF599F788F8891A981CAB1E2 +:1013C000EBA10CD12DC14EF16FE18010A100C23014 +:1013D000E3200450254046706760B9839893FBA3CF +:1013E000DAB33DC31CD37FE35EF3B1029012F32264 +:1013F000D2323542145277625672EAB5CBA5A8951F +:1014000089856EF54FE52CD50DC5E234C324A014B3 +:1014100081046674476424540544DBA7FAB79987AE +:10142000B8975FE77EF71DC73CD7D326F236910603 +:10143000B01657667676154634564CD96DC90EF9F6 +:101440002FE9C899E9898AB9ABA944586548067853 +:101450002768C018E1088238A3287DCB5CDB3FEB0E +:101460001EFBF98BD89BBBAB9ABB754A545A376AA3 +:10147000167AF10AD01AB32A923A2EFD0FED6CDDDE +:101480004DCDAABD8BADE89DC98D267C076C645CF3 +:10149000454CA23C832CE01CC10C1FEF3EFF5DCFEE +:1014A0007CDF9BAFBABFD98FF89F176E367E554E43 +:1014B000745E932EB23ED10EF01E000000000000BC +:1014C00001140000090243000201008032090400F7 +:1014D000000102020000052400100104240200059E +:1014E000240600010524010001070583030800FF0D +:1014F00009040100020A0000000705810240000003 +:10150000070502024000000000C2010000000800C0 +:0C15100069000000410000000000000025 +:040000030000059D57 +:00000001FF diff --git a/sparkfun/samd/cores/arduino/Arduino.h b/sparkfun/samd/cores/arduino/Arduino.h index b6fd4e73..e645743b 100644 --- a/sparkfun/samd/cores/arduino/Arduino.h +++ b/sparkfun/samd/cores/arduino/Arduino.h @@ -55,6 +55,10 @@ extern "C"{ void yield( void ) ; +/* system functions */ +int main( void ); +void init( void ); + /* sketch */ void setup( void ) ; void loop( void ) ; diff --git a/sparkfun/samd/cores/arduino/Reset.cpp b/sparkfun/samd/cores/arduino/Reset.cpp index 8809907e..053d7c5f 100644 --- a/sparkfun/samd/cores/arduino/Reset.cpp +++ b/sparkfun/samd/cores/arduino/Reset.cpp @@ -24,7 +24,15 @@ extern "C" { #endif #define NVM_MEMORY ((volatile uint16_t *)0x000000) + +#if (ARDUINO_SAMD_VARIANT_COMPLIANCE >= 10610) + +extern const uint32_t __text_start__; +#define APP_START ((volatile uint32_t)(&__text_start__) + 4) + +#else #define APP_START 0x00002004 +#endif static inline bool nvmReady(void) { return NVMCTRL->INTFLAG.reg & NVMCTRL_INTFLAG_READY; @@ -35,6 +43,13 @@ static void banzai() { // Disable all interrupts __disable_irq(); + // 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()) ; @@ -44,6 +59,7 @@ static void banzai() { while (!nvmReady()) ; +reset: // Reset the device NVIC_SystemReset() ; diff --git a/sparkfun/samd/cores/arduino/USB/SAMD21_USBDevice.h b/sparkfun/samd/cores/arduino/USB/SAMD21_USBDevice.h index 31b9e965..a33bc1b0 100644 --- a/sparkfun/samd/cores/arduino/USB/SAMD21_USBDevice.h +++ b/sparkfun/samd/cores/arduino/USB/SAMD21_USBDevice.h @@ -106,7 +106,7 @@ class USBDevice_SAMD21G18x { 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.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; } diff --git a/sparkfun/samd/cores/arduino/USB/USBDesc.h b/sparkfun/samd/cores/arduino/USB/USBDesc.h index e4335aa9..6088ee08 100644 --- a/sparkfun/samd/cores/arduino/USB/USBDesc.h +++ b/sparkfun/samd/cores/arduino/USB/USBDesc.h @@ -41,7 +41,7 @@ #define CDC_TX CDC_ENDPOINT_IN #endif -#define ISERIAL_MAX_LEN 20 +#define ISERIAL_MAX_LEN 33 // Defined string description #define IMANUFACTURER 1 diff --git a/sparkfun/samd/cores/arduino/startup.c b/sparkfun/samd/cores/arduino/startup.c index 3e01e79a..73b7526f 100644 --- a/sparkfun/samd/cores/arduino/startup.c +++ b/sparkfun/samd/cores/arduino/startup.c @@ -38,6 +38,7 @@ // Constants for Clock generators #define GENERIC_CLOCK_GENERATOR_MAIN (0u) #define GENERIC_CLOCK_GENERATOR_XOSC32K (1u) +#define GENERIC_CLOCK_GENERATOR_OSC32K (1u) #define GENERIC_CLOCK_GENERATOR_OSCULP32K (2u) /* Initialized at reset for WDT */ #define GENERIC_CLOCK_GENERATOR_OSC8M (3u) // Constants for Clock multiplexers @@ -51,6 +52,24 @@ void SystemInit( void ) /* 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 + /* ---------------------------------------------------------------------------------------------- * 1) Enable XOSC32K clock (External on-board 32.768Hz oscillator) */ @@ -63,6 +82,8 @@ void SystemInit( void ) /* 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 @@ -85,8 +106,12 @@ void SystemInit( void ) } /* Write Generic Clock Generator 1 configuration */ - GCLK->GENCTRL.reg = GCLK_GENCTRL_ID( GENERIC_CLOCK_GENERATOR_XOSC32K ) | // Generic Clock Generator 1 + 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 ; @@ -130,6 +155,40 @@ void SystemInit( void ) /* Wait for synchronization */ } +#if defined(CRYSTALLESS) + + #define NVM_SW_CALIB_DFLL48M_COARSE_VAL 58 + #define NVM_SW_CALIB_DFLL48M_FINE_VAL 64 + + // 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; + } + uint32_t fine =( *((uint32_t *)(NVMCTRL_OTP4) + (NVM_SW_CALIB_DFLL48M_FINE_VAL / 32)) >> (NVM_SW_CALIB_DFLL48M_FINE_VAL % 32) ) + & ((1 << 10) - 1); + if (fine == 0x3ff) { + fine = 0x1ff; + } + + SYSCTRL->DFLLVAL.reg = SYSCTRL_DFLLVAL_COARSE(coarse) | SYSCTRL_DFLLVAL_FINE(fine); + /* Write full configuration to DFLL control register */ + SYSCTRL->DFLLCTRL.reg = SYSCTRL_DFLLCTRL_USBCRM | /* USB correction */ + SYSCTRL_DFLLCTRL_CCDIS | + 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 ; + +#else // has crystal + /* Write full configuration to DFLL control register */ SYSCTRL->DFLLCTRL.reg |= SYSCTRL_DFLLCTRL_MODE | /* Enable the closed loop mode */ SYSCTRL_DFLLCTRL_WAITLOCK | @@ -149,6 +208,8 @@ void SystemInit( void ) /* Wait for locks flags */ } +#endif + while ( (SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLRDY) == 0 ) { /* Wait for synchronization */ diff --git a/sparkfun/samd/platform.txt b/sparkfun/samd/platform.txt index 51399dd8..b8b74381 100644 --- a/sparkfun/samd/platform.txt +++ b/sparkfun/samd/platform.txt @@ -20,7 +20,7 @@ # https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5---3rd-party-Hardware-specification name=SparkFun SAMD (32-bits ARM Cortex-M0+) Boards -version=1.3.2 +version=1.3.3 # Compile variables # ----------------- diff --git a/sparkfun/samd/variants/SparkFun_Spectacle_Director/debug_scripts/variant.gdb b/sparkfun/samd/variants/SparkFun_Spectacle_Director/debug_scripts/variant.gdb new file mode 100644 index 00000000..3c37ffde --- /dev/null +++ b/sparkfun/samd/variants/SparkFun_Spectacle_Director/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/sparkfun/samd/variants/SparkFun_Spectacle_Director/linker_scripts/gcc/flash_with_bootloader.ld b/sparkfun/samd/variants/SparkFun_Spectacle_Director/linker_scripts/gcc/flash_with_bootloader.ld new file mode 100644 index 00000000..4475f951 --- /dev/null +++ b/sparkfun/samd/variants/SparkFun_Spectacle_Director/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/sparkfun/samd/variants/SparkFun_Spectacle_Director/linker_scripts/gcc/flash_without_bootloader.ld b/sparkfun/samd/variants/SparkFun_Spectacle_Director/linker_scripts/gcc/flash_without_bootloader.ld new file mode 100644 index 00000000..0162f077 --- /dev/null +++ b/sparkfun/samd/variants/SparkFun_Spectacle_Director/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/sparkfun/samd/variants/SparkFun_Spectacle_Director/openocd_scripts/arduino_zero.cfg b/sparkfun/samd/variants/SparkFun_Spectacle_Director/openocd_scripts/arduino_zero.cfg new file mode 100644 index 00000000..36c65c32 --- /dev/null +++ b/sparkfun/samd/variants/SparkFun_Spectacle_Director/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/sparkfun/samd/variants/SparkFun_Spectacle_Director/pins_arduino.h b/sparkfun/samd/variants/SparkFun_Spectacle_Director/pins_arduino.h new file mode 100644 index 00000000..db0e40c3 --- /dev/null +++ b/sparkfun/samd/variants/SparkFun_Spectacle_Director/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/sparkfun/samd/variants/SparkFun_Spectacle_Director/variant.cpp b/sparkfun/samd/variants/SparkFun_Spectacle_Director/variant.cpp new file mode 100644 index 00000000..85ba2416 --- /dev/null +++ b/sparkfun/samd/variants/SparkFun_Spectacle_Director/variant.cpp @@ -0,0 +1,221 @@ +/* + Copyright (c) 2014-2015 Arduino LLC. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + 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" + +/* + * 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), 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, 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] + + // 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 +} ; + +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 Serial( &sercom5, PIN_SERIAL_RX, PIN_SERIAL_TX, PAD_SERIAL_RX, PAD_SERIAL_TX ) ; +void SERCOM0_Handler() +{ + Serial1.IrqHandler(); +} + +void SERCOM5_Handler() +{ + Serial.IrqHandler(); +} + diff --git a/sparkfun/samd/variants/SparkFun_Spectacle_Director/variant.h b/sparkfun/samd/variants/SparkFun_Spectacle_Director/variant.h new file mode 100644 index 00000000..4cbf6bee --- /dev/null +++ b/sparkfun/samd/variants/SparkFun_Spectacle_Director/variant.h @@ -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 +*/ + +#ifndef _VARIANT_SPECTACLE_DIRECTOR_ +#define _VARIANT_SPECTACLE_DIRECTOR_ + +// The definitions here needs a SAMD core >=1.6.6 +#define ARDUINO_SAMD_VARIANT_COMPLIANCE 10606 + +/*---------------------------------------------------------------------------- + * Definitions + *----------------------------------------------------------------------------*/ + +#define CRYSTALLESS 1 // The Spectacle does not have an external 32kHz oscillator + +/** Frequency of the board main oscillator */ +#define VARIANT_MAINOSC (32768ul) + +/** Master clock frequency */ +#define VARIANT_MCK (48000000ul) + +/*---------------------------------------------------------------------------- + * 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 (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 + +/* + * 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_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 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 Serial; +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 SerialUSB +#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_SPECTACLE_DIRECTOR_ */ +