tfx2001 3 лет назад
Родитель
Сommit
3896366e3a
60 измененных файлов с 1356 добавлено и 305 удалено
  1. 8 0
      .github/ISSUE_TEMPLATE/bug_report.yml
  2. 0 14
      .github/ISSUE_TEMPLATE/feature_request.md
  3. 49 0
      .github/ISSUE_TEMPLATE/feature_request.yml
  4. 4 4
      README.rst
  5. 58 0
      docs/info/changelog.rst
  6. 9 10
      docs/reference/getting_started.rst
  7. 10 1
      docs/reference/supported.rst
  8. 0 3
      examples/device/audio_4_channel_mic/CMakeLists.txt
  9. 0 3
      examples/device/audio_test/CMakeLists.txt
  10. 0 3
      examples/device/board_test/CMakeLists.txt
  11. 0 3
      examples/device/cdc_dual_ports/CMakeLists.txt
  12. 0 3
      examples/device/cdc_msc/CMakeLists.txt
  13. 0 3
      examples/device/dfu/CMakeLists.txt
  14. 0 3
      examples/device/dfu_runtime/CMakeLists.txt
  15. 0 3
      examples/device/dynamic_configuration/CMakeLists.txt
  16. 0 3
      examples/device/hid_boot_interface/CMakeLists.txt
  17. 1 1
      examples/device/hid_boot_interface/src/main.c
  18. 0 3
      examples/device/hid_composite/CMakeLists.txt
  19. 1 1
      examples/device/hid_composite/src/main.c
  20. 1 1
      examples/device/hid_composite_freertos/src/main.c
  21. 0 3
      examples/device/hid_generic_inout/CMakeLists.txt
  22. 0 3
      examples/device/hid_multiple_interface/CMakeLists.txt
  23. 0 3
      examples/device/midi_test/CMakeLists.txt
  24. 0 3
      examples/device/msc_dual_lun/CMakeLists.txt
  25. 0 3
      examples/device/net_lwip_webserver/CMakeLists.txt
  26. 0 3
      examples/device/uac2_headset/CMakeLists.txt
  27. 2 1
      examples/device/uac2_headset/skip.txt
  28. 0 3
      examples/device/usbtmc/CMakeLists.txt
  29. 59 11
      examples/device/usbtmc/src/usb_descriptors.c
  30. 19 16
      examples/device/usbtmc/visaQuery.py
  31. 0 3
      examples/device/video_capture/CMakeLists.txt
  32. 0 3
      examples/device/webusb_serial/CMakeLists.txt
  33. 4 2
      examples/device/webusb_serial/src/main.c
  34. 3 6
      examples/dual/host_hid_to_device_cdc/CMakeLists.txt
  35. 0 31
      examples/example.cmake
  36. 0 3
      examples/host/bare_api/CMakeLists.txt
  37. 0 3
      examples/host/cdc_msc_hid/CMakeLists.txt
  38. 0 3
      examples/host/hid_controller/CMakeLists.txt
  39. 42 0
      hw/bsp/family_support.cmake
  40. 43 28
      hw/bsp/rp2040/family.cmake
  41. 169 0
      hw/bsp/stm32l0/boards/stm32l052dap52/STM32L052K8Ux_FLASH.ld
  42. 109 0
      hw/bsp/stm32l0/boards/stm32l052dap52/board.h
  43. 11 0
      hw/bsp/stm32l0/boards/stm32l052dap52/board.mk
  44. 181 0
      hw/bsp/stm32l0/family.c
  45. 40 0
      hw/bsp/stm32l0/family.mk
  46. 338 0
      hw/bsp/stm32l0/stm32l0xx_hal_conf.h
  47. 2 1
      repository.yml
  48. 1 1
      src/class/audio/audio_device.c
  49. 2 0
      src/class/dfu/dfu_device.c
  50. 1 1
      src/class/hid/hid_device.c
  51. 1 1
      src/class/hid/hid_device.h
  52. 4 1
      src/class/usbtmc/usbtmc.h
  53. 55 27
      src/class/usbtmc/usbtmc_device.c
  54. 0 4
      src/class/usbtmc/usbtmc_device.h
  55. 10 0
      src/common/tusb_compiler.h
  56. 74 14
      src/host/hub.c
  57. 4 4
      src/host/usbh.c
  58. 37 56
      src/portable/nordic/nrf5x/dcd_nrf5x.c
  59. 2 0
      src/portable/raspberrypi/rp2040/rp2040_usb.c
  60. 2 2
      src/tusb_option.h

+ 8 - 0
.github/ISSUE_TEMPLATE/bug_report.yml

@@ -76,3 +76,11 @@ body:
       description: If applicable, add screenshots to help explain your problem.
     validations:
       required: false
+
+  - type: checkboxes
+    attributes:
+      label: I have checked existing issues, dicussion and documentation
+      description: You agree to check all the resources above before opening a new issue.
+      options:
+        - label: I confirm I have checked existing issues, dicussion and documentation.
+          required: true

+ 0 - 14
.github/ISSUE_TEMPLATE/feature_request.md

@@ -1,14 +0,0 @@
----
-name: Feature Request
-about: Suggest an idea for this project
-title: ''
-labels: Feature 💡
-assignees: ''
-
----
-
-**Is your feature request related to a problem? Please describe.**
-A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
-
-**Describe the solution you'd like**
-A clear and concise description of what you want to happen.

+ 49 - 0
.github/ISSUE_TEMPLATE/feature_request.yml

@@ -0,0 +1,49 @@
+name: Feature Request
+description: Suggest an idea for this project
+labels: 'Feature 💡'
+body:
+  - type: markdown
+    attributes:
+      value: |
+        Thanks for taking the time to fill out this request!
+        It's okay to leave some blank if it doesn't apply to your request.
+
+  - type: input
+    attributes:
+      label: Related area
+      description: Please briefly explain the area of your Feature Request.
+      placeholder: eg. new port support, device stack, class driver ...
+    validations:
+      required: true
+
+  - type: input
+    attributes:
+      label: Hardware specification
+      description: Please provide if your proposal depends on specific Hardware.
+      placeholder: eg. rp2040, samd51 ...
+    validations:
+      required: true
+
+  - type: textarea
+    attributes:
+      label: Is your feature request related to a problem?
+      description: Please provide a clear and concise description of what the problem is. Add relevant issue link.
+      placeholder: ex. I'm facing the issue/missing function...
+    validations:
+      required: true
+
+  - type: textarea
+    attributes:
+      label: Describe the solution you'd like
+      description: Please provide a clear and concise description of what you want to happen.
+      placeholder: ex. When using this function...
+    validations:
+      required: true
+
+  - type: checkboxes
+    attributes:
+      label: I have checked existing issues, dicussion and documentation
+      description: You agree to check all the resources above before opening a new issue.
+      options:
+        - label: I confirm I have checked existing issues, dicussion and documentation.
+          required: true

+ 4 - 4
README.rst

@@ -43,7 +43,7 @@ The stack supports the following MCUs:
 - **Nuvoton:** NUC120, NUC121/NUC125, NUC126, NUC505
 - **NXP:**
 
-  - iMX RT Series: RT1011, RT1015, RT1021, RT1052, RT1062, RT1064
+  - iMX RT Series: RT10xx, RT11xx
   - Kinetis: KL25, K32L2
   - LPC Series: 11u, 13, 15, 17, 18, 40, 43, 51u, 54, 55
 
@@ -51,7 +51,7 @@ The stack supports the following MCUs:
 - **Renesas:** RX63N, RX65N, RX72N
 - **Silabs:** EFM32GG
 - **Sony:** CXD56
-- **ST:** STM32 series: F0, F1, F2, F3, F4, F7, H7, G4, L0, L1, L4, L4+
+- **ST:** STM32 series: F0, F1, F2, F3, F4, F7, H7, G4, L0, L1, L4, L4+, WB
 - **TI:** MSP430, MSP432E4, TM4C123
 - **ValentyUSB:** eptri
 
@@ -94,8 +94,8 @@ TinyUSB is completely thread-safe by pushing all Interrupt Service Request (ISR)
 - `RT-Thread <https://github.com/RT-Thread/rt-thread>`_: `repo <https://github.com/RT-Thread-packages/tinyusb>`_
 - **Mynewt** Due to the newt package build system, Mynewt examples are better to be on its `own repo <https://github.com/hathach/mynewt-tinyusb-example>`_
 
-Local Docs
-==========
+Docs
+====
 
 - Info
 

+ 58 - 0
docs/info/changelog.rst

@@ -2,6 +2,64 @@
 Changelog
 *********
 
+0.14.0
+======
+
+- Improve compiler support for CCRX and IAR
+- Add timeout to osal_queue_receive()
+- Add tud_task_ext(timeout, in_isr) as generic version of tud_task(). Same as tuh_task_ext(), tuh_task()
+- Enable more warnings -Wnull-dereference -Wuninitialized -Wunused -Wredundant-decls -Wconversion
+- Add new examples 
+  - host/bare_api to demonstrate generic (app-level) enumeration and endpoint transfer
+  - dual/host_hid_to_device_cdc to run both device and host stack concurrently, get HID report from host and print out to device CDC. This example only work with multiple-controller MCUs and rp2040 with the help of pio-usb as added controller.
+
+Controller Driver (DCD & HCD)
+-----------------------------
+
+- Enhance rhports management to better support dual roles
+  - CFG_TUD_ENABLED/CFG_TUH_ENABLED, CFG_TUD_MAX_SPEED/CFG_TUH_MAX_SPEED can be used to replace CFG_TUSB_RHPORT0_MODE/CFG_TUSB_RHPORT1_MODE
+  - tud_init(rphort), tuh_init(rhport) can be used to init stack on specified roothub port (controller) instead of tusb_init(void)
+- Add dcd/hcd port specific defines TUP_ (stand for tinyusb port-specific)
+- [dwc2]
+  - Update to support stm32 h72x, h73x with only 1 otg controller
+  - Fix overwrite with grstctl when disable endpoint
+- [EHCI] Fix an issue with EHCI driver
+- [msp430] Fix for possible bug in msp430-elf-gcc 9.3.0
+- [nrf5x] Fix DMA access race condition using atomic function 
+- [pic32] Fix PIC32 santiy
+- [rp2040]
+  - Add PICO-PIO-USB as controller (device/host) support for rp2040
+  - Use shared IRQ handlers, so user can also hook the USB IRQ
+  - Fix resumed signal not reported to device stack
+- [stm32fsdev] Add support for stm32wb55 
+
+Device Stack
+------------
+
+- [Audio] Add support for feedback endpoint computation
+  - New API tud_audio_feedback_params_cb(), tud_audio_feedback_interval_isr().
+  - Supported computation method are: frequency with fixed/float or power of 2. Feedback with fifo count is not yet supported.
+  - Fix nitfs (should be 3) in TUD_AUDIO_HEADSET_STEREO_DESCRIPTOR
+  - Fix typo in audiod_rx_done_cb()
+- [DFU] Fix coexistence with other interfaces BTH, RNDIS
+- [MSC] Fix inquiry response additional length field
+- [Venndor] Improve write performance
+
+Host Stack
+----------
+
+- Add new API tuh_configure(rhport, cfg_id, cfg_param) for dynamnic port specific behavior configuration
+- [HID] Open OUT endpoint if available
+- [Hub] hub clear port and device interrupts
+- [USBH] Major improvement
+  - Rework usbh control transfer with complete callback. New API tuh_control_xfer() though still only carry 1 usbh (no queueing) at a time.
+  - Add generic endpoint transfer with tuh_edpt_open(), tuh_edpt_xfer(). Require `CFG_TUH_API_EDPT_XFER=1`
+  - Support app-level enumeration with new APIs
+    - tuh_descriptor_get(), tuh_descriptor_get_device(), tuh_descriptor_get_configuration(), tuh_descriptor_get_hid_report()
+    - tuh_descriptor_get_string(), tuh_descriptor_get_manufacturer_string(), tuh_descriptor_get_product_string(), tuh_descriptor_get_serial_string()
+    - Also add _sync() as sync/blocking version for above APIs 
+    
+
 0.13.0
 ======
 

+ 9 - 10
docs/reference/getting_started.rst

@@ -50,16 +50,7 @@ Some TinyUSB examples also requires external submodule libraries in ``/lib`` suc
 
    $ git submodule update --init lib
 
-In addition, MCU driver submodule is also needed to provide low-level MCU peripheral's driver. To download these depencies for your board, run the ``get-dpes`` as follow.
-
-.. code-block::
-
-   $ make BOARD=feather_nrf52840_express get-deps
-
-
-Some modules will also require a module-specific SDK (e.g. RP2040) or binary (e.g. Sony Spresense) to build examples.
-
-Note: some examples especially those that uses Vendor class (e.g webUSB) may requires udev permission on Linux (and/or macOS) to access usb device. It depends on your OS distro, typically copy ``/examples/device/99-tinyusb.rules`` file to /etc/udev/rules.d/ then run ``sudo udevadm control --reload-rules && sudo udevadm trigger`` is good enough.
+Some ports will also require a port-specific SDK (e.g. RP2040) or binary (e.g. Sony Spresense) to build examples. They are out of scope for tinyusb, you should download/install it first according to its manufacturer guide. 
 
 Build
 ^^^^^
@@ -70,6 +61,13 @@ To build example, first change directory to an example folder.
 
    $ cd examples/device/cdc_msc
 
+Before building, we need to download MCU driver submodule to provide low-level MCU peripheral's driver first. Run the ``get-dpes`` target in one of the example folder as follow. You only need to do this once per mcu
+
+.. code-block::
+
+   $ make BOARD=feather_nrf52840_express get-deps
+
+
 Some modules (e.g. RP2040 and ESP32s2) require the project makefiles to be customized using CMake. If necessary apply any setup steps for the platform's SDK.
 
 Then compile with ``make BOARD=[board_name] all``\ , for example
@@ -79,6 +77,7 @@ Then compile with ``make BOARD=[board_name] all``\ , for example
    $ make BOARD=feather_nrf52840_express all
 
 Note: ``BOARD`` can be found as directory name in ``hw/bsp``\ , either in its family/boards or directly under bsp (no family).
+Note: some examples especially those that uses Vendor class (e.g webUSB) may requires udev permission on Linux (and/or macOS) to access usb device. It depends on your OS distro, typically copy ``/examples/device/99-tinyusb.rules`` file to /etc/udev/rules.d/ then run ``sudo udevadm control --reload-rules && sudo udevadm trigger`` is good enough.
 
 Port Selection
 ~~~~~~~~~~~~~~

+ 10 - 1
docs/reference/supported.rst

@@ -41,6 +41,8 @@ Supported MCUs
 |              | NUC505                | ✔      |      | ✔         |                   |              |
 +--------------+---------+-------------+--------+------+-----------+-------------------+--------------+
 | NXP          | iMXRT   | RT10xx      | ✔      | ✔    | ✔         | ci_hs             |              |
