Просмотр исходного кода

Introduce a Makefile for the OS_NONE device example

It currently supports the SAMD21 and SAMD51 only. More will be
added later.
Scott Shawcroft 7 лет назад
Родитель
Сommit
bf70f89240

+ 2 - 2
.gitignore

@@ -5,8 +5,6 @@ test_old
 tests/build
 *.d
 *.o
-*.mk
-*.ld
 *.launch
 *.map
 *.axf
@@ -14,7 +12,9 @@ tests/build
 *.emSession
 *.elf
 *.ind
+.env
 /tests/lpc175x_6x/build/
 /tests/lpc18xx_43xx/build/
 /demos/*/*/Board_*
 /demos/*/*/KeilBuild/
+/examples/*/*/build-*

+ 122 - 0
examples/device/cdc_msc_hid/Makefile

@@ -0,0 +1,122 @@
+include ../../../tools/top.mk
+
+# Select the board to build for.
+ifeq ($(BOARD),)
+  $(error You must provide a BOARD parameter)
+else
+  ifeq ($(wildcard $(TOP)/hw/bsp/$(BOARD)/.),)
+    $(error Invalid BOARD specified)
+  endif
+endif
+
+# If the build directory is not given, make it reflect the board name.
+BUILD ?= build-$(BOARD)
+
+CROSS_COMPILE = arm-none-eabi-
+
+include $(TOP)/hw/bsp/$(BOARD)/board.mk
+
+CC = $(CROSS_COMPILE)gcc
+CXX = $(CROSS_COMPILE)g++
+LD = $(CROSS_COMPILE)ld
+OBJCOPY = $(CROSS_COMPILE)objcopy
+MKDIR = mkdir
+SED = sed
+CP = cp
+RM = rm
+
+INC += -Isrc \
+	-I$(TOP)/hw \
+	-I$(TOP)/src
+
+CFLAGS += \
+	-fsingle-precision-constant \
+	-fno-strict-aliasing \
+	-Wdouble-promotion \
+	-Wno-endif-labels \
+	-Wstrict-prototypes \
+	-Werror-implicit-function-declaration \
+	-Wfloat-equal \
+	-Wundef \
+	-Wshadow \
+	-Wwrite-strings \
+	-Wsign-compare \
+	-Wmissing-format-attribute \
+	-Wno-deprecated-declarations \
+	-Wnested-externs \
+	-Wunreachable-code \
+	-Wcast-align \
+	-Wno-error=lto-type-mismatch \
+	-ffunction-sections \
+	-fdata-sections
+
+#Debugging/Optimization
+ifeq ($(DEBUG), 1)
+  CFLAGS += -O0 -ggdb
+else
+  CFLAGS += -flto -Os
+endif
+
+CFLAGS += $(INC) -Wall -Werror -std=gnu11 -nostdlib -DBOARD_$(shell echo $(BOARD) | tr a-z A-Z)
+
+LDFLAGS += $(CFLAGS) -nostartfiles -fshort-enums -Wl,-T,$(TOP)/$(LD_FILE) -Wl,-Map=$@.map -Wl,-cref -Wl,-gc-sections -specs=nosys.specs -specs=nano.specs
+LIBS := -lgcc -lc -lm -lnosys
+
+EXAMPLE_SOURCE += \
+	src/main.c \
+	src/msc_app.c \
+	src/msc_disk_ram.c \
+	src/tusb_descriptors.c
+
+SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE))
+
+LIB_SOURCE += \
+	hw/bsp/$(BOARD)/board_$(BOARD).c \
+	src/common/tusb_fifo.c \
+	src/device/usbd.c \
+	src/device/usbd_auto_desc.c \
+	src/device/usbd_control.c \
+	src/class/msc/msc_device.c \
+	src/class/cdc/cdc_device.c \
+	src/class/hid/hid_device.c \
+	src/tusb.c \
+	src/portable/$(VENDOR)/$(CHIP_FAMILY)/dcd_$(CHIP_FAMILY).c \
+	src/portable/$(VENDOR)/$(CHIP_FAMILY)/hal_$(CHIP_FAMILY).c
+
+SRC_C += $(LIB_SOURCE)
+
+OBJ = $(addprefix $(BUILD)/obj/, $(SRC_C:.c=.o))
+OBJ += $(addprefix $(BUILD)/obj/, $(SRC_S:.s=.o))
+
+all: $(BUILD)/$(BOARD)-firmware.bin
+
+OBJ_DIRS = $(sort $(dir $(OBJ)))
+$(OBJ): | $(OBJ_DIRS)
+$(OBJ_DIRS):
+	@$(MKDIR) -p $@
+
+$(BUILD)/$(BOARD)-firmware.elf: $(OBJ)
+	@echo LINK $@
+	@$(CC) -o $@ $(LDFLAGS) $^ -Wl,--start-group $(LIBS) -Wl,--end-group
+
+$(BUILD)/$(BOARD)-firmware.bin: $(BUILD)/$(BOARD)-firmware.elf
+	@echo CREATE $@
+	$(OBJCOPY) -O binary -j .vectors -j .text -j .data $^ $@
+
+# We set vpath to point to the top of the tree so that the source files
+# can be located. By following this scheme, it allows a single build rule
+# to be used to compile all .c files.
+vpath %.c . $(TOP)
+$(BUILD)/obj/%.o: %.c
+	@echo CC $@
+	@$(CC) $(CFLAGS) -c -MD -o $@ $<
+	@# The following fixes the dependency file.
+	@# See http://make.paulandlesley.org/autodep.html for details.
+	@# Regex adjusted from the above to play better with Windows paths, etc.
+	@$(CP) $(@:.o=.d) $(@:.o=.P); \
+	  $(SED) -e 's/#.*//' -e 's/^.*:  *//' -e 's/ *\\$$//' \
+	      -e '/^$$/ d' -e 's/$$/ :/' < $(@:.o=.d) >> $(@:.o=.P); \
+	  $(RM) $(@:.o=.d)
+
+clean:
+	rm -rf build-$(BOARD)

