Compare commits
1 commit
master
...
squashed_m
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aa9868d3f2 |
58 changed files with 1889 additions and 311 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -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
3
.gitmodules
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
[submodule "lib/uf2"]
|
||||
path = lib/uf2
|
||||
url = https://github.com/Microsoft/uf2.git
|
||||
43
.vscode/c_cpp_properties.json
vendored
43
.vscode/c_cpp_properties.json
vendored
|
|
@ -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
109
Makefile
|
|
@ -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
|
||||
|
|
|
|||
43
README.md
43
README.md
|
|
@ -6,9 +6,9 @@ the USB MSC (mass storage).
|
|||
|
||||
[](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.
|
||||
|
|
|
|||
2
boards/circuitplay_m0/board.mk
Normal file
2
boards/circuitplay_m0/board.mk
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
CHIP_FAMILY = samd21
|
||||
CHIP_VARIANT = SAMD21G18A
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
#ifndef BOARD_CONFIG_H
|
||||
#define BOARD_CONFIG_H
|
||||
|
||||
#define __SAMD21G18A__ 1
|
||||
#define CRYSTALLESS 1
|
||||
|
||||
#define VENDOR_NAME "Adafruit Industries"
|
||||
2
boards/feather_m0/board.mk
Normal file
2
boards/feather_m0/board.mk
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
CHIP_FAMILY = samd21
|
||||
CHIP_VARIANT = SAMD21G18A
|
||||
|
|
@ -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
2
boards/gemma_m0/board.mk
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
CHIP_FAMILY = samd21
|
||||
CHIP_VARIANT = SAMD21E18A
|
||||
|
|
@ -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
2
boards/generic/board.mk
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
CHIP_FAMILY = samd21
|
||||
CHIP_VARIANT = SAMD21G18A
|
||||
2
boards/grove-zero/board.mk
Normal file
2
boards/grove-zero/board.mk
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
CHIP_FAMILY = samd21
|
||||
CHIP_VARIANT = SAMD21G18A
|
||||
20
boards/grove-zero/board_config.h
Normal file
20
boards/grove-zero/board_config.h
Normal 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
|
||||
2
boards/itsybitsy_m0/board.mk
Normal file
2
boards/itsybitsy_m0/board.mk
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
CHIP_FAMILY = samd21
|
||||
CHIP_VARIANT = SAMD21G18A
|
||||
20
boards/itsybitsy_m0/board_config.h
Normal file
20
boards/itsybitsy_m0/board_config.h
Normal 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
2
boards/metro_m0/board.mk
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
CHIP_FAMILY = samd21
|
||||
CHIP_VARIANT = SAMD21G18A
|
||||
2
boards/metro_m4/board.mk
Normal file
2
boards/metro_m4/board.mk
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
CHIP_FAMILY = samd51
|
||||
CHIP_VARIANT = SAMD51J19A
|
||||
31
boards/metro_m4/board_config.h
Normal file
31
boards/metro_m4/board_config.h
Normal 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
2
boards/mkr1000/board.mk
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
CHIP_FAMILY = samd21
|
||||
CHIP_VARIANT = SAMD21G18A
|
||||
|
|
@ -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
2
boards/pirkey/board.mk
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
CHIP_FAMILY = samd21
|
||||
CHIP_VARIANT = SAMD21E18A
|
||||
22
boards/pirkey/board_config.h
Normal file
22
boards/pirkey/board_config.h
Normal 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
|
||||
2
boards/sparkfun-samd21-dev/board.mk
Normal file
2
boards/sparkfun-samd21-dev/board.mk
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
CHIP_FAMILY = samd21
|
||||
CHIP_VARIANT = SAMD21G18A
|
||||
|
|
@ -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"
|
||||
|
|
|
|||
2
boards/sparkfun-samd21-mini/board.mk
Normal file
2
boards/sparkfun-samd21-mini/board.mk
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
CHIP_FAMILY = samd21
|
||||
CHIP_VARIANT = SAMD21G18A
|
||||
|
|
@ -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"
|
||||
|
|
|
|||
2
boards/trinket_m0/board.mk
Normal file
2
boards/trinket_m0/board.mk
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
CHIP_FAMILY = samd21
|
||||
CHIP_VARIANT = SAMD21E18A
|
||||
|
|
@ -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
2
boards/zero/board.mk
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
CHIP_FAMILY = samd21
|
||||
CHIP_VARIANT = SAMD21G18A
|
||||
|
|
@ -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"
|
||||
|
||||
|
|
|
|||
|
|
@ -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_
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
33
inc/uf2.h
33
inc/uf2.h
|
|
@ -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[];
|
||||
|
||||
|
|
|
|||
|
|
@ -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
1
lib/uf2
Submodule
|
|
@ -0,0 +1 @@
|
|||
Subproject commit d7ab98ee50bb42bb1c2ff600324e3a155a3cc4ad
|
||||
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -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
65
scripts/gendata.py
Normal 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
165
scripts/samd21j18a.ld
Normal 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
151
scripts/samd51j19a.ld
Normal 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
163
scripts/samd51j19a_self.ld
Normal 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 = . ;
|
||||
}
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
137
src/flash_samd51.c
Normal 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
84
src/init_samd51.c
Normal 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(); }
|
||||
24
src/main.c
24
src/main.c
|
|
@ -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;
|
||||
|
|
|
|||
52
src/msc.c
52
src/msc.c
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
101
src/selfmain.c
101
src/selfmain.c
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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
548
src/startup_samd51.c
Normal 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) {
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue