Bladeren bron

Merge remote-tracking branch 'upstream/master' into CCRX_Port

Wini-Buh 4 jaren geleden
bovenliggende
commit
c5f6b57755
43 gewijzigde bestanden met toevoegingen van 593 en 132 verwijderingen
  1. 1 0
      .github/workflows/build.yml
  2. 1 1
      examples/device/CMakeLists.txt
  3. 1 1
      examples/device/audio_4_channel_mic/CMakeLists.txt
  4. 1 1
      examples/device/audio_test/CMakeLists.txt
  5. 1 2
      examples/device/board_test/CMakeLists.txt
  6. 1 1
      examples/device/cdc_dual_ports/CMakeLists.txt
  7. 1 1
      examples/device/cdc_msc/CMakeLists.txt
  8. 11 9
      examples/device/cdc_msc_freertos/CMakeLists.txt
  9. 1 1
      examples/device/dfu/CMakeLists.txt
  10. 1 1
      examples/device/dfu_runtime/CMakeLists.txt
  11. 1 1
      examples/device/dynamic_configuration/CMakeLists.txt
  12. 1 1
      examples/device/hid_composite/CMakeLists.txt
  13. 1 1
      examples/device/hid_generic_inout/CMakeLists.txt
  14. 1 1
      examples/device/hid_multiple_interface/CMakeLists.txt
  15. 1 1
      examples/device/midi_test/CMakeLists.txt
  16. 1 1
      examples/device/msc_dual_lun/CMakeLists.txt
  17. 1 1
      examples/device/net_lwip_webserver/CMakeLists.txt
  18. 1 1
      examples/device/uac2_headset/CMakeLists.txt
  19. 1 1
      examples/device/usbtmc/CMakeLists.txt
  20. 1 1
      examples/device/webusb_serial/CMakeLists.txt
  21. 1 1
      examples/host/CMakeLists.txt
  22. 1 1
      examples/host/cdc_msc_hid/CMakeLists.txt
  23. 1 1
      examples/host/cdc_msc_hid/src/tusb_config.h
  24. 1 1
      hw/bsp/board_mcu.h
  25. 0 3
      hw/bsp/esp32s2/family.cmake
  26. 0 3
      hw/bsp/esp32s3/family.cmake
  27. 0 57
      hw/bsp/family_common.cmake
  28. 71 0
      hw/bsp/family_support.cmake
  29. 2 2
      hw/bsp/rp2040/family.cmake
  30. 50 0
      hw/bsp/saml21/boards/atsaml21_xpro/board.h
  31. 10 0
      hw/bsp/saml21/boards/atsaml21_xpro/board.mk
  32. 153 0
      hw/bsp/saml21/boards/atsaml21_xpro/saml21j18b_flash.ld
  33. 163 0
      hw/bsp/saml21/family.c
  34. 50 0
      hw/bsp/saml21/family.mk
  35. 1 1
      hw/mcu/microchip
  36. 1 1
      src/class/hid/hid_host.c
  37. 8 7
      src/class/midi/midi_device.c
  38. 1 1
      src/common/tusb_fifo.h
  39. 2 2
      src/host/usbh.c
  40. 1 1
      src/host/usbh_control.c
  41. 2 2
      src/portable/microchip/samd/dcd_samd.c
  42. 41 18
      src/portable/nordic/nrf5x/dcd_nrf5x.c
  43. 3 2
      src/tusb_option.h

+ 1 - 0
.github/workflows/build.yml

@@ -49,6 +49,7 @@ jobs:
         - 'samd11'
         - 'samd21'
         - 'samd51'
+        - 'saml21'
         - 'saml22'
         - 'stm32f0'
         - 'stm32f4'

+ 1 - 1
examples/device/CMakeLists.txt

@@ -1,6 +1,6 @@
 cmake_minimum_required(VERSION 3.5)
 
-include(${CMAKE_CURRENT_SOURCE_DIR}/../../hw/bsp/${FAMILY}/family.cmake)
+include(${CMAKE_CURRENT_SOURCE_DIR}/../../hw/bsp/family_support.cmake)
 
 project(tinyusb_device_examples)
 family_initialize_project(tinyusb_device_examples ${CMAKE_CURRENT_LIST_DIR})

+ 1 - 1
examples/device/audio_4_channel_mic/CMakeLists.txt

@@ -1,6 +1,6 @@
 cmake_minimum_required(VERSION 3.5)
 
-include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/${FAMILY}/family.cmake)
+include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
 
 # gets PROJECT name for the example (e.g. <BOARD>-<DIR_NAME>)
 family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})

+ 1 - 1
examples/device/audio_test/CMakeLists.txt

@@ -1,6 +1,6 @@
 cmake_minimum_required(VERSION 3.5)
 
-include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/${FAMILY}/family.cmake)
+include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
 
 # gets PROJECT name for the example (e.g. <BOARD>-<DIR_NAME>)
 family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})

+ 1 - 2
examples/device/board_test/CMakeLists.txt

@@ -1,6 +1,6 @@
 cmake_minimum_required(VERSION 3.5)
 
-include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/${FAMILY}/family.cmake)
+include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
 
 # Check for -DFAMILY=
 if(FAMILY MATCHES "^esp32s[2-3]")
@@ -12,7 +12,6 @@ if(FAMILY MATCHES "^esp32s[2-3]")
   set(TOP "../../..")
   get_filename_component(TOP "${TOP}" REALPATH)
 
-  include(${TOP}/hw/bsp/${FAMILY}/family.cmake)
   project(${PROJECT})
 
 else()

+ 1 - 1
examples/device/cdc_dual_ports/CMakeLists.txt

