Bladeren bron

Merge tag '0.14.0' into 0.14

tfx2001 3 jaren geleden
bovenliggende
commit
3896366e3a
60 gewijzigde bestanden met toevoegingen van 1356 en 305 verwijderingen
  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.
       description: If applicable, add screenshots to help explain your problem.
     validations:
     validations:
       required: false
       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
 - **Nuvoton:** NUC120, NUC121/NUC125, NUC126, NUC505
 - **NXP:**
 - **NXP:**
 
 
-  - iMX RT Series: RT1011, RT1015, RT1021, RT1052, RT1062, RT1064
+  - iMX RT Series: RT10xx, RT11xx
   - Kinetis: KL25, K32L2
   - Kinetis: KL25, K32L2
   - LPC Series: 11u, 13, 15, 17, 18, 40, 43, 51u, 54, 55
   - 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
 - **Renesas:** RX63N, RX65N, RX72N
 - **Silabs:** EFM32GG
 - **Silabs:** EFM32GG
 - **Sony:** CXD56
 - **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
 - **TI:** MSP430, MSP432E4, TM4C123
 - **ValentyUSB:** eptri
 - **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>`_
 - `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>`_
 - **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
 - Info
 
 

+ 58 - 0
docs/info/changelog.rst

@@ -2,6 +2,64 @@
 Changelog
 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
 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
    $ 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
 Build
 ^^^^^
 ^^^^^
@@ -70,6 +61,13 @@ To build example, first change directory to an example folder.
 
 
    $ cd examples/device/cdc_msc
    $ 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.
 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
 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
    $ 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: ``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
 Port Selection
 ~~~~~~~~~~~~~~
 ~~~~~~~~~~~~~~

+ 10 - 1
docs/reference/supported.rst

@@ -41,6 +41,8 @@ Supported MCUs
 |              | NUC505                | ✔      |      | ✔         |                   |              |
 |              | NUC505                | ✔      |      | ✔         |                   |              |
 +--------------+---------+-------------+--------+------+-----------+-------------------+--------------+
 +--------------+---------+-------------+--------+------+-----------+-------------------+--------------+
 | NXP          | iMXRT   | RT10xx      | ✔      | ✔    | ✔         | ci_hs             |              |
 | NXP          | iMXRT   | RT10xx      | ✔      | ✔    | ✔         | ci_hs             |              |
+|              |         +-------------+--------+------+-----------+-------------------+--------------+
+|              |         | RT11xx      | ✔      | ✔    | ✔         | ci_hs             |              |
 |              +---------+-------------+--------+------+-----------+-------------------+--------------+
 |              +---------+-------------+--------+------+-----------+-------------------+--------------+
 |              | Kinetis | KL25        | ✔      | ⚠    | ✖         |                   |              |
 |              | Kinetis | KL25        | ✔      | ⚠    | ✖         |                   |              |
 |              |         +-------------+--------+------+-----------+-------------------+--------------+
 |              |         +-------------+--------+------+-----------+-------------------+--------------+
@@ -58,7 +60,7 @@ Supported MCUs
 |              |         +-------------+--------+------+-----------+-------------------+--------------+
 |              |         +-------------+--------+------+-----------+-------------------+--------------+
 |              |         | 55          | ✔      |      | ✔         | lpc_ip3511        |              |
 |              |         | 55          | ✔      |      | ✔         | lpc_ip3511        |              |
 +--------------+---------+-------------+--------+------+-----------+-------------------+--------------+
 +--------------+---------+-------------+--------+------+-----------+-------------------+--------------+
-| Raspberry Pi | RP2040                | ✔      | ✔    | ✖         | rp2040            |              |
+| Raspberry Pi | RP2040                | ✔      | ✔    | ✖         | rp2040, pio_usb   |              |
 +--------------+-----------------------+--------+------+-----------+-------------------+--------------+
 +--------------+-----------------------+--------+------+-----------+-------------------+--------------+
 | Renesas      | RX 63N, 65N, 72N      | ✔      | ✔    | ✖         | usba              |              |
 | Renesas      | RX 63N, 65N, 72N      | ✔      | ✔    | ✖         | usba              |              |
 +--------------+-----------------------+--------+------+-----------+-------------------+--------------+
 +--------------+-----------------------+--------+------+-----------+-------------------+--------------+
@@ -93,6 +95,8 @@ Supported MCUs
 |              | L4+                   | ✔      |      |           | dwc2              |              |
 |              | L4+                   | ✔      |      |           | dwc2              |              |
 |              +-----------------------+--------+------+-----------+-------------------+--------------+
 |              +-----------------------+--------+------+-----------+-------------------+--------------+
 |              | U5                    | ⚠      |      |           | dwc2              |              |
 |              | U5                    | ⚠      |      |           | dwc2              |              |
+|              +-----------------------+--------+------+-----------+-------------------+--------------+
+|              | WBx5                  | ✔      |      |           | stm32_fsdev       |              |
 +--------------+-----------------------+--------+------+-----------+-------------------+--------------+
 +--------------+-----------------------+--------+------+-----------+-------------------+--------------+
 | TI           | MSP430                | ✔      | ✖    | ✖         | msp430x5xx        |              |
 | 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 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>`__
 -  `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.0 Development Board <https://www.pjrc.com/store/teensy40.html>`__
