Compare commits

...

1 commit

Author SHA1 Message Date
Scott Shawcroft
aa9868d3f2 Re-org build in preparation for SAMD51 support.
SAMD51 builds

Enumerates ok but flash doesn't work.

Do manual flash writes and slow delay down when we have a much faster clock.

DM: fixed nvmctrl math in erase

DM: actually I think they want manual page writes

Re-enabled self-updater with SAMD51 support.

Get the version dynamically from git.

Correct flash offset now that we use a uint8_t pointer.

Turn on the neopixel.

Fix M0 compilation by avoiding USB macro.

Add board.mk files for every board.

Clean up ignores

Add grove zero board config file.

Don't use M0 name in the Zero bootloader

add board.mk for grove-zero

Add version info to all generated files.
Add .ino generation to scripts/gendata.py.
Clean up Makefile to handle new version number generation.

Note that Adafruit release tags will be v<a>.<b>.<c>-adafruit.<n>.
The first part of the tag is the upstream version. The <n> is the
Adafruit increment from that.

add pirkey and itsybitsy m0
change dotstar brightness to account for new 'dimmer' apa102's
update makefile to not use py3

consistancy and missing CRYSTALLESS

special metro m0 delay to avoid SWD contention while programming

Update to more recent Arduino

Add comment

Restore IRQs in neopixel functions

Remove -mlong-calls and add -nostartfiles; see #29
  Thanks @awatterott!

Avoid global writes in handover

Handle first read after handover correctly

V1.24; Add O marker for fixed MSC handover

Make the bootloader data go first in binary to avoid HardFault when erasing first page

Update samd pkg version

Fixes for WebUSB support

Fix Windows build

Remove WebUSB landing page support

add _binfo defn to linker scripts for doing usermode handover.

add proper serial number to USB descriptor; fix compile warning
2018-02-13 13:34:31 -05:00
58 changed files with 1889 additions and 311 deletions

3
.gitignore vendored
View file

@ -4,3 +4,6 @@ uf2-bootloader.elf
tmp
*.sw?
Makefile.user
node_modules
scripts/clean-ifaces/*.plist
.vscode/c_cpp_properties.json

3
.gitmodules vendored Normal file
View file

@ -0,0 +1,3 @@
[submodule "lib/uf2"]
path = lib/uf2
url = https://github.com/Microsoft/uf2.git

View file

@ -1,43 +0,0 @@
{
"configurations": [
{
"name": "Mac",
"includePath": [
"/usr/include"
],
"browse": {
"limitSymbolsToIncludedHeaders": true,
"databaseFilename": "",
"path": [
"/usr/include"
]
}
},
{
"name": "Linux",
"includePath": [
"/usr/include"
],
"browse": {
"limitSymbolsToIncludedHeaders": true,
"databaseFilename": "",
"path": [
"/usr/include"
]
}
},
{
"name": "Win32",
"includePath": [
"c:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/include"
],
"browse": {
"limitSymbolsToIncludedHeaders": true,
"databaseFilename": "",
"path": [
"c:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/include"
]
}
}
]
}

109
Makefile
View file

@ -1,13 +1,19 @@
BOARD=zero
-include Makefile.user
include boards/$(BOARD)/board.mk
CC=arm-none-eabi-gcc
COMMON_FLAGS = -mthumb -mcpu=cortex-m0plus -Os -g
ifeq ($(CHIP_FAMILY), samd21)
COMMON_FLAGS = -mthumb -mcpu=cortex-m0plus -Os -g -DSAMD21
endif
ifeq ($(CHIP_FAMILY), samd51)
COMMON_FLAGS = -mthumb -mcpu=cortex-m4 -O2 -g -DSAMD51
endif
WFLAGS = \
-Wall -Wstrict-prototypes \
-Werror-implicit-function-declaration -Wpointer-arith -std=gnu99 \
-ffunction-sections -fdata-sections -Wchar-subscripts -Wcomment -Wformat=2 \
-Wimplicit-int -Wmain -Wparentheses -Wsequence-point -Wreturn-type -Wswitch \
-Wtrigraphs -Wunused -Wuninitialized -Wunknown-pragmas -Wfloat-equal -Wundef \
-Wtrigraphs -Wunused -Wuninitialized -Wunknown-pragmas -Wfloat-equal -Wno-undef \
-Wbad-function-cast -Wwrite-strings -Waggregate-return \
-Wformat -Wmissing-format-attribute \
-Wno-deprecated-declarations -Wpacked -Wredundant-decls -Wnested-externs \
@ -16,25 +22,47 @@ WFLAGS = \
CFLAGS = $(COMMON_FLAGS) \
-x c -c -pipe -nostdlib \
--param max-inline-insns-single=500 \
-fno-strict-aliasing -fdata-sections -ffunction-sections -mlong-calls \
-fno-strict-aliasing -fdata-sections -ffunction-sections \
-D__$(CHIP_VARIANT)__ \
$(WFLAGS)
UF2_VERSION_BASE = $(shell git describe --dirty --always --tags)
ifeq ($(CHIP_FAMILY), samd21)
LINKER_SCRIPT=scripts/samd21j18a.ld
BOOTLOADER_SIZE=8192
SELF_LINKER_SCRIPT=scripts/samd21j18a_self.ld
endif
ifeq ($(CHIP_FAMILY), samd51)
LINKER_SCRIPT=scripts/samd51j19a.ld
BOOTLOADER_SIZE=16384
SELF_LINKER_SCRIPT=scripts/samd51j19a_self.ld
endif
LDFLAGS= $(COMMON_FLAGS) \
-Wall -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--unresolved-symbols=report-all -Wl,--warn-common \
-Wl,--warn-section-align -Wl,--warn-unresolved-symbols \
-save-temps \
--specs=nano.specs --specs=nosys.specs
-save-temps -nostartfiles \
--specs=nano.specs --specs=nosys.specs
BUILD_PATH=build/$(BOARD)
INCLUDES = -I./inc -I./inc/preprocessor
INCLUDES += -I./asf/sam0/utils/cmsis/samd21/include -I./asf/thirdparty/CMSIS/Include -I./asf/sam0/utils/cmsis/samd21/source
INCLUDES += -I./asf/common -I./asf/common/utils -I./asf/sam0/utils/header_files -I./asf/sam0/utils -I./asf/common/utils/interrupt
INCLUDES += -I./asf/sam0/drivers/system/interrupt -I./asf/sam0/drivers/system/interrupt/system_interrupt_samd21
INCLUDES += -I./boards/$(BOARD)
INCLUDES = -I. -I./inc -I./inc/preprocessor
INCLUDES += -I./boards/$(BOARD) -Ilib/cmsis/CMSIS/Include -Ilib/usb_msc
INCLUDES += -I$(BUILD_PATH)
ifeq ($(CHIP_FAMILY), samd21)
INCLUDES += -Ilib/samd21/samd21a/include/
endif
ifeq ($(CHIP_FAMILY), samd51)
INCLUDES += -Ilib/samd51/include/
endif
COMMON_SRC = \
src/flash.c \
src/init.c \
src/startup_samd21.c \
src/flash_$(CHIP_FAMILY).c \
src/init_$(CHIP_FAMILY).c \
src/startup_$(CHIP_FAMILY).c \
src/usart_sam_ba.c \
src/utils.c
@ -53,9 +81,10 @@ SELF_SOURCES = $(COMMON_SRC) \
OBJECTS = $(patsubst src/%.c,$(BUILD_PATH)/%.o,$(SOURCES))
SELF_OBJECTS = $(patsubst src/%.c,$(BUILD_PATH)/%.o,$(SELF_SOURCES)) $(BUILD_PATH)/selfdata.o
NAME=bootloader
NAME=bootloader-$(BOARD)-$(UF2_VERSION_BASE)
EXECUTABLE=$(BUILD_PATH)/$(NAME).bin
SELF_EXECUTABLE=$(BUILD_PATH)/update-$(NAME).uf2
SELF_EXECUTABLE_INO=$(BUILD_PATH)/update-$(NAME).ino
all: dirs $(EXECUTABLE) $(SELF_EXECUTABLE)
@ -82,32 +111,34 @@ dirs:
@echo "Building $(BOARD)"
-@mkdir -p $(BUILD_PATH)
$(EXECUTABLE): $(OBJECTS)
$(EXECUTABLE): $(OBJECTS)
$(CC) -L$(BUILD_PATH) $(LDFLAGS) \
-T./asf/sam0/utils/linker_scripts/samd21/gcc/samd21j18a_flash.ld \
-T$(LINKER_SCRIPT) \
-Wl,-Map,$(BUILD_PATH)/$(NAME).map -o $(BUILD_PATH)/$(NAME).elf $(OBJECTS)
arm-none-eabi-objcopy -O binary $(BUILD_PATH)/$(NAME).elf $@
@echo
-@arm-none-eabi-size $(BUILD_PATH)/$(NAME).elf | awk '{ s=$$1+$$2; print } END { print ""; print "Space left: " (8192-s) }'
-@arm-none-eabi-size $(BUILD_PATH)/$(NAME).elf | awk '{ s=$$1+$$2; print } END { print ""; print "Space left: " ($(BOOTLOADER_SIZE)-s) }'
@echo
$(BUILD_PATH)/uf2_version.h: Makefile
echo "#define UF2_VERSION_BASE \"$(UF2_VERSION_BASE)\""> $@
$(SELF_EXECUTABLE): $(SELF_OBJECTS)
$(CC) -L$(BUILD_PATH) $(LDFLAGS) \
-T./scripts/samd21j18a_self.ld \
-T$(SELF_LINKER_SCRIPT) \
-Wl,-Map,$(BUILD_PATH)/update-$(NAME).map -o $(BUILD_PATH)/update-$(NAME).elf $(SELF_OBJECTS)
arm-none-eabi-objcopy -O binary $(BUILD_PATH)/update-$(NAME).elf $(BUILD_PATH)/update-$(NAME).bin
node scripts/bin2uf2.js $(BUILD_PATH)/update-$(NAME).bin $@
python2 lib/uf2/utils/uf2conv.py -b $(BOOTLOADER_SIZE) -c -o $@ $(BUILD_PATH)/update-$(NAME).bin
$(BUILD_PATH)/%.o: src/%.c $(wildcard inc/*.h boards/*/*.h)
@echo "$<"
@$(CC) $(CFLAGS) $(BLD_EXTA_FLAGS) $(INCLUDES) $< -o $@
$(BUILD_PATH)/%.o: src/%.c $(wildcard inc/*.h boards/*/*.h) $(BUILD_PATH)/uf2_version.h
echo "$<"
$(CC) $(CFLAGS) $(BLD_EXTA_FLAGS) $(INCLUDES) $< -o $@
$(BUILD_PATH)/%.o: $(BUILD_PATH)/%.c
@$(CC) $(CFLAGS) $(BLD_EXTA_FLAGS) $(INCLUDES) $< -o $@
$(CC) $(CFLAGS) $(BLD_EXTA_FLAGS) $(INCLUDES) $< -o $@
$(BUILD_PATH)/selfdata.c: $(EXECUTABLE) scripts/gendata.js src/sketch.cpp
node scripts/gendata.js $(BUILD_PATH) $(NAME).bin
$(BUILD_PATH)/selfdata.c: $(EXECUTABLE) scripts/gendata.py src/sketch.cpp
python2 scripts/gendata.py $(BOOTLOADER_SIZE) $(EXECUTABLE)
clean:
rm -rf build
@ -134,30 +165,16 @@ drop-board: all
mkdir -p build/drop/$(BOARD)
cp $(SELF_EXECUTABLE) build/drop/$(BOARD)/
cp $(EXECUTABLE) build/drop/$(BOARD)/
cp $(BUILD_PATH)/update-bootloader.ino build/drop/$(BOARD)/
cp $(SELF_EXECUTABLE_INO) build/drop/$(BOARD)/
cp boards/$(BOARD)/board_config.h build/drop/$(BOARD)/
drop-pkg:
mv build/drop build/uf2-samd21-$(VERSION)
cp bin-README.md build/uf2-samd21-$(VERSION)/README.md
cd build; 7z a uf2-samd21-$(VERSION).zip uf2-samd21-$(VERSION)
rm -rf build/uf2-samd21-$(VERSION)
tag:
$(MAKE) VERSION=`awk '/define UF2_VERSION_BASE/ { gsub(/"v?/, ""); print $$3 }' inc/uf2.h` do-tag
do-tag:
git add inc/uf2.h
git diff --exit-code
git commit -m "v$(VERSION)"
git tag "v$(VERSION)"
git push
git push --tag
$(MAKE) drop
mv build/drop build/uf2-samd21-$(UF2_VERSION_BASE)
cp bin-README.md build/uf2-samd21-$(UF2_VERSION_BASE)/README.md
cd build; 7z a uf2-samd21-$(UF2_VERSION_BASE).zip uf2-samd21-$(UF2_VERSION_BASE)
rm -rf build/uf2-samd21-$(UF2_VERSION_BASE)
all-boards:
for f in `cd boards; ls` ; do $(MAKE) BOARD=$$f drop-board ; done
drop: all-boards
$(MAKE) VERSION=`awk '/define UF2_VERSION_BASE/ { gsub(/"v?/, ""); print $$3 }' inc/uf2.h` drop-pkg
for f in `cd boards; ls` ; do "$(MAKE)" BOARD=$$f drop-board ; done
drop: all-boards drop-pkg

View file