+ 3 - 2
examples/device/cdc_msc_hid/src/main.c

@@ -49,6 +49,9 @@
 void print_greeting(void);
 void led_blinking_task(void);
 
+extern void virtual_com_task(void);
+extern void usb_hid_task(void);
+
 /*------------- MAIN -------------*/
 int main(void)
 {
@@ -64,12 +67,10 @@ int main(void)
     led_blinking_task();
 
 #if CFG_TUD_CDC
-    extern void virtual_com_task(void);
     virtual_com_task();
 #endif
 
 #if CFG_TUD_HID
-    extern void usb_hid_task(void);
     usb_hid_task();
 #endif
   }

+ 2 - 0
examples/device/cdc_msc_hid/src/tusb_config.h

@@ -39,6 +39,7 @@
 #ifndef _TUSB_CONFIG_H_
 #define _TUSB_CONFIG_H_
 
+#include "tusb_option.h"
 #include "bsp/board.h"
 
 #ifdef __cplusplus
@@ -96,6 +97,7 @@
 //------------- CLASS -------------//
 #define CFG_TUD_CDC                 1
 #define CFG_TUD_MSC                 1
+#define CFG_TUD_CUSTOM_CLASS        0
 
 #define CFG_TUD_HID                 0
 #define CFG_TUD_HID_KEYBOARD        0

+ 35 - 0
hw/bsp/metro_m0_express/board.mk