+|              |         +-------------+--------+------+-----------+-------------------+--------------+
+|              |         | RT11xx      | ✔      | ✔    | ✔         | ci_hs             |              |
 |              +---------+-------------+--------+------+-----------+-------------------+--------------+
 |              | Kinetis | KL25        | ✔      | ⚠    | ✖         |                   |              |
 |              |         +-------------+--------+------+-----------+-------------------+--------------+
@@ -58,7 +60,7 @@ Supported MCUs
 |              |         +-------------+--------+------+-----------+-------------------+--------------+
 |              |         | 55          | ✔      |      | ✔         | lpc_ip3511        |              |
 +--------------+---------+-------------+--------+------+-----------+-------------------+--------------+
-| Raspberry Pi | RP2040                | ✔      | ✔    | ✖         | rp2040            |              |
+| Raspberry Pi | RP2040                | ✔      | ✔    | ✖         | rp2040, pio_usb   |              |
 +--------------+-----------------------+--------+------+-----------+-------------------+--------------+
 | Renesas      | RX 63N, 65N, 72N      | ✔      | ✔    | ✖         | usba              |              |
 +--------------+-----------------------+--------+------+-----------+-------------------+--------------+
@@ -93,6 +95,8 @@ Supported MCUs
 |              | L4+                   | ✔      |      |           | dwc2              |              |
 |              +-----------------------+--------+------+-----------+-------------------+--------------+
 |              | U5                    | ⚠      |      |           | dwc2              |              |
+|              +-----------------------+--------+------+-----------+-------------------+--------------+
+|              | WBx5                  | ✔      |      |           | stm32_fsdev       |              |
 +--------------+-----------------------+--------+------+-----------+-------------------+--------------+
 | TI           | MSP430                | ✔      | ✖    | ✖         | msp430x5xx        |              |
 |              +-----------------------+--------+------+-----------+-------------------+--------------+
@@ -239,6 +243,7 @@ iMX RT
 -  `MIMX RT1060 Evaluation Kit <https://www.nxp.com/design/development-boards/i.mx-evaluation-and-development-boards/mimxrt1060-evk-i.mx-rt1060-evaluation-kit:MIMXRT1060-EVK>`__
 -  `MIMX RT1064 Evaluation Kit <https://www.nxp.com/design/development-boards/i.mx-evaluation-and-development-boards/mimxrt1064-evk-i.mx-rt1064-evaluation-kit:MIMXRT1064-EVK>`__
 -  `Teensy 4.0 Development Board <https://www.pjrc.com/store/teensy40.html>`__
+-  `Teensy 4.1 Development Board <https://www.pjrc.com/store/teensy41.html>`__
 
 Kinetis
 ^^^^^^^
@@ -377,6 +382,10 @@ L4
 -  `STM32 L4P5zg Nucleo <https://www.st.com/en/evaluation-tools/nucleo-l4p5zg.html>`__
 -  `STM32 L4R5zi Nucleo <https://www.st.com/en/evaluation-tools/nucleo-l4r5zi.html>`__
 
+WB
+^^
+-  `STM32 WB55 Nucleo <https://www.st.com/en/evaluation-tools/p-nucleo-wb55.html>`__
+
 TI
 --
 

+ 0 - 3
examples/device/audio_4_channel_mic/CMakeLists.txt

@@ -23,9 +23,6 @@ target_include_directories(${PROJECT} PUBLIC
   ${CMAKE_CURRENT_SOURCE_DIR}/src
 )
 
-# Example common such as compiler warnings
-include(${CMAKE_CURRENT_SOURCE_DIR}/../../example.cmake)
-
 # Configure compilation flags and libraries for the example... see the corresponding function
 # in hw/bsp/FAMILY/family.cmake for details.
 family_configure_device_example(${PROJECT})

+ 0 - 3
examples/device/audio_test/CMakeLists.txt

@@ -23,9 +23,6 @@ target_include_directories(${PROJECT} PUBLIC
   ${CMAKE_CURRENT_SOURCE_DIR}/src
 )
 
-# Example common such as compiler warnings
-include(${CMAKE_CURRENT_SOURCE_DIR}/../../example.cmake)
-
 # Configure compilation flags and libraries for the example... see the corresponding function
 # in hw/bsp/FAMILY/family.cmake for details.
 family_configure_device_example(${PROJECT})

+ 0 - 3
examples/device/board_test/CMakeLists.txt

@@ -36,9 +36,6 @@ else()
           ${CMAKE_CURRENT_SOURCE_DIR}/src
           )
 
-  # Example common such as compiler warnings
-  include(${CMAKE_CURRENT_SOURCE_DIR}/../../example.cmake)
-
   # Configure compilation flags and libraries for the example... see the corresponding function
   # in hw/bsp/FAMILY/family.cmake for details.
   family_configure_device_example(${PROJECT})

+ 0 - 3
examples/device/cdc_dual_ports/CMakeLists.txt

@@ -23,9 +23,6 @@ target_include_directories(${PROJECT} PUBLIC
         ${CMAKE_CURRENT_SOURCE_DIR}/src
         )
 
-# Example common such as compiler warnings
-include(${CMAKE_CURRENT_SOURCE_DIR}/../../example.cmake)
-
 # Configure compilation flags and libraries for the example... see the corresponding function
 # in hw/bsp/FAMILY/family.cmake for details.
 family_configure_device_example(${PROJECT})

+ 0 - 3
examples/device/cdc_msc/CMakeLists.txt

@@ -24,9 +24,6 @@ target_include_directories(${PROJECT} PUBLIC
         ${CMAKE_CURRENT_SOURCE_DIR}/src
         )
 
-# Example common such as compiler warnings
-include(${CMAKE_CURRENT_SOURCE_DIR}/../../example.cmake)
-
 # Configure compilation flags and libraries for the example... see the corresponding function
 # in hw/bsp/FAMILY/family.cmake for details.
 family_configure_device_example(${PROJECT})

+ 0 - 3
examples/device/dfu/CMakeLists.txt

@@ -23,9 +23,6 @@ target_include_directories(${PROJECT} PUBLIC
         ${CMAKE_CURRENT_SOURCE_DIR}/src
         )
 
-# Example common such as compiler warnings
-include(${CMAKE_CURRENT_SOURCE_DIR}/../../example.cmake)
-
 # Configure compilation flags and libraries for the example... see the corresponding function
 # in hw/bsp/FAMILY/family.cmake for details.
 family_configure_device_example(${PROJECT})

+ 0 - 3
examples/device/dfu_runtime/CMakeLists.txt

@@ -23,9 +23,6 @@ target_include_directories(${PROJECT} PUBLIC
         ${CMAKE_CURRENT_SOURCE_DIR}/src
         )
 
-# Example common such as compiler warnings
-include(${CMAKE_CURRENT_SOURCE_DIR}/../../example.cmake)
-
 # Configure compilation flags and libraries for the example... see the corresponding function
 # in hw/bsp/FAMILY/family.cmake for details.
 family_configure_device_example(${PROJECT})

+ 0 - 3
examples/device/dynamic_configuration/CMakeLists.txt

@@ -24,9 +24,6 @@ target_include_directories(${PROJECT} PUBLIC
         ${CMAKE_CURRENT_SOURCE_DIR}/src
         )
 
-# Example common such as compiler warnings
-include(${CMAKE_CURRENT_SOURCE_DIR}/../../example.cmake)
-
 # Configure compilation flags and libraries for the example... see the corresponding function
 # in hw/bsp/FAMILY/family.cmake for details.
 family_configure_device_example(${PROJECT})

+ 0 - 3
examples/device/hid_boot_interface/CMakeLists.txt

@@ -23,9 +23,6 @@ target_include_directories(${PROJECT} PUBLIC
         ${CMAKE_CURRENT_SOURCE_DIR}/src
         )
 
-# Example common such as compiler warnings
-include(${CMAKE_CURRENT_SOURCE_DIR}/../../example.cmake)
-
 # Configure compilation flags and libraries for the example... see the corresponding function
 # in hw/bsp/FAMILY/family.cmake for details.
 family_configure_device_example(${PROJECT})

+ 1 - 1
examples/device/hid_boot_interface/src/main.c

@@ -181,7 +181,7 @@ void tud_hid_set_protocol_cb(uint8_t instance, uint8_t protocol)
 // Invoked when sent REPORT successfully to host
 // Application can use this to send the next report
 // Note: For composite reports, report[0] is report ID
-void tud_hid_report_complete_cb(uint8_t instance, uint8_t const* report, uint16_t len)
+void tud_hid_report_complete_cb(uint8_t instance, uint8_t const* report, /*uint16_t*/ uint8_t len)
 {
   (void) instance;
   (void) report;

+ 0 - 3
examples/device/hid_composite/CMakeLists.txt

@@ -23,9 +23,6 @@ target_include_directories(${PROJECT} PUBLIC
         ${CMAKE_CURRENT_SOURCE_DIR}/src
         )
 
-# Example common such as compiler warnings
-include(${CMAKE_CURRENT_SOURCE_DIR}/../../example.cmake)
-
 # Configure compilation flags and libraries for the example... see the corresponding function
 # in hw/bsp/FAMILY/family.cmake for details.
 family_configure_device_example(${PROJECT})

+ 1 - 1
examples/device/hid_composite/src/main.c

@@ -225,7 +225,7 @@ void hid_task(void)
 // Invoked when sent REPORT successfully to host
 // Application can use this to send the next report
 // Note: For composite reports, report[0] is report ID
-void tud_hid_report_complete_cb(uint8_t instance, uint8_t const* report, uint16_t len)
+void tud_hid_report_complete_cb(uint8_t instance, uint8_t const* report, /*uint16_t*/ uint8_t len)
 {
   (void) instance;
   (void) len;

+ 1 - 1
examples/device/hid_composite_freertos/src/main.c

@@ -294,7 +294,7 @@ void hid_task(void* param)
 // Invoked when sent REPORT successfully to host
 // Application can use this to send the next report
 // Note: For composite reports, report[0] is report ID
-void tud_hid_report_complete_cb(uint8_t instance, uint8_t const* report, uint16_t len)
+void tud_hid_report_complete_cb(uint8_t instance, uint8_t const* report, /*uint16_t*/ uint8_t len)
 {
   (void) instance;
   (void) len;

+ 0 - 3
examples/device/hid_generic_inout/CMakeLists.txt

@@ -23,9 +23,6 @@ target_include_directories(${PROJECT} PUBLIC
         ${CMAKE_CURRENT_SOURCE_DIR}/src
         )
 
-# Example common such as compiler warnings
-include(${CMAKE_CURRENT_SOURCE_DIR}/../../example.cmake)
-
 # Configure compilation flags and libraries for the example... see the corresponding function
 # in hw/bsp/FAMILY/family.cmake for details.
 family_configure_device_example(${PROJECT})

+ 0 - 3
examples/device/hid_multiple_interface/CMakeLists.txt

@@ -23,9 +23,6 @@ target_include_directories(${PROJECT} PUBLIC
         ${CMAKE_CURRENT_SOURCE_DIR}/src
         )
 
-# Example common such as compiler warnings
-include(${CMAKE_CURRENT_SOURCE_DIR}/../../example.cmake)
-
 # Configure compilation flags and libraries for the example... see the corresponding function
 # in hw/bsp/FAMILY/family.cmake for details.
 family_configure_device_example(${PROJECT})

+ 0 - 3
examples/device/midi_test/CMakeLists.txt

@@ -23,9 +23,6 @@ target_include_directories(${PROJECT} PUBLIC
         ${CMAKE_CURRENT_SOURCE_DIR}/src
         )
 
-# Example common such as compiler warnings
-include(${CMAKE_CURRENT_SOURCE_DIR}/../../example.cmake)
-
 # Configure compilation flags and libraries for the example... see the corresponding function
 # in hw/bsp/FAMILY/family.cmake for details.
 family_configure_device_example(${PROJECT})

+ 0 - 3
examples/device/msc_dual_lun/CMakeLists.txt

@@ -24,9 +24,6 @@ target_include_directories(${PROJECT} PUBLIC
         ${CMAKE_CURRENT_SOURCE_DIR}/src
         )
 
-# Example common such as compiler warnings
-include(${CMAKE_CURRENT_SOURCE_DIR}/../../example.cmake)
-
 # Configure compilation flags and libraries for the example... see the corresponding function
 # in hw/bsp/FAMILY/family.cmake for details.
 family_configure_device_example(${PROJECT})

+ 0 - 3
examples/device/net_lwip_webserver/CMakeLists.txt

@@ -69,9 +69,6 @@ if (EXISTS ${TOP}/lib/lwip/src)
             ${TOP}/lib/networking/rndis_reports.c
             )
 
-    # Example common such as compiler warnings
-    include(${CMAKE_CURRENT_SOURCE_DIR}/../../example.cmake)
-
     # due to warnings from other net source, we need to prevent error from some of the warnings options
     target_compile_options(${PROJECT} PUBLIC
         -Wno-error=null-dereference

+ 0 - 3
examples/device/uac2_headset/CMakeLists.txt

@@ -23,9 +23,6 @@ target_include_directories(${PROJECT} PUBLIC
         ${CMAKE_CURRENT_SOURCE_DIR}/src
         )
 
-# Example common such as compiler warnings
-include(${CMAKE_CURRENT_SOURCE_DIR}/../../example.cmake)
-
 # Configure compilation flags and libraries for the example... see the corresponding function
 # in hw/bsp/FAMILY/family.cmake for details.
 family_configure_device_example(${PROJECT})

+ 2 - 1
examples/device/uac2_headset/skip.txt

@@ -3,4 +3,5 @@ mcu:LPC13XX
 mcu:NUC121
 mcu:SAMD11
 mcu:SAME5X
-mcu:SAMG
+mcu:SAMG
+board:stm32l052dap52

+ 0 - 3
examples/device/usbtmc/CMakeLists.txt

@@ -24,9 +24,6 @@ target_include_directories(${PROJECT} PUBLIC
         ${CMAKE_CURRENT_SOURCE_DIR}/src
         )
 
-# Example common such as compiler warnings
-include(${CMAKE_CURRENT_SOURCE_DIR}/../../example.cmake)
-
 # Configure compilation flags and libraries for the example... see the corresponding function
 # in hw/bsp/FAMILY/family.cmake for details.
 family_configure_device_example(${PROJECT})

+ 59 - 11
examples/device/usbtmc/src/usb_descriptors.c

@@ -37,6 +37,9 @@
 #define USB_PID           (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \
                            _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) )
 
+#define USB_VID   0xCafe
+#define USB_BCD   0x0200
+
 //--------------------------------------------------------------------+
 // Device Descriptors
 //--------------------------------------------------------------------+
@@ -51,9 +54,9 @@ tusb_desc_device_t const desc_device =
 
     .bMaxPacketSize0    = CFG_TUD_ENDPOINT0_SIZE,
 
-    .idVendor           = 0xCafe,
+    .idVendor           = USB_VID,
     .idProduct          = USB_PID,
-    .bcdDevice          = 0x0100,
+    .bcdDevice          = USB_BCD,
 
     .iManufacturer      = 0x01,
     .iProduct           = 0x02,
@@ -75,22 +78,22 @@ uint8_t const * tud_descriptor_device_cb(void)
 
 #if defined(CFG_TUD_USBTMC)
 
-#  define TUD_USBTMC_DESC_MAIN(_itfnum,_bNumEndpoints) \
+#  define TUD_USBTMC_DESC_MAIN(_itfnum,_bNumEndpoints, _bulkMaxPacketLength) \
      TUD_USBTMC_IF_DESCRIPTOR(_itfnum, _bNumEndpoints,  /*_stridx = */ 4u, TUD_USBTMC_PROTOCOL_USB488), \
-     TUD_USBTMC_BULK_DESCRIPTORS(/* OUT = */0x01, /* IN = */ 0x81, /* packet size = */USBTMCD_MAX_PACKET_SIZE)
+     TUD_USBTMC_BULK_DESCRIPTORS(/* OUT = */0x01, /* IN = */ 0x81, /* packet size = */_bulkMaxPacketLength)
 
 #if CFG_TUD_USBTMC_ENABLE_INT_EP
 // USBTMC Interrupt xfer always has length of 2, but we use epMaxSize=8 for
 //  compatibility with mcus that only allow 8, 16, 32 or 64 for FS endpoints
-#  define TUD_USBTMC_DESC(_itfnum) \
-     TUD_USBTMC_DESC_MAIN(_itfnum, /* _epCount = */ 3), \
+#  define TUD_USBTMC_DESC(_itfnum, _bulkMaxPacketLength) \
+     TUD_USBTMC_DESC_MAIN(_itfnum, /* _epCount = */ 3, _bulkMaxPacketLength), \
      TUD_USBTMC_INT_DESCRIPTOR(/* INT ep # */ 0x82, /* epMaxSize = */ 8, /* bInterval = */16u )
 #  define TUD_USBTMC_DESC_LEN (TUD_USBTMC_IF_DESCRIPTOR_LEN + TUD_USBTMC_BULK_DESCRIPTORS_LEN + TUD_USBTMC_INT_DESCRIPTOR_LEN)
 
 #else
 
-#  define TUD_USBTMC_DESC(_itfnum) \
-     TUD_USBTMC_DESC_MAIN(_itfnum, /* _epCount = */ 2u)
+#  define TUD_USBTMC_DESC(_itfnum, _bulkMaxPacketLength) \
+     TUD_USBTMC_DESC_MAIN(_itfnum, /* _epCount = */ 2u, _bulkMaxPacketLength)
 #  define TUD_USBTMC_DESC_LEN (TUD_USBTMC_IF_DESCRIPTOR_LEN + TUD_USBTMC_BULK_DESCRIPTORS_LEN)
 
 #endif /* CFG_TUD_USBTMC_ENABLE_INT_EP */
@@ -119,21 +122,66 @@ enum
 #endif
 
 
-uint8_t const desc_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),
 