@ -6,9 +6,9 @@ the USB MSC (mass storage).
[![Build Status](https://travis-ci.org/Microsoft/uf2-samd21.svg?branch=master)](https://travis-ci.org/Microsoft/uf2-samd21)
## UF2
## UF2
**UF2 (USB Flashing Format)** is a name of a file format, developed by Microsoft, that is particularly
**UF2 (USB Flashing Format)** is a name of a file format, developed by Microsoft, that is particularly
suitable for flashing devices over MSC devices. The file consists
of 512 byte blocks, each of which is self-contained and independent
of others.
@ -27,7 +27,7 @@ a UF2 file is written and immediately write it to flash.
## Features
* USB CDC (Serial emulation) monitor mode compatible with Arduino
* USB CDC (Serial emulation) monitor mode compatible with Arduino
(including XYZ commands) and BOSSA flashing tool
* USB MSC interface for writing UF2 files
* reading of the contests of the flash as an UF2 file via USB MSC
@ -38,7 +38,7 @@ a UF2 file is written and immediately write it to flash.
## Board identification
Configuration files for board `foo` is in `boards/foo/board_config.h`. You can
Configuration files for board `foo` are in `boards/foo/board_config.h` and `board.mk`. You can
build it with `make BOARD=foo`. You can also create `Makefile.user` file with `BOARD=foo`
to change the default.
@ -75,21 +75,23 @@ Thus, to update the bootloader, one can ship a user-space program,
that contains the new version of the bootloader and copies it to the
appropriate place in flash.
Such a program is generated during build in files `update-bootloader.uf2`.
Such a program is generated during build in files `update-bootloader*.uf2`.
If you're already running UF2 bootloader, the easiest way to update
it, is to just copy this file to the exposed MSD drive.
The build also generates `update-bootloader.ino` with an equivalent Arduino
The build also generates `update-bootloader*.ino` with an equivalent Arduino
sketch. You can copy&paste it into Arduino IDE and upload it to the device.
## Fuses
### SAMD21
The SAMD21 supports a `BOOTPROT` fuse, which write-protects the flash area of
the bootloader. Changes to this fuse only take effect after device reset.
OpenOCD exposes `at91samd bootloader` command to set this fuse. **This command is buggy.**
It seems to reset both fuse words to `0xffffffff`, which prevents the device
from operating correctly (it seems to reboot very frequently).
from operating correctly (it seems to reboot very frequently).
In `scripts/fuses.tcl` there is an OpenOCD script
which correctly sets the fuse. It's invoked by `dbgtool.js fuses`. It can be also
used to reset the fuses to sane values - just look at the comment at the top.
@ -98,12 +100,23 @@ The bootloader update programs (both the `.uf2` file and the Arduino sketch)
clear the `BOOTPROT` (i.e., set it to `0x7`) before trying to flash anything.
After flashing is done, they set `BOOTPROT` to 8 kilobyte bootloader size (i.e, `0x2`).
### SAMD51
The SAMD51s bootloader protection can be temporarily disabled through an NVM
command rather than a full erase and write of the AUX page. The boot protection
will be checked and set by the self updaters.
So, if you've used self-updaters but want to load it directly, then you'll need
to temporarily turn off the protection. In gdb the command is:
`set ((Nvmctrl *)0x41004000UL)->CTRLB.reg = (0xA5 << 8) | 0x1a`
## Build
### Requirements
* `make` and an Unix environment
* `node`.js in path
* `node`.js in path (optional)
* `arm-none-eabi-gcc` in the path (the one coming with Yotta will do just fine)
* `openocd` - you can use the one coming with Arduino (after your install the M0 board support)
@ -129,10 +142,10 @@ at `0xffffffff`.
The default board is `zero`. You can build a different one using:
```
make BOARD=metro
make BOARD=metro_m0
```
If you're working on different board, it's best to create `Makefile.local`
If you're working on different board, it's best to create `Makefile.local`
with say `BOARD=metro` to change the default.
The names `zero` and `metro` refer to subdirectories of `boards/`.
@ -153,22 +166,22 @@ make r
There is a number of configuration parameters at the top of `uf2.h` file.
Adjust them to your liking.
By default, you cannot enable all the features, as the bootloader would exceed
By default, you cannot enable all the features, as the bootloader would exceed
the 8k allocated to it by Arduino etc. It will assert on startup that it's not bigger
than 8k. Also, the linker script will not allow it.
Three typical configurations are:
* HID, WebUSB, MSC, plus flash reading via FAT; UART and CDC disabled;
* HID, WebUSB, MSC, plus flash reading via FAT; UART and CDC disabled;
logging optional; **recommended**
* USB CDC and MSC, plus flash reading via FAT; UART disabled;
* USB CDC and MSC, plus flash reading via FAT; UART disabled;
logging optional; this may have Windows driver problems
* USB CDC and MSC, no flash reading via FAT (or at least `index.htm` disabled); UART enabled;
* USB CDC and MSC, no flash reading via FAT (or at least `index.htm` disabled); UART enabled;
logging disabled; no handover; no HID;
only this one if you need the UART support in bootloader for whatever reason
CDC and MSC together will work on Linux and Mac with no drivers.
On Windows, if you have drivers installed for the USB ID chosen,
On Windows, if you have drivers installed for the USB ID chosen,
then CDC might work and MSC will not work;
otherwise, if you have no drivers, MSC will work, and CDC will work on Windows 10 only.
Thus, it's best to set the USB ID to one for which there are no drivers.

View file

@ -0,0 +1,2 @@
CHIP_FAMILY = samd21
CHIP_VARIANT = SAMD21G18A

View file

@ -1,7 +1,6 @@
#ifndef BOARD_CONFIG_H
#define BOARD_CONFIG_H
#define __SAMD21G18A__ 1
#define CRYSTALLESS 1
#define VENDOR_NAME "Adafruit Industries"

View file

@ -0,0 +1,2 @@
CHIP_FAMILY = samd21
CHIP_VARIANT = SAMD21G18A

View file

@ -1,8 +1,6 @@
#ifndef BOARD_CONFIG_H
#define BOARD_CONFIG_H
#define __SAMD21G18A__ 1
#define VENDOR_NAME "Adafruit Industries"
#define PRODUCT_NAME "Feather M0"
#define VOLUME_LABEL "FEATHERBOOT"

2
boards/gemma_m0/board.mk Normal file
View file

@ -0,0 +1,2 @@
CHIP_FAMILY = samd21
CHIP_VARIANT = SAMD21E18A

View file

@ -1,8 +1,6 @@
#ifndef BOARD_CONFIG_H
#define BOARD_CONFIG_H
#define __SAMD21E18A__ 1
//#define __SAMD21G18A__ 1
#define CRYSTALLESS 1
#define VENDOR_NAME "Adafruit Industries"

2
boards/generic/board.mk Normal file
View file

@ -0,0 +1,2 @@
CHIP_FAMILY = samd21
CHIP_VARIANT = SAMD21G18A

View file

@ -0,0 +1,2 @@
CHIP_FAMILY = samd21
CHIP_VARIANT = SAMD21G18A

View file

@ -0,0 +1,20 @@
#ifndef BOARD_CONFIG_H
#define BOARD_CONFIG_H
#define __SAMD21G18A__ 1
#define VENDOR_NAME "Seeed Studio"
#define PRODUCT_NAME "Grove Zero"
#define VOLUME_LABEL "Grove Zero"
#define INDEX_URL "https://www.seeedstudio.com/"
#define BOARD_ID "SAMD21G18A-Grove-Zero-v1.0"
#define USB_VID 0x2886
#define USB_PID 0x000D
#define LED_PIN PIN_PA17
#define LED_TX_PIN PIN_PA27
#define LED_RX_PIN PIN_PB03
#endif

View file

@ -0,0 +1,2 @@
CHIP_FAMILY = samd21
CHIP_VARIANT = SAMD21G18A

View file

@ -0,0 +1,20 @@
#ifndef BOARD_CONFIG_H
#define BOARD_CONFIG_H
#define CRYSTALLESS 1
#define VENDOR_NAME "Adafruit Industries"
#define PRODUCT_NAME "ItsyBitsy M0 Express"
#define VOLUME_LABEL "ITSYBOOT"
#define INDEX_URL "http://adafru.it/3727"
#define BOARD_ID "SAMD21G18A-ItsyBitsy-v0"
#define USB_VID 0x239A
#define USB_PID 0x000F
#define LED_PIN PIN_PA17
#define BOARD_RGBLED_CLOCK_PIN PIN_PA00
#define BOARD_RGBLED_DATA_PIN PIN_PA01
#endif

2
boards/metro_m0/board.mk Normal file
View file

@ -0,0 +1,2 @@
CHIP_FAMILY = samd21
CHIP_VARIANT = SAMD21G18A

2
boards/metro_m4/board.mk Normal file
View file

@ -0,0 +1,2 @@
CHIP_FAMILY = samd51
CHIP_VARIANT = SAMD51J19A

View file

@ -0,0 +1,31 @@
#ifndef BOARD_CONFIG_H
#define BOARD_CONFIG_H
#define VENDOR_NAME "Adafruit Industries"
#define PRODUCT_NAME "Metro M4"
#define VOLUME_LABEL "METROM4BOOT"
#define INDEX_URL "http://adafru.it/3505"
#define BOARD_ID "SAMD51J19A-Metro-v0"
#define USB_VID 0x239A
#define USB_PID 0x0021
#define LED_PIN PIN_PA21
#define LED_TX_PIN PIN_PA27
#define LED_RX_PIN PIN_PB06
#define BOARD_NEOPIXEL_PIN PIN_PB17
#define BOARD_NEOPIXEL_COUNT 1
#define BOOT_USART_MODULE SERCOM0
#define BOOT_USART_MASK APBAMASK
#define BOOT_USART_BUS_CLOCK_INDEX MCLK_APBAMASK_SERCOM0
#define BOOT_USART_PAD_SETTINGS UART_RX_PAD3_TX_PAD2
#define BOOT_USART_PAD3 PINMUX_UNUSED
#define BOOT_USART_PAD2 PINMUX_UNUSED
#define BOOT_USART_PAD1 PINMUX_PA10C_SERCOM0_PAD2
#define BOOT_USART_PAD0 PINMUX_PA11C_SERCOM0_PAD3
#define BOOT_GCLK_ID_CORE SERCOM0_GCLK_ID_CORE
#define BOOT_GCLK_ID_SLOW SERCOM0_GCLK_ID_SLOW
#endif

2
boards/mkr1000/board.mk Normal file
View file

@ -0,0 +1,2 @@
CHIP_FAMILY = samd21
CHIP_VARIANT = SAMD21G18A

View file

@ -1,8 +1,6 @@
#ifndef BOARD_CONFIG_H
#define BOARD_CONFIG_H
#define __SAMD21G18A__ 1
#define VENDOR_NAME "Arduino LLC"
#define PRODUCT_NAME "Arduino MKR1000"
#define VOLUME_LABEL "MKR1000"

2
boards/pirkey/board.mk Normal file
View file

@ -0,0 +1,2 @@
CHIP_FAMILY = samd21
CHIP_VARIANT = SAMD21E18A

View file

@ -0,0 +1,22 @@
#ifndef BOARD_CONFIG_H
#define BOARD_CONFIG_H
#define CRYSTALLESS 1
#define VENDOR_NAME "Adafruit Industries"
#define PRODUCT_NAME "pIRKey"
#define VOLUME_LABEL "PIRKEYBOOT"
#define INDEX_URL "http://adafru.it/"
#define BOARD_ID "SAMD21E18A-pIRKey-v0"
#define USB_VID 0x239A
#define USB_PID 0x0027
#define LED_PIN PIN_PA02 // not actually connected
//#define LED_TX_PIN PIN_PA27
//#define LED_RX_PIN PIN_PB03
#define BOARD_RGBLED_CLOCK_PIN PIN_PA01
#define BOARD_RGBLED_DATA_PIN PIN_PA00
#endif

View file

@ -0,0 +1,2 @@
CHIP_FAMILY = samd21
CHIP_VARIANT = SAMD21G18A

View file

@ -1,8 +1,6 @@
#ifndef BOARD_CONFIG_H
#define BOARD_CONFIG_H
#define __SAMD21G18A__ 1
#define VENDOR_NAME "Sparkfun"
#define PRODUCT_NAME "SAMD21 Dev Breakout"
#define VOLUME_LABEL "SPARKFUN"

View file

@ -0,0 +1,2 @@
CHIP_FAMILY = samd21
CHIP_VARIANT = SAMD21G18A

View file

@ -1,8 +1,6 @@
#ifndef BOARD_CONFIG_H
#define BOARD_CONFIG_H
#define __SAMD21G18A__ 1
#define VENDOR_NAME "Sparkfun"
#define PRODUCT_NAME "SAMD21 Mini Breakout"
#define VOLUME_LABEL "SPARKFUN"

View file

@ -0,0 +1,2 @@
CHIP_FAMILY = samd21
CHIP_VARIANT = SAMD21E18A

View file

@ -1,7 +1,6 @@
#ifndef BOARD_CONFIG_H
#define BOARD_CONFIG_H
#define __SAMD21E18A__ 1
#define CRYSTALLESS 1
#define VENDOR_NAME "Adafruit Industries"

2
boards/zero/board.mk Normal file
View file

@ -0,0 +1,2 @@
CHIP_FAMILY = samd21
CHIP_VARIANT = SAMD21G18A

View file

@ -1,11 +1,9 @@
#ifndef BOARD_CONFIG_H
#define BOARD_CONFIG_H
#define __SAMD21G18A__ 1
#define VENDOR_NAME "Arduino LLC"
#define PRODUCT_NAME "Arduino Zero"
#define VOLUME_LABEL "ARDUINO-M0"
#define VOLUME_LABEL "ZEROBOOT"
#define BOARD_ID "SAMD21G18A-Zero-v0"

View file

@ -34,11 +34,13 @@
#define FLASH_WAIT_STATES 1
#ifndef BOOT_USART_MODULE
#define BOOT_USART_MODULE SERCOM3
#define BOOT_USART_MUX_SETTINGS UART_RX_PAD1_TX_PAD0
#define BOOT_USART_PAD_SETTINGS UART_RX_PAD1_TX_PAD0
#define BOOT_USART_PAD3 PINMUX_UNUSED
#define BOOT_USART_PAD2 PINMUX_UNUSED
#define BOOT_USART_PAD1 PINMUX_PA23C_SERCOM3_PAD1
#define BOOT_USART_PAD0 PINMUX_PA22C_SERCOM3_PAD0
#endif
#endif // _MAIN_H_

View file

@ -12,31 +12,49 @@ static void neopixel_send_buffer_core(volatile uint32_t *clraddr, uint32_t pinMa
const uint8_t *ptr, int numBytes) {
asm volatile(" push {r4, r5, r6, lr};"
" add r3, r2, r3;"
" cpsid i;"
"loopLoad:"
" ldrb r5, [r2, #0];" // r5 := *ptr
" add r2, #1;" // ptr++
" movs r4, #128;" // r4-mask, 0x80
"loopBit:"
" str r1, [r0, #4];" // set
#ifdef SAMD21
" movs r6, #3; d2: sub r6, #1; bne d2;" // delay 3
#endif
#ifdef SAMD51
" movs r6, #3; d2: subs r6, #1; bne d2;" // delay 3
#endif
" tst r4, r5;" // mask&r5
" bne skipclr;"
" str r1, [r0, #0];" // clr
"skipclr:"
#ifdef SAMD21
" movs r6, #6; d0: sub r6, #1; bne d0;" // delay 6
#endif
#ifdef SAMD51
" movs r6, #6; d0: subs r6, #1; bne d0;" // delay 6
#endif
" str r1, [r0, #0];" // clr (possibly again, doesn't matter)
#ifdef SAMD21
" asr r4, r4, #1;" // mask >>= 1
#endif
#ifdef SAMD51
" asrs r4, r4, #1;" // mask >>= 1
#endif
" beq nextbyte;"
" uxtb r4, r4;"
#ifdef SAMD21
" movs r6, #2; d1: sub r6, #1; bne d1;" // delay 2
#endif
#ifdef SAMD51
" movs r6, #2; d1: subs r6, #1; bne d1;" // delay 2
#endif
" b loopBit;"
"nextbyte:"
" cmp r2, r3;"
" bcs stop;"
" b loopLoad;"
"stop:"
" cpsie i;"
" pop {r4, r5, r6, pc};"
"");
}
@ -49,14 +67,21 @@ static inline void neopixel_send_buffer(const uint8_t *ptr, int numBytes) {
PINOP(BOARD_NEOPIXEL_PIN, DIRSET);
// turn off mux too, needed for metro m0 but no harm done!
PORT->Group[BOARD_NEOPIXEL_PIN / 32].PINCFG[BOARD_NEOPIXEL_PIN % 32].reg=(uint8_t)(PORT_PINCFG_INEN) ;
PORT->Group[BOARD_NEOPIXEL_PIN / 32].PINCFG[BOARD_NEOPIXEL_PIN % 32].reg =
(uint8_t)(PORT_PINCFG_INEN);
PINOP(BOARD_NEOPIXEL_PIN, OUTCLR);
delay(1);
volatile uint32_t *clraddr = &PORT->Group[portNum].OUTCLR.reg;
neopixel_send_buffer_core(clraddr, pinMask, ptr, numBytes);
if (cpu_irq_is_enabled()) {
__disable_irq();
neopixel_send_buffer_core(clraddr, pinMask, ptr, numBytes);
__enable_irq();
} else {
neopixel_send_buffer_core(clraddr, pinMask, ptr, numBytes);
}
}
#endif

View file

@ -29,7 +29,7 @@
#ifndef UART_DRIVER_H
#define UART_DRIVER_H
#include "samd21.h"
#include "sam.h"
#include <stdbool.h>
#include <stdio.h>
@ -104,4 +104,4 @@ void uart_write_buffer_polled(Sercom *sercom, uint8_t *ptr, uint16_t length);
*/
void uart_read_buffer_polled(Sercom *sercom, uint8_t *ptr, uint16_t length);
#endif
#endif

View file

@ -3,7 +3,7 @@
#include "board_config.h"
#include "samd21.h"
#include "sam.h"
#define UF2_DEFINE_HANDOVER 1 // for testing
#include "uf2format.h"
#include "uf2hid.h"
@ -14,8 +14,6 @@
#include <stdio.h>
#include <string.h>
#include <compiler.h>
#undef DISABLE
#undef ENABLE
@ -33,7 +31,7 @@
#define INDEX_URL "https://www.pxt.io/"
#endif
#define UF2_VERSION_BASE "v1.23.0"
#include "uf2_version.h"
// needs to be more than ~4200 (to force FAT16)
#define NUM_FAT_BLOCKS 8000
@ -53,7 +51,7 @@
// Support Human Interface Device (HID) - serial, flashing and debug
#define USE_HID 1 // 788 bytes
// Expose HID via WebUSB
#define USE_WEBUSB 0 // 400 bytes
#define USE_WEBUSB 1
// Doesn't yet disable code, just enumeration
#define USE_MSC 1
@ -114,9 +112,15 @@
#define WEB_VERSION ""
#endif
#if USE_MSC_HANDOVER
#define MSC_HANDOVER_VERSION "O"
#else
#define MSC_HANDOVER_VERSION ""
#endif
#define UF2_VERSION \
UF2_VERSION_BASE " " CDC_VERSION LOGS_VERSION FAT_VERSION ASSERT_VERSION HID_VERSION \
WEB_VERSION RESET_VERSION
WEB_VERSION RESET_VERSION MSC_HANDOVER_VERSION
// End of config
@ -129,10 +133,10 @@
#define COLOR_UART 0x040400
#define COLOR_LEAVE 0x000000
#else
#define COLOR_START 0x00000A
#define COLOR_USB 0x000A00
#define COLOR_UART 0x0A0A00
#define COLOR_LEAVE 0x0A000A
#define COLOR_START 0x000040
#define COLOR_USB 0x004000
#define COLOR_UART 0x404000
#define COLOR_LEAVE 0x400040
#endif
/*
@ -190,7 +194,7 @@ void panic(int code);
extern volatile bool b_sam_ba_interface_usart;
void flash_write_row(uint32_t *dst, uint32_t *src);
void flash_erase_row(uint32_t *dst);
void flash_erase_to_end(uint32_t *start_address);
void flash_write_words(uint32_t *dst, uint32_t *src, uint32_t n_words);
void copy_words(uint32_t *dst, uint32_t *src, uint32_t n_words);
@ -219,7 +223,12 @@ void padded_memcpy(char *dst, const char *src, int len);
// Unlike for ordinary applications, our link script doesn't place the stack at the bottom
// of the RAM, but instead after all allocated BSS.
// In other words, this word should survive reset.
#ifdef SAMD21
#define DBL_TAP_PTR ((volatile uint32_t *)(HMCRAMC0_ADDR + HMCRAMC0_SIZE - 4))
#endif
#ifdef SAMD51
#define DBL_TAP_PTR ((volatile uint32_t *)(HSRAM_ADDR + HSRAM_SIZE - 4))
#endif
#define DBL_TAP_MAGIC 0xf01669ef // Randomly selected, adjusted to have first and last bit set
#define DBL_TAP_MAGIC_QUICK_BOOT 0xf02669ef
@ -254,9 +263,11 @@ void handoverPrep(void);
#define CONCAT_0(a, b) CONCAT_1(a, b)
#define STATIC_ASSERT(e) enum { CONCAT_0(_static_assert_, __LINE__) = 1 / ((e) ? 1 : 0) }
#ifdef SAMD21
STATIC_ASSERT(FLASH_ROW_SIZE == FLASH_PAGE_SIZE * 4);
STATIC_ASSERT(FLASH_ROW_SIZE == NVMCTRL_ROW_SIZE);
STATIC_ASSERT(FLASH_NUM_ROWS * 4 == FLASH_NB_OF_PAGES);
#endif
extern const char infoUf2File[];

View file

@ -7,7 +7,12 @@
// All entries are little endian.
// if you increase that, you will also need to update the linker script file
#ifdef SAMD21
#define APP_START_ADDRESS 0x00002000
#endif
#ifdef SAMD51
#define APP_START_ADDRESS 0x00004000
#endif
#define UF2_MAGIC_START0 0x0A324655UL // "UF2\n"
#define UF2_MAGIC_START1 0x9E5D5157UL // Randomly selected
@ -85,6 +90,8 @@ static inline void hf2_handover(uint8_t ep) {
}
}
// the ep_in/ep_out are without the 0x80 mask
// cbw_tag is in the same bit format as it came
static inline void check_uf2_handover(uint8_t *buffer, uint32_t blocks_remaining, uint8_t ep_in,
uint8_t ep_out, uint32_t cbw_tag) {
if (!is_uf2_block(buffer))

1
lib/uf2 Submodule

@ -0,0 +1 @@
Subproject commit d7ab98ee50bb42bb1c2ff600324e3a155a3cc4ad

View file

@ -63,7 +63,7 @@ function main() {
if (!pkgDir) fatal("cannot find Arduino packages directory")
let openocdPath = pkgDir + "tools/openocd/0.9.0-arduino/"
let openocdPath = pkgDir + "tools/openocd/0.10.0-arduino1-static/"
if (!fs.existsSync(openocdPath)) fatal("openocd not installed in Arduino")
let openocdBin = openocdPath + "bin/openocd"
@ -71,7 +71,7 @@ function main() {
if (process.platform == "win32")
openocdBin += ".exe"
let zeroCfg = pkgDir + "hardware/samd/1.6.8/variants/arduino_zero/openocd_scripts/arduino_zero.cfg"
let zeroCfg = pkgDir + "hardware/samd/1.6.17/variants/arduino_zero/openocd_scripts/arduino_zero.cfg"
let cmd = `telnet_port disabled; init; halt; `
if (mode == "map")

View file

@ -32,7 +32,9 @@ infostr = infostr.split(/\r?\n/).map(l => "// " + l + "\n").join("")
let size = buf.length
let s = infostr + "\n"
s += "const uint8_t bootloader[" + size + "] __attribute__ ((aligned (4))) = {"
s += "const uint8_t bootloader[" + size + "] "
s += "__attribute__ ((section(\".vectors.needs.to.go.first\"))) "
s += "__attribute__ ((aligned (4))) = {"
function tohex(v) {
return "0x" + ("00" + v.toString(16)).slice(-2) + ", "
}
@ -55,11 +57,11 @@ s += "const uint16_t bootloader_crcs[] = {" + crcs + "};\n"
let selfdata = "#include <stdint.h>\n" + s
fs.writeFileSync(buildPath + "/selfdata.c", selfdata)
let sketch = fs.readFileSync("src/sketch.cpp", "utf8")
let instr =`//
// Bootloader update sketch. Paste into Arduino IDE and upload to the device
// to update bootloader. It will blink a few times and then start pulsing.
// Your OS will then detect a USB mass storage device.
//
`;
fs.writeFileSync(buildPath + "/update-bootloader.ino", instr + s + "\n" + sketch)
// let sketch = fs.readFileSync("src/sketch.cpp", "utf8")
// let instr =`//
// // Bootloader update sketch. Paste into Arduino IDE and upload to the device
// // to update bootloader. It will blink a few times and then start pulsing.
// // Your OS will then detect a USB mass storage device.
// //
// `;
// fs.writeFileSync(buildPath + "/update-bootloader.ino", instr + s + "\n" + sketch)

65
scripts/gendata.py Normal file
View file

@ -0,0 +1,65 @@
import sys
import os
def update_crc(new_byte, current_crc):
crc = current_crc ^ new_byte << 8
for cmpt in range(8):
if crc & 0x8000:
crc = crc << 1 ^ 0x1021
else:
crc = crc << 1
crc &= 0xffff
return crc
# Load the bootloader file
bootloader_size = int(sys.argv[1])
bin_name = sys.argv[2]
bootloader = bytearray()
with open(bin_name, "rb") as bootloader_bin:
bootloader.extend(bootloader_bin.read())
# Fill the remaining space with 0xff.
bootloader.extend([0xff] * (bootloader_size - len(bootloader)))
# Output the bootloader binary data into C code to use in the self updater.
selfdata_c_path = os.path.join(os.path.dirname(bin_name), "selfdata.c")
with open(selfdata_c_path, "w") as output:
output.write("#include <stdint.h>\n")
output.write("const uint8_t bootloader[{}] ".format(bootloader_size) +
"__attribute__ ((aligned (4))) = {")
crcs = []
crc = 0
for row in range(bootloader_size / 16):
# Save the crc every 1k.
if row % (1024 / 16) == 0 and row > 0:
crcs.append(crc)
crc = 0
start_index = row * 16
row_bytes = bootloader[start_index:start_index+16]
formatted_bytes = ["0x{:02x}".format(x) for x in row_bytes]
output.write(", ".join(formatted_bytes) + ",\n")
# Update the crc
for b in row_bytes:
crc = update_crc(b, crc)
crcs.append(crc) # Add the last crc
output.write("\n};\n")
crcs = ["0x{:04x}".format(x) for x in crcs]
output.write("const uint16_t bootloader_crcs[] = {" +
" ,".join(crcs) + "};\n")
bin_dirname = os.path.dirname(bin_name)
bin_basename_no_ext = os.path.basename(os.path.splitext(bin_name)[0])
with open(os.path.join(bin_dirname, "update-" + bin_basename_no_ext + ".ino"), "w") as output:
output.write("""\
// Bootloader update sketch. Paste into Arduino IDE and upload to the device
// to update bootloader. It will blink a few times and then start pulsing.
// Your OS will then detect a USB mass storage device.
""")
with open(selfdata_c_path) as input:
output.write(input.read())
with open("src/sketch.cpp") as input:
output.write(input.read())

165
scripts/samd21j18a.ld Normal file
View file

@ -0,0 +1,165 @@
/**
* \file
*
* \brief Linker script for running in internal FLASH on the SAMD21J18A
*
* Copyright (c) 2014-2015 Atmel Corporation. All rights reserved.
*
* \asf_license_start
*
* \page License
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. The name of Atmel may not be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* 4. This software may only be redistributed and used in connection with an
* Atmel microcontroller product.
*
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* \asf_license_stop
*
*/
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
SEARCH_DIR(.)
/* Memory Spaces Definitions */
MEMORY
{
rom (rx) : ORIGIN = 0x00000000, LENGTH = 0x00002000
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000
}
/* The stack size used by the application. NOTE: you need to adjust according to your application. */
STACK_SIZE = DEFINED(STACK_SIZE) ? STACK_SIZE : DEFINED(__stack_size__) ? __stack_size__ : 0x2000;
/* Section Definitions */
SECTIONS
{
.text :
{
. = ALIGN(4);
_sfixed = .;
KEEP(*(.vectors .vectors.*))
*(.text .text.* .gnu.linkonce.t.*)
*(.glue_7t) *(.glue_7)
*(.rodata .rodata* .gnu.linkonce.r.*)
*(.ARM.extab* .gnu.linkonce.armextab.*)
/* Support C constructors, and C destructors in both user code
and the C library. This also provides support for C++ code. */
. = ALIGN(4);
KEEP(*(.init))
. = ALIGN(4);
__preinit_array_start = .;
KEEP (*(.preinit_array))
__preinit_array_end = .;
. = ALIGN(4);
__init_array_start = .;
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
__init_array_end = .;
. = ALIGN(4);
KEEP (*crtbegin.o(.ctors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*crtend.o(.ctors))
/*
. = ALIGN(4);
KEEP(*(.fini))
. = ALIGN(4);
__fini_array_start = .;
KEEP (*(.fini_array))
KEEP (*(SORT(.fini_array.*)))
__fini_array_end = .;
KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*crtend.o(.dtors))
*/
. = ALIGN(4);
_efixed = .; /* End of text section */
} > rom
/* .ARM.exidx is sorted, so has to go in its own output section. */
PROVIDE_HIDDEN (__exidx_start = .);
.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > rom
PROVIDE_HIDDEN (__exidx_end = .);
. = ALIGN(4);
_etext = .;
.relocate : AT (_etext)
{
. = ALIGN(4);
_srelocate = .;
*(.ramfunc .ramfunc.*);
*(.data .data.*);
. = ALIGN(4);
_erelocate = .;
} > ram
/* .bss section which is used for uninitialized data */
.bss (NOLOAD) :
{
. = ALIGN(4);
_sbss = . ;
_szero = .;
*(.bss .bss.*)
*(COMMON)
. = ALIGN(4);
_ebss = . ;
_ezero = .;
} > ram
/* stack section */
.stack (NOLOAD):
{
. = ALIGN(8);
_sstack = .;
. = . + STACK_SIZE;
. = ALIGN(8);
_estack = .;
} > ram
. = ALIGN(4);
_end = . ;
_binfo_start = 0x00002000 - 4 * 4;
.binfo _binfo_start : {
KEEP(*(.binfo)) ;
} > rom
}

151
scripts/samd51j19a.ld Normal file
View file

@ -0,0 +1,151 @@
/**
* \file
*
* \brief Linker script for running in internal FLASH on the SAMD51J19A
*
* Copyright (c) 2017 Microchip Technology Inc.
*
* \asf_license_start
*
* \page License
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the Licence at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* \asf_license_stop
*
*/
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
SEARCH_DIR(.)
/* Memory Spaces Definitions */
MEMORY
{
rom (rx) : ORIGIN = 0x00000000, LENGTH = 0x00080000
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00030000
}
/* The stack size used by the application. NOTE: you need to adjust according to your application. */
STACK_SIZE = DEFINED(STACK_SIZE) ? STACK_SIZE : DEFINED(__stack_size__) ? __stack_size__ : 0xC000;
/* Section Definitions */
SECTIONS
{
.text :
{
. = ALIGN(4);
_sfixed = .;
KEEP(*(.vectors .vectors.*))
*(.text .text.* .gnu.linkonce.t.*)
*(.glue_7t) *(.glue_7)
*(.rodata .rodata* .gnu.linkonce.r.*)
*(.ARM.extab* .gnu.linkonce.armextab.*)
/* Support C constructors, and C destructors in both user code
and the C library. This also provides support for C++ code. */
. = ALIGN(4);
KEEP(*(.init))
. = ALIGN(4);
__preinit_array_start = .;
KEEP (*(.preinit_array))
__preinit_array_end = .;
. = ALIGN(4);
__init_array_start = .;
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
__init_array_end = .;
. = ALIGN(4);
KEEP (*crtbegin.o(.ctors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*crtend.o(.ctors))
/*
. = ALIGN(4);
KEEP(*(.fini))
. = ALIGN(4);
__fini_array_start = .;
KEEP (*(.fini_array))
KEEP (*(SORT(.fini_array.*)))
__fini_array_end = .;
KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*crtend.o(.dtors))
*/
. = ALIGN(4);
_efixed = .; /* End of text section */
} > rom
/* .ARM.exidx is sorted, so has to go in its own output section. */
PROVIDE_HIDDEN (__exidx_start = .);
.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > rom
PROVIDE_HIDDEN (__exidx_end = .);
. = ALIGN(4);
_etext = .;
.relocate : AT (_etext)
{
. = ALIGN(4);
_srelocate = .;
*(.ramfunc .ramfunc.*);
*(.data .data.*);
. = ALIGN(4);
_erelocate = .;
} > ram
/* .bss section which is used for uninitialized data */
.bss (NOLOAD) :
{
. = ALIGN(4);
_sbss = . ;
_szero = .;
*(.bss .bss.*)
*(COMMON)
. = ALIGN(4);
_ebss = . ;
_ezero = .;
} > ram
/* stack section */
.stack (NOLOAD):
{
. = ALIGN(8);
_sstack = .;
. = . + STACK_SIZE;
. = ALIGN(8);
_estack = .;
} > ram
. = ALIGN(4);
_end = . ;
_binfo_start = 0x00002000 - 4 * 4;
.binfo _binfo_start : {
KEEP(*(.binfo)) ;
} > rom
}

163
scripts/samd51j19a_self.ld Normal file
View file

@ -0,0 +1,163 @@
/**
* \file
*
* \brief Linker script for running in internal FLASH on the SAMD51J19A
*
* Copyright (c) 2017 Microchip Technology Inc.
*
* \asf_license_start
*
* \page License
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the Licence at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* \asf_license_stop
*
*/
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
SEARCH_DIR(.)
/* Memory Spaces Definitions */
MEMORY
{
rom (rx) : ORIGIN = 0x00004000, LENGTH = 0x00080000 - 0x4000
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00030000
bkupram (rwx) : ORIGIN = 0x47000000, LENGTH = 0x00002000
qspi (rwx) : ORIGIN = 0x04000000, LENGTH = 0x01000000
}
/* The stack size used by the application. NOTE: you need to adjust according to your application. */
STACK_SIZE = DEFINED(STACK_SIZE) ? STACK_SIZE : DEFINED(__stack_size__) ? __stack_size__ : 0xC000;
/* Section Definitions */
SECTIONS
{
.text :
{
. = ALIGN(4);
_sfixed = .;
KEEP(*(.vectors .vectors.*))
*(.text .text.* .gnu.linkonce.t.*)
*(.glue_7t) *(.glue_7)
*(.rodata .rodata* .gnu.linkonce.r.*)
*(.ARM.extab* .gnu.linkonce.armextab.*)
/* Support C constructors, and C destructors in both user code
and the C library. This also provides support for C++ code. */
. = ALIGN(4);
KEEP(*(.init))
. = ALIGN(4);
__preinit_array_start = .;
KEEP (*(.preinit_array))
__preinit_array_end = .;
. = ALIGN(4);
__init_array_start = .;
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
__init_array_end = .;
. = ALIGN(4);
KEEP (*crtbegin.o(.ctors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*crtend.o(.ctors))
. = ALIGN(4);
KEEP(*(.fini))
. = ALIGN(4);
__fini_array_start = .;
KEEP (*(.fini_array))
KEEP (*(SORT(.fini_array.*)))
__fini_array_end = .;
KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*crtend.o(.dtors))
. = ALIGN(4);
_efixed = .; /* End of text section */
} > rom
/* .ARM.exidx is sorted, so has to go in its own output section. */
PROVIDE_HIDDEN (__exidx_start = .);
.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > rom
PROVIDE_HIDDEN (__exidx_end = .);
. = ALIGN(4);
_etext = .;
.relocate : AT (_etext)
{
. = ALIGN(4);
_srelocate = .;
*(.ramfunc .ramfunc.*);
*(.data .data.*);
. = ALIGN(4);
_erelocate = .;
} > ram
.bkupram (NOLOAD):
{
. = ALIGN(8);
_sbkupram = .;
*(.bkupram .bkupram.*);
. = ALIGN(8);
_ebkupram = .;
} > bkupram
.qspi (NOLOAD):
{
. = ALIGN(8);
_sqspi = .;
*(.qspi .qspi.*);
. = ALIGN(8);
_eqspi = .;
} > qspi
/* .bss section which is used for uninitialized data */
.bss (NOLOAD) :
{
. = ALIGN(4);
_sbss = . ;
_szero = .;
*(.bss .bss.*)
*(COMMON)
. = ALIGN(4);
_ebss = . ;
_ezero = .;
} > ram
/* stack section */
.stack (NOLOAD):
{
. = ALIGN(8);
_sstack = .;
. = . + STACK_SIZE;
. = ALIGN(8);
_estack = .;
} > ram
. = ALIGN(4);
_end = . ;
}

View file

@ -34,14 +34,20 @@
PacketBuffer ctrlOutCache;
PacketBuffer endpointCache[MAX_EP];
COMPILER_WORD_ALIGNED UsbDeviceDescriptor usb_endpoint_table[MAX_EP];
__attribute__((__aligned__(4))) UsbDeviceDescriptor usb_endpoint_table[MAX_EP];
COMPILER_WORD_ALIGNED
__attribute__((__aligned__(4)))
const char devDescriptor[] = {
/* Device descriptor */
0x12, // bLength
0x01, // bDescriptorType
0x00, // bcdUSBL - v2.00; v2.10 is needed for WebUSB, but it breaks newer laptops running Win10
0x12, // bLength
0x01, // bDescriptorType
// bcdUSBL - v2.00; v2.10 is needed for WebUSB; there were issues with newer laptops running Win10
// but it seems to be resolved
#if USE_WEBUSB
0x10,
#else
0x00,
#endif
0x02, //
0xEF, // bDeviceClass: Misc
0x02, // bDeviceSubclass:
@ -55,7 +61,7 @@ const char devDescriptor[] = {
0x42, //
0x01, // iManufacturer // 0x01
0x02, // iProduct
0x00, // SerialNumber
0x03, // SerialNumber (required (!) for WebUSB)
0x01 // bNumConfigs
};
@ -65,7 +71,7 @@ const char devDescriptor[] = {
#if USE_HID
// can be requested separately from the entire config desc
COMPILER_WORD_ALIGNED
__attribute__((__aligned__(4)))
char hidCfgDescriptor[] = {
9, // size
4, // interface
@ -78,7 +84,7 @@ char hidCfgDescriptor[] = {
3, // stringID
};
COMPILER_WORD_ALIGNED
__attribute__((__aligned__(4)))
const char hidDescriptor[] = {
0x06, 0x97, 0xFF, // usage page vendor 0x97 (usage 0xff97 0x0001)
0x09, 0x01, // usage 1
@ -99,7 +105,7 @@ const char hidDescriptor[] = {
};
#endif
COMPILER_WORD_ALIGNED
__attribute__((__aligned__(4)))
char cfgDescriptor[] = {
/* ============== CONFIGURATION 1 =========== */
/* Configuration 1 descriptor */
@ -111,7 +117,7 @@ char cfgDescriptor[] = {
0x01, // CbConfigurationValue
0x00, // CiConfiguration
0x80, // CbmAttributes 0x80 - bus-powered
250, // 500mA
250, // 500mA
#if USE_CDC
// IAD for CDC
@ -272,7 +278,7 @@ char cfgDescriptor[] = {
#endif
};
COMPILER_WORD_ALIGNED
__attribute__((__aligned__(4)))
static char bosDescriptor[] = {
0x05, // Length
0x0F, // Binary Object Store descriptor
@ -294,7 +300,7 @@ static char bosDescriptor[] = {
0x8B, 0xFD, 0xA0, 0x76, 0x88, 0x15, 0xB6, 0x65, // WebUSB GUID
0x00, 0x01, // Version 1.0
0x01, // Vendor request code
0x02, // landing page
0x00, // landing page
0x1C, // Length
0x10, // Device Capability descriptor
@ -303,62 +309,50 @@ static char bosDescriptor[] = {
0xDF, 0x60, 0xDD, 0xD8, 0x89, 0x45, 0xC7, 0x4C, // MS OS 2.0 GUID
0x9C, 0xD2, 0x65, 0x9D, 0x9E, 0x64, 0x8A, 0x9F, // MS OS 2.0 GUID
0x00, 0x00, 0x03, 0x06, // Windows version
0x2e, 0x00, // Descriptor set length
WINUSB_SIZE, 0x00, // Descriptor set length
0x02, // Vendor request code
0x00 // Alternate enumeration code
#endif
};
#if USE_WEBUSB
COMPILER_WORD_ALIGNED
__attribute__((__aligned__(4)))
static char msOS20Descriptor[] = {
// Microsoft OS 2.0 descriptor set header (table 10)
0x0A, 0x00, // Descriptor size (10 bytes)
0x00, 0x00, // MS OS 2.0 descriptor set header
0x00, 0x00, 0x03, 0x06, // Windows version (8.1) (0x06030000)
0x2e, 0x00, // Size, MS OS 2.0 descriptor set
// Microsoft OS 2.0 configuration subset header
0x08, 0x00, // Descriptor size (8 bytes)
0x01, 0x00, // MS OS 2.0 configuration subset header
0x00, // bConfigurationValue
0x00, // Reserved
0x24, 0x00, // Size, MS OS 2.0 configuration subset
WINUSB_SIZE, 0x00, // Size, MS OS 2.0 descriptor set
// Microsoft OS 2.0 function subset header
0x08, 0x00, // Descriptor size (8 bytes)
0x02, 0x00, // MS OS 2.0 function subset header
WEB_IF_NUM, // first interface no
0x00, // Reserved
0x1c, 0x00, // Size, MS OS 2.0 function subset
0x08, 0x00, // Descriptor size (8 bytes)
0x02, 0x00, // MS OS 2.0 function subset header
WEB_IF_NUM, // first interface no
0x00, // Reserved
WINUSB_SIZE - 10, 0x00, // Size, MS OS 2.0 function subset
// Microsoft OS 2.0 compatible ID descriptor (table 13)
0x14, 0x00, // wLength
20, 0x00, // wLength
0x03, 0x00, // MS_OS_20_FEATURE_COMPATIBLE_ID
'W', 'I', 'N', 'U', 'S', 'B', //
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
#define ALLOWED_ORIGINS_SEQ 1, 2
static const char *allowed_origins[] = {"localhost:3232", "samd.pxt.io"};
// interface guids
132, 0, 4, 0, 7, 0,
//
42, 0,
//
'D', 0, 'e', 0, 'v', 0, 'i', 0, 'c', 0, 'e', 0, 'I', 0, 'n', 0, 't', 0, 'e', 0, 'r', 0, 'f', 0,
'a', 0, 'c', 0, 'e', 0, 'G', 0, 'U', 0, 'I', 0, 'D', 0, 's', 0, 0, 0,
//
80, 0,
//
'{', 0, '9', 0, '2', 0, 'C', 0, 'E', 0, '6', 0, '4', 0, '6', 0, '2', 0, '-', 0, '9', 0, 'C', 0,
'7', 0, '7', 0, '-', 0, '4', 0, '6', 0, 'F', 0, 'E', 0, '-', 0, '9', 0, '3', 0, '3', 0, 'B', 0,
'-', 0, '3', 0, '1', 0, 'C', 0, 'B', 0, '9', 0, 'C', 0, '5', 0, 'A', 0, 'A', 0, '3', 0, 'B', 0,
'9', 0, '}', 0, 0, 0, 0, 0};
#define NUM_ALLOWED_ORIGINS 2
static const uint8_t allowedOriginsDesc[] = {
// Allowed Origins Header, bNumConfigurations = 1
0x05, 0x00, 0x0c + NUM_ALLOWED_ORIGINS, 0x00, 0x01,
// Configuration Subset Header, bNumFunctions = 1
0x04, 0x01, 0x01, 0x01,
// Function Subset Header, bFirstInterface = pluggedInterface
0x03 + NUM_ALLOWED_ORIGINS, 0x02, WEB_IF_NUM, ALLOWED_ORIGINS_SEQ,
};
typedef struct {
uint8_t len, tp, scheme;
uint8_t buf[64];
} __attribute__((packed)) WebUSB_URL;
STATIC_ASSERT((sizeof(allowed_origins) / sizeof(allowed_origins[0])) == NUM_ALLOWED_ORIGINS);
STATIC_ASSERT(sizeof(allowedOriginsDesc) == 0x0c + NUM_ALLOWED_ORIGINS);
STATIC_ASSERT(sizeof(msOS20Descriptor) == WINUSB_SIZE);
#endif
@ -370,10 +364,39 @@ typedef struct {
uint8_t data[70];
} StringDescriptor;
static const char *string_descriptors[] = {0, VENDOR_NAME, PRODUCT_NAME, };
// Serial numbers are derived from four 32-bit words. Add one character for null terminator
#define SERIAL_NUMBER_LENGTH (4 * 8 + 1)
// serial_number will be filled in when needed.
static char serial_number[SERIAL_NUMBER_LENGTH];
static const char *string_descriptors[] = {0, VENDOR_NAME, PRODUCT_NAME, serial_number};
#define STRING_DESCRIPTOR_COUNT (sizeof(string_descriptors) / sizeof(string_descriptors[0]))
static void load_serial_number(char serial_number[SERIAL_NUMBER_LENGTH]) {
// These are locations that taken together make up a unique serial number.
#ifdef SAMD21
uint32_t* addresses[4] = {(uint32_t *) 0x0080A00C, (uint32_t *) 0x0080A040,
(uint32_t *) 0x0080A044, (uint32_t *) 0x0080A048};
#endif
#ifdef SAMD51
uint32_t* addresses[4] = {(uint32_t *) 0x008061FC, (uint32_t *) 0x00806010,
(uint32_t *) 0x00806014, (uint32_t *) 0x00806018};
#endif
uint32_t serial_number_idx = 0;
for (int i = 0; i < 4; i++) {
uint32_t word = *(addresses[i]);
for (int j = 0; j < 8; j++) {
// Get top 4 bits.
uint8_t nibble = word >> 28;
word <<= 4;
serial_number[serial_number_idx++] = (nibble >= 10) ? 'A' + (nibble - 10) : '0' + nibble;
}
}
serial_number[serial_number_idx] = '\0';
}
#if USE_CDC
static usb_cdc_line_coding_t line_coding = {
115200, // baudrate
@ -440,21 +463,39 @@ void AT91F_InitUSB(void) {
uint32_t pad_transn, pad_transp, pad_trim;
/* Enable USB clock */
#ifdef SAMD21
PM->APBBMASK.reg |= PM_APBBMASK_USB;
#define DM_PIN PIN_PA24G_USB_DM
#define DM_MUX MUX_PA24G_USB_DM
#define DP_PIN PIN_PA25G_USB_DP
#define DP_MUX MUX_PA25G_USB_DP
#endif
#ifdef SAMD51
#define DM_PIN PIN_PA24H_USB_DM
#define DM_MUX MUX_PA24H_USB_DM
#define DP_PIN PIN_PA25H_USB_DP
#define DP_MUX MUX_PA25H_USB_DP
#endif
/* 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));
PORT->Group[0].PINCFG[DM_PIN].bit.PMUXEN = 1;
PORT->Group[0].PMUX[DM_PIN / 2].reg &= ~(0xF << (4 * (DM_PIN & 0x01u)));
PORT->Group[0].PMUX[DM_PIN / 2].reg |= DM_MUX << (4 * (DM_PIN & 0x01u));
PORT->Group[0].PINCFG[DP_PIN].bit.PMUXEN = 1;
PORT->Group[0].PMUX[DP_PIN / 2].reg &= ~(0xF << (4 * (DP_PIN & 0x01u)));
PORT->Group[0].PMUX[DP_PIN / 2].reg |= DP_MUX << (4 * (DP_PIN & 0x01u));
#ifdef SAMD21
GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(6) | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_CLKEN;
while (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY)
;
while (GCLK->STATUS.bit.SYNCBUSY) {}
#endif
#ifdef SAMD51
GCLK->PCHCTRL[USB_GCLK_ID].reg = GCLK_PCHCTRL_GEN_GCLK0_Val | (1 << GCLK_PCHCTRL_CHEN_Pos);
MCLK->AHBMASK.bit.USB_ = true;
MCLK->APBBMASK.bit.USB_ = true;
while(GCLK->SYNCBUSY.bit.GENCTRL0) {}
#endif
/* Reset */
USB->HOST.CTRLA.bit.SWRST = 1;
@ -463,9 +504,7 @@ void AT91F_InitUSB(void) {
}
/* 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);
pad_transn = ((*((uint32_t*) USB_FUSES_TRANSN_ADDR)) & USB_FUSES_TRANSN_Msk) >> USB_FUSES_TRANSN_Pos;
if (pad_transn == 0x1F) {
pad_transn = 5;
@ -473,18 +512,14 @@ void AT91F_InitUSB(void) {
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);
pad_transp = ((*((uint32_t*) USB_FUSES_TRANSP_ADDR)) & USB_FUSES_TRANSP_Msk) >> USB_FUSES_TRANSP_Pos;
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);
pad_trim = ((*((uint32_t*) USB_FUSES_TRIM_ADDR)) & USB_FUSES_TRIM_Msk) >> USB_FUSES_TRIM_Pos;
if (pad_trim == 0x7) {
pad_trim = 3;
@ -592,6 +627,12 @@ uint32_t USB_ReadCore(void *pData, uint32_t length, uint32_t ep, PacketBuffer *c
if (USB->DEVICE.DeviceEndpoint[ep].EPINTFLAG.reg & USB_DEVICE_EPINTFLAG_TRCPT0) {
/* Set packet size */
cache->size = epdesc->DeviceDescBank[0].PCKSIZE.bit.BYTE_COUNT;
// this is when processing a hand-over
if (cache->read_job == 2) {
memcpy(&cache->buf, (void *)epdesc->DeviceDescBank[0].ADDR.reg, cache->size);
}
packetSize = MIN(cache->size, length);
if (pData) {
cache->ptr = packetSize;
@ -764,6 +805,7 @@ void AT91F_CDC_Enumerate() {
desc.data[0] = 0x09;
desc.data[1] = 0x04;
} else {
load_serial_number(serial_number);
const char *ptr = string_descriptors[ctrlOutCache.buf[2]];
desc.len = strlen(ptr) * 2 + 2;
for (int i = 0; ptr[i]; i++) {
@ -788,22 +830,7 @@ void AT91F_CDC_Enumerate() {
break;
#if USE_WEBUSB
case STD_VENDOR_CTRL1:
if (wIndex == 0x01)
sendCtrl(allowedOriginsDesc, sizeof(allowedOriginsDesc));
else if (wIndex == 0x02) {
WebUSB_URL url;
uint32_t idx = (uint32_t)ctrlOutCache.buf[2] - 1;
if (idx >= NUM_ALLOWED_ORIGINS)
stall_ep(0);
url.len = strlen(allowed_origins[idx]) + 3;
url.tp = 3;
// first URL is http, rest is https
url.scheme = idx == 0 ? 0 : 1;
memcpy(url.buf, allowed_origins[idx], url.len - 3);
sendCtrl(&url, url.len);
} else {
stall_ep(0);
}
stall_ep(0);
break;
case STD_VENDOR_CTRL2:
if (wIndex == 0x07)

View file

@ -231,11 +231,13 @@ void write_block(uint32_t block_no, uint8_t *data, bool quiet, WriteState *state
if (state->numWritten >= state->numBlocks) {
// wait a little bit before resetting, to avoid Windows transmit error
// https://github.com/Microsoft/uf2-samd21/issues/11
resetHorizon = timerHigh + 30;
if (!quiet)
resetHorizon = timerHigh + 30;
// resetIntoApp();
}
}
} else {
resetHorizon = timerHigh + 300;
if (!quiet)
resetHorizon = timerHigh + 300;
}
}

View file

@ -15,6 +15,21 @@ void flash_erase_row(uint32_t *dst) {
wait_ready();
}
void flash_erase_to_end(uint32_t *start_address) {
// 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 = (uint32_t) start_address; // starting address
while (dst_addr < FLASH_SIZE) {
flash_erase_row((void *)dst_addr);
dst_addr += FLASH_ROW_SIZE;
}
}
void copy_words(uint32_t *dst, uint32_t *src, uint32_t n_words) {
while (n_words--)
*dst++ = *src++;
@ -25,7 +40,7 @@ void flash_write_words(uint32_t *dst, uint32_t *src, uint32_t n_words) {
NVMCTRL->CTRLB.bit.MANW = 0;
while (n_words > 0) {
uint32_t len = min(FLASH_PAGE_SIZE >> 2, n_words);
uint32_t len = (FLASH_PAGE_SIZE >> 2) < n_words ? (FLASH_PAGE_SIZE >> 2) : n_words;
n_words -= len;
// Execute "PBC" Page Buffer Clear

137
src/flash_samd51.c Normal file
View file

@ -0,0 +1,137 @@
#include "uf2.h"
// this actually generates less code than a function
#define wait_ready() \
while (NVMCTRL->STATUS.bit.READY == 0) \
;
void flash_erase_block(uint32_t *dst) {
wait_ready();
// Execute "ER" Erase Row
NVMCTRL->ADDR.reg = (uint32_t)dst;
NVMCTRL->CTRLB.reg = NVMCTRL_CTRLB_CMDEX_KEY | NVMCTRL_CTRLB_CMD_EB;
wait_ready();
}
void flash_erase_to_end(uint32_t *dst) {
for (uint32_t i = ((uint32_t) dst); i < FLASH_SIZE; i += NVMCTRL_BLOCK_SIZE) {
flash_erase_block((uint32_t *)i);
}
}
void copy_words(uint32_t *dst, uint32_t *src, uint32_t n_words) {
while (n_words--)
*dst++ = *src++;
}
#define QUAD_WORD (4 * 4)
void flash_write_words(uint32_t *dst, uint32_t *src, uint32_t n_words) {
// Set manual page write
NVMCTRL->CTRLA.bit.WMODE = NVMCTRL_CTRLA_WMODE_MAN;
// Execute "PBC" Page Buffer Clear
wait_ready();
NVMCTRL->CTRLB.reg = NVMCTRL_CTRLB_CMDEX_KEY | NVMCTRL_CTRLB_CMD_PBC;
wait_ready();
while (n_words > 0) {
// We write quad words so that we can write 256 byte blocks like UF2
// provides. Pages are 512 bytes and would require loading data back out
// of flash for the neighboring row.
uint32_t len = 4 < n_words ? 4 : n_words;
wait_ready();
for (uint32_t i = 0; i < 4; i++) {
if (i < len) {
dst[i] = src[i];
} else {
dst[i] = 0xffffffff;
}
}
// Trigger the quad word write.
NVMCTRL->ADDR.reg = (uint32_t)dst;
NVMCTRL->CTRLB.reg = NVMCTRL_CTRLB_CMDEX_KEY | NVMCTRL_CTRLB_CMD_WQW;
// Advance to quad word
dst += len;
src += len;
n_words -= len;
}
}
// On the SAMD51 we can only erase 4KiB blocks of 512 byte pages. To reduce wear
// and increase flash speed we only want to erase a block at most once per
// flash. Each 256 byte row from the UF2 comes in an unknown order. So, we wait
// to erase until we see a row that varies with current memory. Before erasing,
// we cache the rows that were the same up to this point, perform the erase and
// flush the previously seen rows. Every row after will get written without
// another erase.
bool block_erased[FLASH_SIZE / NVMCTRL_BLOCK_SIZE];
bool row_same[FLASH_SIZE / NVMCTRL_BLOCK_SIZE][NVMCTRL_BLOCK_SIZE / FLASH_ROW_SIZE];
// Skip writing blocks that are identical to the existing block.
// only disable for debugging/timing
#define QUICK_FLASH 1
void flash_write_row(uint32_t *dst, uint32_t *src) {
// The cache in Rev A isn't reliable when reading and writing to the NVM.
NVMCTRL->CTRLA.bit.CACHEDIS0 = true;
NVMCTRL->CTRLA.bit.CACHEDIS1 = true;
uint32_t block = ((uint32_t) dst) / NVMCTRL_BLOCK_SIZE;
uint8_t row = (((uint32_t) dst) % NVMCTRL_BLOCK_SIZE) / FLASH_ROW_SIZE;
#if QUICK_FLASH
bool src_different = false;
for (uint32_t i = 0; i < FLASH_ROW_SIZE / 4; ++i) {
if (src[i] != dst[i]) {
src_different = true;
break;
}
}
// Row is the same, quit early but keep track in case we need to erase its
// block. This is ok after an erase because the destination will be all 1s.
if (!src_different) {
row_same[block][row] = true;
return;
}
#endif
if (!block_erased[block]) {
uint8_t rows_per_block = NVMCTRL_BLOCK_SIZE / FLASH_ROW_SIZE;
uint8_t* block_address = block * NVMCTRL_BLOCK_SIZE;
bool some_rows_same = false;
for (uint8_t i = 0; i < rows_per_block; i++) {
some_rows_same = some_rows_same || row_same[block][i];
}
uint32_t row_cache[rows_per_block][FLASH_ROW_SIZE / 4];
if (some_rows_same) {
for (uint8_t i = 0; i < rows_per_block; i++) {
if(row_same[block][i]) {
memcpy(row_cache[i], block_address + i * FLASH_ROW_SIZE, FLASH_ROW_SIZE);
}
}
}
flash_erase_block(dst);
block_erased[block] = true;
if (some_rows_same) {
for (uint8_t i = 0; i < rows_per_block; i++) {
if(row_same[block][i]) {
// dst is a uint32_t pointer so we add the number of words,
// not bytes.
flash_write_words(block_address + i * FLASH_ROW_SIZE, row_cache[i], FLASH_ROW_SIZE / 4);
}
}
}
}
flash_write_words(dst, src, FLASH_ROW_SIZE / 4);
// Don't return until we're done writing in case something after us causes
// a reset.
wait_ready();
}

84
src/init_samd51.c Normal file
View file

@ -0,0 +1,84 @@
#include "uf2.h"
void system_init(void) {
/* Set 1 Flash Wait State for 48MHz */
NVMCTRL->CTRLA.reg |= NVMCTRL_CTRLA_RWS(0);
// Output GCLK0 to Metro M4 D5. This way we can see if/when we mess it up.
PORT->Group[1].PINCFG[14].bit.PMUXEN = true;
PORT->Group[1].PMUX[7].bit.PMUXE = 12;
/* Software reset the module to ensure it is re-initialized correctly */
/* Note: Due to synchronization, there is a delay from writing CTRL.SWRST until the reset is complete.
* CTRL.SWRST and STATUS.SYNCBUSY will both be cleared when the reset is complete
*/
GCLK->CTRLA.bit.SWRST = 1;
while (GCLK->SYNCBUSY.bit.SWRST) {
/* wait for reset to complete */
}
// Temporarily switch the CPU to the internal 32k oscillator while we
// reconfigure the DFLL.
GCLK->GENCTRL[0].reg = GCLK_GENCTRL_SRC(GCLK_GENCTRL_SRC_OSCULP32K) |
GCLK_GENCTRL_OE |
GCLK_GENCTRL_GENEN;
while (GCLK->SYNCBUSY.bit.GENCTRL0) {
/* Wait for synchronization */
}
// Configure the DFLL for USB clock recovery.
OSCCTRL->DFLLCTRLA.reg = 0;
OSCCTRL->DFLLMUL.reg = OSCCTRL_DFLLMUL_CSTEP( 0x1 ) |
OSCCTRL_DFLLMUL_FSTEP( 0x1 ) |
OSCCTRL_DFLLMUL_MUL( 0xBB80 );
while (OSCCTRL->DFLLSYNC.bit.DFLLMUL) {
/* Wait for synchronization */
}
OSCCTRL->DFLLCTRLB.reg = 0;
while (OSCCTRL->DFLLSYNC.bit.DFLLCTRLB) {
/* Wait for synchronization */
}
OSCCTRL->DFLLCTRLA.bit.ENABLE = true;
while (OSCCTRL->DFLLSYNC.bit.ENABLE) {
/* Wait for synchronization */
}
OSCCTRL->DFLLVAL.reg = OSCCTRL->DFLLVAL.reg;
while(OSCCTRL->DFLLSYNC.bit.DFLLVAL ) {}
OSCCTRL->DFLLCTRLB.reg = OSCCTRL_DFLLCTRLB_WAITLOCK |
OSCCTRL_DFLLCTRLB_CCDIS | OSCCTRL_DFLLCTRLB_USBCRM ;
while (!OSCCTRL->STATUS.bit.DFLLRDY) {
/* Wait for synchronization */
}
// 5) Switch Generic Clock Generator 0 to DFLL48M. CPU will run at 48MHz.
GCLK->GENCTRL[0].reg =
GCLK_GENCTRL_SRC(GCLK_GENCTRL_SRC_DFLL) |
GCLK_GENCTRL_IDC |
GCLK_GENCTRL_OE |
GCLK_GENCTRL_GENEN;
while (GCLK->SYNCBUSY.bit.GENCTRL0) {
/* Wait for synchronization */
}
/* Turn on the digital interface clock */
//MCLK->APBAMASK.reg |= MCLK_APBAMASK_GCLK;
/*
* Now that all system clocks are configured, we can set CLKDIV .
* These values are normally the ones present after Reset.
*/
MCLK->CPUDIV.reg = MCLK_CPUDIV_DIV_DIV1;
SysTick_Config(1000);
}
void SysTick_Handler(void) { LED_TICK(); }

View file

@ -81,6 +81,13 @@ static void check_start_application(void);
static volatile bool main_b_cdc_enable = false;
extern int8_t led_tick_step;
#ifdef SAMD21
#define RESET_CONTROLLER PM
#endif
#ifdef SAMD51
#define RESET_CONTROLLER RSTC
#endif
/**
* \brief Check the application startup condition
*
@ -102,7 +109,8 @@ static void check_start_application(void) {
#if USE_SINGLE_RESET
if (SINGLE_RESET()) {
if (PM->RCAUSE.bit.POR || *DBL_TAP_PTR != DBL_TAP_MAGIC_QUICK_BOOT) {
if (RESET_CONTROLLER->RCAUSE.bit.POR ||
*DBL_TAP_PTR != DBL_TAP_MAGIC_QUICK_BOOT) {
// the second tap on reset will go into app
*DBL_TAP_PTR = DBL_TAP_MAGIC_QUICK_BOOT;
// this will be cleared after succesful USB enumeration
@ -113,7 +121,7 @@ static void check_start_application(void) {
}
#endif
if (PM->RCAUSE.bit.POR) {
if (RESET_CONTROLLER->RCAUSE.bit.POR) {
*DBL_TAP_PTR = 0;
} else if (*DBL_TAP_PTR == DBL_TAP_MAGIC) {
*DBL_TAP_PTR = 0;
@ -154,6 +162,9 @@ int main(void) {
while (1) {
}
#if USB_PID == 0x0013 // Metro m0
delay(100);
#endif
led_init();
logmsg("Start");
@ -170,7 +181,9 @@ int main(void) {
/* We have determined we should stay in the monitor. */
/* System initialization */
system_init();
cpu_irq_enable();
__DMB();
__enable_irq();
#if USE_UART
/* UART is enabled in all cases */
@ -183,7 +196,7 @@ int main(void) {
// not enumerated yet
RGBLED_set_color(COLOR_START);
led_tick_step = 0;
led_tick_step = 10;
/* Wait for a complete enum on usb or a '#' char on serial line */
while (1) {
@ -194,8 +207,7 @@ int main(void) {
resetHorizon = 0;
#endif
RGBLED_set_color(COLOR_USB);
if (!led_tick_step)
led_tick_step = 1;
led_tick_step = 1;
}
main_b_cdc_enable = true;

View file

@ -44,9 +44,10 @@
#include "uf2.h"
#include "services/usb/class/msc/sbc_protocol.h"
#include "services/usb/class/msc/spc_protocol.h"
#include "services/usb/class/msc/usb_protocol_msc.h"
#include "lib/usb_msc/sbc_protocol.h"
#include "lib/usb_msc/spc_protocol.h"
#include "lib/usb_msc/usb_protocol.h"
#include "lib/usb_msc/usb_protocol_msc.h"
#if !USE_DBG_MSC
#undef logmsg
@ -55,6 +56,21 @@
#define logval(...) NOOP
#endif
// From sam0/utils/compiler.h in ASF3
#define le32_to_cpu(x) (x)
#define cpu_to_le32(x) (x)
#define CPU_TO_BE32(x) ((uint32_t)__builtin_bswap32((uint32_t)(x)))
#define cpu_to_be16(x) ((uint16_t)(((uint16_t)(x) >> 8) |\
((uint16_t)(x) << 8)))
#define MSB3(u32) (((uint8_t *)&(u32))[0]) //!< Most significant byte of 4th rank of \a u32.
#define MSB2(u32) (((uint8_t *)&(u32))[1]) //!< Most significant byte of 3rd rank of \a u32.
#define MSB1(u32) (((uint8_t *)&(u32))[2]) //!< Most significant byte of 2nd rank of \a u32.
#define MSB0(u32) (((uint8_t *)&(u32))[3]) //!< Most significant byte of 1st rank of \a u32.
#define MSB(u16) (((uint8_t *)&(u16))[1]) //!< Most significant byte of \a u16.
#define LSB(u16) (((uint8_t *)&(u16))[0]) //!< Least significant byte of \a u16.
bool mscReset = false;
void msc_reset(void) {
@ -468,8 +484,7 @@ static void udi_msc_sense_fail(uint8_t sense_key, uint16_t add_sense, uint32_t l
udi_msc_sense.information[1] = lba >> 16;
udi_msc_sense.information[2] = lba >> 8;
udi_msc_sense.information[3] = lba;
udi_msc_sense.AddSenseCode = add_sense >> 8;
udi_msc_sense.AddSnsCodeQlfr = add_sense;
udi_msc_sense.AddSense = add_sense;
}
static void udi_msc_sense_pass(void) {
@ -533,7 +548,7 @@ static void udi_msc_read_format_capacity(void) {
static void udi_msc_spc_inquiry(void) {
uint8_t length;
COMPILER_ALIGNED(4)
__attribute__((__aligned__(4)))
// Constant inquiry data for all LUNs
static struct scsi_inquiry_data udi_msc_inquiry_data = {
.pq_pdt = SCSI_INQ_PQ_CONNECTED | SCSI_INQ_DT_DIR_ACCESS,
@ -606,7 +621,7 @@ static void udi_msc_spc_mode_sense(bool b_sense10) {
uint8_t mode;
uint8_t request_lgt;
struct spc_control_page_info_execpt *ptr_mode;
COMPILER_ALIGNED(4) static union sense_6_10 sense;
__attribute__((__aligned__(4))) static union sense_6_10 sense;
// Clear all fields
memset(&sense, 0, sizeof(sense));
@ -678,7 +693,7 @@ static void udi_msc_sbc_start_stop(void) {
}
static void udi_msc_sbc_read_capacity(void) {
COMPILER_ALIGNED(4) static struct sbc_read_capacity10_data udi_msc_capacity;
__attribute__((__aligned__(4))) static struct sbc_read_capacity10_data udi_msc_capacity;
if (!udi_msc_cbw_validate(sizeof(udi_msc_capacity), USB_CBW_DIRECTION_IN))
return;
@ -686,12 +701,12 @@ static void udi_msc_sbc_read_capacity(void) {
udi_msc_capacity.max_lba = NUM_FAT_BLOCKS - 1;
// Format capacity data
udi_msc_capacity.block_len = CPU_TO_BE32(UDI_MSC_BLOCK_SIZE);
udi_msc_capacity.max_lba = cpu_to_be32(udi_msc_capacity.max_lba);
udi_msc_capacity.max_lba = CPU_TO_BE32(udi_msc_capacity.max_lba);
// Send the corresponding sense data
udi_msc_data_send((uint8_t *)&udi_msc_capacity, sizeof(udi_msc_capacity));
}
COMPILER_ALIGNED(4) static uint8_t block_buffer[UDI_MSC_BLOCK_SIZE];
__attribute__((__aligned__(4))) static uint8_t block_buffer[UDI_MSC_BLOCK_SIZE];
static WriteState usbWriteState;
static void udi_msc_sbc_trans(bool b_read) {
@ -820,10 +835,9 @@ static void process_handover(UF2_HandoverArgs *handover, PacketBuffer *handoverC
USB_WriteCore((void *)&csw, sizeof(csw), handover->ep_in, true);
}
#include "system_interrupt.h"
void handoverPrep() {
cpu_irq_disable();
__disable_irq();
__DMB();
USB->DEVICE.INTENCLR.reg = USB_DEVICE_INTENCLR_MASK;
USB->DEVICE.INTFLAG.reg = USB_DEVICE_INTFLAG_MASK;
@ -832,21 +846,11 @@ void handoverPrep() {
}
static void handover(UF2_HandoverArgs *args) {
// reset interrupt vectors, so that we're not disturbed by
// interrupt handlers from user space
// for (int i = 1; i <= 0x1f; ++i){
// system_interrupt_disable(i);
//}
handoverPrep();
PacketBuffer cache = {0};
WriteState writeState = {0};
// for (int i = 0; i < 1000000; i++) {
// asm("nop");
//}
cache.read_job = 2;
// They may have 0x80 bit set
args->ep_in &= 0xf;

View file

@ -94,7 +94,8 @@ volatile uint32_t sp;
void call_applet(uint32_t address) {
uint32_t app_start_address;
cpu_irq_disable();
__disable_irq();
__DMB();
sp = __get_MSP();
@ -157,7 +158,7 @@ void sam_ba_monitor_run(void) {
// We need to add first the remaining data of the
// current buffer already read from usb
// read a maximum of "current_number" bytes
u32tmp = min((length - i), current_number);
u32tmp = (length - i) < current_number ? (length - i) : current_number;
memcpy(ptr_data, ptr, u32tmp);
i += u32tmp;
ptr += u32tmp;
@ -194,7 +195,8 @@ void sam_ba_monitor_run(void) {
call_applet(current_number);
/* Rebase the Stack Pointer */
__set_MSP(sp);
cpu_irq_enable();
__DMB();
__enable_irq();
if (b_sam_ba_interface_usart) {
cdc_write_buf("\x06", 1);
}
@ -217,18 +219,7 @@ void sam_ba_monitor_run(void) {
// 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 < FLASH_SIZE) {
flash_erase_row((void *)dst_addr);
dst_addr += FLASH_ROW_SIZE;
}
flash_erase_to_end((uint32_t *) current_number);
// Notify command completed
cdc_write_buf("X\n\r", 3);

View file

@ -1,29 +1,51 @@
#include "uf2.h"
#include "sam.h"
#ifdef SAMD21
#define BOOTLOADER_K 8
#endif
#ifdef SAMD51
#define BOOTLOADER_K 16
#endif
extern const uint8_t bootloader[];
extern const uint16_t bootloader_crcs[];
uint8_t pageBuf[FLASH_ROW_SIZE];
#define exec_cmd(cmd) \
do { \
NVMCTRL->STATUS.reg |= NVMCTRL_STATUS_MASK; \
NVMCTRL->ADDR.reg = (uint32_t)NVMCTRL_USER / 2; \
NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | cmd; \
while (NVMCTRL->INTFLAG.bit.READY == 0) \
; \
#ifdef SAMD21
#define NVM_FUSE_ADDR NVMCTRL_AUX0_ADDRESS
#define exec_cmd(cmd) \
do { \
NVMCTRL->STATUS.reg |= NVMCTRL_STATUS_MASK; \
NVMCTRL->ADDR.reg = (uint32_t)NVMCTRL_USER / 2; \
NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | cmd; \
while (NVMCTRL->INTFLAG.bit.READY == 0) {} \
} while (0)
#endif
#ifdef SAMD51
#define NVM_FUSE_ADDR NVMCTRL_FUSES_BOOTPROT_ADDR
#define exec_cmd(cmd) \
do { \
NVMCTRL->ADDR.reg = (uint32_t)NVMCTRL_USER; \
NVMCTRL->CTRLB.reg = NVMCTRL_CTRLB_CMDEX_KEY | cmd; \
while (NVMCTRL->STATUS.bit.READY == 0) {} \
} while (0)
#endif
void setBootProt(int v) {
uint32_t fuses[2];
while (!(NVMCTRL->INTFLAG.reg & NVMCTRL_INTFLAG_READY))
;
#ifdef SAMD21
while (!(NVMCTRL->INTFLAG.reg & NVMCTRL_INTFLAG_READY)) {}
#endif
#ifdef SAMD51
while (NVMCTRL->STATUS.bit.READY == 0) {}
#endif
fuses[0] = *((uint32_t *)NVMCTRL_AUX0_ADDRESS);
fuses[1] = *(((uint32_t *)NVMCTRL_AUX0_ADDRESS) + 1);
fuses[0] = *((uint32_t *)NVM_FUSE_ADDR);
fuses[1] = *(((uint32_t *)NVM_FUSE_ADDR) + 1);
uint32_t bootprot = (fuses[0] & NVMCTRL_FUSES_BOOTPROT_Msk) >> NVMCTRL_FUSES_BOOTPROT_Pos;
@ -37,15 +59,28 @@ void setBootProt(int v) {
fuses[0] = (fuses[0] & ~NVMCTRL_FUSES_BOOTPROT_Msk) | (v << NVMCTRL_FUSES_BOOTPROT_Pos);
#ifdef SAMD21
NVMCTRL->CTRLB.reg = NVMCTRL->CTRLB.reg | NVMCTRL_CTRLB_CACHEDIS | NVMCTRL_CTRLB_MANW;
exec_cmd(NVMCTRL_CTRLA_CMD_EAR);
exec_cmd(NVMCTRL_CTRLA_CMD_PBC);
#endif
#ifdef SAMD51
NVMCTRL->CTRLA.bit.WMODE = NVMCTRL_CTRLA_WMODE_MAN;
*((uint32_t *)NVMCTRL_AUX0_ADDRESS) = fuses[0];
*(((uint32_t *)NVMCTRL_AUX0_ADDRESS) + 1) = fuses[1];
exec_cmd(NVMCTRL_CTRLB_CMD_EP);
exec_cmd(NVMCTRL_CTRLB_CMD_PBC);
#endif
*((uint32_t *)NVM_FUSE_ADDR) = fuses[0];
*(((uint32_t *)NVM_FUSE_ADDR) + 1) = fuses[1];
#ifdef SAMD21
exec_cmd(NVMCTRL_CTRLA_CMD_WAP);
#endif
#ifdef SAMD51
exec_cmd(NVMCTRL_CTRLB_CMD_WQW);
#endif
resetIntoApp();
}
@ -55,17 +90,30 @@ int main(void) {
logmsg("Start");
assert(8 << NVMCTRL->PARAM.bit.PSZ == FLASH_PAGE_SIZE);
assert((8 << NVMCTRL->PARAM.bit.PSZ) == FLASH_PAGE_SIZE);
// assert(FLASH_PAGE_SIZE * NVMCTRL->PARAM.bit.NVMP == FLASH_SIZE);
/* We have determined we should stay in the monitor. */
/* System initialization */
system_init();
cpu_irq_disable();
__disable_irq();
__DMB();
logmsg("Before main loop");
#ifdef SAMD21
setBootProt(7); // 0k
#endif
#ifdef SAMD51
// We only need to set the BOOTPROT once on the SAMD51. For updates, we can
// temporarily turn the protection off instead.
if (NVMCTRL->STATUS.bit.BOOTPROT != 13) {
setBootProt(13); // 16k
}
exec_cmd(NVMCTRL_CTRLB_CMD_SBPDIS);
NVMCTRL->CTRLA.bit.CACHEDIS0 = true;
NVMCTRL->CTRLA.bit.CACHEDIS1 = true;
#endif
const uint8_t *ptr = bootloader;
int i;
@ -88,22 +136,29 @@ int main(void) {
logmsg("Update successful!");
// re-base int vector back to bootloader, so that the flash erase below doesn't write over the
// vectors
SCB->VTOR = 0;
// Write zeros to the stack location and reset handler location so the
// bootloader doesn't run us a second time. We don't need to erase to write
// zeros. The remainder of the write unit will be set to 1s which should
// preserve the existing values but its not critical.
uint32_t zeros[2] = {0, 0};
flash_write_words((void *)(BOOTLOADER_K * 1024), zeros, 2);
for (i = 0; i < 20; ++i) {
LED_MSC_TGL();
delay(1000);
}
// re-base int vector back to bootloader, so that the flash erase below doesn't write over the
// vectors
SCB->VTOR = 0;
// erase first row of this updater app, so the bootloader doesn't start us again
flash_erase_row((void *)(BOOTLOADER_K * 1024));
LED_MSC_OFF();
#ifdef SAMD21
setBootProt(2); // 8k
#endif
// For the SAMD51, the boot protection will automatically be re-enabled on
// reset.
resetIntoBootloader();

View file

@ -273,21 +273,17 @@ void Reset_Handler(void)
while (1);
}
#include "system_interrupt.h"
/**
* \brief Default interrupt handler for unused IRQs.
*/
void Dummy_Handler(void)
{
volatile int act = system_interrupt_get_active();
(void)act;
while (1) {
}
}
void HardFault_Handler(void)
void HardFault_Handler(void)
{
while (1) {
}
}
}

548
src/startup_samd51.c Normal file
View file

@ -0,0 +1,548 @@
/**
* \file
*
* \brief gcc starttup file for SAMD51
*
* Copyright (c) 2017 Microchip Technology Inc.
*
* \asf_license_start
*
* \page License
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the Licence at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* \asf_license_stop
*
*/
#include "samd51.h"
/* Initialize segments */
extern uint32_t _sfixed;
extern uint32_t _efixed;
extern uint32_t _etext;
extern uint32_t _srelocate;
extern uint32_t _erelocate;
extern uint32_t _szero;
extern uint32_t _ezero;
extern uint32_t _sstack;
extern uint32_t _estack;
/** \cond DOXYGEN_SHOULD_SKIP_THIS */
int main(void);
/** \endcond */
void __libc_init_array(void);
/* Default empty handler */
void Dummy_Handler(void);
/* Cortex-M4 core handlers */
void NMI_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void HardFault_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void MemManage_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void BusFault_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void UsageFault_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void SVC_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void DebugMon_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void PendSV_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void SysTick_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
/* Peripherals handlers */
void PM_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void MCLK_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void OSCCTRL_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* OSCCTRL_XOSCFAIL_0, OSCCTRL_XOSCRDY_0 */
void OSCCTRL_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* OSCCTRL_XOSCFAIL_1, OSCCTRL_XOSCRDY_1 */
void OSCCTRL_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* OSCCTRL_DFLLLOCKC, OSCCTRL_DFLLLOCKF, OSCCTRL_DFLLOOB, OSCCTRL_DFLLRCS, OSCCTRL_DFLLRDY */
void OSCCTRL_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* OSCCTRL_DPLLLCKF_0, OSCCTRL_DPLLLCKR_0, OSCCTRL_DPLLLDRTO_0, OSCCTRL_DPLLLTO_0 */
void OSCCTRL_4_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* OSCCTRL_DPLLLCKF_1, OSCCTRL_DPLLLCKR_1, OSCCTRL_DPLLLDRTO_1, OSCCTRL_DPLLLTO_1 */
void OSC32KCTRL_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void SUPC_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SUPC_B12SRDY, SUPC_B33SRDY, SUPC_BOD12RDY, SUPC_BOD33RDY, SUPC_VCORERDY, SUPC_VREGRDY */
void SUPC_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SUPC_BOD12DET, SUPC_BOD33DET */
void WDT_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void RTC_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void EIC_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EIC_EXTINT_0 */
void EIC_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EIC_EXTINT_1 */
void EIC_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EIC_EXTINT_2 */
void EIC_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EIC_EXTINT_3 */
void EIC_4_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EIC_EXTINT_4 */
void EIC_5_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EIC_EXTINT_5 */
void EIC_6_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EIC_EXTINT_6 */
void EIC_7_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EIC_EXTINT_7 */
void EIC_8_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EIC_EXTINT_8 */
void EIC_9_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EIC_EXTINT_9 */
void EIC_10_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EIC_EXTINT_10 */
void EIC_11_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EIC_EXTINT_11 */
void EIC_12_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EIC_EXTINT_12 */
void EIC_13_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EIC_EXTINT_13 */
void EIC_14_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EIC_EXTINT_14 */
void EIC_15_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EIC_EXTINT_15 */
void FREQM_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void NVMCTRL_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* NVMCTRL_0, NVMCTRL_1, NVMCTRL_2, NVMCTRL_3, NVMCTRL_4, NVMCTRL_5, NVMCTRL_6, NVMCTRL_7 */
void NVMCTRL_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* NVMCTRL_10, NVMCTRL_8, NVMCTRL_9 */
void DMAC_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* DMAC_SUSP_0, DMAC_TCMPL_0, DMAC_TERR_0 */
void DMAC_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* DMAC_SUSP_1, DMAC_TCMPL_1, DMAC_TERR_1 */
void DMAC_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* DMAC_SUSP_2, DMAC_TCMPL_2, DMAC_TERR_2 */
void DMAC_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* DMAC_SUSP_3, DMAC_TCMPL_3, DMAC_TERR_3 */
void DMAC_4_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* DMAC_SUSP_10, DMAC_SUSP_11, DMAC_SUSP_12, DMAC_SUSP_13, DMAC_SUSP_14, DMAC_SUSP_15, DMAC_SUSP_16, DMAC_SUSP_17, DMAC_SUSP_18, DMAC_SUSP_19, DMAC_SUSP_20, DMAC_SUSP_21, DMAC_SUSP_22, DMAC_SUSP_23, DMAC_SUSP_24, DMAC_SUSP_25, DMAC_SUSP_26, DMAC_SUSP_27, DMAC_SUSP_28, DMAC_SUSP_29, DMAC_SUSP_30, DMAC_SUSP_31, DMAC_SUSP_4, DMAC_SUSP_5, DMAC_SUSP_6, DMAC_SUSP_7, DMAC_SUSP_8, DMAC_SUSP_9, DMAC_TCMPL_10, DMAC_TCMPL_11, DMAC_TCMPL_12, DMAC_TCMPL_13, DMAC_TCMPL_14, DMAC_TCMPL_15, DMAC_TCMPL_16, DMAC_TCMPL_17, DMAC_TCMPL_18, DMAC_TCMPL_19, DMAC_TCMPL_20, DMAC_TCMPL_21, DMAC_TCMPL_22, DMAC_TCMPL_23, DMAC_TCMPL_24, DMAC_TCMPL_25, DMAC_TCMPL_26, DMAC_TCMPL_27, DMAC_TCMPL_28, DMAC_TCMPL_29, DMAC_TCMPL_30, DMAC_TCMPL_31, DMAC_TCMPL_4, DMAC_TCMPL_5, DMAC_TCMPL_6, DMAC_TCMPL_7, DMAC_TCMPL_8, DMAC_TCMPL_9, DMAC_TERR_10, DMAC_TERR_11, DMAC_TERR_12, DMAC_TERR_13, DMAC_TERR_14, DMAC_TERR_15, DMAC_TERR_16, DMAC_TERR_17, DMAC_TERR_18, DMAC_TERR_19, DMAC_TERR_20, DMAC_TERR_21, DMAC_TERR_22, DMAC_TERR_23, DMAC_TERR_24, DMAC_TERR_25, DMAC_TERR_26, DMAC_TERR_27, DMAC_TERR_28, DMAC_TERR_29, DMAC_TERR_30, DMAC_TERR_31, DMAC_TERR_4, DMAC_TERR_5, DMAC_TERR_6, DMAC_TERR_7, DMAC_TERR_8, DMAC_TERR_9 */
void EVSYS_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EVSYS_EVD_0, EVSYS_OVR_0 */
void EVSYS_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EVSYS_EVD_1, EVSYS_OVR_1 */
void EVSYS_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EVSYS_EVD_2, EVSYS_OVR_2 */
void EVSYS_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EVSYS_EVD_3, EVSYS_OVR_3 */
void EVSYS_4_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* EVSYS_EVD_10, EVSYS_EVD_11, EVSYS_EVD_4, EVSYS_EVD_5, EVSYS_EVD_6, EVSYS_EVD_7, EVSYS_EVD_8, EVSYS_EVD_9, EVSYS_OVR_10, EVSYS_OVR_11, EVSYS_OVR_4, EVSYS_OVR_5, EVSYS_OVR_6, EVSYS_OVR_7, EVSYS_OVR_8, EVSYS_OVR_9 */
void PAC_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TAL_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TAL_BRK */
void TAL_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TAL_IPS_0, TAL_IPS_1 */
void RAMECC_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void SERCOM0_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM0_0 */
void SERCOM0_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM0_1 */
void SERCOM0_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM0_2 */
void SERCOM0_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM0_3, SERCOM0_4, SERCOM0_5, SERCOM0_6 */
void SERCOM1_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM1_0 */
void SERCOM1_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM1_1 */
void SERCOM1_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM1_2 */
void SERCOM1_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM1_3, SERCOM1_4, SERCOM1_5, SERCOM1_6 */
void SERCOM2_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM2_0 */
void SERCOM2_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM2_1 */
void SERCOM2_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM2_2 */
void SERCOM2_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM2_3, SERCOM2_4, SERCOM2_5, SERCOM2_6 */
void SERCOM3_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM3_0 */
void SERCOM3_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM3_1 */
void SERCOM3_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM3_2 */
void SERCOM3_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM3_3, SERCOM3_4, SERCOM3_5, SERCOM3_6 */
#ifdef ID_SERCOM4
void SERCOM4_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM4_0 */
void SERCOM4_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM4_1 */
void SERCOM4_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM4_2 */
void SERCOM4_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM4_3, SERCOM4_4, SERCOM4_5, SERCOM4_6 */
#endif
#ifdef ID_SERCOM5
void SERCOM5_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM5_0 */
void SERCOM5_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM5_1 */
void SERCOM5_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM5_2 */
void SERCOM5_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM5_3, SERCOM5_4, SERCOM5_5, SERCOM5_6 */
#endif
#ifdef ID_SERCOM6
void SERCOM6_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM6_0 */
void SERCOM6_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM6_1 */
void SERCOM6_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM6_2 */
void SERCOM6_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM6_3, SERCOM6_4, SERCOM6_5, SERCOM6_6 */
#endif
#ifdef ID_SERCOM7
void SERCOM7_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM7_0 */
void SERCOM7_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM7_1 */
void SERCOM7_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM7_2 */
void SERCOM7_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* SERCOM7_3, SERCOM7_4, SERCOM7_5, SERCOM7_6 */
#endif
#ifdef ID_CAN0
void CAN0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
#endif
#ifdef ID_CAN1
void CAN1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
#endif
#ifdef ID_USB
void USB_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* USB_EORSM_DNRSM, USB_EORST_RST, USB_LPMSUSP_DDISC, USB_LPM_DCONN, USB_MSOF, USB_RAMACER, USB_RXSTP_TXSTP_0, USB_RXSTP_TXSTP_1, USB_RXSTP_TXSTP_2, USB_RXSTP_TXSTP_3, USB_RXSTP_TXSTP_4, USB_RXSTP_TXSTP_5, USB_RXSTP_TXSTP_6, USB_RXSTP_TXSTP_7, USB_STALL0_STALL_0, USB_STALL0_STALL_1, USB_STALL0_STALL_2, USB_STALL0_STALL_3, USB_STALL0_STALL_4, USB_STALL0_STALL_5, USB_STALL0_STALL_6, USB_STALL0_STALL_7, USB_STALL1_0, USB_STALL1_1, USB_STALL1_2, USB_STALL1_3, USB_STALL1_4, USB_STALL1_5, USB_STALL1_6, USB_STALL1_7, USB_SUSPEND, USB_TRFAIL0_TRFAIL_0, USB_TRFAIL0_TRFAIL_1, USB_TRFAIL0_TRFAIL_2, USB_TRFAIL0_TRFAIL_3, USB_TRFAIL0_TRFAIL_4, USB_TRFAIL0_TRFAIL_5, USB_TRFAIL0_TRFAIL_6, USB_TRFAIL0_TRFAIL_7, USB_TRFAIL1_PERR_0, USB_TRFAIL1_PERR_1, USB_TRFAIL1_PERR_2, USB_TRFAIL1_PERR_3, USB_TRFAIL1_PERR_4, USB_TRFAIL1_PERR_5, USB_TRFAIL1_PERR_6, USB_TRFAIL1_PERR_7, USB_UPRSM, USB_WAKEUP */
void USB_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* USB_SOF_HSOF */
void USB_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* USB_TRCPT0_0, USB_TRCPT0_1, USB_TRCPT0_2, USB_TRCPT0_3, USB_TRCPT0_4, USB_TRCPT0_5, USB_TRCPT0_6, USB_TRCPT0_7 */
void USB_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* USB_TRCPT1_0, USB_TRCPT1_1, USB_TRCPT1_2, USB_TRCPT1_3, USB_TRCPT1_4, USB_TRCPT1_5, USB_TRCPT1_6, USB_TRCPT1_7 */
#endif
#ifdef ID_GMAC
void GMAC_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
#endif
void TCC0_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC0_CNT_A, TCC0_DFS_A, TCC0_ERR_A, TCC0_FAULT0_A, TCC0_FAULT1_A, TCC0_FAULTA_A, TCC0_FAULTB_A, TCC0_OVF, TCC0_TRG, TCC0_UFS_A */
void TCC0_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC0_MC_0 */
void TCC0_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC0_MC_1 */
void TCC0_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC0_MC_2 */
void TCC0_4_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC0_MC_3 */
void TCC0_5_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC0_MC_4 */
void TCC0_6_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC0_MC_5 */
void TCC1_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC1_CNT_A, TCC1_DFS_A, TCC1_ERR_A, TCC1_FAULT0_A, TCC1_FAULT1_A, TCC1_FAULTA_A, TCC1_FAULTB_A, TCC1_OVF, TCC1_TRG, TCC1_UFS_A */
void TCC1_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC1_MC_0 */
void TCC1_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC1_MC_1 */
void TCC1_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC1_MC_2 */
void TCC1_4_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC1_MC_3 */
void TCC2_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC2_CNT_A, TCC2_DFS_A, TCC2_ERR_A, TCC2_FAULT0_A, TCC2_FAULT1_A, TCC2_FAULTA_A, TCC2_FAULTB_A, TCC2_OVF, TCC2_TRG, TCC2_UFS_A */
void TCC2_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC2_MC_0 */
void TCC2_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC2_MC_1 */
void TCC2_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC2_MC_2 */
#ifdef ID_TCC3
void TCC3_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC3_CNT_A, TCC3_DFS_A, TCC3_ERR_A, TCC3_FAULT0_A, TCC3_FAULT1_A, TCC3_FAULTA_A, TCC3_FAULTB_A, TCC3_OVF, TCC3_TRG, TCC3_UFS_A */
void TCC3_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC3_MC_0 */
void TCC3_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC3_MC_1 */
#endif
#ifdef ID_TCC4
void TCC4_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC4_CNT_A, TCC4_DFS_A, TCC4_ERR_A, TCC4_FAULT0_A, TCC4_FAULT1_A, TCC4_FAULTA_A, TCC4_FAULTB_A, TCC4_OVF, TCC4_TRG, TCC4_UFS_A */
void TCC4_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC4_MC_0 */
void TCC4_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* TCC4_MC_1 */
#endif
void TC0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TC1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TC2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TC3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
#ifdef ID_TC4
void TC4_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
#endif
#ifdef ID_TC5
void TC5_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
#endif
#ifdef ID_TC6
void TC6_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
#endif
#ifdef ID_TC7
void TC7_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
#endif
void PDEC_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* PDEC_DIR_A, PDEC_ERR_A, PDEC_OVF, PDEC_VLC_A */
void PDEC_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* PDEC_MC_0 */
void PDEC_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* PDEC_MC_1 */
void ADC0_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* ADC0_OVERRUN, ADC0_WINMON */
void ADC0_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* ADC0_RESRDY */
void ADC1_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* ADC1_OVERRUN, ADC1_WINMON */
void ADC1_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* ADC1_RESRDY */
void AC_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void DAC_0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* DAC_OVERRUN_A_0, DAC_OVERRUN_A_1, DAC_UNDERRUN_A_0, DAC_UNDERRUN_A_1 */
void DAC_1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* DAC_EMPTY_0 */
void DAC_2_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* DAC_EMPTY_1 */
void DAC_3_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* DAC_RESRDY_0 */
void DAC_4_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); /* DAC_RESRDY_1 */
#ifdef ID_I2S
void I2S_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
#endif
void PCC_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void AES_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
void TRNG_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
#ifdef ID_ICM
void ICM_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
#endif
#ifdef ID_PUKCC
void PUKCC_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
#endif
void QSPI_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
#ifdef ID_SDHC0
void SDHC0_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
#endif
#ifdef ID_SDHC1
void SDHC1_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
#endif
/* Exception Table */
__attribute__ ((section(".vectors")))
const DeviceVectors exception_table = {
/* Configure Initial Stack Pointer, using linker-generated symbols */
.pvStack = (void*) (&_estack),
.pfnReset_Handler = (void*) Reset_Handler,
.pfnNMI_Handler = (void*) NMI_Handler,
.pfnHardFault_Handler = (void*) HardFault_Handler,
.pfnMemManage_Handler = (void*) MemManage_Handler,
.pfnBusFault_Handler = (void*) BusFault_Handler,
.pfnUsageFault_Handler = (void*) UsageFault_Handler,
.pvReservedM9 = (void*) (0UL), /* Reserved */
.pvReservedM8 = (void*) (0UL), /* Reserved */
.pvReservedM7 = (void*) (0UL), /* Reserved */
.pvReservedM6 = (void*) (0UL), /* Reserved */
.pfnSVC_Handler = (void*) SVC_Handler,
.pfnDebugMon_Handler = (void*) DebugMon_Handler,
.pvReservedM3 = (void*) (0UL), /* Reserved */
.pfnPendSV_Handler = (void*) PendSV_Handler,
.pfnSysTick_Handler = (void*) SysTick_Handler,
/* Configurable interrupts */
.pfnPM_Handler = (void*) PM_Handler, /* 0 Power Manager */
.pfnMCLK_Handler = (void*) MCLK_Handler, /* 1 Main Clock */
.pfnOSCCTRL_0_Handler = (void*) OSCCTRL_0_Handler, /* 2 OSCCTRL_XOSCFAIL_0, OSCCTRL_XOSCRDY_0 */
.pfnOSCCTRL_1_Handler = (void*) OSCCTRL_1_Handler, /* 3 OSCCTRL_XOSCFAIL_1, OSCCTRL_XOSCRDY_1 */
.pfnOSCCTRL_2_Handler = (void*) OSCCTRL_2_Handler, /* 4 OSCCTRL_DFLLLOCKC, OSCCTRL_DFLLLOCKF, OSCCTRL_DFLLOOB, OSCCTRL_DFLLRCS, OSCCTRL_DFLLRDY */
.pfnOSCCTRL_3_Handler = (void*) OSCCTRL_3_Handler, /* 5 OSCCTRL_DPLLLCKF_0, OSCCTRL_DPLLLCKR_0, OSCCTRL_DPLLLDRTO_0, OSCCTRL_DPLLLTO_0 */
.pfnOSCCTRL_4_Handler = (void*) OSCCTRL_4_Handler, /* 6 OSCCTRL_DPLLLCKF_1, OSCCTRL_DPLLLCKR_1, OSCCTRL_DPLLLDRTO_1, OSCCTRL_DPLLLTO_1 */
.pfnOSC32KCTRL_Handler = (void*) OSC32KCTRL_Handler, /* 7 32kHz Oscillators Control */
.pfnSUPC_0_Handler = (void*) SUPC_0_Handler, /* 8 SUPC_B12SRDY, SUPC_B33SRDY, SUPC_BOD12RDY, SUPC_BOD33RDY, SUPC_VCORERDY, SUPC_VREGRDY */
.pfnSUPC_1_Handler = (void*) SUPC_1_Handler, /* 9 SUPC_BOD12DET, SUPC_BOD33DET */
.pfnWDT_Handler = (void*) WDT_Handler, /* 10 Watchdog Timer */
.pfnRTC_Handler = (void*) RTC_Handler, /* 11 Real-Time Counter */
.pfnEIC_0_Handler = (void*) EIC_0_Handler, /* 12 EIC_EXTINT_0 */
.pfnEIC_1_Handler = (void*) EIC_1_Handler, /* 13 EIC_EXTINT_1 */
.pfnEIC_2_Handler = (void*) EIC_2_Handler, /* 14 EIC_EXTINT_2 */
.pfnEIC_3_Handler = (void*) EIC_3_Handler, /* 15 EIC_EXTINT_3 */
.pfnEIC_4_Handler = (void*) EIC_4_Handler, /* 16 EIC_EXTINT_4 */
.pfnEIC_5_Handler = (void*) EIC_5_Handler, /* 17 EIC_EXTINT_5 */
.pfnEIC_6_Handler = (void*) EIC_6_Handler, /* 18 EIC_EXTINT_6 */
.pfnEIC_7_Handler = (void*) EIC_7_Handler, /* 19 EIC_EXTINT_7 */
.pfnEIC_8_Handler = (void*) EIC_8_Handler, /* 20 EIC_EXTINT_8 */
.pfnEIC_9_Handler = (void*) EIC_9_Handler, /* 21 EIC_EXTINT_9 */
.pfnEIC_10_Handler = (void*) EIC_10_Handler, /* 22 EIC_EXTINT_10 */
.pfnEIC_11_Handler = (void*) EIC_11_Handler, /* 23 EIC_EXTINT_11 */
.pfnEIC_12_Handler = (void*) EIC_12_Handler, /* 24 EIC_EXTINT_12 */
.pfnEIC_13_Handler = (void*) EIC_13_Handler, /* 25 EIC_EXTINT_13 */
.pfnEIC_14_Handler = (void*) EIC_14_Handler, /* 26 EIC_EXTINT_14 */
.pfnEIC_15_Handler = (void*) EIC_15_Handler, /* 27 EIC_EXTINT_15 */
.pfnFREQM_Handler = (void*) FREQM_Handler, /* 28 Frequency Meter */
.pfnNVMCTRL_0_Handler = (void*) NVMCTRL_0_Handler, /* 29 NVMCTRL_0, NVMCTRL_1, NVMCTRL_2, NVMCTRL_3, NVMCTRL_4, NVMCTRL_5, NVMCTRL_6, NVMCTRL_7 */
.pfnNVMCTRL_1_Handler = (void*) NVMCTRL_1_Handler, /* 30 NVMCTRL_10, NVMCTRL_8, NVMCTRL_9 */
.pfnDMAC_0_Handler = (void*) DMAC_0_Handler, /* 31 DMAC_SUSP_0, DMAC_TCMPL_0, DMAC_TERR_0 */
.pfnDMAC_1_Handler = (void*) DMAC_1_Handler, /* 32 DMAC_SUSP_1, DMAC_TCMPL_1, DMAC_TERR_1 */
.pfnDMAC_2_Handler = (void*) DMAC_2_Handler, /* 33 DMAC_SUSP_2, DMAC_TCMPL_2, DMAC_TERR_2 */
.pfnDMAC_3_Handler = (void*) DMAC_3_Handler, /* 34 DMAC_SUSP_3, DMAC_TCMPL_3, DMAC_TERR_3 */
.pfnDMAC_4_Handler = (void*) DMAC_4_Handler, /* 35 DMAC_SUSP_10, DMAC_SUSP_11, DMAC_SUSP_12, DMAC_SUSP_13, DMAC_SUSP_14, DMAC_SUSP_15, DMAC_SUSP_16, DMAC_SUSP_17, DMAC_SUSP_18, DMAC_SUSP_19, DMAC_SUSP_20, DMAC_SUSP_21, DMAC_SUSP_22, DMAC_SUSP_23, DMAC_SUSP_24, DMAC_SUSP_25, DMAC_SUSP_26, DMAC_SUSP_27, DMAC_SUSP_28, DMAC_SUSP_29, DMAC_SUSP_30, DMAC_SUSP_31, DMAC_SUSP_4, DMAC_SUSP_5, DMAC_SUSP_6, DMAC_SUSP_7, DMAC_SUSP_8, DMAC_SUSP_9, DMAC_TCMPL_10, DMAC_TCMPL_11, DMAC_TCMPL_12, DMAC_TCMPL_13, DMAC_TCMPL_14, DMAC_TCMPL_15, DMAC_TCMPL_16, DMAC_TCMPL_17, DMAC_TCMPL_18, DMAC_TCMPL_19, DMAC_TCMPL_20, DMAC_TCMPL_21, DMAC_TCMPL_22, DMAC_TCMPL_23, DMAC_TCMPL_24, DMAC_TCMPL_25, DMAC_TCMPL_26, DMAC_TCMPL_27, DMAC_TCMPL_28, DMAC_TCMPL_29, DMAC_TCMPL_30, DMAC_TCMPL_31, DMAC_TCMPL_4, DMAC_TCMPL_5, DMAC_TCMPL_6, DMAC_TCMPL_7, DMAC_TCMPL_8, DMAC_TCMPL_9, DMAC_TERR_10, DMAC_TERR_11, DMAC_TERR_12, DMAC_TERR_13, DMAC_TERR_14, DMAC_TERR_15, DMAC_TERR_16, DMAC_TERR_17, DMAC_TERR_18, DMAC_TERR_19, DMAC_TERR_20, DMAC_TERR_21, DMAC_TERR_22, DMAC_TERR_23, DMAC_TERR_24, DMAC_TERR_25, DMAC_TERR_26, DMAC_TERR_27, DMAC_TERR_28, DMAC_TERR_29, DMAC_TERR_30, DMAC_TERR_31, DMAC_TERR_4, DMAC_TERR_5, DMAC_TERR_6, DMAC_TERR_7, DMAC_TERR_8, DMAC_TERR_9 */
.pfnEVSYS_0_Handler = (void*) EVSYS_0_Handler, /* 36 EVSYS_EVD_0, EVSYS_OVR_0 */
.pfnEVSYS_1_Handler = (void*) EVSYS_1_Handler, /* 37 EVSYS_EVD_1, EVSYS_OVR_1 */
.pfnEVSYS_2_Handler = (void*) EVSYS_2_Handler, /* 38 EVSYS_EVD_2, EVSYS_OVR_2 */
.pfnEVSYS_3_Handler = (void*) EVSYS_3_Handler, /* 39 EVSYS_EVD_3, EVSYS_OVR_3 */
.pfnEVSYS_4_Handler = (void*) EVSYS_4_Handler, /* 40 EVSYS_EVD_10, EVSYS_EVD_11, EVSYS_EVD_4, EVSYS_EVD_5, EVSYS_EVD_6, EVSYS_EVD_7, EVSYS_EVD_8, EVSYS_EVD_9, EVSYS_OVR_10, EVSYS_OVR_11, EVSYS_OVR_4, EVSYS_OVR_5, EVSYS_OVR_6, EVSYS_OVR_7, EVSYS_OVR_8, EVSYS_OVR_9 */
.pfnPAC_Handler = (void*) PAC_Handler, /* 41 Peripheral Access Controller */
.pfnTAL_0_Handler = (void*) TAL_0_Handler, /* 42 TAL_BRK */
.pfnTAL_1_Handler = (void*) TAL_1_Handler, /* 43 TAL_IPS_0, TAL_IPS_1 */
.pvReserved44 = (void*) (0UL), /* 44 Reserved */
.pfnRAMECC_Handler = (void*) RAMECC_Handler, /* 45 RAM ECC */
.pfnSERCOM0_0_Handler = (void*) SERCOM0_0_Handler, /* 46 SERCOM0_0 */
.pfnSERCOM0_1_Handler = (void*) SERCOM0_1_Handler, /* 47 SERCOM0_1 */
.pfnSERCOM0_2_Handler = (void*) SERCOM0_2_Handler, /* 48 SERCOM0_2 */
.pfnSERCOM0_3_Handler = (void*) SERCOM0_3_Handler, /* 49 SERCOM0_3, SERCOM0_4, SERCOM0_5, SERCOM0_6 */
.pfnSERCOM1_0_Handler = (void*) SERCOM1_0_Handler, /* 50 SERCOM1_0 */
.pfnSERCOM1_1_Handler = (void*) SERCOM1_1_Handler, /* 51 SERCOM1_1 */
.pfnSERCOM1_2_Handler = (void*) SERCOM1_2_Handler, /* 52 SERCOM1_2 */
.pfnSERCOM1_3_Handler = (void*) SERCOM1_3_Handler, /* 53 SERCOM1_3, SERCOM1_4, SERCOM1_5, SERCOM1_6 */
.pfnSERCOM2_0_Handler = (void*) SERCOM2_0_Handler, /* 54 SERCOM2_0 */
.pfnSERCOM2_1_Handler = (void*) SERCOM2_1_Handler, /* 55 SERCOM2_1 */
.pfnSERCOM2_2_Handler = (void*) SERCOM2_2_Handler, /* 56 SERCOM2_2 */
.pfnSERCOM2_3_Handler = (void*) SERCOM2_3_Handler, /* 57 SERCOM2_3, SERCOM2_4, SERCOM2_5, SERCOM2_6 */
.pfnSERCOM3_0_Handler = (void*) SERCOM3_0_Handler, /* 58 SERCOM3_0 */
.pfnSERCOM3_1_Handler = (void*) SERCOM3_1_Handler, /* 59 SERCOM3_1 */
.pfnSERCOM3_2_Handler = (void*) SERCOM3_2_Handler, /* 60 SERCOM3_2 */
.pfnSERCOM3_3_Handler = (void*) SERCOM3_3_Handler, /* 61 SERCOM3_3, SERCOM3_4, SERCOM3_5, SERCOM3_6 */
#ifdef ID_SERCOM4
.pfnSERCOM4_0_Handler = (void*) SERCOM4_0_Handler, /* 62 SERCOM4_0 */
.pfnSERCOM4_1_Handler = (void*) SERCOM4_1_Handler, /* 63 SERCOM4_1 */
.pfnSERCOM4_2_Handler = (void*) SERCOM4_2_Handler, /* 64 SERCOM4_2 */
.pfnSERCOM4_3_Handler = (void*) SERCOM4_3_Handler, /* 65 SERCOM4_3, SERCOM4_4, SERCOM4_5, SERCOM4_6 */
#else
.pvReserved62 = (void*) (0UL), /* 62 Reserved */
.pvReserved63 = (void*) (0UL), /* 63 Reserved */
.pvReserved64 = (void*) (0UL), /* 64 Reserved */
.pvReserved65 = (void*) (0UL), /* 65 Reserved */
#endif
#ifdef ID_SERCOM5
.pfnSERCOM5_0_Handler = (void*) SERCOM5_0_Handler, /* 66 SERCOM5_0 */
.pfnSERCOM5_1_Handler = (void*) SERCOM5_1_Handler, /* 67 SERCOM5_1 */
.pfnSERCOM5_2_Handler = (void*) SERCOM5_2_Handler, /* 68 SERCOM5_2 */
.pfnSERCOM5_3_Handler = (void*) SERCOM5_3_Handler, /* 69 SERCOM5_3, SERCOM5_4, SERCOM5_5, SERCOM5_6 */
#else
.pvReserved66 = (void*) (0UL), /* 66 Reserved */
.pvReserved67 = (void*) (0UL), /* 67 Reserved */
.pvReserved68 = (void*) (0UL), /* 68 Reserved */
.pvReserved69 = (void*) (0UL), /* 69 Reserved */
#endif
#ifdef ID_SERCOM6
.pfnSERCOM6_0_Handler = (void*) SERCOM6_0_Handler, /* 70 SERCOM6_0 */
.pfnSERCOM6_1_Handler = (void*) SERCOM6_1_Handler, /* 71 SERCOM6_1 */
.pfnSERCOM6_2_Handler = (void*) SERCOM6_2_Handler, /* 72 SERCOM6_2 */
.pfnSERCOM6_3_Handler = (void*) SERCOM6_3_Handler, /* 73 SERCOM6_3, SERCOM6_4, SERCOM6_5, SERCOM6_6 */
#else
.pvReserved70 = (void*) (0UL), /* 70 Reserved */
.pvReserved71 = (void*) (0UL), /* 71 Reserved */
.pvReserved72 = (void*) (0UL), /* 72 Reserved */
.pvReserved73 = (void*) (0UL), /* 73 Reserved */
#endif
#ifdef ID_SERCOM7
.pfnSERCOM7_0_Handler = (void*) SERCOM7_0_Handler, /* 74 SERCOM7_0 */
.pfnSERCOM7_1_Handler = (void*) SERCOM7_1_Handler, /* 75 SERCOM7_1 */
.pfnSERCOM7_2_Handler = (void*) SERCOM7_2_Handler, /* 76 SERCOM7_2 */
.pfnSERCOM7_3_Handler = (void*) SERCOM7_3_Handler, /* 77 SERCOM7_3, SERCOM7_4, SERCOM7_5, SERCOM7_6 */
#else
.pvReserved74 = (void*) (0UL), /* 74 Reserved */
.pvReserved75 = (void*) (0UL), /* 75 Reserved */
.pvReserved76 = (void*) (0UL), /* 76 Reserved */
.pvReserved77 = (void*) (0UL), /* 77 Reserved */
#endif
#ifdef ID_CAN0
.pfnCAN0_Handler = (void*) CAN0_Handler, /* 78 Control Area Network 0 */
#else
.pvReserved78 = (void*) (0UL), /* 78 Reserved */
#endif
#ifdef ID_CAN1
.pfnCAN1_Handler = (void*) CAN1_Handler, /* 79 Control Area Network 1 */
#else
.pvReserved79 = (void*) (0UL), /* 79 Reserved */
#endif
#ifdef ID_USB
.pfnUSB_0_Handler = (void*) USB_0_Handler, /* 80 USB_EORSM_DNRSM, USB_EORST_RST, USB_LPMSUSP_DDISC, USB_LPM_DCONN, USB_MSOF, USB_RAMACER, USB_RXSTP_TXSTP_0, USB_RXSTP_TXSTP_1, USB_RXSTP_TXSTP_2, USB_RXSTP_TXSTP_3, USB_RXSTP_TXSTP_4, USB_RXSTP_TXSTP_5, USB_RXSTP_TXSTP_6, USB_RXSTP_TXSTP_7, USB_STALL0_STALL_0, USB_STALL0_STALL_1, USB_STALL0_STALL_2, USB_STALL0_STALL_3, USB_STALL0_STALL_4, USB_STALL0_STALL_5, USB_STALL0_STALL_6, USB_STALL0_STALL_7, USB_STALL1_0, USB_STALL1_1, USB_STALL1_2, USB_STALL1_3, USB_STALL1_4, USB_STALL1_5, USB_STALL1_6, USB_STALL1_7, USB_SUSPEND, USB_TRFAIL0_TRFAIL_0, USB_TRFAIL0_TRFAIL_1, USB_TRFAIL0_TRFAIL_2, USB_TRFAIL0_TRFAIL_3, USB_TRFAIL0_TRFAIL_4, USB_TRFAIL0_TRFAIL_5, USB_TRFAIL0_TRFAIL_6, USB_TRFAIL0_TRFAIL_7, USB_TRFAIL1_PERR_0, USB_TRFAIL1_PERR_1, USB_TRFAIL1_PERR_2, USB_TRFAIL1_PERR_3, USB_TRFAIL1_PERR_4, USB_TRFAIL1_PERR_5, USB_TRFAIL1_PERR_6, USB_TRFAIL1_PERR_7, USB_UPRSM, USB_WAKEUP */
.pfnUSB_1_Handler = (void*) USB_1_Handler, /* 81 USB_SOF_HSOF */
.pfnUSB_2_Handler = (void*) USB_2_Handler, /* 82 USB_TRCPT0_0, USB_TRCPT0_1, USB_TRCPT0_2, USB_TRCPT0_3, USB_TRCPT0_4, USB_TRCPT0_5, USB_TRCPT0_6, USB_TRCPT0_7 */
.pfnUSB_3_Handler = (void*) USB_3_Handler, /* 83 USB_TRCPT1_0, USB_TRCPT1_1, USB_TRCPT1_2, USB_TRCPT1_3, USB_TRCPT1_4, USB_TRCPT1_5, USB_TRCPT1_6, USB_TRCPT1_7 */
#else
.pvReserved80 = (void*) (0UL), /* 80 Reserved */
.pvReserved81 = (void*) (0UL), /* 81 Reserved */
.pvReserved82 = (void*) (0UL), /* 82 Reserved */
.pvReserved83 = (void*) (0UL), /* 83 Reserved */
#endif
#ifdef ID_GMAC
.pfnGMAC_Handler = (void*) GMAC_Handler, /* 84 Ethernet MAC */
#else
.pvReserved84 = (void*) (0UL), /* 84 Reserved */
#endif
.pfnTCC0_0_Handler = (void*) TCC0_0_Handler, /* 85 TCC0_CNT_A, TCC0_DFS_A, TCC0_ERR_A, TCC0_FAULT0_A, TCC0_FAULT1_A, TCC0_FAULTA_A, TCC0_FAULTB_A, TCC0_OVF, TCC0_TRG, TCC0_UFS_A */
.pfnTCC0_1_Handler = (void*) TCC0_1_Handler, /* 86 TCC0_MC_0 */
.pfnTCC0_2_Handler = (void*) TCC0_2_Handler, /* 87 TCC0_MC_1 */
.pfnTCC0_3_Handler = (void*) TCC0_3_Handler, /* 88 TCC0_MC_2 */
.pfnTCC0_4_Handler = (void*) TCC0_4_Handler, /* 89 TCC0_MC_3 */
.pfnTCC0_5_Handler = (void*) TCC0_5_Handler, /* 90 TCC0_MC_4 */
.pfnTCC0_6_Handler = (void*) TCC0_6_Handler, /* 91 TCC0_MC_5 */
.pfnTCC1_0_Handler = (void*) TCC1_0_Handler, /* 92 TCC1_CNT_A, TCC1_DFS_A, TCC1_ERR_A, TCC1_FAULT0_A, TCC1_FAULT1_A, TCC1_FAULTA_A, TCC1_FAULTB_A, TCC1_OVF, TCC1_TRG, TCC1_UFS_A */
.pfnTCC1_1_Handler = (void*) TCC1_1_Handler, /* 93 TCC1_MC_0 */
.pfnTCC1_2_Handler = (void*) TCC1_2_Handler, /* 94 TCC1_MC_1 */
.pfnTCC1_3_Handler = (void*) TCC1_3_Handler, /* 95 TCC1_MC_2 */
.pfnTCC1_4_Handler = (void*) TCC1_4_Handler, /* 96 TCC1_MC_3 */
.pfnTCC2_0_Handler = (void*) TCC2_0_Handler, /* 97 TCC2_CNT_A, TCC2_DFS_A, TCC2_ERR_A, TCC2_FAULT0_A, TCC2_FAULT1_A, TCC2_FAULTA_A, TCC2_FAULTB_A, TCC2_OVF, TCC2_TRG, TCC2_UFS_A */
.pfnTCC2_1_Handler = (void*) TCC2_1_Handler, /* 98 TCC2_MC_0 */
.pfnTCC2_2_Handler = (void*) TCC2_2_Handler, /* 99 TCC2_MC_1 */
.pfnTCC2_3_Handler = (void*) TCC2_3_Handler, /* 100 TCC2_MC_2 */
#ifdef ID_TCC3
.pfnTCC3_0_Handler = (void*) TCC3_0_Handler, /* 101 TCC3_CNT_A, TCC3_DFS_A, TCC3_ERR_A, TCC3_FAULT0_A, TCC3_FAULT1_A, TCC3_FAULTA_A, TCC3_FAULTB_A, TCC3_OVF, TCC3_TRG, TCC3_UFS_A */
.pfnTCC3_1_Handler = (void*) TCC3_1_Handler, /* 102 TCC3_MC_0 */
.pfnTCC3_2_Handler = (void*) TCC3_2_Handler, /* 103 TCC3_MC_1 */
#else
.pvReserved101 = (void*) (0UL), /* 101 Reserved */
.pvReserved102 = (void*) (0UL), /* 102 Reserved */
.pvReserved103 = (void*) (0UL), /* 103 Reserved */
#endif
#ifdef ID_TCC4
.pfnTCC4_0_Handler = (void*) TCC4_0_Handler, /* 104 TCC4_CNT_A, TCC4_DFS_A, TCC4_ERR_A, TCC4_FAULT0_A, TCC4_FAULT1_A, TCC4_FAULTA_A, TCC4_FAULTB_A, TCC4_OVF, TCC4_TRG, TCC4_UFS_A */
.pfnTCC4_1_Handler = (void*) TCC4_1_Handler, /* 105 TCC4_MC_0 */
.pfnTCC4_2_Handler = (void*) TCC4_2_Handler, /* 106 TCC4_MC_1 */
#else
.pvReserved104 = (void*) (0UL), /* 104 Reserved */
.pvReserved105 = (void*) (0UL), /* 105 Reserved */
.pvReserved106 = (void*) (0UL), /* 106 Reserved */
#endif
.pfnTC0_Handler = (void*) TC0_Handler, /* 107 Basic Timer Counter 0 */
.pfnTC1_Handler = (void*) TC1_Handler, /* 108 Basic Timer Counter 1 */
.pfnTC2_Handler = (void*) TC2_Handler, /* 109 Basic Timer Counter 2 */
.pfnTC3_Handler = (void*) TC3_Handler, /* 110 Basic Timer Counter 3 */
#ifdef ID_TC4
.pfnTC4_Handler = (void*) TC4_Handler, /* 111 Basic Timer Counter 4 */
#else
.pvReserved111 = (void*) (0UL), /* 111 Reserved */
#endif
#ifdef ID_TC5
.pfnTC5_Handler = (void*) TC5_Handler, /* 112 Basic Timer Counter 5 */
#else
.pvReserved112 = (void*) (0UL), /* 112 Reserved */
#endif
#ifdef ID_TC6
.pfnTC6_Handler = (void*) TC6_Handler, /* 113 Basic Timer Counter 6 */
#else
.pvReserved113 = (void*) (0UL), /* 113 Reserved */
#endif
#ifdef ID_TC7
.pfnTC7_Handler = (void*) TC7_Handler, /* 114 Basic Timer Counter 7 */
#else
.pvReserved114 = (void*) (0UL), /* 114 Reserved */
#endif
.pfnPDEC_0_Handler = (void*) PDEC_0_Handler, /* 115 PDEC_DIR_A, PDEC_ERR_A, PDEC_OVF, PDEC_VLC_A */
.pfnPDEC_1_Handler = (void*) PDEC_1_Handler, /* 116 PDEC_MC_0 */
.pfnPDEC_2_Handler = (void*) PDEC_2_Handler, /* 117 PDEC_MC_1 */
.pfnADC0_0_Handler = (void*) ADC0_0_Handler, /* 118 ADC0_OVERRUN, ADC0_WINMON */
.pfnADC0_1_Handler = (void*) ADC0_1_Handler, /* 119 ADC0_RESRDY */
.pfnADC1_0_Handler = (void*) ADC1_0_Handler, /* 120 ADC1_OVERRUN, ADC1_WINMON */
.pfnADC1_1_Handler = (void*) ADC1_1_Handler, /* 121 ADC1_RESRDY */
.pfnAC_Handler = (void*) AC_Handler, /* 122 Analog Comparators */
.pfnDAC_0_Handler = (void*) DAC_0_Handler, /* 123 DAC_OVERRUN_A_0, DAC_OVERRUN_A_1, DAC_UNDERRUN_A_0, DAC_UNDERRUN_A_1 */
.pfnDAC_1_Handler = (void*) DAC_1_Handler, /* 124 DAC_EMPTY_0 */
.pfnDAC_2_Handler = (void*) DAC_2_Handler, /* 125 DAC_EMPTY_1 */
.pfnDAC_3_Handler = (void*) DAC_3_Handler, /* 126 DAC_RESRDY_0 */
.pfnDAC_4_Handler = (void*) DAC_4_Handler, /* 127 DAC_RESRDY_1 */
#ifdef ID_I2S
.pfnI2S_Handler = (void*) I2S_Handler, /* 128 Inter-IC Sound Interface */
#else
.pvReserved128 = (void*) (0UL), /* 128 Reserved */
#endif
.pfnPCC_Handler = (void*) PCC_Handler, /* 129 Parallel Capture Controller */
.pfnAES_Handler = (void*) AES_Handler, /* 130 Advanced Encryption Standard */
.pfnTRNG_Handler = (void*) TRNG_Handler, /* 131 True Random Generator */
#ifdef ID_ICM
.pfnICM_Handler = (void*) ICM_Handler, /* 132 Integrity Check Monitor */
#else
.pvReserved132 = (void*) (0UL), /* 132 Reserved */
#endif
#ifdef ID_PUKCC
.pfnPUKCC_Handler = (void*) PUKCC_Handler, /* 133 PUblic-Key Cryptography Controller */
#else
.pvReserved133 = (void*) (0UL), /* 133 Reserved */
#endif
.pfnQSPI_Handler = (void*) QSPI_Handler, /* 134 Quad SPI interface */
#ifdef ID_SDHC0
.pfnSDHC0_Handler = (void*) SDHC0_Handler, /* 135 SD/MMC Host Controller 0 */
#else
.pvReserved135 = (void*) (0UL), /* 135 Reserved */
#endif
#ifdef ID_SDHC1
.pfnSDHC1_Handler = (void*) SDHC1_Handler /* 136 SD/MMC Host Controller 1 */
#else
.pvReserved136 = (void*) (0UL) /* 136 Reserved */
#endif
};
/**
* \brief This is the code that gets called on processor reset.
* To initialize the device, and call the main() routine.
*/
void Reset_Handler(void)
{
uint32_t *pSrc, *pDest;
/* Initialize the relocate segment */
pSrc = &_etext;
pDest = &_srelocate;
if (pSrc != pDest) {
for (; pDest < &_erelocate;) {
*pDest++ = *pSrc++;
}
}
/* Clear the zero segment */
for (pDest = &_szero; pDest < &_ezero;) {
*pDest++ = 0;
}
/* Set the vector table base address */
pSrc = (uint32_t *) & _sfixed;
SCB->VTOR = ((uint32_t) pSrc & SCB_VTOR_TBLOFF_Msk);
#if __FPU_USED
/* Enable FPU */
SCB->CPACR |= (0xFu << 20);
__DSB();
__ISB();
#endif
/* Initialize the C library */
//__libc_init_array();
/* Branch to main function */
main();
/* Infinite loop */
while (1);
}
/**
* \brief Default interrupt handler for unused IRQs.
*/
void Dummy_Handler(void)
{
while (1) {
}
}

View file

@ -102,8 +102,8 @@ void usart_open() {
<< (4 * (pin & 0x01u));
}
#ifdef SAMD21
inst = uart_get_sercom_index(BOOT_USART_MODULE);
/* Enable clock for BOOT_USART_MODULE */
PM->APBCMASK.reg |= (1u << (inst + PM_APBCMASK_SERCOM0_Pos));
@ -116,9 +116,17 @@ void usart_open() {
clkctrl.bit.WRTLOCK = false;
clkctrl.bit.GEN = GCLK_CLKCTRL_GEN_GCLK0_Val;
GCLK->CLKCTRL.reg = (clkctrl.reg | temp);
#endif
#ifdef SAMD51
GCLK->PCHCTRL[BOOT_GCLK_ID_CORE].reg = GCLK_PCHCTRL_GEN_GCLK0_Val | (1 << GCLK_PCHCTRL_CHEN_Pos);
GCLK->PCHCTRL[BOOT_GCLK_ID_SLOW].reg = GCLK_PCHCTRL_GEN_GCLK3_Val | (1 << GCLK_PCHCTRL_CHEN_Pos);
MCLK->BOOT_USART_MASK.reg |= BOOT_USART_BUS_CLOCK_INDEX ;
#endif
/* Baud rate 115200 - clock 8MHz -> BAUD value-50436 */
uart_basic_init(BOOT_USART_MODULE, 50436, BOOT_USART_MUX_SETTINGS);
uart_basic_init(BOOT_USART_MODULE, 50436, BOOT_USART_PAD_SETTINGS);
// Initialize flag
b_sharp_received = false;

View file

@ -5,7 +5,14 @@ static uint32_t timerLow;
uint32_t timerHigh, resetHorizon;
void delay(uint32_t ms) {
// SAMD21 starts up at 1mhz by default.
#ifdef SAMD21
ms <<= 8;
#endif
// SAMD51 starts up at 48mhz by default.
#ifdef SAMD51
ms <<= 12;
#endif
for (int i = 1; i < ms; ++i) {
asm("nop");
}