@@ -1,6 +1,6 @@
 cmake_minimum_required(VERSION 3.5)
 
-include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/${FAMILY}/family.cmake)
+include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
 
 # gets PROJECT name for the example (e.g. <BOARD>-<DIR_NAME>)
 family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})

+ 1 - 1
examples/device/cdc_msc/CMakeLists.txt

@@ -1,6 +1,6 @@
 cmake_minimum_required(VERSION 3.5)
 
-include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/${FAMILY}/family.cmake)
+include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
 
 # gets PROJECT name for the example (e.g. <BOARD>-<DIR_NAME>)
 family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})

+ 11 - 9
examples/device/cdc_msc_freertos/CMakeLists.txt

@@ -1,20 +1,22 @@
 cmake_minimum_required(VERSION 3.5)
 
-# use BOARD-Directory name for project id
-get_filename_component(PROJECT ${CMAKE_CURRENT_SOURCE_DIR} NAME)
-set(PROJECT ${BOARD}-${PROJECT})
-
 # TOP is absolute path to root directory of TinyUSB git repo
+# needed for esp32sx build. TOOD could be removed later on
 set(TOP "../../..")
 get_filename_component(TOP "${TOP}" REALPATH)
 
-# Check for -DFAMILY=
-if(FAMILY MATCHES "^esp32s[2-3]")
-  cmake_minimum_required(VERSION 3.5)
+include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
+
+# gets PROJECT name for the example (e.g. <BOARD>-<DIR_NAME>)
+family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})
 
-  include(${TOP}/hw/bsp/${FAMILY}/family.cmake)
-  project(${PROJECT})
+project(${PROJECT})
 
+# Checks this example is valid for the family and initializes the project
+family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR})
+
+# Check for -DFAMILY=
+if(FAMILY MATCHES "^esp32s[2-3]")
 else()
   message(FATAL_ERROR "Invalid FAMILY specified: ${FAMILY}")
 endif()

+ 1 - 1
examples/device/dfu/CMakeLists.txt

@@ -1,6 +1,6 @@
 cmake_minimum_required(VERSION 3.5)
 
-include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/${FAMILY}/family.cmake)
+include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
 
 # gets PROJECT name for the example (e.g. <BOARD>-<DIR_NAME>)
 family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})

+ 1 - 1
examples/device/dfu_runtime/CMakeLists.txt

@@ -1,6 +1,6 @@
 cmake_minimum_required(VERSION 3.5)
 
-include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/${FAMILY}/family.cmake)
+include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
 
 # gets PROJECT name for the example (e.g. <BOARD>-<DIR_NAME>)
 family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})

+ 1 - 1
examples/device/dynamic_configuration/CMakeLists.txt

@@ -1,6 +1,6 @@
 cmake_minimum_required(VERSION 3.5)
 
-include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/${FAMILY}/family.cmake)
+include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
 
 # gets PROJECT name for the example (e.g. <BOARD>-<DIR_NAME>)
 family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})

+ 1 - 1
examples/device/hid_composite/CMakeLists.txt

@@ -1,6 +1,6 @@
 cmake_minimum_required(VERSION 3.5)
 
-include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/${FAMILY}/family.cmake)
+include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
 
 # gets PROJECT name for the example (e.g. <BOARD>-<DIR_NAME>)
 family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})

+ 1 - 1
examples/device/hid_generic_inout/CMakeLists.txt

@@ -1,6 +1,6 @@
 cmake_minimum_required(VERSION 3.5)
 
-include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/${FAMILY}/family.cmake)
+include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
 
 # gets PROJECT name for the example (e.g. <BOARD>-<DIR_NAME>)
 family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})

+ 1 - 1
examples/device/hid_multiple_interface/CMakeLists.txt

@@ -1,6 +1,6 @@
 cmake_minimum_required(VERSION 3.5)
 
-include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/${FAMILY}/family.cmake)
+include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
 
 # gets PROJECT name for the example (e.g. <BOARD>-<DIR_NAME>)
 family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})

+ 1 - 1
examples/device/midi_test/CMakeLists.txt

@@ -1,6 +1,6 @@
 cmake_minimum_required(VERSION 3.5)
 
-include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/${FAMILY}/family.cmake)
+include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
 
 # gets PROJECT name for the example (e.g. <BOARD>-<DIR_NAME>)
 family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})

+ 1 - 1
examples/device/msc_dual_lun/CMakeLists.txt

@@ -1,6 +1,6 @@
 cmake_minimum_required(VERSION 3.5)
 
-include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/${FAMILY}/family.cmake)
+include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
 
 # gets PROJECT name for the example (e.g. <BOARD>-<DIR_NAME>)
 family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})

+ 1 - 1
examples/device/net_lwip_webserver/CMakeLists.txt

@@ -4,7 +4,7 @@ set(TOP "../../..")
 get_filename_component(TOP "${TOP}" REALPATH)
 
 if (EXISTS ${TOP}/lib/lwip/src)
-    include(${TOP}/hw/bsp/${FAMILY}/family.cmake)
+    include(${TOP}/hw/bsp/family_support.cmake)
 
     # gets PROJECT name for the example (e.g. <BOARD>-<DIR_NAME>)
     family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})

+ 1 - 1
examples/device/uac2_headset/CMakeLists.txt

@@ -1,6 +1,6 @@
 cmake_minimum_required(VERSION 3.5)
 
-include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/${FAMILY}/family.cmake)
+include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
 
 # gets PROJECT name for the example (e.g. <BOARD>-<DIR_NAME>)
 family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})

+ 1 - 1
examples/device/usbtmc/CMakeLists.txt

@@ -1,6 +1,6 @@
 cmake_minimum_required(VERSION 3.5)
 