-  TUD_USBTMC_DESC(ITF_NUM_USBTMC),
+  TUD_USBTMC_DESC(ITF_NUM_USBTMC, /* _bulkMaxPacketLength = */ 64),
 };
 
+#if TUD_OPT_HIGH_SPEED
+
+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),
+
+  TUD_USBTMC_DESC(ITF_NUM_USBTMC, /* _bulkMaxPacketLength = */ 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       = 0x00,
+  .bDeviceSubClass    = 0x00,
+  .bDeviceProtocol    = 0x00,
+
+  .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;
+}
+
+#endif
+
 // 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
-  return desc_configuration;
+#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
 }
 
 //--------------------------------------------------------------------+

+ 19 - 16
examples/device/usbtmc/visaQuery.py

@@ -1,6 +1,6 @@
 #!/usr/bin/env python3
 
-import visa
+import pyvisa
 import time
 import sys
 
@@ -54,9 +54,9 @@ def test_srq():
 	assert (inst.read_stb() == 0)
 	inst.write("123")
 	
-	#inst.enable_event(visa.constants.VI_EVENT_SERVICE_REQ, visa.constants.VI_QUEUE)
-	#waitrsp = inst.wait_on_event(visa.constants.VI_EVENT_SERVICE_REQ, 5000)
-	#inst.discard_events(visa.constants.VI_EVENT_SERVICE_REQ, visa.constants.VI_QUEUE)
+	#inst.enable_event(pyvisa.constants.VI_EVENT_SERVICE_REQ, pyvisa.constants.VI_QUEUE)
+	#waitrsp = inst.wait_on_event(pyvisa.constants.VI_EVENT_SERVICE_REQ, 5000)
+	#inst.discard_events(pyvisa.constants.VI_EVENT_SERVICE_REQ, pyvisa.constants.VI_QUEUE)
 	#inst.wait_for_srq()
 	time.sleep(0.3)
 	stb = inst.read_stb()
@@ -77,8 +77,8 @@ def test_read_timeout():
 	t0 = time.monotonic()
 	try:
 		rsp = inst.read()
-		assert(false), "Read should have resulted in timeout"
-	except visa.VisaIOError:
+		assert(False), "Read should have resulted in timeout"
+	except pyvisa.VisaIOError:
 		print("  Got expected exception")
 	t = time.monotonic() - t0
 	assert ((t*1000.0) > (inst.timeout - 300))
@@ -99,23 +99,27 @@ def test_abort_in():
 	t0 = time.monotonic()
 	try:
 		rsp = inst.read()
-		assert(false), "Read should have resulted in timeout"
-	except visa.VisaIOError:
+		assert(False), "Read should have resulted in timeout"
+	except pyvisa.VisaIOError:
 		print("  Got expected exception")
 	t = time.monotonic() - t0
 	assert ((t*1000.0) > (inst.timeout - 300))
 	assert ((t*1000.0) < (inst.timeout + 300))
 	print(f"  Delay was {t:0.3}")
-	# Response is still in queue, so send a clear (to be more helpful to the next test)
+	# Response is still in queue, so read it out (to be more helpful to the next test)
 	inst.timeout = 800
 	y = inst.read()
 	assert(y == "xxx\r\n")
 	
 def test_indicate():
 	# perform indicator pulse
-	usb_iface = inst.get_visa_attribute(visa.constants.VI_ATTR_USB_INTFC_NUM)
+	usb_iface = inst.get_visa_attribute(pyvisa.constants.VI_ATTR_USB_INTFC_NUM)
 	retv = inst.control_in(request_type_bitmap_field=0xA1, request_id=64, request_value=0x0000, index=usb_iface, length=0x0001)
-	assert((retv[1] == visa.constants.StatusCode(0)) and (retv[0] == b'\x01')), f"indicator pulse failed: retv={retv}"
+	# pyvisa used to return (statuscode,bytes), but now only returns bytes, so we need to handle both cases
+	if(isinstance(retv,bytes)):
+		assert(retv == b'\x01')
+	else:
+		assert((retv[1] == pyvisa.constants.StatusCode(0)) and (retv[0] == b'\x01')), f"indicator pulse failed: retv={retv}"
 	
 	
 def test_multi_read():
@@ -131,19 +135,19 @@ def test_multi_read():
 	#inst.chunk_size = old_chunk_size
 	
 def test_stall_ep0():
-	usb_iface = inst.get_visa_attribute(visa.constants.VI_ATTR_USB_INTFC_NUM)
+	usb_iface = inst.get_visa_attribute(pyvisa.constants.VI_ATTR_USB_INTFC_NUM)
 	inst.read_stb()
 	# This is an invalid request, should create stall.
 	try:
 		retv = inst.control_in(request_type_bitmap_field=0xA1, request_id=60, request_value=0x0000, index=usb_iface, length=0x0001)
-		assert false
-	except visa.VisaIOError:
+		assert(False)
+	except pyvisa.VisaIOError:
 		pass
 	
 	assert (inst.read_stb() == 0)
 
 
-rm = visa.ResourceManager()
+rm = pyvisa.ResourceManager()
 reslist = rm.list_resources("USB?::?*::INSTR")
 print(reslist)
 
@@ -167,7 +171,6 @@ inst.timeout = 2000
 print("+ multi read")
 test_multi_read()
 
-
 print("+ echo delay=0")
 inst.write("delay 0")
 test_echo(1,175)

+ 0 - 3
examples/device/video_capture/CMakeLists.txt

@@ -23,9 +23,6 @@ target_include_directories(${PROJECT} PUBLIC
   ${CMAKE_CURRENT_SOURCE_DIR}/src
 )
 
-# Example common such as compiler warnings
-include(${CMAKE_CURRENT_SOURCE_DIR}/../../example.cmake)
-
 # Configure compilation flags and libraries for the example... see the corresponding function
 # in hw/bsp/FAMILY/family.cmake for details.
 family_configure_device_example(${PROJECT})

+ 0 - 3
examples/device/webusb_serial/CMakeLists.txt

@@ -23,9 +23,6 @@ target_include_directories(${PROJECT} PUBLIC
         ${CMAKE_CURRENT_SOURCE_DIR}/src
         )
 
-# Example common such as compiler warnings
-include(${CMAKE_CURRENT_SOURCE_DIR}/../../example.cmake)
-
 # Configure compilation flags and libraries for the example... see the corresponding function
 # in hw/bsp/FAMILY/family.cmake for details.
 family_configure_device_example(${PROJECT})

+ 4 - 2
examples/device/webusb_serial/src/main.c

@@ -71,7 +71,7 @@ enum  {
 
 static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED;
 
-#define URL  "example.tinyusb.org/webusb-serial/"
+#define URL  "example.tinyusb.org/webusb-serial/index.html"
 
 const tusb_desc_webusb_url_t desc_url =
 {
@@ -114,6 +114,7 @@ void echo_all(uint8_t buf[], uint32_t count)
   if ( web_serial_connected )
   {
     tud_vendor_write(buf, count);
+    tud_vendor_flush();
   }
 
   // echo to cdc
@@ -211,7 +212,8 @@ bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_requ
           board_led_write(true);
           blink_interval_ms = BLINK_ALWAYS_ON;
 
-          tud_vendor_write_str("\r\nTinyUSB WebUSB device example\r\n");
+          tud_vendor_write_str("\r\nWebUSB interface connected\r\n");
+          tud_vendor_flush();
         }else
         {
           blink_interval_ms = BLINK_MOUNTED;

+ 3 - 6
examples/dual/host_hid_to_device_cdc/CMakeLists.txt

@@ -23,8 +23,9 @@ target_include_directories(${PROJECT} PUBLIC
         ${CMAKE_CURRENT_SOURCE_DIR}/src
         )
 
-# Example common such as compiler warnings
-include(${CMAKE_CURRENT_SOURCE_DIR}/../../example.cmake)
+# Configure compilation flags and libraries for the example... see the corresponding function
+# in hw/bsp/FAMILY/family.cmake for details.
+family_configure_dual_usb_example(${PROJECT})
 
 # due to warnings from other net source, we need to prevent error from some of the warnings options
 target_compile_options(${PROJECT} PUBLIC
@@ -37,7 +38,3 @@ target_compile_options(${PROJECT} PUBLIC
         -Wno-error=sign-compare
         -Wno-error=unused-function
         )
-
-# Configure compilation flags and libraries for the example... see the corresponding function
-# in hw/bsp/FAMILY/family.cmake for details.
-family_configure_dual_usb_example(${PROJECT})

+ 0 - 31
examples/example.cmake

@@ -1,31 +0,0 @@
-target_compile_options(${PROJECT} PUBLIC
-        -Wall
-        -Wextra
-        -Werror
-        -Wfatal-errors
-        -Wdouble-promotion
-        #-Wstrict-prototypes
-        -Wstrict-overflow
-        #-Werror-implicit-function-declaration
-        -Wfloat-equal
-        #-Wundef
-        -Wshadow
-        -Wwrite-strings
-        -Wsign-compare
-        -Wmissing-format-attribute
-        -Wunreachable-code
-        -Wcast-align
-        -Wcast-function-type
-        -Wcast-qual
-        -Wnull-dereference
-        -Wuninitialized
-        -Wunused
-        -Wredundant-decls
-        )
-
-# GCC version 9 or prior has a bug with incorrect Wconversion warnings
-if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 10.0)
-  target_compile_options(${PROJECT} PUBLIC
-        -Wconversion
-        )
-endif()

+ 0 - 3
examples/host/bare_api/CMakeLists.txt

@@ -22,9 +22,6 @@ target_include_directories(${PROJECT} PUBLIC
         ${CMAKE_CURRENT_SOURCE_DIR}/src
         )
 
-# Example common such as compiler warnings
-include(${CMAKE_CURRENT_SOURCE_DIR}/../../example.cmake)
-
 # Configure compilation flags and libraries for the example... see the corresponding function
 # in hw/bsp/FAMILY/family.cmake for details.
 family_configure_host_example(${PROJECT})

+ 0 - 3
examples/host/cdc_msc_hid/CMakeLists.txt

@@ -24,9 +24,6 @@ target_include_directories(${PROJECT} PUBLIC
         ${CMAKE_CURRENT_SOURCE_DIR}/src
         )
 
-# Example common such as compiler warnings
-include(${CMAKE_CURRENT_SOURCE_DIR}/../../example.cmake)
-
 # Configure compilation flags and libraries for the example... see the corresponding function
 # in hw/bsp/FAMILY/family.cmake for details.
 family_configure_host_example(${PROJECT})

+ 0 - 3
examples/host/hid_controller/CMakeLists.txt

@@ -23,9 +23,6 @@ target_include_directories(${PROJECT} PUBLIC
         ${CMAKE_CURRENT_SOURCE_DIR}/src
         )
 
-# Example common such as compiler warnings
-include(${CMAKE_CURRENT_SOURCE_DIR}/../../example.cmake)
-
 # Configure compilation flags and libraries for the example... see the corresponding function
 # in hw/bsp/FAMILY/family.cmake for details.
 family_configure_host_example(${PROJECT})

+ 42 - 0
hw/bsp/family_support.cmake

@@ -79,6 +79,48 @@ if (NOT TARGET _family_support_marker)
         endif()
     endfunction()
 
+    function(family_add_default_example_warnings TARGET)
+        target_compile_options(${TARGET} PUBLIC
+                -Wall
+                -Wextra
+                -Werror
+                -Wfatal-errors
+                -Wdouble-promotion
+                -Wfloat-equal
+                -Wshadow
+                -Wwrite-strings
+                -Wsign-compare
+                -Wmissing-format-attribute
+                -Wunreachable-code
+                -Wcast-align
+                -Wcast-qual
+                -Wnull-dereference
+                -Wuninitialized
+                -Wunused
+                -Wredundant-decls
+                #-Wstrict-prototypes
+                #-Werror-implicit-function-declaration
+                #-Wundef
+                )
+
+        if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
+            # GCC 10
+            if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 10.0)
+                target_compile_options(${TARGET} PUBLIC -Wconversion)
+            endif()
+
+            # GCC 8
+            if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 8.0)
+                target_compile_options(${TARGET} PUBLIC -Wcast-function-type -Wstrict-overflow)
+            endif()
+
+            # GCC 6
+            if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 6.0)
+                target_compile_options(${TARGET} PUBLIC -Wno-strict-aliasing)
+            endif()
+        endif()
+    endfunction()
+
     # configure an executable target to link to tinyusb in device mode, and add the board implementation
     function(family_configure_device_example TARGET)
         # default implentation is empty, the function should be redefined in the FAMILY/family.cmake