@@ -0,0 +1,35 @@
+CFLAGS = \
+	-DCFG_TUSB_MCU=OPT_MCU_SAMD21 \
+	-DCONF_DFLL_OVERWRITE_CALIBRATION=0 \
+	-D__SAMD21G18A__ \
+	-mthumb \
+	-mabi=aapcs-linux \
+	-mcpu=cortex-m0plus \
+	-msoft-float \
+	-mfloat-abi=soft
+
+# All source paths should be relative to the top level.
+LD_FILE = hw/bsp/metro_m0_express/samd21g18a_flash.ld
+
+LD_FLAGS += -mthumb -mcpu=cortex-m0plus
+
+SRC_C += \
+	hw/mcu/microchip/samd/asf4/samd21/gcc/gcc/startup_samd21.c \
+	hw/mcu/microchip/samd/asf4/samd21/gcc/system_samd21.c \
+	hw/mcu/microchip/samd/asf4/samd21/hpl/gclk/hpl_gclk.c \
+	hw/mcu/microchip/samd/asf4/samd21/hpl/pm/hpl_pm.c \
+	hw/mcu/microchip/samd/asf4/samd21/hpl/sysctrl/hpl_sysctrl.c
+
+INC += \
+	-I$(TOP)/hw/mcu/microchip/samd/asf4/samd21/ \
+	-I$(TOP)/hw/mcu/microchip/samd/asf4/samd21/config \
+	-I$(TOP)/hw/mcu/microchip/samd/asf4/samd21/include \
+	-I$(TOP)/hw/mcu/microchip/samd/asf4/samd21/hal/include \
+	-I$(TOP)/hw/mcu/microchip/samd/asf4/samd21/hal/utils/include \
+	-I$(TOP)/hw/mcu/microchip/samd/asf4/samd51/hpl/pm/ \
+	-I$(TOP)/hw/mcu/microchip/samd/asf4/samd21/hpl/port \
+	-I$(TOP)/hw/mcu/microchip/samd/asf4/samd21/hri \
+	-I$(TOP)/hw/mcu/microchip/samd/asf4/samd21/CMSIS/Include
+
+VENDOR = microchip
+CHIP_FAMILY = samd21

+ 12 - 1
hw/bsp/metro_m0_express/board_metro_m0_express.c

@@ -47,6 +47,8 @@
 #include "hpl_pm_config.h"
 #include "hpl/pm/hpl_pm_base.h"
 
+#include "tusb_option.h"
+
 //--------------------------------------------------------------------+
 // MACRO TYPEDEF CONSTANT ENUM DECLARATION
 //--------------------------------------------------------------------+
@@ -77,7 +79,7 @@ void board_init(void)
 
 #if CFG_TUSB_OS  == OPT_OS_NONE
   // Tick init, samd SystemCoreClock may not correct
-  SysTick_Config(SystemCoreClock/1000);
+  SysTick_Config(CONF_CPU_FREQUENCY/1000);
 #endif
 
   /* USB Clock init
@@ -97,6 +99,15 @@ void board_init(void)
 
   gpio_set_pin_function(PIN_PA24, PINMUX_PA24G_USB_DM);
   gpio_set_pin_function(PIN_PA25, PINMUX_PA25G_USB_DP);
+
+  // Output 500hz PWM on D12 (PA19 - TCC0 WO[3]) so we can validate the GCLK0 clock speed with a Saleae.
+  _pm_enable_bus_clock(PM_BUS_APBC, TCC0);
+  TCC0->PER.bit.PER = 48000000 / 1000;
+  TCC0->CC[3].bit.CC = 48000000 / 2000;
+  TCC0->CTRLA.bit.ENABLE = true;
+
+  gpio_set_pin_function(PIN_PA19, PINMUX_PA19F_TCC0_WO3);
+  _gclk_enable_channel(TCC0_GCLK_ID, GCLK_CLKCTRL_GEN_GCLK0_Val);
 }
 
 void board_led_control(uint32_t led_id, bool state)

+ 144 - 0
hw/bsp/metro_m0_express/samd21g18a_flash.ld

@@ -0,0 +1,144 @@
+/**
+ * \file
+ *
+ * \brief Linker script for running in internal FLASH on the SAMD21G18A
+ *
+ * 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 + 8K, LENGTH = 0x00040000 - 8K
+  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 = .;
+        end = .;
+    } > ram
+
+    /* stack section */
+    .stack (NOLOAD):
+    {
+        . = ALIGN(8);
+        _sstack = .;
+        . = . + STACK_SIZE;
+        . = ALIGN(8);
+        _estack = .;
+    } > ram
+
+    . = ALIGN(4);
+    _end = . ;
+}

+ 34 - 0
hw/bsp/metro_m4_express/board.mk