-include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/${FAMILY}/family.cmake)
+include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
 
 # gets PROJECT name for the example (e.g. <BOARD>-<DIR_NAME>)
 family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})

+ 1 - 1
examples/device/webusb_serial/CMakeLists.txt

@@ -1,6 +1,6 @@
 cmake_minimum_required(VERSION 3.5)
 
-include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/${FAMILY}/family.cmake)
+include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
 
 # gets PROJECT name for the example (e.g. <BOARD>-<DIR_NAME>)
 family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})

+ 1 - 1
examples/host/CMakeLists.txt

@@ -1,6 +1,6 @@
 cmake_minimum_required(VERSION 3.5)
 
-include(${CMAKE_CURRENT_SOURCE_DIR}/../../hw/bsp/${FAMILY}/family.cmake)
+include(${CMAKE_CURRENT_SOURCE_DIR}/../../hw/bsp/family_support.cmake)
 
 project(tinyusb_host_examples)
 family_initialize_project(tinyusb_host_examples ${CMAKE_CURRENT_LIST_DIR})

+ 1 - 1
examples/host/cdc_msc_hid/CMakeLists.txt

@@ -1,6 +1,6 @@
 cmake_minimum_required(VERSION 3.5)
 
-include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/${FAMILY}/family.cmake)
+include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
 
 # gets PROJECT name for the example (e.g. <BOARD>-<DIR_NAME>)
 family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})

+ 1 - 1
examples/host/cdc_msc_hid/src/tusb_config.h

@@ -72,7 +72,7 @@
 //--------------------------------------------------------------------
 
 // Size of buffer to hold descriptors and other data used for enumeration
-#define CFG_TUH_ENUMERATION_BUFSZIE 256
+#define CFG_TUH_ENUMERATION_BUFSIZE 256
 
 #define CFG_TUH_HUB                 1
 #define CFG_TUH_CDC                 1

+ 1 - 1
hw/bsp/board_mcu.h

@@ -54,7 +54,7 @@
 
 #elif CFG_TUSB_MCU == OPT_MCU_SAMD11 || CFG_TUSB_MCU == OPT_MCU_SAMD21 || \
       CFG_TUSB_MCU == OPT_MCU_SAMD51 || CFG_TUSB_MCU == OPT_MCU_SAME5X || \
-      CFG_TUSB_MCU == OPT_MCU_SAML22
+      CFG_TUSB_MCU == OPT_MCU_SAML22 || CFG_TUSB_MCU == OPT_MCU_SAML21
   #include "sam.h"
 
 #elif CFG_TUSB_MCU == OPT_MCU_SAMG

+ 0 - 3
hw/bsp/esp32s2/family.cmake

@@ -4,7 +4,4 @@ cmake_minimum_required(VERSION 3.5)
 set(EXTRA_COMPONENT_DIRS "src" "${TOP}/hw/bsp/esp32s2/boards" "${TOP}/hw/bsp/esp32s2/components")  
 include($ENV{IDF_PATH}/tools/cmake/project.cmake)
 set(SUPPORTED_TARGETS esp32s2)
-
-# include basic family CMake functionality
 set(FAMILY_MCUS ESP32S2)
-include(${CMAKE_CURRENT_LIST_DIR}/../family_common.cmake)

+ 0 - 3
hw/bsp/esp32s3/family.cmake

@@ -4,7 +4,4 @@ cmake_minimum_required(VERSION 3.5)
 set(EXTRA_COMPONENT_DIRS "src" "${TOP}/hw/bsp/esp32s3/boards" "${TOP}/hw/bsp/esp32s3/components")  
 include($ENV{IDF_PATH}/tools/cmake/project.cmake)
 set(SUPPORTED_TARGETS esp32s3)
-
-# include basic family CMake functionality
 set(FAMILY_MCUS ESP32S3)
-include(${CMAKE_CURRENT_LIST_DIR}/../family_common.cmake)

+ 0 - 57
hw/bsp/family_common.cmake

