diff --git a/Makefile.features b/Makefile.features index 62499d2a2c..426933bf77 100644 --- a/Makefile.features +++ b/Makefile.features @@ -23,7 +23,11 @@ FEATURES_PROVIDED += cpu_$(CPU) # Features that are conflicting for all architectures FEATURES_CONFLICT += picolibc:newlib -FEATURES_CONFLICT_MSG += "Only one standard C library can be used" +FEATURES_CONFLICT_MSG += "Only one standard C library can be used." FEATURES_CONFLICT += periph_gpio_irq:periph_gpio_ll_irq -FEATURES_CONFLICT_MSG += "Only one GPIO IRQ implementation can be used" +FEATURES_CONFLICT_MSG += "Only one GPIO IRQ implementation can be used." + +FEATURES_CONFLICT += periph_usbdev:tinyusb_device +FEATURES_CONFLICT += periph_usbdev:tinyusb_host +FEATURES_CONFLICT_MSG += "Package tinyUSB is not yet compatible with periph_usbdev." diff --git a/boards/b-l475e-iot01a/Kconfig b/boards/b-l475e-iot01a/Kconfig index 83b1d863d7..00e61e932f 100644 --- a/boards/b-l475e-iot01a/Kconfig +++ b/boards/b-l475e-iot01a/Kconfig @@ -26,6 +26,7 @@ config BOARD_B_L475E_IOT01A # Put other features for this board (in alphabetical order) select HAS_RIOTBOOT + select HAS_TINYUSB_DEVICE # Clock configuration select BOARD_HAS_LSE diff --git a/boards/b-l475e-iot01a/Makefile.features b/boards/b-l475e-iot01a/Makefile.features index ae95e240aa..1e361a74a2 100644 --- a/boards/b-l475e-iot01a/Makefile.features +++ b/boards/b-l475e-iot01a/Makefile.features @@ -14,3 +14,4 @@ FEATURES_PROVIDED += periph_usbdev # Put other features for this board (in alphabetical order) FEATURES_PROVIDED += riotboot +FEATURES_PROVIDED += tinyusb_device diff --git a/boards/common/weact-f4x1cx/Kconfig b/boards/common/weact-f4x1cx/Kconfig index 38f86150a0..77fd5fca62 100644 --- a/boards/common/weact-f4x1cx/Kconfig +++ b/boards/common/weact-f4x1cx/Kconfig @@ -18,6 +18,9 @@ config BOARD_COMMON_WEACT_F4X1CX select HAS_PERIPH_USBDEV select HAS_HIGHLEVEL_STDIO + # Put other features for this board (in alphabetical order) + select HAS_TINYUSB_DEVICE + # Clock configuration select BOARD_HAS_HSE select BOARD_HAS_LSE diff --git a/boards/common/weact-f4x1cx/Makefile.features b/boards/common/weact-f4x1cx/Makefile.features index 66250c5a64..6a2f08acda 100644 --- a/boards/common/weact-f4x1cx/Makefile.features +++ b/boards/common/weact-f4x1cx/Makefile.features @@ -12,6 +12,7 @@ FEATURES_PROVIDED += periph_usbdev # Various other features (if any) FEATURES_PROVIDED += highlevel_stdio +FEATURES_PROVIDED += tinyusb_device # weact-f4x1cx boards provide a custom default Kconfig clock configuration KCONFIG_BOARD_CONFIG += $(RIOTBOARD)/common/weact-f4x1cx/clock.config diff --git a/boards/esp32s2-devkit/Kconfig b/boards/esp32s2-devkit/Kconfig index ec8398c4a4..c51b29253b 100644 --- a/boards/esp32s2-devkit/Kconfig +++ b/boards/esp32s2-devkit/Kconfig @@ -34,6 +34,10 @@ config BOARD_ESP32S2_DEVKIT select HAS_PERIPH_USBDEV if BOARD_VERSION_ESP32S2_DEVKITC_1U select HAS_PERIPH_USBDEV if BOARD_VERSION_ESP32S2_DEVKITC_1R select HAS_PERIPH_USBDEV if BOARD_VERSION_ESP32S2_DEVKITC_1RU + select HAS_TINYUSB_DEVICE if BOARD_VERSION_ESP32S2_DEVKITC_1 + select HAS_TINYUSB_DEVICE if BOARD_VERSION_ESP32S2_DEVKITC_1U + select HAS_TINYUSB_DEVICE if BOARD_VERSION_ESP32S2_DEVKITC_1R + select HAS_TINYUSB_DEVICE if BOARD_VERSION_ESP32S2_DEVKITC_1RU choice bool "ESP32-S2-DevKit board version" diff --git a/boards/esp32s2-devkit/Makefile.features b/boards/esp32s2-devkit/Makefile.features index 7968cc24cc..cb42fd74ee 100644 --- a/boards/esp32s2-devkit/Makefile.features +++ b/boards/esp32s2-devkit/Makefile.features @@ -43,4 +43,5 @@ FEATURES_PROVIDED += arduino ifneq (,$(filter esp32s2-devkitc-%,$(BOARD_VERSION))) FEATURES_PROVIDED += periph_usbdev -endif + FEATURES_PROVIDED += tinyusb_device +endif \ No newline at end of file diff --git a/boards/esp32s3-devkit/Kconfig b/boards/esp32s3-devkit/Kconfig index 141af216c8..5f1f8f2787 100644 --- a/boards/esp32s3-devkit/Kconfig +++ b/boards/esp32s3-devkit/Kconfig @@ -44,6 +44,7 @@ config BOARD_ESP32S3_DEVKIT select HAS_PERIPH_PWM select HAS_PERIPH_SPI select HAS_PERIPH_USBDEV + select HAS_TINYUSB_DEVICE choice bool "ESP32-S3-DevKit board version" diff --git a/boards/esp32s3-devkit/Makefile.features b/boards/esp32s3-devkit/Makefile.features index 29ce79cba2..e009433f58 100644 --- a/boards/esp32s3-devkit/Makefile.features +++ b/boards/esp32s3-devkit/Makefile.features @@ -39,3 +39,4 @@ FEATURES_PROVIDED += esp_jtag FEATURES_PROVIDED += arduino FEATURES_PROVIDED += periph_usbdev +FEATURES_PROVIDED += tinyusb_device diff --git a/boards/nucleo-f207zg/Kconfig b/boards/nucleo-f207zg/Kconfig index 76e72f8595..56b9c997b2 100644 --- a/boards/nucleo-f207zg/Kconfig +++ b/boards/nucleo-f207zg/Kconfig @@ -27,6 +27,8 @@ config BOARD_NUCLEO_F207ZG # Put other features for this board (in alphabetical order) select HAS_RIOTBOOT + select HAS_TINYUSB_DEVICE + select HAVE_STM32_ETH source "$(RIOTBOARD)/common/nucleo144/Kconfig" diff --git a/boards/nucleo-f207zg/Makefile.features b/boards/nucleo-f207zg/Makefile.features index 1e1f728ace..be16d5ee5c 100644 --- a/boards/nucleo-f207zg/Makefile.features +++ b/boards/nucleo-f207zg/Makefile.features @@ -14,6 +14,7 @@ FEATURES_PROVIDED += periph_usbdev # Put other features for this board (in alphabetical order) FEATURES_PROVIDED += riotboot +FEATURES_PROVIDED += tinyusb_device # load the common Makefile.features for Nucleo-144 boards include $(RIOTBOARD)/common/nucleo144/Makefile.features diff --git a/boards/nucleo-f412zg/Kconfig b/boards/nucleo-f412zg/Kconfig index b370bafebc..c5b945bafc 100644 --- a/boards/nucleo-f412zg/Kconfig +++ b/boards/nucleo-f412zg/Kconfig @@ -25,4 +25,7 @@ config BOARD_NUCLEO_F412ZG select HAS_PERIPH_UART select HAS_PERIPH_USBDEV + # Put other features for this board (in alphabetical order) + select HAS_TINYUSB_DEVICE + source "$(RIOTBOARD)/common/nucleo144/Kconfig" diff --git a/boards/nucleo-f412zg/Makefile.features b/boards/nucleo-f412zg/Makefile.features index af1b6b7a1e..d13fc84eb5 100644 --- a/boards/nucleo-f412zg/Makefile.features +++ b/boards/nucleo-f412zg/Makefile.features @@ -12,5 +12,8 @@ FEATURES_PROVIDED += periph_timer FEATURES_PROVIDED += periph_uart FEATURES_PROVIDED += periph_usbdev +# Put other features for this board (in alphabetical order) +FEATURES_PROVIDED += tinyusb_device + # load the common Makefile.features for Nucleo-144 boards include $(RIOTBOARD)/common/nucleo144/Makefile.features diff --git a/boards/nucleo-f413zh/Kconfig b/boards/nucleo-f413zh/Kconfig index a2343df2c8..8ec9fd7a34 100644 --- a/boards/nucleo-f413zh/Kconfig +++ b/boards/nucleo-f413zh/Kconfig @@ -28,4 +28,7 @@ config BOARD_NUCLEO_F413ZH select HAS_PERIPH_UART select HAS_PERIPH_USBDEV + # Put other features for this board (in alphabetical order) + select HAS_TINYUSB_DEVICE + source "$(RIOTBOARD)/common/nucleo144/Kconfig" diff --git a/boards/nucleo-f413zh/Makefile.features b/boards/nucleo-f413zh/Makefile.features index 8af0aedecb..409cd4e609 100644 --- a/boards/nucleo-f413zh/Makefile.features +++ b/boards/nucleo-f413zh/Makefile.features @@ -14,5 +14,8 @@ FEATURES_PROVIDED += periph_timer FEATURES_PROVIDED += periph_uart FEATURES_PROVIDED += periph_usbdev +# Put other features for this board (in alphabetical order) +FEATURES_PROVIDED += tinyusb_device + # load the common Makefile.features for Nucleo boards include $(RIOTBOARD)/common/nucleo144/Makefile.features diff --git a/boards/nucleo-f429zi/Kconfig b/boards/nucleo-f429zi/Kconfig index 6180a1b3ed..b6d4ab11a6 100644 --- a/boards/nucleo-f429zi/Kconfig +++ b/boards/nucleo-f429zi/Kconfig @@ -26,4 +26,7 @@ config BOARD_NUCLEO_F429ZI select HAS_PERIPH_UART select HAS_PERIPH_USBDEV + # Put other features for this board (in alphabetical order) + select HAS_TINYUSB_DEVICE + source "$(RIOTBOARD)/common/nucleo144/Kconfig" diff --git a/boards/nucleo-f429zi/Makefile.features b/boards/nucleo-f429zi/Makefile.features index 9e973c9028..92e2f945a8 100644 --- a/boards/nucleo-f429zi/Makefile.features +++ b/boards/nucleo-f429zi/Makefile.features @@ -13,5 +13,8 @@ FEATURES_PROVIDED += periph_timer FEATURES_PROVIDED += periph_uart FEATURES_PROVIDED += periph_usbdev +# Put other features for this board (in alphabetical order) +FEATURES_PROVIDED += tinyusb_device + # load the common Makefile.features for Nucleo boards include $(RIOTBOARD)/common/nucleo144/Makefile.features diff --git a/boards/nucleo-f439zi/Kconfig b/boards/nucleo-f439zi/Kconfig index 15c750eb73..9e06fe4b99 100644 --- a/boards/nucleo-f439zi/Kconfig +++ b/boards/nucleo-f439zi/Kconfig @@ -25,4 +25,7 @@ config BOARD_NUCLEO_F439ZI select HAS_PERIPH_UART select HAS_PERIPH_USBDEV + # Put other features for this board (in alphabetical order) + select HAS_TINYUSB_DEVICE + source "$(RIOTBOARD)/common/nucleo144/Kconfig" diff --git a/boards/nucleo-f439zi/Makefile.features b/boards/nucleo-f439zi/Makefile.features index fffc0ad652..8abb89362d 100644 --- a/boards/nucleo-f439zi/Makefile.features +++ b/boards/nucleo-f439zi/Makefile.features @@ -12,5 +12,8 @@ FEATURES_PROVIDED += periph_timer FEATURES_PROVIDED += periph_uart FEATURES_PROVIDED += periph_usbdev +# Put other features for this board (in alphabetical order) +FEATURES_PROVIDED += tinyusb_device + # load the common Makefile.features for Nucleo boards include $(RIOTBOARD)/common/nucleo144/Makefile.features diff --git a/boards/nucleo-f446ze/Kconfig b/boards/nucleo-f446ze/Kconfig index e50f161c08..e7e3349547 100644 --- a/boards/nucleo-f446ze/Kconfig +++ b/boards/nucleo-f446ze/Kconfig @@ -26,4 +26,7 @@ config BOARD_NUCLEO_F446ZE select HAS_PERIPH_UART select HAS_PERIPH_USBDEV + # Put other features for this board (in alphabetical order) + select HAS_TINYUSB_DEVICE + source "$(RIOTBOARD)/common/nucleo144/Kconfig" diff --git a/boards/nucleo-f446ze/Makefile.features b/boards/nucleo-f446ze/Makefile.features index 484ad9d961..a3961b87e2 100644 --- a/boards/nucleo-f446ze/Makefile.features +++ b/boards/nucleo-f446ze/Makefile.features @@ -13,5 +13,8 @@ FEATURES_PROVIDED += periph_timer FEATURES_PROVIDED += periph_uart FEATURES_PROVIDED += periph_usbdev +# Put other features for this board (in alphabetical order) +FEATURES_PROVIDED += tinyusb_device + # load the common Makefile.features for Nucleo boards include $(RIOTBOARD)/common/nucleo144/Makefile.features diff --git a/boards/nucleo-f722ze/Kconfig b/boards/nucleo-f722ze/Kconfig index a6d9b19328..9c943162b2 100644 --- a/boards/nucleo-f722ze/Kconfig +++ b/boards/nucleo-f722ze/Kconfig @@ -25,5 +25,6 @@ config BOARD_NUCLEO_F722ZE # Put other features for this board (in alphabetical order) select HAS_RIOTBOOT + select HAS_TINYUSB_DEVICE source "$(RIOTBOARD)/common/nucleo144/Kconfig" diff --git a/boards/nucleo-f722ze/Makefile.features b/boards/nucleo-f722ze/Makefile.features index 87f80e5c15..aa05bafc46 100644 --- a/boards/nucleo-f722ze/Makefile.features +++ b/boards/nucleo-f722ze/Makefile.features @@ -12,6 +12,7 @@ FEATURES_PROVIDED += periph_can # Put other features for this board (in alphabetical order) FEATURES_PROVIDED += riotboot +FEATURES_PROVIDED += tinyusb_device # load the common Makefile.features for Nucleo144 boards include $(RIOTBOARD)/common/nucleo144/Makefile.features diff --git a/boards/nucleo-f746zg/Kconfig b/boards/nucleo-f746zg/Kconfig index a533c9f345..503ec45187 100644 --- a/boards/nucleo-f746zg/Kconfig +++ b/boards/nucleo-f746zg/Kconfig @@ -28,6 +28,7 @@ config BOARD_NUCLEO_F746ZG # Put other features for this board (in alphabetical order) select HAS_RIOTBOOT + select HAS_TINYUSB_DEVICE select HAVE_STM32_ETH source "$(RIOTBOARD)/common/nucleo144/Kconfig" diff --git a/boards/nucleo-f746zg/Makefile.features b/boards/nucleo-f746zg/Makefile.features index 1eddc8d8c2..aef40ecaff 100644 --- a/boards/nucleo-f746zg/Makefile.features +++ b/boards/nucleo-f746zg/Makefile.features @@ -15,6 +15,7 @@ FEATURES_PROVIDED += periph_usbdev # Put other features for this board (in alphabetical order) FEATURES_PROVIDED += riotboot +FEATURES_PROVIDED += tinyusb_device # load the common Makefile.features for Nucleo boards include $(RIOTBOARD)/common/nucleo144/Makefile.features diff --git a/boards/nucleo-f767zi/Kconfig b/boards/nucleo-f767zi/Kconfig index a7d9d3b707..5a68db3efd 100644 --- a/boards/nucleo-f767zi/Kconfig +++ b/boards/nucleo-f767zi/Kconfig @@ -34,6 +34,7 @@ config BOARD_NUCLEO_F767ZI # Put other features for this board (in alphabetical order) select HAS_RIOTBOOT + select HAS_TINYUSB_DEVICE select HAVE_STM32_ETH source "$(RIOTBOARD)/common/nucleo144/Kconfig" diff --git a/boards/nucleo-f767zi/Makefile.features b/boards/nucleo-f767zi/Makefile.features index e72a424755..94380f44bd 100644 --- a/boards/nucleo-f767zi/Makefile.features +++ b/boards/nucleo-f767zi/Makefile.features @@ -21,6 +21,7 @@ FEATURES_PROVIDED += periph_usbdev # Put other features for this board (in alphabetical order) FEATURES_PROVIDED += riotboot +FEATURES_PROVIDED += tinyusb_device # load the common Makefile.features for Nucleo boards include $(RIOTBOARD)/common/nucleo144/Makefile.features diff --git a/boards/nucleo-l496zg/Kconfig b/boards/nucleo-l496zg/Kconfig index cf75250409..1b7b45d8d5 100644 --- a/boards/nucleo-l496zg/Kconfig +++ b/boards/nucleo-l496zg/Kconfig @@ -29,5 +29,6 @@ config BOARD_NUCLEO_L496ZG # Put other features for this board (in alphabetical order) select HAS_RIOTBOOT + select HAS_TINYUSB_DEVICE source "$(RIOTBOARD)/common/nucleo144/Kconfig" diff --git a/boards/nucleo-l496zg/Makefile.features b/boards/nucleo-l496zg/Makefile.features index 3f337e6e31..5240bca884 100644 --- a/boards/nucleo-l496zg/Makefile.features +++ b/boards/nucleo-l496zg/Makefile.features @@ -13,6 +13,7 @@ FEATURES_PROVIDED += periph_usbdev # Put other features for this board (in alphabetical order) FEATURES_PROVIDED += riotboot +FEATURES_PROVIDED += tinyusb_device # load the common Makefile.features for Nucleo boards include $(RIOTBOARD)/common/nucleo144/Makefile.features diff --git a/boards/nucleo-l4r5zi/Kconfig b/boards/nucleo-l4r5zi/Kconfig index b45e616762..cea985e6d0 100644 --- a/boards/nucleo-l4r5zi/Kconfig +++ b/boards/nucleo-l4r5zi/Kconfig @@ -28,5 +28,6 @@ config BOARD_NUCLEO_L4R5ZI # Put other features for this board (in alphabetical order) select HAS_RIOTBOOT + select HAS_TINYUSB_DEVICE source "$(RIOTBOARD)/common/nucleo144/Kconfig" diff --git a/boards/nucleo-l4r5zi/Makefile.features b/boards/nucleo-l4r5zi/Makefile.features index c44eef41c6..a3d3970109 100644 --- a/boards/nucleo-l4r5zi/Makefile.features +++ b/boards/nucleo-l4r5zi/Makefile.features @@ -13,6 +13,7 @@ FEATURES_PROVIDED += periph_usbdev # Put other features for this board (in alphabetical order) FEATURES_PROVIDED += riotboot +FEATURES_PROVIDED += tinyusb_device # load the common Makefile.features for Nucleo boards include $(RIOTBOARD)/common/nucleo144/Makefile.features diff --git a/boards/p-l496g-cell02/Kconfig b/boards/p-l496g-cell02/Kconfig index c69e9f1835..eb770200a2 100644 --- a/boards/p-l496g-cell02/Kconfig +++ b/boards/p-l496g-cell02/Kconfig @@ -25,6 +25,7 @@ config BOARD_P_L496G_CELL02 # Put other features for this board (in alphabetical order) select HAS_RIOTBOOT + select HAS_TINYUSB_DEVICE # Clock configuration select BOARD_HAS_LSE diff --git a/boards/p-l496g-cell02/Makefile.features b/boards/p-l496g-cell02/Makefile.features index f3879710e6..ab9e9e7bfd 100644 --- a/boards/p-l496g-cell02/Makefile.features +++ b/boards/p-l496g-cell02/Makefile.features @@ -14,3 +14,4 @@ FEATURES_PROVIDED += periph_usbdev # Put other features for this board (in alphabetical order) FEATURES_PROVIDED += riotboot +FEATURES_PROVIDED += tinyusb_device diff --git a/boards/pyboard/Kconfig b/boards/pyboard/Kconfig index 4f18e33e8b..52a5e4b580 100644 --- a/boards/pyboard/Kconfig +++ b/boards/pyboard/Kconfig @@ -22,6 +22,9 @@ config BOARD_PYBOARD select HAS_PERIPH_UART select HAS_PERIPH_USBDEV + # Put other features for this board (in alphabetical order) + select HAS_TINYUSB_DEVICE + # Clock configuration select BOARD_HAS_HSE select BOARD_HAS_LSE diff --git a/boards/pyboard/Makefile.features b/boards/pyboard/Makefile.features index 1237c2661e..89cc9e58ba 100644 --- a/boards/pyboard/Makefile.features +++ b/boards/pyboard/Makefile.features @@ -9,3 +9,6 @@ FEATURES_PROVIDED += periph_spi FEATURES_PROVIDED += periph_timer FEATURES_PROVIDED += periph_uart FEATURES_PROVIDED += periph_usbdev + +# Put other features for this board (in alphabetical order) +FEATURES_PROVIDED += tinyusb_device diff --git a/boards/stm32f429i-disc1/Kconfig b/boards/stm32f429i-disc1/Kconfig index 98929a0101..bec0878951 100644 --- a/boards/stm32f429i-disc1/Kconfig +++ b/boards/stm32f429i-disc1/Kconfig @@ -23,6 +23,7 @@ config BOARD_STM32F429I_DISC1 # Put other features for this board (in alphabetical order) select HAS_RIOTBOOT + select HAS_TINYUSB_DEVICE # Clock configuration select BOARD_HAS_HSE diff --git a/boards/stm32f429i-disc1/Makefile.features b/boards/stm32f429i-disc1/Makefile.features index 71c477ce08..0f69893c65 100644 --- a/boards/stm32f429i-disc1/Makefile.features +++ b/boards/stm32f429i-disc1/Makefile.features @@ -11,3 +11,4 @@ FEATURES_PROVIDED += periph_usbdev # Put other features for this board (in alphabetical order) FEATURES_PROVIDED += riotboot +FEATURES_PROVIDED += tinyusb_device diff --git a/boards/stm32f469i-disco/Kconfig b/boards/stm32f469i-disco/Kconfig index 860dff6cb3..0f1197435e 100644 --- a/boards/stm32f469i-disco/Kconfig +++ b/boards/stm32f469i-disco/Kconfig @@ -18,6 +18,9 @@ config BOARD_STM32F469I_DISCO select HAS_PERIPH_UART select HAS_PERIPH_USBDEV + # Put other features for this board (in alphabetical order) + select HAS_TINYUSB_DEVICE + # Clock configuration select BOARD_HAS_HSE select BOARD_HAS_LSE diff --git a/boards/stm32f469i-disco/Makefile.features b/boards/stm32f469i-disco/Makefile.features index 65ff88110c..3117b048c0 100644 --- a/boards/stm32f469i-disco/Makefile.features +++ b/boards/stm32f469i-disco/Makefile.features @@ -12,3 +12,6 @@ FEATURES_PROVIDED += periph_spi FEATURES_PROVIDED += periph_timer FEATURES_PROVIDED += periph_uart FEATURES_PROVIDED += periph_usbdev + +# Put other features for this board (in alphabetical order) +FEATURES_PROVIDED += tinyusb_device diff --git a/boards/stm32f4discovery/Kconfig b/boards/stm32f4discovery/Kconfig index be03e78426..a79d46d756 100644 --- a/boards/stm32f4discovery/Kconfig +++ b/boards/stm32f4discovery/Kconfig @@ -27,6 +27,7 @@ config BOARD_STM32F4DISCOVERY # Various other features (if any) select HAS_ARDUINO + select HAS_TINYUSB_DEVICE # Clock configuration select BOARD_HAS_HSE diff --git a/boards/stm32f4discovery/Makefile.features b/boards/stm32f4discovery/Makefile.features index 450411cea3..a111fc95a8 100644 --- a/boards/stm32f4discovery/Makefile.features +++ b/boards/stm32f4discovery/Makefile.features @@ -15,6 +15,7 @@ FEATURES_PROVIDED += periph_usbdev # Various other features (if any) FEATURES_PROVIDED += arduino +FEATURES_PROVIDED += tinyusb_device # TODO: re-think concept for conflicts based on actual used peripherals... FEATURES_CONFLICT += periph_spi:periph_dac diff --git a/boards/stm32f723e-disco/Kconfig b/boards/stm32f723e-disco/Kconfig index 1202848358..5e3a794970 100644 --- a/boards/stm32f723e-disco/Kconfig +++ b/boards/stm32f723e-disco/Kconfig @@ -23,6 +23,9 @@ config BOARD_STM32F723E_DISCO select HAS_PERIPH_UART_HW_FC select HAS_PERIPH_USBDEV + # Put other features for this board (in alphabetical order) + select HAS_TINYUSB_DEVICE + # Clock configuration select BOARD_HAS_HSE select BOARD_HAS_LSE diff --git a/boards/stm32f723e-disco/Makefile.features b/boards/stm32f723e-disco/Makefile.features index 1149406a57..1e87f7b710 100644 --- a/boards/stm32f723e-disco/Makefile.features +++ b/boards/stm32f723e-disco/Makefile.features @@ -12,5 +12,8 @@ FEATURES_PROVIDED += periph_uart FEATURES_PROVIDED += periph_uart_hw_fc FEATURES_PROVIDED += periph_usbdev +# Put other features for this board (in alphabetical order) +FEATURES_PROVIDED += tinyusb_device + # stm32f723e-disco provides a custom default Kconfig clock configuration KCONFIG_BOARD_CONFIG += $(RIOTBOARD)/stm32f723e-disco/clock.config diff --git a/boards/stm32f769i-disco/Kconfig b/boards/stm32f769i-disco/Kconfig index 0ff75d637b..94671967f5 100644 --- a/boards/stm32f769i-disco/Kconfig +++ b/boards/stm32f769i-disco/Kconfig @@ -20,6 +20,9 @@ config BOARD_STM32F769I_DISCO select HAS_PERIPH_UART select HAS_PERIPH_USBDEV + # Put other features for this board (in alphabetical order) + select HAS_TINYUSB_DEVICE + # Clock configuration select BOARD_HAS_HSE select BOARD_HAS_LSE diff --git a/boards/stm32f769i-disco/Makefile.features b/boards/stm32f769i-disco/Makefile.features index 7a8128e5aa..7577140b5e 100644 --- a/boards/stm32f769i-disco/Makefile.features +++ b/boards/stm32f769i-disco/Makefile.features @@ -8,5 +8,8 @@ FEATURES_PROVIDED += periph_timer FEATURES_PROVIDED += periph_uart FEATURES_PROVIDED += periph_usbdev +# Put other features for this board (in alphabetical order) +FEATURES_PROVIDED += tinyusb_device + # stm32f769i-disco provides a custom default Kconfig clock configuration KCONFIG_BOARD_CONFIG += $(RIOTBOARD)/stm32f769i-disco/clock.config diff --git a/boards/stm32l476g-disco/Kconfig b/boards/stm32l476g-disco/Kconfig index 448f763764..f778cbf561 100644 --- a/boards/stm32l476g-disco/Kconfig +++ b/boards/stm32l476g-disco/Kconfig @@ -22,6 +22,7 @@ config BOARD_STM32L476G_DISCO # Put other features for this board (in alphabetical order) select HAS_RIOTBOOT + select HAS_TINYUSB_DEVICE # Clock configuration select BOARD_HAS_LSE diff --git a/boards/stm32l476g-disco/Makefile.features b/boards/stm32l476g-disco/Makefile.features index 78f0a21701..8151764276 100644 --- a/boards/stm32l476g-disco/Makefile.features +++ b/boards/stm32l476g-disco/Makefile.features @@ -10,3 +10,4 @@ FEATURES_PROVIDED += periph_usbdev # Put other features for this board (in alphabetical order) FEATURES_PROVIDED += riotboot +FEATURES_PROVIDED += tinyusb_device diff --git a/cpu/esp32/Kconfig.esp32s3 b/cpu/esp32/Kconfig.esp32s3 index 83d7c47e57..ce91209943 100644 --- a/cpu/esp32/Kconfig.esp32s3 +++ b/cpu/esp32/Kconfig.esp32s3 @@ -24,6 +24,7 @@ config CPU_FAM_ESP32S3 select HAS_PERIPH_GPIO_LL_IRQ_LEVEL_TRIGGERED_HIGH select HAS_PERIPH_GPIO_LL_IRQ_LEVEL_TRIGGERED_LOW select HAS_PUF_SRAM + select HAS_TINYUSB_DEVICE select PACKAGE_ESP32_SDK if TEST_KCONFIG diff --git a/cpu/esp32/Makefile.dep b/cpu/esp32/Makefile.dep index 5ada3f39ab..f46f939e5d 100644 --- a/cpu/esp32/Makefile.dep +++ b/cpu/esp32/Makefile.dep @@ -167,6 +167,10 @@ ifneq (,$(filter shell,$(USEMODULE))) USEMODULE += ps endif +ifneq (,$(filter tinyusb_portable_espressif,$(USEMODULE))) + USEMODULE += esp_idf_usb +endif + ifneq (,$(filter esp_jtag,$(USEMODULE))) FEATURES_REQUIRED += esp_jtag endif diff --git a/cpu/esp32/esp-idf/Kconfig b/cpu/esp32/esp-idf/Kconfig index 7702960912..114701e809 100644 --- a/cpu/esp32/esp-idf/Kconfig +++ b/cpu/esp32/esp-idf/Kconfig @@ -14,6 +14,7 @@ config MODULE_ESP_IDF select MODULE_ESP_IDF_COMMON select MODULE_ESP_IDF_EFUSE select MODULE_ESP_IDF_SPI_FLASH if MODULE_MTD + select MODULE_ESP_IDF_USB if MODULE_TINYUSB_PORTABLE_ESPRESSIF help Espressif IoT Development Framework. diff --git a/cpu/esp32/include/sdkconfig_esp32s2.h b/cpu/esp32/include/sdkconfig_esp32s2.h index d80d3c2c1e..5ea8f87424 100644 --- a/cpu/esp32/include/sdkconfig_esp32s2.h +++ b/cpu/esp32/include/sdkconfig_esp32s2.h @@ -103,10 +103,12 @@ extern "C" { #define CONFIG_ESP_SLEEP_RTC_BUS_ISO_WORKAROUND 1 /** - * ESP32-S2 specific PHY configuration + * ESP32-S2 specific USB configuration */ +#ifdef MODULE_ESP_IDF_USB +#define CONFIG_ESP_PHY_ENABLE_USB 1 #define CONFIG_USB_OTG_SUPPORTED 1 - +#endif /** * ESP32-S2 specific SPI RAM configuration */ diff --git a/cpu/esp32/include/sdkconfig_esp32s3.h b/cpu/esp32/include/sdkconfig_esp32s3.h index 511061867e..d8be6c4437 100644 --- a/cpu/esp32/include/sdkconfig_esp32s3.h +++ b/cpu/esp32/include/sdkconfig_esp32s3.h @@ -107,10 +107,12 @@ extern "C" { #define CONFIG_ESP_SLEEP_GPIO_RESET_WORKAROUND 1 /** - * ESP32-S3 specific PHY configuration + * ESP32-S3 specific USB configuration */ +#ifdef MODULE_ESP_IDF_USB #define CONFIG_ESP_PHY_ENABLE_USB 1 #define CONFIG_USB_OTG_SUPPORTED 1 +#endif /** * ESP32-S3 specific SPI RAM configuration diff --git a/cpu/stm32/include/clk/f2f4f7/cfg_clock_default_100.h b/cpu/stm32/include/clk/f2f4f7/cfg_clock_default_100.h index ed1f54755c..6187b671e7 100644 --- a/cpu/stm32/include/clk/f2f4f7/cfg_clock_default_100.h +++ b/cpu/stm32/include/clk/f2f4f7/cfg_clock_default_100.h @@ -44,7 +44,7 @@ extern "C" { #endif #endif #ifndef CONFIG_CLOCK_PLL_N -#if IS_USED(MODULE_PERIPH_USBDEV) && defined(CPU_LINE_STM32F411xE) +#if IS_USED(MODULE_PERIPH_USBDEV_CLK) && defined(CPU_LINE_STM32F411xE) #if IS_ACTIVE(CONFIG_BOARD_HAS_HSE) && (CLOCK_HSE == MHZ(8)) #define CONFIG_CLOCK_PLL_N (96) #elif IS_ACTIVE(CONFIG_BOARD_HAS_HSE) && (CLOCK_HSE == MHZ(25)) @@ -60,7 +60,7 @@ extern "C" { #else #define CONFIG_CLOCK_PLL_N (50) #endif -#endif /* MODULE_PERIPH_USBDEV */ +#endif /* MODULE_PERIPH_USBDEV_CLK */ #endif #ifndef CONFIG_CLOCK_PLL_P #define CONFIG_CLOCK_PLL_P (2) diff --git a/cpu/stm32/include/clk/f2f4f7/cfg_clock_default_180.h b/cpu/stm32/include/clk/f2f4f7/cfg_clock_default_180.h index f9cf35c7fb..cc6f137245 100644 --- a/cpu/stm32/include/clk/f2f4f7/cfg_clock_default_180.h +++ b/cpu/stm32/include/clk/f2f4f7/cfg_clock_default_180.h @@ -46,7 +46,7 @@ extern "C" { #endif #endif #ifndef CONFIG_CLOCK_PLL_N -#if IS_USED(MODULE_PERIPH_USBDEV) && \ +#if IS_USED(MODULE_PERIPH_USBDEV_CLK) && \ (defined(CPU_LINE_STM32F405xx) || defined(CPU_LINE_STM32F407xx) || \ defined(CPU_LINE_STM32F415xx) || defined(CPU_LINE_STM32F417xx) || \ defined(CPU_LINE_STM32F427xx) || defined(CPU_LINE_STM32F429xx) || \ @@ -68,13 +68,13 @@ extern "C" { #else #define CONFIG_CLOCK_PLL_N (90) #endif -#endif /* MODULE_PERIPH_USBDEV */ +#endif /* MODULE_PERIPH_USBDEV_CLK */ #endif #ifndef CONFIG_CLOCK_PLL_P #define CONFIG_CLOCK_PLL_P (2) #endif #ifndef CONFIG_CLOCK_PLL_Q -#if IS_USED(MODULE_PERIPH_USBDEV) && \ +#if IS_USED(MODULE_PERIPH_USBDEV_CLK) && \ (defined(CPU_LINE_STM32F405xx) || defined(CPU_LINE_STM32F407xx) || \ defined(CPU_LINE_STM32F415xx) || defined(CPU_LINE_STM32F417xx) || \ defined(CPU_LINE_STM32F427xx) || defined(CPU_LINE_STM32F429xx) || \ diff --git a/cpu/stm32/include/tinyusb_hw_defaults.h b/cpu/stm32/include/tinyusb_hw_defaults.h new file mode 100644 index 0000000000..b669be43ab --- /dev/null +++ b/cpu/stm32/include/tinyusb_hw_defaults.h @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2022 Gunar Schorcht + * + * 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. + */ + +/** + * @ingroup pkg_tinyusb + * @ingroup cpu_stm32 + * @{ + * + * @file + * @brief STM32 specific default configurations for tinyUSB + * + * @author Gunar Schorcht + */ + +#ifndef TINYUSB_HW_DEFAULTS_H +#define TINYUSB_HW_DEFAULTS_H + +#include "periph_conf.h" + +#if !DOXYGEN + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @name Definition of ports used by tinyUSB host and device stack + * + * The tinyUSB device driver used for the STM32 USB-OTG controller supposes + * that the USB-OTG-FS port is port 0 and the USB-OTG-HS port is port 1. + * Therefore, the following default definitions can be used: + * + * - If both USB OTG FS and USB OTG HS ports are used, the device stack uses + * port 0 and the host stack uses port 1. + * - If only USB OTG HS is used, both the device and the host stack use port 1. + * - In all other cases, both the device and the host stack use port 0. + * This also applies if only the USB FS controller is used. + * + * @{ + */ +#if defined(DWC2_USB_OTG_HS_ENABLED) && defined(DWC2_USB_OTG_FS_ENABLED) + +#ifndef TINYUSB_TUD_RHPORT +#define TINYUSB_TUD_RHPORT 0 +#endif + +#ifndef TINYUSB_TUH_RHPORT +#define TINYUSB_TUH_RHPORT 1 +#endif + +#elif defined(DWC2_USB_OTG_HS_ENABLED) + +#ifndef TINYUSB_TUD_RHPORT +#define TINYUSB_TUD_RHPORT 1 +#endif + +#ifndef TINYUSB_TUH_RHPORT +#define TINYUSB_TUH_RHPORT 1 +#endif + +#else + +#ifndef TINYUSB_TUD_RHPORT +#define TINYUSB_TUD_RHPORT 0 +#endif + +#ifndef TINYUSB_TUH_RHPORT +#define TINYUSB_TUH_RHPORT 0 +#endif + +#endif +/** @} */ + +#ifdef USB_HS_PHYC +/** + * @brief Definition of HSE clock value + * + * If the CMSIS defines that the internal UTMI HS PHY is used, the Synopsys DWC2 + * driver needs the definition of the HSE clock value. + */ +#define HSE_VALUE CLOCK_HSE +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* !DOXYGEN */ +#endif /* TINYUSB_HW_DEFAULTS_H */ +/** @} */ diff --git a/cpu/stm32/stmclk/stmclk_f2f4f7.c b/cpu/stm32/stmclk/stmclk_f2f4f7.c index 64d05cd607..9459fffcf0 100644 --- a/cpu/stm32/stmclk/stmclk_f2f4f7.c +++ b/cpu/stm32/stmclk/stmclk_f2f4f7.c @@ -56,7 +56,7 @@ /* Determine if PLL is required, even if not used as SYSCLK This is the case when USB is used in application and PLLQ is configured to output 48MHz */ -#if IS_USED(MODULE_PERIPH_USBDEV) && (CLOCK_PLLQ == MHZ(48)) +#if IS_USED(MODULE_PERIPH_USBDEV_CLK) && (CLOCK_PLLQ == MHZ(48)) #define CLOCK_REQUIRE_PLLQ 1 #else #define CLOCK_REQUIRE_PLLQ 0 @@ -67,7 +67,7 @@ #if (defined(CPU_LINE_STM32F412Cx) || defined(CPU_LINE_STM32F412Rx) || \ defined(CPU_LINE_STM32F412Vx) || defined(CPU_LINE_STM32F412Zx) || \ defined(CPU_LINE_STM32F413xx) || defined(CPU_LINE_STM32F423xx)) && \ - IS_USED(MODULE_PERIPH_USBDEV) && !IS_ACTIVE(CLOCK_REQUIRE_PLLQ) + IS_USED(MODULE_PERIPH_USBDEV_CLK) && !IS_ACTIVE(CLOCK_REQUIRE_PLLQ) #define CLOCK_REQUIRE_PLLI2SR 1 #else /* Disable PLLI2S if USB is not required or is required but PLLQ cannot generate 48MHz clock */ @@ -78,14 +78,14 @@ PLLSAI is only enabled if no suitable 48MHz clock source can be generated with PLLQ */ #if (defined(CPU_LINE_STM32F446xx) || defined(CPU_LINE_STM32F469xx) || \ defined(CPU_LINE_STM32F479xx) || defined(CPU_FAM_STM32F7)) && \ - IS_USED(MODULE_PERIPH_USBDEV) && !IS_ACTIVE(CLOCK_REQUIRE_PLLQ) + IS_USED(MODULE_PERIPH_USBDEV_CLK) && !IS_ACTIVE(CLOCK_REQUIRE_PLLQ) #define CLOCK_REQUIRE_PLLSAIP 1 #else /* Disable PLLSAI if USB is not required or is required but PLLQ cannot generate 48MHz clock */ #define CLOCK_REQUIRE_PLLSAIP 0 #endif -#if IS_USED(MODULE_PERIPH_USBDEV) && \ +#if IS_USED(MODULE_PERIPH_USBDEV_CLK) && \ !(IS_ACTIVE(CLOCK_REQUIRE_PLLQ) || \ IS_ACTIVE(CLOCK_REQUIRE_PLLI2SR) || \ IS_ACTIVE(CLOCK_REQUIRE_PLLSAIP)) diff --git a/cpu/stm32/stmclk/stmclk_l4wx.c b/cpu/stm32/stmclk/stmclk_l4wx.c index d511a53f41..b58eaa3b1d 100644 --- a/cpu/stm32/stmclk/stmclk_l4wx.c +++ b/cpu/stm32/stmclk/stmclk_l4wx.c @@ -351,7 +351,7 @@ #endif /* periph_hwrng and periph_usbdev require a 48MHz clock source */ -#if IS_USED(MODULE_PERIPH_HWRNG) || IS_USED(MODULE_PERIPH_USBDEV) +#if IS_USED(MODULE_PERIPH_HWRNG) || IS_USED(MODULE_PERIPH_USBDEV_CLK) #if !IS_ACTIVE(CLOCK48MHZ_USE_PLLQ) && !IS_ACTIVE(CLOCK48MHZ_USE_MSI) && \ !IS_ACTIVE(CLOCK48MHZ_USE_HSI48) #error "No 48MHz clock source available, HWRNG cannot work" @@ -663,7 +663,7 @@ void stmclk_init_sysclk(void) gpio_init_af(GPIO_PIN(PORT_A, 8), GPIO_AF0); } -#if IS_USED(MODULE_PERIPH_USBDEV) && defined(RCC_APB1RSTR1_USBRST) +#if IS_USED(MODULE_PERIPH_USBDEV_CLK) && defined(RCC_APB1RSTR1_USBRST) RCC->APB1RSTR1 |= RCC_APB1RSTR1_USBRST; RCC->APB1RSTR1 &= ~RCC_APB1RSTR1_USBRST; #endif diff --git a/drivers/Makefile.dep b/drivers/Makefile.dep index 09f99693d3..239c53f5d3 100644 --- a/drivers/Makefile.dep +++ b/drivers/Makefile.dep @@ -137,6 +137,10 @@ ifneq (,$(filter periph_ptp_timer periph_ptp_speed_adjustment,$(FEATURES_USED))) FEATURES_REQUIRED += periph_ptp endif +ifneq (,$(filter periph_usbdev,$(USEMODULE))) + USEMODULE += periph_usbdev_clk +endif + ifneq (,$(filter pn532_i2c,$(USEMODULE))) FEATURES_REQUIRED += periph_i2c USEMODULE += pn532 diff --git a/drivers/periph_common/Kconfig b/drivers/periph_common/Kconfig index 4add675808..f0b90862fc 100644 --- a/drivers/periph_common/Kconfig +++ b/drivers/periph_common/Kconfig @@ -161,12 +161,24 @@ config MODULE_PERIPH_USBDEV bool "USBDEV peripheral driver" depends on HAS_PERIPH_USBDEV select MODULE_PERIPH_COMMON + select MODULE_PERIPH_USBDEV_CLK config MODULE_PERIPH_INIT_USBDEV bool "Auto initialize USBDEV peripheral" default y if MODULE_PERIPH_INIT depends on MODULE_PERIPH_USBDEV +config MODULE_PERIPH_USBDEV_CLK + bool + depends on HAS_PERIPH_USBDEV + help + Enable the USB device specific clock settings, if there are any + +config MODULE_PERIPH_INIT_USBDEV_CLK + bool + default y if MODULE_PERIPH_INIT && MODULE_PERIPH_USBDEV_CLK + depends on HAS_PERIPH_USBDEV + endif # TEST_KCONFIG config HAVE_SHARED_PERIPH_RTT_PERIPH_RTC diff --git a/pkg/Kconfig b/pkg/Kconfig index d983bf8782..4f0269d1a5 100644 --- a/pkg/Kconfig +++ b/pkg/Kconfig @@ -67,6 +67,7 @@ rsource "tiny-asn1/Kconfig" rsource "tinycbor/Kconfig" rsource "tinycrypt/Kconfig" rsource "tinydtls/Kconfig" +rsource "tinyusb/Kconfig" rsource "tinyvcdiff/Kconfig" rsource "tlsf/Kconfig" rsource "tweetnacl/Kconfig" diff --git a/pkg/tinyusb/Kconfig b/pkg/tinyusb/Kconfig new file mode 100644 index 0000000000..9d6b9797fb --- /dev/null +++ b/pkg/tinyusb/Kconfig @@ -0,0 +1,147 @@ +# Copyright (c) 2022 Gunar Schorcht +# +# This file is subject to the terms and conditions of the GNU Lesser +# General Public License v2.1. See the file LICENSE in the top level +# directory for more details. +# + +config HAS_TINYUSB_DEVICE + bool + help + Indicates that the hardware supports tinyUSB device stack + +config HAS_TINYUSB_HOST + bool + help + Indicates that the hardware supports tinyUSB host stack + +menuconfig PACKAGE_TINYUSB + bool "TinyUSB stack package" + depends on HAS_ARCH_32BIT + depends on HAS_TINYUSB_DEVICE || HAS_TINYUSB_HOST + select MODULE_PERIPH_USBDEV_CLK + select MODULE_SEMA + select MODULE_TINYUSB_COMMON + select MODULE_TINYUSB_CONTRIB + select MODULE_TINYUSB_HW + select MODULE_TINYUSB_PORTABLE_ESPRESSIF if CPU_FAM_ESP32S2 || CPU_FAM_ESP32S3 + select MODULE_TINYUSB_PORTABLE_SYNOPSYS_DWC2 if CPU_STM32 && CPU_FAM_F2 + select MODULE_TINYUSB_PORTABLE_SYNOPSYS_DWC2 if CPU_STM32 && CPU_FAM_F4 + select MODULE_TINYUSB_PORTABLE_SYNOPSYS_DWC2 if CPU_STM32 && CPU_FAM_F7 + select MODULE_TINYUSB_PORTABLE_SYNOPSYS_DWC2 if CPU_STM32 && CPU_FAM_H7 + select MODULE_TINYUSB_PORTABLE_SYNOPSYS_DWC2 if CPU_STM32 && CPU_FAM_L4 + select MODULE_TINYUSB_PORTABLE_STM32_FSEDV if CPU_STM32 && CPU_FAM_F0 + select MODULE_TINYUSB_PORTABLE_STM32_FSEDV if CPU_STM32 && CPU_FAM_F1 + select MODULE_TINYUSB_PORTABLE_STM32_FSEDV if CPU_STM32 && CPU_FAM_G4 + select MODULE_TINYUSB_PORTABLE_STM32_FSEDV if CPU_STM32 && CPU_FAM_L0 + select MODULE_TINYUSB_PORTABLE_STM32_FSEDV if CPU_STM32 && CPU_FAM_WB + select MODULE_ZTIMER_MSEC + help + tinyUSB is an open-source cross-platform USB Host/Device stack for + embedded systems. + +if PACKAGE_TINYUSB + +config MODULE_AUTO_INIT_TINYUSB + bool "Auto-initialize the tinyUSB package" + default y + depends on MODULE_AUTO_INIT + help + The tinyUSB stack including the used peripherals are initialized + automatically at startup. Additionally, the auto-initialization + starts the tinyUSB thread. + +config MODULE_TINYUSB_COMMON + bool + help + Common tinyUSB files + +config MODULE_TINYUSB_CONTRIB + bool + help + RIOT support for tinyUSB + +config MODULE_TINYUSB_HW + bool + help + tinyUSB hardware driver implementation + +config MODULE_TINYUSB_DEVICE + bool "Device Stack" + depends on HAS_TINYUSB_DEVICE + help + Select to enable tinyUSB device stack + +config MODULE_TINYUSB_HOST + bool "Host Stack" + depends on HAS_TINYUSB_HOST + help + Select to enable tinyUSB host stack + +config MODULE_TINYUSB_PORTABLE_ESPRESSIF + bool + help + tinyUSB driver for ESP32Sx is used + +config MODULE_TINYUSB_PORTABLE_SYNOPSYS_DWC2 + bool + help + tinyUSB Sysnopsys DCW2 driver is used + +config MODULE_TINYUSB_PORTABLE_STM32_FSDEV + bool + help + tinyUSB STM32 FS device driver is used + +menu "Device Classes" + config MODULE_TINYUSB_CLASS_AUDIO + bool "Audio Class 2.0 (UAC2)" + depends on MODULE_TINYUSB_DEVICE + + config MODULE_TINYUSB_CLASS_BTH + bool "Bluetooth Host Controller Interface (BTH HCI)" + depends on MODULE_TINYUSB_DEVICE + + config MODULE_TINYUSB_CLASS_CDC + bool "Communication Device Class (CDC)" + + config MODULE_TINYUSB_CLASS_DFU + bool "Device Firmware Update (DFU) Runtime" + depends on MODULE_TINYUSB_DEVICE + + config MODULE_TINYUSB_CLASS_DFU_RUNTIME + bool "Device Firmware Update (DFU)" + depends on MODULE_TINYUSB_DEVICE + + config MODULE_TINYUSB_CLASS_HID + bool "Human Interface Device (HID)" + + config MODULE_TINYUSB_CLASS_MSC + bool "Mass Storage Class (MSC)" + + config MODULE_TINYUSB_CLASS_MIDI + bool "Musical Instrument Digital Interface (MIDI)" + depends on MODULE_TINYUSB_DEVICE + + config MODULE_TINYUSB_CLASS_NET_ECM_RNDIS + bool "Network with RNDIS, Ethernet Control Model (ECM)" + depends on MODULE_TINYUSB_DEVICE + + config MODULE_TINYUSB_CLASS_NET_NCM + bool "Network with Network Control Model (NCM)" + depends on MODULE_TINYUSB_DEVICE + + config MODULE_TINYUSB_CLASS_USBTMC + bool "Test and Measurement Class (USBTMC)" + depends on MODULE_TINYUSB_DEVICE + + config MODULE_TINYUSB_CLASS_VENDOR + bool "Vendor-specific class support with generic IN & OUT endpoints" + + config MODULE_TINYUSB_CLASS_VIDEO + bool "Video class 1.5 (UVC)" + depends on MODULE_TINYUSB_DEVICE + +endmenu + +endif # PACKAGE_TINYUSB diff --git a/pkg/tinyusb/Makefile b/pkg/tinyusb/Makefile new file mode 100644 index 0000000000..591c244cca --- /dev/null +++ b/pkg/tinyusb/Makefile @@ -0,0 +1,78 @@ +PKG_NAME=tinyusb +PKG_URL=https://github.com/hathach/tinyusb +# TinyUSB 0.14.0 +PKG_VERSION=9e91b02ec7fb3502747b5c413a4824654fa7fc7e + +PKG_LICENSE=MIT + +include $(RIOTBASE)/pkg/pkg.mk + +PSRC = $(PKG_SOURCE_DIR)/src + +.PHONY: all + +all: $(filter tinyusb_%,$(USEMODULE)) + $(QQ)"$(MAKE)" -C $(PSRC) -f $(RIOTBASE)/Makefile.base MODULE=tinyusb + +tinyusb_contrib: + $(QQ)"$(MAKE)" -C $(RIOTPKG)/$(PKG_NAME)/contrib + +tinyusb_hw: + $(QQ)"$(MAKE)" -C $(RIOTPKG)/$(PKG_NAME)/hw + +tinyusb_class_audio: + $(QQ)"$(MAKE)" -C $(PSRC)/class/audio -f $(RIOTBASE)/Makefile.base MODULE=$@ + +tinyusb_class_bth: + $(QQ)"$(MAKE)" -C $(PSRC)/class/bth -f $(RIOTBASE)/Makefile.base MODULE=$@ + +tinyusb_class_cdc: + $(QQ)"$(MAKE)" -C $(PSRC)/class/cdc -f $(RIOTBASE)/Makefile.base MODULE=$@ + +tinyusb_class_dfu: + $(QQ)"$(MAKE)" -C $(PSRC)/class/dfu -f $(RIOTBASE)/Makefile.base MODULE=$@ + +tinyusb_class_dfu_runtime: + $(QQ)"$(MAKE)" -C $(PSRC)/class/dfu -f $(RIOTBASE)/Makefile.base MODULE=$@ + +tinyusb_class_hid: + $(QQ)"$(MAKE)" -C $(PSRC)/class/hid -f $(RIOTBASE)/Makefile.base MODULE=$@ + +tinyusb_class_midi: + $(QQ)"$(MAKE)" -C $(PSRC)/class/midi -f $(RIOTBASE)/Makefile.base MODULE=$@ + +tinyusb_class_msc: + $(QQ)"$(MAKE)" -C $(PSRC)/class/msc -f $(RIOTBASE)/Makefile.base MODULE=$@ + +tinyusb_class_net_ecm_rndis: + $(QQ)"$(MAKE)" -C $(PSRC)/class/net -f $(RIOTBASE)/Makefile.base MODULE=$@ + +tinyusb_class_net_ncm: + $(QQ)"$(MAKE)" -C $(PSRC)/class/net -f $(RIOTBASE)/Makefile.base MODULE=$@ + +tinyusb_class_usbtmc: + $(QQ)"$(MAKE)" -C $(PSRC)/class/usbtmc -f $(RIOTBASE)/Makefile.base MODULE=$@ + +tinyusb_class_vendor: + $(QQ)"$(MAKE)" -C $(PSRC)/class/vendor -f $(RIOTBASE)/Makefile.base MODULE=$@ + +tinyusb_class_video: + $(QQ)"$(MAKE)" -C $(PSRC)/class/video -f $(RIOTBASE)/Makefile.base MODULE=$@ + +tinyusb_common: + $(QQ)"$(MAKE)" -C $(PSRC)/common -f $(RIOTBASE)/Makefile.base MODULE=$@ + +tinyusb_device: + $(QQ)"$(MAKE)" -C $(PSRC)/device -f $(RIOTBASE)/Makefile.base MODULE=$@ + +tinyusb_host: + $(QQ)"$(MAKE)" -C $(PSRC)/host -f $(RIOTBASE)/Makefile.base MODULE=$@ + +tinyusb_portable_espressif: + $(QQ)"$(MAKE)" -C $(PSRC)/portable/espressif/esp32sx -f $(RIOTBASE)/Makefile.base MODULE=$@ + +tinyusb_portable_stm32_fsdev: + $(QQ)"$(MAKE)" -C $(PSRC)/portable/st/stm32_fsdev -f $(RIOTBASE)/Makefile.base MODULE=$@ + +tinyusb_portable_synopsys_dwc2: + $(QQ)"$(MAKE)" -C $(PSRC)/portable/synopsys/dwc2 -f $(RIOTBASE)/Makefile.base MODULE=$@ diff --git a/pkg/tinyusb/Makefile.dep b/pkg/tinyusb/Makefile.dep new file mode 100644 index 0000000000..eaaacc48c1 --- /dev/null +++ b/pkg/tinyusb/Makefile.dep @@ -0,0 +1,69 @@ +# tinyUSB mutexes use priority inheritance +# USEMODULE += core_mutex_priority_inheritance + +# tinyUSB modules always needed +USEMODULE += tinyusb_common +USEMODULE += tinyusb_contrib +USEMODULE += tinyusb_hw + +DEFAULT_MODULE += auto_init_tinyusb + +ifeq (,$(filter tinyusb_class_%,$(USEMODULE))) + $(error At least one tinyusb_class_* module has to be enabled) +endif + +# tinyUSB device stack has to be supported if tinyusb_device is used +ifneq (,$(filter tinyusb_device,$(USEMODULE))) + FEATURES_REQUIRED += tinyusb_device +endif + +# tinyUSB host stack has to be supported if tinyusb_host is used +ifneq (,$(filter tinyusb_host,$(USEMODULE))) + FEATURES_REQUIRED += tinyusb_host +endif + +# Following device classes work only with tinyUSB device stack +ifneq (,$(filter tinyusb_class_audio,$(USEMODULE))) + FEATURES_REQUIRED += tinyusb_device +endif +ifneq (,$(filter tinyusb_class_bth,$(USEMODULE))) + FEATURES_REQUIRED += tinyusb_device +endif +ifneq (,$(filter tinyusb_class_dfu,$(USEMODULE))) + FEATURES_REQUIRED += tinyusb_device +endif +ifneq (,$(filter tinyusb_class_dfu_runtime,$(USEMODULE))) + FEATURES_REQUIRED += tinyusb_device +endif +ifneq (,$(filter tinyusb_class_midi,$(USEMODULE))) + FEATURES_REQUIRED += tinyusb_device +endif +ifneq (,$(filter tinyusb_class_net_ecm_rndis,$(USEMODULE))) + FEATURES_REQUIRED += tinyusb_device +endif +ifneq (,$(filter tinyusb_class_net_ncm,$(USEMODULE))) + FEATURES_REQUIRED += tinyusb_device +endif +ifneq (,$(filter tinyusb_class_usbtmc,$(USEMODULE))) + FEATURES_REQUIRED += tinyusb_device +endif +ifneq (,$(filter tinyusb_class_video,$(USEMODULE))) + FEATURES_REQUIRED += tinyusb_device +endif + +# tinyUSB hardware driver selection +ifneq (,$(filter esp32s2 esp32s3,$(CPU_FAM))) + USEMODULE += tinyusb_portable_espressif +else ifeq (stm32,$(CPU)) + ifneq (,$(filter f2 f4 f7 h7 l4,$(CPU_FAM))) + USEMODULE += tinyusb_portable_synopsys_dwc2 + else ifneq (,$(filter f0 f1 g4 l0 wb,$(CPU_FAM))) + # TODO not yet working, the driver has to be ported + USEMODULE += tinyusb_portable_stm32_fsdev + endif +endif + +# other module dependencies +USEMODULE += periph_usbdev_clk +USEMODULE += sema +USEMODULE += ztimer_msec diff --git a/pkg/tinyusb/Makefile.include b/pkg/tinyusb/Makefile.include new file mode 100644 index 0000000000..ff2756da72 --- /dev/null +++ b/pkg/tinyusb/Makefile.include @@ -0,0 +1,21 @@ +INCLUDES += -I$(RIOTBASE)/pkg/tinyusb/contrib +INCLUDES += -I$(RIOTBASE)/pkg/tinyusb/contrib/include +INCLUDES += -I$(RIOTBASE)/pkg/tinyusb/hw/include +INCLUDES += -I$(PKGDIRBASE)/tinyusb/src + +CFLAGS += -DCFG_TUSB_OS=OPT_OS_CUSTOM +CFLAGS += -Wno-format-nonliteral + +ifeq (esp32s2,$(CPU_FAM)) + CFLAGS += -DCFG_TUSB_MCU=OPT_MCU_ESP32S2 +else ifeq (esp32s3,$(CPU_FAM)) + CFLAGS += -DCFG_TUSB_MCU=OPT_MCU_ESP32S3 +else ifeq (stm32,$(CPU)) + CFLAGS += -DCFG_TUSB_MCU=OPT_MCU_STM32$(call uppercase_and_underscore,$(CPU_FAM)) +else + $(error CPU $(CPU) or CPU family $(CPU_FAM) not supported) +endif + +ifneq (,$(filter tinyusb_class_net_ecm_rndis,$(USEMODULE))) + INCLUDES += -I$(PKGDIRBASE)/tinyusb/lib/networking +endif diff --git a/pkg/tinyusb/contrib/Makefile b/pkg/tinyusb/contrib/Makefile new file mode 100644 index 0000000000..15d741bf25 --- /dev/null +++ b/pkg/tinyusb/contrib/Makefile @@ -0,0 +1,3 @@ +MODULE = tinyusb_contrib + +include $(RIOTBASE)/Makefile.base diff --git a/pkg/tinyusb/contrib/include/tinyusb.h b/pkg/tinyusb/contrib/include/tinyusb.h new file mode 100644 index 0000000000..7919add266 --- /dev/null +++ b/pkg/tinyusb/contrib/include/tinyusb.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2022 Gunar Schorcht + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup pkg_tinyusb + * @{ + * + * @file + * @brief TinyUSB API + * + * @author Gunar Schorcht + */ + +#ifndef TINYUSB_H +#define TINYUSB_H + +#include "periph_conf.h" +#include "tinyusb_hw_defaults.h" + +#ifndef TINYUSB_THREAD_STACKSIZE_MAIN +/** Stack size used for the tinyUSB thread */ +#define TINYUSB_THREAD_STACKSIZE (THREAD_STACKSIZE_DEFAULT) +#endif + +#ifndef TINYUSB_PRIORITY +/** Priority used for the tinyUSB thread */ +#define TINYUSB_PRIORITY (2) +#endif + +#ifndef TINYUSB_TUD_RHPORT +/** tinyUSB RHPort number used for the device stack, default value is 0 */ +#define TINYUSB_TUD_RHPORT 0 +#endif + +#ifndef TINYUSB_TUH_RHPORT +/** tinyUSB RHPort number used for the host stack, defaults value is 0 */ +#define TINYUSB_TUH_RHPORT 0 +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Initialize the tinyUSB stack including used peripherals and start the tinyUSB thread + * + * @return 0 on success + * @return -ENODEV if peripherals couldn't be initialized + * @return -EINVAL or -EOVERFLOW if the thread couldn't be created + */ +int tinyusb_setup(void); + +#ifdef __cplusplus +} +#endif + +#endif /* TINYUSB_H */ +/** @} */ diff --git a/pkg/tinyusb/contrib/include/tinyusb_config.h b/pkg/tinyusb/contrib/include/tinyusb_config.h new file mode 100644 index 0000000000..55ec032e98 --- /dev/null +++ b/pkg/tinyusb/contrib/include/tinyusb_config.h @@ -0,0 +1,306 @@ +/* + * Copyright (C) 2019 Ha Thach (tinyusb.org) + * 2022 Gunar Schorcht + * + * 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. + */ + +/** + * @ingroup pkg_tinyusb + * @{ + * + * @file + * @brief TinyUSB default configurations + * + * @author Gunar Schorcht + */ + +#ifndef TINYUSB_CONFIG_H +#define TINYUSB_CONFIG_H + +#include "tusb_config.h" /* defined by the application */ +#include "tinyusb.h" + +#if !DOXYGEN + +/** + * @name Common tinyUSB configurations + * @{ + */ +/** Sanity check, the MCU must be defined */ +#ifndef CFG_TUSB_MCU +#error CFG_TUSB_MCU must be defined +#endif + +/** RIOT provides the custom OS API */ +#define CFG_TUSB_OS OPT_OS_CUSTOM + +/** Debug log level */ +#ifndef CFG_TUSB_DEBUG +#define CFG_TUSB_DEBUG 0 +#endif + +/** + * @brief DMA memory section and alignment + * + * USB DMA on some MCUs can only access a specific SRAM region with restriction + * on alignment. + * - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") )) + * - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4))) + */ +#ifndef CFG_TUSB_MEM_SECTION +#define CFG_TUSB_MEM_SECTION +#endif + +#ifndef CFG_TUSB_MEM_ALIGN +#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4))) +#endif + +/** @} */ + +/** + * @name Common device configurations + * @{ + */ +#define CFG_TUD_ENABLED MODULE_TINYUSB_DEVICE + +#ifndef CFG_TUD_MAX_SPEED +#define CFG_TUD_MAX_SPEED OPT_MODE_DEFAULT_SPEED +#endif + +#ifndef CFG_TUD_ENDPOINT0_SIZE +#define CFG_TUD_ENDPOINT0_SIZE 64 +#endif + +#ifndef CFG_TUD_AUDIO +#if defined(MODULE_TINYUSB_DEVICE) && defined(MODULE_TINYUSB_CLASS_AUDIO) +#define CFG_TUD_AUDIO 1 +#else +#define CFG_TUD_AUDIO 0 +#endif +#endif + +#ifndef CFG_TUD_BTH +#if defined(MODULE_TINYUSB_DEVICE) && defined(MODULE_TINYUSB_CLASS_BTH) +#define CFG_TUD_BTH 1 +#else +#define CFG_TUD_BTH 0 +#endif +#endif /* CFG_TUD_BTH */ + +#ifndef CFG_TUD_CDC +#if defined(MODULE_TINYUSB_DEVICE) && defined(MODULE_TINYUSB_CLASS_CDC) +#define CFG_TUD_CDC 1 +#else +#define CFG_TUD_CDC 0 +#endif +#endif /* CFG_TUD_CDC */ + +#ifndef CFG_TUD_DFU +#if defined(MODULE_TINYUSB_DEVICE) && defined(MODULE_TINYUSB_CLASS_DFU) +#define CFG_TUD_DFU 1 +#else +#define CFG_TUD_DFU 0 +#endif +#endif /* CFG_TUD_DFU */ + +#ifndef CFG_TUD_DFU_RUNTIME +#if defined(MODULE_TINYUSB_DEVICE) && defined(MODULE_TINYUSB_CLASS_DFU_RUNTIME) +#define CFG_TUD_DFU_RUNTIME 1 +#else +#define CFG_TUD_DFU_RUNTIME 0 +#endif +#endif /* CFG_TUD_DFU */ + +#ifndef CFG_TUD_HID +#if defined(MODULE_TINYUSB_DEVICE) && defined(MODULE_TINYUSB_CLASS_HID) +#define CFG_TUD_HID 1 +#else +#define CFG_TUD_HID 0 +#endif +#endif /* CFG_TUD_HID */ + +#ifndef CFG_TUD_MIDI +#if defined(MODULE_TINYUSB_DEVICE) && defined(MODULE_TINYUSB_CLASS_MIDI) +#define CFG_TUD_MIDI 1 +#else +#define CFG_TUD_MIDI 0 +#endif +#endif /* CFG_TUD_MIDI */ + +#ifndef CFG_TUD_MSC +#if defined(MODULE_TINYUSB_DEVICE) && defined(MODULE_TINYUSB_CLASS_MSC) +#define CFG_TUD_MSC 1 +#else +#define CFG_TUD_MSC 0 +#endif +#endif /* CFG_TUD_MSC */ + +#ifndef CFG_TUD_ECM_RNDIS +#if defined(MODULE_TINYUSB_DEVICE) && defined(MODULE_TINYUSB_CLASS_NET_ECM_RNDIS) +#define CFG_TUD_ECM_RNDIS 1 +#else +#define CFG_TUD_ECM_RNDIS 0 +#endif +#endif /* CFG_TUD_ECM_RNDIS */ + +#ifndef CFG_TUD_NCM +#if defined(MODULE_TINYUSB_DEVICE) && defined(MODULE_TINYUSB_CLASS_NET_NCM) +#define CFG_TUD_NCM 1 +#else +#define CFG_TUD_NCM 0 +#endif +#endif /* CFG_TUD_NCM */ + +#ifndef CFG_TUD_USBMTC +#if defined(MODULE_TINYUSB_DEVICE) && defined(MODULE_TINYUSB_CLASS_USBMTC) +#define CFG_TUD_USBMTC 1 +#else +#define CFG_TUD_USBMTC 0 +#endif +#endif /* CFG_TUD_USBMTC */ + +#ifndef CFG_TUD_VENDOR +#if defined(MODULE_TINYUSB_DEVICE) && defined(MODULE_TINYUSB_CLASS_VENDOR) +#define CFG_TUD_VENDOR 1 +#else +#define CFG_TUD_VENDOR 0 +#endif +#endif /* CFG_TUD_VENDOR */ + +#ifndef CFG_TUD_VIDEO +#if defined(MODULE_TINYUSB_DEVICE) && defined(MODULE_TINYUSB_CLASS_VIDEO) +#define CFG_TUD_VIDEO 1 +#else +#define CFG_TUD_VIDEO 0 +#endif +#endif /* CFG_TUD_VIDEO */ + +/** @} */ + +/** + * @name Common host configurations + * @{ + */ +#define CFG_TUH_ENABLED MODULE_TINYUSB_HOST + +#ifndef CFG_TUH_MAX_SPEED +#define CFG_TUH_MAX_SPEED OPT_MODE_DEFAULT_SPEED +#endif + +#ifndef CFG_TUH_ENUMERATION_BUFSIZE +#define CFG_TUH_ENUMERATION_BUFSIZE 256 +#endif + +/** Hub typically has 4 ports */ +#ifndef CFG_TUH_DEVICE_MAX +#define CFG_TUH_DEVICE_MAX (CFG_TUH_HUB ? 4 : 1) +#endif + +#ifndef CFG_TUH_CDC +#if defined(MODULE_TINYUSB_HOST) && defined(MODULE_TINYUSB_CLASS_CDC) +#define CFG_TUH_CDC 1 +#else +#define CFG_TUH_CDC 0 +#endif +#endif /* CFG_TUH_CDC */ + +#ifndef CFG_TUH_HID +#if defined(MODULE_TINYUSB_HOST) && defined(MODULE_TINYUSB_CLASS_HID) +#define CFG_TUH_HID 1 +#else +#define CFG_TUH_HID 0 +#endif +#endif /* CFG_TUH_HID */ + +#ifndef CFG_TUH_MSC +#if defined(MODULE_TINYUSB_HOST) && defined(MODULE_TINYUSB_CLASS_MSC) +#define CFG_TUH_MSC 1 +#else +#define CFG_TUH_MSC 0 +#endif +#endif /* CFG_TUH_MSC */ + +#ifndef CFG_TUD_VENDOR +#if defined(MODULE_TINYUSB_HOST) && defined(MODULE_TINYUSB_CLASS_VENDOR) +#define CFG_TUH_VENDOR 1 +#else +#define CFG_TUH_VENDOR 0 +#endif +#endif /* CFG_TUD_VENDOR */ + +/** @} */ + +/** + * @name Typical required CDC device class configurations + * @{ + */ +/** CDC RX FIFO size */ +#ifndef CFG_TUD_CDC_RX_BUFSIZE +#define CFG_TUD_CDC_RX_BUFSIZE CFG_TUD_CDC_EP_BUFSIZE +#endif + +/** CDC RX FIFO size */ +#ifndef CFG_TUD_CDC_TX_BUFSIZE +#define CFG_TUD_CDC_TX_BUFSIZE CFG_TUD_CDC_EP_BUFSIZE +#endif + +/** @} */ + +/** + * @name Typical required DFU device class configurations + * @{ + */ +#ifndef CFG_TUD_DFU_XFER_BUFSIZE +#define CFG_TUD_DFU_XFER_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) +#endif +/** @} */ + +/** + * @name Typical required MIDI device class configurations + * @{ + */ +#ifndef CFG_TUD_MIDI_RX_BUFSIZE +#define CFG_TUD_MIDI_RX_BUFSIZE CFG_TUD_MIDI_EP_BUFSIZE +#endif + +#ifndef CFG_TUD_MIDI_TX_BUFSIZE +#define CFG_TUD_MIDI_TX_BUFSIZE CFG_TUD_MIDI_EP_BUFSIZE +#endif +/** @} */ + +/** + * @name Typical required MSC device class configurations + * @{ + */ +#ifndef CFG_TUD_MSC_EP_BUFSIZE +#define CFG_TUD_MSC_EP_BUFSIZE 512 +#endif +/** @} */ +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* !DOXYGEN */ +#endif /* TINYUSB_CONFIG_H */ +/** @} */ diff --git a/pkg/tinyusb/contrib/include/tusb_os_custom.h b/pkg/tinyusb/contrib/include/tusb_os_custom.h new file mode 100644 index 0000000000..930170aade --- /dev/null +++ b/pkg/tinyusb/contrib/include/tusb_os_custom.h @@ -0,0 +1,255 @@ +/* + * Copyright (C) 2022 Gunar Schorcht + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup pkg_tinyusb + * @{ + * + * @file + * @brief TinyUSB OS Abstraction Layer for RIOT + * + * @author Gunar Schorcht + */ + +#ifndef TUSB_OS_CUSTOM_H +#define TUSB_OS_CUSTOM_H + +#include "mutex.h" +#include "sema.h" +#include "ztimer.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if !DOXYGEN + +/* set to 1 to use cancelable mutex in osal_mutex and osal_queue */ +#ifndef TINYUSB_OSAL_MUTEX_CANCELABLE +#define TINYUSB_OSAL_MUTEX_CANCELABLE 0 +#endif + +/** + * Task API + */ + +TU_ATTR_ALWAYS_INLINE static inline void osal_task_delay(uint32_t msec) +{ + ztimer_sleep(ZTIMER_MSEC, msec); +} + +/** + * Semaphore API + * + * This API is only used by RNDIS-CDC. + */ + +typedef sema_t osal_semaphore_def_t; /* semaphore */ +typedef sema_t *osal_semaphore_t; /* semaphore handle */ + +TU_ATTR_ALWAYS_INLINE +static inline osal_semaphore_t osal_semaphore_create(osal_semaphore_def_t* semdef) +{ + sema_create(semdef, 0); + return (osal_semaphore_t)semdef; +} + +TU_ATTR_ALWAYS_INLINE +static inline bool osal_semaphore_post(osal_semaphore_t sem_hdl, bool in_isr) +{ + (void)in_isr; /* hasn't to be considered since RIOT doesn't block in sema_post */ + return sema_post(sem_hdl) == 0; +} + +TU_ATTR_ALWAYS_INLINE +static inline bool osal_semaphore_wait(osal_semaphore_t sem_hdl, uint32_t msec) +{ + assert(0); + return sema_wait_timed_ztimer(sem_hdl, ZTIMER_MSEC, msec) == 0; +} + +TU_ATTR_ALWAYS_INLINE static inline void osal_semaphore_reset(osal_semaphore_t const sem_hdl) +{ + (void)sem_hdl; + /* TODO, function seems to be removed anyway */ +} + +/** Mutex API (priority inheritance) */ +typedef mutex_t osal_mutex_def_t; /* RIOT mutex */ +typedef mutex_t *osal_mutex_t; /* RIOT mutex handle */ + +TU_ATTR_ALWAYS_INLINE +static inline osal_mutex_t osal_mutex_create(osal_mutex_def_t* mdef) +{ + assert(mdef != NULL); + mutex_init((mutex_t *)mdef); + return (osal_mutex_t)mdef; +} + +#if TINYUSB_OSAL_MUTEX_CANCELABLE +static void _osal_mutex_lock_timeout(void *arg) +{ + mutex_cancel(arg); +} +#endif + +TU_ATTR_ALWAYS_INLINE +static inline bool osal_mutex_lock(osal_mutex_t mutex_hdl, uint32_t msec) +{ + assert(mutex_hdl); +#if TINYUSB_OSAL_MUTEX_CANCELABLE + mutex_cancel_t _mc = mutex_cancel_init(mutex_hdl); + + ztimer_t _timer = { .callback = _osal_mutex_lock_timeout, .arg = &_mc }; + ztimer_set(ZTIMER_MSEC, &_timer, msec); + + return mutex_lock_cancelable(&_mc) == 0; +#else + assert(msec == OSAL_TIMEOUT_WAIT_FOREVER); + mutex_lock(mutex_hdl); + return true; +#endif +} + +TU_ATTR_ALWAYS_INLINE +static inline bool osal_mutex_unlock(osal_mutex_t mutex_hdl) +{ + assert(mutex_hdl); + mutex_unlock(mutex_hdl); + return true; +} + +/** + * Queue API + */ + +#define OSAL_QUEUE_DEF(_int_set, _name, _depth, _type) \ + /* _int_set is not used in RTOS */ \ + static _type _name##_##q_items[_depth]; /* queue item data storage */ \ + osal_queue_def_t _name = { \ + .buffer = _name##_##q_items, \ + .size = sizeof(_type), \ + .depth = _depth, \ + }; + +typedef struct { + list_node_t node; + void *data; +} osal_queue_entry; + +typedef struct { + void *buffer; /* buffer used for queue item data */ + uint16_t size; /* queue item size */ + uint16_t depth; /* maximum number of queue items */ + uint16_t front; + uint16_t tail; + sema_t smphr; /* semaphore value represents the queue fill level */ +} osal_queue_def_t; + +typedef osal_queue_def_t *osal_queue_t; + +TU_ATTR_ALWAYS_INLINE static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) +{ + assert(qdef != NULL); + + qdef->front = 0; + qdef->tail = 0; + + sema_create(&qdef->smphr, 0); + + return (osal_queue_t)qdef; +} + +TU_ATTR_ALWAYS_INLINE +static inline bool osal_queue_send(osal_queue_t qhdl, void const * data, bool in_isr) +{ + assert(qhdl != NULL); + assert(data != NULL); + + if (sema_get_value(&qhdl->smphr) == qhdl->depth) { + /* queue is full */ + if (in_isr) { + /* return in case of ISR */ + return false; + } + /* We do not block the sending thread when `osal_queue_send` is called + * from a thread context and the queue is full. The call of function + * `osal_queue_send` is usually interrupt-driven and must not block + * anyway. There is only one exception in `src/class/msc/msc_device.c` + * where it is called in thread context. However, since the call of + * `osal_queue_send` would then be made in the same thread context as + * the call of the unlocking function `osal_queue_receive`, using a + * mutex to block the sending thread would not work here anyway. + * Therefore, we return with false in all cases when `NDEBUG` is + * defined, as most other implementations of `osal_queue_send` do, + * or point out the problem with assertion. */ +#ifdef NDEBUG + return false; +#else + assert(0); +#endif + } + + /* copy the data to the queue item data */ + memcpy(qhdl->buffer + (qhdl->tail * (qhdl->size)), data, qhdl->size); + /* update write pointer */ + qhdl->tail = (qhdl->tail + 1) % qhdl->depth; + + /* unlock a possibly waiting receiving thread */ + sema_post(&qhdl->smphr); + + return true; +} + +#if TINYUSB_OSAL_MUTEX_CANCELABLE +static void _osal_queue_lock_timeout(void *arg) +{ + mutex_cancel(arg); +} +#endif + +TU_ATTR_ALWAYS_INLINE +static inline bool osal_queue_receive(osal_queue_t qhdl, void* data, uint32_t msec) +{ + assert(qhdl != NULL); + assert(data != NULL); + + (void)msec; + /* In RIOT we use only `tusd_task` and `tush_task` functions which call + * `osal_queue_receive` with `OSAL_TIMEOUT_WAIT_FOREVER` (`UINT32_MAX`). + * Therefore we do not use `msec` and just call `sema_wait` without timeout + * handling here. */ + if (sema_wait(&qhdl->smphr) != 0) { + /* timeout error or any other semaphore error on receiving */ + return false; + } + + /* at least one item should be in the queue now */ + assert(qhdl->front != qhdl->tail); + + /* copy data from queue item data */ + memcpy(data, qhdl->buffer + (qhdl->front * (qhdl->size)), qhdl->size); + /* update read pointer */ + qhdl->front = (qhdl->front + 1) % qhdl->depth; + + return true; +} + +TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_empty(osal_queue_t qhdl) +{ + assert(qhdl != NULL); + return sema_get_value(&qhdl->smphr) == 0; +} + +#ifdef __cplusplus +} +#endif + +#endif /* !DOXYGEN */ +#endif /* TUSB_OS_CUSTOM_H */ +/** @} */ diff --git a/pkg/tinyusb/contrib/tinyusb.c b/pkg/tinyusb/contrib/tinyusb.c new file mode 100644 index 0000000000..e4f3ecf3d1 --- /dev/null +++ b/pkg/tinyusb/contrib/tinyusb.c @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2022 Gunar Schorcht + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +#include "kernel_defines.h" +#include "thread.h" + +#include "tusb.h" +#include "device/usbd.h" +#include "host/usbh.h" + +#include "tinyusb.h" +#include "tinyusb_hw.h" + +#if IS_USED(MODULE_AUTO_INIT) +#include "auto_init_utils.h" +#endif + +#define ENABLE_DEBUG 0 +#include "debug.h" + +static void *_tinyusb_thread_impl(void *arg) +{ + (void)arg; + + if (IS_USED(MODULE_TINYUSB_DEVICE)) { + if (!tud_init(TINYUSB_TUD_RHPORT)) { + DEBUG("tinyUSB device stack couldn't be initialized\n"); + assert(0); + } + DEBUG("tinyUSB device stack initialized\n"); + } + + if (IS_USED(MODULE_TINYUSB_HOST)) { + if (!tuh_init(TINYUSB_TUH_RHPORT)) { + DEBUG("tinyUSB host stack couldn't be initialized\n"); + assert(0); + } + DEBUG("tinyUSB host stack initialized\n"); + } + + while (1) { + if (IS_USED(MODULE_TINYUSB_DEVICE)) { + /* call tinyUSB device task blocking */ + tud_task(); + DEBUG("tinyUSB device task executed\n"); + } + if (IS_USED(MODULE_TINYUSB_HOST)) { + /* call tinyUSB device task blocking */ + tuh_task(); + DEBUG("tinyUSB host task executed\n"); + } + } + + return NULL; +} + +static char _tinyusb_thread_stack[TINYUSB_THREAD_STACKSIZE]; + +int tinyusb_setup(void) +{ + int res; + + if ((res = tinyusb_hw_init()) != 0) { + DEBUG("tinyUSB peripherals couldn't be initialized\n"); + return res; + } + DEBUG("tinyUSB peripherals initialized\n"); + + if ((res = thread_create(_tinyusb_thread_stack, + sizeof(_tinyusb_thread_stack), + TINYUSB_PRIORITY, + THREAD_CREATE_WOUT_YIELD | THREAD_CREATE_STACKTEST, + _tinyusb_thread_impl, NULL, "tinyusb")) < 0) { + DEBUG("tinyUSB thread couldn't be created, reason %d\n", res); + return res; + } + DEBUG("tinyUSB thread created\n"); + + return 0; +} + +void tinyusb_auto_init(void) +{ + tinyusb_setup(); +} + +#if IS_USED(MODULE_AUTO_INIT_TINYUSB) +AUTO_INIT(tinyusb_auto_init, AUTO_INIT_PRIO_MOD_TINYUSB); +#endif diff --git a/pkg/tinyusb/doc.txt b/pkg/tinyusb/doc.txt new file mode 100644 index 0000000000..7933e36a54 --- /dev/null +++ b/pkg/tinyusb/doc.txt @@ -0,0 +1,82 @@ +/** + * @defgroup pkg_tinyusb TinyUSB package + * @ingroup pkg + * @brief Provides the tinyUSB stack as package + * @author Gunar Schorcht + * @see https://github.com/hathach/tinyusb + * + * # TinyUSB + * + * tinyUSB is an open-source cross-platform USB Host/Device stack for + * embedded systems. + * + * # Usage + * + * Add the following entries to your application makefile: + * - Enable tinyUSB package + * ```makefile + * USEPKG += tinyusb + * ``` + * - Select whether to use the tinyUSB device stack or the tinyUSB host stack or both: + * ```makefile + * USEMODULE += tinyusb_device + * ``` + * - Select the device/host classes to be used, for example: + * ```makefile + * USEMODULE += tinyusb_class_cdc tinyusb_class_msc + * ``` + * + * Either add `tinyusb_setup()` to your main function to explicitly initialize + * the tinyUSB stack including the used peripherals and start the tinyUSB + * thread, or use the `auto_init` module (**default**). + * + * ```c + * int main(void) + * { + * ... + * // If auto-initialization is not used (module `auto_init`), + * // initialize the tinyUSB stack including used peripherals and + * // start the tinyUSB thread. Auto-initialization is used by default. + * tinyusb_setup(); + * + * while (1) { + * ... + * } + * + * return 0; + * } + * ``` + * + * Create a file `tusb_config.h` in your application directory which includes + * at least the file `tinyusb_config.h` from the tinyUSB package. This file is + * required by the tinyUSB stack and can be used to override the default + * configuration defined in `tinyusb_config.h`. + * ```c + * #define CFG_TUD_CDC 2 + * #define CFG_TUD_CDC_EP_BUFSIZE 128 + * + * #include "tinyusb_config.h" + * ``` + * + * Add the application path to the include paths at the end of your + * application's Makefile. This is necessary so that the tinyUSB stack + * uses the file `tusb_config.h` from your application directory and thus the + * file `tinyusb_config.h` from the tinyUSB package. + * ```makefile + * USEPKG += tinyusb + * USEMODULE += tinyusb_class_cdc + * USEMODULE += tinyusb_class_msc + * USEMODULE += tinyusb_device + * + * include $(RIOTBASE)/Makefile.include + * + * INCLUDES += -I$(APPDIR) + * ``` + * + * Implement required device descriptors and descriptor callbacks as well as + * the callbacks of the enabled classes. + * + * Please refer `$RIOTBASE/tests/pkg_tinyusb_cdc_msc` and the + * [tinyUSB documentation](https://docs.tinyusb.org/en/latest/reference/getting_started.html) + * for details. + */ diff --git a/pkg/tinyusb/hw/Makefile b/pkg/tinyusb/hw/Makefile new file mode 100644 index 0000000000..b18b9ec0e5 --- /dev/null +++ b/pkg/tinyusb/hw/Makefile @@ -0,0 +1,5 @@ +MODULE = tinyusb_hw + +SRC = hw_$(CPU).c + +include $(RIOTBASE)/Makefile.base diff --git a/pkg/tinyusb/hw/hw_esp32.c b/pkg/tinyusb/hw/hw_esp32.c new file mode 100644 index 0000000000..a0ebe80cfe --- /dev/null +++ b/pkg/tinyusb/hw/hw_esp32.c @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2022 Gunar Schorcht + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup pkg_tinyusb + * @brief + * @{ + * + * @brief tinyUSB hardware driver for ESP32x SoCs + * @author Gunar Schorcht + */ + +#include + +#include "esp_err.h" +#include "esp_private/usb_phy.h" + +#include "log.h" + +static usb_phy_handle_t phy_hdl; + +int tinyusb_hw_init(void) +{ + usb_phy_config_t phy_conf = { + .controller = USB_PHY_CTRL_OTG, + .otg_mode = USB_OTG_MODE_DEVICE, + .target = USB_PHY_TARGET_INT, /* only internal PHY supported */ + }; + + if (usb_new_phy(&phy_conf, &phy_hdl) != ESP_OK) { + LOG_TAG_ERROR("usb", "Install USB PHY failed"); + return -ENODEV; + } + + return 0; +} diff --git a/pkg/tinyusb/hw/hw_stm32.c b/pkg/tinyusb/hw/hw_stm32.c new file mode 100644 index 0000000000..e8e9e91ed9 --- /dev/null +++ b/pkg/tinyusb/hw/hw_stm32.c @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2022 Gunar Schorcht + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup pkg_tinyusb + * @brief + * @{ + * + * @brief tinyUSB hardware driver for STM32 MCUs + * @author Gunar Schorcht + */ + +#include + +#include "periph_conf.h" +#include "periph/gpio.h" +#include "periph/pm.h" + +#include "tusb.h" +#include "device/usbd.h" +#include "host/usbh.h" + +static int tinyusb_hw_init_dev(const dwc2_usb_otg_fshs_config_t *conf) +{ + /* Block both STOP and STANDBY, TODO STOP is unblocked during USB suspend + * status */ + pm_block(STM32_PM_STOP); + pm_block(STM32_PM_STANDBY); + + /* Enable the clock to the peripheral */ + periph_clk_en(conf->ahb, conf->rcc_mask); + + /* Enables clock on the GPIO bus */ + gpio_init(conf->dp, GPIO_IN); + gpio_init(conf->dm, GPIO_IN); + /* Configure AF for the pins */ + gpio_init_af(conf->dp, conf->af); + gpio_init_af(conf->dm, conf->af); + +#if 0 /* TODO we don't use USB ID pin for now */ + gpio_init(conf->id, GPIO_IN); +#endif + +#ifdef USB_OTG_GCCFG_NOVBUSSENS +#if 0 /* TODO V_USB sensing pin */ + gpio_init(conf->vbus, GPIO_OD_PU); + gpio_init_af(conf->vbus, conf->af); + + USB_OTG_GlobalTypeDef *global_regs = + (USB_OTG_GlobalTypeDef *)(conf->periph + USB_OTG_GLOBAL_BASE); + + global_regs->GCCFG &= ~USB_OTG_GCCFG_NOVBUSSENS; + global_regs->GCCFG |= USB_OTG_GCCFG_VBUSBSEN; +#else + /* Enable no Vbus sensing and enable `Power Down Disable` */ + USB_OTG_GlobalTypeDef *global_regs = + (USB_OTG_GlobalTypeDef *)(conf->periph + USB_OTG_GLOBAL_BASE); + + /* Enable no Vbus Detect enable and enable `Power Down Disable` */ + global_regs->GCCFG |= USB_OTG_GCCFG_NOVBUSSENS | USB_OTG_GCCFG_PWRDWN; +#endif +#endif /* USB_OTG_GCCFG_NOVBUSSENS */ + +#ifdef DWC2_USB_OTG_HS_ENABLED + if (conf->type == DWC2_USB_OTG_HS) { + /* Disable the ULPI clock in low power mode, this is essential for the + * peripheral when using the built-in phy */ + periph_lpclk_dis(conf->ahb, RCC_AHB1LPENR_OTGHSULPILPEN); + /* Only the built-in phy supported for now */ + assert(conf->phy == DWC2_USB_OTG_PHY_BUILTIN); + global_regs->GUSBCFG |= USB_OTG_GUSBCFG_PHYSEL; + } +#endif + + return 0; +} + +int tinyusb_hw_init(void) +{ + for (unsigned i = 0; i < USBDEV_NUMOF; i++) { + if (tinyusb_hw_init_dev(&dwc2_usb_otg_fshs_config[i]) != 0) { + return -ENODEV; + } + } + return 0; +} + +/* + * If the STM32 MCU has 2 controllers, tinyUSB supposes that device 0 is + * a FS device and device 1 is a HS device + */ +#ifdef DWC2_USB_OTG_FS_ENABLED +void isr_otg_fs(void) +{ + /* call device interrupt handler with the first device */ + if (IS_USED(MODULE_TINYUSB_DEVICE)) { + tud_int_handler(TINYUSB_TUD_RHPORT); + } + + /* call host interrupt handler with the first device */ + if (IS_USED(MODULE_TINYUSB_HOST)) { + tuh_int_handler(TINYUSB_TUH_RHPORT); + } + + cortexm_isr_end(); +} +#endif /* DWC2_USB_OTG_FS_ENABLED */ + +#ifdef DWC2_USB_OTG_HS_ENABLED +void isr_otg_hs(void) +{ + /* call device interrupt handler with the last device */ + if (IS_USED(MODULE_TINYUSB_DEVICE)) { + tud_int_handler(TINYUSB_TUD_RHPORT); + } + + /* call host interrupt handler with the last device */ + if (IS_USED(MODULE_TINYUSB_HOST)) { + tuh_int_handler(TINYUSB_TUH_RHPORT); + } + + cortexm_isr_end(); +} +#endif /* DWC2_USB_OTG_HS_ENABLED */ diff --git a/pkg/tinyusb/hw/include/tinyusb_hw.h b/pkg/tinyusb/hw/include/tinyusb_hw.h new file mode 100644 index 0000000000..40c4654afd --- /dev/null +++ b/pkg/tinyusb/hw/include/tinyusb_hw.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2022 Gunar Schorcht + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup pkg_tinyusb + * @{ + * + * @file + * @brief TinyUSB hardware driver API + * + * @author Gunar Schorcht + */ + +#ifndef TINYUSB_HW_H +#define TINYUSB_HW_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Initialize the peripherals for tinyUSB. + * + * This functions is called by #tinyusb_setup to initialize the peripherals. + * + * @return 0 on success + * @return -ENODEV if peripherals couldn't be initialized + */ +int tinyusb_hw_init(void); + +#ifdef __cplusplus +} +#endif + +#endif /* TINYUSB_HW_H */ +/** @} */ diff --git a/pkg/tinyusb/hw/include/tinyusb_hw_defaults.h b/pkg/tinyusb/hw/include/tinyusb_hw_defaults.h new file mode 100644 index 0000000000..99f0dcd8f0 --- /dev/null +++ b/pkg/tinyusb/hw/include/tinyusb_hw_defaults.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2022 Gunar Schorcht + * + * 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. + */ + +/** + * @ingroup pkg_tinyusb + * @{ + * + * @file + * @brief Hardware specific default configurations for tinyUSB + * + * The platform or the board can define a file `tinyusb_hw_defaults.h` + * to define default values for tinyUSB such as `TINYUSB_TUD_RHORT` + * or `TINYUSB_TUH_RHPORT` according to the given hardware. In case + * the platform or board does not define such a file, this dummy file + * is used instead. + * + * @author Gunar Schorcht + */ + +#ifndef TINYUSB_HW_DEFAULTS_H +#define TINYUSB_HW_DEFAULTS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* TINYUSB_HW_DEFAULTS_H */ +/** @} */ diff --git a/pkg/tinyusb/patches/0001-src-portable-espressif-fix-include.patch b/pkg/tinyusb/patches/0001-src-portable-espressif-fix-include.patch new file mode 100644 index 0000000000..33891d23a0 Binary files /dev/null and b/pkg/tinyusb/patches/0001-src-portable-espressif-fix-include.patch differ diff --git a/pkg/tinyusb/patches/0002-src-portable-synopsys-define-SystemCoreClock-variabl.patch b/pkg/tinyusb/patches/0002-src-portable-synopsys-define-SystemCoreClock-variabl.patch new file mode 100644 index 0000000000..a197b606e1 Binary files /dev/null and b/pkg/tinyusb/patches/0002-src-portable-synopsys-define-SystemCoreClock-variabl.patch differ diff --git a/sys/auto_init/include/auto_init_priorities.h b/sys/auto_init/include/auto_init_priorities.h index 8dd90b5ce3..be941ded7d 100644 --- a/sys/auto_init/include/auto_init_priorities.h +++ b/sys/auto_init/include/auto_init_priorities.h @@ -239,6 +239,12 @@ extern "C" { */ #define AUTO_INIT_PRIO_MOD_USBUS 1350 #endif +#ifndef AUTO_INIT_PRIO_MOD_TINYUSB +/** + * @brief tinyUSB priority + */ +#define AUTO_INIT_PRIO_MOD_TINYUSB 1350 +#endif #ifndef AUTO_INIT_PRIO_MOD_GNRC_NETIF /** * @brief GNRC netif priority diff --git a/tests/pkg_tinyusb_cdc_msc/Makefile b/tests/pkg_tinyusb_cdc_msc/Makefile new file mode 100644 index 0000000000..846cd4130d --- /dev/null +++ b/tests/pkg_tinyusb_cdc_msc/Makefile @@ -0,0 +1,13 @@ +include ../Makefile.tests_common + +USB_VID ?= $(USB_VID_TESTING) +USB_PID ?= $(USB_PID_TESTING) + +USEPKG += tinyusb +USEMODULE += tinyusb_class_cdc +USEMODULE += tinyusb_class_msc +USEMODULE += tinyusb_device + +include $(RIOTBASE)/Makefile.include + +INCLUDES += -I$(APPDIR) diff --git a/tests/pkg_tinyusb_cdc_msc/README.md b/tests/pkg_tinyusb_cdc_msc/README.md new file mode 100644 index 0000000000..a3b596fddc --- /dev/null +++ b/tests/pkg_tinyusb_cdc_msc/README.md @@ -0,0 +1,43 @@ +# TinyUSB package test application + +## Overview + +This application uses the tinyUSB device stack to emulate a mass storage +device (MSC) with a communication interface (CDC). + +**Please note:** RIOT doesn't own any USB vendor and product ID. The test +application therefore uses `USB_VID_TESTING=0x1209` as manufacturer ID and +`USB_PID_TESTING=0x7d01` as product ID. Do not use these IDs outside of +test environments! They MUST NOT be used on any device that is redistributed, +sold or manufactured, as they are not unique! + +To compile this application with your own vendor and product ID, set the +variables `USB_VID` and `USB_PID` in the makefile or at the command line, +for example + +``` +USB_VID=1234 USB_PID=5678 BOARD=... make -C tests/pkg_tinyusb_cdc_msc +``` + +## Usage + +Once the application is flashed, the device should be mounted when it is +connected to a host. That is, + +- the mass storage interface is mounted as volume `TinyUSB MSC` in the + operating system and +- the communication interface is mounted as a serial device, for example + as `/dev/ttyACM0` on Linux. + +It should then be possible + +1. to read from and write to the mass storage with the usual file operations + of the operating system +2. to connect to the serial interface of the device with a terminal program, e.g. + ``` + python -m serial.tools.miniterm /dev/ttyACM0 115200 + ``` + and get the entered characters sent back. + +The test application uses LED0, if present, to indicate the status of the +device by blinking at different frequencies. diff --git a/tests/pkg_tinyusb_cdc_msc/app.config.test b/tests/pkg_tinyusb_cdc_msc/app.config.test new file mode 100644 index 0000000000..efd8b538ab --- /dev/null +++ b/tests/pkg_tinyusb_cdc_msc/app.config.test @@ -0,0 +1,5 @@ +CONFIG_PACKAGE_TINYUSB=y +CONFIG_MODULE_TINYUSB_CLASS_CDC=y +CONFIG_MODULE_TINYUSB_CLASS_MSC=y +CONFIG_MODULE_TINYUSB_COMMON=y +CONFIG_MODULE_TINYUSB_DEVICE=y diff --git a/tests/pkg_tinyusb_cdc_msc/main.c b/tests/pkg_tinyusb_cdc_msc/main.c new file mode 100644 index 0000000000..06dbfd5214 --- /dev/null +++ b/tests/pkg_tinyusb_cdc_msc/main.c @@ -0,0 +1,198 @@ +/* + * 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. + * + */ + +#include +#include +#include + +#include "board.h" +#include "log.h" +#include "ztimer.h" + +#include "tusb.h" +#include "tinyusb.h" + +/* + * -------------------------------------------------------------------- + * MACRO CONSTANT TYPEDEF PROTYPES + * -------------------------------------------------------------------- + */ + +/* + * Blink pattern + * - 250 ms : device not mounted + * - 1000 ms : device mounted + * - 2500 ms : device is suspended + */ +enum { + BLINK_NOT_MOUNTED = 250, + BLINK_MOUNTED = 1000, + BLINK_SUSPENDED = 2500, +}; + +static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; + +/* + * -------------------------------------------------------------------- + * BLINKING TASK + * -------------------------------------------------------------------- + */ +char led_thread_stack[THREAD_STACKSIZE_MAIN]; + +void *led_thread_impl(void *arg) +{ + (void)arg; + + while (1) { + ztimer_sleep(ZTIMER_MSEC, blink_interval_ms); +#ifdef LED0_TOGGLE + LED0_TOGGLE; +#else + printf("Blinking with %"PRIu32" msec!\n", blink_interval_ms); +#endif + } +} + +void cdc_task(void); + +/* ------------- MAIN ------------- */ + +int main(void) +{ + ztimer_sleep(ZTIMER_MSEC, 200); + + thread_create(led_thread_stack, sizeof(led_thread_stack), + THREAD_PRIORITY_MAIN + 1, + THREAD_CREATE_WOUT_YIELD | THREAD_CREATE_STACKTEST, + led_thread_impl, NULL, "led"); + + if (!IS_USED(MODULE_AUTO_INIT)) { + /* If auto-initialization is not used (module `auto_init`), + * initialize the tinyUSB stack including used peripherals and + * start the tinyUSB thread. Auto-initialization is used by default. */ + tinyusb_setup(); + } + + while (1) { + ztimer_sleep(ZTIMER_MSEC, 10); + cdc_task(); + } + + return 0; +} + +/* + * -------------------------------------------------------------------- + * Device callbacks to be implemented + * -------------------------------------------------------------------- + */ + +/* + * Invoked when device is mounted + */ +void tud_mount_cb(void) +{ + printf("tinyUSB %s\n", __func__); + blink_interval_ms = BLINK_MOUNTED; +} + +/* + * Invoked when device is unmounted + */ +void tud_umount_cb(void) +{ + printf("tinyUSB %s\n", __func__); + blink_interval_ms = BLINK_NOT_MOUNTED; +} + +/* + * Invoked when usb bus is suspended + * remote_wakeup_en : if host allow us to perform remote wakeup + * Within 7ms, device must draw an average of current less than 2.5 mA from bus + */ +void tud_suspend_cb(bool remote_wakeup_en) +{ + (void) remote_wakeup_en; + printf("tinyUSB %s\n", __func__); + blink_interval_ms = BLINK_SUSPENDED; +} + +/* + * Invoked when usb bus is resumed + */ +void tud_resume_cb(void) +{ + printf("tinyUSB %s\n", __func__); + blink_interval_ms = BLINK_MOUNTED; +} + +/* + * --------------------------------------------------------------------+ + * USB CDC + * --------------------------------------------------------------------+ + */ +void cdc_task(void) +{ + /* + * connected() check for DTR bit + * Most but not all terminal client set this when making connection + */ + if ( tud_cdc_connected() ) { + /* connected and there are data available */ + if ( tud_cdc_available() ) + { + /* read data */ + char buf[64]; + uint32_t count = tud_cdc_read(buf, sizeof(buf)); + (void) count; + + /* + * Echo back + * Note: Skip echo by commenting out write() and write_flush() + * for throughput test e.g + * $ dd if=/dev/zero of=/dev/ttyACM0 count=10000 + */ + tud_cdc_write(buf, count); + tud_cdc_write_flush(); + } + } +} + +/* + * Invoked when cdc when line state changed e.g connected/disconnected + */ +void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) +{ + (void) itf; + (void) rts; + + /* TODO set some indicator */ + if ( dtr ) { + /* Terminal connected */ + } + else { + /* Terminal disconnected */ + } +} diff --git a/tests/pkg_tinyusb_cdc_msc/msc_disk.c b/tests/pkg_tinyusb_cdc_msc/msc_disk.c new file mode 100644 index 0000000000..2e8fd29bcb --- /dev/null +++ b/tests/pkg_tinyusb_cdc_msc/msc_disk.c @@ -0,0 +1,360 @@ +/* + * 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. + * + */ + +#include "tusb.h" + +#define ENABLE_DEBUG 0 +#include "debug.h" + +#if CFG_TUD_MSC + +/* whether host does safe-eject */ +static bool ejected = false; + +/* Some MCU doesn't have enough 8KB SRAM to store the whole disk + * We will use Flash as read-only disk with board that has + * CFG_EXAMPLE_MSC_READONLY defined + */ + +#define README_CONTENTS \ + "This is tinyusb's MassStorage Class demo.\r\n\r\n" \ + "If you find any bugs or get any questions, feel free to file an\r\n" \ + "issue at github.com/hathach/tinyusb" + +enum { + DISK_BLOCK_NUM = 16, /* 8KB is the smallest size that windows allow to mount */ + DISK_BLOCK_SIZE = 512 +}; + +#ifdef CFG_EXAMPLE_MSC_READONLY +const +#endif +uint8_t msc_disk[DISK_BLOCK_NUM][DISK_BLOCK_SIZE] = { + /*------------- Block0: Boot Sector ------------- * + * byte_per_sector = DISK_BLOCK_SIZE; + fat12_sector_num_16 = DISK_BLOCK_NUM; + * sector_per_cluster = 1; + * reserved_sectors = 1; + * fat_num = 1; + * fat12_root_entry_num = 16; + * sector_per_fat = 1; + * sector_per_track = 1; + * head_num = 1; + * hidden_sectors = 0; + * drive_number = 0x80; + * media_type = 0xf8; + * extended_boot_signature = 0x29; + * filesystem_type = "FAT12 "; + * volume_serial_number = 0x1234; + * volume_label = "TinyUSB MSC"; + * FAT magic code at offset 510-511 + */ + { + 0xEB, 0x3C, 0x90, 0x4D, 0x53, 0x44, 0x4F, 0x53, + 0x35, 0x2E, 0x30, 0x00, 0x02, 0x01, 0x01, 0x00, + 0x01, 0x10, 0x00, 0x10, 0x00, 0xF8, 0x01, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x29, 0x34, + 0x12, 0x00, 0x00, 'T' , 'i' , 'n' , 'y' , 'U' , + 'S' , 'B' , ' ' , 'M' , 'S' , 'C' , 0x46, 0x41, + 0x54, 0x31, 0x32, 0x20, 0x20, 0x20, 0x00, 0x00, + + /* Zero up to 2 last bytes of FAT magic code */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xAA + }, + + /* ------------- Block1: FAT12 Table ------------- */ + { + 0xF8, 0xFF, 0xFF, 0xFF, 0x0F /* first 2 entries must be F8FF, + * third entry is cluster end of readme file */ + }, + + /* ------------- Block2: Root Directory ------------- */ + { + /* first entry is volume label */ + 'T' , 'i' , 'n' , 'y' , 'U' , 'S' , 'B' , ' ' , + 'M' , 'S' , 'C' , 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4F, 0x6D, + 0x65, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* second entry is readme file */ + 'R' , 'E' , 'A' , 'D' , 'M' , 'E' , ' ' , ' ' , + 'T' , 'X' , 'T' , 0x20, 0x00, 0xC6, 0x52, 0x6D, + 0x65, 0x43, 0x65, 0x43, 0x00, 0x00, 0x88, 0x6D, + 0x65, 0x43, 0x02, 0x00, + sizeof(README_CONTENTS)-1, 0x00, 0x00, 0x00 /* readme's files size (4 Bytes) */ + }, + + /* ------------- Block3: Readme Content ------------- */ + README_CONTENTS +}; + +/* + * Invoked when received SCSI_CMD_INQUIRY + * Application fill vendor id, product id and revision with string up to 8, 16, 4 + * characters respectively + */ +void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], + uint8_t product_id[16], uint8_t product_rev[4]) +{ + (void)lun; + + DEBUG("tinyUSB %s\n", __func__); + + const char vid[] = "TinyUSB"; + const char pid[] = "Mass Storage"; + const char rev[] = "1.0"; + + memcpy(vendor_id, vid, strlen(vid)); + memcpy(product_id, pid, strlen(pid)); + memcpy(product_rev, rev, strlen(rev)); +} + +/* + * Invoked when received Test Unit Ready command. + * return true allowing host to read/write this LUN e.g SD card inserted + */ +bool tud_msc_test_unit_ready_cb(uint8_t lun) +{ + (void)lun; + + DEBUG("tinyUSB %s\n", __func__); + + /* RAM disk is ready until ejected */ + if (ejected) { + /* Additional Sense 3A-00 is NOT_FOUND */ + tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x3a, 0x00); + return false; + } + + return true; +} + +/* + * Invoked when received SCSI_CMD_READ_CAPACITY_10 and + * SCSI_CMD_READ_FORMAT_CAPACITY to determine the disk size + * Application update block count and block size + */ +void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* block_size) +{ + (void)lun; + + DEBUG("tinyUSB %s\n", __func__); + + *block_count = DISK_BLOCK_NUM; + *block_size = DISK_BLOCK_SIZE; +} + +/* + * Invoked when received Start Stop Unit command + * - Start = 0 : stopped power mode, if load_eject = 1 : unload disk storage + * - Start = 1 : active mode, if load_eject = 1 : load disk storage + */ +bool tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, + bool start, bool load_eject) +{ + (void)lun; + (void)power_condition; + + DEBUG("tinyUSB %s\n", __func__); + + if (load_eject) { + if (start) { + /* load disk storage */ + } + else { + /* unload disk storage */ + ejected = true; + } + } + return true; +} + +/* + * Callback invoked when received READ10 command. + * Copy disk's data to buffer (up to bufsize) and return number of copied bytes. + */ +int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, + void* buffer, uint32_t bufsize) +{ + (void)lun; + + DEBUG("tinyUSB %s\n", __func__); + + /* out of ramdisk */ + if (lba >= DISK_BLOCK_NUM) { + return -1; + } + + uint8_t const* addr = msc_disk[lba] + offset; + memcpy(buffer, addr, bufsize); + + return (int32_t)bufsize; +} + +bool tud_msc_is_writable_cb(uint8_t lun) +{ + (void)lun; + + DEBUG("tinyUSB %s\n", __func__); + +#ifdef CFG_EXAMPLE_MSC_READONLY + return false; +#else + return true; +#endif +} + +/* + * Callback invoked when received WRITE10 command. + * Process data in buffer to disk's storage and return number of written bytes + */ +int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, + uint8_t* buffer, uint32_t bufsize) +{ + (void)lun; + + DEBUG("tinyUSB %s\n", __func__); + + /* out of ramdisk */ + if (lba >= DISK_BLOCK_NUM) { + return -1; + } + +#ifndef CFG_EXAMPLE_MSC_READONLY + uint8_t* addr = msc_disk[lba] + offset; + memcpy(addr, buffer, bufsize); +#else + (void)lba; + (void)offset; + (void)buffer; +#endif + + return (int32_t) bufsize; +} + +/* + * Callback invoked when received an SCSI command not in built-in list below + * - READ_CAPACITY10, READ_FORMAT_CAPACITY, INQUIRY, MODE_SENSE6, REQUEST_SENSE + * - READ10 and WRITE10 has their own callbacks + */ +int32_t tud_msc_scsi_cb (uint8_t lun, uint8_t const scsi_cmd[16], + void* buffer, uint16_t bufsize) +{ + /* read10 & write10 has their own callback and MUST not be handled here */ + + DEBUG("tinyUSB %s\n", __func__); + + void const* response = NULL; + int32_t resplen = 0; + + /* most scsi handled is input */ + bool in_xfer = true; + + switch (scsi_cmd[0]) { + default: + /* Set Sense = Invalid Command Operation */ + tud_msc_set_sense(lun, SCSI_SENSE_ILLEGAL_REQUEST, 0x20, 0x00); + + /* negative means error -> tinyusb could stall and/or response with failed status */ + resplen = -1; + break; + } + + /* return resplen must not larger than bufsize */ + if (resplen > bufsize) { + resplen = bufsize; + } + + if (response && (resplen > 0)) { + if (in_xfer) { + memcpy(buffer, response, (size_t) resplen); + } + else { + /* SCSI output */ + } + } + + return (int32_t)resplen; +} + +#endif diff --git a/tests/pkg_tinyusb_cdc_msc/tusb_config.h b/tests/pkg_tinyusb_cdc_msc/tusb_config.h new file mode 100644 index 0000000000..dcde62b0b6 --- /dev/null +++ b/tests/pkg_tinyusb_cdc_msc/tusb_config.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2022 Gunar Schorcht + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +#ifndef TUSB_CONFIG_H +#define TUSB_CONFIG_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * By default, the number of `CFG_TUD_*` device class and `CFG_TUH_*` + * host class interfaces is defined to 1 if the corresponding `tinyusb_class_*` + * and `tinyusb_device`/`tinyusb_host` module are enabled, and 0 otherwise. + * That is, there is one interface of each class. + * + * For example, if the `tinyusb_device` and `tinyusb_class_cdc` modules are + * enabled, `CFG_TUD_CDC` is defined to 1 by default. The number of all other + * `CFG_TUD_*` device class interfaces are 0. + * + * To define a different number of device class or host class interfaces, + * just define them here to override these default values, for example: + * ```c + * #define CFG_TUD_CDC 2 + * #define CFG_TUD_HID 3 + * ``` + */ + +/* Default configuration defined by RIOT package tinyUSB has to be included last */ +#include "tinyusb_config.h" + +#ifdef __cplusplus +} +#endif + +#endif /* TUSB_CONFIG_H */ diff --git a/tests/pkg_tinyusb_cdc_msc/usb_descriptors.c b/tests/pkg_tinyusb_cdc_msc/usb_descriptors.c new file mode 100644 index 0000000000..3bd2523449 --- /dev/null +++ b/tests/pkg_tinyusb_cdc_msc/usb_descriptors.c @@ -0,0 +1,340 @@ +/* + * 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. + * + */ + +#include "tusb.h" + +#ifdef CONFIG_USB_PID +#define USB_PID CONFIG_USB_PID +#else +/* + * A combination of interfaces must have a unique product id, since PC will + * save device driver after the first plug. Same VID/PID with different + * interface e.g MSC (first), then CDC (later) will possibly cause system error + * on PC. + * + * Auto ProductID layout's Bitmap: + * [MSB] VIDEO | AUDIO | MIDI | HID | MSC | CDC [LSB] + */ +#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) ) +#define USB_PID (0x4000 | _PID_MAP(CDC, 0) \ + | _PID_MAP(MSC, 1) \ + | _PID_MAP(HID, 2) \ + | _PID_MAP(MIDI, 3) \ + | _PID_MAP(AUDIO, 4) \ + | _PID_MAP(VIDEO, 5) ) +#endif + +#ifdef CONFIG_USB_VID +#define USB_VID CONFIG_USB_VID +#else +#error USB_VID has to be defined +#endif + +#define USB_BCD 0x0200 + +/* + * --------------------------------------------------------------------+ + * Device Descriptors + * --------------------------------------------------------------------+ + */ +static tusb_desc_device_t const desc_device = { + .bLength = sizeof(tusb_desc_device_t), + .bDescriptorType = TUSB_DESC_DEVICE, + .bcdUSB = USB_BCD, + + /* Use Interface Association Descriptor (IAD) for CDC + * As required by USB Specs IAD's subclass must be common class (2) + * and protocol must be IAD (1) */ + .bDeviceClass = TUSB_CLASS_MISC, + .bDeviceSubClass = MISC_SUBCLASS_COMMON, + .bDeviceProtocol = MISC_PROTOCOL_IAD, + + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, + + .idVendor = USB_VID, + .idProduct = USB_PID, + .bcdDevice = 0x0100, + + .iManufacturer = 0x01, + .iProduct = 0x02, + .iSerialNumber = 0x03, + + .bNumConfigurations = 0x01 +}; + +/* + * Invoked when received GET DEVICE DESCRIPTOR + * Application return pointer to descriptor + */ +uint8_t const *tud_descriptor_device_cb(void) +{ + return (uint8_t const *)&desc_device; +} + +/* + *--------------------------------------------------------------------+ + * Configuration Descriptor + *--------------------------------------------------------------------+ + */ +enum { + ITF_NUM_CDC = 0, + ITF_NUM_CDC_DATA, + ITF_NUM_MSC, + ITF_NUM_TOTAL +}; + +#if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || \ + CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX + /* + * LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number + * 0 control, 1 In, 2 Bulk, 3 Iso, 4 In, 5 Bulk etc ... + */ + #define EPNUM_CDC_NOTIF 0x81 + #define EPNUM_CDC_OUT 0x02 + #define EPNUM_CDC_IN 0x82 + + #define EPNUM_MSC_OUT 0x05 + #define EPNUM_MSC_IN 0x85 + +#elif CFG_TUSB_MCU == OPT_MCU_SAMG || CFG_TUSB_MCU == OPT_MCU_SAMX7X + /* + * SAMG & SAME70 don't support a same endpoint number with different + * direction IN and OUT, e.g EP1 OUT & EP1 IN cannot exist together + */ + #define EPNUM_CDC_NOTIF 0x81 + #define EPNUM_CDC_OUT 0x02 + #define EPNUM_CDC_IN 0x83 + + #define EPNUM_MSC_OUT 0x04 + #define EPNUM_MSC_IN 0x85 + +#elif CFG_TUSB_MCU == OPT_MCU_CXD56 + /* + * CXD56 doesn't support a same endpoint number with different direction IN + * and OUT, e.g EP1 OUT & EP1 IN cannot exist together + * CXD56 USB driver has fixed endpoint type (bulk/interrupt/iso) and + * direction (IN/OUT) by its number + * 0 control (IN/OUT), 1 Bulk (IN), 2 Bulk (OUT), 3 In (IN), 4 Bulk (IN), + * 5 Bulk (OUT), 6 In (IN) + */ + #define EPNUM_CDC_NOTIF 0x83 + #define EPNUM_CDC_OUT 0x02 + #define EPNUM_CDC_IN 0x81 + + #define EPNUM_MSC_OUT 0x05 + #define EPNUM_MSC_IN 0x84 + +#elif CFG_TUSB_MCU == OPT_MCU_FT90X || CFG_TUSB_MCU == OPT_MCU_FT93X + /* + * FT9XX doesn't support a same endpoint number with different direction + * IN and OUT, e.g EP1 OUT & EP1 IN cannot exist together + */ + #define EPNUM_CDC_NOTIF 0x81 + #define EPNUM_CDC_OUT 0x02 + #define EPNUM_CDC_IN 0x83 + + #define EPNUM_MSC_OUT 0x04 + #define EPNUM_MSC_IN 0x85 + +#else + #define EPNUM_CDC_NOTIF 0x81 + #define EPNUM_CDC_OUT 0x02 + #define EPNUM_CDC_IN 0x82 + + #define EPNUM_MSC_OUT 0x03 + #define EPNUM_MSC_IN 0x83 + +#endif + +#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN + TUD_MSC_DESC_LEN) + +/* full speed configuration */ +uint8_t const desc_fs_configuration[] = { + /* Config number, interface count, string index, total length, attribute, + * power in mA */ + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), + + /* Interface number, string index, EP notification address and size, EP data + * address (out, in) and size. */ + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 64), + + /* Interface number, string index, EP Out & EP In address, EP size */ + TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 5, EPNUM_MSC_OUT, EPNUM_MSC_IN, 64), +}; + +#if TUD_OPT_HIGH_SPEED + /* Per USB specs: high speed capable device must report device_qualifier + * and other_speed_configuration */ + +/* high speed configuration */ +uint8_t const desc_hs_configuration[] = +{ + /* Config number, interface count, string index, total length, attribute, + * power in mA */ + TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100), + + /* Interface number, string index, EP notification address and size, EP data + * address (out, in) and size. */ + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 512), + + /* Interface number, string index, EP Out & EP In address, EP size */ + TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 5, EPNUM_MSC_OUT, EPNUM_MSC_IN, 512), +}; + +/* other speed configuration */ +uint8_t desc_other_speed_config[CONFIG_TOTAL_LEN]; + +/* device qualifier is mostly similar to device descriptor since we don't + * change configuration based on speed */ +tusb_desc_device_qualifier_t const desc_device_qualifier = { + .bLength = sizeof(tusb_desc_device_qualifier_t), + .bDescriptorType = TUSB_DESC_DEVICE_QUALIFIER, + .bcdUSB = USB_BCD, + + .bDeviceClass = TUSB_CLASS_MISC, + .bDeviceSubClass = MISC_SUBCLASS_COMMON, + .bDeviceProtocol = MISC_PROTOCOL_IAD, + + .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, + .bNumConfigurations = 0x01, + .bReserved = 0x00 +}; + +/* + * Invoked when received GET DEVICE QUALIFIER DESCRIPTOR request + * Application return pointer to descriptor, whose contents must exist long + * enough for transfer to complete. Device_qualifier descriptor describes + * information about a high-speed capable device that would change if the + * device were operating at the other speed. If not highspeed capable stall + * this request. + */ +uint8_t const* tud_descriptor_device_qualifier_cb(void) +{ + return (uint8_t const*)&desc_device_qualifier; +} + +/* + * Invoked when received GET OTHER SEED CONFIGURATION DESCRIPTOR request + * Application return pointer to descriptor, whose contents must exist long + * enough for transfer to complete. Configuration descriptor in the other + * speed e.g if high speed then this is for full speed and vice versa + */ +uint8_t const* tud_descriptor_other_speed_configuration_cb(uint8_t index) +{ + (void)index; /* for multiple configurations */ + + /* if link speed is high return fullspeed config, and vice versa + * Note: the descriptor type is OHER_SPEED_CONFIG instead of CONFIG */ + memcpy(desc_other_speed_config, + (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_fs_configuration + : desc_hs_configuration, + CONFIG_TOTAL_LEN); + + desc_other_speed_config[1] = TUSB_DESC_OTHER_SPEED_CONFIG; + + return desc_other_speed_config; +} + +#endif /* highspeed */ + +/* + * Invoked when received GET CONFIGURATION DESCRIPTOR + * Application return pointer to descriptor + * Descriptor contents must exist long enough for transfer to complete + */ +uint8_t const * tud_descriptor_configuration_cb(uint8_t index) +{ + (void)index; /* for multiple configurations */ + +#if TUD_OPT_HIGH_SPEED + /* Although we are highspeed, host may be fullspeed. */ + return (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_hs_configuration + : desc_fs_configuration; +#else + return desc_fs_configuration; +#endif +} + +/* + *--------------------------------------------------------------------+ + * String Descriptors + *--------------------------------------------------------------------+ + */ + +/* array of pointer to string descriptors */ +char const* string_desc_arr [] = { + (const char[]){ 0x09, 0x04 }, /* 0: is supported language is English (0x0409) */ + "RIOT-OS", /* 1: Manufacturer */ + "TinyUSB Device", /* 2: Product */ + "123456789012", /* 3: Serials, should use chip ID */ + "TinyUSB CDC", /* 4: CDC Interface */ + "TinyUSB MSC", /* 5: MSC Interface */ +}; + +static uint16_t _desc_str[32]; + +/* + * Invoked when received GET STRING DESCRIPTOR request + * Application return pointer to descriptor, whose contents must exist long + * enough for transfer to complete. + */ +uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid) +{ + (void)langid; + + uint8_t chr_count; + + if ( index == 0) { + memcpy(&_desc_str[1], string_desc_arr[0], 2); + chr_count = 1; + } + else { + /* Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors. + * https: *docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors + */ + + if (!(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0]))) { + return NULL; + } + + const char* str = string_desc_arr[index]; + + /* Cap at max char */ + chr_count = (uint8_t) strlen(str); + if (chr_count > 31) { + chr_count = 31; + } + + /* Convert ASCII string into UTF-16 */ + for (uint8_t i=0; i