+ 43 - 28
hw/bsp/rp2040/family.cmake

@@ -147,16 +147,23 @@ if (NOT TARGET _rp2040_family_inclusion_marker)
 		target_link_libraries(${TARGET} PUBLIC pico_stdlib pico_bootsel_via_double_reset tinyusb_board tinyusb_additions)
 	endfunction()
 
+	function(rp2040_family_configure_example_warnings TARGET)
+		if (NOT PICO_TINYUSB_NO_EXAMPLE_WARNINGS)
+			family_add_default_example_warnings(${TARGET})
+		endif()
+		suppress_tinyusb_warnings()
+	endfunction()
+
 	function(family_configure_device_example TARGET)
 		family_configure_target(${TARGET})
 		target_link_libraries(${TARGET} PUBLIC pico_stdlib tinyusb_device)
-		suppress_tinyusb_warnings()
+		rp2040_family_configure_example_warnings(${TARGET})
 	endfunction()
 
 	function(family_configure_host_example TARGET)
 		family_configure_target(${TARGET})
 		target_link_libraries(${TARGET} PUBLIC pico_stdlib tinyusb_host)
-		suppress_tinyusb_warnings()
+		rp2040_family_configure_example_warnings(${TARGET})
 	endfunction()
 
 	function(family_add_pico_pio_usb TARGET)
@@ -167,7 +174,7 @@ if (NOT TARGET _rp2040_family_inclusion_marker)
 		family_configure_target(${TARGET})
 		# require tinyusb_pico_pio_usb
 		target_link_libraries(${TARGET} PUBLIC pico_stdlib tinyusb_device tinyusb_host tinyusb_pico_pio_usb )
-		suppress_tinyusb_warnings()
+		rp2040_family_configure_example_warnings(${TARGET})
 	endfunction()
 
 	function(check_and_add_pico_pio_usb_support)
@@ -236,30 +243,38 @@ if (NOT TARGET _rp2040_family_inclusion_marker)
 	# This method must be called from the project scope to suppress known warnings in TinyUSB source files
 	function(suppress_tinyusb_warnings)
 		# some of these are pretty silly warnings only occurring in some older GCC versions 9 or prior
-		if (CMAKE_C_COMPILER_VERSION VERSION_LESS 10.0)
-  		set(CONVERSION_WARNING_FILES
-  				${PICO_TINYUSB_PATH}/src/tusb.c
-  				${PICO_TINYUSB_PATH}/src/common/tusb_fifo.c
-  				${PICO_TINYUSB_PATH}/src/device/usbd.c
-  				${PICO_TINYUSB_PATH}/src/device/usbd_control.c
-  				${PICO_TINYUSB_PATH}/src/host/usbh.c
-  				${PICO_TINYUSB_PATH}/src/class/cdc/cdc_device.c
-  				${PICO_TINYUSB_PATH}/src/class/cdc/cdc_host.c
-  				${PICO_TINYUSB_PATH}/src/class/hid/hid_device.c
-  				${PICO_TINYUSB_PATH}/src/class/hid/hid_host.c
-  				${PICO_TINYUSB_PATH}/src/class/audio/audio_device.c
-  				${PICO_TINYUSB_PATH}/src/class/dfu/dfu_device.c
-  				${PICO_TINYUSB_PATH}/src/class/dfu/dfu_rt_device.c
-  				${PICO_TINYUSB_PATH}/src/class/midi/midi_device.c
-  				${PICO_TINYUSB_PATH}/src/class/usbtmc/usbtmc_device.c
-  				${PICO_TINYUSB_PATH}/src/portable/raspberrypi/rp2040/hcd_rp2040.c
-  				)
-  		foreach(SOURCE_FILE IN LISTS CONVERSION_WARNING_FILES)
-  			set_source_files_properties(
-  					${SOURCE_FILE}
-  					PROPERTIES
-  					COMPILE_FLAGS "-Wno-conversion")
-  		endforeach()
-  	endif()
+		if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
+			if (CMAKE_C_COMPILER_VERSION VERSION_LESS 10.0)
+				set(CONVERSION_WARNING_FILES
+					${PICO_TINYUSB_PATH}/src/tusb.c
+					${PICO_TINYUSB_PATH}/src/common/tusb_fifo.c
+					${PICO_TINYUSB_PATH}/src/device/usbd.c
+					${PICO_TINYUSB_PATH}/src/device/usbd_control.c
+					${PICO_TINYUSB_PATH}/src/host/usbh.c
+					${PICO_TINYUSB_PATH}/src/class/cdc/cdc_device.c
+					${PICO_TINYUSB_PATH}/src/class/cdc/cdc_host.c
+					${PICO_TINYUSB_PATH}/src/class/hid/hid_device.c
+					${PICO_TINYUSB_PATH}/src/class/hid/hid_host.c
+					${PICO_TINYUSB_PATH}/src/class/audio/audio_device.c
+					${PICO_TINYUSB_PATH}/src/class/dfu/dfu_device.c
+					${PICO_TINYUSB_PATH}/src/class/dfu/dfu_rt_device.c
+					${PICO_TINYUSB_PATH}/src/class/midi/midi_device.c
+					${PICO_TINYUSB_PATH}/src/class/usbtmc/usbtmc_device.c
+					${PICO_TINYUSB_PATH}/src/portable/raspberrypi/rp2040/hcd_rp2040.c
+					)
+				foreach(SOURCE_FILE IN LISTS CONVERSION_WARNING_FILES)
+					set_source_files_properties(
+							${SOURCE_FILE}
+							PROPERTIES
+							COMPILE_FLAGS "-Wno-conversion")
+				endforeach()
+			endif()
+			if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 11.0)
+				set_source_files_properties(
+						${PICO_TINYUSB_PATH}/src/portable/raspberrypi/rp2040/rp2040_usb.c
+						PROPERTIES
+						COMPILE_FLAGS "-Wno-stringop-overflow -Wno-array-bounds")
+			endif()
+		endif()
 	endfunction()
 endif()

+ 169 - 0
hw/bsp/stm32l0/boards/stm32l052dap52/STM32L052K8Ux_FLASH.ld

@@ -0,0 +1,169 @@
+/*
+*****************************************************************************
+**
+
+**  File        : LinkerScript.ld
+**
+**  Abstract    : Linker script for STM32L052K8Ux Device with
+**                64KByte FLASH, 8KByte RAM
+**
+**                Set heap size, stack size and stack location according
+**                to application requirements.
+**
+**                Set memory bank area and size if external memory is used.
+**
+**  Target      : STMicroelectronics STM32
+**
+**
+**  Distribution: The file is distributed as is, without any warranty
+**                of any kind.
+**
+**  (c)Copyright Ac6.
+**  You may use this file as-is or modify it according to the needs of your
+**  project. Distribution of this file (unmodified or modified) is not
+**  permitted. Ac6 permit registered System Workbench for MCU users the
+**  rights to distribute the assembled, compiled & linked contents of this
+**  file as part of an application binary file, provided that it is built
+**  using the System Workbench for MCU toolchain.
+**
+*****************************************************************************
+*/
+
+/* Entry Point */
+ENTRY(Reset_Handler)
+
+/* Highest address of the user mode stack */
+_estack = 0x20002000;    /* end of RAM */
+/* Generate a link error if heap and stack don't fit into RAM */
+_Min_Heap_Size = 0x200;      /* required amount of heap  */
+_Min_Stack_Size = 0x400; /* required amount of stack */
+
+/* Specify the memory areas */
+MEMORY
+{
+FLASH (rx)      : ORIGIN = 0x8000000, LENGTH = 64K
+RAM (xrw)      : ORIGIN = 0x20000000, LENGTH = 8K
+}
+
+/* Define output sections */
+SECTIONS
+{
+  /* The startup code goes first into FLASH */
+  .isr_vector :
+  {
+    . = ALIGN(4);
+    KEEP(*(.isr_vector)) /* Startup code */
+    . = ALIGN(4);
+  } >FLASH
+
+  /* The program code and other data goes into FLASH */
+  .text :
+  {
+    . = ALIGN(4);
+    *(.text)           /* .text sections (code) */
+    *(.text*)          /* .text* sections (code) */
+    *(.glue_7)         /* glue arm to thumb code */
+    *(.glue_7t)        /* glue thumb to arm code */
+    *(.eh_frame)
+
+    KEEP (*(.init))
+    KEEP (*(.fini))
+
+    . = ALIGN(4);
+    _etext = .;        /* define a global symbols at end of code */
+  } >FLASH
+
+  /* Constant data goes into FLASH */
+  .rodata :
+  {
+    . = ALIGN(4);
+    *(.rodata)         /* .rodata sections (constants, strings, etc.) */
+    *(.rodata*)        /* .rodata* sections (constants, strings, etc.) */
+    . = ALIGN(4);
+  } >FLASH
+
+  .ARM.extab   : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH
+  .ARM : {
+    __exidx_start = .;
+    *(.ARM.exidx*)
+    __exidx_end = .;
+  } >FLASH
+
+  .preinit_array     :
+  {
+    PROVIDE_HIDDEN (__preinit_array_start = .);
+    KEEP (*(.preinit_array*))
+    PROVIDE_HIDDEN (__preinit_array_end = .);
+  } >FLASH
+  .init_array :
+  {
+    PROVIDE_HIDDEN (__init_array_start = .);
+    KEEP (*(SORT(.init_array.*)))
+    KEEP (*(.init_array*))
+    PROVIDE_HIDDEN (__init_array_end = .);
+  } >FLASH
+  .fini_array :
+  {
+    PROVIDE_HIDDEN (__fini_array_start = .);
+    KEEP (*(SORT(.fini_array.*)))
+    KEEP (*(.fini_array*))
+    PROVIDE_HIDDEN (__fini_array_end = .);
+  } >FLASH
+
+  /* used by the startup to initialize data */
+  _sidata = LOADADDR(.data);
+
+  /* Initialized data sections goes into RAM, load LMA copy after code */
+  .data : 
+  {
+    . = ALIGN(4);
+    _sdata = .;        /* create a global symbol at data start */
+    *(.data)           /* .data sections */
+    *(.data*)          /* .data* sections */
+
+    . = ALIGN(4);
+    _edata = .;        /* define a global symbol at data end */
+  } >RAM AT> FLASH
+
+  
+  /* Uninitialized data section */
+  . = ALIGN(4);
+  .bss :
+  {
+    /* This is used by the startup in order to initialize the .bss secion */
+    _sbss = .;         /* define a global symbol at bss start */
+    __bss_start__ = _sbss;
+    *(.bss)
+    *(.bss*)
+    *(COMMON)
+
+    . = ALIGN(4);
+    _ebss = .;         /* define a global symbol at bss end */
+    __bss_end__ = _ebss;
+  } >RAM
+
+  /* User_heap_stack section, used to check that there is enough RAM left */
+  ._user_heap_stack :
+  {
+    . = ALIGN(8);
+    PROVIDE ( end = . );
+    PROVIDE ( _end = . );
+    . = . + _Min_Heap_Size;
+    . = . + _Min_Stack_Size;
+    . = ALIGN(8);
+  } >RAM
+
+  
+
+  /* Remove information from the standard libraries */
+  /DISCARD/ :
+  {
+    libc.a ( * )
+    libm.a ( * )
+    libgcc.a ( * )
+  }
+
+  .ARM.attributes 0 : { *(.ARM.attributes) }
+}
+
+

+ 109 - 0
hw/bsp/stm32l0/boards/stm32l052dap52/board.h

@@ -0,0 +1,109 @@
+/* 
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020, Ha Thach (tinyusb.org)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * This file is part of the TinyUSB stack.
+ */
+
+#ifndef BOARD_H_
+#define BOARD_H_
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+// LED
+#define LED_PORT              GPIOB
+#define LED_PIN               GPIO_PIN_4
+#define LED_STATE_ON          1
+
+// Button
+#define BUTTON_PORT           GPIOA
+#define BUTTON_PIN            GPIO_PIN_6
+#define BUTTON_STATE_ACTIVE   0
+
+// UART
+#define UART_DEV              USART2
+#define UART_CLK_EN           __HAL_RCC_USART2_CLK_ENABLE
+#define UART_GPIO_PORT        GPIOA
+#define UART_GPIO_AF          GPIO_AF4_USART2
+#define UART_TX_PIN           GPIO_PIN_2
+#define UART_RX_PIN           GPIO_PIN_3
+
+//--------------------------------------------------------------------+
+// RCC Clock
+//--------------------------------------------------------------------+
+static inline void board_stm32l0_clock_init(void)
+{
+  RCC_ClkInitTypeDef RCC_ClkInitStruct;
+  RCC_OscInitTypeDef RCC_OscInitStruct;
+  RCC_PeriphCLKInitTypeDef  PeriphClkInitStruct;
+  static RCC_CRSInitTypeDef RCC_CRSInitStruct;
+  
+  /* Enable HSI Oscillator to be used as System clock source
+     Enable HSI48 Oscillator to be used as USB clock source */
+  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI | RCC_OSCILLATORTYPE_HSI48;
+  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
+  RCC_OscInitStruct.HSI48State = RCC_HSI48_ON;
+  HAL_RCC_OscConfig(&RCC_OscInitStruct); 
+ 
+  /* Select HSI48 as USB clock source */
+  PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USB;
+  PeriphClkInitStruct.UsbClockSelection = RCC_USBCLKSOURCE_HSI48;
+  HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);
+  
+  /* Select HSI as system clock source and configure the HCLK, PCLK1 and PCLK2 
+     clock dividers */
+  RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
+  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
+  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
+  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;  
+  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;  
+  HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0);
+    
+  /*Configure the clock recovery system (CRS)**********************************/
+  
+  /*Enable CRS Clock*/
+  __HAL_RCC_CRS_CLK_ENABLE(); 
+  
+  /* Default Synchro Signal division factor (not divided) */
+  RCC_CRSInitStruct.Prescaler = RCC_CRS_SYNC_DIV1;  
+  /* Set the SYNCSRC[1:0] bits according to CRS_Source value */
+  RCC_CRSInitStruct.Source = RCC_CRS_SYNC_SOURCE_USB;  
+  /* HSI48 is synchronized with USB SOF at 1KHz rate */
+  RCC_CRSInitStruct.ReloadValue =  __HAL_RCC_CRS_RELOADVALUE_CALCULATE(48000000, 1000);
+  RCC_CRSInitStruct.ErrorLimitValue = RCC_CRS_ERRORLIMIT_DEFAULT;  
+  /* Set the TRIM[5:0] to the default value*/
+  RCC_CRSInitStruct.HSI48CalibrationValue = 0x20;   
+  /* Start automatic synchronization */ 
+  HAL_RCCEx_CRSConfig (&RCC_CRSInitStruct);
+}
+
+static inline void board_vbus_sense_init(void)
+{
+}
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* BOARD_H_ */