@@ -1,57 +0,0 @@
-if (NOT FAMILY_MCUS)
-    set(FAMILY_MCUS ${FAMILY})
-endif()
-
-# save it in case of re-inclusion
-set(FAMILY_MCUS ${FAMILY_MCUS} CACHE INTERNAL "")
-
-function(family_filter RESULT DIR)
-    get_filename_component(DIR ${DIR} ABSOLUTE BASE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
-    file(GLOB ONLYS "${DIR}/.only.MCU_*")
-    if (ONLYS)
-        foreach(MCU IN LISTS FAMILY_MCUS)
-            if (EXISTS ${DIR}/.only.MCU_${MCU})
-                set(${RESULT} 1 PARENT_SCOPE)
-                return()
-            endif()
-        endforeach()
-    else()
-        foreach(MCU IN LISTS FAMILY_MCUS)
-            if (EXISTS ${DIR}/.skip.MCU_${MCU})
-                set(${RESULT} 0 PARENT_SCOPE)
-                return()
-            endif()
-        endforeach()
-    endif()
-    set(${RESULT} 1 PARENT_SCOPE)
-endfunction()
-
-function(family_add_subdirectory DIR)
-    family_filter(SHOULD_ADD "${DIR}")
-    if (SHOULD_ADD)
-        add_subdirectory(${DIR})
-    endif()
-endfunction()
-
-function(family_get_project_name OUTPUT_NAME DIR)
-    get_filename_component(SHORT_NAME ${DIR} NAME)
-    set(${OUTPUT_NAME} ${TINYUSB_FAMILY_PROJECT_NAME_PREFIX}${SHORT_NAME} PARENT_SCOPE)
-endfunction()
-
-function(family_initialize_project PROJECT DIR)
-    family_filter(ALLOWED "${DIR}")
-    if (NOT ALLOWED)
-        get_filename_component(SHORT_NAME ${DIR} NAME)
-        message(FATAL_ERROR "${SHORT_NAME} is not supported on FAMILY=${FAMILY}")
-    endif()
-endfunction()
-
-# configure an executable target to link to tinyusb in device mode, and add the board implementation
-function(family_configure_device_example TARGET)
-    # default implentation is empty, the function should be redefined in the FAMILY/family.cmake
-endfunction()
-
-# configure an executable target to link to tinyusb in host mode, and add the board implementation
-function(family_configure_host_example TARGET)
-    # default implentation is empty, the function should be redefined in the FAMILY/family.cmake
-endfunction()

+ 71 - 0
hw/bsp/family_support.cmake

@@ -0,0 +1,71 @@
+if (NOT TARGET _family_support_marker)
+    add_library(_family_support_marker INTERFACE)
+
+    if (NOT FAMILY)
+        message(FATAL_ERROR "You must set a FAMILY variable for the build (e.g. rp2040, eps32s2, esp32s3). You can do this via -DFAMILY=xxx on the camke command line")
+    endif()
+
+    if (NOT EXISTS ${CMAKE_CURRENT_LIST_DIR}/${FAMILY}/family.cmake)
+        message(FATAL_ERROR "Family '${FAMILY}' is not known/supported")
+    endif()
+
+    function(family_filter RESULT DIR)
+        get_filename_component(DIR ${DIR} ABSOLUTE BASE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
+        file(GLOB ONLYS "${DIR}/.only.MCU_*")
+        if (ONLYS)
+            foreach(MCU IN LISTS FAMILY_MCUS)
+                if (EXISTS ${DIR}/.only.MCU_${MCU})
+                    set(${RESULT} 1 PARENT_SCOPE)
+                    return()
+                endif()
+            endforeach()
+        else()
+            foreach(MCU IN LISTS FAMILY_MCUS)
+                if (EXISTS ${DIR}/.skip.MCU_${MCU})
+                    set(${RESULT} 0 PARENT_SCOPE)
+                    return()
+                endif()
+            endforeach()
+        endif()
+        set(${RESULT} 1 PARENT_SCOPE)
+    endfunction()
+
+    function(family_add_subdirectory DIR)
+        family_filter(SHOULD_ADD "${DIR}")
+        if (SHOULD_ADD)
+            add_subdirectory(${DIR})
+        endif()
+    endfunction()
+
+    function(family_get_project_name OUTPUT_NAME DIR)
+        get_filename_component(SHORT_NAME ${DIR} NAME)
+        set(${OUTPUT_NAME} ${TINYUSB_FAMILY_PROJECT_NAME_PREFIX}${SHORT_NAME} PARENT_SCOPE)
+    endfunction()
+
+    function(family_initialize_project PROJECT DIR)
+        family_filter(ALLOWED "${DIR}")
+        if (NOT ALLOWED)
+            get_filename_component(SHORT_NAME ${DIR} NAME)
+            message(FATAL_ERROR "${SHORT_NAME} is not supported on FAMILY=${FAMILY}")
+        endif()
+    endfunction()
+
+    # configure an executable target to link to tinyusb in device mode, and add the board implementation
+    function(family_configure_device_example TARGET)
+        # default implentation is empty, the function should be redefined in the FAMILY/family.cmake
+    endfunction()
+
+    # configure an executable target to link to tinyusb in host mode, and add the board implementation
+    function(family_configure_host_example TARGET)
+        # default implentation is empty, the function should be redefined in the FAMILY/family.cmake
+    endfunction()
+
+    include(${CMAKE_CURRENT_LIST_DIR}/${FAMILY}/family.cmake)
+
+    if (NOT FAMILY_MCUS)
+        set(FAMILY_MCUS ${FAMILY})
+    endif()
+
+    # save it in case of re-inclusion
+    set(FAMILY_MCUS ${FAMILY_MCUS} CACHE INTERNAL "")
+endif()

+ 2 - 2
hw/bsp/rp2040/family.cmake

@@ -3,7 +3,8 @@ if (NOT TARGET _rp2040_family_inclusion_marker)
 	add_library(_rp2040_family_inclusion_marker INTERFACE)
 
 	if (NOT BOARD)
-		message(FATAL_ERROR "BOARD must be specified")
+		message("BOARD not specified, defaulting to pico_sdk")
+		set(BOARD pico_sdk)
 	endif()
 
 	# add the SDK in case we are standalone tinyusb example (noop if already present)
@@ -11,7 +12,6 @@ if (NOT TARGET _rp2040_family_inclusion_marker)
 
 	# include basic family CMake functionality
 	set(FAMILY_MCUS RP2040)
-	include(${CMAKE_CURRENT_LIST_DIR}/../family_common.cmake)
 
 	include(${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}/board.cmake)
 

+ 50 - 0
hw/bsp/saml21/boards/atsaml21_xpro/board.h

@@ -0,0 +1,50 @@
+/* 
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020, Ha Thach (tinyusb.org)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * This file is part of the TinyUSB stack.
+ */
+
+#ifndef BOARD_H_
+#define BOARD_H_
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+// LED
+#define LED_PIN               (32 + 30) // PB30
+#define LED_STATE_ON          0
+
+// Button
+#define BUTTON_PIN            (0  + 15) // PA15
+#define BUTTON_STATE_ACTIVE   0
+
+// UART
+#define UART_RX_PIN           4
+#define UART_TX_PIN           5
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* BOARD_H_ */

+ 10 - 0
hw/bsp/saml21/boards/atsaml21_xpro/board.mk

@@ -0,0 +1,10 @@
+CFLAGS += -D__SAML21J18B__
+
+# All source paths should be relative to the top level.
+LD_FILE = $(BOARD_PATH)/saml21j18b_flash.ld
+
+# For flash-jlink target
+JLINK_DEVICE = ATSAML21J18
+
+# flash using jlink
+flash: flash-jlink

+ 153 - 0
hw/bsp/saml21/boards/atsaml21_xpro/saml21j18b_flash.ld

@@ -0,0 +1,153 @@
+/**
+ * \file
+ *
+ * \brief Linker script for running in internal FLASH on the SAML21J18B
+ *
+ * Copyright (c) 2016 Atmel Corporation,
+ *                    a wholly owned subsidiary of Microchip Technology Inc.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * 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 = 0x00040000
+  ram      (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000
+  lpram    (rwx) : ORIGIN = 0x30000000, LENGTH = 0x00002000
+}
+
+/* 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
+
+    .lpram (NOLOAD):
+    {
+        . = ALIGN(8);
+        _slpram = .;
+        *(.lpram .lpram.*);
+        . = ALIGN(8);
+        _elpram = .;
+    } > lpram
+
+    /* .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 = . ;
+}

+ 163 - 0
hw/bsp/saml21/family.c

@@ -0,0 +1,163 @@
+/* 
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Ha Thach (tinyusb.org)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * This file is part of the TinyUSB stack.
+ */
+
+#include "sam.h"
+#include "bsp/board.h"
+#include "board.h"
+
+#include "hal/include/hal_gpio.h"
+#include "hal/include/hal_init.h"
+#include "hpl/gclk/hpl_gclk_base.h"
+#include "hpl_mclk_config.h"
+
+//--------------------------------------------------------------------+
+// Forward USB interrupt events to TinyUSB IRQ Handler
+//--------------------------------------------------------------------+
+void USB_Handler(void)
+{
+  tud_int_handler(0);
+}
+
+//--------------------------------------------------------------------+
+// MACRO TYPEDEF CONSTANT ENUM DECLARATION
+//--------------------------------------------------------------------+
+
+/* Referenced GCLKs (out of 0~4), should be initialized firstly */
+#define _GCLK_INIT_1ST 0x00000000
+/* Not referenced GCLKs, initialized last */
+#define _GCLK_INIT_LAST 0x0000001F
+
+void board_init(void)
+{
+  // Clock init ( follow hpl_init.c )
+  hri_nvmctrl_set_CTRLB_RWS_bf(NVMCTRL, CONF_NVM_WAIT_STATE);
+
+  _set_performance_level(2);
+
+  _osc32kctrl_init_sources();
+  _oscctrl_init_sources();
+  _mclk_init();
+#if _GCLK_INIT_1ST
+  _gclk_init_generators_by_fref(_GCLK_INIT_1ST);
+#endif
+  _oscctrl_init_referenced_generators();
+  _gclk_init_generators_by_fref(_GCLK_INIT_LAST);
+
+#if (CONF_PORT_EVCTRL_PORT_0 | CONF_PORT_EVCTRL_PORT_1 | CONF_PORT_EVCTRL_PORT_2 | CONF_PORT_EVCTRL_PORT_3)
+  hri_port_set_EVCTRL_reg(PORT, 0, CONF_PORTA_EVCTRL);
+  hri_port_set_EVCTRL_reg(PORT, 1, CONF_PORTB_EVCTRL);
+#endif
+
+  // Update SystemCoreClock since it is hard coded with asf4 and not correct
+  // Init 1ms tick timer (samd SystemCoreClock may not correct)
+  SystemCoreClock = CONF_CPU_FREQUENCY;
+  SysTick_Config(CONF_CPU_FREQUENCY / 1000);
+
+  // Led init
+  gpio_set_pin_direction(LED_PIN, GPIO_DIRECTION_OUT);
+  gpio_set_pin_level(LED_PIN, !LED_STATE_ON);
+
+  // Button init
+  gpio_set_pin_direction(BUTTON_PIN, GPIO_DIRECTION_IN);
+  gpio_set_pin_pull_mode(BUTTON_PIN, BUTTON_STATE_ACTIVE ? GPIO_PULL_DOWN : GPIO_PULL_UP);
+
+#if CFG_TUSB_OS  == OPT_OS_FREERTOS
+  // If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher )
+  NVIC_SetPriority(USB_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY);
+#endif
+
+  /* USB Clock init
+   * The USB module requires a GCLK_USB of 48 MHz ~ 0.25% clock
+   * for low speed and full speed operation. */
+  hri_gclk_write_PCHCTRL_reg(GCLK, USB_GCLK_ID, GCLK_PCHCTRL_GEN_GCLK1_Val | GCLK_PCHCTRL_CHEN);
+  hri_mclk_set_AHBMASK_USB_bit(MCLK);
+  hri_mclk_set_APBBMASK_USB_bit(MCLK);
+
+  // USB Pin Init
+  gpio_set_pin_direction(PIN_PA24, GPIO_DIRECTION_OUT);
+  gpio_set_pin_level(PIN_PA24, false);
+  gpio_set_pin_pull_mode(PIN_PA24, GPIO_PULL_OFF);
+  gpio_set_pin_direction(PIN_PA25, GPIO_DIRECTION_OUT);
+  gpio_set_pin_level(PIN_PA25, false);
+  gpio_set_pin_pull_mode(PIN_PA25, GPIO_PULL_OFF);
+
+  gpio_set_pin_function(PIN_PA24, PINMUX_PA24G_USB_DM);
+  gpio_set_pin_function(PIN_PA25, PINMUX_PA25G_USB_DP);
+
+  // Output 500hz PWM on PB23 (TCC0 WO[3]) so we can validate the GCLK1 clock speed
+  hri_mclk_set_APBCMASK_TCC0_bit(MCLK);
+  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);
+  hri_gclk_write_PCHCTRL_reg(GCLK, TCC0_GCLK_ID, GCLK_PCHCTRL_GEN_GCLK1_Val | GCLK_PCHCTRL_CHEN);
+}
+
+//--------------------------------------------------------------------+
+// Board porting API
+//--------------------------------------------------------------------+
+
+void board_led_write(bool state)
+{
+  gpio_set_pin_level(LED_PIN, state);
+}
+
+uint32_t board_button_read(void)
+{
+  // button is active low
+  return gpio_get_pin_level(BUTTON_PIN) ? 0 : 1;
+}
+
+int board_uart_read(uint8_t* buf, int len)
+{
+  (void) buf; (void) len;
+  return 0;
+}
+
+int board_uart_write(void const * buf, int len)
+{
+  (void) buf; (void) len;
+  return 0;
+}
+
+#if CFG_TUSB_OS  == OPT_OS_NONE
+volatile uint32_t system_ticks = 0;
+
+void SysTick_Handler (void)
+{
+  system_ticks++;
+}
+
+uint32_t board_millis(void)
+{
+  return system_ticks;
+}
+#endif
+void _init(void)
+{
+
+}

+ 50 - 0
hw/bsp/saml21/family.mk

@@ -0,0 +1,50 @@
+UF2_FAMILY_ID = 0x68ed2b88
+DEPS_SUBMODULES += hw/mcu/microchip
+
+include $(TOP)/$(BOARD_PATH)/board.mk
+
+CFLAGS += \
+  -mthumb \
+  -mabi=aapcs \
+  -mcpu=cortex-m0plus \
+  -nostdlib -nostartfiles \
+  -DCONF_OSC32K_CALIB_ENABLE=0 \
+  -DCFG_TUSB_MCU=OPT_MCU_SAML21
+
+SRC_C += \
+	src/portable/microchip/samd/dcd_samd.c \
+	hw/mcu/microchip/saml21/gcc/gcc/startup_saml21.c \
+	hw/mcu/microchip/saml21/gcc/system_saml21.c \
+	hw/mcu/microchip/saml21/hpl/gclk/hpl_gclk.c \
+	hw/mcu/microchip/saml21/hpl/mclk/hpl_mclk.c \
+	hw/mcu/microchip/saml21/hpl/pm/hpl_pm.c \
+	hw/mcu/microchip/saml21/hpl/osc32kctrl/hpl_osc32kctrl.c \
+	hw/mcu/microchip/saml21/hpl/oscctrl/hpl_oscctrl.c \
+	hw/mcu/microchip/saml21/hal/src/hal_atomic.c
+
+INC += \
+	$(TOP)/$(BOARD_PATH) \
+	$(TOP)/hw/mcu/microchip/saml21/ \
+	$(TOP)/hw/mcu/microchip/saml21/config \
+	$(TOP)/hw/mcu/microchip/saml21/include \
+	$(TOP)/hw/mcu/microchip/saml21/hal/include \
+	$(TOP)/hw/mcu/microchip/saml21/hal/utils/include \
+	$(TOP)/hw/mcu/microchip/saml21/hpl/port \
+	$(TOP)/hw/mcu/microchip/saml21/hri \
+	$(TOP)/hw/mcu/microchip/saml21/CMSIS/Include
+
+# For TinyUSB port source 
+VENDOR = microchip
+CHIP_FAMILY = samd
+
+# For freeRTOS port source
+FREERTOS_PORT = ARM_CM0
+
+# flash using bossac at least version 1.8
+# can be found in arduino15/packages/arduino/tools/bossac/
+# Add it to your PATH or change BOSSAC variable to match your installation
+BOSSAC = bossac
+
+flash-bossac: $(BUILD)/$(PROJECT).bin
+	@:$(call check_defined, SERIAL, example: SERIAL=/dev/ttyACM0)
+	$(BOSSAC) --port=$(SERIAL) -U -i --offset=0x2000 -e -w $^ -R

+ 1 - 1
hw/mcu/microchip

@@ -1 +1 @@
-Subproject commit f7087f04783c896627061fc151fa3527b73733c7
+Subproject commit 58eb3763200ff51a998be5f537acf67299add227

+ 1 - 1
src/class/hid/hid_host.c

@@ -368,7 +368,7 @@ static bool config_get_report_desc(uint8_t dev_addr, tusb_control_request_t cons
 
   // Get Report Descriptor
   // using usbh enumeration buffer since report descriptor can be very long
-  TU_ASSERT( hid_itf->report_desc_len <= CFG_TUH_ENUMERATION_BUFSZIE );
+  TU_ASSERT( hid_itf->report_desc_len <= CFG_TUH_ENUMERATION_BUFSIZE );
 
   TU_LOG2("HID Get Report Descriptor\r\n");
   tusb_control_request_t const new_request =

+ 8 - 7
src/class/midi/midi_device.c

@@ -197,9 +197,11 @@ uint32_t tud_midi_n_stream_read(uint8_t itf, uint8_t cable_num, void* buffer, ui
 
 bool tud_midi_n_packet_read (uint8_t itf, uint8_t packet[4])
 {
-  midid_interface_t* p_midi = &_midid_itf[itf];
-  uint32_t num_read = tu_fifo_read_n(&p_midi->rx_ff, packet, 4);
-  _prep_out_transaction(p_midi);
+  midid_interface_t* midi = &_midid_itf[itf];
+  TU_VERIFY(midi->ep_out);
+
+  uint32_t const num_read = tu_fifo_read_n(&midi->rx_ff, packet, 4);
+  _prep_out_transaction(midi);
   return (num_read == 4);
 }
 
@@ -234,7 +236,7 @@ static uint32_t write_flush(midid_interface_t* midi)
 uint32_t tud_midi_n_stream_write(uint8_t itf, uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize)
 {
   midid_interface_t* midi = &_midid_itf[itf];
-  TU_VERIFY(midi->itf_num, 0);
+  TU_VERIFY(midi->ep_in, 0);
 
   midid_stream_t* stream = &midi->stream_write;
 
@@ -351,9 +353,7 @@ uint32_t tud_midi_n_stream_write(uint8_t itf, uint8_t cable_num, uint8_t const*
 bool tud_midi_n_packet_write (uint8_t itf, uint8_t const packet[4])
 {
   midid_interface_t* midi = &_midid_itf[itf];
-  if (midi->itf_num == 0) {
-    return 0;
-  }
+  TU_VERIFY(midi->ep_in);
 
   if (tu_fifo_remaining(&midi->tx_ff) < 4) return false;
 
@@ -435,6 +435,7 @@ uint16_t midid_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint
   }
 
   p_midi->itf_num = desc_midi->bInterfaceNumber;
+  (void) p_midi->itf_num;
 
   // next descriptor
   drv_len += tu_desc_len(p_desc);

+ 1 - 1
src/common/tusb_fifo.h

@@ -86,8 +86,8 @@ typedef struct
   .depth                = _depth,                           \
   .item_size            = sizeof(_type),                    \
   .overwritable         = _overwritable,                    \
-  .max_pointer_idx      = 2*(_depth)-1,                     \
   .non_used_index_space = UINT16_MAX - (2*(_depth)-1),      \
+  .max_pointer_idx      = 2*(_depth)-1,                     \
 }
 
 #define TU_FIFO_DEF(_name, _depth, _type, _overwritable)                      \

+ 2 - 2
src/host/usbh.c

@@ -130,7 +130,7 @@ CFG_TUSB_MEM_SECTION usbh_device_t _usbh_devices[CFG_TUSB_HOST_DEVICE_MAX+1];
 OSAL_QUEUE_DEF(OPT_MODE_HOST, _usbh_qdef, CFG_TUH_TASK_QUEUE_SZ, hcd_event_t);
 static osal_queue_t _usbh_q;
 
-CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t _usbh_ctrl_buf[CFG_TUH_ENUMERATION_BUFSZIE];
+CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t _usbh_ctrl_buf[CFG_TUH_ENUMERATION_BUFSIZE];
 
 //------------- Helper Function Prototypes -------------//
 static bool enum_new_device(hcd_event_t* event);
@@ -907,7 +907,7 @@ static bool enum_get_9byte_config_desc_complete(uint8_t dev_addr, tusb_control_r
   // Use offsetof to avoid pointer to the odd/misaligned address
   memcpy(&total_len, (uint8_t*) desc_config + offsetof(tusb_desc_configuration_t, wTotalLength), 2);
 
-  TU_ASSERT(total_len <= CFG_TUH_ENUMERATION_BUFSZIE);
+  TU_ASSERT(total_len <= CFG_TUH_ENUMERATION_BUFSIZE);
 
   // Get full configuration descriptor
   TU_LOG2("Get Configuration Descriptor\r\n");

+ 1 - 1
src/host/usbh_control.c

@@ -50,7 +50,7 @@ typedef struct
 static usbh_control_xfer_t _ctrl_xfer;
 
 //CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN
-//static uint8_t _tuh_ctrl_buf[CFG_TUH_ENUMERATION_BUFSZIE];
+//static uint8_t _tuh_ctrl_buf[CFG_TUH_ENUMERATION_BUFSIZE];
 
 //--------------------------------------------------------------------+
 // MACRO TYPEDEF CONSTANT ENUM DECLARATION

+ 2 - 2
src/portable/microchip/samd/dcd_samd.c

@@ -29,7 +29,7 @@
 #if TUSB_OPT_DEVICE_ENABLED && \
     (CFG_TUSB_MCU == OPT_MCU_SAMD11 || CFG_TUSB_MCU == OPT_MCU_SAMD21 || \
      CFG_TUSB_MCU == OPT_MCU_SAMD51 || CFG_TUSB_MCU == OPT_MCU_SAME5X || \
-     CFG_TUSB_MCU == OPT_MCU_SAML22)
+     CFG_TUSB_MCU == OPT_MCU_SAML22 || CFG_TUSB_MCU == OPT_MCU_SAML21)
 
 #include "sam.h"
 #include "device/dcd.h"
@@ -125,7 +125,7 @@ void dcd_int_disable(uint8_t rhport)
 }
 
 #elif CFG_TUSB_MCU == OPT_MCU_SAMD11 || CFG_TUSB_MCU == OPT_MCU_SAMD21 || \
-      CFG_TUSB_MCU == OPT_MCU_SAML22
+      CFG_TUSB_MCU == OPT_MCU_SAML22 || CFG_TUSB_MCU == OPT_MCU_SAML21
 
 void dcd_int_enable(uint8_t rhport)
 {

+ 41 - 18
src/portable/nordic/nrf5x/dcd_nrf5x.c

@@ -108,13 +108,21 @@ static inline uint32_t NVIC_GetEnableIRQ(IRQn_Type IRQn)
 }
 #endif
 
+// check if we are in ISR
+TU_ATTR_ALWAYS_INLINE static inline bool is_in_isr(void)
+{
+  return (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) ? true : false;
+}
+
 // helper to start DMA
+// TODO use Cortex M4 LDREX and STREX command (atomic) to have better mutex access to EasyDMA
+// since current implementation does not 100% guarded against race condition
 static void edpt_dma_start(volatile uint32_t* reg_startep)
 {
   // Only one dma can be active
   if ( _dcd.dma_pending )
   {
-    if (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk)
+    if (is_in_isr())
     {
       // Called within ISR, use usbd task to defer later
       usbd_defer_func( (osal_task_func_t) edpt_dma_start, (void*) reg_startep, true );
@@ -159,6 +167,17 @@ static void edpt_dma_end(void)
   _dcd.dma_pending = 0;
 }
 
+// helper to set TASKS_EP0STATUS / TASKS_EP0RCVOUT since they also need EasyDMA
+// However TASKS_EP0STATUS doesn't trigger any DMA transfer and got ENDED event subsequently
+// Therefore dma_running state will be corrected right away
+void start_ep0_task(volatile uint32_t* reg_task)
+{
+  edpt_dma_start(reg_task);
+
+  // correct the dma_running++ in dma start
+  if (_dcd.dma_pending) _dcd.dma_pending--;
+}
+
 // helper getting td
 static inline xfer_td_t* get_td(uint8_t epnum, uint8_t dir)
 {
@@ -407,21 +426,18 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t
 
   if ( control_status )
   {
-    // Status Phase also requires Easy DMA has to be available as well !!!!
-    // However TASKS_EP0STATUS doesn't trigger any DMA transfer and got ENDED event subsequently
-    // Therefore dma_running state will be corrected right away
-    edpt_dma_start(&NRF_USBD->TASKS_EP0STATUS);
-    if (_dcd.dma_pending) _dcd.dma_pending--; // correct the dma_running++ in dma start
+    // Status Phase also requires EasyDMA has to be available as well !!!!
+    start_ep0_task(&NRF_USBD->TASKS_EP0STATUS);
 
     // The nRF doesn't interrupt on status transmit so we queue up a success response.
-    dcd_event_xfer_complete(0, ep_addr, 0, XFER_RESULT_SUCCESS, false);
+    dcd_event_xfer_complete(0, ep_addr, 0, XFER_RESULT_SUCCESS, is_in_isr());
   }
   else if ( dir == TUSB_DIR_OUT )
   {
     if ( epnum == 0 )
     {
-      // Accept next Control Out packet
-      NRF_USBD->TASKS_EP0RCVOUT = 1;
+      // Accept next Control Out packet. TASKS_EP0RCVOUT also require EasyDMA
+      start_ep0_task(&NRF_USBD->TASKS_EP0RCVOUT);
     }else
     {
       if ( xfer->data_received )
@@ -581,12 +597,6 @@ void dcd_int_handler(uint8_t rhport)
     }
   }
 
-  if ( int_status & EDPT_END_ALL_MASK )
-  {
-    // DMA complete move data from SRAM -> Endpoint
-    edpt_dma_end();
-  }
- 
   // Setup tokens are specific to the Control endpoint.
   if ( int_status & USBD_INTEN_EP0SETUP_Msk )
   {
@@ -607,6 +617,12 @@ void dcd_int_handler(uint8_t rhport)
     }
   }
 
+  if ( int_status & EDPT_END_ALL_MASK )
+  {
+    // DMA complete move data from SRAM -> Endpoint
+    edpt_dma_end();
+  }
+
   //--------------------------------------------------------------------+
   /* Control/Bulk/Interrupt (CBI) Transfer
    *
@@ -655,8 +671,15 @@ void dcd_int_handler(uint8_t rhport)
       {
         if ( epnum == 0 )
         {
-          // Accept next Control Out packet
-          NRF_USBD->TASKS_EP0RCVOUT = 1;
+          // Accept next Control Out packet. TASKS_EP0RCVOUT also require EasyDMA
+          if ( _dcd.dma_pending )
+          {
+            // use usbd task to defer later
+            usbd_defer_func( (osal_task_func_t) start_ep0_task, (void*) &NRF_USBD->TASKS_EP0RCVOUT, true );
+          }else
+          {
+            start_ep0_task(&NRF_USBD->TASKS_EP0RCVOUT);
+          }
         }else
         {
           // nRF auto accept next Bulk/Interrupt OUT packet
@@ -973,7 +996,7 @@ void tusb_hal_nrf_power_event (uint32_t event)
 
         hfclk_disable();
 
-        dcd_event_bus_signal(0, DCD_EVENT_UNPLUGGED, (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) ? true : false);
+        dcd_event_bus_signal(0, DCD_EVENT_UNPLUGGED, is_in_isr());
       }
     break;
 

+ 3 - 2
src/tusb_option.h

@@ -61,6 +61,7 @@
 #define OPT_MCU_SAME5X            203 ///< MicroChip SAM E5x
 #define OPT_MCU_SAMD11            204 ///< MicroChip SAMD11
 #define OPT_MCU_SAML22            205 ///< MicroChip SAML22
+#define OPT_MCU_SAML21            206 ///< MicroChip SAML21
 
 // STM32
 #define OPT_MCU_STM32F0           300 ///< ST STM32F0
@@ -278,8 +279,8 @@
     #error there is no benefit enable hub with max device is 1. Please disable hub or increase CFG_TUSB_HOST_DEVICE_MAX
   #endif
 
-  #ifndef CFG_TUH_ENUMERATION_BUFSZIE
-    #define CFG_TUH_ENUMERATION_BUFSZIE 256
+  #ifndef CFG_TUH_ENUMERATION_BUFSIZE
+    #define CFG_TUH_ENUMERATION_BUFSIZE 256
   #endif
 
   //------------- CLASS -------------//