+-  `Teensy 4.1 Development Board <https://www.pjrc.com/store/teensy41.html>`__
 
 
 Kinetis
 Kinetis
 ^^^^^^^
 ^^^^^^^
@@ -377,6 +382,10 @@ L4
 -  `STM32 L4P5zg Nucleo <https://www.st.com/en/evaluation-tools/nucleo-l4p5zg.html>`__
 -  `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>`__
 -  `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
 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
   ${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
 # Configure compilation flags and libraries for the example... see the corresponding function
 # in hw/bsp/FAMILY/family.cmake for details.
 # in hw/bsp/FAMILY/family.cmake for details.
 family_configure_device_example(${PROJECT})
 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
   ${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
 # Configure compilation flags and libraries for the example... see the corresponding function
 # in hw/bsp/FAMILY/family.cmake for details.
 # in hw/bsp/FAMILY/family.cmake for details.
 family_configure_device_example(${PROJECT})
 family_configure_device_example(${PROJECT})

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

@@ -36,9 +36,6 @@ else()
           ${CMAKE_CURRENT_SOURCE_DIR}/src
           ${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
   # Configure compilation flags and libraries for the example... see the corresponding function
   # in hw/bsp/FAMILY/family.cmake for details.
   # in hw/bsp/FAMILY/family.cmake for details.
   family_configure_device_example(${PROJECT})
   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
         ${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
 # Configure compilation flags and libraries for the example... see the corresponding function
 # in hw/bsp/FAMILY/family.cmake for details.
 # in hw/bsp/FAMILY/family.cmake for details.
 family_configure_device_example(${PROJECT})
 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
         ${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
 # Configure compilation flags and libraries for the example... see the corresponding function
 # in hw/bsp/FAMILY/family.cmake for details.
 # in hw/bsp/FAMILY/family.cmake for details.
 family_configure_device_example(${PROJECT})
 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
         ${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
 # Configure compilation flags and libraries for the example... see the corresponding function
 # in hw/bsp/FAMILY/family.cmake for details.
 # in hw/bsp/FAMILY/family.cmake for details.
 family_configure_device_example(${PROJECT})
 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
         ${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
 # Configure compilation flags and libraries for the example... see the corresponding function
 # in hw/bsp/FAMILY/family.cmake for details.
 # in hw/bsp/FAMILY/family.cmake for details.
 family_configure_device_example(${PROJECT})
 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
         ${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
 # Configure compilation flags and libraries for the example... see the corresponding function
 # in hw/bsp/FAMILY/family.cmake for details.
 # in hw/bsp/FAMILY/family.cmake for details.
 family_configure_device_example(${PROJECT})
 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
         ${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
 # Configure compilation flags and libraries for the example... see the corresponding function
 # in hw/bsp/FAMILY/family.cmake for details.
 # in hw/bsp/FAMILY/family.cmake for details.
 family_configure_device_example(${PROJECT})
 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
 // Invoked when sent REPORT successfully to host
 // Application can use this to send the next report
 // Application can use this to send the next report
 // Note: For composite reports, report[0] is report ID
 // 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) instance;
   (void) report;
   (void) report;

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

@@ -23,9 +23,6 @@ target_include_directories(${PROJECT} PUBLIC
         ${CMAKE_CURRENT_SOURCE_DIR}/src
         ${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
 # Configure compilation flags and libraries for the example... see the corresponding function
 # in hw/bsp/FAMILY/family.cmake for details.
 # in hw/bsp/FAMILY/family.cmake for details.
 family_configure_device_example(${PROJECT})
 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
 // Invoked when sent REPORT successfully to host
 // Application can use this to send the next report
 // Application can use this to send the next report
 // Note: For composite reports, report[0] is report ID
 // 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) instance;
   (void) len;
   (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
 // Invoked when sent REPORT successfully to host
 // Application can use this to send the next report
 // Application can use this to send the next report
 // Note: For composite reports, report[0] is report ID
 // 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) instance;
   (void) len;
   (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
         ${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
 # Configure compilation flags and libraries for the example... see the corresponding function
 # in hw/bsp/FAMILY/family.cmake for details.
 # in hw/bsp/FAMILY/family.cmake for details.
 family_configure_device_example(${PROJECT})
 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
         ${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
 # Configure compilation flags and libraries for the example... see the corresponding function
 # in hw/bsp/FAMILY/family.cmake for details.
 # in hw/bsp/FAMILY/family.cmake for details.
 family_configure_device_example(${PROJECT})
 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
         ${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
 # Configure compilation flags and libraries for the example... see the corresponding function
 # in hw/bsp/FAMILY/family.cmake for details.
 # in hw/bsp/FAMILY/family.cmake for details.
 family_configure_device_example(${PROJECT})
 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
         ${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
 # Configure compilation flags and libraries for the example... see the corresponding function
 # in hw/bsp/FAMILY/family.cmake for details.
 # in hw/bsp/FAMILY/family.cmake for details.
 family_configure_device_example(${PROJECT})
 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
             ${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
     # due to warnings from other net source, we need to prevent error from some of the warnings options
     target_compile_options(${PROJECT} PUBLIC
     target_compile_options(${PROJECT} PUBLIC
         -Wno-error=null-dereference
         -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
         ${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
 # Configure compilation flags and libraries for the example... see the corresponding function
 # in hw/bsp/FAMILY/family.cmake for details.
 # in hw/bsp/FAMILY/family.cmake for details.
 family_configure_device_example(${PROJECT})
 family_configure_device_example(${PROJECT})

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

@@ -3,4 +3,5 @@ mcu:LPC13XX
 mcu:NUC121
 mcu:NUC121
 mcu:SAMD11
 mcu:SAMD11
 mcu:SAME5X
 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
         ${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
 # Configure compilation flags and libraries for the example... see the corresponding function
 # in hw/bsp/FAMILY/family.cmake for details.
 # in hw/bsp/FAMILY/family.cmake for details.
 family_configure_device_example(${PROJECT})
 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) | \
 #define USB_PID           (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \
                            _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) )
                            _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) )
 
 
+#define USB_VID   0xCafe
+#define USB_BCD   0x0200
+
 //--------------------------------------------------------------------+
 //--------------------------------------------------------------------+
 // Device Descriptors
 // Device Descriptors
 //--------------------------------------------------------------------+
 //--------------------------------------------------------------------+
@@ -51,9 +54,9 @@ tusb_desc_device_t const desc_device =
 
 
     .bMaxPacketSize0    = CFG_TUD_ENDPOINT0_SIZE,
     .bMaxPacketSize0    = CFG_TUD_ENDPOINT0_SIZE,
 
 
-    .idVendor           = 0xCafe,
+    .idVendor           = USB_VID,
     .idProduct          = USB_PID,
     .idProduct          = USB_PID,
-    .bcdDevice          = 0x0100,
+    .bcdDevice          = USB_BCD,
 
 
     .iManufacturer      = 0x01,
     .iManufacturer      = 0x01,
     .iProduct           = 0x02,
     .iProduct           = 0x02,
@@ -75,22 +78,22 @@ uint8_t const * tud_descriptor_device_cb(void)
 
 
 #if defined(CFG_TUD_USBTMC)
 #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_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
 #if CFG_TUD_USBTMC_ENABLE_INT_EP
 // USBTMC Interrupt xfer always has length of 2, but we use epMaxSize=8 for
 // 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
 //  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 )
      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)
 #  define TUD_USBTMC_DESC_LEN (TUD_USBTMC_IF_DESCRIPTOR_LEN + TUD_USBTMC_BULK_DESCRIPTORS_LEN + TUD_USBTMC_INT_DESCRIPTOR_LEN)
 
 
 #else
 #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)
 #  define TUD_USBTMC_DESC_LEN (TUD_USBTMC_IF_DESCRIPTOR_LEN + TUD_USBTMC_BULK_DESCRIPTORS_LEN)
 
 
 #endif /* CFG_TUD_USBTMC_ENABLE_INT_EP */
 #endif /* CFG_TUD_USBTMC_ENABLE_INT_EP */
@@ -119,21 +122,66 @@ enum
 #endif
 #endif
 
 
 
 
-uint8_t const desc_configuration[] =
+uint8_t const desc_fs_configuration[] =
 {
 {
   // Config number, interface count, string index, total length, attribute, power in mA
   // 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_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
 // Invoked when received GET CONFIGURATION DESCRIPTOR
 // Application return pointer to descriptor
 // Application return pointer to descriptor
 // Descriptor contents must exist long enough for transfer to complete
 // Descriptor contents must exist long enough for transfer to complete
 uint8_t const * tud_descriptor_configuration_cb(uint8_t index)
 uint8_t const * tud_descriptor_configuration_cb(uint8_t index)
 {
 {
   (void) index; // for multiple configurations
   (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
 #!/usr/bin/env python3
 
 
-import visa
+import pyvisa
 import time
 import time
 import sys
 import sys
 
 
@@ -54,9 +54,9 @@ def test_srq():
 	assert (inst.read_stb() == 0)
 	assert (inst.read_stb() == 0)
 	inst.write("123")
 	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()
 	#inst.wait_for_srq()
 	time.sleep(0.3)
 	time.sleep(0.3)
 	stb = inst.read_stb()
 	stb = inst.read_stb()
@@ -77,8 +77,8 @@ def test_read_timeout():
 	t0 = time.monotonic()
 	t0 = time.monotonic()
 	try:
 	try:
 		rsp = inst.read()
 		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")
 		print("  Got expected exception")
 	t = time.monotonic() - t0
 	t = time.monotonic() - t0
 	assert ((t*1000.0) > (inst.timeout - 300))
 	assert ((t*1000.0) > (inst.timeout - 300))
@@ -99,23 +99,27 @@ def test_abort_in():
 	t0 = time.monotonic()
 	t0 = time.monotonic()
 	try:
 	try:
 		rsp = inst.read()
 		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")
 		print("  Got expected exception")
 	t = time.monotonic() - t0
 	t = time.monotonic() - t0
 	assert ((t*1000.0) > (inst.timeout - 300))
 	assert ((t*1000.0) > (inst.timeout - 300))
 	assert ((t*1000.0) < (inst.timeout + 300))
 	assert ((t*1000.0) < (inst.timeout + 300))
 	print(f"  Delay was {t:0.3}")
 	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
 	inst.timeout = 800
 	y = inst.read()
 	y = inst.read()
 	assert(y == "xxx\r\n")
 	assert(y == "xxx\r\n")
 	
 	
 def test_indicate():
 def test_indicate():
 	# perform indicator pulse
 	# 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)
 	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():
 def test_multi_read():
@@ -131,19 +135,19 @@ def test_multi_read():
 	#inst.chunk_size = old_chunk_size
 	#inst.chunk_size = old_chunk_size
 	
 	
 def test_stall_ep0():
 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()
 	inst.read_stb()
 	# This is an invalid request, should create stall.
 	# This is an invalid request, should create stall.
 	try:
 	try:
 		retv = inst.control_in(request_type_bitmap_field=0xA1, request_id=60, request_value=0x0000, index=usb_iface, length=0x0001)
 		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
 		pass
 	
 	
 	assert (inst.read_stb() == 0)
 	assert (inst.read_stb() == 0)
 
 
 
 
-rm = visa.ResourceManager()
+rm = pyvisa.ResourceManager()
 reslist = rm.list_resources("USB?::?*::INSTR")
 reslist = rm.list_resources("USB?::?*::INSTR")
 print(reslist)
 print(reslist)
 
 
@@ -167,7 +171,6 @@ inst.timeout = 2000
 print("+ multi read")
 print("+ multi read")
 test_multi_read()
 test_multi_read()
 
 
-
 print("+ echo delay=0")
 print("+ echo delay=0")
 inst.write("delay 0")
 inst.write("delay 0")
 test_echo(1,175)
 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
   ${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
 # Configure compilation flags and libraries for the example... see the corresponding function
 # in hw/bsp/FAMILY/family.cmake for details.
 # in hw/bsp/FAMILY/family.cmake for details.
 family_configure_device_example(${PROJECT})
 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
         ${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
 # Configure compilation flags and libraries for the example... see the corresponding function
 # in hw/bsp/FAMILY/family.cmake for details.
 # in hw/bsp/FAMILY/family.cmake for details.
 family_configure_device_example(${PROJECT})
 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;
 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 =
 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 )
   if ( web_serial_connected )
   {
   {
     tud_vendor_write(buf, count);
     tud_vendor_write(buf, count);
+    tud_vendor_flush();
   }
   }
 
 
   // echo to cdc
   // 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);
           board_led_write(true);
           blink_interval_ms = BLINK_ALWAYS_ON;
           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
         }else
         {
         {
           blink_interval_ms = BLINK_MOUNTED;
           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
         ${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
 # due to warnings from other net source, we need to prevent error from some of the warnings options
 target_compile_options(${PROJECT} PUBLIC
 target_compile_options(${PROJECT} PUBLIC
@@ -37,7 +38,3 @@ target_compile_options(${PROJECT} PUBLIC
         -Wno-error=sign-compare
         -Wno-error=sign-compare
         -Wno-error=unused-function
         -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
         ${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
 # Configure compilation flags and libraries for the example... see the corresponding function
 # in hw/bsp/FAMILY/family.cmake for details.
 # in hw/bsp/FAMILY/family.cmake for details.
 family_configure_host_example(${PROJECT})
 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
         ${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
 # Configure compilation flags and libraries for the example... see the corresponding function
 # in hw/bsp/FAMILY/family.cmake for details.
 # in hw/bsp/FAMILY/family.cmake for details.
 family_configure_host_example(${PROJECT})
 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
         ${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
 # Configure compilation flags and libraries for the example... see the corresponding function
 # in hw/bsp/FAMILY/family.cmake for details.
 # in hw/bsp/FAMILY/family.cmake for details.
 family_configure_host_example(${PROJECT})
 family_configure_host_example(${PROJECT})

+ 42 - 0
hw/bsp/family_support.cmake

@@ -79,6 +79,48 @@ if (NOT TARGET _family_support_marker)
         endif()
         endif()
     endfunction()
     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
     # configure an executable target to link to tinyusb in device mode, and add the board implementation
     function(family_configure_device_example TARGET)
     function(family_configure_device_example TARGET)
         # default implentation is empty, the function should be redefined in the FAMILY/family.cmake
         # 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)
 		target_link_libraries(${TARGET} PUBLIC pico_stdlib pico_bootsel_via_double_reset tinyusb_board tinyusb_additions)
 	endfunction()
 	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)
 	function(family_configure_device_example TARGET)
 		family_configure_target(${TARGET})
 		family_configure_target(${TARGET})
 		target_link_libraries(${TARGET} PUBLIC pico_stdlib tinyusb_device)
 		target_link_libraries(${TARGET} PUBLIC pico_stdlib tinyusb_device)
-		suppress_tinyusb_warnings()
+		rp2040_family_configure_example_warnings(${TARGET})
 	endfunction()
 	endfunction()
 
 
 	function(family_configure_host_example TARGET)
 	function(family_configure_host_example TARGET)
 		family_configure_target(${TARGET})
 		family_configure_target(${TARGET})
 		target_link_libraries(${TARGET} PUBLIC pico_stdlib tinyusb_host)
 		target_link_libraries(${TARGET} PUBLIC pico_stdlib tinyusb_host)
-		suppress_tinyusb_warnings()
+		rp2040_family_configure_example_warnings(${TARGET})
 	endfunction()
 	endfunction()
 
 
 	function(family_add_pico_pio_usb TARGET)
 	function(family_add_pico_pio_usb TARGET)
@@ -167,7 +174,7 @@ if (NOT TARGET _rp2040_family_inclusion_marker)
 		family_configure_target(${TARGET})
 		family_configure_target(${TARGET})
 		# require tinyusb_pico_pio_usb
 		# require tinyusb_pico_pio_usb
 		target_link_libraries(${TARGET} PUBLIC pico_stdlib tinyusb_device tinyusb_host 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()
 	endfunction()
 
 
 	function(check_and_add_pico_pio_usb_support)
 	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
 	# This method must be called from the project scope to suppress known warnings in TinyUSB source files
 	function(suppress_tinyusb_warnings)
 	function(suppress_tinyusb_warnings)
 		# some of these are pretty silly warnings only occurring in some older GCC versions 9 or prior
 		# 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()
 	endfunction()
 endif()
 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.11.0": "0.11.0"
     "0.12.0": "0.12.0"
     "0.12.0": "0.12.0"
     "0.13.0": "0.13.0"
     "0.13.0": "0.13.0"
+    "0.14.0": "0.14.0"
 
 
     "0-dev": "0.0.0"        # master
     "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:
     case AUDIO_FORMAT_TYPE_I:
 
 
-      switch (audio->format_type_I_tx)
+      switch (audio->format_type_I_rx)
       {
       {
         case AUDIO_DATA_FORMAT_TYPE_I_PCM:
         case AUDIO_DATA_FORMAT_TYPE_I_PCM:
           TU_VERIFY(audiod_decode_type_I_pcm(rhport, audio, n_bytes_received));
           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;
   uint8_t alt_count = 0;
 
 
   uint16_t drv_len = 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)
   while(itf_desc->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS && itf_desc->bInterfaceProtocol == DFU_PROTOCOL_DFU)
   {
   {
     TU_ASSERT(max_len > drv_len, 0);
     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)
     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
   // 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
 // Invoked when sent REPORT successfully to host
 // Application can use this to send the next report
 // Application can use this to send the next report
 // Note: For composite reports, report[0] is report ID
 // 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_FAILED = 0x80,
   USBTMC_STATUS_TRANSFER_NOT_IN_PROGRESS = 0x81,
   USBTMC_STATUS_TRANSFER_NOT_IN_PROGRESS = 0x81,
   USBTMC_STATUS_SPLIT_NOT_IN_PROGRESS = 0x82,
   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;
 } usbtmc_status_enum;
 
 
 /************************************************************
 /************************************************************

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

@@ -64,7 +64,8 @@
 // USBTMC 3.2.2 error conditions not strictly followed
 // USBTMC 3.2.2 error conditions not strictly followed
 // No local lock-out, REN, or GTL.
 // No local lock-out, REN, or GTL.
 // Clear message available status byte at the correct time? (488 4.3.1.3)
 // 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"
 #include "tusb_option.h"
 
 
@@ -80,6 +81,11 @@
 static char logMsg[150];
 static char logMsg[150];
 #endif
 #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
  * The state machine does not allow simultaneous reading and writing. This is
  * consistent with USBTMC.
  * consistent with USBTMC.
@@ -120,9 +126,12 @@ typedef struct
   uint8_t ep_int_in;
   uint8_t ep_int_in;
   // IN buffer is only used for first packet, not the remainder
   // IN buffer is only used for first packet, not the remainder
   // in order to deal with prepending header
   // 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
   // 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_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)
   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,
     .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_devMsgOutStart(uint8_t rhport, void *data, size_t len);
 static bool handle_devMsgOut(uint8_t rhport, void *data, size_t len, size_t packetLen);
 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 termChar;
 static uint8_t termCharRequested = false;
 static uint8_t termCharRequested = false;
 
 
-
 osal_mutex_def_t usbtmcLockBuffer;
 osal_mutex_def_t usbtmcLockBuffer;
 static osal_mutex_t usbtmcLock;
 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;
       tusb_desc_endpoint_t const *ep_desc = (tusb_desc_endpoint_t const *)p_desc;
       switch(ep_desc->bmAttributes.xfer) {
       switch(ep_desc->bmAttributes.xfer) {
         case TUSB_XFER_BULK:
         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)
           if (tu_edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN)
           {
           {
             usbtmc_state.ep_bulk_in = ep_desc->bEndpointAddress;
             usbtmc_state.ep_bulk_in = ep_desc->bEndpointAddress;
+            usbtmc_state.ep_bulk_in_wMaxPacketSize = tu_edpt_packet_size(ep_desc);
           } else {
           } else {
             usbtmc_state.ep_bulk_out = ep_desc->bEndpointAddress;
             usbtmc_state.ep_bulk_out = ep_desc->bEndpointAddress;
+            usbtmc_state.ep_bulk_out_wMaxPacketSize = tu_edpt_packet_size(ep_desc);
           }
           }
 
 
           break;
           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.
   // return true upon failure, as we can assume error is being handled elsewhere.
   TU_VERIFY(usbtmc_state.state == STATE_RCV,true);
   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.
   // Packet is to be considered complete when we get enough data or at a short packet.
   bool atEnd = false;
   bool atEnd = false;
@@ -522,7 +530,7 @@ bool usbtmcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint
       break;
       break;
 
 
     case STATE_TX_INITIATED:
     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!
         // FIXME! This removes const below!
         TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in,
         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.transfer_size_remaining = 0;
         usbtmc_state.devInBuffer = NULL;
         usbtmc_state.devInBuffer = NULL;
         TU_VERIFY( usbd_edpt_xfer(rhport, usbtmc_state.ep_bulk_in, usbtmc_state.ep_bulk_in_buf, (uint16_t)packetLen) );
         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;
           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);
     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)
     if(ep_addr == usbtmc_state.ep_bulk_out)
     {
     {
       criticalEnter();
       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
       usbtmc_state.state = STATE_NAK; // USBD core has placed EP in NAK state for us
       criticalLeave();
       criticalLeave();
       tud_usbtmc_bulkOut_clearFeature_cb();
       tud_usbtmc_bulkOut_clearFeature_cb();
     }
     }
     else if (ep_addr == usbtmc_state.ep_bulk_in)
     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();
       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;
       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;
     usbtmc_state.transfer_size_remaining = 0u;
       // Check if we've queued a short packet
       // Check if we've queued a short packet
       criticalEnter();
       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;
               STATE_ABORTING_BULK_IN : STATE_ABORTING_BULK_IN_SHORTED;
       criticalLeave();
       criticalLeave();
       if(usbtmc_state.transfer_size_sent  == 0)
       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;
       bTag = request->wValue & 0x7F;
       TU_VERIFY(request->bmRequestType == 0xA1);
       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(bTag >= 0x02 && bTag <= 127);
       TU_VERIFY(request->wIndex == usbtmc_state.itf_id);
       TU_VERIFY(request->wIndex == usbtmc_state.itf_id);
       TU_VERIFY(request->wLength == 0x0003);
       TU_VERIFY(request->wLength == 0x0003);
       rsp.bTag = (uint8_t)bTag;
       rsp.bTag = (uint8_t)bTag;
       if(usbtmc_state.ep_int_in != 0)
       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
       else
       {
       {

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

@@ -35,10 +35,6 @@
 #define CFG_TUD_USBTMC_ENABLE_488 (1)
 #define CFG_TUD_USBTMC_ENABLE_488 (1)
 #endif
 #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
  *  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_BEGIN
   #define TU_ATTR_BIT_FIELD_ORDER_END
   #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
   // Endian conversion use well-known host to network (big endian) naming
   #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
   #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
     #define TU_BYTE_ORDER TU_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_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_UNUSED                __attribute__ ((unused))           // Function/Variable is meant to be possibly unused
   #define TU_ATTR_USED                  __attribute__ ((used))
   #define TU_ATTR_USED                  __attribute__ ((used))
+  #define TU_ATTR_FALLTHROUGH           __attribute__((fallthrough))
 
 
   #define TU_ATTR_PACKED_BEGIN
   #define TU_ATTR_PACKED_BEGIN
   #define TU_ATTR_PACKED_END
   #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_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_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_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_BEGIN
   #define TU_ATTR_PACKED_END
   #define TU_ATTR_PACKED_END
@@ -207,6 +215,7 @@
   #define TU_ATTR_DEPRECATED(mess)
   #define TU_ATTR_DEPRECATED(mess)
   #define TU_ATTR_UNUSED
   #define TU_ATTR_UNUSED
   #define TU_ATTR_USED
   #define TU_ATTR_USED
+  #define TU_ATTR_FALLTHROUGH           do {} while (0)  /* fallthrough */
 
 
   #define TU_ATTR_PACKED_BEGIN          _Pragma("pack")
   #define TU_ATTR_PACKED_BEGIN          _Pragma("pack")
   #define TU_ATTR_PACKED_END            _Pragma("packoption")
   #define TU_ATTR_PACKED_END            _Pragma("packoption")
@@ -227,6 +236,7 @@
   #error "Compiler attribute porting is required"
   #error "Compiler attribute porting is required"
 #endif
 #endif
 
 
+
 #if (TU_BYTE_ORDER == TU_LITTLE_ENDIAN)
 #if (TU_BYTE_ORDER == TU_LITTLE_ENDIAN)
 
 
   #define tu_htons(u16)  (TU_BSWAP16(u16))
   #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
   uint8_t status_change; // data from status change interrupt endpoint
 
 
   hub_port_status_response_t port_status;
   hub_port_status_response_t port_status;
+  hub_status_response_t hub_status;
 } hub_interface_t;
 } hub_interface_t;
 
 
 CFG_TUSB_MEM_SECTION static hub_interface_t hub_data[CFG_TUH_HUB];
 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 =
     .bmRequestType_bit =
     {
     {
-      .recipient = TUSB_REQ_RCPT_OTHER,
+      .recipient = (hub_port == 0) ? TUSB_REQ_RCPT_DEVICE : TUSB_REQ_RCPT_OTHER,
       .type      = TUSB_REQ_TYPE_CLASS,
       .type      = TUSB_REQ_TYPE_CLASS,
       .direction = TUSB_DIR_OUT
       .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 =
     .bmRequestType_bit =
     {
     {
-      .recipient = TUSB_REQ_RCPT_OTHER,
+      .recipient = (hub_port == 0) ? TUSB_REQ_RCPT_DEVICE : TUSB_REQ_RCPT_OTHER,
       .type      = TUSB_REQ_TYPE_CLASS,
       .type      = TUSB_REQ_TYPE_CLASS,
       .direction = TUSB_DIR_OUT
       .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 =
     .bmRequestType_bit =
     {
     {
-      .recipient = TUSB_REQ_RCPT_OTHER,
+      .recipient = (hub_port == 0) ? TUSB_REQ_RCPT_DEVICE : TUSB_REQ_RCPT_OTHER,
       .type      = TUSB_REQ_TYPE_CLASS,
       .type      = TUSB_REQ_TYPE_CLASS,
       .direction = TUSB_DIR_IN
       .direction = TUSB_DIR_IN
     },
     },
@@ -313,7 +314,8 @@ static void config_port_power_complete (tuh_xfer_t* xfer)
 // Connection Changes
 // 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_clear_conn_change_complete (tuh_xfer_t* xfer);
 static void connection_port_reset_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);
   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;
   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, );
   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);
     hub_port_clear_feature(daddr, port_num, HUB_FEATURE_PORT_CONNECTION_CHANGE, connection_clear_conn_change_complete, 0);
   }else
   }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
     // TODO clear change
 
 
     // prepare for next hub status
     // prepare for next hub status

+ 4 - 4
src/host/usbh.c

@@ -123,7 +123,6 @@ typedef struct {
 
 
 // Invalid driver ID in itf2drv[] ep2drv[][] mapping
 // Invalid driver ID in itf2drv[] ep2drv[][] mapping
 enum { DRVID_INVALID = 0xFFu };
 enum { DRVID_INVALID = 0xFFu };
-enum { ADDR_INVALID  = 0xFFu };
 enum { CONTROLLER_INVALID = 0xFFu };
 enum { CONTROLLER_INVALID = 0xFFu };
 
 
 #if CFG_TUSB_DEBUG >= 2
 #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) );
           TU_ASSERT( hcd_edpt_xfer(rhport, dev_addr, tu_edpt_addr(0, request->bmRequestType_bit.direction), _ctrl_xfer.buffer, request->wLength) );
           return true;
           return true;
         }
         }
-        __attribute__((fallthrough));
+        TU_ATTR_FALLTHROUGH;
 
 
       case CONTROL_STAGE_DATA:
       case CONTROL_STAGE_DATA:
         if (request->wLength)
         if (request->wLength)
@@ -1434,7 +1433,8 @@ static uint8_t get_new_address(bool is_hub)
   {
   {
     if (!_usbh_devices[idx].connected) return (idx+1);
     if (!_usbh_devices[idx].connected) return (idx+1);
   }
   }
-  return ADDR_INVALID;
+
+  return 0; // invalid address
 }
 }
 
 
 static bool enum_request_set_addr(void)
 static bool enum_request_set_addr(void)
@@ -1443,7 +1443,7 @@ static bool enum_request_set_addr(void)
 
 
   // Get new address
   // Get new address
   uint8_t const new_addr = get_new_address(desc_device->bDeviceClass == TUSB_CLASS_HUB);
   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);
   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
 #if CFG_TUD_ENABLED && CFG_TUSB_MCU == OPT_MCU_NRF5X
 
 
+#include <stdatomic.h>
 #include "nrf.h"
 #include "nrf.h"
 #include "nrf_clock.h"
 #include "nrf_clock.h"
 #include "nrf_power.h"
 #include "nrf_power.h"
@@ -72,6 +73,7 @@ typedef struct
   // nRF will auto accept OUT packet after DMA is done
   // nRF will auto accept OUT packet after DMA is done
   // indicate packet is already ACK
   // indicate packet is already ACK
   volatile bool data_received;
   volatile bool data_received;
+  volatile bool started;
 
 
   // Set to true when data was transferred from RAM to ISO IN output buffer.
   // 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.
   // New data can be put in ISO IN output buffer after SOF.
@@ -79,9 +81,6 @@ typedef struct
 
 
 } xfer_td_t;
 } xfer_td_t;
 
 
-static osal_mutex_def_t dcd_mutex_def;
-static osal_mutex_t dcd_mutex;
-
 // Data for managing dcd
 // Data for managing dcd
 static struct
 static struct
 {
 {
@@ -90,7 +89,7 @@ static struct
   xfer_td_t xfer[EP_CBI_COUNT + 1][2];
   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
   // 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;
 }_dcd;
 
 
 /*------------------------------------------------------------------*/
 /*------------------------------------------------------------------*/
@@ -121,8 +120,6 @@ TU_ATTR_ALWAYS_INLINE static inline bool is_in_isr(void)
 // helper to start DMA
 // helper to start DMA
 static void start_dma(volatile uint32_t* reg_startep)
 static void start_dma(volatile uint32_t* reg_startep)
 {
 {
-  _dcd.dma_running = true;
-
   (*reg_startep) = 1;
   (*reg_startep) = 1;
   __ISB(); __DSB();
   __ISB(); __DSB();
 
 
@@ -131,50 +128,18 @@ static void start_dma(volatile uint32_t* reg_startep)
   // Therefore dma_pending is corrected right away
   // Therefore dma_pending is corrected right away
   if ( (reg_startep == &NRF_USBD->TASKS_EP0STATUS) || (reg_startep == &NRF_USBD->TASKS_EP0RCVOUT) )
   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)
 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
   }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)
 static void edpt_dma_end(void)
 {
 {
   TU_ASSERT(_dcd.dma_running, );
   TU_ASSERT(_dcd.dma_running, );
-  _dcd.dma_running = false;
+  atomic_flag_clear(&_dcd.dma_running);
 }
 }
 
 
 // helper getting td
 // 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];
   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
 // Start DMA to move data from Endpoint -> RAM
 static void xact_out_dma(uint8_t epnum)
 static void xact_out_dma(uint8_t epnum)
 {
 {
   xfer_td_t* xfer = get_td(epnum, TUSB_DIR_OUT);
   xfer_td_t* xfer = get_td(epnum, TUSB_DIR_OUT);
   uint32_t xact_len;
   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)
   if (epnum == EP_ISO_NUM)
   {
   {
     xact_len = NRF_USBD->SIZE.ISOOUT;
     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)
     if (xact_len & USBD_SIZE_ISOOUT_ZERO_Msk)
     {
     {
       xact_len = 0;
       xact_len = 0;
+      atomic_flag_clear(&_dcd.dma_running);
     }
     }
     else
     else
     {
     {
@@ -211,7 +191,7 @@ static void xact_out_dma(uint8_t epnum)
       NRF_USBD->ISOOUT.PTR = (uint32_t) xfer->buffer;
       NRF_USBD->ISOOUT.PTR = (uint32_t) xfer->buffer;
       NRF_USBD->ISOOUT.MAXCNT = xact_len;
       NRF_USBD->ISOOUT.MAXCNT = xact_len;
 
 
-      edpt_dma_start(&NRF_USBD->TASKS_STARTISOOUT);
+      start_dma(&NRF_USBD->TASKS_STARTISOOUT);
     }
     }
   }
   }
   else
   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].PTR = (uint32_t) xfer->buffer;
     NRF_USBD->EPOUT[epnum].MAXCNT = xact_len;
     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)
 void dcd_init (uint8_t rhport)
 {
 {
   TU_LOG1("dcd init\r\n");
   TU_LOG1("dcd init\r\n");
-  dcd_mutex = osal_mutex_create(&dcd_mutex_def);
   (void) rhport;
   (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);
   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->buffer     = buffer;
   xfer->total_len  = total_bytes;
   xfer->total_len  = total_bytes;
   xfer->actual_len = 0;
   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
   // 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));
   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 )
   else if ( dir == TUSB_DIR_OUT )
   {
   {
+    xfer->started = true;
     if ( epnum == 0 )
     if ( epnum == 0 )
     {
     {
       // Accept next Control Out packet. TASKS_EP0RCVOUT also require EasyDMA
       // Accept next Control Out packet. TASKS_EP0RCVOUT also require EasyDMA
       edpt_dma_start(&NRF_USBD->TASKS_EP0RCVOUT);
       edpt_dma_start(&NRF_USBD->TASKS_EP0RCVOUT);
     }else
     }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
         // Data is already received previously
         // start DMA to copy to SRAM
         // start DMA to copy to SRAM
@@ -804,7 +783,9 @@ void dcd_int_handler(uint8_t rhport)
         }
         }
       }else
       }else
       {
       {
+        TU_ASSERT(xfer->started,);
         xfer->total_len = xfer->actual_len;
         xfer->total_len = xfer->actual_len;
+        xfer->started = false;
 
 
         // CBI OUT complete
         // CBI OUT complete
         dcd_event_xfer_complete(0, epnum, xfer->actual_len, XFER_RESULT_SUCCESS, true);
         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);
         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);
           xact_out_dma(epnum);
         }else
         }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
   // Clear any previous state just in case
 #pragma GCC diagnostic push
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Warray-bounds"
 #pragma GCC diagnostic ignored "-Warray-bounds"
+#if __GNUC__ > 6
 #pragma GCC diagnostic ignored "-Wstringop-overflow"
 #pragma GCC diagnostic ignored "-Wstringop-overflow"
+#endif
   memset(usb_hw, 0, sizeof(*usb_hw));
   memset(usb_hw, 0, sizeof(*usb_hw));
   memset(usb_dpram, 0, sizeof(*usb_dpram));
   memset(usb_dpram, 0, sizeof(*usb_dpram));
 #pragma GCC diagnostic pop
 #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"
 #include "common/tusb_compiler.h"
 
 
 #define TUSB_VERSION_MAJOR     0
 #define TUSB_VERSION_MAJOR     0
-#define TUSB_VERSION_MINOR     13
+#define TUSB_VERSION_MINOR     14
 #define TUSB_VERSION_REVISION  0
 #define TUSB_VERSION_REVISION  0
 #define TUSB_VERSION_STRING    TU_STRING(TUSB_VERSION_MAJOR) "." TU_STRING(TUSB_VERSION_MINOR) "." TU_STRING(TUSB_VERSION_REVISION)
 #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
 #define TUSB_OPT_DEVICE_ENABLED CFG_TUD_ENABLED
 
 
 // highspeed support indicator
 // 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 -------------//
 //------------- Roothub as Host -------------//