+ 11 - 0
hw/bsp/stm32l0/boards/stm32l052dap52/board.mk

@@ -0,0 +1,11 @@
+CFLAGS += -DSTM32L052xx -DCFG_EXAMPLE_VIDEO_READONLY
+
+LD_FILE = $(BOARD_PATH)/STM32L052K8Ux_FLASH.ld
+
+SRC_S += $(ST_CMSIS)/Source/Templates/gcc/startup_stm32l052xx.s
+
+# For flash-jlink target
+JLINK_DEVICE = stm32l052k8
+
+# flash target using on-board stlink
+flash: flash-stlink

+ 181 - 0
hw/bsp/stm32l0/family.c

@@ -0,0 +1,181 @@
+/* 
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Ha Thach (tinyusb.org)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * This file is part of the TinyUSB stack.
+ */
+
+#include "stm32l0xx_hal.h"
+#include "bsp/board.h"
+#include "board.h"
+
+//--------------------------------------------------------------------+
+// Forward USB interrupt events to TinyUSB IRQ Handler
+//--------------------------------------------------------------------+
+void USB_IRQHandler(void)
+{
+  tud_int_handler(0);
+}
+
+//--------------------------------------------------------------------+
+// MACRO TYPEDEF CONSTANT ENUM
+//--------------------------------------------------------------------+
+UART_HandleTypeDef UartHandle;
+
+void board_init(void)
+{
+  board_stm32l0_clock_init();
+
+  // Enable All GPIOs clocks
+  __HAL_RCC_GPIOA_CLK_ENABLE();
+  __HAL_RCC_GPIOB_CLK_ENABLE();
+  __HAL_RCC_GPIOC_CLK_ENABLE();
+  __HAL_RCC_GPIOD_CLK_ENABLE();
+
+  // Enable UART Clock
+  UART_CLK_EN();
+
+#if CFG_TUSB_OS == OPT_OS_NONE
+  // 1ms tick timer
+  SysTick_Config(SystemCoreClock / 1000);
+
+#elif CFG_TUSB_OS == OPT_OS_FREERTOS
+  // Explicitly disable systick to prevent its ISR runs before scheduler start
+  SysTick->CTRL &= ~1U;
+
+  // If freeRTOS is used, IRQ priority is limit by max syscall ( smaller is higher )
+  NVIC_SetPriority(USB_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY);
+#endif
+
+  // LED
+  GPIO_InitTypeDef  GPIO_InitStruct;
+  GPIO_InitStruct.Pin = LED_PIN;
+  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
+  GPIO_InitStruct.Pull = GPIO_PULLUP;
+  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
+  HAL_GPIO_Init(LED_PORT, &GPIO_InitStruct);
+
+  // Button
+  GPIO_InitStruct.Pin = BUTTON_PIN;
+  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
+  GPIO_InitStruct.Pull = GPIO_PULLDOWN;
+  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
+  HAL_GPIO_Init(BUTTON_PORT, &GPIO_InitStruct);
+
+  // Uart
+  GPIO_InitStruct.Pin       = UART_TX_PIN | UART_RX_PIN;
+  GPIO_InitStruct.Mode      = GPIO_MODE_AF_PP;
+  GPIO_InitStruct.Pull      = GPIO_PULLUP;
+  GPIO_InitStruct.Speed     = GPIO_SPEED_FREQ_HIGH;
+  GPIO_InitStruct.Alternate = UART_GPIO_AF;
+  HAL_GPIO_Init(UART_GPIO_PORT, &GPIO_InitStruct);
+
+  UartHandle.Instance        = UART_DEV;
+  UartHandle.Init.BaudRate   = CFG_BOARD_UART_BAUDRATE;
+  UartHandle.Init.WordLength = UART_WORDLENGTH_8B;
+  UartHandle.Init.StopBits   = UART_STOPBITS_1;
+  UartHandle.Init.Parity     = UART_PARITY_NONE;
+  UartHandle.Init.HwFlowCtl  = UART_HWCONTROL_NONE;
+  UartHandle.Init.Mode       = UART_MODE_TX_RX;
+  UartHandle.Init.OverSampling = UART_OVERSAMPLING_16;
+  HAL_UART_Init(&UartHandle);
+
+  // USB Pins
+  // Configure USB DM and DP pins. This is optional, and maintained only for user guidance.
+  GPIO_InitStruct.Pin = (GPIO_PIN_11 | GPIO_PIN_12);
+  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
+  GPIO_InitStruct.Pull = GPIO_NOPULL;
+  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
+  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
+
+  // USB Clock enable
+  __HAL_RCC_USB_CLK_ENABLE();
+}
+
+//--------------------------------------------------------------------+
+// Board porting API
+//--------------------------------------------------------------------+
+
+void board_led_write(bool state)
+{
+  HAL_GPIO_WritePin(LED_PORT, LED_PIN, state ? LED_STATE_ON : (1-LED_STATE_ON));
+}
+
+uint32_t board_button_read(void)
+{
+  return BUTTON_STATE_ACTIVE == HAL_GPIO_ReadPin(BUTTON_PORT, BUTTON_PIN);
+}
+
+int board_uart_read(uint8_t* buf, int len)
+{
+  (void) buf; (void) len;
+  return 0;
+}
+
+int board_uart_write(void const * buf, int len)
+{
+  HAL_UART_Transmit(&UartHandle, (uint8_t*)(uintptr_t) buf, len, 0xffff);
+  return len;
+}
+
+#if CFG_TUSB_OS  == OPT_OS_NONE
+volatile uint32_t system_ticks = 0;
+void SysTick_Handler (void)
+{
+  system_ticks++;
+}
+
+uint32_t board_millis(void)
+{
+  return system_ticks;
+}
+#endif
+
+void HardFault_Handler (void)
+{
+  asm("bkpt");
+}
+
+#ifdef  USE_FULL_ASSERT
+/**
+  * @brief  Reports the name of the source file and the source line number
+  *         where the assert_param error has occurred.
+  * @param  file: pointer to the source file name
+  * @param  line: assert_param error line source number
+  * @retval None
+  */
+void assert_failed(uint8_t* file, uint32_t line)
+{
+  (void) file; (void) line;
+  /* USER CODE BEGIN 6 */
+  /* User can add his own implementation to report the file name and line number,
+     tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
+  /* USER CODE END 6 */
+}
+#endif /* USE_FULL_ASSERT */
+
+// Required by __libc_init_array in startup code if we are compiling using
+// -nostdlib/-nostartfiles.
+void _init(void)
+{
+
+}

+ 40 - 0
hw/bsp/stm32l0/family.mk