@@ -0,0 +1,34 @@
+CFLAGS = \
+	-DCFG_TUSB_MCU=OPT_MCU_SAMD51 \
+	-D__SAMD51J19A__ \
+	-mthumb \
+	-mabi=aapcs-linux \
+	-mcpu=cortex-m4 \
+	-mfloat-abi=hard \
+	-mfpu=fpv4-sp-d16
+
+# All source paths should be relative to the top level.
+LD_FILE = hw/bsp/metro_m4_express/samd51g19a_flash.ld
+
+LDFLAGS += -mthumb -mcpu=cortex-m4
+
+SRC_C += \
+	hw/mcu/microchip/samd/asf4/samd51/gcc/gcc/startup_samd51.c \
+	hw/mcu/microchip/samd/asf4/samd51/gcc/system_samd51.c \
+	hw/mcu/microchip/samd/asf4/samd51/hpl/gclk/hpl_gclk.c \
+	hw/mcu/microchip/samd/asf4/samd51/hpl/mclk/hpl_mclk.c \
+	hw/mcu/microchip/samd/asf4/samd51/hpl/osc32kctrl/hpl_osc32kctrl.c \
+	hw/mcu/microchip/samd/asf4/samd51/hpl/oscctrl/hpl_oscctrl.c
+
+INC += \
+	-I$(TOP)/hw/mcu/microchip/samd/asf4/samd51/ \
+	-I$(TOP)/hw/mcu/microchip/samd/asf4/samd51/config \
+	-I$(TOP)/hw/mcu/microchip/samd/asf4/samd51/include \
+	-I$(TOP)/hw/mcu/microchip/samd/asf4/samd51/hal/include \
+	-I$(TOP)/hw/mcu/microchip/samd/asf4/samd51/hal/utils/include \
+	-I$(TOP)/hw/mcu/microchip/samd/asf4/samd51/hpl/port \
+	-I$(TOP)/hw/mcu/microchip/samd/asf4/samd51/hri \
+	-I$(TOP)/hw/mcu/microchip/samd/asf4/samd51/CMSIS/Include
+
+VENDOR = microchip
+CHIP_FAMILY = samd51

+ 2 - 0
hw/bsp/metro_m4_express/board_metro_m4_express.c

@@ -44,6 +44,8 @@
 #include "hpl/gclk/hpl_gclk_base.h"
 #include "hpl_mclk_config.h"
 
+#include "tusb_option.h"
+
 //--------------------------------------------------------------------+
 // MACRO TYPEDEF CONSTANT ENUM DECLARATION
 //--------------------------------------------------------------------+

+ 164 - 0
hw/bsp/metro_m4_express/samd51g19a_flash.ld

@@ -0,0 +1,164 @@
+/**
+ * \file
+ *
+ * \brief Linker script for running in internal FLASH on the SAMD51G19A
+ *
+ * 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 + 16K, LENGTH = 0x00080000 - 16K
+  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 = .;
+        end = .;
+    } > ram
+
+    /* stack section */
+    .stack (NOLOAD):
+    {
+        . = ALIGN(8);
+        _sstack = .;
+        . = . + STACK_SIZE;
+        . = ALIGN(8);
+        _estack = .;
+    } > ram
+
+    . = ALIGN(4);
+    _end = . ;
+}

+ 1 - 1
hw/mcu/microchip/samd/asf4

@@ -1 +1 @@
-Subproject commit d270f79aa16dd8fd4ae3b6c14544283dcb992e9c
+Subproject commit 82fe3aa05bc3b9f4956ee775c748a3885443f66b

+ 0 - 7
src/portable/microchip/samd21/dcd_samd21.c