@@ -0,0 +1,40 @@
+ST_FAMILY = l0
+DEPS_SUBMODULES += lib/CMSIS_5 hw/mcu/st/cmsis_device_$(ST_FAMILY) hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver
+
+ST_CMSIS = hw/mcu/st/cmsis_device_$(ST_FAMILY)
+ST_HAL_DRIVER = hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver
+
+include $(TOP)/$(BOARD_PATH)/board.mk
+
+CFLAGS += \
+  -flto \
+  -mthumb \
+  -mabi=aapcs \
+  -mcpu=cortex-m0plus \
+  -mfloat-abi=soft \
+  -nostdlib -nostartfiles \
+  -DCFG_EXAMPLE_MSC_READONLY \
+  -DCFG_EXAMPLE_VIDEO_READONLY \
+  -DCFG_TUSB_MCU=OPT_MCU_STM32L0
+
+# suppress warning caused by vendor mcu driver
+CFLAGS += -Wno-error=unused-parameter -Wno-error=redundant-decls -Wno-error=cast-align -Wno-error=maybe-uninitialized
+
+SRC_C += \
+  src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \
+  $(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \
+  $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \
+  $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \
+  $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc.c \
+  $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc_ex.c \
+  $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_gpio.c \
+  $(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_uart.c
+
+INC += \
+	$(TOP)/$(BOARD_PATH) \
+  $(TOP)/lib/CMSIS_5/CMSIS/Core/Include \
+  $(TOP)/$(ST_CMSIS)/Include \
+  $(TOP)/$(ST_HAL_DRIVER)/Inc
+
+# For freeRTOS port source
+FREERTOS_PORT = ARM_CM0

+ 338 - 0
hw/bsp/stm32l0/stm32l0xx_hal_conf.h

@@ -0,0 +1,338 @@
+/**
+  ******************************************************************************
+  * @file    stm32l0xx_hal_conf.h
+  * @author  MCD Application Team
+  * @brief   HAL configuration template file. 
+  *          This file should be copied to the application folder and renamed
+  *          to stm32l0xx_hal_conf.h.
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>&copy; Copyright (c) 2016 STMicroelectronics. 
+  * All rights reserved.</center></h2>
+  *
+  * This software component is licensed by ST under BSD 3-Clause license,
+  * the "License"; You may not use this file except in compliance with the 
+  * License. You may obtain a copy of the License at:
+  *                        opensource.org/licenses/BSD-3-Clause
+  *
+  ******************************************************************************
+  */ 
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM32L0xx_HAL_CONF_H
+#define __STM32L0xx_HAL_CONF_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* Exported types ------------------------------------------------------------*/
+/* Exported constants --------------------------------------------------------*/
+
+/* ########################## Module Selection ############################## */
+/**
+  * @brief This is the list of modules to be used in the HAL driver 
+  */
+#define HAL_MODULE_ENABLED  
+/*#define HAL_ADC_MODULE_ENABLED */
+/*#define HAL_COMP_MODULE_ENABLED */
+/*#define HAL_CRC_MODULE_ENABLED */
+/*#define HAL_CRYP_MODULE_ENABLED */
+/*#define HAL_DAC_MODULE_ENABLED */
+#define HAL_DMA_MODULE_ENABLED
+/*#define HAL_FIREWALL_MODULE_ENABLED */
+#define HAL_FLASH_MODULE_ENABLED
+#define HAL_GPIO_MODULE_ENABLED
+/*#define HAL_I2C_MODULE_ENABLED */
+/*#define HAL_I2S_MODULE_ENABLED */
+/*#define HAL_IWDG_MODULE_ENABLED */
+/*#define HAL_LCD_MODULE_ENABLED */
+/*#define HAL_LPTIM_MODULE_ENABLED */
+#define HAL_PWR_MODULE_ENABLED
+#define HAL_RCC_MODULE_ENABLED
+/*#define HAL_RNG_MODULE_ENABLED */
+/*#define HAL_RTC_MODULE_ENABLED */
+/*#define HAL_SPI_MODULE_ENABLED */
+/*#define HAL_TIM_MODULE_ENABLED */
+/*#define HAL_TSC_MODULE_ENABLED */
+#define HAL_UART_MODULE_ENABLED
+/*#define HAL_USART_MODULE_ENABLED */
+/*#define HAL_IRDA_MODULE_ENABLED */
+/*#define HAL_SMARTCARD_MODULE_ENABLED */
+/*#define HAL_SMBUS_MODULE_ENABLED */
+/*#define HAL_WWDG_MODULE_ENABLED */
+#define HAL_CORTEX_MODULE_ENABLED
+#define HAL_PCD_MODULE_ENABLED
+
+/* ########################## Oscillator Values adaptation ####################*/
+/**
+  * @brief Adjust the value of External High Speed oscillator (HSE) used in your application.
+  *        This value is used by the RCC HAL module to compute the system frequency
+  *        (when HSE is used as system clock source, directly or through the PLL).  
+  */
+#if !defined  (HSE_VALUE) 
+  #define HSE_VALUE    ((uint32_t)8000000U) /*!< Value of the External oscillator in Hz */
+#endif /* HSE_VALUE */
+
+#if !defined  (HSE_STARTUP_TIMEOUT)
+  #define HSE_STARTUP_TIMEOUT    ((uint32_t)100U)   /*!< Time out for HSE start up, in ms */
+#endif /* HSE_STARTUP_TIMEOUT */
+
+/**
+  * @brief Internal Multiple Speed oscillator (MSI) default value.
+  *        This value is the default MSI range value after Reset.
+  */
+#if !defined  (MSI_VALUE)
+  #define MSI_VALUE    ((uint32_t)2097152U) /*!< Value of the Internal oscillator in Hz*/
+#endif /* MSI_VALUE */
+
+/**
+  * @brief Internal High Speed oscillator (HSI) value.
+  *        This value is used by the RCC HAL module to compute the system frequency
+  *        (when HSI is used as system clock source, directly or through the PLL). 
+  */
+#if !defined  (HSI_VALUE)
+  #define HSI_VALUE    ((uint32_t)16000000U) /*!< Value of the Internal oscillator in Hz*/
+#endif /* HSI_VALUE */
+
+/**
+  * @brief Internal High Speed oscillator for USB (HSI48) value.
+  */
+#if !defined  (HSI48_VALUE) 
+#define HSI48_VALUE ((uint32_t)48000000U) /*!< Value of the Internal High Speed oscillator for USB in Hz.
+                                             The real value may vary depending on the variations
+                                             in voltage and temperature.  */
+#endif /* HSI48_VALUE */
+
+/**
+  * @brief Internal Low Speed oscillator (LSI) value.
+  */
+#if !defined  (LSI_VALUE) 
+ #define LSI_VALUE  ((uint32_t)37000U)       /*!< LSI Typical Value in Hz*/
+#endif /* LSI_VALUE */                      /*!< Value of the Internal Low Speed oscillator in Hz
+                                             The real value may vary depending on the variations
+                                             in voltage and temperature.*/
+/**
+  * @brief External Low Speed oscillator (LSE) value.
+  *        This value is used by the UART, RTC HAL module to compute the system frequency
+  */
+#if !defined  (LSE_VALUE)
+  #define LSE_VALUE    ((uint32_t)32768U) /*!< Value of the External oscillator in Hz*/
+#endif /* LSE_VALUE */
+
+/**
+  * @brief Time out for LSE start up value in ms.
+  */
+#if !defined  (LSE_STARTUP_TIMEOUT)
+  #define LSE_STARTUP_TIMEOUT    ((uint32_t)5000U)   /*!< Time out for LSE start up, in ms */
+#endif /* LSE_STARTUP_TIMEOUT */
+
+   
+/* Tip: To avoid modifying this file each time you need to use different HSE,
+   ===  you can define the HSE value in your toolchain compiler preprocessor. */
+
+/* ########################### System Configuration ######################### */
+/**
+  * @brief This is the HAL system configuration section
+  */     
+#define  VDD_VALUE                    ((uint32_t)3300U) /*!< Value of VDD in mv */
+#define  TICK_INT_PRIORITY            (((uint32_t)1U<<__NVIC_PRIO_BITS) - 1U)    /*!< tick interrupt priority */            
+#define  USE_RTOS                     0U     
+#define  PREFETCH_ENABLE              1U              
+#define  PREREAD_ENABLE               0U
+#define  BUFFER_CACHE_DISABLE         0U
+
+/* ########################## Assert Selection ############################## */
+/**
+  * @brief Uncomment the line below to expanse the "assert_param" macro in the 
+  *        HAL drivers code
+  */
+/* #define USE_FULL_ASSERT    1U */
+
+
+/* ################## Register callback feature configuration ############### */
+/**
+  * @brief Set below the peripheral configuration  to "1U" to add the support
+  *        of HAL callback registration/deregistration feature for the HAL
+  *        driver(s). This allows user application to provide specific callback
+  *        functions thanks to HAL_PPP_RegisterCallback() rather than overwriting
+  *        the default weak callback functions (see each stm32l0xx_hal_ppp.h file
+  *        for possible callback identifiers defined in HAL_PPP_CallbackIDTypeDef
+  *        for each PPP peripheral).
+  */
+#define USE_HAL_ADC_REGISTER_CALLBACKS        0U
+#define USE_HAL_COMP_REGISTER_CALLBACKS       0U
+#define USE_HAL_DAC_REGISTER_CALLBACKS        0U
+#define USE_HAL_I2C_REGISTER_CALLBACKS        0U
+#define USE_HAL_I2S_REGISTER_CALLBACKS        0U
+#define USE_HAL_IRDA_REGISTER_CALLBACKS       0U
+#define USE_HAL_LPTIM_REGISTER_CALLBACKS      0U
+#define USE_HAL_PCD_REGISTER_CALLBACKS        0U
+#define USE_HAL_RNG_REGISTER_CALLBACKS        0U
+#define USE_HAL_RTC_REGISTER_CALLBACKS        0U
+#define USE_HAL_SMARTCARD_REGISTER_CALLBACKS  0U
+#define USE_HAL_SMBUS_REGISTER_CALLBACKS      0U
+#define USE_HAL_SPI_REGISTER_CALLBACKS        0U
+#define USE_HAL_TIM_REGISTER_CALLBACKS        0U
+#define USE_HAL_TSC_REGISTER_CALLBACKS        0U
+#define USE_HAL_UART_REGISTER_CALLBACKS       0U
+#define USE_HAL_USART_REGISTER_CALLBACKS      0U
+#define USE_HAL_WWDG_REGISTER_CALLBACKS       0U
+
+/* ################## SPI peripheral configuration ########################## */
+
+/* CRC FEATURE: Use to activate CRC feature inside HAL SPI Driver
+ * Activated: CRC code is present inside driver
+ * Deactivated: CRC code cleaned from driver
+ */
+
+#define USE_SPI_CRC                   1U
+
+/* Includes ------------------------------------------------------------------*/
+/**
+  * @brief Include module's header file 
+  */
+
+#ifdef HAL_RCC_MODULE_ENABLED
+  #include "stm32l0xx_hal_rcc.h"
+#endif /* HAL_RCC_MODULE_ENABLED */
+  
+#ifdef HAL_GPIO_MODULE_ENABLED
+  #include "stm32l0xx_hal_gpio.h"
+#endif /* HAL_GPIO_MODULE_ENABLED */
+
+#ifdef HAL_DMA_MODULE_ENABLED
+  #include "stm32l0xx_hal_dma.h"
+#endif /* HAL_DMA_MODULE_ENABLED */
+
+#ifdef HAL_CORTEX_MODULE_ENABLED
+  #include "stm32l0xx_hal_cortex.h"
+#endif /* HAL_CORTEX_MODULE_ENABLED */
+
+#ifdef HAL_ADC_MODULE_ENABLED
+  #include "stm32l0xx_hal_adc.h"
+#endif /* HAL_ADC_MODULE_ENABLED */
+
+#ifdef HAL_COMP_MODULE_ENABLED
+  #include "stm32l0xx_hal_comp.h"
+#endif /* HAL_COMP_MODULE_ENABLED */
+
+#ifdef HAL_CRC_MODULE_ENABLED
+  #include "stm32l0xx_hal_crc.h"
+#endif /* HAL_CRC_MODULE_ENABLED */
+
+#ifdef HAL_CRYP_MODULE_ENABLED
+  #include "stm32l0xx_hal_cryp.h"
+#endif /* HAL_CRYP_MODULE_ENABLED */
+
+#ifdef HAL_DAC_MODULE_ENABLED
+  #include "stm32l0xx_hal_dac.h"
+#endif /* HAL_DAC_MODULE_ENABLED */
+
+#ifdef HAL_FIREWALL_MODULE_ENABLED
+  #include "stm32l0xx_hal_firewall.h"
+#endif /* HAL_FIREWALL_MODULE_ENABLED */
+ 
+#ifdef HAL_FLASH_MODULE_ENABLED
+  #include "stm32l0xx_hal_flash.h"
+#endif /* HAL_FLASH_MODULE_ENABLED */
+ 
+#ifdef HAL_I2C_MODULE_ENABLED
+ #include "stm32l0xx_hal_i2c.h"
+#endif /* HAL_I2C_MODULE_ENABLED */
+
+#ifdef HAL_I2S_MODULE_ENABLED
+ #include "stm32l0xx_hal_i2s.h"
+#endif /* HAL_I2S_MODULE_ENABLED */
+
+#ifdef HAL_IWDG_MODULE_ENABLED
+ #include "stm32l0xx_hal_iwdg.h"
+#endif /* HAL_IWDG_MODULE_ENABLED */
+
+#ifdef HAL_LCD_MODULE_ENABLED
+ #include "stm32l0xx_hal_lcd.h"
+#endif /* HAL_LCD_MODULE_ENABLED */
+
+#ifdef HAL_LPTIM_MODULE_ENABLED
+#include "stm32l0xx_hal_lptim.h"
+#endif /* HAL_LPTIM_MODULE_ENABLED */
+   
+#ifdef HAL_PWR_MODULE_ENABLED
+ #include "stm32l0xx_hal_pwr.h"
+#endif /* HAL_PWR_MODULE_ENABLED */
+
+#ifdef HAL_RNG_MODULE_ENABLED
+ #include "stm32l0xx_hal_rng.h"
+#endif /* HAL_RNG_MODULE_ENABLED */
+
+#ifdef HAL_RTC_MODULE_ENABLED
+ #include "stm32l0xx_hal_rtc.h"
+#endif /* HAL_RTC_MODULE_ENABLED */
+
+#ifdef HAL_SPI_MODULE_ENABLED
+ #include "stm32l0xx_hal_spi.h"
+#endif /* HAL_SPI_MODULE_ENABLED */
+
+#ifdef HAL_TIM_MODULE_ENABLED
+ #include "stm32l0xx_hal_tim.h"
+#endif /* HAL_TIM_MODULE_ENABLED */
+
+#ifdef HAL_TSC_MODULE_ENABLED
+ #include "stm32l0xx_hal_tsc.h"
+#endif /* HAL_TSC_MODULE_ENABLED */
+
+#ifdef HAL_UART_MODULE_ENABLED
+ #include "stm32l0xx_hal_uart.h"
+#endif /* HAL_UART_MODULE_ENABLED */
+
+#ifdef HAL_USART_MODULE_ENABLED
+ #include "stm32l0xx_hal_usart.h"
+#endif /* HAL_USART_MODULE_ENABLED */
+
+#ifdef HAL_IRDA_MODULE_ENABLED
+ #include "stm32l0xx_hal_irda.h"
+#endif /* HAL_IRDA_MODULE_ENABLED */
+
+#ifdef HAL_SMARTCARD_MODULE_ENABLED
+ #include "stm32l0xx_hal_smartcard.h"
+#endif /* HAL_SMARTCARD_MODULE_ENABLED */
+
+#ifdef HAL_SMBUS_MODULE_ENABLED
+ #include "stm32l0xx_hal_smbus.h"
+#endif /* HAL_SMBUS_MODULE_ENABLED */
+
+#ifdef HAL_WWDG_MODULE_ENABLED
+ #include "stm32l0xx_hal_wwdg.h"
+#endif /* HAL_WWDG_MODULE_ENABLED */
+
+#ifdef HAL_PCD_MODULE_ENABLED
+ #include "stm32l0xx_hal_pcd.h"
+#endif /* HAL_PCD_MODULE_ENABLED */
+
+/* Exported macro ------------------------------------------------------------*/
+#ifdef  USE_FULL_ASSERT
+/**
+  * @brief  The assert_param macro is used for function's parameters check.
+  * @param  expr If expr is false, it calls assert_failed function
+  *         which reports the name of the source file and the source
+  *         line number of the call that failed. 
+  *         If expr is true, it returns no value.
+  * @retval None
+  */
+  #define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__))
+/* Exported functions ------------------------------------------------------- */
+  void assert_failed(uint8_t* file, uint32_t line);
+#else
+  #define assert_param(expr) ((void)0U)
+#endif /* USE_FULL_ASSERT */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __STM32L0xx_HAL_CONF_H */
+ 
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
+

+ 2 - 1
repository.yml

@@ -11,7 +11,8 @@ repo.versions:
     "0.11.0": "0.11.0"
     "0.12.0": "0.12.0"
     "0.13.0": "0.13.0"
+    "0.14.0": "0.14.0"
 
     "0-dev": "0.0.0"        # master
-    "0-latest": "0.13.0"    # latest stable release
+    "0-latest": "0.14.0"    # latest stable release
 

+ 1 - 1
src/class/audio/audio_device.c

@@ -565,7 +565,7 @@ static bool audiod_rx_done_cb(uint8_t rhport, audiod_function_t* audio, uint16_t
 
     case AUDIO_FORMAT_TYPE_I:
 
-      switch (audio->format_type_I_tx)
+      switch (audio->format_type_I_rx)
       {
         case AUDIO_DATA_FORMAT_TYPE_I_PCM:
           TU_VERIFY(audiod_decode_type_I_pcm(rhport, audio, n_bytes_received));

+ 2 - 0
src/class/dfu/dfu_device.c

@@ -167,6 +167,8 @@ uint16_t dfu_moded_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc,
   uint8_t alt_count = 0;
 
   uint16_t drv_len = 0;
+  TU_VERIFY(itf_desc->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS && itf_desc->bInterfaceProtocol == DFU_PROTOCOL_DFU, 0);
+
   while(itf_desc->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS && itf_desc->bInterfaceProtocol == DFU_PROTOCOL_DFU)
   {
     TU_ASSERT(max_len > drv_len, 0);

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

@@ -424,7 +424,7 @@ bool hidd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_
   {
     if (tud_hid_report_complete_cb)
     {
-      tud_hid_report_complete_cb(instance, p_hid->epin_buf, (uint16_t) xferred_bytes);
+      tud_hid_report_complete_cb(instance, p_hid->epin_buf, (/*uint16_t*/ uint8_t) xferred_bytes);
     }
   }
   // Received report

+ 1 - 1
src/class/hid/hid_device.h

@@ -124,7 +124,7 @@ TU_ATTR_WEAK bool tud_hid_set_idle_cb(uint8_t instance, uint8_t idle_rate);
 // Invoked when sent REPORT successfully to host
 // Application can use this to send the next report
 // Note: For composite reports, report[0] is report ID
-TU_ATTR_WEAK void tud_hid_report_complete_cb(uint8_t instance, uint8_t const* report, uint16_t len);
+TU_ATTR_WEAK void tud_hid_report_complete_cb(uint8_t instance, uint8_t const* report, /*uint16_t*/ uint8_t len );
 
 
 //--------------------------------------------------------------------+

+ 4 - 1
src/class/usbtmc/usbtmc.h

@@ -189,7 +189,10 @@ typedef enum {
   USBTMC_STATUS_FAILED = 0x80,
   USBTMC_STATUS_TRANSFER_NOT_IN_PROGRESS = 0x81,
   USBTMC_STATUS_SPLIT_NOT_IN_PROGRESS = 0x82,
-  USBTMC_STATUS_SPLIT_IN_PROGRESS  = 0x83
+  USBTMC_STATUS_SPLIT_IN_PROGRESS  = 0x83,
+
+  /****** USBTMC 488 *************/
+  USB488_STATUS_INTERRUPT_IN_BUSY = 0x20
 } usbtmc_status_enum;
 
 /************************************************************

+ 55 - 27
src/class/usbtmc/usbtmc_device.c

@@ -64,7 +64,8 @@
 // USBTMC 3.2.2 error conditions not strictly followed
 // No local lock-out, REN, or GTL.
 // Clear message available status byte at the correct time? (488 4.3.1.3)
-
+// Ability to defer status byte transmission
+// Transmission of status byte in response to USB488 SRQ condition
 
 #include "tusb_option.h"
 
@@ -80,6 +81,11 @@
 static char logMsg[150];
 #endif
 
+// Buffer size must be an exact multiple of the max packet size for both
+// bulk  (up to 64 bytes for FS, 512 bytes for HS). In addation, this driver
+// imposes a minimum buffer size of 32 bytes. 
+#define USBTMCD_BUFFER_SIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
+
 /*
  * The state machine does not allow simultaneous reading and writing. This is
  * consistent with USBTMC.
@@ -120,9 +126,12 @@ typedef struct
   uint8_t ep_int_in;
   // IN buffer is only used for first packet, not the remainder
   // in order to deal with prepending header
-  CFG_TUSB_MEM_ALIGN uint8_t ep_bulk_in_buf[USBTMCD_MAX_PACKET_SIZE];
+  CFG_TUSB_MEM_ALIGN uint8_t ep_bulk_in_buf[USBTMCD_BUFFER_SIZE];
+  uint32_t ep_bulk_in_wMaxPacketSize;
   // OUT buffer receives one packet at a time
-  CFG_TUSB_MEM_ALIGN uint8_t ep_bulk_out_buf[USBTMCD_MAX_PACKET_SIZE];
+  CFG_TUSB_MEM_ALIGN uint8_t ep_bulk_out_buf[USBTMCD_BUFFER_SIZE];
+  uint32_t ep_bulk_out_wMaxPacketSize;
+
   uint32_t transfer_size_remaining; // also used for requested length for bulk IN.
   uint32_t transfer_size_sent;      // To keep track of data bytes that have been queued in FIFO (not header bytes)
 
@@ -139,11 +148,8 @@ CFG_TUSB_MEM_SECTION static usbtmc_interface_state_t usbtmc_state =
     .itf_id = 0xFF,
 };
 
-// We need all headers to fit in a single packet in this implementation.
-TU_VERIFY_STATIC(USBTMCD_MAX_PACKET_SIZE >= 32u,"USBTMC dev EP packet size too small");
-TU_VERIFY_STATIC(
-    (sizeof(usbtmc_state.ep_bulk_in_buf) % USBTMCD_MAX_PACKET_SIZE) == 0,
-    "packet buffer must be a multiple of the packet size");
+// We need all headers to fit in a single packet in this implementation, 32 bytes will fit all standard USBTMC headers
+TU_VERIFY_STATIC(USBTMCD_BUFFER_SIZE >= 32u,"USBTMC dev buffer size too small");
 
 static bool handle_devMsgOutStart(uint8_t rhport, void *data, size_t len);
 static bool handle_devMsgOut(uint8_t rhport, void *data, size_t len, size_t packetLen);
@@ -151,7 +157,6 @@ static bool handle_devMsgOut(uint8_t rhport, void *data, size_t len, size_t pack
 static uint8_t termChar;
 static uint8_t termCharRequested = false;
 
-
 osal_mutex_def_t usbtmcLockBuffer;
 static osal_mutex_t usbtmcLock;
 
@@ -282,12 +287,15 @@ uint16_t usbtmcd_open_cb(uint8_t rhport, tusb_desc_interface_t const * itf_desc,
       tusb_desc_endpoint_t const *ep_desc = (tusb_desc_endpoint_t const *)p_desc;
       switch(ep_desc->bmAttributes.xfer) {
         case TUSB_XFER_BULK:
-          TU_ASSERT(tu_edpt_packet_size(ep_desc) == USBTMCD_MAX_PACKET_SIZE, 0);
+          // Ensure  buffer is an exact multiple of the maxPacketSize
+          TU_ASSERT((USBTMCD_BUFFER_SIZE % tu_edpt_packet_size(ep_desc)) == 0, 0);
           if (tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN)
           {
             usbtmc_state.ep_bulk_in = ep_desc->bEndpointAddress;
+            usbtmc_state.ep_bulk_in_wMaxPacketSize = tu_edpt_packet_size(ep_desc);
           } else {
             usbtmc_state.ep_bulk_out = ep_desc->bEndpointAddress;
+            usbtmc_state.ep_bulk_out_wMaxPacketSize = tu_edpt_packet_size(ep_desc);
           }
 
           break;
@@ -395,7 +403,7 @@ static bool handle_devMsgOut(uint8_t rhport, void *data, size_t len, size_t pack
   // return true upon failure, as we can assume error is being handled elsewhere.
   TU_VERIFY(usbtmc_state.state == STATE_RCV,true);
 
-  bool shortPacket = (packetLen < USBTMCD_MAX_PACKET_SIZE);
+  bool shortPacket = (packetLen < usbtmc_state.ep_bulk_out_wMaxPacketSize);
 
   // Packet is to be considered complete when we get enough data or at a short packet.
   bool atEnd = false;
@@ -522,7 +530,7 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint
       break;
 
     case STATE_TX_INITIATED:
-      if(usbtmc_state.transfer_size_remaining >=sizeof(usbtmc_state.ep_bulk_in_buf))
+      if(usbtmc_state.transfer_size_remaining >= sizeof(usbtmc_state.ep_bulk_in_buf))
       {
         // FIXME! This removes const below!
         TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in,
@@ -539,7 +547,7 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint
         usbtmc_state.transfer_size_remaining = 0;
         usbtmc_state.devInBuffer = NULL;
         TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf, (uint16_t)packetLen) );
-        if(((packetLen % USBTMCD_MAX_PACKET_SIZE) != 0) || (packetLen == 0 ))
+        if(((packetLen % usbtmc_state.ep_bulk_in_wMaxPacketSize) != 0) || (packetLen == 0 ))
         {
           usbtmc_state.state = STATE_TX_SHORTED;
         }
@@ -589,18 +597,31 @@ bool usbtmcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request
   {
     uint32_t ep_addr = (request->wIndex);
 
+    // At this point, a transfer MAY be in progress. Based on USB spec, when clearing bulk EP HALT,
+    // the EP transfer buffer needs to be cleared and DTOG needs to be reset, even if 
+    // the EP is not halted. The only USBD API interface to do this is to stall and then unstall the EP.
     if(ep_addr == usbtmc_state.ep_bulk_out)
     {
       criticalEnter();
+      usbd_edpt_stall(rhport, (uint8_t)ep_addr);
+      usbd_edpt_clear_stall(rhport, (uint8_t)ep_addr);
       usbtmc_state.state = STATE_NAK; // USBD core has placed EP in NAK state for us
       criticalLeave();
       tud_usbtmc_bulkOut_clearFeature_cb();
     }
     else if (ep_addr == usbtmc_state.ep_bulk_in)
     {
+      usbd_edpt_stall(rhport, (uint8_t)ep_addr);
+      usbd_edpt_clear_stall(rhport, (uint8_t)ep_addr);
       tud_usbtmc_bulkIn_clearFeature_cb();
     }
-    else
+    else if ((usbtmc_state.ep_int_in != 0) && (ep_addr == usbtmc_state.ep_int_in))
+    {
+      // Clearing interrupt in EP
+      usbd_edpt_stall(rhport, (uint8_t)ep_addr);
+      usbd_edpt_clear_stall(rhport, (uint8_t)ep_addr);
+    }
+     else
     {
       return false;
     }
@@ -680,7 +701,7 @@ bool usbtmcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request
     usbtmc_state.transfer_size_remaining = 0u;
       // Check if we've queued a short packet
       criticalEnter();
-      usbtmc_state.state = ((usbtmc_state.transfer_size_sent % USBTMCD_MAX_PACKET_SIZE) == 0) ?
+      usbtmc_state.state = ((usbtmc_state.transfer_size_sent % usbtmc_state.ep_bulk_in_wMaxPacketSize) == 0) ?
               STATE_ABORTING_BULK_IN : STATE_ABORTING_BULK_IN_SHORTED;
       criticalLeave();
       if(usbtmc_state.transfer_size_sent  == 0)
@@ -810,25 +831,32 @@ bool usbtmcd_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request
 
       bTag = request->wValue & 0x7F;
       TU_VERIFY(request->bmRequestType == 0xA1);
-      TU_VERIFY((request->wValue & (~0x7F)) == 0u); // Other bits are required to be zero
+      TU_VERIFY((request->wValue & (~0x7F)) == 0u); // Other bits are required to be zero (USB488v1.0 Table 11)
       TU_VERIFY(bTag >= 0x02 && bTag <= 127);
       TU_VERIFY(request->wIndex == usbtmc_state.itf_id);
       TU_VERIFY(request->wLength == 0x0003);
       rsp.bTag = (uint8_t)bTag;
       if(usbtmc_state.ep_int_in != 0)
       {
-        rsp.USBTMC_status = USBTMC_STATUS_SUCCESS;
-        rsp.statusByte = 0x00; // Use interrupt endpoint, instead.
-
-        usbtmc_read_stb_interrupt_488_t intMsg =
+        rsp.statusByte = 0x00; // Use interrupt endpoint, instead. Must be 0x00 (USB488v1.0 4.3.1.2)
+        if(usbd_edpt_busy(rhport, usbtmc_state.ep_int_in))
+        {
+          rsp.USBTMC_status = USB488_STATUS_INTERRUPT_IN_BUSY;
+        }
+        else
         {
-          .bNotify1 = {
-              .one = 1,
-              .bTag = bTag & 0x7Fu,
-          },
-          .StatusByte = tud_usbtmc_get_stb_cb(&(rsp.USBTMC_status))
-        };
-        usbd_edpt_xfer(rhport, usbtmc_state.ep_int_in, (void*)&intMsg, sizeof(intMsg));
+          rsp.USBTMC_status = USBTMC_STATUS_SUCCESS;
+          usbtmc_read_stb_interrupt_488_t intMsg =
+          {
+            .bNotify1 = {
+                .one = 1,
+                .bTag = bTag & 0x7Fu,
+            },
+            .StatusByte = tud_usbtmc_get_stb_cb(&(rsp.USBTMC_status))
+          };
+          // Must be queued before control request response sent (USB488v1.0 4.3.1.2)
+          usbd_edpt_xfer(rhport, usbtmc_state.ep_int_in, (void*)&intMsg, sizeof(intMsg));
+        }
       }
       else
       {

+ 0 - 4
src/class/usbtmc/usbtmc_device.h

@@ -35,10 +35,6 @@
 #define CFG_TUD_USBTMC_ENABLE_488 (1)
 #endif
 
-// USB spec says that full-speed must be 8,16,32, or 64.
-// However, this driver implementation requires it to be >=32
-#define USBTMCD_MAX_PACKET_SIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
-
 /***********************************************
  *  Functions to be implemeted by the class implementation
  */

+ 10 - 0
src/common/tusb_compiler.h

@@ -131,6 +131,12 @@
   #define TU_ATTR_BIT_FIELD_ORDER_BEGIN
   #define TU_ATTR_BIT_FIELD_ORDER_END
 
+  #if __has_attribute(__fallthrough__)
+    #define TU_ATTR_FALLTHROUGH         __attribute__((fallthrough))
+  #else
+    #define TU_ATTR_FALLTHROUGH         do {} while (0)  /* fallthrough */
+  #endif
+
   // Endian conversion use well-known host to network (big endian) naming
   #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
     #define TU_BYTE_ORDER TU_LITTLE_ENDIAN
@@ -156,6 +162,7 @@
   #define TU_ATTR_DEPRECATED(mess)      __attribute__ ((deprecated(mess))) // warn if function with this attribute is used
   #define TU_ATTR_UNUSED                __attribute__ ((unused))           // Function/Variable is meant to be possibly unused
   #define TU_ATTR_USED                  __attribute__ ((used))
+  #define TU_ATTR_FALLTHROUGH           __attribute__((fallthrough))
 
   #define TU_ATTR_PACKED_BEGIN
   #define TU_ATTR_PACKED_END
@@ -182,6 +189,7 @@
   #define TU_ATTR_DEPRECATED(mess)      __attribute__ ((deprecated(mess))) // warn if function with this attribute is used
   #define TU_ATTR_UNUSED                __attribute__ ((unused))           // Function/Variable is meant to be possibly unused
   #define TU_ATTR_USED                  __attribute__ ((used))             // Function/Variable is meant to be used
+  #define TU_ATTR_FALLTHROUGH           __attribute__((fallthrough))
 
   #define TU_ATTR_PACKED_BEGIN
   #define TU_ATTR_PACKED_END
@@ -207,6 +215,7 @@
   #define TU_ATTR_DEPRECATED(mess)
   #define TU_ATTR_UNUSED
   #define TU_ATTR_USED
+  #define TU_ATTR_FALLTHROUGH           do {} while (0)  /* fallthrough */
 
   #define TU_ATTR_PACKED_BEGIN          _Pragma("pack")
   #define TU_ATTR_PACKED_END            _Pragma("packoption")
@@ -227,6 +236,7 @@
   #error "Compiler attribute porting is required"
 #endif
 
+
 #if (TU_BYTE_ORDER == TU_LITTLE_ENDIAN)
 
   #define tu_htons(u16)  (TU_BSWAP16(u16))

+ 74 - 14
src/host/hub.c

@@ -44,6 +44,7 @@ typedef struct
   uint8_t status_change; // data from status change interrupt endpoint
 
   hub_port_status_response_t port_status;
+  hub_status_response_t hub_status;
 } hub_interface_t;
 
 CFG_TUSB_MEM_SECTION static hub_interface_t hub_data[CFG_TUH_HUB];
@@ -85,7 +86,7 @@ bool hub_port_clear_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature,
   {
     .bmRequestType_bit =
     {
-      .recipient = TUSB_REQ_RCPT_OTHER,
+      .recipient = (hub_port == 0) ? TUSB_REQ_RCPT_DEVICE : TUSB_REQ_RCPT_OTHER,
       .type      = TUSB_REQ_TYPE_CLASS,
       .direction = TUSB_DIR_OUT
     },
@@ -117,7 +118,7 @@ bool hub_port_set_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature,
   {
     .bmRequestType_bit =
     {
-      .recipient = TUSB_REQ_RCPT_OTHER,
+      .recipient = (hub_port == 0) ? TUSB_REQ_RCPT_DEVICE : TUSB_REQ_RCPT_OTHER,
       .type      = TUSB_REQ_TYPE_CLASS,
       .direction = TUSB_DIR_OUT
     },
@@ -149,7 +150,7 @@ bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, void* resp,
   {
     .bmRequestType_bit =
     {
-      .recipient = TUSB_REQ_RCPT_OTHER,
+      .recipient = (hub_port == 0) ? TUSB_REQ_RCPT_DEVICE : TUSB_REQ_RCPT_OTHER,
       .type      = TUSB_REQ_TYPE_CLASS,
       .direction = TUSB_DIR_IN
     },
@@ -313,7 +314,8 @@ static void config_port_power_complete (tuh_xfer_t* xfer)
 // Connection Changes
 //--------------------------------------------------------------------+
 
-static void connection_get_status_complete (tuh_xfer_t* xfer);
+static void hub_port_get_status_complete (tuh_xfer_t* xfer);
+static void hub_get_status_complete (tuh_xfer_t* xfer);
 static void connection_clear_conn_change_complete (tuh_xfer_t* xfer);
 static void connection_port_reset_complete (tuh_xfer_t* xfer);
 
@@ -326,19 +328,31 @@ bool hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32
 
   hub_interface_t* p_hub = get_itf(dev_addr);
 
-  TU_LOG2("  Port Status Change = 0x%02X\r\n", p_hub->status_change);
+  TU_LOG2("  Hub Status Change = 0x%02X\r\n", p_hub->status_change);
 
-  // Hub ignore bit0 in status change
-  for (uint8_t port=1; port <= p_hub->port_count; port++)
+  // Hub bit 0 is for the hub device events
+  if (tu_bit_test(p_hub->status_change, 0))
   {
-    if ( tu_bit_test(p_hub->status_change, port) )
+    if (hub_port_get_status(dev_addr, 0, &p_hub->hub_status, hub_get_status_complete, 0) == false)
     {
-      if (hub_port_get_status(dev_addr, port, &p_hub->port_status, connection_get_status_complete, 0) == false)
+      //Hub status control transfer failed, retry
+      hub_edpt_status_xfer(dev_addr);
+    }
+  }
+  else
+  {
+    // Hub bits 1 to n are hub port events
+    for (uint8_t port=1; port <= p_hub->port_count; port++)
+    {
+      if ( tu_bit_test(p_hub->status_change, port) )
       {
-        //Hub status control transfer failed, retry
-        hub_edpt_status_xfer(dev_addr);
+        if (hub_port_get_status(dev_addr, port, &p_hub->port_status, hub_port_get_status_complete, 0) == false)
+        {
+          //Hub status control transfer failed, retry
+          hub_edpt_status_xfer(dev_addr);
+        }
+        break;
       }
-      break;
     }
   }
 
@@ -347,7 +361,36 @@ bool hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32
   return true;
 }
 
-static void connection_get_status_complete (tuh_xfer_t* xfer)
+static void hub_clear_feature_complete_stub(tuh_xfer_t* xfer)
+{
+  TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS, );
+  hub_edpt_status_xfer(xfer->daddr);
+}
+
+static void hub_get_status_complete (tuh_xfer_t* xfer)
+{
+  TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS, );
+
+  uint8_t const daddr = xfer->daddr;
+  hub_interface_t* p_hub = get_itf(daddr);
+  uint8_t const port_num = (uint8_t) tu_le16toh(xfer->setup->wIndex);
+  TU_ASSERT(port_num == 0 , );
+
+  TU_LOG2("HUB Got hub status, addr = %u, status = %04x\r\n", daddr, p_hub->hub_status.change.value);
+
+  if (p_hub->hub_status.change.local_power_source)
+  {
+    TU_LOG2("HUB Local Power Change, addr = %u\r\n", daddr);
+    hub_port_clear_feature(daddr, port_num, HUB_FEATURE_HUB_LOCAL_POWER_CHANGE, hub_clear_feature_complete_stub, 0);
+  }
+  else if (p_hub->hub_status.change.over_current)
+  {
+    TU_LOG1("HUB Over Current, addr = %u\r\n", daddr);
+    hub_port_clear_feature(daddr, port_num, HUB_FEATURE_HUB_OVER_CURRENT_CHANGE, hub_clear_feature_complete_stub, 0);
+  }
+}
+
+static void hub_port_get_status_complete (tuh_xfer_t* xfer)
 {
   TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS, );
 
@@ -365,7 +408,24 @@ static void connection_get_status_complete (tuh_xfer_t* xfer)
     hub_port_clear_feature(daddr, port_num, HUB_FEATURE_PORT_CONNECTION_CHANGE, connection_clear_conn_change_complete, 0);
   }else
   {
-    // Other changes are: Enable, Suspend, Over Current, Reset, L1 state
+    // Clear other port status change interrupts. TODO Not currently handled - just cleared.
+    if (p_hub->port_status.change.port_enable)
+    {
+      hub_port_clear_feature(daddr, port_num, HUB_FEATURE_PORT_ENABLE_CHANGE, hub_clear_feature_complete_stub, 0);
+    }
+    else if (p_hub->port_status.change.suspend)
+    {
+      hub_port_clear_feature(daddr, port_num, HUB_FEATURE_PORT_SUSPEND_CHANGE, hub_clear_feature_complete_stub, 0);
+    }
+    else if (p_hub->port_status.change.over_current)
+    {
+      hub_port_clear_feature(daddr, port_num, HUB_FEATURE_PORT_OVER_CURRENT_CHANGE, hub_clear_feature_complete_stub, 0);
+    }
+    else if (p_hub->port_status.change.reset)
+    {
+      hub_port_clear_feature(daddr, port_num, HUB_FEATURE_PORT_RESET_CHANGE, hub_clear_feature_complete_stub, 0);
+    }
+    // Other changes are: L1 state
     // TODO clear change
 
     // prepare for next hub status

+ 4 - 4
src/host/usbh.c

@@ -123,7 +123,6 @@ typedef struct {
 
 // Invalid driver ID in itf2drv[] ep2drv[][] mapping
 enum { DRVID_INVALID = 0xFFu };
-enum { ADDR_INVALID  = 0xFFu };
 enum { CONTROLLER_INVALID = 0xFFu };
 
 #if CFG_TUSB_DEBUG >= 2
@@ -656,7 +655,7 @@ static bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result
           TU_ASSERT( hcd_edpt_xfer(rhport, dev_addr, tu_edpt_addr(0, request->bmRequestType_bit.direction), _ctrl_xfer.buffer, request->wLength) );
           return true;
         }
-        __attribute__((fallthrough));
+        TU_ATTR_FALLTHROUGH;
 
       case CONTROL_STAGE_DATA:
         if (request->wLength)
@@ -1434,7 +1433,8 @@ static uint8_t get_new_address(bool is_hub)
   {
     if (!_usbh_devices[idx].connected) return (idx+1);
   }
-  return ADDR_INVALID;
+
+  return 0; // invalid address
 }
 
 static bool enum_request_set_addr(void)
@@ -1443,7 +1443,7 @@ static bool enum_request_set_addr(void)
 
   // Get new address
   uint8_t const new_addr = get_new_address(desc_device->bDeviceClass == TUSB_CLASS_HUB);
-  TU_ASSERT(new_addr != ADDR_INVALID);
+  TU_ASSERT(new_addr != 0);
 
   TU_LOG2("Set Address = %d\r\n", new_addr);
 

+ 37 - 56
src/portable/nordic/nrf5x/dcd_nrf5x.c

@@ -28,6 +28,7 @@
 
 #if CFG_TUD_ENABLED && CFG_TUSB_MCU == OPT_MCU_NRF5X
 
+#include <stdatomic.h>
 #include "nrf.h"
 #include "nrf_clock.h"
 #include "nrf_power.h"
@@ -72,6 +73,7 @@ typedef struct
   // nRF will auto accept OUT packet after DMA is done
   // indicate packet is already ACK
   volatile bool data_received;
+  volatile bool started;
 
   // Set to true when data was transferred from RAM to ISO IN output buffer.
   // New data can be put in ISO IN output buffer after SOF.
@@ -79,9 +81,6 @@ typedef struct
 
 } xfer_td_t;
 
-static osal_mutex_def_t dcd_mutex_def;
-static osal_mutex_t dcd_mutex;
-
 // Data for managing dcd
 static struct
 {
@@ -90,7 +89,7 @@ static struct
   xfer_td_t xfer[EP_CBI_COUNT + 1][2];
 
   // nRF can only carry one DMA at a time, this is used to guard the access to EasyDMA
-  volatile bool dma_running;
+  atomic_bool dma_running;
 }_dcd;
 
 /*------------------------------------------------------------------*/
@@ -121,8 +120,6 @@ TU_ATTR_ALWAYS_INLINE static inline bool is_in_isr(void)
 // helper to start DMA
 static void start_dma(volatile uint32_t* reg_startep)
 {
-  _dcd.dma_running = true;
-
   (*reg_startep) = 1;
   __ISB(); __DSB();
 
@@ -131,50 +128,18 @@ static void start_dma(volatile uint32_t* reg_startep)
   // Therefore dma_pending is corrected right away
   if ( (reg_startep == &NRF_USBD->TASKS_EP0STATUS) || (reg_startep == &NRF_USBD->TASKS_EP0RCVOUT) )
   {
-    _dcd.dma_running = false;
+    atomic_flag_clear(&_dcd.dma_running);
   }
 }
 
-// only 1 EasyDMA can be active at any time
-// TODO use Cortex M4 LDREX and STREX command (atomic) to have better mutex access to EasyDMA
-// since current implementation does not 100% guarded against race condition
 static void edpt_dma_start(volatile uint32_t* reg_startep)
 {
-  // Called in critical section i.e within USB ISR, or USB/Global interrupt disabled
-  if ( is_in_isr() || __get_PRIMASK() || !NVIC_GetEnableIRQ(USBD_IRQn) )
+  if ( atomic_flag_test_and_set(&_dcd.dma_running) )
   {
-    if (_dcd.dma_running)
-    {
-      //use usbd task to defer later
-      usbd_defer_func((osal_task_func_t) edpt_dma_start, (void*) (uintptr_t) reg_startep, true);
-    }else
-    {
-      start_dma(reg_startep);
-    }
+    usbd_defer_func((osal_task_func_t) edpt_dma_start, (void*) (uintptr_t) reg_startep, true);
   }else
   {
-    // Called in non-critical thread-mode, should be 99% of the time.
-    // Should be safe to blocking wait until previous DMA transfer complete
-    uint8_t const rhport = 0;
-    bool started = false;
-    osal_mutex_lock(dcd_mutex, OSAL_TIMEOUT_WAIT_FOREVER);
-    while(!started)
-    {
-      // LDREX/STREX may be needed in form of std atomic (required C11) or
-      // use osal mutex to guard against multiple core MCUs such as nRF53
-      dcd_int_disable(rhport);
-
-      if ( !_dcd.dma_running )
-      {
-        start_dma(reg_startep);
-        started = true;
-      }
-
-      dcd_int_enable(rhport);
-
-      // osal_yield();
-    }
-    osal_mutex_unlock(dcd_mutex);
+    start_dma(reg_startep);
   }
 }
 
@@ -182,7 +147,7 @@ static void edpt_dma_start(volatile uint32_t* reg_startep)
 static void edpt_dma_end(void)
 {
   TU_ASSERT(_dcd.dma_running, );
-  _dcd.dma_running = false;
+  atomic_flag_clear(&_dcd.dma_running);
 }
 
 // helper getting td
@@ -191,12 +156,26 @@ static inline xfer_td_t* get_td(uint8_t epnum, uint8_t dir)
   return &_dcd.xfer[epnum][dir];
 }
 
+static void xact_out_dma(uint8_t epnum);
+// Function wraps xact_out_dma which wants uint8_t while usbd_defer_func wants void (*)(void *)
+static void xact_out_dma_wrapper(void *epnum)
+{
+  xact_out_dma((uint8_t)((uintptr_t)epnum));
+}
+
 // Start DMA to move data from Endpoint -> RAM
 static void xact_out_dma(uint8_t epnum)
 {
   xfer_td_t* xfer = get_td(epnum, TUSB_DIR_OUT);
   uint32_t xact_len;
 
+  // DMA can't be active during read of SIZE.EPOUT or SIZE.ISOOUT, so try to lock,
+  // If already running deffer call regardless if it was called from ISR or task,
+  if ( atomic_flag_test_and_set(&_dcd.dma_running) )
+  {
+    usbd_defer_func((osal_task_func_t)xact_out_dma_wrapper, (void *)(uint32_t)epnum, is_in_isr());
+    return;
+  }
   if (epnum == EP_ISO_NUM)
   {
     xact_len = NRF_USBD->SIZE.ISOOUT;
@@ -204,6 +183,7 @@ static void xact_out_dma(uint8_t epnum)
     if (xact_len & USBD_SIZE_ISOOUT_ZERO_Msk)
     {
       xact_len = 0;
+      atomic_flag_clear(&_dcd.dma_running);
     }
     else
     {
@@ -211,7 +191,7 @@ static void xact_out_dma(uint8_t epnum)
       NRF_USBD->ISOOUT.PTR = (uint32_t) xfer->buffer;
       NRF_USBD->ISOOUT.MAXCNT = xact_len;
 
-      edpt_dma_start(&NRF_USBD->TASKS_STARTISOOUT);
+      start_dma(&NRF_USBD->TASKS_STARTISOOUT);
     }
   }
   else
@@ -223,7 +203,7 @@ static void xact_out_dma(uint8_t epnum)
     NRF_USBD->EPOUT[epnum].PTR = (uint32_t) xfer->buffer;
     NRF_USBD->EPOUT[epnum].MAXCNT = xact_len;
 
-    edpt_dma_start(&NRF_USBD->TASKS_STARTEPOUT[epnum]);
+    start_dma(&NRF_USBD->TASKS_STARTEPOUT[epnum]);
   }
 }
 