@@ -71,13 +71,6 @@ static void bus_reset(void) {
  *------------------------------------------------------------------*/
 bool dcd_init (uint8_t rhport)
 {
-  // Reset to get in a clean state.
-  USB->DEVICE.CTRLA.bit.SWRST = true;
-  while (USB->DEVICE.SYNCBUSY.bit.SWRST == 0) {
-
-  }
-  while (USB->DEVICE.SYNCBUSY.bit.SWRST == 1) {}
-
   (void) rhport;
   USB->DEVICE.DESCADD.reg = (uint32_t) &sram_registers;
   USB->DEVICE.CTRLB.reg = USB_DEVICE_CTRLB_SPDCONF_FS;

+ 5 - 0
src/portable/microchip/samd21/hal_samd21.c

@@ -50,6 +50,11 @@
  *------------------------------------------------------------------*/
 bool tusb_hal_init(void)
 {
+  // Reset to get in a clean state.
+  USB->DEVICE.CTRLA.bit.SWRST = true;
+  while (USB->DEVICE.SYNCBUSY.bit.SWRST == 0) {}
+  while (USB->DEVICE.SYNCBUSY.bit.SWRST == 1) {}
+
   USB->DEVICE.PADCAL.bit.TRANSP = (*((uint32_t*) USB_FUSES_TRANSP_ADDR) & USB_FUSES_TRANSP_Msk) >> USB_FUSES_TRANSP_Pos;
   USB->DEVICE.PADCAL.bit.TRANSN = (*((uint32_t*) USB_FUSES_TRANSN_ADDR) & USB_FUSES_TRANSN_Msk) >> USB_FUSES_TRANSN_Pos;
   USB->DEVICE.PADCAL.bit.TRIM = (*((uint32_t*) USB_FUSES_TRIM_ADDR) & USB_FUSES_TRIM_Msk) >> USB_FUSES_TRIM_Pos;

+ 0 - 6
src/portable/microchip/samd51/dcd_samd51.c

@@ -72,12 +72,6 @@ static void bus_reset(void) {
 bool dcd_init (uint8_t rhport)
 {
   (void) rhport;
-  // Reset to get in a clean state.
-  USB->DEVICE.CTRLA.bit.SWRST = true;
-  while (USB->DEVICE.SYNCBUSY.bit.SWRST == 0) {
-
-  }
-  while (USB->DEVICE.SYNCBUSY.bit.SWRST == 1) {}
 
   USB->DEVICE.DESCADD.reg = (uint32_t) &sram_registers;
   USB->DEVICE.CTRLB.reg = USB_DEVICE_CTRLB_SPDCONF_FS;

+ 5 - 0
src/portable/microchip/samd51/hal_samd51.c

@@ -49,6 +49,11 @@
  *------------------------------------------------------------------*/
 bool tusb_hal_init(void)
 {
+  // Reset to get in a clean state.
+  USB->DEVICE.CTRLA.bit.SWRST = true;
+  while (USB->DEVICE.SYNCBUSY.bit.SWRST == 0) {}
+  while (USB->DEVICE.SYNCBUSY.bit.SWRST == 1) {}
+
   USB->DEVICE.PADCAL.bit.TRANSP = (*((uint32_t*) USB_FUSES_TRANSP_ADDR) & USB_FUSES_TRANSP_Msk) >> USB_FUSES_TRANSP_Pos;
   USB->DEVICE.PADCAL.bit.TRANSN = (*((uint32_t*) USB_FUSES_TRANSN_ADDR) & USB_FUSES_TRANSN_Msk) >> USB_FUSES_TRANSN_Pos;
   USB->DEVICE.PADCAL.bit.TRIM = (*((uint32_t*) USB_FUSES_TRIM_ADDR) & USB_FUSES_TRIM_Msk) >> USB_FUSES_TRIM_Pos;

+ 17 - 0
tools/top.mk

@@ -0,0 +1,17 @@
+ifneq ($(lastword a b),b)
+$(error This Makefile require make 3.81 or newer)
+endif
+
+# Set TOP to be the path to get from the current directory (where make was
+# invoked) to the top of the tree. $(lastword $(MAKEFILE_LIST)) returns
+# the name of this makefile relative to where make was invoked.
+
+THIS_MAKEFILE := $(lastword $(MAKEFILE_LIST))
+TOP := $(patsubst %/tools/top.mk,%,$(THIS_MAKEFILE))
+
+TOP := $(shell realpath $(TOP))
+
+$(info Top directory is $(TOP))
+
+CURRENT_PATH := $(shell realpath --relative-to=$(TOP) `pwd`)
+$(info Path from top is $(CURRENT_PATH))