@@ -248,7 +228,6 @@ static void xact_in_dma(uint8_t epnum)
 void dcd_init (uint8_t rhport)
 {
   TU_LOG1("dcd init\r\n");
-  dcd_mutex = osal_mutex_create(&dcd_mutex_def);
   (void) rhport;
 }
 
@@ -471,17 +450,10 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t
 
   xfer_td_t* xfer = get_td(epnum, dir);
 
-  if (!is_in_isr()) {
-    osal_mutex_lock(dcd_mutex, OSAL_TIMEOUT_WAIT_FOREVER);
-    dcd_int_disable(rhport);
-  }
+  TU_ASSERT(!xfer->started);
   xfer->buffer     = buffer;
   xfer->total_len  = total_bytes;
   xfer->actual_len = 0;
-  if (!is_in_isr()) {
-    dcd_int_enable(rhport);
-    osal_mutex_unlock(dcd_mutex);
-  }
 
   // Control endpoint with zero-length packet and opposite direction to 1st request byte --> status stage
   bool const control_status = (epnum == 0 && total_bytes == 0 && dir != tu_edpt_dir(NRF_USBD->BMREQUESTTYPE));
@@ -496,13 +468,20 @@ bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t
   }
   else if ( dir == TUSB_DIR_OUT )
   {
+    xfer->started = true;
     if ( epnum == 0 )
     {
       // Accept next Control Out packet. TASKS_EP0RCVOUT also require EasyDMA
       edpt_dma_start(&NRF_USBD->TASKS_EP0RCVOUT);
     }else
     {
-      if ( xfer->data_received && xfer->total_len > xfer->actual_len)
+      // started just set, it could start DMA transfer if interrupt was trigger after this line
+      // code only needs to start transfer (from Endpoint to RAM) when data_received was set
+      // before started was set. If started is NOT set but data_received is, it means that
+      // current transfer was already finished and next data is already present in endpoint and
+      // can be consumed by future transfer
+      __ISB(); __DSB();
+      if ( xfer->data_received && xfer->started )
       {
         // Data is already received previously
         // start DMA to copy to SRAM
@@ -804,7 +783,9 @@ void dcd_int_handler(uint8_t rhport)
         }
       }else
       {
+        TU_ASSERT(xfer->started,);
         xfer->total_len = xfer->actual_len;
+        xfer->started = false;
 
         // CBI OUT complete
         dcd_event_xfer_complete(0, epnum, xfer->actual_len, XFER_RESULT_SUCCESS, true);
@@ -857,7 +838,7 @@ void dcd_int_handler(uint8_t rhport)
       {
         xfer_td_t* xfer = get_td(epnum, TUSB_DIR_OUT);
 
-        if (xfer->actual_len < xfer->total_len)
+        if ( xfer->started && xfer->actual_len < xfer->total_len )
         {
           xact_out_dma(epnum);
         }else

+ 2 - 0
src/portable/raspberrypi/rp2040/rp2040_usb.c

@@ -60,7 +60,9 @@ void rp2040_usb_init(void)
   // Clear any previous state just in case
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Warray-bounds"
+#if __GNUC__ > 6
 #pragma GCC diagnostic ignored "-Wstringop-overflow"
+#endif
   memset(usb_hw, 0, sizeof(*usb_hw));
   memset(usb_dpram, 0, sizeof(*usb_dpram));
 #pragma GCC diagnostic pop

+ 2 - 2
src/tusb_option.h

@@ -33,7 +33,7 @@ typedef int make_iso_compilers_happy;
 #include "common/tusb_compiler.h"
 
 #define TUSB_VERSION_MAJOR     0
-#define TUSB_VERSION_MINOR     13
+#define TUSB_VERSION_MINOR     14
 #define TUSB_VERSION_REVISION  0
 #define TUSB_VERSION_STRING    TU_STRING(TUSB_VERSION_MAJOR) "." TU_STRING(TUSB_VERSION_MINOR) "." TU_STRING(TUSB_VERSION_REVISION)
 
@@ -226,7 +226,7 @@ typedef int make_iso_compilers_happy;
 #define TUSB_OPT_DEVICE_ENABLED CFG_TUD_ENABLED
 
 // highspeed support indicator
-#define TUD_OPT_HIGH_SPEED    (CFG_TUD_MAX_SPEED ? CFG_TUD_MAX_SPEED : TUP_RHPORT_HIGHSPEED)
+#define TUD_OPT_HIGH_SPEED    (CFG_TUD_MAX_SPEED ? (CFG_TUD_MAX_SPEED & OPT_MODE_HIGH_SPEED) : TUP_RHPORT_HIGHSPEED)
 
 //------------- Roothub as Host -------------//